Mercurial > hg > openjdk > jdk7u > hotspot
changeset 2854:7e508fbcb950 jdk7u4-b01
Merge
author | jcoomes |
---|---|
date | Thu, 27 Oct 2011 12:21:43 -0700 |
parents | 92be6a664a86 (current diff) 4538caeef7b6 (diff) |
children | b6d9d5bbea50 |
files | .hgtags make/hotspot_version make/templates/bsd-header src/cpu/x86/vm/vm_version_x86.cpp src/os/windows/vm/os_windows.cpp src/share/vm/prims/methodHandleWalk.cpp |
diffstat | 444 files changed, 38695 insertions(+), 1875 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Wed Oct 26 12:43:05 2011 -0700 +++ b/.hgignore Thu Oct 27 12:21:43 2011 -0700 @@ -6,3 +6,4 @@ ^src/share/tools/IdealGraphVisualizer/build/ ^src/share/tools/IdealGraphVisualizer/dist/ ^.hgtip +.DS_Store
--- a/.hgtags Wed Oct 26 12:43:05 2011 -0700 +++ b/.hgtags Thu Oct 27 12:21:43 2011 -0700 @@ -188,6 +188,8 @@ 3a2fb61165dfc72e398179a2796d740c8da5b8c0 jdk8-b03 0fa3ace511fe98fe948e751531f3e2b7c60c8376 jdk8-b04 dce7d24674f4d0bed00de24f00119057fdce7cfb jdk8-b05 +0db80d8e77fccddf5e6fa49963226b54ac7d0f62 jdk8-b06 +3f0cf875af83f55ec5e1a5cea80455315f9322a2 jdk8-b07 0cc8a70952c368e06de2adab1f2649a408f5e577 hs22-b01 7c29742c41b44fb0cd5a13c7ac8834f3f2ca649e hs22-b02 3a2fb61165dfc72e398179a2796d740c8da5b8c0 hs22-b03 @@ -199,3 +201,9 @@ 513a84dd0f8b56dc0836b4e0bdd5dd0a778fc634 hs22-b05 650d15d8f37255d3b805aa00c5bd1c30984b203d hs22-b06 8035e71ac3f6c8a453f7e9483e7144731388b14e jdk7u2-b08 +da883b9e6d3788057f9577e72712998ed82c9b7e hs23-b01 +49ed7eacfd16616166ff066493143889741097af jdk8-b08 +7c20d272643f47195478708eff593a9cce40fec4 jdk8-b09 +e4f412d2b75d2c797acff965aa2c420e3d358f09 hs23-b02 +d815de2e85e511b7deab2a83cf80c0224d011da9 jdk8-b10 +4d3850d9d326ac3a9bee2d867727e954322d014e hs23-b03
--- a/agent/make/Makefile Wed Oct 26 12:43:05 2011 -0700 +++ b/agent/make/Makefile Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 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 @@ -53,6 +53,9 @@ sun.jvm.hotspot.compiler \ sun.jvm.hotspot.debugger \ sun.jvm.hotspot.debugger.amd64 \ +sun.jvm.hotspot.debugger.bsd \ +sun.jvm.hotspot.debugger.bsd.amd64 \ +sun.jvm.hotspot.debugger.bsd.x86 \ sun.jvm.hotspot.debugger.cdbg \ sun.jvm.hotspot.debugger.cdbg.basic \ sun.jvm.hotspot.debugger.cdbg.basic.amd64 \ @@ -81,6 +84,7 @@ sun.jvm.hotspot.debugger.windbg.x86 \ sun.jvm.hotspot.debugger.x86 \ sun.jvm.hotspot.gc_implementation \ +sun.jvm.hotspot.gc_implementation.g1 \ sun.jvm.hotspot.gc_implementation.parallelScavenge \ sun.jvm.hotspot.gc_implementation.shared \ sun.jvm.hotspot.gc_interface \ @@ -93,6 +97,9 @@ sun.jvm.hotspot.prims \ sun.jvm.hotspot.runtime \ sun.jvm.hotspot.runtime.amd64 \ +sun.jvm.hotspot.runtime.bsd \ +sun.jvm.hotspot.runtime.bsd_amd64 \ +sun.jvm.hotspot.runtime.bsd_x86 \ sun.jvm.hotspot.runtime.ia64 \ sun.jvm.hotspot.runtime.linux \ sun.jvm.hotspot.runtime.linux_amd64 \ @@ -143,6 +150,9 @@ sun/jvm/hotspot/compiler/*.java \ sun/jvm/hotspot/debugger/*.java \ sun/jvm/hotspot/debugger/amd64/*.java \ +sun/jvm/hotspot/debugger/bsd/*.java \ +sun/jvm/hotspot/debugger/bsd/amd64/*.java \ +sun/jvm/hotspot/debugger/bsd/x86/*.java \ sun/jvm/hotspot/debugger/cdbg/*.java \ sun/jvm/hotspot/debugger/cdbg/basic/*.java \ sun/jvm/hotspot/debugger/cdbg/basic/amd64/*.java \ @@ -167,6 +177,9 @@ sun/jvm/hotspot/debugger/windbg/ia64/*.java \ sun/jvm/hotspot/debugger/windbg/x86/*.java \ sun/jvm/hotspot/debugger/x86/*.java \ +sun/jvm/hotspot/gc_implementation/g1/*.java \ +sun/jvm/hotspot/gc_implementation/parallelScavenge/*.java \ +sun/jvm/hotspot/gc_implementation/shared/*.java \ sun/jvm/hotspot/interpreter/*.java \ sun/jvm/hotspot/jdi/*.java \ sun/jvm/hotspot/livejvm/*.java \ @@ -176,6 +189,9 @@ sun/jvm/hotspot/prims/*.java \ sun/jvm/hotspot/runtime/*.java \ sun/jvm/hotspot/runtime/amd64/*.java \ +sun/jvm/hotspot/runtime/bsd/*.java \ +sun/jvm/hotspot/runtime/bsd_amd64/*.java \ +sun/jvm/hotspot/runtime/bsd_x86/*.java \ sun/jvm/hotspot/runtime/ia64/*.java \ sun/jvm/hotspot/runtime/linux/*.java \ sun/jvm/hotspot/runtime/linux_amd64/*.java \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/os/bsd/BsdDebuggerLocal.c Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,413 @@ +/* + * Copyright (c) 2002, 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. + * + */ + +#include <stdlib.h> +#include <jni.h> +#include "libproc.h" + +#if defined(x86_64) && !defined(amd64) +#define amd64 1 +#endif + +#ifdef i386 +#include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h" +#endif + +#ifdef amd64 +#include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h" +#endif + +#if defined(sparc) || defined(sparcv9) +#include "sun_jvm_hotspot_debugger_sparc_SPARCThreadContext.h" +#endif + +static jfieldID p_ps_prochandle_ID = 0; +static jfieldID threadList_ID = 0; +static jfieldID loadObjectList_ID = 0; + +static jmethodID createClosestSymbol_ID = 0; +static jmethodID createLoadObject_ID = 0; +static jmethodID getThreadForThreadId_ID = 0; +static jmethodID listAdd_ID = 0; + +#define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; } +#define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;} +#define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; } +#define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;} + +static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) { + (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg); +} + +static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) { + jlong ptr = (*env)->GetLongField(env, this_obj, p_ps_prochandle_ID); + return (struct ps_prochandle*)(intptr_t)ptr; +} + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal + * Method: init0 + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0 + (JNIEnv *env, jclass cls) { + jclass listClass; + + if (init_libproc(getenv("LIBSAPROC_DEBUG") != NULL) != true) { + THROW_NEW_DEBUGGER_EXCEPTION("can't initialize libproc"); + } + + // fields we use + p_ps_prochandle_ID = (*env)->GetFieldID(env, cls, "p_ps_prochandle", "J"); + CHECK_EXCEPTION; + threadList_ID = (*env)->GetFieldID(env, cls, "threadList", "Ljava/util/List;"); + CHECK_EXCEPTION; + loadObjectList_ID = (*env)->GetFieldID(env, cls, "loadObjectList", "Ljava/util/List;"); + CHECK_EXCEPTION; + + // methods we use + createClosestSymbol_ID = (*env)->GetMethodID(env, cls, "createClosestSymbol", + "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;"); + CHECK_EXCEPTION; + createLoadObject_ID = (*env)->GetMethodID(env, cls, "createLoadObject", + "(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;"); + CHECK_EXCEPTION; + getThreadForThreadId_ID = (*env)->GetMethodID(env, cls, "getThreadForThreadId", + "(J)Lsun/jvm/hotspot/debugger/ThreadProxy;"); + CHECK_EXCEPTION; + // java.util.List method we call + listClass = (*env)->FindClass(env, "java/util/List"); + CHECK_EXCEPTION; + listAdd_ID = (*env)->GetMethodID(env, listClass, "add", "(Ljava/lang/Object;)Z"); + CHECK_EXCEPTION; +} + +JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize + (JNIEnv *env, jclass cls) +{ +#ifdef _LP64 + return 8; +#else + return 4; +#endif + +} + + +static void fillThreadsAndLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) { + int n = 0, i = 0; + + // add threads + n = get_num_threads(ph); + for (i = 0; i < n; i++) { + jobject thread; + jobject threadList; + lwpid_t lwpid; + + lwpid = get_lwp_id(ph, i); + thread = (*env)->CallObjectMethod(env, this_obj, getThreadForThreadId_ID, + (jlong)lwpid); + CHECK_EXCEPTION; + threadList = (*env)->GetObjectField(env, this_obj, threadList_ID); + CHECK_EXCEPTION; + (*env)->CallBooleanMethod(env, threadList, listAdd_ID, thread); + CHECK_EXCEPTION; + } + + // add load objects + n = get_num_libs(ph); + for (i = 0; i < n; i++) { + uintptr_t base; + const char* name; + jobject loadObject; + jobject loadObjectList; + + base = get_lib_base(ph, i); + name = get_lib_name(ph, i); + loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID, + (*env)->NewStringUTF(env, name), (jlong)0, (jlong)base); + CHECK_EXCEPTION; + loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID); + CHECK_EXCEPTION; + (*env)->CallBooleanMethod(env, loadObjectList, listAdd_ID, loadObject); + CHECK_EXCEPTION; + } +} + +/* + * 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) { + + struct ps_prochandle* ph; + if ( (ph = Pgrab(jpid)) == NULL) { + THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process"); + } + (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph); + fillThreadsAndLoadObjects(env, this_obj, ph); +} + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal + * Method: attach0 + * Signature: (Ljava/lang/String;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 + (JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) { + const char *execName_cstr; + const char *coreName_cstr; + jboolean isCopy; + struct ps_prochandle* ph; + + execName_cstr = (*env)->GetStringUTFChars(env, execName, &isCopy); + CHECK_EXCEPTION; + coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy); + CHECK_EXCEPTION; + + if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) { + (*env)->ReleaseStringUTFChars(env, execName, execName_cstr); + (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr); + THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file"); + } + (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph); + (*env)->ReleaseStringUTFChars(env, execName, execName_cstr); + (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr); + fillThreadsAndLoadObjects(env, this_obj, ph); +} + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal + * Method: detach0 + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0 + (JNIEnv *env, jobject this_obj) { + struct ps_prochandle* ph = get_proc_handle(env, this_obj); + if (ph != NULL) { + Prelease(ph); + } +} + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal + * 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) { + const char *objectName_cstr, *symbolName_cstr; + jlong addr; + jboolean isCopy; + struct ps_prochandle* ph = get_proc_handle(env, this_obj); + + objectName_cstr = NULL; + if (objectName != NULL) { + objectName_cstr = (*env)->GetStringUTFChars(env, objectName, &isCopy); + CHECK_EXCEPTION_(0); + } + symbolName_cstr = (*env)->GetStringUTFChars(env, symbolName, &isCopy); + CHECK_EXCEPTION_(0); + + addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr); + + if (objectName_cstr != NULL) { + (*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr); + } + (*env)->ReleaseStringUTFChars(env, symbolName, symbolName_cstr); + return addr; +} + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal + * Method: lookupByAddress0 + * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol; + */ +JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0 + (JNIEnv *env, jobject this_obj, jlong addr) { + uintptr_t offset; + const char* sym = NULL; + + struct ps_prochandle* ph = get_proc_handle(env, this_obj); + sym = symbol_for_pc(ph, (uintptr_t) addr, &offset); + if (sym == NULL) return 0; + return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID, + (*env)->NewStringUTF(env, sym), (jlong)offset); +} + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal + * 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) { + + jboolean isCopy; + jbyteArray array; + jbyte *bufPtr; + ps_err_e err; + + array = (*env)->NewByteArray(env, numBytes); + CHECK_EXCEPTION_(0); + bufPtr = (*env)->GetByteArrayElements(env, array, &isCopy); + CHECK_EXCEPTION_(0); + + err = ps_pread(get_proc_handle(env, this_obj), (psaddr_t) (uintptr_t)addr, bufPtr, numBytes); + (*env)->ReleaseByteArrayElements(env, array, bufPtr, 0); + return (err == PS_OK)? array : 0; +} + +JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0 + (JNIEnv *env, jobject this_obj, jint lwp_id) { + + struct reg gregs; + jboolean isCopy; + jlongArray array; + jlong *regs; + + struct ps_prochandle* ph = get_proc_handle(env, this_obj); + if (get_lwp_regs(ph, lwp_id, &gregs) != true) { + THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0); + } + +#undef NPRGREG +#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 +#if defined(sparc) || defined(sparcv9) +#define NPRGREG sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_NPRGREG +#endif + + array = (*env)->NewLongArray(env, NPRGREG); + CHECK_EXCEPTION_(0); + regs = (*env)->GetLongArrayElements(env, array, &isCopy); + +#undef REG_INDEX + +#ifdef i386 +#define REG_INDEX(reg) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##reg + + regs[REG_INDEX(GS)] = (uintptr_t) gregs.r_gs; + regs[REG_INDEX(FS)] = (uintptr_t) gregs.r_fs; + regs[REG_INDEX(ES)] = (uintptr_t) gregs.r_es; + regs[REG_INDEX(DS)] = (uintptr_t) gregs.r_ds; + regs[REG_INDEX(EDI)] = (uintptr_t) gregs.r_edi; + regs[REG_INDEX(ESI)] = (uintptr_t) gregs.r_esi; + regs[REG_INDEX(FP)] = (uintptr_t) gregs.r_ebp; + regs[REG_INDEX(SP)] = (uintptr_t) gregs.r_isp; + regs[REG_INDEX(EBX)] = (uintptr_t) gregs.r_ebx; + regs[REG_INDEX(EDX)] = (uintptr_t) gregs.r_edx; + regs[REG_INDEX(ECX)] = (uintptr_t) gregs.r_ecx; + regs[REG_INDEX(EAX)] = (uintptr_t) gregs.r_eax; + regs[REG_INDEX(PC)] = (uintptr_t) gregs.r_eip; + regs[REG_INDEX(CS)] = (uintptr_t) gregs.r_cs; + regs[REG_INDEX(SS)] = (uintptr_t) gregs.r_ss; + +#endif /* i386 */ + +#if ia64 + regs = (*env)->GetLongArrayElements(env, array, &isCopy); + int i; + for (i = 0; i < NPRGREG; i++ ) { + regs[i] = 0xDEADDEAD; + } +#endif /* ia64 */ + +#ifdef amd64 +#define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg + + regs[REG_INDEX(R15)] = gregs.r_r15; + regs[REG_INDEX(R14)] = gregs.r_r14; + regs[REG_INDEX(R13)] = gregs.r_r13; + regs[REG_INDEX(R12)] = gregs.r_r12; + regs[REG_INDEX(RBP)] = gregs.r_rbp; + regs[REG_INDEX(RBX)] = gregs.r_rbx; + regs[REG_INDEX(R11)] = gregs.r_r11; + regs[REG_INDEX(R10)] = gregs.r_r10; + regs[REG_INDEX(R9)] = gregs.r_r9; + regs[REG_INDEX(R8)] = gregs.r_r8; + regs[REG_INDEX(RAX)] = gregs.r_rax; + regs[REG_INDEX(RCX)] = gregs.r_rcx; + regs[REG_INDEX(RDX)] = gregs.r_rdx; + regs[REG_INDEX(RSI)] = gregs.r_rsi; + regs[REG_INDEX(RDI)] = gregs.r_rdi; + regs[REG_INDEX(RIP)] = gregs.r_rip; + regs[REG_INDEX(CS)] = gregs.r_cs; + regs[REG_INDEX(RSP)] = gregs.r_rsp; + regs[REG_INDEX(SS)] = gregs.r_ss; +// regs[REG_INDEX(FSBASE)] = gregs.fs_base; +// regs[REG_INDEX(GSBASE)] = gregs.gs_base; +// regs[REG_INDEX(DS)] = gregs.ds; +// regs[REG_INDEX(ES)] = gregs.es; +// regs[REG_INDEX(FS)] = gregs.fs; +// regs[REG_INDEX(GS)] = gregs.gs; + +#endif /* amd64 */ + +#if defined(sparc) || defined(sparcv9) + +#define REG_INDEX(reg) sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_##reg + +#ifdef _LP64 + regs[REG_INDEX(R_PSR)] = gregs.tstate; + regs[REG_INDEX(R_PC)] = gregs.tpc; + regs[REG_INDEX(R_nPC)] = gregs.tnpc; + regs[REG_INDEX(R_Y)] = gregs.y; +#else + regs[REG_INDEX(R_PSR)] = gregs.psr; + regs[REG_INDEX(R_PC)] = gregs.pc; + regs[REG_INDEX(R_nPC)] = gregs.npc; + regs[REG_INDEX(R_Y)] = gregs.y; +#endif + regs[REG_INDEX(R_G0)] = 0 ; + regs[REG_INDEX(R_G1)] = gregs.u_regs[0]; + regs[REG_INDEX(R_G2)] = gregs.u_regs[1]; + regs[REG_INDEX(R_G3)] = gregs.u_regs[2]; + regs[REG_INDEX(R_G4)] = gregs.u_regs[3]; + regs[REG_INDEX(R_G5)] = gregs.u_regs[4]; + regs[REG_INDEX(R_G6)] = gregs.u_regs[5]; + regs[REG_INDEX(R_G7)] = gregs.u_regs[6]; + regs[REG_INDEX(R_O0)] = gregs.u_regs[7]; + regs[REG_INDEX(R_O1)] = gregs.u_regs[8]; + regs[REG_INDEX(R_O2)] = gregs.u_regs[ 9]; + regs[REG_INDEX(R_O3)] = gregs.u_regs[10]; + regs[REG_INDEX(R_O4)] = gregs.u_regs[11]; + regs[REG_INDEX(R_O5)] = gregs.u_regs[12]; + regs[REG_INDEX(R_O6)] = gregs.u_regs[13]; + regs[REG_INDEX(R_O7)] = gregs.u_regs[14]; +#endif /* sparc */ + + + (*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT); + return array; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/os/bsd/MacosxDebuggerLocal.m Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,406 @@ +/* + * Copyright (c) 2002, 2007, 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. + * + */ + +#include <objc/objc-runtime.h> +#import <Foundation/Foundation.h> +#import <JavaNativeFoundation/JavaNativeFoundation.h> + +#include <JavaVM/jni.h> + +#import <mach/mach.h> +#import <mach/mach_types.h> +#import <sys/sysctl.h> +#import <stdlib.h> + +jboolean debug = JNI_FALSE; + +static jfieldID symbolicatorID = 0; // set in _init0 +static jfieldID taskID = 0; // set in _init0 + +static void putSymbolicator(JNIEnv *env, jobject this_obj, id symbolicator) { + (*env)->SetLongField(env, this_obj, symbolicatorID, (jlong)(intptr_t)symbolicator); +} + +static id getSymbolicator(JNIEnv *env, jobject this_obj) { + jlong ptr = (*env)->GetLongField(env, this_obj, symbolicatorID); + return (id)(intptr_t)ptr; +} + +static void putTask(JNIEnv *env, jobject this_obj, task_t task) { + (*env)->SetLongField(env, this_obj, taskID, (jlong)task); +} + +static task_t getTask(JNIEnv *env, jobject this_obj) { + jlong ptr = (*env)->GetLongField(env, this_obj, taskID); + return (task_t)ptr; +} + +#define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; } +#define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;} +#define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; } +#define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;} + +static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) { + (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg); +} + +#if defined(__i386__) + #define hsdb_thread_state_t x86_thread_state32_t + #define hsdb_float_state_t x86_float_state32_t + #define HSDB_THREAD_STATE x86_THREAD_STATE32 + #define HSDB_FLOAT_STATE x86_FLOAT_STATE32 + #define HSDB_THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT + #define HSDB_FLOAT_STATE_COUNT x86_FLOAT_STATE32_COUNT +#elif defined(__x86_64__) + #define hsdb_thread_state_t x86_thread_state64_t + #define hsdb_float_state_t x86_float_state64_t + #define HSDB_THREAD_STATE x86_THREAD_STATE64 + #define HSDB_FLOAT_STATE x86_FLOAT_STATE64 + #define HSDB_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT + #define HSDB_FLOAT_STATE_COUNT x86_FLOAT_STATE64_COUNT +#else + #error "Unsupported architecture" +#endif + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal + * Method: init0 + * Signature: ()V + */ +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; +} + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal + * 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) { + jlong address = 0; + +JNF_COCOA_ENTER(env); + NSString *symbolNameString = JNFJavaToNSString(env, symbolName); + + if (debug) { + printf("lookupInProcess called for %s\n", [symbolNameString UTF8String]); + } + + id symbolicator = getSymbolicator(env, this_obj); + if (symbolicator != nil) { + uint64_t (*dynamicCall)(id, SEL, NSString *) = (uint64_t (*)(id, SEL, NSString *))&objc_msgSend; + address = (jlong) dynamicCall(symbolicator, @selector(addressForSymbol:), symbolNameString); + } + + if (debug) { + printf("address of symbol %s = %llx\n", [symbolNameString UTF8String], address); + } +JNF_COCOA_EXIT(env); + + return address; +} + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal + * 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) { + if (debug) printf("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes); + + // must allocate storage instead of using former parameter buf + jboolean isCopy; + jbyteArray array; + jbyte *bufPtr; + + array = (*env)->NewByteArray(env, numBytes); + CHECK_EXCEPTION_(0); + + unsigned long alignedAddress; + unsigned long alignedLength; + kern_return_t result; + vm_offset_t *pages; + int *mapped; + long pageCount; + uint byteCount; + int i; + unsigned long remaining; + + alignedAddress = trunc_page(addr); + if (addr != alignedAddress) { + alignedLength += addr - alignedAddress; + } + alignedLength = round_page(numBytes); + pageCount = alignedLength/vm_page_size; + + // Allocate storage for pages and flags. + pages = malloc(pageCount * sizeof(vm_offset_t)); + mapped = calloc(pageCount, sizeof(int)); + + task_t gTask = getTask(env, this_obj); + // Try to read each of the pages. + for (i = 0; i < pageCount; i++) { + result = vm_read(gTask, alignedAddress + i*vm_page_size, vm_page_size, + &pages[i], &byteCount); + mapped[i] = (result == KERN_SUCCESS); + // assume all failures are unmapped pages + } + + if (debug) fprintf(stderr, "%ld pages\n", pageCount); + + remaining = numBytes; + + for (i = 0; i < pageCount; i++) { + unsigned long len = vm_page_size; + unsigned long start = 0; + + if (i == 0) { + start = addr - alignedAddress; + len = vm_page_size - start; + } + + if (i == (pageCount - 1)) { + len = remaining; + } + + if (mapped[i]) { + if (debug) fprintf(stderr, "page %d mapped (len %ld start %ld)\n", i, len, start); + (*env)->SetByteArrayRegion(env, array, 0, len, ((jbyte *) pages[i] + start)); + vm_deallocate(mach_task_self(), pages[i], vm_page_size); + } + + remaining -= len; + } + + free (pages); + free (mapped); + return array; +} + +/* + * Class: sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal + * Method: getThreadIntegerRegisterSet0 + * Signature: (I)[J + */ +JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0(JNIEnv *env, jobject this_obj, jint lwp_id) { + if (debug) + printf("getThreadRegisterSet0 called\n"); + + kern_return_t result; + thread_t tid; + mach_msg_type_number_t count = HSDB_THREAD_STATE_COUNT; + hsdb_thread_state_t state; + unsigned int *r; + int i; + jlongArray registerArray; + jlong *primitiveArray; + + tid = lwp_id; + + result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count); + + if (result != KERN_SUCCESS) { + if (debug) + printf("getregs: thread_get_state(%d) failed (%d)\n", tid, result); + return NULL; + } + + // 40 32-bit registers on ppc, 16 on x86. + // Output order is the same as the order in the ppc_thread_state/i386_thread_state struct. +#if defined(__i386__) + r = (unsigned int *)&state; + registerArray = (*env)->NewLongArray(env, 8); + primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL); + primitiveArray[0] = r[0]; // eax + primitiveArray[1] = r[2]; // ecx + primitiveArray[2] = r[3]; // edx + primitiveArray[3] = r[1]; // ebx + primitiveArray[4] = r[7]; // esp + primitiveArray[5] = r[6]; // ebp + primitiveArray[6] = r[5]; // esi + primitiveArray[7] = r[4]; // edi + (*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0); +#elif defined(__x86_64__) + /* From AMD64ThreadContext.java + public static final int R15 = 0; + public static final int R14 = 1; + public static final int R13 = 2; + public static final int R12 = 3; + public static final int R11 = 4; + public static final int R10 = 5; + public static final int R9 = 6; + public static final int R8 = 7; + public static final int RDI = 8; + public static final int RSI = 9; + public static final int RBP = 10; + public static final int RBX = 11; + public static final int RDX = 12; + public static final int RCX = 13; + public static final int RAX = 14; + public static final int TRAPNO = 15; + public static final int ERR = 16; + public static final int RIP = 17; + public static final int CS = 18; + public static final int RFL = 19; + public static final int RSP = 20; + public static final int SS = 21; + public static final int FS = 22; + public static final int GS = 23; + public static final int ES = 24; + public static final int DS = 25; + public static final int FSBASE = 26; + public static final int GSBASE = 27; + */ + // 64 bit + if (debug) printf("Getting threads for a 64-bit process\n"); + registerArray = (*env)->NewLongArray(env, 28); + primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL); + + primitiveArray[0] = state.__r15; + primitiveArray[1] = state.__r14; + primitiveArray[2] = state.__r13; + primitiveArray[3] = state.__r12; + primitiveArray[4] = state.__r11; + primitiveArray[5] = state.__r10; + primitiveArray[6] = state.__r9; + primitiveArray[7] = state.__r8; + primitiveArray[8] = state.__rdi; + primitiveArray[9] = state.__rsi; + primitiveArray[10] = state.__rbp; + primitiveArray[11] = state.__rbx; + primitiveArray[12] = state.__rdx; + primitiveArray[13] = state.__rcx; + primitiveArray[14] = state.__rax; + primitiveArray[15] = 0; // trapno ? + primitiveArray[16] = 0; // err ? + primitiveArray[17] = state.__rip; + primitiveArray[18] = state.__cs; + primitiveArray[19] = state.__rflags; + primitiveArray[20] = state.__rsp; + primitiveArray[21] = 0; // We don't have SS + primitiveArray[22] = state.__fs; + primitiveArray[23] = state.__gs; + primitiveArray[24] = 0; + primitiveArray[25] = 0; + primitiveArray[26] = 0; + primitiveArray[27] = 0; + + if (debug) printf("set registers\n"); + + (*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0); +#else +#error Unsupported architecture +#endif + + return registerArray; +} + +/* + * Class: sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal + * Method: translateTID0 + * Signature: (I)I + */ +JNIEXPORT jint JNICALL +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); + result = mach_port_extract_right(gTask, foreign_tid, + MACH_MSG_TYPE_COPY_SEND, + &usable_tid, &type); + if (result != KERN_SUCCESS) + return -1; + + if (debug) + printf("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid); + + return (jint) usable_tid; +} + +/* + * 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) { +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); + + kern_return_t result; + task_t gTask = 0; + result = task_for_pid(mach_task_self(), jpid, &gTask); + if (result != KERN_SUCCESS) { + fprintf(stderr, "attach: task_for_pid(%d) failed (%d)\n", (int)jpid, result); + THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process"); + } + putTask(env, this_obj, gTask); + + id symbolicator = nil; + id jrsSymbolicator = objc_lookUpClass("JRSSymbolicator"); + if (jrsSymbolicator != nil) { + id (*dynamicCall)(id, SEL, pid_t) = (id (*)(id, SEL, pid_t))&objc_msgSend; + symbolicator = dynamicCall(jrsSymbolicator, @selector(symbolicatorForPid:), (pid_t)jpid); + } + if (symbolicator != nil) { + CFRetain(symbolicator); // pin symbolicator while in java heap + } + + putSymbolicator(env, this_obj, symbolicator); + if (symbolicator == nil) { + THROW_NEW_DEBUGGER_EXCEPTION("Can't attach symbolicator to the process"); + } + +JNF_COCOA_EXIT(env); +} + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal + * Method: detach0 + * Signature: ()V + */ +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); + mach_port_deallocate(mach_task_self(), gTask); + id symbolicator = getSymbolicator(env, this_obj); + if (symbolicator != nil) { + CFRelease(symbolicator); + } +JNF_COCOA_EXIT(env); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/os/bsd/Makefile Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,77 @@ +# +# Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +ARCH := $(shell if ([ `uname -m` = "ia64" ]) ; then echo ia64 ; elif ([ `uname -m` = "amd64" ]) ; then echo amd64; elif ([ `uname -m` = "sparc64" ]) ; then echo sparc; else echo i386 ; fi ) +GCC = gcc + +JAVAH = ${JAVA_HOME}/bin/javah + +SOURCES = salibelf.c \ + symtab.c \ + libproc_impl.c \ + ps_proc.c \ + ps_core.c \ + BsdDebuggerLocal.c + +INCLUDES = -I${JAVA_HOME}/include -I${JAVA_HOME}/include/$(shell uname -s | tr "[:upper:]" "[:lower:]") + +OBJS = $(SOURCES:.c=.o) + +LIBS = -lutil -lthread_db + +CFLAGS = -c -fPIC -g -Wall -D_ALLBSD_SOURCE -D_GNU_SOURCE -D$(ARCH) $(INCLUDES) + +LIBSA = $(ARCH)/libsaproc.so + +all: $(LIBSA) + +BsdDebuggerLocal.o: BsdDebuggerLocal.c + $(JAVAH) -jni -classpath ../../../../../build/bsd-i586/hotspot/outputdir/bsd_i486_compiler2/generated/saclasses \ + sun.jvm.hotspot.debugger.x86.X86ThreadContext \ + sun.jvm.hotspot.debugger.amd64.AMD64ThreadContext + $(GCC) $(CFLAGS) $< + +.c.obj: + $(GCC) $(CFLAGS) + +ifndef LDNOMAP + LFLAGS_LIBSA = -Xlinker --version-script=mapfile +endif + +$(LIBSA): $(OBJS) mapfile + if [ ! -d $(ARCH) ] ; then mkdir $(ARCH) ; fi + $(GCC) -shared $(LFLAGS_LIBSA) -o $(LIBSA) $(OBJS) $(LIBS) + +test.o: $(LIBSA) test.c + $(GCC) -c -o test.o -g -D_GNU_SOURCE -D$(ARCH) $(INCLUDES) test.c + +test: test.o + $(GCC) -o test test.o -L$(ARCH) -lsaproc $(LIBS) + +clean: + rm -f $(LIBSA) + rm -f $(OBJS) + rm -f test.o + -rmdir $(ARCH) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/os/bsd/StubDebuggerLocal.c Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 <stdlib.h> +#include <jni.h> + +#define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; } +#define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;} +#define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; } +#define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;} + +static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) { + (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg); +} + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal + * Method: init0 + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0 + (JNIEnv *env, jclass cls) { +} + +JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize + (JNIEnv *env, jclass cls) +{ +#ifdef _LP64 + return 8; +#else + return 4; +#endif + +} + +/* + * 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) { + + THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process"); +} + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal + * Method: attach0 + * Signature: (Ljava/lang/String;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 + (JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) { + THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file"); +} + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal + * Method: detach0 + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0 + (JNIEnv *env, jobject this_obj) { +} + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal + * 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) { + return 0; +} + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal + * Method: lookupByAddress0 + * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol; + */ +JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0 + (JNIEnv *env, jobject this_obj, jlong addr) { + return 0; +} + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal + * 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) { + return 0; +} + +JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0 + (JNIEnv *env, jobject this_obj, jint lwp_id) { + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/os/bsd/elfmacros.h Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 _ELFMACROS_H_ +#define _ELFMACROS_H_ + +#define ELF_NHDR Elf_Note + +#if defined(_LP64) +#define ELF_EHDR Elf64_Ehdr +#define ELF_SHDR Elf64_Shdr +#define ELF_PHDR Elf64_Phdr +#define ELF_SYM Elf64_Sym +#define ELF_DYN Elf64_Dyn +#define ELF_ADDR Elf64_Addr + +#ifndef ELF_ST_TYPE +#define ELF_ST_TYPE ELF64_ST_TYPE +#endif + +#else + +#define ELF_EHDR Elf32_Ehdr +#define ELF_SHDR Elf32_Shdr +#define ELF_PHDR Elf32_Phdr +#define ELF_SYM Elf32_Sym +#define ELF_DYN Elf32_Dyn +#define ELF_ADDR Elf32_Addr + +#ifndef ELF_ST_TYPE +#define ELF_ST_TYPE ELF32_ST_TYPE +#endif + +#endif + + +#endif /* _ELFMACROS_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/os/bsd/libproc.h Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2003, 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. + * + */ + +#ifndef _LIBPROC_H_ +#define _LIBPROC_H_ + +#include <unistd.h> +#include <stdint.h> +#include <machine/reg.h> +#include <proc_service.h> + +#if defined(sparc) || defined(sparcv9) +/* + If _LP64 is defined ptrace.h should be taken from /usr/include/asm-sparc64 + otherwise it should be from /usr/include/asm-sparc + These two files define pt_regs structure differently +*/ +#ifdef _LP64 +#include "asm-sparc64/ptrace.h" +#else +#include "asm-sparc/ptrace.h" +#endif + +#endif //sparc or sparcv9 + +/************************************************************************************ + +0. This is very minimal subset of Solaris libproc just enough for current application. +Please note that the bulk of the functionality is from proc_service interface. This +adds Pgrab__ and some missing stuff. We hide the difference b/w live process and core +file by this interface. + +1. pthread_id is unique. We store this in OSThread::_pthread_id in JVM code. + +2. All threads see the same pid when they call getpid(). +We used to save the result of ::getpid() call in OSThread::_thread_id. +Because gettid returns actual pid of thread (lwp id), this is +unique again. We therefore use OSThread::_thread_id as unique identifier. + +3. There is a unique LWP id under both thread libraries. libthread_db maps pthread_id +to its underlying lwp_id under both the thread libraries. thread_info.lwp_id stores +lwp_id of the thread. The lwp id is nothing but the actual pid of clone'd processes. But +unfortunately libthread_db does not work very well for core dumps. So, we get pthread_id +only for processes. For core dumps, we don't use libthread_db at all (like gdb). + +4. ptrace operates on this LWP id under both the thread libraries. When we say 'pid' for +ptrace call, we refer to lwp_id of the thread. + +5. for core file, we parse ELF files and read data from them. For processes we use +combination of ptrace and /proc calls. + +*************************************************************************************/ + +// This C bool type must be int for compatibility with BSD calls and +// it would be a mistake to equivalence it to C++ bool on many platforms + +typedef int bool; +#define true 1 +#define false 0 + +struct ps_prochandle; + +// attach to a process +struct ps_prochandle* Pgrab(pid_t pid); + +// attach to a core dump +struct ps_prochandle* Pgrab_core(const char* execfile, const char* corefile); + +// release a process or core +void Prelease(struct ps_prochandle* ph); + +// functions not directly available in Solaris libproc + +// initialize libproc (call this only once per app) +// pass true to make library verbose +bool init_libproc(bool verbose); + +// get number of threads +int get_num_threads(struct ps_prochandle* ph); + +// get lwp_id of n'th thread +lwpid_t get_lwp_id(struct ps_prochandle* ph, int index); + +// get regs for a given lwp +bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lid, struct reg* regs); + +// get number of shared objects +int get_num_libs(struct ps_prochandle* ph); + +// get name of n'th lib +const char* get_lib_name(struct ps_prochandle* ph, int index); + +// get base of lib +uintptr_t get_lib_base(struct ps_prochandle* ph, int index); + +// returns true if given library is found in lib list +bool find_lib(struct ps_prochandle* ph, const char *lib_name); + +// symbol lookup +uintptr_t lookup_symbol(struct ps_prochandle* ph, const char* object_name, + const char* sym_name); + +// address->nearest symbol lookup. return NULL for no symbol +const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset); + +#endif //__LIBPROC_H_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/os/bsd/libproc_impl.c Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,452 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <thread_db.h> +#include "libproc_impl.h" + +static const char* alt_root = NULL; +static int alt_root_len = -1; + +#define SA_ALTROOT "SA_ALTROOT" + +static void init_alt_root() { + if (alt_root_len == -1) { + alt_root = getenv(SA_ALTROOT); + if (alt_root) { + alt_root_len = strlen(alt_root); + } else { + alt_root_len = 0; + } + } +} + +int pathmap_open(const char* name) { + int fd; + char alt_path[PATH_MAX + 1]; + + init_alt_root(); + fd = open(name, O_RDONLY); + if (fd >= 0) { + return fd; + } + + if (alt_root_len > 0) { + strcpy(alt_path, alt_root); + strcat(alt_path, name); + fd = open(alt_path, O_RDONLY); + if (fd >= 0) { + print_debug("path %s substituted for %s\n", alt_path, name); + return fd; + } + + if (strrchr(name, '/')) { + strcpy(alt_path, alt_root); + strcat(alt_path, strrchr(name, '/')); + fd = open(alt_path, O_RDONLY); + if (fd >= 0) { + print_debug("path %s substituted for %s\n", alt_path, name); + return fd; + } + } + } + + return -1; +} + +static bool _libsaproc_debug; + +void print_debug(const char* format,...) { + if (_libsaproc_debug) { + va_list alist; + + va_start(alist, format); + fputs("libsaproc DEBUG: ", stderr); + vfprintf(stderr, format, alist); + va_end(alist); + } +} + +bool is_debug() { + return _libsaproc_debug; +} + +// initialize libproc +bool init_libproc(bool debug) { + // init debug mode + _libsaproc_debug = debug; + + // initialize the thread_db library + if (td_init() != TD_OK) { + print_debug("libthread_db's td_init failed\n"); + return false; + } + + return true; +} + +static void destroy_lib_info(struct ps_prochandle* ph) { + lib_info* lib = ph->libs; + while (lib) { + lib_info *next = lib->next; + if (lib->symtab) { + destroy_symtab(lib->symtab); + } + free(lib); + lib = next; + } +} + +static void destroy_thread_info(struct ps_prochandle* ph) { + thread_info* thr = ph->threads; + while (thr) { + thread_info *next = thr->next; + free(thr); + thr = next; + } +} + +// ps_prochandle cleanup + +// ps_prochandle cleanup +void Prelease(struct ps_prochandle* ph) { + // do the "derived class" clean-up first + ph->ops->release(ph); + destroy_lib_info(ph); + destroy_thread_info(ph); + free(ph); +} + +lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base) { + return add_lib_info_fd(ph, libname, -1, base); +} + +lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) { + lib_info* newlib; + + if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) { + print_debug("can't allocate memory for lib_info\n"); + return NULL; + } + + strncpy(newlib->name, libname, sizeof(newlib->name)); + newlib->base = base; + + if (fd == -1) { + if ( (newlib->fd = pathmap_open(newlib->name)) < 0) { + print_debug("can't open shared object %s\n", newlib->name); + free(newlib); + return NULL; + } + } else { + newlib->fd = fd; + } + + // check whether we have got an ELF file. /proc/<pid>/map + // gives out all file mappings and not just shared objects + if (is_elf_file(newlib->fd) == false) { + close(newlib->fd); + free(newlib); + return NULL; + } + + newlib->symtab = build_symtab(newlib->fd); + if (newlib->symtab == NULL) { + print_debug("symbol table build failed for %s\n", newlib->name); + } + else { + print_debug("built symbol table for %s\n", newlib->name); + } + + // even if symbol table building fails, we add the lib_info. + // This is because we may need to read from the ELF file for core file + // address read functionality. lookup_symbol checks for NULL symtab. + if (ph->libs) { + ph->lib_tail->next = newlib; + ph->lib_tail = newlib; + } else { + ph->libs = ph->lib_tail = newlib; + } + ph->num_libs++; + + return newlib; +} + +// lookup for a specific symbol +uintptr_t lookup_symbol(struct ps_prochandle* ph, const char* object_name, + const char* sym_name) { + // ignore object_name. search in all libraries + // FIXME: what should we do with object_name?? The library names are obtained + // by parsing /proc/<pid>/maps, which may not be the same as object_name. + // What we need is a utility to map object_name to real file name, something + // dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For + // now, we just ignore object_name and do a global search for the symbol. + + lib_info* lib = ph->libs; + while (lib) { + if (lib->symtab) { + uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL); + if (res) return res; + } + lib = lib->next; + } + + print_debug("lookup failed for symbol '%s' in obj '%s'\n", + sym_name, object_name); + return (uintptr_t) NULL; +} + + +const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset) { + const char* res = NULL; + lib_info* lib = ph->libs; + while (lib) { + if (lib->symtab && addr >= lib->base) { + res = nearest_symbol(lib->symtab, addr - lib->base, poffset); + if (res) return res; + } + lib = lib->next; + } + return NULL; +} + +// add a thread to ps_prochandle +thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) { + thread_info* newthr; + if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) { + print_debug("can't allocate memory for thread_info\n"); + return NULL; + } + + // initialize thread info + newthr->pthread_id = pthread_id; + newthr->lwp_id = lwp_id; + + // add new thread to the list + newthr->next = ph->threads; + ph->threads = newthr; + ph->num_threads++; + return newthr; +} + + +// struct used for client data from thread_db callback +struct thread_db_client_data { + struct ps_prochandle* ph; + thread_info_callback callback; +}; + +// callback function for libthread_db +static int thread_db_callback(const td_thrhandle_t *th_p, void *data) { + struct thread_db_client_data* ptr = (struct thread_db_client_data*) data; + td_thrinfo_t ti; + td_err_e err; + + memset(&ti, 0, sizeof(ti)); + err = td_thr_get_info(th_p, &ti); + if (err != TD_OK) { + print_debug("libthread_db : td_thr_get_info failed, can't get thread info\n"); + return err; + } + + print_debug("thread_db : pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid); + + if (ptr->callback(ptr->ph, (pthread_t)ti.ti_tid, ti.ti_lid) != true) + return TD_ERR; + + return TD_OK; +} + +// read thread_info using libthread_db +bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb) { + struct thread_db_client_data mydata; + td_thragent_t* thread_agent = NULL; + if (td_ta_new(ph, &thread_agent) != TD_OK) { + print_debug("can't create libthread_db agent\n"); + return false; + } + + mydata.ph = ph; + mydata.callback = cb; + + // we use libthread_db iterator to iterate thru list of threads. + if (td_ta_thr_iter(thread_agent, thread_db_callback, &mydata, + TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, + TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS) != TD_OK) { + td_ta_delete(thread_agent); + return false; + } + + // delete thread agent + td_ta_delete(thread_agent); + return true; +} + + +// get number of threads +int get_num_threads(struct ps_prochandle* ph) { + return ph->num_threads; +} + +// get lwp_id of n'th thread +lwpid_t get_lwp_id(struct ps_prochandle* ph, int index) { + int count = 0; + thread_info* thr = ph->threads; + while (thr) { + if (count == index) { + return thr->lwp_id; + } + count++; + thr = thr->next; + } + return -1; +} + +// get regs for a given lwp +bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, struct reg* regs) { + return ph->ops->get_lwp_regs(ph, lwp_id, regs); +} + +// get number of shared objects +int get_num_libs(struct ps_prochandle* ph) { + return ph->num_libs; +} + +// get name of n'th solib +const char* get_lib_name(struct ps_prochandle* ph, int index) { + int count = 0; + lib_info* lib = ph->libs; + while (lib) { + if (count == index) { + return lib->name; + } + count++; + lib = lib->next; + } + return NULL; +} + +// get base address of a lib +uintptr_t get_lib_base(struct ps_prochandle* ph, int index) { + int count = 0; + lib_info* lib = ph->libs; + while (lib) { + if (count == index) { + return lib->base; + } + count++; + lib = lib->next; + } + return (uintptr_t)NULL; +} + +bool find_lib(struct ps_prochandle* ph, const char *lib_name) { + lib_info *p = ph->libs; + while (p) { + if (strcmp(p->name, lib_name) == 0) { + return true; + } + p = p->next; + } + return false; +} + +//-------------------------------------------------------------------------- +// proc service functions + +// ps_pglobal_lookup() looks up the symbol sym_name in the symbol table +// of the load object object_name in the target process identified by ph. +// It returns the symbol's value as an address in the target process in +// *sym_addr. + +ps_err_e ps_pglobal_lookup(struct ps_prochandle *ph, const char *object_name, + const char *sym_name, psaddr_t *sym_addr) { + *sym_addr = (psaddr_t) lookup_symbol(ph, object_name, sym_name); + return (*sym_addr ? PS_OK : PS_NOSYM); +} + +// read "size" bytes info "buf" from address "addr" +ps_err_e ps_pread(struct ps_prochandle *ph, psaddr_t addr, + void *buf, size_t size) { + return ph->ops->p_pread(ph, (uintptr_t) addr, buf, size)? PS_OK: PS_ERR; +} + +// write "size" bytes of data to debuggee at address "addr" +ps_err_e ps_pwrite(struct ps_prochandle *ph, psaddr_t addr, + const void *buf, size_t size) { + return ph->ops->p_pwrite(ph, (uintptr_t)addr, buf, size)? PS_OK: PS_ERR; +} + +// fill in ptrace_lwpinfo for lid +ps_err_e ps_linfo(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo) { + return ph->ops->get_lwp_info(ph, lwp_id, linfo)? PS_OK: PS_ERR; +} + +// needed for when libthread_db is compiled with TD_DEBUG defined +void +ps_plog (const char *format, ...) +{ + va_list alist; + + va_start(alist, format); + vfprintf(stderr, format, alist); + va_end(alist); +} + +// ------------------------------------------------------------------------ +// Functions below this point are not yet implemented. They are here only +// to make the linker happy. + +ps_err_e ps_lsetfpregs(struct ps_prochandle *ph, lwpid_t lid, const prfpregset_t *fpregs) { + print_debug("ps_lsetfpregs not implemented\n"); + return PS_OK; +} + +ps_err_e ps_lsetregs(struct ps_prochandle *ph, lwpid_t lid, const prgregset_t gregset) { + print_debug("ps_lsetregs not implemented\n"); + return PS_OK; +} + +ps_err_e ps_lgetfpregs(struct ps_prochandle *ph, lwpid_t lid, prfpregset_t *fpregs) { + print_debug("ps_lgetfpregs not implemented\n"); + return PS_OK; +} + +ps_err_e ps_lgetregs(struct ps_prochandle *ph, lwpid_t lid, prgregset_t gregset) { + print_debug("ps_lgetfpregs not implemented\n"); + return PS_OK; +} + +ps_err_e ps_lstop(struct ps_prochandle *ph, lwpid_t lid) { + print_debug("ps_lstop not implemented\n"); + return PS_OK; +} + +ps_err_e ps_pcontinue(struct ps_prochandle *ph) { + print_debug("ps_pcontinue not implemented\n"); + return PS_OK; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/os/bsd/libproc_impl.h Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 _LIBPROC_IMPL_H_ +#define _LIBPROC_IMPL_H_ + +#include <unistd.h> +#include <limits.h> +#include "libproc.h" +#include "symtab.h" + +// data structures in this file mimic those of Solaris 8.0 - libproc's Pcontrol.h + +#define BUF_SIZE (PATH_MAX + NAME_MAX + 1) + +// list of shared objects +typedef struct lib_info { + char name[BUF_SIZE]; + uintptr_t base; + struct symtab* symtab; + int fd; // file descriptor for lib + struct lib_info* next; +} lib_info; + +// list of threads +typedef struct thread_info { + lwpid_t lwp_id; + pthread_t pthread_id; // not used cores, always -1 + struct reg regs; // not for process, core uses for caching regset + struct thread_info* next; +} thread_info; + +// list of virtual memory maps +typedef struct map_info { + int fd; // file descriptor + off_t offset; // file offset of this mapping + uintptr_t vaddr; // starting virtual address + size_t memsz; // size of the mapping + struct map_info* next; +} map_info; + +// vtable for ps_prochandle +typedef struct ps_prochandle_ops { + // "derived class" clean-up + void (*release)(struct ps_prochandle* ph); + // read from debuggee + bool (*p_pread)(struct ps_prochandle *ph, + uintptr_t addr, char *buf, size_t size); + // write into debuggee + bool (*p_pwrite)(struct ps_prochandle *ph, + uintptr_t addr, const char *buf , size_t size); + // get integer regset of a thread + bool (*get_lwp_regs)(struct ps_prochandle* ph, lwpid_t lwp_id, struct reg* regs); + // get info on thread + bool (*get_lwp_info)(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo); +} ps_prochandle_ops; + +// the ps_prochandle + +struct core_data { + int core_fd; // file descriptor of core file + int exec_fd; // file descriptor of exec file + int interp_fd; // file descriptor of interpreter (ld-elf.so.1) + // part of the class sharing workaround + int classes_jsa_fd; // file descriptor of class share archive + uintptr_t dynamic_addr; // address of dynamic section of a.out + uintptr_t ld_base_addr; // base address of ld.so + size_t num_maps; // number of maps. + map_info* maps; // maps in a linked list + // part of the class sharing workaround + map_info* class_share_maps;// class share maps in a linked list + map_info** map_array; // sorted (by vaddr) array of map_info pointers +}; + +struct ps_prochandle { + ps_prochandle_ops* ops; // vtable ptr + pid_t pid; + int num_libs; + lib_info* libs; // head of lib list + lib_info* lib_tail; // tail of lib list - to append at the end + int num_threads; + thread_info* threads; // head of thread list + struct core_data* core; // data only used for core dumps, NULL for process +}; + +int pathmap_open(const char* name); + +void print_debug(const char* format,...); +bool is_debug(); + +typedef bool (*thread_info_callback)(struct ps_prochandle* ph, pthread_t pid, lwpid_t lwpid); + +// reads thread info using libthread_db and calls above callback for each thread +bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb); + +// adds a new shared object to lib list, returns NULL on failure +lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base); + +// adds a new shared object to lib list, supply open lib file descriptor as well +lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, + uintptr_t base); + +// adds a new thread to threads list, returns NULL on failure +thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id); + +// a test for ELF signature without using libelf +bool is_elf_file(int fd); + +#endif //_LIBPROC_IMPL_H_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/os/bsd/mapfile Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,66 @@ +# + +# +# Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Define public interface. + +SUNWprivate_1.1 { + global: + + # native methods of BsdDebuggerLocal class + Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0; + Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize; + Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I; + Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2; + Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0; + Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0; + Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0; + Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0; + Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0; + + # proc_service.h functions - to be used by libthread_db + ps_getpid; + ps_pglobal_lookup; + ps_pread; + ps_pwrite; + ps_lsetfpregs; + ps_lsetregs; + ps_lgetfpregs; + ps_lgetregs; + ps_lcontinue; + ps_lgetxmmregs; + ps_lsetxmmregs; + ps_lstop; + ps_linfo; + + # used by attach test program + init_libproc; + Pgrab; + Pgrab_core; + Prelease; + + local: + *; +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/os/bsd/ps_core.c Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,1023 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> +#include <stddef.h> +#include <elf.h> +#include <link.h> +#include "libproc_impl.h" +#include "salibelf.h" + +// This file has the libproc implementation to read core files. +// For live processes, refer to ps_proc.c. Portions of this is adapted +// /modelled after Solaris libproc.so (in particular Pcore.c) + +//---------------------------------------------------------------------- +// ps_prochandle cleanup helper functions + +// close all file descriptors +static void close_elf_files(struct ps_prochandle* ph) { + lib_info* lib = NULL; + + // close core file descriptor + if (ph->core->core_fd >= 0) + close(ph->core->core_fd); + + // close exec file descriptor + if (ph->core->exec_fd >= 0) + close(ph->core->exec_fd); + + // close interp file descriptor + if (ph->core->interp_fd >= 0) + close(ph->core->interp_fd); + + // close class share archive file + if (ph->core->classes_jsa_fd >= 0) + close(ph->core->classes_jsa_fd); + + // close all library file descriptors + lib = ph->libs; + while (lib) { + int fd = lib->fd; + if (fd >= 0 && fd != ph->core->exec_fd) close(fd); + lib = lib->next; + } +} + +// clean all map_info stuff +static void destroy_map_info(struct ps_prochandle* ph) { + map_info* map = ph->core->maps; + while (map) { + map_info* next = map->next; + free(map); + map = next; + } + + if (ph->core->map_array) { + free(ph->core->map_array); + } + + // Part of the class sharing workaround + map = ph->core->class_share_maps; + while (map) { + map_info* next = map->next; + free(map); + map = next; + } +} + +// ps_prochandle operations +static void core_release(struct ps_prochandle* ph) { + if (ph->core) { + close_elf_files(ph); + destroy_map_info(ph); + free(ph->core); + } +} + +static map_info* allocate_init_map(int fd, off_t offset, uintptr_t vaddr, size_t memsz) { + map_info* map; + if ( (map = (map_info*) calloc(1, sizeof(map_info))) == NULL) { + print_debug("can't allocate memory for map_info\n"); + return NULL; + } + + // initialize map + map->fd = fd; + map->offset = offset; + map->vaddr = vaddr; + map->memsz = memsz; + return map; +} + +// add map info with given fd, offset, vaddr and memsz +static map_info* add_map_info(struct ps_prochandle* ph, int fd, off_t offset, + uintptr_t vaddr, size_t memsz) { + map_info* map; + if ((map = allocate_init_map(fd, offset, vaddr, memsz)) == NULL) { + return NULL; + } + + // add this to map list + map->next = ph->core->maps; + ph->core->maps = map; + ph->core->num_maps++; + + return map; +} + +// Part of the class sharing workaround +static map_info* add_class_share_map_info(struct ps_prochandle* ph, off_t offset, + uintptr_t vaddr, size_t memsz) { + map_info* map; + if ((map = allocate_init_map(ph->core->classes_jsa_fd, + offset, vaddr, memsz)) == NULL) { + return NULL; + } + + map->next = ph->core->class_share_maps; + ph->core->class_share_maps = map; + return map; +} + +// Return the map_info for the given virtual address. We keep a sorted +// array of pointers in ph->map_array, so we can binary search. +static map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr) +{ + int mid, lo = 0, hi = ph->core->num_maps - 1; + map_info *mp; + + while (hi - lo > 1) { + mid = (lo + hi) / 2; + if (addr >= ph->core->map_array[mid]->vaddr) + lo = mid; + else + hi = mid; + } + + if (addr < ph->core->map_array[hi]->vaddr) + mp = ph->core->map_array[lo]; + else + mp = ph->core->map_array[hi]; + + if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) + return (mp); + + + // Part of the class sharing workaround + // Unfortunately, we have no way of detecting -Xshare state. + // Check out the share maps atlast, if we don't find anywhere. + // This is done this way so to avoid reading share pages + // ahead of other normal maps. For eg. with -Xshare:off we don't + // want to prefer class sharing data to data from core. + mp = ph->core->class_share_maps; + if (mp) { + print_debug("can't locate map_info at 0x%lx, trying class share maps\n", + addr); + } + while (mp) { + if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) { + print_debug("located map_info at 0x%lx from class share maps\n", + addr); + return (mp); + } + mp = mp->next; + } + + print_debug("can't locate map_info at 0x%lx\n", addr); + return (NULL); +} + +//--------------------------------------------------------------- +// Part of the class sharing workaround: +// +// With class sharing, pages are mapped from classes[_g].jsa file. +// The read-only class sharing pages are mapped as MAP_SHARED, +// PROT_READ pages. These pages are not dumped into core dump. +// With this workaround, these pages are read from classes[_g].jsa. + +// FIXME: !HACK ALERT! +// The format of sharing achive file header is needed to read shared heap +// file mappings. For now, I am hard coding portion of FileMapHeader here. +// Refer to filemap.hpp. + +// FileMapHeader describes the shared space data in the file to be +// mapped. This structure gets written to a file. It is not a class, +// so that the compilers don't add any compiler-private data to it. + +// Refer to CompactingPermGenGen::n_regions in compactingPermGenGen.hpp +#define NUM_SHARED_MAPS 4 + +// Refer to FileMapInfo::_current_version in filemap.hpp +#define CURRENT_ARCHIVE_VERSION 1 + +struct FileMapHeader { + int _magic; // identify file type. + int _version; // (from enum, above.) + size_t _alignment; // how shared archive should be aligned + + struct space_info { + int _file_offset; // sizeof(this) rounded to vm page size + char* _base; // copy-on-write base address + size_t _capacity; // for validity checking + size_t _used; // for setting space top on read + + // 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with + // the C type matching the C++ bool type on any given platform. For + // Hotspot on BSD we assume the corresponding C type is char but + // licensees on BSD versions may need to adjust the type of these fields. + char _read_only; // read only space? + char _allow_exec; // executable code in space? + + } _space[NUM_SHARED_MAPS]; // was _space[CompactingPermGenGen::n_regions]; + + // Ignore the rest of the FileMapHeader. We don't need those fields here. +}; + +static bool read_jboolean(struct ps_prochandle* ph, uintptr_t addr, jboolean* pvalue) { + jboolean i; + if (ps_pread(ph, (psaddr_t) addr, &i, sizeof(i)) == PS_OK) { + *pvalue = i; + return true; + } else { + return false; + } +} + +static bool read_pointer(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* pvalue) { + uintptr_t uip; + if (ps_pread(ph, (psaddr_t) addr, &uip, sizeof(uip)) == PS_OK) { + *pvalue = uip; + return true; + } else { + return false; + } +} + +// used to read strings from debuggee +static bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, size_t size) { + size_t i = 0; + char c = ' '; + + while (c != '\0') { + if (ps_pread(ph, (psaddr_t) addr, &c, sizeof(char)) != PS_OK) + return false; + if (i < size - 1) + buf[i] = c; + else // smaller buffer + return false; + i++; addr++; + } + + buf[i] = '\0'; + return true; +} + +#define USE_SHARED_SPACES_SYM "UseSharedSpaces" +// mangled name of Arguments::SharedArchivePath +#define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE" + +static bool init_classsharing_workaround(struct ps_prochandle* ph) { + lib_info* lib = ph->libs; + while (lib != NULL) { + // we are iterating over shared objects from the core dump. look for + // libjvm[_g].so. + const char *jvm_name = 0; + if ((jvm_name = strstr(lib->name, "/libjvm.so")) != 0 || + (jvm_name = strstr(lib->name, "/libjvm_g.so")) != 0) { + char classes_jsa[PATH_MAX]; + struct FileMapHeader header; + size_t n = 0; + int fd = -1, m = 0; + uintptr_t base = 0, useSharedSpacesAddr = 0; + uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0; + jboolean useSharedSpaces = 0; + + memset(classes_jsa, 0, sizeof(classes_jsa)); + jvm_name = lib->name; + useSharedSpacesAddr = lookup_symbol(ph, jvm_name, USE_SHARED_SPACES_SYM); + if (useSharedSpacesAddr == 0) { + print_debug("can't lookup 'UseSharedSpaces' flag\n"); + return false; + } + + // Hotspot vm types are not exported to build this library. So + // using equivalent type jboolean to read the value of + // UseSharedSpaces which is same as hotspot type "bool". + if (read_jboolean(ph, useSharedSpacesAddr, &useSharedSpaces) != true) { + print_debug("can't read the value of 'UseSharedSpaces' flag\n"); + return false; + } + + if ((int)useSharedSpaces == 0) { + print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n"); + return true; + } + + sharedArchivePathAddrAddr = lookup_symbol(ph, jvm_name, SHARED_ARCHIVE_PATH_SYM); + if (sharedArchivePathAddrAddr == 0) { + print_debug("can't lookup shared archive path symbol\n"); + return false; + } + + if (read_pointer(ph, sharedArchivePathAddrAddr, &sharedArchivePathAddr) != true) { + print_debug("can't read shared archive path pointer\n"); + return false; + } + + if (read_string(ph, sharedArchivePathAddr, classes_jsa, sizeof(classes_jsa)) != true) { + print_debug("can't read shared archive path value\n"); + return false; + } + + print_debug("looking for %s\n", classes_jsa); + // open the class sharing archive file + fd = pathmap_open(classes_jsa); + if (fd < 0) { + print_debug("can't open %s!\n", classes_jsa); + ph->core->classes_jsa_fd = -1; + return false; + } else { + print_debug("opened %s\n", classes_jsa); + } + + // read FileMapHeader from the file + memset(&header, 0, sizeof(struct FileMapHeader)); + if ((n = read(fd, &header, sizeof(struct FileMapHeader))) + != sizeof(struct FileMapHeader)) { + print_debug("can't read shared archive file map header from %s\n", classes_jsa); + close(fd); + return false; + } + + // check file magic + if (header._magic != 0xf00baba2) { + print_debug("%s has bad shared archive file magic number 0x%x, expecing 0xf00baba2\n", + classes_jsa, header._magic); + close(fd); + return false; + } + + // check version + if (header._version != CURRENT_ARCHIVE_VERSION) { + print_debug("%s has wrong shared archive file version %d, expecting %d\n", + classes_jsa, header._version, CURRENT_ARCHIVE_VERSION); + close(fd); + return false; + } + + ph->core->classes_jsa_fd = fd; + // add read-only maps from classes[_g].jsa to the list of maps + for (m = 0; m < NUM_SHARED_MAPS; m++) { + if (header._space[m]._read_only) { + base = (uintptr_t) header._space[m]._base; + // no need to worry about the fractional pages at-the-end. + // possible fractional pages are handled by core_read_data. + add_class_share_map_info(ph, (off_t) header._space[m]._file_offset, + base, (size_t) header._space[m]._used); + print_debug("added a share archive map at 0x%lx\n", base); + } + } + return true; + } + lib = lib->next; + } + return true; +} + + +//--------------------------------------------------------------------------- +// functions to handle map_info + +// Order mappings based on virtual address. We use this function as the +// callback for sorting the array of map_info pointers. +static int core_cmp_mapping(const void *lhsp, const void *rhsp) +{ + const map_info *lhs = *((const map_info **)lhsp); + const map_info *rhs = *((const map_info **)rhsp); + + if (lhs->vaddr == rhs->vaddr) + return (0); + + return (lhs->vaddr < rhs->vaddr ? -1 : 1); +} + +// we sort map_info by starting virtual address so that we can do +// binary search to read from an address. +static bool sort_map_array(struct ps_prochandle* ph) { + size_t num_maps = ph->core->num_maps; + map_info* map = ph->core->maps; + int i = 0; + + // allocate map_array + map_info** array; + if ( (array = (map_info**) malloc(sizeof(map_info*) * num_maps)) == NULL) { + print_debug("can't allocate memory for map array\n"); + return false; + } + + // add maps to array + while (map) { + array[i] = map; + i++; + map = map->next; + } + + // sort is called twice. If this is second time, clear map array + if (ph->core->map_array) free(ph->core->map_array); + ph->core->map_array = array; + // sort the map_info array by base virtual address. + qsort(ph->core->map_array, ph->core->num_maps, sizeof (map_info*), + core_cmp_mapping); + + // print map + if (is_debug()) { + int j = 0; + print_debug("---- sorted virtual address map ----\n"); + for (j = 0; j < ph->core->num_maps; j++) { + print_debug("base = 0x%lx\tsize = %d\n", ph->core->map_array[j]->vaddr, + ph->core->map_array[j]->memsz); + } + } + + return true; +} + +#ifndef MIN +#define MIN(x, y) (((x) < (y))? (x): (y)) +#endif + +static bool core_read_data(struct ps_prochandle* ph, uintptr_t addr, char *buf, size_t size) { + ssize_t resid = size; + int page_size=sysconf(_SC_PAGE_SIZE); + while (resid != 0) { + map_info *mp = core_lookup(ph, addr); + uintptr_t mapoff; + ssize_t len, rem; + off_t off; + int fd; + + if (mp == NULL) + break; /* No mapping for this address */ + + fd = mp->fd; + mapoff = addr - mp->vaddr; + len = MIN(resid, mp->memsz - mapoff); + off = mp->offset + mapoff; + + if ((len = pread(fd, buf, len, off)) <= 0) + break; + + resid -= len; + addr += len; + buf = (char *)buf + len; + + // mappings always start at page boundary. But, may end in fractional + // page. fill zeros for possible fractional page at the end of a mapping. + rem = mp->memsz % page_size; + if (rem > 0) { + rem = page_size - rem; + len = MIN(resid, rem); + resid -= len; + addr += len; + // we are not assuming 'buf' to be zero initialized. + memset(buf, 0, len); + buf += len; + } + } + + if (resid) { + print_debug("core read failed for %d byte(s) @ 0x%lx (%d more bytes)\n", + size, addr, resid); + return false; + } else { + return true; + } +} + +// null implementation for write +static bool core_write_data(struct ps_prochandle* ph, + uintptr_t addr, const char *buf , size_t size) { + return false; +} + +static bool core_get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, + struct reg* regs) { + // for core we have cached the lwp regs from NOTE section + thread_info* thr = ph->threads; + while (thr) { + if (thr->lwp_id == lwp_id) { + memcpy(regs, &thr->regs, sizeof(struct reg)); + return true; + } + thr = thr->next; + } + return false; +} + +static bool core_get_lwp_info(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo) { + print_debug("core_get_lwp_info not implemented\n"); + return false; +} + +static ps_prochandle_ops core_ops = { + .release= core_release, + .p_pread= core_read_data, + .p_pwrite= core_write_data, + .get_lwp_regs= core_get_lwp_regs, + .get_lwp_info= core_get_lwp_info +}; + +// read regs and create thread from NT_PRSTATUS entries from core file +static bool core_handle_prstatus(struct ps_prochandle* ph, const char* buf, size_t nbytes) { + // we have to read prstatus_t from buf + // assert(nbytes == sizeof(prstaus_t), "size mismatch on prstatus_t"); + prstatus_t* prstat = (prstatus_t*) buf; + thread_info* newthr; + print_debug("got integer regset for lwp %d\n", prstat->pr_pid); + // we set pthread_t to -1 for core dump + if((newthr = add_thread_info(ph, (pthread_t) -1, prstat->pr_pid)) == NULL) + return false; + + // copy regs + memcpy(&newthr->regs, &prstat->pr_reg, sizeof(struct reg)); + + if (is_debug()) { + print_debug("integer regset\n"); +#ifdef i386 + // print the regset + print_debug("\teax = 0x%x\n", newthr->regs.r_eax); + print_debug("\tebx = 0x%x\n", newthr->regs.r_ebx); + print_debug("\tecx = 0x%x\n", newthr->regs.r_ecx); + print_debug("\tedx = 0x%x\n", newthr->regs.r_edx); + print_debug("\tesp = 0x%x\n", newthr->regs.r_esp); + print_debug("\tebp = 0x%x\n", newthr->regs.r_ebp); + print_debug("\tesi = 0x%x\n", newthr->regs.r_esi); + print_debug("\tedi = 0x%x\n", newthr->regs.r_edi); + print_debug("\teip = 0x%x\n", newthr->regs.r_eip); +#endif + +#if defined(amd64) || defined(x86_64) + // print the regset + print_debug("\tr15 = 0x%lx\n", newthr->regs.r_r15); + print_debug("\tr14 = 0x%lx\n", newthr->regs.r_r14); + print_debug("\tr13 = 0x%lx\n", newthr->regs.r_r13); + print_debug("\tr12 = 0x%lx\n", newthr->regs.r_r12); + print_debug("\trbp = 0x%lx\n", newthr->regs.r_rbp); + print_debug("\trbx = 0x%lx\n", newthr->regs.r_rbx); + print_debug("\tr11 = 0x%lx\n", newthr->regs.r_r11); + print_debug("\tr10 = 0x%lx\n", newthr->regs.r_r10); + print_debug("\tr9 = 0x%lx\n", newthr->regs.r_r9); + print_debug("\tr8 = 0x%lx\n", newthr->regs.r_r8); + print_debug("\trax = 0x%lx\n", newthr->regs.r_rax); + print_debug("\trcx = 0x%lx\n", newthr->regs.r_rcx); + print_debug("\trdx = 0x%lx\n", newthr->regs.r_rdx); + print_debug("\trsi = 0x%lx\n", newthr->regs.r_rsi); + print_debug("\trdi = 0x%lx\n", newthr->regs.r_rdi); + //print_debug("\torig_rax = 0x%lx\n", newthr->regs.orig_rax); + print_debug("\trip = 0x%lx\n", newthr->regs.r_rip); + print_debug("\tcs = 0x%lx\n", newthr->regs.r_cs); + //print_debug("\teflags = 0x%lx\n", newthr->regs.eflags); + print_debug("\trsp = 0x%lx\n", newthr->regs.r_rsp); + print_debug("\tss = 0x%lx\n", newthr->regs.r_ss); + //print_debug("\tfs_base = 0x%lx\n", newthr->regs.fs_base); + //print_debug("\tgs_base = 0x%lx\n", newthr->regs.gs_base); + //print_debug("\tds = 0x%lx\n", newthr->regs.ds); + //print_debug("\tes = 0x%lx\n", newthr->regs.es); + //print_debug("\tfs = 0x%lx\n", newthr->regs.fs); + //print_debug("\tgs = 0x%lx\n", newthr->regs.gs); +#endif + } + + return true; +} + +#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y)) + +// read NT_PRSTATUS entries from core NOTE segment +static bool core_handle_note(struct ps_prochandle* ph, ELF_PHDR* note_phdr) { + char* buf = NULL; + char* p = NULL; + size_t size = note_phdr->p_filesz; + + // we are interested in just prstatus entries. we will ignore the rest. + // Advance the seek pointer to the start of the PT_NOTE data + if (lseek(ph->core->core_fd, note_phdr->p_offset, SEEK_SET) == (off_t)-1) { + print_debug("failed to lseek to PT_NOTE data\n"); + return false; + } + + // Now process the PT_NOTE structures. Each one is preceded by + // an Elf{32/64}_Nhdr structure describing its type and size. + if ( (buf = (char*) malloc(size)) == NULL) { + print_debug("can't allocate memory for reading core notes\n"); + goto err; + } + + // read notes into buffer + if (read(ph->core->core_fd, buf, size) != size) { + print_debug("failed to read notes, core file must have been truncated\n"); + goto err; + } + + p = buf; + while (p < buf + size) { + ELF_NHDR* notep = (ELF_NHDR*) p; + char* descdata = p + sizeof(ELF_NHDR) + ROUNDUP(notep->n_namesz, 4); + print_debug("Note header with n_type = %d and n_descsz = %u\n", + notep->n_type, notep->n_descsz); + + if (notep->n_type == NT_PRSTATUS) { + if (core_handle_prstatus(ph, descdata, notep->n_descsz) != true) + return false; + } + p = descdata + ROUNDUP(notep->n_descsz, 4); + } + + free(buf); + return true; + +err: + if (buf) free(buf); + return false; +} + +// read all segments from core file +static bool read_core_segments(struct ps_prochandle* ph, ELF_EHDR* core_ehdr) { + int i = 0; + ELF_PHDR* phbuf = NULL; + ELF_PHDR* core_php = NULL; + + if ((phbuf = read_program_header_table(ph->core->core_fd, core_ehdr)) == NULL) + return false; + + /* + * Now iterate through the program headers in the core file. + * We're interested in two types of Phdrs: PT_NOTE (which + * contains a set of saved /proc structures), and PT_LOAD (which + * represents a memory mapping from the process's address space). + * + * Difference b/w Solaris PT_NOTE and BSD PT_NOTE: + * + * In Solaris there are two PT_NOTE segments the first PT_NOTE (if present) + * contains /proc structs in the pre-2.6 unstructured /proc format. the last + * PT_NOTE has data in new /proc format. + * + * In Solaris, there is only one pstatus (process status). pstatus contains + * integer register set among other stuff. For each LWP, we have one lwpstatus + * entry that has integer regset for that LWP. + * + * Linux threads are actually 'clone'd processes. To support core analysis + * of "multithreaded" process, Linux creates more than one pstatus (called + * "prstatus") entry in PT_NOTE. Each prstatus entry has integer regset for one + * "thread". Please refer to Linux kernel src file 'fs/binfmt_elf.c', in particular + * function "elf_core_dump". + */ + + for (core_php = phbuf, i = 0; i < core_ehdr->e_phnum; i++) { + switch (core_php->p_type) { + case PT_NOTE: + if (core_handle_note(ph, core_php) != true) goto err; + break; + + case PT_LOAD: { + if (core_php->p_filesz != 0) { + if (add_map_info(ph, ph->core->core_fd, core_php->p_offset, + core_php->p_vaddr, core_php->p_filesz) == NULL) goto err; + } + break; + } + } + + core_php++; + } + + free(phbuf); + return true; +err: + free(phbuf); + return false; +} + +// read segments of a shared object +static bool read_lib_segments(struct ps_prochandle* ph, int lib_fd, ELF_EHDR* lib_ehdr, uintptr_t lib_base) { + int i = 0; + ELF_PHDR* phbuf; + ELF_PHDR* lib_php = NULL; + + if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL) + return false; + + // we want to process only PT_LOAD segments that are not writable. + // i.e., text segments. The read/write/exec (data) segments would + // have been already added from core file segments. + for (lib_php = phbuf, i = 0; i < lib_ehdr->e_phnum; i++) { + if ((lib_php->p_type == PT_LOAD) && !(lib_php->p_flags & PF_W) && (lib_php->p_filesz != 0)) { + if (add_map_info(ph, lib_fd, lib_php->p_offset, lib_php->p_vaddr + lib_base, lib_php->p_filesz) == NULL) + goto err; + } + lib_php++; + } + + free(phbuf); + return true; +err: + free(phbuf); + return false; +} + +// process segments from interpreter (ld-elf.so.1) +static bool read_interp_segments(struct ps_prochandle* ph) { + ELF_EHDR interp_ehdr; + + if (read_elf_header(ph->core->interp_fd, &interp_ehdr) != true) { + print_debug("interpreter is not a valid ELF file\n"); + return false; + } + + if (read_lib_segments(ph, ph->core->interp_fd, &interp_ehdr, ph->core->ld_base_addr) != true) { + print_debug("can't read segments of interpreter\n"); + return false; + } + + return true; +} + +// process segments of a a.out +static bool read_exec_segments(struct ps_prochandle* ph, ELF_EHDR* exec_ehdr) { + int i = 0; + ELF_PHDR* phbuf = NULL; + ELF_PHDR* exec_php = NULL; + + if ((phbuf = read_program_header_table(ph->core->exec_fd, exec_ehdr)) == NULL) + return false; + + for (exec_php = phbuf, i = 0; i < exec_ehdr->e_phnum; i++) { + switch (exec_php->p_type) { + + // add mappings for PT_LOAD segments + case PT_LOAD: { + // add only non-writable segments of non-zero filesz + if (!(exec_php->p_flags & PF_W) && exec_php->p_filesz != 0) { + if (add_map_info(ph, ph->core->exec_fd, exec_php->p_offset, exec_php->p_vaddr, exec_php->p_filesz) == NULL) goto err; + } + break; + } + + // read the interpreter and it's segments + case PT_INTERP: { + char interp_name[BUF_SIZE]; + + pread(ph->core->exec_fd, interp_name, MIN(exec_php->p_filesz, BUF_SIZE), exec_php->p_offset); + print_debug("ELF interpreter %s\n", interp_name); + // read interpreter segments as well + if ((ph->core->interp_fd = pathmap_open(interp_name)) < 0) { + print_debug("can't open runtime loader\n"); + goto err; + } + break; + } + + // from PT_DYNAMIC we want to read address of first link_map addr + case PT_DYNAMIC: { + ph->core->dynamic_addr = exec_php->p_vaddr; + print_debug("address of _DYNAMIC is 0x%lx\n", ph->core->dynamic_addr); + break; + } + + } // switch + exec_php++; + } // for + + free(phbuf); + return true; +err: + free(phbuf); + return false; +} + + +#define FIRST_LINK_MAP_OFFSET offsetof(struct r_debug, r_map) +#define LD_BASE_OFFSET offsetof(struct r_debug, r_ldbase) +#define LINK_MAP_ADDR_OFFSET offsetof(struct link_map, l_addr) +#define LINK_MAP_NAME_OFFSET offsetof(struct link_map, l_name) +#define LINK_MAP_NEXT_OFFSET offsetof(struct link_map, l_next) + +// read shared library info from runtime linker's data structures. +// This work is done by librtlb_db in Solaris +static bool read_shared_lib_info(struct ps_prochandle* ph) { + uintptr_t addr = ph->core->dynamic_addr; + uintptr_t debug_base; + uintptr_t first_link_map_addr; + uintptr_t ld_base_addr; + uintptr_t link_map_addr; + uintptr_t lib_base_diff; + uintptr_t lib_base; + uintptr_t lib_name_addr; + char lib_name[BUF_SIZE]; + ELF_DYN dyn; + ELF_EHDR elf_ehdr; + int lib_fd; + + // _DYNAMIC has information of the form + // [tag] [data] [tag] [data] ..... + // Both tag and data are pointer sized. + // We look for dynamic info with DT_DEBUG. This has shared object info. + // refer to struct r_debug in link.h + + dyn.d_tag = DT_NULL; + while (dyn.d_tag != DT_DEBUG) { + if (ps_pread(ph, (psaddr_t) addr, &dyn, sizeof(ELF_DYN)) != PS_OK) { + print_debug("can't read debug info from _DYNAMIC\n"); + return false; + } + addr += sizeof(ELF_DYN); + } + + // we have got Dyn entry with DT_DEBUG + debug_base = dyn.d_un.d_ptr; + // at debug_base we have struct r_debug. This has first link map in r_map field + if (ps_pread(ph, (psaddr_t) debug_base + FIRST_LINK_MAP_OFFSET, + &first_link_map_addr, sizeof(uintptr_t)) != PS_OK) { + print_debug("can't read first link map address\n"); + return false; + } + + // read ld_base address from struct r_debug + // XXX: There is no r_ldbase member on BSD +/* + if (ps_pread(ph, (psaddr_t) debug_base + LD_BASE_OFFSET, &ld_base_addr, + sizeof(uintptr_t)) != PS_OK) { + print_debug("can't read ld base address\n"); + return false; + } + ph->core->ld_base_addr = ld_base_addr; +*/ + ph->core->ld_base_addr = 0; + + print_debug("interpreter base address is 0x%lx\n", ld_base_addr); + + // now read segments from interp (i.e ld-elf.so.1) + if (read_interp_segments(ph) != true) + return false; + + // after adding interpreter (ld.so) mappings sort again + if (sort_map_array(ph) != true) + return false; + + print_debug("first link map is at 0x%lx\n", first_link_map_addr); + + link_map_addr = first_link_map_addr; + while (link_map_addr != 0) { + // read library base address of the .so. Note that even though <sys/link.h> calls + // link_map->l_addr as "base address", this is * not * really base virtual + // address of the shared object. This is actually the difference b/w the virtual + // address mentioned in shared object and the actual virtual base where runtime + // linker loaded it. We use "base diff" in read_lib_segments call below. + + if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_ADDR_OFFSET, + &lib_base_diff, sizeof(uintptr_t)) != PS_OK) { + print_debug("can't read shared object base address diff\n"); + return false; + } + + // read address of the name + if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_NAME_OFFSET, + &lib_name_addr, sizeof(uintptr_t)) != PS_OK) { + print_debug("can't read address of shared object name\n"); + return false; + } + + // read name of the shared object + if (read_string(ph, (uintptr_t) lib_name_addr, lib_name, sizeof(lib_name)) != true) { + print_debug("can't read shared object name\n"); + return false; + } + + if (lib_name[0] != '\0') { + // ignore empty lib names + lib_fd = pathmap_open(lib_name); + + if (lib_fd < 0) { + print_debug("can't open shared object %s\n", lib_name); + // continue with other libraries... + } else { + if (read_elf_header(lib_fd, &elf_ehdr)) { + lib_base = lib_base_diff + find_base_address(lib_fd, &elf_ehdr); + print_debug("reading library %s @ 0x%lx [ 0x%lx ]\n", + lib_name, lib_base, lib_base_diff); + // while adding library mappings we need to use "base difference". + if (! read_lib_segments(ph, lib_fd, &elf_ehdr, lib_base_diff)) { + print_debug("can't read shared object's segments\n"); + close(lib_fd); + return false; + } + add_lib_info_fd(ph, lib_name, lib_fd, lib_base); + // Map info is added for the library (lib_name) so + // we need to re-sort it before calling the p_pdread. + if (sort_map_array(ph) != true) + return false; + } else { + print_debug("can't read ELF header for shared object %s\n", lib_name); + close(lib_fd); + // continue with other libraries... + } + } + } + + // read next link_map address + if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_NEXT_OFFSET, + &link_map_addr, sizeof(uintptr_t)) != PS_OK) { + print_debug("can't read next link in link_map\n"); + return false; + } + } + + return true; +} + +// the one and only one exposed stuff from this file +struct ps_prochandle* Pgrab_core(const char* exec_file, const char* core_file) { + ELF_EHDR core_ehdr; + ELF_EHDR exec_ehdr; + + struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle)); + if (ph == NULL) { + print_debug("can't allocate ps_prochandle\n"); + return NULL; + } + + if ((ph->core = (struct core_data*) calloc(1, sizeof(struct core_data))) == NULL) { + free(ph); + print_debug("can't allocate ps_prochandle\n"); + return NULL; + } + + // initialize ph + ph->ops = &core_ops; + ph->core->core_fd = -1; + ph->core->exec_fd = -1; + ph->core->interp_fd = -1; + + // open the core file + if ((ph->core->core_fd = open(core_file, O_RDONLY)) < 0) { + print_debug("can't open core file\n"); + goto err; + } + + // read core file ELF header + if (read_elf_header(ph->core->core_fd, &core_ehdr) != true || core_ehdr.e_type != ET_CORE) { + print_debug("core file is not a valid ELF ET_CORE file\n"); + goto err; + } + + if ((ph->core->exec_fd = open(exec_file, O_RDONLY)) < 0) { + print_debug("can't open executable file\n"); + goto err; + } + + if (read_elf_header(ph->core->exec_fd, &exec_ehdr) != true || exec_ehdr.e_type != ET_EXEC) { + print_debug("executable file is not a valid ELF ET_EXEC file\n"); + goto err; + } + + // process core file segments + if (read_core_segments(ph, &core_ehdr) != true) + goto err; + + // process exec file segments + if (read_exec_segments(ph, &exec_ehdr) != true) + goto err; + + // exec file is also treated like a shared object for symbol search + if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd, + (uintptr_t)0 + find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL) + goto err; + + // allocate and sort maps into map_array, we need to do this + // here because read_shared_lib_info needs to read from debuggee + // address space + if (sort_map_array(ph) != true) + goto err; + + if (read_shared_lib_info(ph) != true) + goto err; + + // sort again because we have added more mappings from shared objects + if (sort_map_array(ph) != true) + goto err; + + if (init_classsharing_workaround(ph) != true) + goto err; + + return ph; + +err: + Prelease(ph); + return NULL; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/os/bsd/ps_proc.c Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/ptrace.h> +#include <sys/param.h> +#include <sys/user.h> +#include <elf.h> +#include <sys/elf_common.h> +#include <sys/link_elf.h> +#include <libutil.h> +#include "libproc_impl.h" +#include "elfmacros.h" + +// This file has the libproc implementation specific to live process +// For core files, refer to ps_core.c + +static inline uintptr_t align(uintptr_t ptr, size_t size) { + return (ptr & ~(size - 1)); +} + +// --------------------------------------------- +// ptrace functions +// --------------------------------------------- + +// read "size" bytes of data from "addr" within the target process. +// unlike the standard ptrace() function, process_read_data() can handle +// unaligned address - alignment check, if required, should be done +// before calling process_read_data. + +static bool process_read_data(struct ps_prochandle* ph, uintptr_t addr, char *buf, size_t size) { + int rslt; + size_t i, words; + uintptr_t end_addr = addr + size; + uintptr_t aligned_addr = align(addr, sizeof(int)); + + if (aligned_addr != addr) { + char *ptr = (char *)&rslt; + errno = 0; + rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0); + if (errno) { + print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr); + return false; + } + for (; aligned_addr != addr; aligned_addr++, ptr++); + for (; ((intptr_t)aligned_addr % sizeof(int)) && aligned_addr < end_addr; + aligned_addr++) + *(buf++) = *(ptr++); + } + + words = (end_addr - aligned_addr) / sizeof(int); + + // assert((intptr_t)aligned_addr % sizeof(int) == 0); + for (i = 0; i < words; i++) { + errno = 0; + rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0); + if (errno) { + print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr); + return false; + } + *(int *)buf = rslt; + buf += sizeof(int); + aligned_addr += sizeof(int); + } + + if (aligned_addr != end_addr) { + char *ptr = (char *)&rslt; + errno = 0; + rslt = ptrace(PT_READ_D, ph->pid, (caddr_t) aligned_addr, 0); + if (errno) { + print_debug("ptrace(PT_READ_D, ..) failed for %d bytes @ %lx\n", size, addr); + return false; + } + for (; aligned_addr != end_addr; aligned_addr++) + *(buf++) = *(ptr++); + } + return true; +} + +// null implementation for write +static bool process_write_data(struct ps_prochandle* ph, + uintptr_t addr, const char *buf , size_t size) { + return false; +} + +// "user" should be a pointer to a reg +static bool process_get_lwp_regs(struct ps_prochandle* ph, pid_t pid, struct reg *user) { + // we have already attached to all thread 'pid's, just use ptrace call + // to get regset now. Note that we don't cache regset upfront for processes. + if (ptrace(PT_GETREGS, pid, (caddr_t) user, 0) < 0) { + print_debug("ptrace(PTRACE_GETREGS, ...) failed for lwp %d\n", pid); + return false; + } + return true; +} + +// fill in ptrace_lwpinfo for lid +static bool process_get_lwp_info(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo) { + errno = 0; + ptrace(PT_LWPINFO, lwp_id, linfo, sizeof(struct ptrace_lwpinfo)); + + return (errno == 0)? true: false; +} + +// 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); + } +} + +// ------------------------------------------------------- +// functions for obtaining library information +// ------------------------------------------------------- + +// callback for read_thread_info +static bool add_new_thread(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) { + return add_thread_info(ph, pthread_id, lwp_id) != NULL; +} + +#if defined(__FreeBSD__) && __FreeBSD_version < 701000 +/* + * TEXT_START_ADDR from binutils/ld/emulparams/<arch_spec>.sh + * Not the most robust but good enough. + */ + +#if defined(amd64) || defined(x86_64) +#define TEXT_START_ADDR 0x400000 +#elif defined(i386) +#define TEXT_START_ADDR 0x8048000 +#else +#error TEXT_START_ADDR not defined +#endif + +#define BUF_SIZE (PATH_MAX + NAME_MAX + 1) + +uintptr_t linkmap_addr(struct ps_prochandle *ph) { + uintptr_t ehdr_addr, phdr_addr, dyn_addr, dmap_addr, lmap_addr; + ELF_EHDR ehdr; + ELF_PHDR *phdrs, *phdr; + ELF_DYN *dyns, *dyn; + struct r_debug dmap; + unsigned long hdrs_size; + unsigned int i; + + /* read ELF_EHDR at TEXT_START_ADDR and validate */ + + ehdr_addr = (uintptr_t)TEXT_START_ADDR; + + if (process_read_data(ph, ehdr_addr, (char *)&ehdr, sizeof(ehdr)) != true) { + print_debug("process_read_data failed for ehdr_addr %p\n", ehdr_addr); + return (0); + } + + if (!IS_ELF(ehdr) || + ehdr.e_ident[EI_CLASS] != ELF_TARG_CLASS || + ehdr.e_ident[EI_DATA] != ELF_TARG_DATA || + ehdr.e_ident[EI_VERSION] != EV_CURRENT || + ehdr.e_phentsize != sizeof(ELF_PHDR) || + ehdr.e_version != ELF_TARG_VER || + ehdr.e_machine != ELF_TARG_MACH) { + print_debug("not an ELF_EHDR at %p\n", ehdr_addr); + return (0); + } + + /* allocate space for all ELF_PHDR's and read */ + + phdr_addr = ehdr_addr + ehdr.e_phoff; + hdrs_size = ehdr.e_phnum * sizeof(ELF_PHDR); + + if ((phdrs = malloc(hdrs_size)) == NULL) + return (0); + + if (process_read_data(ph, phdr_addr, (char *)phdrs, hdrs_size) != true) { + print_debug("process_read_data failed for phdr_addr %p\n", phdr_addr); + return (0); + } + + /* find PT_DYNAMIC section */ + + for (i = 0, phdr = phdrs; i < ehdr.e_phnum; i++, phdr++) { + if (phdr->p_type == PT_DYNAMIC) + break; + } + + if (i >= ehdr.e_phnum) { + print_debug("PT_DYNAMIC section not found!\n"); + free(phdrs); + return (0); + } + + /* allocate space and read in ELF_DYN headers */ + + dyn_addr = phdr->p_vaddr; + hdrs_size = phdr->p_memsz; + free(phdrs); + + if ((dyns = malloc(hdrs_size)) == NULL) + return (0); + + if (process_read_data(ph, dyn_addr, (char *)dyns, hdrs_size) != true) { + print_debug("process_read_data failed for dyn_addr %p\n", dyn_addr); + free(dyns); + return (0); + } + + /* find DT_DEBUG */ + + dyn = dyns; + while (dyn->d_tag != DT_DEBUG && dyn->d_tag != DT_NULL) { + dyn++; + } + + if (dyn->d_tag != DT_DEBUG) { + print_debug("failed to find DT_DEBUG\n"); + free(dyns); + return (0); + } + + /* read struct r_debug into dmap */ + + dmap_addr = (uintptr_t)dyn->d_un.d_ptr; + free(dyns); + + if (process_read_data(ph, dmap_addr, (char *)&dmap, sizeof(dmap)) != true) { + print_debug("process_read_data failed for dmap_addr %p\n", dmap_addr); + return (0); + } + + lmap_addr = (uintptr_t)dmap.r_map; + + return (lmap_addr); +} +#endif // __FreeBSD__ && __FreeBSD_version < 701000 + +static bool read_lib_info(struct ps_prochandle* ph) { +#if defined(__FreeBSD__) && __FreeBSD_version >= 701000 + struct kinfo_vmentry *freep, *kve; + int i, cnt; + + freep = kinfo_getvmmap(ph->pid, &cnt); + if (freep == NULL) { + print_debug("can't get vm map for pid\n", ph->pid); + return false; + } + + for (i = 0; i < cnt; i++) { + kve = &freep[i]; + if ((kve->kve_flags & KVME_FLAG_COW) && + kve->kve_path != NULL && + strlen(kve->kve_path) > 0) { + + if (find_lib(ph, kve->kve_path) == false) { + lib_info* lib; + if ((lib = add_lib_info(ph, kve->kve_path, + (uintptr_t) kve->kve_start)) == NULL) + continue; // ignore, add_lib_info prints error + + // we don't need to keep the library open, symtab is already + // built. Only for core dump we need to keep the fd open. + close(lib->fd); + lib->fd = -1; + } + } + } + + free(freep); + + return true; +#else + char *l_name; + struct link_map *lmap; + uintptr_t lmap_addr; + + if ((l_name = malloc(BUF_SIZE)) == NULL) + return false; + + if ((lmap = malloc(sizeof(*lmap))) == NULL) { + free(l_name); + return false; + } + + lmap_addr = linkmap_addr(ph); + + if (lmap_addr == 0) { + free(l_name); + free(lmap); + return false; + } + + do { + if (process_read_data(ph, lmap_addr, (char *)lmap, sizeof(*lmap)) != true) { + print_debug("process_read_data failed for lmap_addr %p\n", lmap_addr); + free (l_name); + free (lmap); + return false; + } + + if (process_read_data(ph, (uintptr_t)lmap->l_name, l_name, + BUF_SIZE) != true) { + print_debug("process_read_data failed for lmap->l_name %p\n", + lmap->l_name); + free (l_name); + free (lmap); + return false; + } + + if (find_lib(ph, l_name) == false) { + lib_info* lib; + if ((lib = add_lib_info(ph, l_name, + (uintptr_t) lmap->l_addr)) == NULL) + continue; // ignore, add_lib_info prints error + + // we don't need to keep the library open, symtab is already + // built. Only for core dump we need to keep the fd open. + close(lib->fd); + lib->fd = -1; + } + lmap_addr = (uintptr_t)lmap->l_next; + } while (lmap->l_next != NULL); + + free (l_name); + free (lmap); + + return true; +#endif +} + +// detach a given pid +static bool ptrace_detach(pid_t pid) { + if (pid && ptrace(PT_DETACH, pid, (caddr_t)1, 0) < 0) { + print_debug("ptrace(PTRACE_DETACH, ..) failed for %d\n", pid); + return false; + } else { + return true; + } +} + +static void process_cleanup(struct ps_prochandle* ph) { + ptrace_detach(ph->pid); +} + +static ps_prochandle_ops process_ops = { + .release= process_cleanup, + .p_pread= process_read_data, + .p_pwrite= process_write_data, + .get_lwp_regs= process_get_lwp_regs, + .get_lwp_info= process_get_lwp_info +}; + +// attach to the process. One and only one exposed stuff +struct ps_prochandle* Pgrab(pid_t pid) { + struct ps_prochandle* ph = NULL; + thread_info* thr = NULL; + + if ( (ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle))) == NULL) { + print_debug("can't allocate memory for ps_prochandle\n"); + return NULL; + } + + if (ptrace_attach(pid) != true) { + free(ph); + return NULL; + } + + // initialize ps_prochandle + ph->pid = pid; + + // initialize vtable + ph->ops = &process_ops; + + // read library info and symbol tables, must do this before attaching threads, + // as the symbols in the pthread library will be used to figure out + // the list of threads within the same process. + if (read_lib_info(ph) != true) { + ptrace_detach(pid); + free(ph); + return NULL; + } + + // read thread info + read_thread_info(ph, add_new_thread); + + return ph; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/os/bsd/salibelf.c Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "salibelf.h" +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +extern void print_debug(const char*,...); + +// ELF file parsing helpers. Note that we do *not* use libelf here. +int read_elf_header(int fd, ELF_EHDR* ehdr) { + if (pread(fd, ehdr, sizeof (ELF_EHDR), 0) != sizeof (ELF_EHDR) || + memcmp(&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0 || + ehdr->e_version != EV_CURRENT) { + return 0; + } + return 1; +} + +bool is_elf_file(int fd) { + ELF_EHDR ehdr; + return read_elf_header(fd, &ehdr); +} + +// read program header table of an ELF file +ELF_PHDR* read_program_header_table(int fd, ELF_EHDR* hdr) { + ELF_PHDR* phbuf = 0; + // allocate memory for program header table + size_t nbytes = hdr->e_phnum * hdr->e_phentsize; + + if ((phbuf = (ELF_PHDR*) malloc(nbytes)) == NULL) { + print_debug("can't allocate memory for reading program header table\n"); + return NULL; + } + + if (pread(fd, phbuf, nbytes, hdr->e_phoff) != nbytes) { + print_debug("ELF file is truncated! can't read program header table\n"); + free(phbuf); + return NULL; + } + + return phbuf; +} + +// read section header table of an ELF file +ELF_SHDR* read_section_header_table(int fd, ELF_EHDR* hdr) { + ELF_SHDR* shbuf = 0; + // allocate memory for section header table + size_t nbytes = hdr->e_shnum * hdr->e_shentsize; + + if ((shbuf = (ELF_SHDR*) malloc(nbytes)) == NULL) { + print_debug("can't allocate memory for reading section header table\n"); + return NULL; + } + + if (pread(fd, shbuf, nbytes, hdr->e_shoff) != nbytes) { + print_debug("ELF file is truncated! can't read section header table\n"); + free(shbuf); + return NULL; + } + + return shbuf; +} + +// read a particular section's data +void* read_section_data(int fd, ELF_EHDR* ehdr, ELF_SHDR* shdr) { + void *buf = NULL; + if (shdr->sh_type == SHT_NOBITS || shdr->sh_size == 0) { + return buf; + } + if ((buf = calloc(shdr->sh_size, 1)) == NULL) { + print_debug("can't allocate memory for reading section data\n"); + return NULL; + } + if (pread(fd, buf, shdr->sh_size, shdr->sh_offset) != shdr->sh_size) { + free(buf); + print_debug("section data read failed\n"); + return NULL; + } + return buf; +} + +uintptr_t find_base_address(int fd, ELF_EHDR* ehdr) { + uintptr_t baseaddr = (uintptr_t)-1; + int cnt; + ELF_PHDR *phbuf, *phdr; + + // read program header table + if ((phbuf = read_program_header_table(fd, ehdr)) == NULL) { + goto quit; + } + + // the base address of a shared object is the lowest vaddr of + // its loadable segments (PT_LOAD) + for (phdr = phbuf, cnt = 0; cnt < ehdr->e_phnum; cnt++, phdr++) { + if (phdr->p_type == PT_LOAD && phdr->p_vaddr < baseaddr) { + baseaddr = phdr->p_vaddr; + } + } + +quit: + if (phbuf) free(phbuf); + return baseaddr; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/os/bsd/salibelf.h Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 _SALIBELF_H_ +#define _SALIBELF_H_ + +#include <elf.h> +#include "elfmacros.h" +#include "libproc_impl.h" + +// read ELF file header. +int read_elf_header(int fd, ELF_EHDR* ehdr); + +// is given file descriptor corresponds to an ELF file? +bool is_elf_file(int fd); + +// read program header table of an ELF file. caller has to +// free the result pointer after use. NULL on failure. +ELF_PHDR* read_program_header_table(int fd, ELF_EHDR* hdr); + +// read section header table of an ELF file. caller has to +// free the result pointer after use. NULL on failure. +ELF_SHDR* read_section_header_table(int fd, ELF_EHDR* hdr); + +// read a particular section's data. caller has to free the +// result pointer after use. NULL on failure. +void* read_section_data(int fd, ELF_EHDR* ehdr, ELF_SHDR* shdr); + +// find the base address at which the library wants to load itself +uintptr_t find_base_address(int fd, ELF_EHDR* ehdr); +#endif /* _SALIBELF_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/os/bsd/symtab.c Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 <unistd.h> +#include <search.h> +#include <stdlib.h> +#include <string.h> +#include <db.h> +#include <fcntl.h> +#include "symtab.h" +#include "salibelf.h" + + +// ---------------------------------------------------- +// functions for symbol lookups +// ---------------------------------------------------- + +struct elf_section { + ELF_SHDR *c_shdr; + void *c_data; +}; + +struct elf_symbol { + char *name; + uintptr_t offset; + uintptr_t size; +}; + +typedef struct symtab { + char *strs; + size_t num_symbols; + struct elf_symbol *symbols; + DB* hash_table; +} symtab_t; + +// read symbol table from given fd. +struct symtab* build_symtab(int fd) { + ELF_EHDR ehdr; + struct symtab* symtab = NULL; + + // Reading of elf header + struct elf_section *scn_cache = NULL; + int cnt = 0; + ELF_SHDR* shbuf = NULL; + ELF_SHDR* cursct = NULL; + ELF_PHDR* phbuf = NULL; + int symtab_found = 0; + int dynsym_found = 0; + uint32_t symsection = SHT_SYMTAB; + + uintptr_t baseaddr = (uintptr_t)-1; + + lseek(fd, (off_t)0L, SEEK_SET); + if (! read_elf_header(fd, &ehdr)) { + // not an elf + return NULL; + } + + // read ELF header + if ((shbuf = read_section_header_table(fd, &ehdr)) == NULL) { + goto quit; + } + + baseaddr = find_base_address(fd, &ehdr); + + scn_cache = calloc(ehdr.e_shnum, sizeof(*scn_cache)); + if (scn_cache == NULL) { + goto quit; + } + + for (cursct = shbuf, cnt = 0; cnt < ehdr.e_shnum; cnt++) { + scn_cache[cnt].c_shdr = cursct; + if (cursct->sh_type == SHT_SYMTAB || + cursct->sh_type == SHT_STRTAB || + cursct->sh_type == SHT_DYNSYM) { + if ( (scn_cache[cnt].c_data = read_section_data(fd, &ehdr, cursct)) == NULL) { + goto quit; + } + } + + if (cursct->sh_type == SHT_SYMTAB) + symtab_found++; + + if (cursct->sh_type == SHT_DYNSYM) + dynsym_found++; + + cursct++; + } + + if (!symtab_found && dynsym_found) + symsection = SHT_DYNSYM; + + for (cnt = 1; cnt < ehdr.e_shnum; cnt++) { + ELF_SHDR *shdr = scn_cache[cnt].c_shdr; + + if (shdr->sh_type == symsection) { + ELF_SYM *syms; + int j, n; + size_t size; + + // FIXME: there could be multiple data buffers associated with the + // same ELF section. Here we can handle only one buffer. See man page + // for elf_getdata on Solaris. + + // guarantee(symtab == NULL, "multiple symtab"); + symtab = calloc(1, sizeof(*symtab)); + if (symtab == NULL) { + goto quit; + } + // the symbol table + syms = (ELF_SYM *)scn_cache[cnt].c_data; + + // number of symbols + n = shdr->sh_size / shdr->sh_entsize; + + // create hash table, we use berkeley db to + // manipulate the hash table. + symtab->hash_table = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL); + // guarantee(symtab->hash_table, "unexpected failure: dbopen"); + if (symtab->hash_table == NULL) + goto bad; + + // shdr->sh_link points to the section that contains the actual strings + // for symbol names. the st_name field in ELF_SYM is just the + // string table index. we make a copy of the string table so the + // strings will not be destroyed by elf_end. + size = scn_cache[shdr->sh_link].c_shdr->sh_size; + symtab->strs = malloc(size); + if (symtab->strs == NULL) + goto bad; + memcpy(symtab->strs, scn_cache[shdr->sh_link].c_data, size); + + // allocate memory for storing symbol offset and size; + symtab->num_symbols = n; + symtab->symbols = calloc(n , sizeof(*symtab->symbols)); + if (symtab->symbols == NULL) + goto bad; + + // copy symbols info our symtab and enter them info the hash table + for (j = 0; j < n; j++, syms++) { + DBT key, value; + char *sym_name = symtab->strs + syms->st_name; + + // skip non-object and non-function symbols + int st_type = ELF_ST_TYPE(syms->st_info); + if ( st_type != STT_FUNC && st_type != STT_OBJECT) + continue; + // skip empty strings and undefined symbols + if (*sym_name == '\0' || syms->st_shndx == SHN_UNDEF) continue; + + symtab->symbols[j].name = sym_name; + symtab->symbols[j].offset = syms->st_value - baseaddr; + symtab->symbols[j].size = syms->st_size; + + key.data = sym_name; + key.size = strlen(sym_name) + 1; + value.data = &(symtab->symbols[j]); + value.size = sizeof(void *); + (*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0); + } + } + } + goto quit; + +bad: + destroy_symtab(symtab); + symtab = NULL; + +quit: + if (shbuf) free(shbuf); + if (phbuf) free(phbuf); + if (scn_cache) { + for (cnt = 0; cnt < ehdr.e_shnum; cnt++) { + if (scn_cache[cnt].c_data != NULL) { + free(scn_cache[cnt].c_data); + } + } + free(scn_cache); + } + return symtab; +} + +void destroy_symtab(struct symtab* symtab) { + if (!symtab) return; + if (symtab->strs) free(symtab->strs); + if (symtab->symbols) free(symtab->symbols); + if (symtab->hash_table) { + (*symtab->hash_table->close)(symtab->hash_table); + } + free(symtab); +} + +uintptr_t search_symbol(struct symtab* symtab, uintptr_t base, + const char *sym_name, int *sym_size) { + DBT key, value; + int ret; + + // library does not have symbol table + if (!symtab || !symtab->hash_table) + return 0; + + key.data = (char*)(uintptr_t)sym_name; + key.size = strlen(sym_name) + 1; + ret = (*symtab->hash_table->get)(symtab->hash_table, &key, &value, 0); + if (ret == 0) { + struct elf_symbol *sym = value.data; + uintptr_t rslt = (uintptr_t) ((char*)base + sym->offset); + if (sym_size) *sym_size = sym->size; + return rslt; + } + + return 0; +} + +const char* nearest_symbol(struct symtab* symtab, uintptr_t offset, + uintptr_t* poffset) { + int n = 0; + if (!symtab) return NULL; + for (; n < symtab->num_symbols; n++) { + struct elf_symbol* sym = &(symtab->symbols[n]); + if (sym->name != NULL && + offset >= sym->offset && offset < sym->offset + sym->size) { + if (poffset) *poffset = (offset - sym->offset); + return sym->name; + } + } + return NULL; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/os/bsd/symtab.h Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 _SYMTAB_H_ +#define _SYMTAB_H_ + +#include <stdint.h> + +// interface to manage ELF symbol tables + +struct symtab; + +// build symbol table for a given ELF file descriptor +struct symtab* build_symtab(int fd); + +// destroy the symbol table +void destroy_symtab(struct symtab* symtab); + +// search for symbol in the given symbol table. Adds offset +// to the base uintptr_t supplied. Returns NULL if not found. +uintptr_t search_symbol(struct symtab* symtab, uintptr_t base, + const char *sym_name, int *sym_size); + +// look for nearest symbol for a given offset (not address - base +// subtraction done by caller +const char* nearest_symbol(struct symtab* symtab, uintptr_t offset, + uintptr_t* poffset); + +#endif /*_SYMTAB_H_*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/os/bsd/test.c Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,59 @@ +/* + * 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include "libproc.h" + +int main(int argc, char** argv) { + struct ps_prochandle* ph; + + init_libproc(true); + switch (argc) { + case 2: { + // process + ph = Pgrab(atoi(argv[1])); + break; + } + + case 3: { + // core + ph = Pgrab_core(argv[1], argv[2]); + break; + } + + default: { + fprintf(stderr, "usage %s <pid> or %s <exec file> <core file>\n", argv[0], argv[0]); + return 1; + } + } + + if (ph) { + Prelease(ph); + return 0; + } else { + printf("can't connect to debuggee\n"); + return 1; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/BsdVtblAccess.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002, 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; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.types.basic.*; + +public class BsdVtblAccess extends BasicVtblAccess { + private String vt; + + public BsdVtblAccess(SymbolLookup symbolLookup, + String[] dllNames) { + super(symbolLookup, dllNames); + + if (symbolLookup.lookup("libjvm.so", "__vt_10JavaThread") != null || + symbolLookup.lookup("libjvm_g.so", "__vt_10JavaThread") != null) { + // old C++ ABI + vt = "__vt_"; + } else { + // new C++ ABI + vt = "_ZTV"; + } + } + + protected String vtblSymbolForType(Type type) { + return vt + type.getName().length() + type; + } +}
--- a/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java Wed Oct 26 12:43:05 2011 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java Thu Oct 27 12:21:43 2011 -0700 @@ -28,6 +28,7 @@ import java.net.*; import java.rmi.*; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.bsd.*; import sun.jvm.hotspot.debugger.proc.*; import sun.jvm.hotspot.debugger.remote.*; import sun.jvm.hotspot.debugger.windbg.*; @@ -335,6 +336,8 @@ 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"); @@ -390,6 +393,10 @@ 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 yet)"); } @@ -477,6 +484,8 @@ setupJVMLibNamesWin32(); } else if (os.equals("linux")) { setupJVMLibNamesLinux(); + } else if (os.equals("bsd")) { + setupJVMLibNamesBsd(); } else { throw new RuntimeException("Unknown OS type"); } @@ -554,6 +563,31 @@ jvmLibNames = new String[] { "libjvm.so", "libjvm_g.so" }; } + // + // BSD + // + + private void setupDebuggerBsd() { + setupJVMLibNamesBsd(); + + if (cpu.equals("x86")) { + machDesc = new MachineDescriptionIntelX86(); + } else if (cpu.equals("amd64")) { + machDesc = new MachineDescriptionAMD64(); + } else { + throw new DebuggerException("BSD only supported on x86/amd64"); + } + + BsdDebuggerLocal dbg = new BsdDebuggerLocal(machDesc, !isServer); + debugger = dbg; + + attachDebugger(); + } + + private void setupJVMLibNamesBsd() { + jvmLibNames = new String[] { "libjvm.so", "libjvm_g.so" }; + } + /** Convenience routine which should be called by per-platform debugger setup. Should not be called when startupMode is REMOTE_MODE. */
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java Wed Oct 26 12:43:05 2011 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java Thu Oct 27 12:21:43 2011 -0700 @@ -29,6 +29,7 @@ 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.*; @@ -514,6 +515,8 @@ 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"); @@ -565,6 +568,9 @@ } 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)"); } @@ -666,6 +672,8 @@ setupJVMLibNamesWin32(); } else if (os.equals("linux")) { setupJVMLibNamesLinux(); + } else if (os.equals("bsd")) { + setupJVMLibNamesBsd(); } else { throw new RuntimeException("Unknown OS type"); } @@ -745,6 +753,34 @@ setupJVMLibNamesSolaris(); } + // + // BSD + // + + private void setupDebuggerBsd() { + setupJVMLibNamesBsd(); + + if (cpu.equals("x86")) { + machDesc = new MachineDescriptionIntelX86(); + } else if (cpu.equals("amd64")) { + machDesc = new MachineDescriptionAMD64(); + } else { + throw new DebuggerException("Bsd only supported on x86/amd64"); + } + + // 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. */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdAddress.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2002, 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.debugger.bsd; + +import sun.jvm.hotspot.debugger.*; + +class BsdAddress implements Address { + protected BsdDebugger debugger; + protected long addr; + + BsdAddress(BsdDebugger debugger, long addr) { + this.debugger = debugger; + this.addr = addr; + } + + // + // Basic Java routines + // + + public boolean equals(Object arg) { + if (arg == null) { + return false; + } + + if (!(arg instanceof BsdAddress)) { + return false; + } + + return (addr == ((BsdAddress) arg).addr); + } + + public int hashCode() { + // FIXME: suggestions on a better hash code? + return (int) addr; + } + + public String toString() { + return debugger.addressValueToString(addr); + } + + // + // C/C++-related routines + // + + public long getCIntegerAt(long offset, long numBytes, boolean isUnsigned) + throws UnalignedAddressException, UnmappedAddressException { + return debugger.readCInteger(addr + offset, numBytes, isUnsigned); + } + + public Address getAddressAt(long offset) + throws UnalignedAddressException, UnmappedAddressException { + return debugger.readAddress(addr + offset); + } + + public Address getCompOopAddressAt(long offset) + throws UnalignedAddressException, UnmappedAddressException { + return debugger.readCompOopAddress(addr + offset); + } + + // + // Java-related routines + // + + public boolean getJBooleanAt(long offset) throws UnalignedAddressException, UnmappedAddressException { + return debugger.readJBoolean(addr + offset); + } + + public byte getJByteAt(long offset) throws UnalignedAddressException, UnmappedAddressException { + return debugger.readJByte(addr + offset); + } + + public char getJCharAt(long offset) throws UnalignedAddressException, UnmappedAddressException { + return debugger.readJChar(addr + offset); + } + + public double getJDoubleAt(long offset) throws UnalignedAddressException, UnmappedAddressException { + return debugger.readJDouble(addr + offset); + } + + public float getJFloatAt(long offset) throws UnalignedAddressException, UnmappedAddressException { + return debugger.readJFloat(addr + offset); + } + + public int getJIntAt(long offset) throws UnalignedAddressException, UnmappedAddressException { + return debugger.readJInt(addr + offset); + } + + public long getJLongAt(long offset) throws UnalignedAddressException, UnmappedAddressException { + return debugger.readJLong(addr + offset); + } + + public short getJShortAt(long offset) throws UnalignedAddressException, UnmappedAddressException { + return debugger.readJShort(addr + offset); + } + + public OopHandle getOopHandleAt(long offset) + throws UnalignedAddressException, UnmappedAddressException, NotInHeapException { + return debugger.readOopHandle(addr + offset); + } + + public OopHandle getCompOopHandleAt(long offset) + throws UnalignedAddressException, UnmappedAddressException, NotInHeapException { + return debugger.readCompOopHandle(addr + offset); + } + + // Mutators -- not implemented for now (FIXME) + public void setCIntegerAt(long offset, long numBytes, long value) { + throw new DebuggerException("Unimplemented"); + } + public void setAddressAt(long offset, Address value) { + throw new DebuggerException("Unimplemented"); + } + public void setJBooleanAt (long offset, boolean value) + throws UnmappedAddressException, UnalignedAddressException { + throw new DebuggerException("Unimplemented"); + } + public void setJByteAt (long offset, byte value) + throws UnmappedAddressException, UnalignedAddressException { + throw new DebuggerException("Unimplemented"); + } + public void setJCharAt (long offset, char value) + throws UnmappedAddressException, UnalignedAddressException { + throw new DebuggerException("Unimplemented"); + } + public void setJDoubleAt (long offset, double value) + throws UnmappedAddressException, UnalignedAddressException { + throw new DebuggerException("Unimplemented"); + } + public void setJFloatAt (long offset, float value) + throws UnmappedAddressException, UnalignedAddressException { + throw new DebuggerException("Unimplemented"); + } + public void setJIntAt (long offset, int value) + throws UnmappedAddressException, UnalignedAddressException { + throw new DebuggerException("Unimplemented"); + } + public void setJLongAt (long offset, long value) + throws UnmappedAddressException, UnalignedAddressException { + throw new DebuggerException("Unimplemented"); + } + public void setJShortAt (long offset, short value) + throws UnmappedAddressException, UnalignedAddressException { + throw new DebuggerException("Unimplemented"); + } + public void setOopHandleAt (long offset, OopHandle value) + throws UnmappedAddressException, UnalignedAddressException { + throw new DebuggerException("Unimplemented"); + } + + // + // Arithmetic operations -- necessary evil. + // + + public Address addOffsetTo (long offset) throws UnsupportedOperationException { + long value = addr + offset; + if (value == 0) { + return null; + } + return new BsdAddress(debugger, value); + } + + public OopHandle addOffsetToAsOopHandle(long offset) throws UnsupportedOperationException { + long value = addr + offset; + if (value == 0) { + return null; + } + return new BsdOopHandle(debugger, value); + } + + /** (FIXME: any signed/unsigned issues? Should this work for + OopHandles?) */ + public long minus(Address arg) { + if (arg == null) { + return addr; + } + return addr - ((BsdAddress) arg).addr; + } + + // Two's complement representation. + // All negative numbers are larger than positive numbers. + // Numbers with the same sign can be compared normally. + // Test harness is below in main(). + + public boolean lessThan (Address a) { + if (a == null) { + return false; + } + BsdAddress arg = (BsdAddress) a; + if ((addr >= 0) && (arg.addr < 0)) { + return true; + } + if ((addr < 0) && (arg.addr >= 0)) { + return false; + } + return (addr < arg.addr); + } + + public boolean lessThanOrEqual (Address a) { + if (a == null) { + return false; + } + BsdAddress arg = (BsdAddress) a; + if ((addr >= 0) && (arg.addr < 0)) { + return true; + } + if ((addr < 0) && (arg.addr >= 0)) { + return false; + } + return (addr <= arg.addr); + } + + public boolean greaterThan (Address a) { + if (a == null) { + return true; + } + BsdAddress arg = (BsdAddress) a; + if ((addr >= 0) && (arg.addr < 0)) { + return false; + } + if ((addr < 0) && (arg.addr >= 0)) { + return true; + } + return (addr > arg.addr); + } + + public boolean greaterThanOrEqual(Address a) { + if (a == null) { + return true; + } + BsdAddress arg = (BsdAddress) a; + if ((addr >= 0) && (arg.addr < 0)) { + return false; + } + if ((addr < 0) && (arg.addr >= 0)) { + return true; + } + return (addr >= arg.addr); + } + + public Address andWithMask(long mask) throws UnsupportedOperationException { + long value = addr & mask; + if (value == 0) { + return null; + } + return new BsdAddress(debugger, value); + } + + public Address orWithMask(long mask) throws UnsupportedOperationException { + long value = addr | mask; + if (value == 0) { + return null; + } + return new BsdAddress(debugger, value); + } + + public Address xorWithMask(long mask) throws UnsupportedOperationException { + long value = addr ^ mask; + if (value == 0) { + return null; + } + return new BsdAddress(debugger, value); + } + + + //-------------------------------------------------------------------------------- + // Internals only below this point + // + + long getValue() { + return addr; + } + + + private static void check(boolean arg, String failMessage) { + if (!arg) { + System.err.println(failMessage + ": FAILED"); + System.exit(1); + } + } + + // Test harness + public static void main(String[] args) { + // p/n indicates whether the interior address is really positive + // or negative. In unsigned terms, p1 < p2 < n1 < n2. + + BsdAddress p1 = new BsdAddress(null, 0x7FFFFFFFFFFFFFF0L); + BsdAddress p2 = (BsdAddress) p1.addOffsetTo(10); + BsdAddress n1 = (BsdAddress) p2.addOffsetTo(10); + BsdAddress n2 = (BsdAddress) n1.addOffsetTo(10); + + // lessThan positive tests + check(p1.lessThan(p2), "lessThan 1"); + check(p1.lessThan(n1), "lessThan 2"); + check(p1.lessThan(n2), "lessThan 3"); + check(p2.lessThan(n1), "lessThan 4"); + check(p2.lessThan(n2), "lessThan 5"); + check(n1.lessThan(n2), "lessThan 6"); + + // lessThan negative tests + check(!p1.lessThan(p1), "lessThan 7"); + check(!p2.lessThan(p2), "lessThan 8"); + check(!n1.lessThan(n1), "lessThan 9"); + check(!n2.lessThan(n2), "lessThan 10"); + + check(!p2.lessThan(p1), "lessThan 11"); + check(!n1.lessThan(p1), "lessThan 12"); + check(!n2.lessThan(p1), "lessThan 13"); + check(!n1.lessThan(p2), "lessThan 14"); + check(!n2.lessThan(p2), "lessThan 15"); + check(!n2.lessThan(n1), "lessThan 16"); + + // lessThanOrEqual positive tests + check(p1.lessThanOrEqual(p1), "lessThanOrEqual 1"); + check(p2.lessThanOrEqual(p2), "lessThanOrEqual 2"); + check(n1.lessThanOrEqual(n1), "lessThanOrEqual 3"); + check(n2.lessThanOrEqual(n2), "lessThanOrEqual 4"); + + check(p1.lessThanOrEqual(p2), "lessThanOrEqual 5"); + check(p1.lessThanOrEqual(n1), "lessThanOrEqual 6"); + check(p1.lessThanOrEqual(n2), "lessThanOrEqual 7"); + check(p2.lessThanOrEqual(n1), "lessThanOrEqual 8"); + check(p2.lessThanOrEqual(n2), "lessThanOrEqual 9"); + check(n1.lessThanOrEqual(n2), "lessThanOrEqual 10"); + + // lessThanOrEqual negative tests + check(!p2.lessThanOrEqual(p1), "lessThanOrEqual 11"); + check(!n1.lessThanOrEqual(p1), "lessThanOrEqual 12"); + check(!n2.lessThanOrEqual(p1), "lessThanOrEqual 13"); + check(!n1.lessThanOrEqual(p2), "lessThanOrEqual 14"); + check(!n2.lessThanOrEqual(p2), "lessThanOrEqual 15"); + check(!n2.lessThanOrEqual(n1), "lessThanOrEqual 16"); + + // greaterThan positive tests + check(n2.greaterThan(p1), "greaterThan 1"); + check(n2.greaterThan(p2), "greaterThan 2"); + check(n2.greaterThan(n1), "greaterThan 3"); + check(n1.greaterThan(p1), "greaterThan 4"); + check(n1.greaterThan(p2), "greaterThan 5"); + check(p2.greaterThan(p1), "greaterThan 6"); + + // greaterThan negative tests + check(!p1.greaterThan(p1), "greaterThan 7"); + check(!p2.greaterThan(p2), "greaterThan 8"); + check(!n1.greaterThan(n1), "greaterThan 9"); + check(!n2.greaterThan(n2), "greaterThan 10"); + + check(!p1.greaterThan(n2), "greaterThan 11"); + check(!p2.greaterThan(n2), "greaterThan 12"); + check(!n1.greaterThan(n2), "greaterThan 13"); + check(!p1.greaterThan(n1), "greaterThan 14"); + check(!p2.greaterThan(n1), "greaterThan 15"); + check(!p1.greaterThan(p2), "greaterThan 16"); + + // greaterThanOrEqual positive tests + check(p1.greaterThanOrEqual(p1), "greaterThanOrEqual 1"); + check(p2.greaterThanOrEqual(p2), "greaterThanOrEqual 2"); + check(n1.greaterThanOrEqual(n1), "greaterThanOrEqual 3"); + check(n2.greaterThanOrEqual(n2), "greaterThanOrEqual 4"); + + check(n2.greaterThanOrEqual(p1), "greaterThanOrEqual 5"); + check(n2.greaterThanOrEqual(p2), "greaterThanOrEqual 6"); + check(n2.greaterThanOrEqual(n1), "greaterThanOrEqual 7"); + check(n1.greaterThanOrEqual(p1), "greaterThanOrEqual 8"); + check(n1.greaterThanOrEqual(p2), "greaterThanOrEqual 9"); + check(p2.greaterThanOrEqual(p1), "greaterThanOrEqual 10"); + + // greaterThanOrEqual negative tests + check(!p1.greaterThanOrEqual(n2), "greaterThanOrEqual 11"); + check(!p2.greaterThanOrEqual(n2), "greaterThanOrEqual 12"); + check(!n1.greaterThanOrEqual(n2), "greaterThanOrEqual 13"); + check(!p1.greaterThanOrEqual(n1), "greaterThanOrEqual 14"); + check(!p2.greaterThanOrEqual(n1), "greaterThanOrEqual 15"); + check(!p1.greaterThanOrEqual(p2), "greaterThanOrEqual 16"); + + System.err.println("BsdAddress: all tests passed successfully."); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdCDebugger.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.debugger.bsd; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.cdbg.*; +import sun.jvm.hotspot.debugger.x86.*; +import sun.jvm.hotspot.debugger.amd64.*; +import sun.jvm.hotspot.debugger.bsd.x86.*; +import sun.jvm.hotspot.debugger.bsd.amd64.*; +import sun.jvm.hotspot.utilities.*; + +class BsdCDebugger implements CDebugger { + private BsdDebugger dbg; + + BsdCDebugger(BsdDebugger dbg) { + this.dbg = dbg; + } + + public List getThreadList() throws DebuggerException { + return dbg.getThreadList(); + } + + public List/*<LoadObject>*/ getLoadObjectList() throws DebuggerException { + return dbg.getLoadObjectList(); + } + + public LoadObject loadObjectContainingPC(Address pc) throws DebuggerException { + if (pc == null) { + return null; + } + List objs = getLoadObjectList(); + Object[] arr = objs.toArray(); + // load objects are sorted by base address, do binary search + int mid = -1; + int low = 0; + int high = arr.length - 1; + + while (low <= high) { + mid = (low + high) >> 1; + LoadObject midVal = (LoadObject) arr[mid]; + long cmp = pc.minus(midVal.getBase()); + if (cmp < 0) { + high = mid - 1; + } else if (cmp > 0) { + long size = midVal.getSize(); + if (cmp >= size) { + low = mid + 1; + } else { + return (LoadObject) arr[mid]; + } + } else { // match found + return (LoadObject) arr[mid]; + } + } + // no match found. + return null; + } + + public CFrame topFrameForThread(ThreadProxy thread) throws DebuggerException { + String cpu = dbg.getCPU(); + if (cpu.equals("x86")) { + X86ThreadContext context = (X86ThreadContext) thread.getContext(); + Address ebp = context.getRegisterAsAddress(X86ThreadContext.EBP); + if (ebp == null) return null; + Address pc = context.getRegisterAsAddress(X86ThreadContext.EIP); + if (pc == null) return null; + return new BsdX86CFrame(dbg, ebp, pc); + } else if (cpu.equals("amd64")) { + AMD64ThreadContext context = (AMD64ThreadContext) thread.getContext(); + Address rbp = context.getRegisterAsAddress(AMD64ThreadContext.RBP); + if (rbp == null) return null; + Address pc = context.getRegisterAsAddress(AMD64ThreadContext.RIP); + if (pc == null) return null; + return new BsdAMD64CFrame(dbg, rbp, pc); + } else { + throw new DebuggerException(cpu + " is not yet supported"); + } + } + + public String getNameOfFile(String fileName) { + return new File(fileName).getName(); + } + + public ProcessControl getProcessControl() throws DebuggerException { + // FIXME: after stabs parser + return null; + } + + public boolean canDemangle() { + return false; + } + + public String demangle(String sym) { + throw new UnsupportedOperationException(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebugger.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2002, 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.debugger.bsd; + +import java.util.List; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.cdbg.*; + +/** An extension of the JVMDebugger interface with a few additions to + support 32-bit vs. 64-bit debugging as well as features required + by the architecture-specific subpackages. */ + +public interface BsdDebugger extends JVMDebugger { + public String addressValueToString(long address) throws DebuggerException; + public boolean readJBoolean(long address) throws DebuggerException; + public byte readJByte(long address) throws DebuggerException; + public char readJChar(long address) throws DebuggerException; + public double readJDouble(long address) throws DebuggerException; + public float readJFloat(long address) throws DebuggerException; + public int readJInt(long address) throws DebuggerException; + public long readJLong(long address) throws DebuggerException; + public short readJShort(long address) throws DebuggerException; + public long readCInteger(long address, long numBytes, boolean isUnsigned) + throws DebuggerException; + public BsdAddress readAddress(long address) throws DebuggerException; + public BsdAddress readCompOopAddress(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 getAddressValue(Address addr) throws DebuggerException; + public Address newAddress(long value) throws DebuggerException; + + // For BsdCDebugger + public List getThreadList(); + public List getLoadObjectList(); + public ClosestSymbol lookup(long address); + + // NOTE: this interface implicitly contains the following methods: + // From the Debugger interface via JVMDebugger + // public void attach(int processID) throws DebuggerException; + // public void attach(String executableName, String coreFileName) throws DebuggerException; + // public boolean detach(); + // public Address parseAddress(String addressString) throws NumberFormatException; + // public String getOS(); + // public String getCPU(); + // From the SymbolLookup interface via Debugger and JVMDebugger + // public Address lookup(String objectName, String symbol); + // public OopHandle lookupOop(String objectName, String symbol); + // From the JVMDebugger interface + // public void configureJavaPrimitiveTypeSizes(long jbooleanSize, + // long jbyteSize, + // long jcharSize, + // long jdoubleSize, + // long jfloatSize, + // long jintSize, + // long jlongSize, + // long jshortSize); + // From the ThreadAccess interface via Debugger and JVMDebugger + // public ThreadProxy getThreadForIdentifierAddress(Address addr); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,597 @@ +/* + * Copyright (c) 2002, 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.debugger.bsd; + +import java.io.*; +import java.net.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.x86.*; +import sun.jvm.hotspot.debugger.cdbg.*; +import sun.jvm.hotspot.utilities.*; +import java.lang.reflect.*; + +/** <P> An implementation of the JVMDebugger interface. The basic debug + facilities are implemented through ptrace interface in the JNI code + (libsaproc.so). Library maps and symbol table management are done in + JNI. </P> + + <P> <B>NOTE</B> that since we have the notion of fetching "Java + primitive types" from the remote process (which might have + different sizes than we expect) we have a bootstrapping + problem. We need to know the sizes of these types before we can + fetch them. The current implementation solves this problem by + requiring that it be configured with these type sizes before they + can be fetched. The readJ(Type) routines here will throw a + RuntimeException if they are called before the debugger is + configured with the Java primitive type sizes. </P> */ + +public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger { + private boolean useGCC32ABI; + private boolean attached; + private long p_ps_prochandle; // native debugger handle + private long symbolicator; // macosx symbolicator handle + private long task; // macosx task handle + private boolean isCore; + + // CDebugger support + private BsdCDebugger cdbg; + + // threadList and loadObjectList are filled by attach0 method + private List threadList; + private List loadObjectList; + + // called by native method lookupByAddress0 + private ClosestSymbol createClosestSymbol(String name, long offset) { + return new ClosestSymbol(name, offset); + } + + // called by native method attach0 + private LoadObject createLoadObject(String fileName, long textsize, + long base) { + File f = new File(fileName); + Address baseAddr = newAddress(base); + return new SharedObject(this, fileName, f.length(), baseAddr); + } + + // native methods + + private native static void init0() + throws DebuggerException; + private native void attach0(int pid) + throws DebuggerException; + private native void attach0(String execName, String coreName) + throws DebuggerException; + private native void detach0() + throws DebuggerException; + private native long lookupByName0(String objectName, String symbol) + throws DebuggerException; + private native ClosestSymbol lookupByAddress0(long address) + throws DebuggerException; + private native long[] getThreadIntegerRegisterSet0(int lwp_id) + throws DebuggerException; + private native byte[] readBytesFromProcess0(long address, long numBytes) + throws DebuggerException; + public native static int getAddressSize() ; + + // Note on Bsd threads are really processes. When target process is + // attached by a serviceability agent thread, only that thread can do + // ptrace operations on the target. This is because from kernel's point + // view, other threads are just separate processes and they are not + // attached to the target. When they attempt to make ptrace calls, + // an ESRCH error will be returned as kernel believes target is not + // being traced by the caller. + // To work around the problem, we use a worker thread here to handle + // all JNI functions that are making ptrace calls. + + interface WorkerThreadTask { + public void doit(BsdDebuggerLocal debugger) throws DebuggerException; + } + + class BsdDebuggerLocalWorkerThread extends Thread { + BsdDebuggerLocal debugger; + WorkerThreadTask task; + DebuggerException lastException; + + public BsdDebuggerLocalWorkerThread(BsdDebuggerLocal debugger) { + this.debugger = debugger; + setDaemon(true); + } + + public void run() { + synchronized (workerThread) { + for (;;) { + if (task != null) { + lastException = null; + try { + task.doit(debugger); + } catch (DebuggerException exp) { + lastException = exp; + } + task = null; + workerThread.notifyAll(); + } + + try { + workerThread.wait(); + } catch (InterruptedException x) {} + } + } + } + + public WorkerThreadTask execute(WorkerThreadTask task) throws DebuggerException { + synchronized (workerThread) { + this.task = task; + workerThread.notifyAll(); + while (this.task != null) { + try { + workerThread.wait(); + } catch (InterruptedException x) {} + } + if (lastException != null) { + throw new DebuggerException(lastException); + } else { + return task; + } + } + } + } + + private BsdDebuggerLocalWorkerThread workerThread = null; + + //---------------------------------------------------------------------- + // Implementation of Debugger interface + // + + /** <P> machDesc may not be null. </P> + + <P> useCache should be set to true if debugging is being done + locally, and to false if the debugger is being created for the + purpose of supporting remote debugging. </P> */ + public BsdDebuggerLocal(MachineDescription machDesc, + boolean useCache) throws DebuggerException { + this.machDesc = machDesc; + utils = new DebuggerUtilities(machDesc.getAddressSize(), + machDesc.isBigEndian()) { + public void checkAlignment(long address, long alignment) { + // Need to override default checkAlignment because we need to + // relax alignment constraints on Bsd/x86 + if ( (address % alignment != 0) + &&(alignment != 8 || address % 4 != 0)) { + throw new UnalignedAddressException( + "Trying to read at address: " + + addressValueToString(address) + + " with alignment: " + alignment, + address); + } + } + }; + + if (useCache) { + // FIXME: re-test necessity of cache on Bsd, where data + // fetching is faster + // Cache portion of the remote process's address space. + // Fetching data over the socket connection to dbx is slow. + // Might be faster if we were using a binary protocol to talk to + // dbx, but would have to test. For now, this cache works best + // if it covers the entire heap of the remote process. FIXME: at + // least should make this tunable from the outside, i.e., via + // the UI. This is a cache of 4096 4K pages, or 16 MB. The page + // size must be adjusted to be the hardware's page size. + // (FIXME: should pick this up from the debugger.) + if (getCPU().equals("ia64")) { + initCache(16384, parseCacheNumPagesProperty(1024)); + } else { + initCache(4096, parseCacheNumPagesProperty(4096)); + } + } + + workerThread = new BsdDebuggerLocalWorkerThread(this); + workerThread.start(); + } + + /** From the Debugger interface via JVMDebugger */ + public boolean hasProcessList() throws DebuggerException { + return false; + } + + /** From the Debugger interface via JVMDebugger */ + public List getProcessList() throws DebuggerException { + throw new DebuggerException("getProcessList not implemented yet"); + } + + private void checkAttached() throws DebuggerException { + if (attached) { + if (isCore) { + throw new DebuggerException("attached to a core dump already"); + } else { + throw new DebuggerException("attached to a process already"); + } + } + } + + private void requireAttach() { + if (! attached) { + throw new RuntimeException("not attached to a process or a core!"); + } + } + + /* called from attach methods */ + private void findABIVersion() throws DebuggerException { + if (lookupByName0("libjvm.so", "__vt_10JavaThread") != 0 || + lookupByName0("libjvm_g.so", "__vt_10JavaThread") != 0) { + // old C++ ABI + useGCC32ABI = false; + } else { + // new C++ ABI + useGCC32ABI = true; + } + } + + /** From the Debugger interface via JVMDebugger */ + public synchronized void attach(int processID) throws DebuggerException { + checkAttached(); + threadList = new ArrayList(); + loadObjectList = new ArrayList(); + class AttachTask implements WorkerThreadTask { + int pid; + public void doit(BsdDebuggerLocal debugger) { + debugger.attach0(pid); + debugger.attached = true; + debugger.isCore = false; + findABIVersion(); + } + } + + AttachTask task = new AttachTask(); + task.pid = processID; + workerThread.execute(task); + } + + /** From the Debugger interface via JVMDebugger */ + public synchronized void attach(String execName, String coreName) { + checkAttached(); + threadList = new ArrayList(); + loadObjectList = new ArrayList(); + attach0(execName, coreName); + attached = true; + isCore = true; + findABIVersion(); + } + + /** From the Debugger interface via JVMDebugger */ + public synchronized boolean detach() { + if (!attached) { + return false; + } + + threadList = null; + loadObjectList = null; + + if (isCore) { + detach0(); + attached = false; + return true; + } else { + class DetachTask implements WorkerThreadTask { + boolean result = false; + + public void doit(BsdDebuggerLocal debugger) { + debugger.detach0(); + debugger.attached = false; + result = true; + } + } + + DetachTask task = new DetachTask(); + workerThread.execute(task); + return task.result; + } + } + + /** From the Debugger interface via JVMDebugger */ + public Address parseAddress(String addressString) + throws NumberFormatException { + long addr = utils.scanAddress(addressString); + if (addr == 0) { + return null; + } + return new BsdAddress(this, addr); + } + + /** From the Debugger interface via JVMDebugger */ + public String getOS() { + return PlatformInfo.getOS(); + } + + /** From the Debugger interface via JVMDebugger */ + public String getCPU() { + return PlatformInfo.getCPU(); + } + + public boolean hasConsole() throws DebuggerException { + return false; + } + + public String consoleExecuteCommand(String cmd) throws DebuggerException { + throw new DebuggerException("No debugger console available on Bsd"); + } + + public String getConsolePrompt() throws DebuggerException { + return null; + } + + /* called from lookup */ + private long handleGCC32ABI(long addr, String symbol) throws DebuggerException { + if (useGCC32ABI && symbol.startsWith("_ZTV")) { + return addr + (2 * machDesc.getAddressSize()); + } else { + return addr; + } + } + + /** From the SymbolLookup interface via Debugger and JVMDebugger */ + public synchronized Address lookup(String objectName, String symbol) { + requireAttach(); + if (!attached) { + return null; + } + + if (isCore) { + long addr = lookupByName0(objectName, symbol); + return (addr == 0)? null : new BsdAddress(this, handleGCC32ABI(addr, symbol)); + } else { + class LookupByNameTask implements WorkerThreadTask { + String objectName, symbol; + Address result; + + public void doit(BsdDebuggerLocal debugger) { + long addr = debugger.lookupByName0(objectName, symbol); + result = (addr == 0 ? null : new BsdAddress(debugger, handleGCC32ABI(addr, symbol))); + } + } + + LookupByNameTask task = new LookupByNameTask(); + task.objectName = objectName; + task.symbol = symbol; + workerThread.execute(task); + return task.result; + } + } + + /** From the SymbolLookup interface via Debugger and JVMDebugger */ + public synchronized OopHandle lookupOop(String objectName, String symbol) { + Address addr = lookup(objectName, symbol); + if (addr == null) { + return null; + } + return addr.addOffsetToAsOopHandle(0); + } + + /** From the Debugger interface */ + public MachineDescription getMachineDescription() { + return machDesc; + } + + //---------------------------------------------------------------------- + // Implementation of ThreadAccess interface + // + + /** From the ThreadAccess interface via Debugger and JVMDebugger */ + public ThreadProxy getThreadForIdentifierAddress(Address addr) { + return new BsdThread(this, addr); + } + + /** From the ThreadAccess interface via Debugger and JVMDebugger */ + public ThreadProxy getThreadForThreadId(long id) { + return new BsdThread(this, id); + } + + //---------------------------------------------------------------------- + // Internal routines (for implementation of BsdAddress). + // These must not be called until the MachineDescription has been set up. + // + + /** From the BsdDebugger interface */ + public String addressValueToString(long address) { + return utils.addressValueToString(address); + } + + /** From the BsdDebugger interface */ + public BsdAddress readAddress(long address) + throws UnmappedAddressException, UnalignedAddressException { + long value = readAddressValue(address); + return (value == 0 ? null : new BsdAddress(this, value)); + } + public BsdAddress readCompOopAddress(long address) + throws UnmappedAddressException, UnalignedAddressException { + long value = readCompOopAddressValue(address); + return (value == 0 ? null : new BsdAddress(this, value)); + } + + /** From the BsdDebugger interface */ + public BsdOopHandle readOopHandle(long address) + throws UnmappedAddressException, UnalignedAddressException, + NotInHeapException { + long value = readAddressValue(address); + return (value == 0 ? null : new BsdOopHandle(this, value)); + } + public BsdOopHandle readCompOopHandle(long address) + throws UnmappedAddressException, UnalignedAddressException, + NotInHeapException { + long value = readCompOopAddressValue(address); + return (value == 0 ? null : new BsdOopHandle(this, value)); + } + + //---------------------------------------------------------------------- + // Thread context access + // + + public synchronized long[] getThreadIntegerRegisterSet(int lwp_id) + throws DebuggerException { + requireAttach(); + if (isCore) { + return getThreadIntegerRegisterSet0(lwp_id); + } else { + class GetThreadIntegerRegisterSetTask implements WorkerThreadTask { + int lwp_id; + long[] result; + public void doit(BsdDebuggerLocal debugger) { + result = debugger.getThreadIntegerRegisterSet0(lwp_id); + } + } + + GetThreadIntegerRegisterSetTask task = new GetThreadIntegerRegisterSetTask(); + task.lwp_id = lwp_id; + workerThread.execute(task); + return task.result; + } + } + + /** Need to override this to relax alignment checks on x86. */ + public long readCInteger(long address, long numBytes, boolean isUnsigned) + throws UnmappedAddressException, UnalignedAddressException { + // Only slightly relaxed semantics -- this is a hack, but is + // necessary on x86 where it seems the compiler is + // putting some global 64-bit data on 32-bit boundaries + if (numBytes == 8) { + utils.checkAlignment(address, 4); + } else { + utils.checkAlignment(address, numBytes); + } + byte[] data = readBytes(address, numBytes); + return utils.dataToCInteger(data, isUnsigned); + } + + // Overridden from DebuggerBase because we need to relax alignment + // constraints on x86 + public long readJLong(long address) + throws UnmappedAddressException, UnalignedAddressException { + utils.checkAlignment(address, jintSize); + byte[] data = readBytes(address, jlongSize); + return utils.dataToJLong(data, jlongSize); + } + + //---------------------------------------------------------------------- + // Address access. Can not be package private, but should only be + // accessed by the architecture-specific subpackages. + + /** From the BsdDebugger interface */ + public long getAddressValue(Address addr) { + if (addr == null) return 0; + return ((BsdAddress) addr).getValue(); + } + + /** From the BsdDebugger interface */ + public Address newAddress(long value) { + if (value == 0) return null; + return new BsdAddress(this, value); + } + + /** From the BsdCDebugger interface */ + public List/*<ThreadProxy>*/ getThreadList() { + requireAttach(); + return threadList; + } + + /** From the BsdCDebugger interface */ + public List/*<LoadObject>*/ getLoadObjectList() { + requireAttach(); + return loadObjectList; + } + + /** From the BsdCDebugger interface */ + public synchronized ClosestSymbol lookup(long addr) { + requireAttach(); + if (isCore) { + return lookupByAddress0(addr); + } else { + class LookupByAddressTask implements WorkerThreadTask { + long addr; + ClosestSymbol result; + + public void doit(BsdDebuggerLocal debugger) { + result = debugger.lookupByAddress0(addr); + } + } + + LookupByAddressTask task = new LookupByAddressTask(); + task.addr = addr; + workerThread.execute(task); + return task.result; + } + } + + public CDebugger getCDebugger() { + if (cdbg == null) { + String cpu = getCPU(); + if (cpu.equals("ia64") ) { + // IA-64 is not supported because of stack-walking issues + return null; + } + cdbg = new BsdCDebugger(this); + } + return cdbg; + } + + /** This reads bytes from the remote process. */ + public synchronized ReadResult readBytesFromProcess(long address, + long numBytes) throws UnmappedAddressException, DebuggerException { + requireAttach(); + if (isCore) { + byte[] res = readBytesFromProcess0(address, numBytes); + return (res != null)? new ReadResult(res) : new ReadResult(address); + } else { + class ReadBytesFromProcessTask implements WorkerThreadTask { + long address, numBytes; + ReadResult result; + public void doit(BsdDebuggerLocal debugger) { + byte[] res = debugger.readBytesFromProcess0(address, numBytes); + if (res != null) + result = new ReadResult(res); + else + result = new ReadResult(address); + } + } + + ReadBytesFromProcessTask task = new ReadBytesFromProcessTask(); + task.address = address; + task.numBytes = numBytes; + workerThread.execute(task); + return task.result; + } + } + + public void writeBytesToProcess(long address, long numBytes, byte[] data) + throws UnmappedAddressException, DebuggerException { + // FIXME + throw new DebuggerException("Unimplemented"); + } + + static { + System.loadLibrary("saproc"); + init0(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdOopHandle.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,61 @@ +/* + * 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.debugger.bsd; + +import sun.jvm.hotspot.debugger.*; + +class BsdOopHandle extends BsdAddress implements OopHandle { + BsdOopHandle(BsdDebugger debugger, long addr) { + super(debugger, addr); + } + + public boolean equals(Object arg) { + if (arg == null) { + return false; + } + + if (!(arg instanceof BsdOopHandle)) { + return false; + } + + return (addr == ((BsdAddress) arg).addr); + } + + public Address addOffsetTo (long offset) throws UnsupportedOperationException { + throw new UnsupportedOperationException("addOffsetTo not applicable to OopHandles (interior object pointers not allowed)"); + } + + public Address andWithMask(long mask) throws UnsupportedOperationException { + throw new UnsupportedOperationException("andWithMask not applicable to OopHandles (i.e., anything but C addresses)"); + } + + public Address orWithMask(long mask) throws UnsupportedOperationException { + throw new UnsupportedOperationException("orWithMask not applicable to OopHandles (i.e., anything but C addresses)"); + } + + public Address xorWithMask(long mask) throws UnsupportedOperationException { + throw new UnsupportedOperationException("xorWithMask not applicable to OopHandles (i.e., anything but C addresses)"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2002, 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.debugger.bsd; + +import sun.jvm.hotspot.debugger.*; + +class BsdThread implements ThreadProxy { + private BsdDebugger debugger; + private int lwp_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) { + 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); + } + + BsdThread(BsdDebugger debugger, long id) { + this.debugger = debugger; + this.lwp_id = (int) id; + } + + public boolean equals(Object obj) { + if ((obj == null) || !(obj instanceof BsdThread)) { + return false; + } + + return (((BsdThread) obj).lwp_id == lwp_id); + } + + public int hashCode() { + return lwp_id; + } + + public String toString() { + return Integer.toString(lwp_id); + } + + public ThreadContext getContext() throws IllegalThreadStateException { + long[] data = debugger.getThreadIntegerRegisterSet(lwp_id); + ThreadContext context = BsdThreadContextFactory.createThreadContext(debugger); + for (int i = 0; i < data.length; i++) { + context.setRegister(i, data[i]); + } + return context; + } + + public boolean canSetContext() throws DebuggerException { + return false; + } + + public void setContext(ThreadContext context) + throws IllegalThreadStateException, DebuggerException { + throw new DebuggerException("Unimplemented"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThreadContextFactory.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.debugger.bsd; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.bsd.amd64.*; +import sun.jvm.hotspot.debugger.bsd.x86.*; + +class BsdThreadContextFactory { + static ThreadContext createThreadContext(BsdDebugger dbg) { + String cpu = dbg.getCPU(); + if (cpu.equals("x86")) { + return new BsdX86ThreadContext(dbg); + } else if (cpu.equals("amd64")) { + return new BsdAMD64ThreadContext(dbg); + } else { + throw new RuntimeException("cpu " + cpu + " is not yet supported"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/SharedObject.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,48 @@ +/* + * 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.debugger.bsd; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.cdbg.*; +import sun.jvm.hotspot.debugger.posix.*; + +/** A Object can represent either a .so or an a.out file. */ + +class SharedObject extends DSO { + SharedObject(BsdDebugger dbg, String filename, long size, Address relocation) { + super(filename, size, relocation); + this.dbg = dbg; + } + + protected Address newAddress(long address) { + return dbg.newAddress(address); + } + + protected long getAddressValue(Address addr) { + return dbg.getAddressValue(addr); + } + + private BsdDebugger dbg; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,75 @@ +/* + * 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.debugger.bsd.amd64; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.bsd.*; +import sun.jvm.hotspot.debugger.cdbg.*; +import sun.jvm.hotspot.debugger.cdbg.basic.*; + +final public class BsdAMD64CFrame extends BasicCFrame { + public BsdAMD64CFrame(BsdDebugger dbg, Address rbp, Address rip) { + super(dbg.getCDebugger()); + this.rbp = rbp; + this.rip = rip; + this.dbg = dbg; + } + + // override base class impl to avoid ELF parsing + public ClosestSymbol closestSymbolToPC() { + // try native lookup in debugger. + return dbg.lookup(dbg.getAddressValue(pc())); + } + + public Address pc() { + return rip; + } + + public Address localVariableBase() { + return rbp; + } + + public CFrame sender() { + if (rbp == null) { + return null; + } + + Address nextRBP = rbp.getAddressAt( 0 * ADDRESS_SIZE); + if (nextRBP == null) { + return null; + } + Address nextPC = rbp.getAddressAt( 1 * ADDRESS_SIZE); + if (nextPC == null) { + return null; + } + return new BsdAMD64CFrame(dbg, nextRBP, nextPC); + } + + // package/class internals only + private static final int ADDRESS_SIZE = 8; + private Address rip; + private Address rbp; + private BsdDebugger dbg; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64ThreadContext.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,46 @@ +/* + * 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.debugger.bsd.amd64; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.amd64.*; +import sun.jvm.hotspot.debugger.bsd.*; + +public class BsdAMD64ThreadContext extends AMD64ThreadContext { + private BsdDebugger debugger; + + public BsdAMD64ThreadContext(BsdDebugger debugger) { + super(); + this.debugger = debugger; + } + + public void setRegisterAsAddress(int index, Address value) { + setRegister(index, debugger.getAddressValue(value)); + } + + public Address getRegisterAsAddress(int index) { + return debugger.newAddress(getRegister(index)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/x86/BsdX86CFrame.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,75 @@ +/* + * 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.debugger.bsd.x86; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.bsd.*; +import sun.jvm.hotspot.debugger.cdbg.*; +import sun.jvm.hotspot.debugger.cdbg.basic.*; + +final public class BsdX86CFrame extends BasicCFrame { + // package/class internals only + public BsdX86CFrame(BsdDebugger dbg, Address ebp, Address pc) { + super(dbg.getCDebugger()); + this.ebp = ebp; + this.pc = pc; + this.dbg = dbg; + } + + // override base class impl to avoid ELF parsing + public ClosestSymbol closestSymbolToPC() { + // try native lookup in debugger. + return dbg.lookup(dbg.getAddressValue(pc())); + } + + public Address pc() { + return pc; + } + + public Address localVariableBase() { + return ebp; + } + + public CFrame sender() { + if (ebp == null) { + return null; + } + + Address nextEBP = ebp.getAddressAt( 0 * ADDRESS_SIZE); + if (nextEBP == null) { + return null; + } + Address nextPC = ebp.getAddressAt( 1 * ADDRESS_SIZE); + if (nextPC == null) { + return null; + } + return new BsdX86CFrame(dbg, nextEBP, nextPC); + } + + private static final int ADDRESS_SIZE = 4; + private Address pc; + private Address ebp; + private BsdDebugger dbg; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/x86/BsdX86ThreadContext.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,46 @@ +/* + * 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.debugger.bsd.x86; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.x86.*; +import sun.jvm.hotspot.debugger.bsd.*; + +public class BsdX86ThreadContext extends X86ThreadContext { + private BsdDebugger debugger; + + public BsdX86ThreadContext(BsdDebugger debugger) { + super(); + this.debugger = debugger; + } + + public void setRegisterAsAddress(int index, Address value) { + setRegister(index, debugger.getAddressValue(value)); + } + + public Address getRegisterAsAddress(int index) { + return debugger.newAddress(getRegister(index)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,116 @@ +/* + * 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 sun.jvm.hotspot.gc_implementation.g1; + +import java.util.Iterator; +import java.util.Observable; +import java.util.Observer; + +import sun.jvm.hotspot.debugger.Address; +import sun.jvm.hotspot.gc_interface.CollectedHeapName; +import sun.jvm.hotspot.memory.MemRegion; +import sun.jvm.hotspot.memory.SharedHeap; +import sun.jvm.hotspot.memory.SpaceClosure; +import sun.jvm.hotspot.runtime.VM; +import sun.jvm.hotspot.runtime.VMObjectFactory; +import sun.jvm.hotspot.types.AddressField; +import sun.jvm.hotspot.types.CIntegerField; +import sun.jvm.hotspot.types.Type; +import sun.jvm.hotspot.types.TypeDataBase; + +// Mirror class for G1CollectedHeap. + +public class G1CollectedHeap extends SharedHeap { + // HeapRegionSeq _seq; + static private long hrsFieldOffset; + // MemRegion _g1_committed; + static private long g1CommittedFieldOffset; + // size_t _summary_bytes_used; + static private CIntegerField summaryBytesUsedField; + // G1MonitoringSupport* _g1mm + static private AddressField g1mmField; + + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + static private synchronized void initialize(TypeDataBase db) { + Type type = db.lookupType("G1CollectedHeap"); + + hrsFieldOffset = type.getField("_hrs").getOffset(); + g1CommittedFieldOffset = type.getField("_g1_committed").getOffset(); + summaryBytesUsedField = type.getCIntegerField("_summary_bytes_used"); + g1mmField = type.getAddressField("_g1mm"); + } + + public long capacity() { + Address g1CommittedAddr = addr.addOffsetTo(g1CommittedFieldOffset); + MemRegion g1_committed = new MemRegion(g1CommittedAddr); + return g1_committed.byteSize(); + } + + public long used() { + return summaryBytesUsedField.getValue(addr); + } + + public long n_regions() { + return hrs().length(); + } + + private HeapRegionSeq hrs() { + Address hrsAddr = addr.addOffsetTo(hrsFieldOffset); + return (HeapRegionSeq) VMObjectFactory.newObject(HeapRegionSeq.class, + hrsAddr); + } + + public G1MonitoringSupport g1mm() { + Address g1mmAddr = g1mmField.getValue(addr); + return (G1MonitoringSupport) VMObjectFactory.newObject(G1MonitoringSupport.class, g1mmAddr); + } + + private Iterator<HeapRegion> heapRegionIterator() { + return hrs().heapRegionIterator(); + } + + public void heapRegionIterate(SpaceClosure scl) { + Iterator<HeapRegion> iter = heapRegionIterator(); + while (iter.hasNext()) { + HeapRegion hr = iter.next(); + scl.doSpace(hr); + } + } + + public CollectedHeapName kind() { + return CollectedHeapName.G1_COLLECTED_HEAP; + } + + public G1CollectedHeap(Address addr) { + super(addr); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1MonitoringSupport.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,99 @@ +/* + * 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 sun.jvm.hotspot.gc_implementation.g1; + +import java.util.Observable; +import java.util.Observer; + +import sun.jvm.hotspot.debugger.Address; +import sun.jvm.hotspot.runtime.VM; +import sun.jvm.hotspot.runtime.VMObject; +import sun.jvm.hotspot.types.CIntegerField; +import sun.jvm.hotspot.types.Type; +import sun.jvm.hotspot.types.TypeDataBase; + +// Mirror class for G1MonitoringSupport. + +public class G1MonitoringSupport extends VMObject { + // size_t _eden_committed; + static private CIntegerField edenCommittedField; + // size_t _eden_used; + static private CIntegerField edenUsedField; + // size_t _survivor_committed; + static private CIntegerField survivorCommittedField; + // size_t _survivor_used; + static private CIntegerField survivorUsedField; + // size_t _old_committed; + static private CIntegerField oldCommittedField; + // size_t _old_used; + static private CIntegerField oldUsedField; + + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + static private synchronized void initialize(TypeDataBase db) { + Type type = db.lookupType("G1MonitoringSupport"); + + edenCommittedField = type.getCIntegerField("_eden_committed"); + edenUsedField = type.getCIntegerField("_eden_used"); + survivorCommittedField = type.getCIntegerField("_survivor_committed"); + survivorUsedField = type.getCIntegerField("_survivor_used"); + oldCommittedField = type.getCIntegerField("_old_committed"); + oldUsedField = type.getCIntegerField("_old_used"); + } + + public long edenCommitted() { + return edenCommittedField.getValue(addr); + } + + public long edenUsed() { + return edenUsedField.getValue(addr); + } + + public long survivorCommitted() { + return survivorCommittedField.getValue(addr); + } + + public long survivorUsed() { + return survivorUsedField.getValue(addr); + } + + public long oldCommitted() { + return oldCommittedField.getValue(addr); + } + + public long oldUsed() { + return oldUsedField.getValue(addr); + } + + public G1MonitoringSupport(Address addr) { + super(addr); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegion.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,66 @@ +/* + * 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 sun.jvm.hotspot.gc_implementation.g1; + +import java.util.Observable; +import java.util.Observer; + +import sun.jvm.hotspot.debugger.Address; +import sun.jvm.hotspot.memory.ContiguousSpace; +import sun.jvm.hotspot.runtime.VM; +import sun.jvm.hotspot.types.CIntegerField; +import sun.jvm.hotspot.types.Type; +import sun.jvm.hotspot.types.TypeDataBase; + +// Mirror class for HeapRegion. Currently we don't actually include +// any of its fields but only iterate over it (which we get "for free" +// as HeapRegion ultimately inherits from ContiguousSpace). + +public class HeapRegion extends ContiguousSpace { + // static int GrainBytes; + static private CIntegerField grainBytesField; + + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + static private synchronized void initialize(TypeDataBase db) { + Type type = db.lookupType("HeapRegion"); + + grainBytesField = type.getCIntegerField("GrainBytes"); + } + + static public long grainBytes() { + return grainBytesField.getValue(); + } + + public HeapRegion(Address addr) { + super(addr); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSeq.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,102 @@ +/* + * 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 sun.jvm.hotspot.gc_implementation.g1; + +import java.util.Iterator; +import java.util.Observable; +import java.util.Observer; + +import sun.jvm.hotspot.debugger.Address; +import sun.jvm.hotspot.runtime.VM; +import sun.jvm.hotspot.runtime.VMObject; +import sun.jvm.hotspot.runtime.VMObjectFactory; +import sun.jvm.hotspot.types.AddressField; +import sun.jvm.hotspot.types.CIntegerField; +import sun.jvm.hotspot.types.Type; +import sun.jvm.hotspot.types.TypeDataBase; + +// Mirror class for HeapRegionSeq. It's essentially an index -> HeapRegion map. + +public class HeapRegionSeq extends VMObject { + // HeapRegion** _regions; + static private AddressField regionsField; + // size_t _length; + static private CIntegerField lengthField; + + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + static private synchronized void initialize(TypeDataBase db) { + Type type = db.lookupType("HeapRegionSeq"); + + regionsField = type.getAddressField("_regions"); + lengthField = type.getCIntegerField("_length"); + } + + private HeapRegion at(long index) { + Address arrayAddr = regionsField.getValue(addr); + // Offset of &_region[index] + long offset = index * VM.getVM().getAddressSize(); + Address regionAddr = arrayAddr.getAddressAt(offset); + return (HeapRegion) VMObjectFactory.newObject(HeapRegion.class, + regionAddr); + } + + public long length() { + return lengthField.getValue(addr); + } + + private class HeapRegionIterator implements Iterator<HeapRegion> { + private long index; + private long length; + + @Override + public boolean hasNext() { return index < length; } + + @Override + public HeapRegion next() { return at(index++); } + + @Override + public void remove() { /* not supported */ } + + HeapRegionIterator(Address addr) { + index = 0; + length = length(); + } + } + + public Iterator<HeapRegion> heapRegionIterator() { + return new HeapRegionIterator(addr); + } + + public HeapRegionSeq(Address addr) { + super(addr); + } +}
--- a/agent/src/share/classes/sun/jvm/hotspot/gc_interface/CollectedHeapName.java Wed Oct 26 12:43:05 2011 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/gc_interface/CollectedHeapName.java Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -34,6 +34,7 @@ public static final CollectedHeapName ABSTRACT = new CollectedHeapName("abstract"); public static final CollectedHeapName SHARED_HEAP = new CollectedHeapName("SharedHeap"); public static final CollectedHeapName GEN_COLLECTED_HEAP = new CollectedHeapName("GenCollectedHeap"); + public static final CollectedHeapName G1_COLLECTED_HEAP = new CollectedHeapName("G1CollectedHeap"); public static final CollectedHeapName PARALLEL_SCAVENGE_HEAP = new CollectedHeapName("ParallelScavengeHeap"); public String toString() {
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/Universe.java Wed Oct 26 12:43:05 2011 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/memory/Universe.java Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -28,6 +28,7 @@ import java.util.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.gc_interface.*; +import sun.jvm.hotspot.gc_implementation.g1.G1CollectedHeap; import sun.jvm.hotspot.gc_implementation.parallelScavenge.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.types.*; @@ -72,6 +73,7 @@ heapConstructor = new VirtualConstructor(db); heapConstructor.addMapping("GenCollectedHeap", GenCollectedHeap.class); heapConstructor.addMapping("ParallelScavengeHeap", ParallelScavengeHeap.class); + heapConstructor.addMapping("G1CollectedHeap", G1CollectedHeap.class); mainThreadGroupField = type.getOopField("_main_thread_group"); systemThreadGroupField = type.getOopField("_system_thread_group");
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Wed Oct 26 12:43:05 2011 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Thu Oct 27 12:21:43 2011 -0700 @@ -44,14 +44,14 @@ } // field offset constants - public static int ACCESS_FLAGS_OFFSET; - public static int NAME_INDEX_OFFSET; - public static int SIGNATURE_INDEX_OFFSET; - public static int INITVAL_INDEX_OFFSET; - public static int LOW_OFFSET; - public static int HIGH_OFFSET; - public static int GENERIC_SIGNATURE_INDEX_OFFSET; - public static int FIELD_SLOTS; + private static int ACCESS_FLAGS_OFFSET; + private static int NAME_INDEX_OFFSET; + private static int SIGNATURE_INDEX_OFFSET; + private static int INITVAL_INDEX_OFFSET; + private static int LOW_OFFSET; + private static int HIGH_OFFSET; + private static int GENERIC_SIGNATURE_INDEX_OFFSET; + private static int FIELD_SLOTS; public static int IMPLEMENTORS_LIMIT; // ClassState constants @@ -122,6 +122,13 @@ InstanceKlass(OopHandle handle, ObjectHeap heap) { super(handle, heap); + if (getJavaFieldsCount() != getAllFieldsCount()) { + // Exercise the injected field logic + for (int i = getJavaFieldsCount(); i < getAllFieldsCount(); i++) { + getFieldName(i); + getFieldSignature(i); + } + } } private static OopField arrayKlasses; @@ -253,24 +260,51 @@ return getFields().getShortAt(index * FIELD_SLOTS + ACCESS_FLAGS_OFFSET); } + public short getFieldNameIndex(int index) { + if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;"); + return getFields().getShortAt(index * FIELD_SLOTS + NAME_INDEX_OFFSET); + } + public Symbol getFieldName(int index) { int nameIndex = getFields().getShortAt(index * FIELD_SLOTS + NAME_INDEX_OFFSET); - return getConstants().getSymbolAt(nameIndex); + if (index < getJavaFieldsCount()) { + return getConstants().getSymbolAt(nameIndex); + } else { + return vmSymbols.symbolAt(nameIndex); + } + } + + public short getFieldSignatureIndex(int index) { + if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;"); + return getFields().getShortAt(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET); } public Symbol getFieldSignature(int index) { int signatureIndex = getFields().getShortAt(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET); - return getConstants().getSymbolAt(signatureIndex); + if (index < getJavaFieldsCount()) { + return getConstants().getSymbolAt(signatureIndex); + } else { + return vmSymbols.symbolAt(signatureIndex); + } + } + + public short getFieldGenericSignatureIndex(int index) { + return getFields().getShortAt(index * FIELD_SLOTS + GENERIC_SIGNATURE_INDEX_OFFSET); } public Symbol getFieldGenericSignature(int index) { - short genericSignatureIndex = getFields().getShortAt(index * FIELD_SLOTS + GENERIC_SIGNATURE_INDEX_OFFSET); + short genericSignatureIndex = getFieldGenericSignatureIndex(index); if (genericSignatureIndex != 0) { return getConstants().getSymbolAt(genericSignatureIndex); } return null; } + public short getFieldInitialValueIndex(int index) { + if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;"); + return getFields().getShortAt(index * FIELD_SLOTS + INITVAL_INDEX_OFFSET); + } + public int getFieldOffset(int index) { TypeArray fields = getFields(); return VM.getVM().buildIntFromShorts(fields.getShortAt(index * FIELD_SLOTS + LOW_OFFSET), @@ -288,7 +322,7 @@ public Klass getImplementor(int i) { return (Klass) implementors[i].getValue(this); } public TypeArray getFields() { return (TypeArray) fields.getValue(this); } public int getJavaFieldsCount() { return (int) javaFieldsCount.getValue(this); } - public int getAllFieldsCount() { return (int)getFields().getLength(); } + public int getAllFieldsCount() { return (int)getFields().getLength() / FIELD_SLOTS; } public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); } public Oop getClassLoader() { return classLoader.getValue(this); } public Oop getProtectionDomain() { return protectionDomain.getValue(this); } @@ -511,7 +545,6 @@ } void iterateStaticFieldsInternal(OopVisitor visitor) { - TypeArray fields = getFields(); int length = getJavaFieldsCount(); for (int index = 0; index < length; index++) { short accessFlags = getFieldAccessFlags(index); @@ -541,8 +574,6 @@ if (getSuper() != null) { ((InstanceKlass) getSuper()).iterateNonStaticFields(visitor, obj); } - TypeArray fields = getFields(); - int length = getJavaFieldsCount(); for (int index = 0; index < length; index++) { short accessFlags = getFieldAccessFlags(index); @@ -556,9 +587,7 @@ /** Field access by name. */ public Field findLocalField(Symbol name, Symbol sig) { - TypeArray fields = getFields(); - int length = (int) fields.getLength(); - ConstantPool cp = getConstants(); + int length = getJavaFieldsCount(); for (int i = 0; i < length; i++) { Symbol f_name = getFieldName(i); Symbol f_sig = getFieldSignature(i); @@ -648,8 +677,6 @@ public List getImmediateFields() { // A list of Fields for each field declared in this class/interface, // not including inherited fields. - TypeArray fields = getFields(); - int length = getJavaFieldsCount(); List immediateFields = new ArrayList(length); for (int index = 0; index < length; index++) { @@ -839,7 +866,6 @@ // Creates new field from index in fields TypeArray private Field newField(int index) { - TypeArray fields = getFields(); FieldType type = new FieldType(getFieldSignature(index)); if (type.isOop()) { if (VM.getVM().isCompressedOopsEnabled()) {
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java Wed Oct 26 12:43:05 2011 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java Thu Oct 27 12:21:43 2011 -0700 @@ -33,6 +33,7 @@ import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.gc_interface.*; +import sun.jvm.hotspot.gc_implementation.g1.*; import sun.jvm.hotspot.gc_implementation.parallelScavenge.*; import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.runtime.*; @@ -514,9 +515,16 @@ private void addPermGenLiveRegions(List output, CollectedHeap heap) { LiveRegionsCollector lrc = new LiveRegionsCollector(output); - if (heap instanceof GenCollectedHeap) { - GenCollectedHeap genHeap = (GenCollectedHeap) heap; - Generation gen = genHeap.permGen(); + if (heap instanceof SharedHeap) { + if (Assert.ASSERTS_ENABLED) { + Assert.that(heap instanceof GenCollectedHeap || + heap instanceof G1CollectedHeap, + "Expecting GenCollectedHeap or G1CollectedHeap, " + + "but got " + heap.getClass().getName()); + } + // Handles both GenCollectedHeap and G1CollectedHeap + SharedHeap sharedHeap = (SharedHeap) heap; + Generation gen = sharedHeap.permGen(); gen.spaceIterate(lrc, true); } else if (heap instanceof ParallelScavengeHeap) { ParallelScavengeHeap psh = (ParallelScavengeHeap) heap; @@ -524,8 +532,9 @@ addLiveRegions(permGen.objectSpace().getLiveRegions(), output); } else { if (Assert.ASSERTS_ENABLED) { - Assert.that(false, "Expecting GenCollectedHeap or ParallelScavengeHeap, but got " + - heap.getClass().getName()); + Assert.that(false, + "Expecting SharedHeap or ParallelScavengeHeap, " + + "but got " + heap.getClass().getName()); } } } @@ -588,10 +597,14 @@ addLiveRegions(youngGen.fromSpace().getLiveRegions(), liveRegions); PSOldGen oldGen = psh.oldGen(); addLiveRegions(oldGen.objectSpace().getLiveRegions(), liveRegions); + } else if (heap instanceof G1CollectedHeap) { + G1CollectedHeap g1h = (G1CollectedHeap) heap; + g1h.heapRegionIterate(lrc); } else { if (Assert.ASSERTS_ENABLED) { - Assert.that(false, "Expecting GenCollectedHeap or ParallelScavengeHeap, but got " + - heap.getClass().getName()); + Assert.that(false, "Expecting GenCollectedHeap, G1CollectedHeap, " + + "or ParallelScavengeHeap, but got " + + heap.getClass().getName()); } }
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java Wed Oct 26 12:43:05 2011 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java Thu Oct 27 12:21:43 2011 -0700 @@ -37,6 +37,8 @@ import sun.jvm.hotspot.runtime.linux_ia64.LinuxIA64JavaThreadPDAccess; import sun.jvm.hotspot.runtime.linux_amd64.LinuxAMD64JavaThreadPDAccess; import sun.jvm.hotspot.runtime.linux_sparc.LinuxSPARCJavaThreadPDAccess; +import sun.jvm.hotspot.runtime.bsd_x86.BsdX86JavaThreadPDAccess; +import sun.jvm.hotspot.runtime.bsd_amd64.BsdAMD64JavaThreadPDAccess; import sun.jvm.hotspot.utilities.*; public class Threads { @@ -90,7 +92,12 @@ } else if (cpu.equals("sparc")) { access = new LinuxSPARCJavaThreadPDAccess(); } - + } else if (os.equals("bsd")) { + if (cpu.equals("x86")) { + access = new BsdX86JavaThreadPDAccess(); + } else if (cpu.equals("amd64")) { + access = new BsdAMD64JavaThreadPDAccess(); + } } if (access == null) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd/BsdSignals.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,70 @@ +/* + * 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.runtime.bsd; + +public class BsdSignals { + private static String[] signalNames = { + "", /* No signal 0 */ + "SIGHUP", /* hangup */ + "SIGINT", /* interrupt */ + "SIGQUIT", /* quit */ + "SIGILL", /* illegal instr. (not reset when caught) */ + "SIGTRAP", /* trace trap (not reset when caught) */ + "SIGABRT", /* abort() */ + "SIGEMT", /* EMT instruction */ + "SIGFPE", /* floating point exception */ + "SIGKILL", /* kill (cannot be caught or ignored) */ + "SIGBUS", /* bus error */ + "SIGSEGV", /* segmentation violation */ + "SIGSYS", /* non-existent system call invoked */ + "SIGPIPE", /* write on a pipe with no one to read it */ + "SIGALRM", /* alarm clock */ + "SIGTERM", /* software termination signal from kill */ + "SIGURG", /* urgent condition on IO channel */ + "SIGSTOP", /* sendable stop signal not from tty */ + "SIGTSTP", /* stop signal from tty */ + "SIGCONT", /* continue a stopped process */ + "SIGCHLD", /* to parent on child stop or exit */ + "SIGTTIN", /* to readers pgrp upon background tty read */ + "SIGTTOU", /* like TTIN if (tp->t_local<OSTOP) */ + "SIGIO", /* input/output possible signal */ + "SIGXCPU", /* exceeded CPU time limit */ + "SIGXFSZ", /* exceeded file size limit */ + "SIGVTALRM", /* virtual time alarm */ + "SIGPROF", /* profiling time alarm */ + "SIGWINCH", /* window size changes */ + "SIGINFO", /* information request */ + "SIGUSR1", /* user defined signal 1 */ + "SIGUSR2" /* user defined signal 2 */ + }; + + public static String getSignalName(int sigNum) { + if ((sigNum <= 0) || (sigNum >= signalNames.length)) { + // Probably best to fail in a non-destructive way + return "<Error: Illegal signal number " + sigNum + ">"; + } + return signalNames[sigNum]; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_amd64/BsdAMD64JavaThreadPDAccess.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,132 @@ +/* + * 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.runtime.bsd_amd64; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.amd64.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.runtime.amd64.*; +import sun.jvm.hotspot.runtime.x86.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; + +public class BsdAMD64JavaThreadPDAccess implements JavaThreadPDAccess { + private static AddressField lastJavaFPField; + private static AddressField osThreadField; + + // Field from OSThread + private static CIntegerField osThreadThreadIDField; + + // This is currently unneeded but is being kept in case we change + // the currentFrameGuess algorithm + private static final long GUESS_SCAN_RANGE = 128 * 1024; + + 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("JavaThread"); + osThreadField = type.getAddressField("_osthread"); + + Type anchorType = db.lookupType("JavaFrameAnchor"); + lastJavaFPField = anchorType.getAddressField("_last_Java_fp"); + + Type osThreadType = db.lookupType("OSThread"); + osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id"); + } + + public Address getLastJavaFP(Address addr) { + return lastJavaFPField.getValue(addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset())); + } + + public Address getLastJavaPC(Address addr) { + return null; + } + + public Address getBaseOfStackPointer(Address addr) { + return null; + } + + public Frame getLastFramePD(JavaThread thread, Address addr) { + Address fp = thread.getLastJavaFP(); + if (fp == null) { + return null; // no information + } + return new X86Frame(thread.getLastJavaSP(), fp); + } + + public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) { + return new X86RegisterMap(thread, updateMap); + } + + public Frame getCurrentFrameGuess(JavaThread thread, Address addr) { + ThreadProxy t = getThreadProxy(addr); + AMD64ThreadContext context = (AMD64ThreadContext) t.getContext(); + AMD64CurrentFrameGuess guesser = new AMD64CurrentFrameGuess(context, thread); + if (!guesser.run(GUESS_SCAN_RANGE)) { + return null; + } + if (guesser.getPC() == null) { + return new X86Frame(guesser.getSP(), guesser.getFP()); + } else { + return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC()); + } + } + + public void printThreadIDOn(Address addr, PrintStream tty) { + tty.print(getThreadProxy(addr)); + } + + public void printInfoOn(Address threadAddr, PrintStream tty) { + tty.print("Thread id: "); + printThreadIDOn(threadAddr, tty); +// tty.println("\nPostJavaState: " + getPostJavaState(threadAddr)); + } + + public Address getLastSP(Address addr) { + ThreadProxy t = getThreadProxy(addr); + AMD64ThreadContext context = (AMD64ThreadContext) t.getContext(); + return context.getRegisterAsAddress(AMD64ThreadContext.RSP); + } + + public ThreadProxy getThreadProxy(Address addr) { + // Addr is the address of the JavaThread. + // 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 _thread_id from the OSThread + Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset()); + + JVMDebugger debugger = VM.getVM().getDebugger(); + return debugger.getThreadForIdentifierAddress(threadIdAddr); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_x86/BsdSignals.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,70 @@ +/* + * 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.runtime.bsd_x86; + +public class BsdSignals { + private static String[] signalNames = { + "", /* No signal 0 */ + "SIGHUP", /* hangup */ + "SIGINT", /* interrupt */ + "SIGQUIT", /* quit */ + "SIGILL", /* illegal instr. (not reset when caught) */ + "SIGTRAP", /* trace trap (not reset when caught) */ + "SIGABRT", /* abort() */ + "SIGEMT", /* EMT instruction */ + "SIGFPE", /* floating point exception */ + "SIGKILL", /* kill (cannot be caught or ignored) */ + "SIGBUS", /* bus error */ + "SIGSEGV", /* segmentation violation */ + "SIGSYS", /* non-existent system call invoked */ + "SIGPIPE", /* write on a pipe with no one to read it */ + "SIGALRM", /* alarm clock */ + "SIGTERM", /* software termination signal from kill */ + "SIGURG", /* urgent condition on IO channel */ + "SIGSTOP", /* sendable stop signal not from tty */ + "SIGTSTP", /* stop signal from tty */ + "SIGCONT", /* continue a stopped process */ + "SIGCHLD", /* to parent on child stop or exit */ + "SIGTTIN", /* to readers pgrp upon background tty read */ + "SIGTTOU", /* like TTIN if (tp->t_local<OSTOP) */ + "SIGIO", /* input/output possible signal */ + "SIGXCPU", /* exceeded CPU time limit */ + "SIGXFSZ", /* exceeded file size limit */ + "SIGVTALRM", /* virtual time alarm */ + "SIGPROF", /* profiling time alarm */ + "SIGWINCH", /* window size changes */ + "SIGINFO", /* information request */ + "SIGUSR1", /* user defined signal 1 */ + "SIGUSR2" /* user defined signal 2 */ + }; + + public static String getSignalName(int sigNum) { + if ((sigNum <= 0) || (sigNum >= signalNames.length)) { + // Probably best to fail in a non-destructive way + return "<Error: Illegal signal number " + sigNum + ">"; + } + return signalNames[sigNum]; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_x86/BsdX86JavaThreadPDAccess.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2002, 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.runtime.bsd_x86; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.x86.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.runtime.x86.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; + +public class BsdX86JavaThreadPDAccess implements JavaThreadPDAccess { + private static AddressField lastJavaFPField; + private static AddressField osThreadField; + + // Field from OSThread + private static CIntegerField osThreadThreadIDField; + + // This is currently unneeded but is being kept in case we change + // the currentFrameGuess algorithm + private static final long GUESS_SCAN_RANGE = 128 * 1024; + + 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("JavaThread"); + osThreadField = type.getAddressField("_osthread"); + + Type anchorType = db.lookupType("JavaFrameAnchor"); + lastJavaFPField = anchorType.getAddressField("_last_Java_fp"); + + Type osThreadType = db.lookupType("OSThread"); + osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id"); + } + + public Address getLastJavaFP(Address addr) { + return lastJavaFPField.getValue(addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset())); + } + + public Address getLastJavaPC(Address addr) { + return null; + } + + public Address getBaseOfStackPointer(Address addr) { + return null; + } + + public Frame getLastFramePD(JavaThread thread, Address addr) { + Address fp = thread.getLastJavaFP(); + if (fp == null) { + return null; // no information + } + return new X86Frame(thread.getLastJavaSP(), fp); + } + + public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) { + return new X86RegisterMap(thread, updateMap); + } + + public Frame getCurrentFrameGuess(JavaThread thread, Address addr) { + ThreadProxy t = getThreadProxy(addr); + X86ThreadContext context = (X86ThreadContext) t.getContext(); + X86CurrentFrameGuess guesser = new X86CurrentFrameGuess(context, thread); + if (!guesser.run(GUESS_SCAN_RANGE)) { + return null; + } + if (guesser.getPC() == null) { + return new X86Frame(guesser.getSP(), guesser.getFP()); + } else { + return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC()); + } + } + + public void printThreadIDOn(Address addr, PrintStream tty) { + tty.print(getThreadProxy(addr)); + } + + public void printInfoOn(Address threadAddr, PrintStream tty) { + tty.print("Thread id: "); + printThreadIDOn(threadAddr, tty); +// tty.println("\nPostJavaState: " + getPostJavaState(threadAddr)); + } + + public Address getLastSP(Address addr) { + ThreadProxy t = getThreadProxy(addr); + X86ThreadContext context = (X86ThreadContext) t.getContext(); + return context.getRegisterAsAddress(X86ThreadContext.ESP); + } + + public ThreadProxy getThreadProxy(Address addr) { + // Addr is the address of the JavaThread. + // 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 _thread_id from the OSThread + Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset()); + + JVMDebugger debugger = VM.getVM().getDebugger(); + return debugger.getThreadForIdentifierAddress(threadIdAddr); + } +}
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java Wed Oct 26 12:43:05 2011 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java Thu Oct 27 12:21:43 2011 -0700 @@ -956,7 +956,7 @@ map.makeIntegerRegsUnsaved(); map.shiftWindow(sp, youngerSP); boolean thisFrameAdjustedStack = true; // I5_savedSP is live in this RF - return new SPARCFrame(sp, youngerSP, thisFrameAdjustedStack); + return new SPARCFrame(biasSP(sp), biasSP(youngerSP), thisFrameAdjustedStack); } private Frame senderForEntryFrame(RegisterMap regMap) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/vmSymbols.java Thu Oct 27 12:21:43 2011 -0700 @@ -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 sun.jvm.hotspot.runtime; + +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.types.*; +import sun.jvm.hotspot.utilities.*; + + +public class vmSymbols { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static Address symbolsAddress; + private static int FIRST_SID; + private static int SID_LIMIT; + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("vmSymbols"); + symbolsAddress = type.getAddressField("_symbols[0]").getStaticFieldAddress(); + FIRST_SID = db.lookupIntConstant("vmSymbols::FIRST_SID"); + SID_LIMIT = db.lookupIntConstant("vmSymbols::SID_LIMIT"); + } + + public static Symbol symbolAt(int id) { + if (id < FIRST_SID || id >= SID_LIMIT) throw new IndexOutOfBoundsException("bad SID " + id); + return Symbol.create(symbolsAddress.getAddressAt(id * VM.getVM().getAddressSize())); + } +}
--- a/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java Wed Oct 26 12:43:05 2011 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -26,11 +26,11 @@ import java.util.*; import sun.jvm.hotspot.gc_interface.*; +import sun.jvm.hotspot.gc_implementation.g1.*; import sun.jvm.hotspot.gc_implementation.parallelScavenge.*; import sun.jvm.hotspot.gc_implementation.shared.*; import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.tools.*; public class HeapSummary extends Tool { @@ -70,32 +70,45 @@ System.out.println(); System.out.println("Heap Usage:"); - if (heap instanceof GenCollectedHeap) { - GenCollectedHeap genHeap = (GenCollectedHeap) heap; - for (int n = 0; n < genHeap.nGens(); n++) { - Generation gen = genHeap.getGen(n); - if (gen instanceof sun.jvm.hotspot.memory.DefNewGeneration) { - System.out.println("New Generation (Eden + 1 Survivor Space):"); - printGen(gen); + if (heap instanceof SharedHeap) { + SharedHeap sharedHeap = (SharedHeap) heap; + if (sharedHeap instanceof GenCollectedHeap) { + GenCollectedHeap genHeap = (GenCollectedHeap) sharedHeap; + for (int n = 0; n < genHeap.nGens(); n++) { + Generation gen = genHeap.getGen(n); + if (gen instanceof sun.jvm.hotspot.memory.DefNewGeneration) { + System.out.println("New Generation (Eden + 1 Survivor Space):"); + printGen(gen); - ContiguousSpace eden = ((DefNewGeneration)gen).eden(); - System.out.println("Eden Space:"); - printSpace(eden); + ContiguousSpace eden = ((DefNewGeneration)gen).eden(); + System.out.println("Eden Space:"); + printSpace(eden); + + ContiguousSpace from = ((DefNewGeneration)gen).from(); + System.out.println("From Space:"); + printSpace(from); - ContiguousSpace from = ((DefNewGeneration)gen).from(); - System.out.println("From Space:"); - printSpace(from); - - ContiguousSpace to = ((DefNewGeneration)gen).to(); - System.out.println("To Space:"); - printSpace(to); - } else { - System.out.println(gen.name() + ":"); - printGen(gen); + ContiguousSpace to = ((DefNewGeneration)gen).to(); + System.out.println("To Space:"); + printSpace(to); + } else { + System.out.println(gen.name() + ":"); + printGen(gen); + } } + } else if (sharedHeap instanceof G1CollectedHeap) { + G1CollectedHeap g1h = (G1CollectedHeap) sharedHeap; + G1MonitoringSupport g1mm = g1h.g1mm(); + System.out.println("G1 Young Generation"); + printG1Space("Eden Space:", g1mm.edenUsed(), g1mm.edenCommitted()); + printG1Space("From Space:", g1mm.survivorUsed(), g1mm.survivorCommitted()); + printG1Space("To Space:", 0, 0); + printG1Space("G1 Old Generation", g1mm.oldUsed(), g1mm.oldCommitted()); + } else { + throw new RuntimeException("unknown SharedHeap type : " + heap.getClass()); } - // Perm generation - Generation permGen = genHeap.permGen(); + // Perm generation shared by the above + Generation permGen = sharedHeap.permGen(); System.out.println("Perm Generation:"); printGen(permGen); } else if (heap instanceof ParallelScavengeHeap) { @@ -119,7 +132,7 @@ printValMB("free = ", permFree); System.out.println(alignment + (double)permGen.used() * 100.0 / permGen.capacity() + "% used"); } else { - throw new RuntimeException("unknown heap type : " + heap.getClass()); + throw new RuntimeException("unknown CollectedHeap type : " + heap.getClass()); } } @@ -151,6 +164,14 @@ return; } + l = getFlagValue("UseG1GC", flagMap); + if (l == 1L) { + System.out.print("Garbage-First (G1) GC "); + l = getFlagValue("ParallelGCThreads", flagMap); + System.out.println("with " + l + " thread(s)"); + return; + } + System.out.println("Mark Sweep Compact GC"); } @@ -191,6 +212,16 @@ System.out.println(alignment + (double)space.used() * 100.0 / space.capacity() + "% used"); } + private void printG1Space(String spaceName, long used, long capacity) { + long free = capacity - used; + System.out.println(spaceName); + printValMB("capacity = ", capacity); + printValMB("used = ", used); + printValMB("free = ", free); + double occPerc = (capacity > 0) ? (double) used * 100.0 / capacity : 0.0; + System.out.println(alignment + occPerc + "% used"); + } + private static final double FACTOR = 1024*1024; private void printValMB(String title, long value) { if (value < 0) {
--- a/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java Wed Oct 26 12:43:05 2011 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java Thu Oct 27 12:21:43 2011 -0700 @@ -379,23 +379,21 @@ } protected void writeFields() throws IOException { - TypeArray fields = klass.getFields(); final int length = klass.getJavaFieldsCount(); // write number of fields - dos.writeShort((short) (length / InstanceKlass.FIELD_SLOTS) ); + dos.writeShort((short) length); - if (DEBUG) debugMessage("number of fields = " - + length/InstanceKlass.FIELD_SLOTS); + if (DEBUG) debugMessage("number of fields = " + length); - for (int index = 0; index < length; index += InstanceKlass.FIELD_SLOTS) { - short accessFlags = fields.getShortAt(index + InstanceKlass.ACCESS_FLAGS_OFFSET); + for (int index = 0; index < length; index++) { + short accessFlags = klass.getFieldAccessFlags(index); dos.writeShort(accessFlags & (short) JVM_RECOGNIZED_FIELD_MODIFIERS); - short nameIndex = fields.getShortAt(index + InstanceKlass.NAME_INDEX_OFFSET); + short nameIndex = klass.getFieldNameIndex(index); dos.writeShort(nameIndex); - short signatureIndex = fields.getShortAt(index + InstanceKlass.SIGNATURE_INDEX_OFFSET); + short signatureIndex = klass.getFieldSignatureIndex(index); dos.writeShort(signatureIndex); if (DEBUG) debugMessage("\tfield name = " + nameIndex + ", signature = " + signatureIndex); @@ -404,11 +402,11 @@ if (hasSyn) fieldAttributeCount++; - short initvalIndex = fields.getShortAt(index + InstanceKlass.INITVAL_INDEX_OFFSET); + short initvalIndex = klass.getFieldInitialValueIndex(index); if (initvalIndex != 0) fieldAttributeCount++; - short genSigIndex = fields.getShortAt(index + InstanceKlass.GENERIC_SIGNATURE_INDEX_OFFSET); + short genSigIndex = klass.getFieldGenericSignatureIndex(index); if (genSigIndex != 0) fieldAttributeCount++;
--- a/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java Wed Oct 26 12:43:05 2011 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java Thu Oct 27 12:21:43 2011 -0700 @@ -37,6 +37,14 @@ return "solaris"; } else if (os.equals("Linux")) { return "linux"; + } else if (os.equals("FreeBSD")) { + return "bsd"; + } else if (os.equals("NetBSD")) { + return "bsd"; + } else if (os.equals("OpenBSD")) { + return "bsd"; + } else if (os.equals("Darwin") || os.startsWith("Mac OS X")) { + return "bsd"; } else if (os.startsWith("Windows")) { return "win32"; } else {
--- a/make/Makefile Wed Oct 26 12:43:05 2011 -0700 +++ b/make/Makefile Thu Oct 27 12:21:43 2011 -0700 @@ -323,28 +323,42 @@ ifneq ($(OSNAME),windows) ifeq ($(ZERO_BUILD), true) ifeq ($(SHARK_BUILD), true) -$(EXPORT_JRE_LIB_ARCH_DIR)/%.so: $(SHARK_DIR)/%.so +$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_SERVER_DIR)/%.so: $(SHARK_DIR)/%.so +$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) else -$(EXPORT_JRE_LIB_ARCH_DIR)/%.so: $(ZERO_DIR)/%.so +$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_SERVER_DIR)/%.so: $(ZERO_DIR)/%.so +$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) endif else -$(EXPORT_JRE_LIB_ARCH_DIR)/%.so: $(C1_DIR)/%.so +$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX) + $(install-file) +$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX) + $(install-file) +$(EXPORT_CLIENT_DIR)/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_JRE_LIB_ARCH_DIR)/%.so: $(C2_DIR)/%.so +$(EXPORT_CLIENT_DIR)/64/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_CLIENT_DIR)/%.so: $(C1_DIR)/%.so +$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX) + $(install-file) +$(EXPORT_SERVER_DIR)/64/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) -$(EXPORT_CLIENT_DIR)/64/%.so: $(C1_DIR)/%.so + +# Debug info for shared library +$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C1_DIR)/%.debuginfo + $(install-file) +$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C2_DIR)/%.debuginfo $(install-file) -$(EXPORT_SERVER_DIR)/%.so: $(C2_DIR)/%.so +$(EXPORT_CLIENT_DIR)/%.debuginfo: $(C1_DIR)/%.debuginfo + $(install-file) +$(EXPORT_CLIENT_DIR)/64/%.debuginfo: $(C1_DIR)/%.debuginfo $(install-file) -$(EXPORT_SERVER_DIR)/64/%.so: $(C2_DIR)/%.so +$(EXPORT_SERVER_DIR)/%.debuginfo: $(C2_DIR)/%.debuginfo + $(install-file) +$(EXPORT_SERVER_DIR)/64/%.debuginfo: $(C2_DIR)/%.debuginfo $(install-file) endif endif @@ -457,6 +471,36 @@ ($(CD) $(JDK_IMAGE_DIR)/debug && $(TAR) -xf -) ; \ fi +# macosx universal builds + +ifeq ($(MACOSX_UNIVERSAL), true) +$(UNIVERSAL_LIPO_LIST): + lipo -create -output $@ $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) + +$(UNIVERSAL_COPY_LIST): + $(CP) $(EXPORT_JRE_LIB_DIR)/i386/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) $@ + +universalize: $(UNIVERSAL_LIPO_LIST) $(UNIVERSAL_COPY_LIST) +endif + +universal_product: + $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 MACOSX_UNIVERSAL=true all_product + $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 MACOSX_UNIVERSAL=true all_product + $(MKDIR) -p $(EXPORT_JRE_LIB_DIR)/{client,server} + $(QUIETLY) $(MAKE) MACOSX_UNIVERSAL=true universalize + +universal_fastdebug: + $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 MACOSX_UNIVERSAL=true all_fastdebug + $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 MACOSX_UNIVERSAL=true all_fastdebug + $(MKDIR) -p $(EXPORT_JRE_LIB_DIR)/{client,server} + $(QUIETLY) $(MAKE) MACOSX_UNIVERSAL=true universalize + +universal_debug: + $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 MACOSX_UNIVERSAL=true all_debug + $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 MACOSX_UNIVERSAL=true all_debug + $(MKDIR) -p $(EXPORT_JRE_LIB_DIR)/{client,server} + $(QUIETLY) $(MAKE) MACOSX_UNIVERSAL=true universalize + # # Check target # @@ -585,5 +629,6 @@ 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 \ - copy_product_jdk copy_fastdebug_jdk copy_debug_jdk + copy_product_jdk copy_fastdebug_jdk copy_debug_jdk universalize \ + universal_product
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/Makefile Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,371 @@ +# +# Copyright (c) 1999, 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. +# +# + +# This makefile creates a build tree and lights off a build. +# You can go back into the build tree and perform rebuilds or +# incremental builds as desired. Be sure to reestablish +# environment variable settings for LD_LIBRARY_PATH and JAVA_HOME. + +# The make process now relies on java and javac. These can be +# specified either implicitly on the PATH, by setting the +# (JDK-inherited) ALT_BOOTDIR environment variable to full path to a +# JDK in which bin/java and bin/javac are present and working (e.g., +# /usr/local/java/jdk1.3/solaris), or via the (JDK-inherited) +# default BOOTDIR path value. Note that one of ALT_BOOTDIR +# or BOOTDIR has to be set. We do *not* search javac, javah, rmic etc. +# from the PATH. +# +# One can set ALT_BOOTDIR or BOOTDIR to point to a jdk that runs on +# an architecture that differs from the target architecture, as long +# as the bootstrap jdk runs under the same flavor of OS as the target +# (i.e., if the target is linux, point to a jdk that runs on a linux +# box). In order to use such a bootstrap jdk, set the make variable +# REMOTE to the desired remote command mechanism, e.g., +# +# make REMOTE="rsh -l me myotherlinuxbox" + +# Along with VM, Serviceability Agent (SA) is built for SA/JDI binding. +# JDI binding on SA produces two binaries: +# 1. sa-jdi.jar - This is build before building libjvm[_g].so +# Please refer to ./makefiles/sa.make +# 2. libsa[_g].so - Native library for SA - This is built after +# libjsig[_g].so (signal interposition library) +# Please refer to ./makefiles/vm.make +# If $(GAMMADIR)/agent dir is not present, SA components are not built. + +ifeq ($(GAMMADIR),) +include ../../make/defs.make +else +include $(GAMMADIR)/make/defs.make +endif +include $(GAMMADIR)/make/$(OSNAME)/makefiles/rules.make + +ifndef CC_INTERP + ifndef FORCE_TIERED + FORCE_TIERED=1 + endif +endif + +ifdef LP64 + ifeq ("$(filter $(LP64_ARCH),$(BUILDARCH))","") + _JUNK_ := $(shell echo >&2 \ + $(OSNAME) $(ARCH) "*** ERROR: this platform does not support 64-bit compilers!") + @exit 1 + endif +endif + +# we need to set up LP64 correctly to satisfy sanity checks in adlc +ifneq ("$(filter $(LP64_ARCH),$(BUILDARCH))","") + MFLAGS += " LP64=1 " +endif + +# pass USE_SUNCC further, through MFLAGS +ifdef USE_SUNCC + MFLAGS += " USE_SUNCC=1 " +endif + +# The following renders pathnames in generated Makefiles valid on +# machines other than the machine containing the build tree. +# +# For example, let's say my build tree lives on /files12 on +# exact.east.sun.com. This logic will cause GAMMADIR to begin with +# /net/exact/files12/... +# +# We only do this on SunOS variants, for a couple of reasons: +# * It is extremely rare that source trees exist on other systems +# * It has been claimed that the Linux automounter is flakey, so +# changing GAMMADIR in a way that exercises the automounter could +# prove to be a source of unreliability in the build process. +# Obviously, this Makefile is only relevant on SunOS boxes to begin +# with, but the SunOS conditionalization will make it easier to +# combine Makefiles in the future (assuming we ever do that). + +ifeq ($(OSNAME),solaris) + + # prepend current directory to relative pathnames. + NEW_GAMMADIR := \ + $(shell echo $(GAMMADIR) | \ + sed -e "s=^\([^/].*\)=$(shell pwd)/\1=" \ + ) + unexport NEW_GAMMADIR + + # If NEW_GAMMADIR doesn't already start with "/net/": + ifeq ($(strip $(filter /net/%,$(NEW_GAMMADIR))),) + # prepend /net/$(HOST) + # remove /net/$(HOST) if name already began with /home/ + # remove /net/$(HOST) if name already began with /java/ + # remove /net/$(HOST) if name already began with /lab/ + NEW_GAMMADIR := \ + $(shell echo $(NEW_GAMMADIR) | \ + sed -e "s=^\(.*\)=/net/$(HOST)\1=" \ + -e "s=^/net/$(HOST)/home/=/home/=" \ + -e "s=^/net/$(HOST)/java/=/java/=" \ + -e "s=^/net/$(HOST)/lab/=/lab/=" \ + ) + # Don't use the new value for GAMMADIR unless a file with the new + # name actually exists. + ifneq ($(wildcard $(NEW_GAMMADIR)),) + GAMMADIR := $(NEW_GAMMADIR) + endif + endif + +endif + +# BUILDARCH is set to "zero" for Zero builds. VARIANTARCH +# is used to give the build directories meaningful names. +VARIANTARCH = $(subst i386,i486,$(ZERO_LIBARCH)) + +# There is a (semi-) regular correspondence between make targets and actions: +# +# Target Tree Type Build Dir +# +# debug compiler2 <os>_<arch>_compiler2/debug +# fastdebug compiler2 <os>_<arch>_compiler2/fastdebug +# jvmg compiler2 <os>_<arch>_compiler2/jvmg +# optimized compiler2 <os>_<arch>_compiler2/optimized +# profiled compiler2 <os>_<arch>_compiler2/profiled +# product compiler2 <os>_<arch>_compiler2/product +# +# debug1 compiler1 <os>_<arch>_compiler1/debug +# fastdebug1 compiler1 <os>_<arch>_compiler1/fastdebug +# jvmg1 compiler1 <os>_<arch>_compiler1/jvmg +# optimized1 compiler1 <os>_<arch>_compiler1/optimized +# profiled1 compiler1 <os>_<arch>_compiler1/profiled +# product1 compiler1 <os>_<arch>_compiler1/product +# +# debugcore core <os>_<arch>_core/debug +# fastdebugcore core <os>_<arch>_core/fastdebug +# jvmgcore core <os>_<arch>_core/jvmg +# optimizedcore core <os>_<arch>_core/optimized +# profiledcore core <os>_<arch>_core/profiled +# productcore core <os>_<arch>_core/product +# +# debugzero zero <os>_<arch>_zero/debug +# fastdebugzero zero <os>_<arch>_zero/fastdebug +# jvmgzero zero <os>_<arch>_zero/jvmg +# optimizedzero zero <os>_<arch>_zero/optimized +# profiledzero zero <os>_<arch>_zero/profiled +# productzero zero <os>_<arch>_zero/product +# +# debugshark shark <os>_<arch>_shark/debug +# fastdebugshark shark <os>_<arch>_shark/fastdebug +# jvmgshark shark <os>_<arch>_shark/jvmg +# optimizedshark shark <os>_<arch>_shark/optimized +# profiledshark shark <os>_<arch>_shark/profiled +# productshark shark <os>_<arch>_shark/product +# +# What you get with each target: +# +# debug* - "thin" libjvm_g - debug info linked into the gamma_g launcher +# fastdebug* - optimized compile, but with asserts enabled +# jvmg* - "fat" libjvm_g - debug info linked into libjvm_g.so +# optimized* - optimized compile, no asserts +# profiled* - gprof +# product* - the shippable thing: optimized compile, no asserts, -DPRODUCT + +# This target list needs to be coordinated with the usage message +# in the build.sh script: +TARGETS = debug jvmg fastdebug optimized profiled product + +ifeq ($(ZERO_BUILD), true) + SUBDIR_DOCS = $(OSNAME)_$(VARIANTARCH)_docs +else + SUBDIR_DOCS = $(OSNAME)_$(BUILDARCH)_docs +endif +SUBDIRS_C1 = $(addprefix $(OSNAME)_$(BUILDARCH)_compiler1/,$(TARGETS)) +SUBDIRS_C2 = $(addprefix $(OSNAME)_$(BUILDARCH)_compiler2/,$(TARGETS)) +SUBDIRS_TIERED = $(addprefix $(OSNAME)_$(BUILDARCH)_tiered/,$(TARGETS)) +SUBDIRS_CORE = $(addprefix $(OSNAME)_$(BUILDARCH)_core/,$(TARGETS)) +SUBDIRS_ZERO = $(addprefix $(OSNAME)_$(VARIANTARCH)_zero/,$(TARGETS)) +SUBDIRS_SHARK = $(addprefix $(OSNAME)_$(VARIANTARCH)_shark/,$(TARGETS)) + +TARGETS_C2 = $(TARGETS) +TARGETS_C1 = $(addsuffix 1,$(TARGETS)) +TARGETS_TIERED = $(addsuffix tiered,$(TARGETS)) +TARGETS_CORE = $(addsuffix core,$(TARGETS)) +TARGETS_ZERO = $(addsuffix zero,$(TARGETS)) +TARGETS_SHARK = $(addsuffix shark,$(TARGETS)) + +BUILDTREE_MAKE = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make +BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) +BUILDTREE_VARS += HOTSPOT_RELEASE_VERSION=$(HOTSPOT_RELEASE_VERSION) HOTSPOT_BUILD_VERSION=$(HOTSPOT_BUILD_VERSION) JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) + +BUILDTREE = $(MAKE) -f $(BUILDTREE_MAKE) $(BUILDTREE_VARS) + +#------------------------------------------------------------------------------- + +# Could make everything by default, but that would take a while. +all: + @echo "Try '$(MAKE) <target> ...' where <target> is one or more of" + @echo " $(TARGETS_C2)" + @echo " $(TARGETS_C1)" + @echo " $(TARGETS_CORE)" + @echo " $(TARGETS_ZERO)" + @echo " $(TARGETS_SHARK)" + +checks: check_os_version check_j2se_version + +# We do not want people accidentally building on old systems (e.g. Linux 2.2.x, +# Solaris 2.5.1, 2.6). +# Disable this check by setting DISABLE_HOTSPOT_OS_VERSION_CHECK=ok. + +#SUPPORTED_OS_VERSION = 2.4% 2.5% 2.6% 2.7% +DISABLE_HOTSPOT_OS_VERSION_CHECK = ok +OS_VERSION := $(shell uname -r) +EMPTY_IF_NOT_SUPPORTED = $(filter $(SUPPORTED_OS_VERSION),$(OS_VERSION)) + +check_os_version: +ifeq ($(DISABLE_HOTSPOT_OS_VERSION_CHECK)$(EMPTY_IF_NOT_SUPPORTED),) + $(QUIETLY) >&2 echo "*** This OS is not supported:" `uname -a`; exit 1; +endif + +# jvmti.make requires XSLT (J2SE 1.4.x or newer): +XSLT_CHECK = $(REMOTE) $(RUN.JAVAP) javax.xml.transform.TransformerFactory +# If not found then fail fast. +check_j2se_version: + $(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \ + if [ $$? -ne 0 ]; then \ + $(REMOTE) $(RUN.JAVA) -version; \ + echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \ + "to bootstrap this build" 1>&2; \ + exit 1; \ + fi + +$(SUBDIRS_TIERED): $(BUILDTREE_MAKE) + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks + $(BUILDTREE) VARIANT=tiered + +$(SUBDIRS_C2): $(BUILDTREE_MAKE) +ifeq ($(FORCE_TIERED),1) + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks + $(BUILDTREE) VARIANT=tiered FORCE_TIERED=1 +else + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks + $(BUILDTREE) VARIANT=compiler2 +endif + +$(SUBDIRS_C1): $(BUILDTREE_MAKE) + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks + $(BUILDTREE) VARIANT=compiler1 + +$(SUBDIRS_CORE): $(BUILDTREE_MAKE) + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks + $(BUILDTREE) VARIANT=core + +$(SUBDIRS_ZERO): $(BUILDTREE_MAKE) platform_zero + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks + $(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH) + +$(SUBDIRS_SHARK): $(BUILDTREE_MAKE) platform_zero + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks + $(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH) + +platform_zero: $(GAMMADIR)/make/$(OSNAME)/platform_zero.in + $(SED) 's/@ZERO_ARCHDEF@/$(ZERO_ARCHDEF)/g;s/@ZERO_LIBARCH@/$(ZERO_LIBARCH)/g;' < $< > $@ + +# Define INSTALL=y at command line to automatically copy JVM into JAVA_HOME + +$(TARGETS_C2): $(SUBDIRS_C2) + cd $(OSNAME)_$(BUILDARCH)_compiler2/$@ && $(MAKE) $(MFLAGS) + cd $(OSNAME)_$(BUILDARCH)_compiler2/$@ && ./test_gamma +ifdef INSTALL + cd $(OSNAME)_$(BUILDARCH)_compiler2/$@ && $(MAKE) $(MFLAGS) install +endif + +$(TARGETS_TIERED): $(SUBDIRS_TIERED) + cd $(OSNAME)_$(BUILDARCH)_tiered/$(patsubst %tiered,%,$@) && $(MAKE) $(MFLAGS) + cd $(OSNAME)_$(BUILDARCH)_tiered/$(patsubst %tiered,%,$@) && ./test_gamma +ifdef INSTALL + cd $(OSNAME)_$(BUILDARCH)_tiered/$(patsubst %tiered,%,$@) && $(MAKE) $(MFLAGS) install +endif + +$(TARGETS_C1): $(SUBDIRS_C1) + cd $(OSNAME)_$(BUILDARCH)_compiler1/$(patsubst %1,%,$@) && $(MAKE) $(MFLAGS) + cd $(OSNAME)_$(BUILDARCH)_compiler1/$(patsubst %1,%,$@) && ./test_gamma +ifdef INSTALL + cd $(OSNAME)_$(BUILDARCH)_compiler1/$(patsubst %1,%,$@) && $(MAKE) $(MFLAGS) install +endif + +$(TARGETS_CORE): $(SUBDIRS_CORE) + cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS) + cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && ./test_gamma +ifdef INSTALL + cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS) install +endif + +$(TARGETS_ZERO): $(SUBDIRS_ZERO) + cd $(OSNAME)_$(VARIANTARCH)_zero/$(patsubst %zero,%,$@) && $(MAKE) $(MFLAGS) + cd $(OSNAME)_$(VARIANTARCH)_zero/$(patsubst %zero,%,$@) && ./test_gamma +ifdef INSTALL + cd $(OSNAME)_$(VARIANTARCH)_zero/$(patsubst %zero,%,$@) && $(MAKE) $(MFLAGS) install +endif + +$(TARGETS_SHARK): $(SUBDIRS_SHARK) + cd $(OSNAME)_$(VARIANTARCH)_shark/$(patsubst %shark,%,$@) && $(MAKE) $(MFLAGS) + cd $(OSNAME)_$(VARIANTARCH)_shark/$(patsubst %shark,%,$@) && ./test_gamma +ifdef INSTALL + cd $(OSNAME)_$(VARIANTARCH)_shark/$(patsubst %shark,%,$@) && $(MAKE) $(MFLAGS) install +endif + +# Just build the tree, and nothing else: +tree: $(SUBDIRS_C2) +tree1: $(SUBDIRS_C1) +treecore: $(SUBDIRS_CORE) +treezero: $(SUBDIRS_ZERO) +treeshark: $(SUBDIRS_SHARK) + +# Doc target. This is the same for all build options. +# Hence create a docs directory beside ...$(ARCH)_[...] +docs: checks + $(QUIETLY) mkdir -p $(SUBDIR_DOCS) + $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/makefiles/jvmti.make $(MFLAGS) $(BUILDTREE_VARS) JvmtiOutDir=$(SUBDIR_DOCS) jvmtidocs + +# Synonyms for win32-like targets. +compiler2: jvmg product + +compiler1: jvmg1 product1 + +core: jvmgcore productcore + +zero: jvmgzero productzero + +shark: jvmgshark productshark + +clean_docs: + rm -rf $(SUBDIR_DOCS) + +clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark: + rm -rf $(OSNAME)_$(BUILDARCH)_$(subst clean_,,$@) + +clean: clean_compiler2 clean_compiler1 clean_core clean_zero clean_shark clean_docs + +include $(GAMMADIR)/make/cscope.make + +#------------------------------------------------------------------------------- + +.PHONY: $(TARGETS_C2) $(TARGETS_C1) $(TARGETS_CORE) $(TARGETS_ZERO) $(TARGETS_SHARK) +.PHONY: tree tree1 treecore treezero treeshark +.PHONY: all compiler1 compiler2 core zero shark +.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark docs clean_docs +.PHONY: checks check_os_version check_j2se_version
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/README Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,26 @@ +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. + +________________________________________________________________________ + +Please refer to the comments in the Makefile in this directory +for instructions how to build the Solaris versions. +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/adlc_updater Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,20 @@ +#! /bin/sh +# +# This file is used by adlc.make to selectively update generated +# adlc files. Because source and target diretories are relative +# paths, this file is copied to the target build directory before +# use. +# +# adlc-updater <file> <source-dir> <target-dir> +# +fix_lines() { + # repair bare #line directives in $1 to refer to $2 + awk < $1 > $1+ ' + /^#line 999999$/ {print "#line " (NR+1) " \"" F2 "\""; next} + {print} + ' F2=$2 + mv $1+ $1 +} +fix_lines $2/$1 $3/$1 +[ -f $3/$1 ] && cmp -s $2/$1 $3/$1 || \ +( [ -f $3/$1 ] && echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/build.sh Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,95 @@ +#! /bin/sh +# +# Copyright (c) 1999, 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. +# +# + +# Make sure the variable JAVA_HOME is set before running this script. + +set -u + + +if [ $# != 2 ]; then + echo "Usage : $0 Build_Options Location" + echo "Build Options : debug or optimized or basicdebug or basic or clean" + echo "Location : specify any workspace which has gamma sources" + exit 1 +fi + +# Just in case: +case ${JAVA_HOME} in +/*) true;; +?*) JAVA_HOME=`( cd $JAVA_HOME; pwd )`;; +esac + +case `uname -m` in + i386|i486|i586|i686) + mach=i386 + ;; + *) + echo "Unsupported machine: " `uname -m` + exit 1 + ;; +esac + +if [ "${JAVA_HOME}" = "" -o ! -d "${JAVA_HOME}" -o ! -d ${JAVA_HOME}/jre/lib/${mach} ]; then + echo "JAVA_HOME needs to be set to a valid JDK path" + echo "ksh : export JAVA_HOME=/net/tetrasparc/export/gobi/JDK1.2_fcs_V/bsd" + echo "csh : setenv JAVA_HOME /net/tetrasparc/export/gobi/JDK1.2_fcs_V/bsd" + exit 1 +fi + + +LD_LIBRARY_PATH=${JAVA_HOME}/jre/lib/`uname -p`:\ +${JAVA_HOME}/jre/lib/`uname -p`/native_threads:${LD_LIBRARY_PATH-.} + +# This is necessary as long as we are using the old launcher +# with the new distribution format: +CLASSPATH=${JAVA_HOME}/jre/lib/rt.jar:${CLASSPATH-.} + + +for gm in gmake gnumake +do + if [ "${GNUMAKE-}" != "" ]; then break; fi + ($gm --version >/dev/null) 2>/dev/null && GNUMAKE=$gm +done +: ${GNUMAKE:?'Cannot locate the gnumake program. Stop.'} + + +echo "### ENVIRONMENT SETTINGS:" +export JAVA_HOME ; echo "JAVA_HOME=$JAVA_HOME" +export LD_LIBRARY_PATH ; echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" +export CLASSPATH ; echo "CLASSPATH=$CLASSPATH" +export GNUMAKE ; echo "GNUMAKE=$GNUMAKE" +echo "###" + +Build_Options=$1 +Location=$2 + +case ${Location} in +/*) true;; +?*) Location=`(cd ${Location}; pwd)`;; +esac + +echo \ +${GNUMAKE} -f ${Location}/make/bsd/Makefile $Build_Options GAMMADIR=${Location} +${GNUMAKE} -f ${Location}/make/bsd/Makefile $Build_Options GAMMADIR=${Location}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/adjust-mflags.sh Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,87 @@ +#! /bin/sh +# +# Copyright (c) 1999, 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. +# +# + +# This script is used only from top.make. +# The macro $(MFLAGS-adjusted) calls this script to +# adjust the "-j" arguments to take into account +# the HOTSPOT_BUILD_JOBS variable. The default +# handling of the "-j" argument by gnumake does +# not meet our needs, so we must adjust it ourselves. + +# This argument adjustment applies to two recursive +# calls to "$(MAKE) $(MFLAGS-adjusted)" in top.make. +# One invokes adlc.make, and the other invokes vm.make. +# The adjustment propagates the desired concurrency +# level down to the sub-make (of the adlc or vm). +# The default behavior of gnumake is to run all +# sub-makes without concurrency ("-j1"). + +# Also, we use a make variable rather than an explicit +# "-j<N>" argument to control this setting, so that +# the concurrency setting (which must be tuned separately +# for each MP system) can be set via an environment variable. +# The recommended setting is 1.5x to 2x the number of available +# CPUs on the MP system, which is large enough to keep the CPUs +# busy (even though some jobs may be I/O bound) but not too large, +# we may presume, to overflow the system's swap space. + +set -eu + +default_build_jobs=4 + +case $# in +[12]) true;; +*) >&2 echo "Usage: $0 ${MFLAGS} ${HOTSPOT_BUILD_JOBS}"; exit 2;; +esac + +MFLAGS=$1 +HOTSPOT_BUILD_JOBS=${2-} + +# Normalize any -jN argument to the form " -j${HBJ}" +MFLAGS=` + echo "$MFLAGS" \ + | sed ' + s/^-/ -/ + s/ -\([^ ][^ ]*\)j/ -\1 -j/ + s/ -j[0-9][0-9]*/ -j/ + s/ -j\([^ ]\)/ -j -\1/ + s/ -j/ -j'${HOTSPOT_BUILD_JOBS:-${default_build_jobs}}'/ + ' ` + +case ${HOTSPOT_BUILD_JOBS} in \ + +'') case ${MFLAGS} in + *\ -j*) + >&2 echo "# Note: -jN is ineffective for setting parallelism in this makefile." + >&2 echo "# please set HOTSPOT_BUILD_JOBS=${default_build_jobs} in the command line or environment." + esac;; + +?*) case ${MFLAGS} in + *\ -j*) true;; + *) MFLAGS="-j${HOTSPOT_BUILD_JOBS} ${MFLAGS}";; + esac;; +esac + +echo "${MFLAGS}"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/adlc.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,228 @@ +# +# Copyright (c) 1999, 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. +# +# + +# This makefile (adlc.make) is included from the adlc.make in the +# build directories. +# It knows how to compile, link, and run the adlc. + +include $(GAMMADIR)/make/$(Platform_os_family)/makefiles/rules.make + +# ######################################################################### + +# OUTDIR must be the same as AD_Dir = $(GENERATED)/adfiles in top.make: +GENERATED = ../generated +OUTDIR = $(GENERATED)/adfiles + +ARCH = $(Platform_arch) +OS = $(Platform_os_family) + +SOURCE.AD = $(OUTDIR)/$(OS)_$(Platform_arch_model).ad + +SOURCES.AD = \ + $(call altsrc-replace,$(HS_COMMON_SRC)/cpu/$(ARCH)/vm/$(Platform_arch_model).ad) \ + $(call altsrc-replace,$(HS_COMMON_SRC)/os_cpu/$(OS)_$(ARCH)/vm/$(OS)_$(Platform_arch_model).ad) + +EXEC = $(OUTDIR)/adlc + +# set VPATH so make knows where to look for source files +Src_Dirs_V += $(GAMMADIR)/src/share/vm/adlc +VPATH += $(Src_Dirs_V:%=%:) + +# set INCLUDES for C preprocessor +Src_Dirs_I += $(GAMMADIR)/src/share/vm/adlc $(GENERATED) +INCLUDES += $(Src_Dirs_I:%=-I%) + +# set flags for adlc compilation +CPPFLAGS = $(SYSDEFS) $(INCLUDES) + +# Force assertions on. +CPPFLAGS += -DASSERT + +# CFLAGS_WARN holds compiler options to suppress/enable warnings. +# Compiler warnings are treated as errors +ifneq ($(COMPILER_WARNINGS_FATAL),false) + CFLAGS_WARN = -Werror +endif +CFLAGS += $(CFLAGS_WARN) + +OBJECTNAMES = \ + adlparse.o \ + archDesc.o \ + arena.o \ + dfa.o \ + dict2.o \ + filebuff.o \ + forms.o \ + formsopt.o \ + formssel.o \ + main.o \ + adlc-opcodes.o \ + output_c.o \ + output_h.o \ + +OBJECTS = $(OBJECTNAMES:%=$(OUTDIR)/%) + +GENERATEDNAMES = \ + ad_$(Platform_arch_model).cpp \ + ad_$(Platform_arch_model).hpp \ + ad_$(Platform_arch_model)_clone.cpp \ + ad_$(Platform_arch_model)_expand.cpp \ + ad_$(Platform_arch_model)_format.cpp \ + ad_$(Platform_arch_model)_gen.cpp \ + ad_$(Platform_arch_model)_misc.cpp \ + ad_$(Platform_arch_model)_peephole.cpp \ + ad_$(Platform_arch_model)_pipeline.cpp \ + adGlobals_$(Platform_arch_model).hpp \ + dfa_$(Platform_arch_model).cpp \ + +GENERATEDFILES = $(GENERATEDNAMES:%=$(OUTDIR)/%) + +# ######################################################################### + +all: $(EXEC) + +$(EXEC) : $(OBJECTS) + @echo Making adlc + $(QUIETLY) $(HOST.LINK_NOPROF.CC) -o $(EXEC) $(OBJECTS) + +# Random dependencies: +$(OBJECTS): opcodes.hpp classes.hpp adlc.hpp adlcVMDeps.hpp adlparse.hpp archDesc.hpp arena.hpp dict2.hpp filebuff.hpp forms.hpp formsopt.hpp formssel.hpp + +# The source files refer to ostream.h, which sparcworks calls iostream.h +$(OBJECTS): ostream.h + +ostream.h : + @echo >$@ '#include <iostream.h>' + +dump: + : OUTDIR=$(OUTDIR) + : OBJECTS=$(OBJECTS) + : products = $(GENERATEDFILES) + +all: $(GENERATEDFILES) + +$(GENERATEDFILES): refresh_adfiles + +# Get a unique temporary directory name, so multiple makes can run in parallel. +# Note that product files are updated via "mv", which is atomic. +TEMPDIR := $(OUTDIR)/mktmp$(shell echo $$$$) + +# Debuggable by default +CFLAGS += -g + +# Pass -D flags into ADLC. +ADLCFLAGS += $(SYSDEFS) + +# Note "+="; it is a hook so flags.make can add more flags, like -g or -DFOO. +ADLCFLAGS += -q -T + +# Normally, debugging is done directly on the ad_<arch>*.cpp files. +# But -g will put #line directives in those files pointing back to <arch>.ad. +# Some builds of gcc 3.2 have a bug that gets tickled by the extra #line directives +# so skip it for 3.2 and ealier. +ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) \| \( \( $(CC_VER_MAJOR) = 3 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0" +ADLCFLAGS += -g +endif + +ifdef LP64 +ADLCFLAGS += -D_LP64 +else +ADLCFLAGS += -U_LP64 +endif + +# +# adlc_updater is a simple sh script, under sccs control. It is +# used to selectively update generated adlc files. This should +# provide a nice compilation speed improvement. +# +ADLC_UPDATER_DIRECTORY = $(GAMMADIR)/make/$(OS) +ADLC_UPDATER = adlc_updater +$(ADLC_UPDATER): $(ADLC_UPDATER_DIRECTORY)/$(ADLC_UPDATER) + $(QUIETLY) cp $< $@; chmod +x $@ + +# This action refreshes all generated adlc files simultaneously. +# The way it works is this: +# 1) create a scratch directory to work in. +# 2) if the current working directory does not have $(ADLC_UPDATER), copy it. +# 3) run the compiled adlc executable. This will create new adlc files in the scratch directory. +# 4) call $(ADLC_UPDATER) on each generated adlc file. It will selectively update changed or missing files. +# 5) If we actually updated any files, echo a notice. +# +refresh_adfiles: $(EXEC) $(SOURCE.AD) $(ADLC_UPDATER) + @rm -rf $(TEMPDIR); mkdir $(TEMPDIR) + $(QUIETLY) $(EXEC) $(ADLCFLAGS) $(SOURCE.AD) \ + -c$(TEMPDIR)/ad_$(Platform_arch_model).cpp -h$(TEMPDIR)/ad_$(Platform_arch_model).hpp -a$(TEMPDIR)/dfa_$(Platform_arch_model).cpp -v$(TEMPDIR)/adGlobals_$(Platform_arch_model).hpp \ + || { rm -rf $(TEMPDIR); exit 1; } + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model).cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model).hpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_clone.cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_expand.cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_format.cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_gen.cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_misc.cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_peephole.cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) ad_$(Platform_arch_model)_pipeline.cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) adGlobals_$(Platform_arch_model).hpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) ./$(ADLC_UPDATER) dfa_$(Platform_arch_model).cpp $(TEMPDIR) $(OUTDIR) + $(QUIETLY) [ -f $(TEMPDIR)/made-change ] \ + || echo "Rescanned $(SOURCE.AD) but encountered no changes." + $(QUIETLY) rm -rf $(TEMPDIR) + + +# ######################################################################### + +$(SOURCE.AD): $(SOURCES.AD) + $(QUIETLY) $(PROCESS_AD_FILES) $(SOURCES.AD) > $(SOURCE.AD) + +#PROCESS_AD_FILES = cat +# Pass through #line directives, in case user enables -g option above: +PROCESS_AD_FILES = awk '{ \ + if (CUR_FN != FILENAME) { CUR_FN=FILENAME; NR_BASE=NR-1; need_lineno=1 } \ + if (need_lineno && $$0 !~ /\/\//) \ + { print "\n\n\#line " (NR-NR_BASE) " \"" FILENAME "\""; need_lineno=0 }; \ + print }' + +$(OUTDIR)/%.o: %.cpp + @echo Compiling $< + $(QUIETLY) $(REMOVE_TARGET) + $(QUIETLY) $(HOST.COMPILE.CC) -o $@ $< $(COMPILE_DONE) + +# Some object files are given a prefix, to disambiguate +# them from objects of the same name built for the VM. +$(OUTDIR)/adlc-%.o: %.cpp + @echo Compiling $< + $(QUIETLY) $(REMOVE_TARGET) + $(QUIETLY) $(HOST.COMPILE.CC) -o $@ $< $(COMPILE_DONE) + +# ######################################################################### + +clean : + rm $(OBJECTS) + +cleanall : + rm $(OBJECTS) $(EXEC) + +# ######################################################################### + +.PHONY: all dump refresh_adfiles clean cleanall
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/amd64.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,39 @@ +# +# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized +OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT) +# The copied fdlibm routines in sharedRuntimeTrans.o must not be optimized +OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT) +# Must also specify if CPU is little endian +CFLAGS += -DVM_LITTLE_ENDIAN + +CFLAGS += -D_LP64=1 + +# The serviceability agent relies on frame pointer (%rbp) to walk thread stack +ifndef USE_SUNCC + CFLAGS += -fno-omit-frame-pointer +endif + +OPT_CFLAGS/compactingPermGenGen.o = -O1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/arm.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,29 @@ +# +# Copyright (c) 2008, 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. +# +# + +Obj_Files += bsd_arm.o + +LIBS += $(EXT_LIBS_PATH)/sflt_glibc.a + +CFLAGS += -DVM_LITTLE_ENDIAN
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/build_vm_def.sh Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,12 @@ +#!/bin/sh + +# If we're cross compiling use that path for nm +if [ "$CROSS_COMPILE_ARCH" != "" ]; then +NM=$ALT_COMPILER_PATH/nm +else +NM=nm +fi + +$NM --defined-only $* | awk ' + { if ($3 ~ /^_ZTV/ || $3 ~ /^gHotSpotVM/) print "\t" $3 ";" } + '
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/buildtree.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,430 @@ +# +# Copyright (c) 2005, 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. +# +# + +# Usage: +# +# $(MAKE) -f buildtree.make SRCARCH=srcarch BUILDARCH=buildarch LIBARCH=libarch +# GAMMADIR=dir OS_FAMILY=os VARIANT=variant +# +# The macros ARCH, GAMMADIR, OS_FAMILY and VARIANT must be defined in the +# environment or on the command-line: +# +# ARCH - sparc, i486, ... HotSpot cpu and os_cpu source directory +# BUILDARCH - build directory +# LIBARCH - the corresponding directory in JDK/JRE +# GAMMADIR - top of workspace +# OS_FAMILY - operating system +# VARIANT - core, compiler1, compiler2, or tiered +# HOTSPOT_RELEASE_VERSION - <major>.<minor>-b<nn> (11.0-b07) +# HOTSPOT_BUILD_VERSION - internal, internal-$(USER_RELEASE_SUFFIX) or empty +# JRE_RELEASE_VERSION - <major>.<minor>.<micro> (1.7.0) +# +# Builds the directory trees with makefiles plus some convenience files in +# each directory: +# +# Makefile - for "make foo" +# flags.make - with macro settings +# vm.make - to support making "$(MAKE) -v vm.make" in makefiles +# adlc.make - +# jvmti.make - generate JVMTI bindings from the spec (JSR-163) +# sa.make - generate SA jar file and natives +# env.[ck]sh - environment settings +# test_gamma - script to run the Queens program +# +# The makefiles are split this way so that "make foo" will run faster by not +# having to read the dependency files for the vm. + +include $(GAMMADIR)/make/scm.make +include $(GAMMADIR)/make/altsrc.make + + +# 'gmake MAKE_VERBOSE=y' or 'gmake QUIETLY=' gives all the gory details. +QUIETLY$(MAKE_VERBOSE) = @ + +# For now, until the compiler is less wobbly: +TESTFLAGS = -Xbatch -showversion + +ifeq ($(ZERO_BUILD), true) + PLATFORM_FILE = $(shell dirname $(shell dirname $(shell pwd)))/platform_zero +else + ifdef USE_SUNCC + PLATFORM_FILE = $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH).suncc + else + PLATFORM_FILE = $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH) + endif +endif + +# Allow overriding of the arch part of the directory but default +# to BUILDARCH if nothing is specified +ifeq ($(VARIANTARCH),) + VARIANTARCH=$(BUILDARCH) +endif + +ifdef FORCE_TIERED +ifeq ($(VARIANT),tiered) +PLATFORM_DIR = $(OS_FAMILY)_$(VARIANTARCH)_compiler2 +else +PLATFORM_DIR = $(OS_FAMILY)_$(VARIANTARCH)_$(VARIANT) +endif +else +PLATFORM_DIR = $(OS_FAMILY)_$(VARIANTARCH)_$(VARIANT) +endif + +# +# We do two levels of exclusion in the shared directory. +# TOPLEVEL excludes are pruned, they are not recursively searched, +# but lower level directories can be named without fear of collision. +# ALWAYS excludes are excluded at any level in the directory tree. +# + +ALWAYS_EXCLUDE_DIRS = $(SCM_DIRS) + +ifeq ($(VARIANT),tiered) +TOPLEVEL_EXCLUDE_DIRS = $(ALWAYS_EXCLUDE_DIRS) -o -name adlc -o -name agent +else +ifeq ($(VARIANT),compiler2) +TOPLEVEL_EXCLUDE_DIRS = $(ALWAYS_EXCLUDE_DIRS) -o -name adlc -o -name c1 -o -name agent +else +# compiler1 and core use the same exclude list +TOPLEVEL_EXCLUDE_DIRS = $(ALWAYS_EXCLUDE_DIRS) -o -name adlc -o -name opto -o -name libadt -o -name agent +endif +endif + +# Get things from the platform file. +COMPILER = $(shell sed -n 's/^compiler[ ]*=[ ]*//p' $(PLATFORM_FILE)) + +# dtracefiles is used on BSD versions that implement Dtrace (like MacOS X) +SIMPLE_DIRS = \ + $(PLATFORM_DIR)/generated/dependencies \ + $(PLATFORM_DIR)/generated/adfiles \ + $(PLATFORM_DIR)/generated/jvmtifiles \ + $(PLATFORM_DIR)/generated/dtracefiles + +TARGETS = debug fastdebug jvmg optimized product profiled +SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) + +# For dependencies and recursive makes. +BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make + +# dtrace.make is used on BSD versions that implement Dtrace (like MacOS X) +BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make \ + jvmti.make sa.make dtrace.make \ + env.sh env.csh jdkpath.sh .dbxrc test_gamma + +BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \ + SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT) + +# Define variables to be set in flags.make. +# Default values are set in make/defs.make. +ifeq ($(HOTSPOT_BUILD_VERSION),) + HS_BUILD_VER=$(HOTSPOT_RELEASE_VERSION) +else + HS_BUILD_VER=$(HOTSPOT_RELEASE_VERSION)-$(HOTSPOT_BUILD_VERSION) +endif +# Set BUILD_USER from system-dependent hints: $LOGNAME, $(whoami) +ifndef HOTSPOT_BUILD_USER + HOTSPOT_BUILD_USER := $(shell echo $$LOGNAME) +endif +ifndef HOTSPOT_BUILD_USER + HOTSPOT_BUILD_USER := $(shell whoami) +endif +# Define HOTSPOT_VM_DISTRO based on settings in make/openjdk_distro +# or make/hotspot_distro. +ifndef HOTSPOT_VM_DISTRO + ifeq ($(call if-has-altsrc,$(HS_COMMON_SRC)/,true,false),true) + include $(GAMMADIR)/make/hotspot_distro + else + include $(GAMMADIR)/make/openjdk_distro + endif +endif + +# MACOSX FIXME: we should be able to run test_gamma (see MACOSX_PORT-214) +ifdef ALWAYS_PASS_TEST_GAMMA + TEST_GAMMA_STATUS= echo 'exit 0'; +else + TEST_GAMMA_STATUS= +endif + +BUILDTREE_VARS += HOTSPOT_RELEASE_VERSION=$(HS_BUILD_VER) HOTSPOT_BUILD_VERSION= JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) + +BUILDTREE = \ + $(MAKE) -f $(BUILDTREE_MAKE) $(BUILDTREE_TARGETS) $(BUILDTREE_VARS) + +BUILDTREE_COMMENT = echo "\# Generated by $(BUILDTREE_MAKE)" + +all: $(SUBMAKE_DIRS) + +# Run make in each subdirectory recursively. +$(SUBMAKE_DIRS): $(SIMPLE_DIRS) FORCE + $(QUIETLY) [ -d $@ ] || { mkdir -p $@; } + $(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F) + $(QUIETLY) touch $@ + +$(SIMPLE_DIRS): + $(QUIETLY) mkdir -p $@ + +# Convenience macro which takes a source relative path, applies $(1) to the +# absolute path, and then replaces $(GAMMADIR) in the result with a +# literal "$(GAMMADIR)/" suitable for inclusion in a Makefile. +gamma-path=$(subst $(GAMMADIR),\$$(GAMMADIR),$(call $(1),$(HS_COMMON_SRC)/$(2))) + +flags.make: $(BUILDTREE_MAKE) ../shared_dirs.lst + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo "Platform_file = $(PLATFORM_FILE)" | sed 's|$(GAMMADIR)|$$(GAMMADIR)|'; \ + sed -n '/=/s/^ */Platform_/p' < $(PLATFORM_FILE); \ + echo; \ + echo "GAMMADIR = $(GAMMADIR)"; \ + echo "SYSDEFS = \$$(Platform_sysdefs)"; \ + echo "SRCARCH = $(SRCARCH)"; \ + echo "BUILDARCH = $(BUILDARCH)"; \ + echo "LIBARCH = $(LIBARCH)"; \ + echo "TARGET = $(TARGET)"; \ + echo "HS_BUILD_VER = $(HS_BUILD_VER)"; \ + echo "JRE_RELEASE_VER = $(JRE_RELEASE_VERSION)"; \ + echo "SA_BUILD_VERSION = $(HS_BUILD_VER)"; \ + echo "HOTSPOT_BUILD_USER = $(HOTSPOT_BUILD_USER)"; \ + echo "HOTSPOT_VM_DISTRO = $(HOTSPOT_VM_DISTRO)"; \ + echo; \ + echo "# Used for platform dispatching"; \ + echo "TARGET_DEFINES = -DTARGET_OS_FAMILY_\$$(Platform_os_family)"; \ + echo "TARGET_DEFINES += -DTARGET_ARCH_\$$(Platform_arch)"; \ + echo "TARGET_DEFINES += -DTARGET_ARCH_MODEL_\$$(Platform_arch_model)"; \ + echo "TARGET_DEFINES += -DTARGET_OS_ARCH_\$$(Platform_os_arch)"; \ + echo "TARGET_DEFINES += -DTARGET_OS_ARCH_MODEL_\$$(Platform_os_arch_model)"; \ + echo "TARGET_DEFINES += -DTARGET_COMPILER_\$$(Platform_compiler)"; \ + echo "CFLAGS += \$$(TARGET_DEFINES)"; \ + echo; \ + echo "Src_Dirs_V = \\"; \ + sed 's/$$/ \\/;s|$(GAMMADIR)|$$(GAMMADIR)|' ../shared_dirs.lst; \ + echo "$(call gamma-path,altsrc,cpu/$(SRCARCH)/vm) \\"; \ + echo "$(call gamma-path,commonsrc,cpu/$(SRCARCH)/vm) \\"; \ + echo "$(call gamma-path,altsrc,os_cpu/$(OS_FAMILY)_$(SRCARCH)/vm) \\"; \ + echo "$(call gamma-path,commonsrc,os_cpu/$(OS_FAMILY)_$(SRCARCH)/vm) \\"; \ + echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \ + echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \ + echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \ + echo "$(call gamma-path,commonsrc,os/posix/vm)"; \ + echo; \ + echo "Src_Dirs_I = \\"; \ + echo "$(call gamma-path,altsrc,share/vm/prims) \\"; \ + echo "$(call gamma-path,commonsrc,share/vm/prims) \\"; \ + echo "$(call gamma-path,altsrc,share/vm) \\"; \ + echo "$(call gamma-path,commonsrc,share/vm) \\"; \ + echo "$(call gamma-path,altsrc,cpu/$(SRCARCH)/vm) \\"; \ + echo "$(call gamma-path,commonsrc,cpu/$(SRCARCH)/vm) \\"; \ + echo "$(call gamma-path,altsrc,os_cpu/$(OS_FAMILY)_$(SRCARCH)/vm) \\"; \ + echo "$(call gamma-path,commonsrc,os_cpu/$(OS_FAMILY)_$(SRCARCH)/vm) \\"; \ + echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \ + echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \ + echo "$(call gamma-path,altsrc,os/posix/vm) \\"; \ + echo "$(call gamma-path,commonsrc,os/posix/vm)"; \ + [ -n "$(CFLAGS_BROWSE)" ] && \ + echo && echo "CFLAGS_BROWSE = $(CFLAGS_BROWSE)"; \ + [ -n "$(HOTSPOT_EXTRA_SYSDEFS)" ] && \ + echo && \ + echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \ + echo "SYSDEFS += \$$(HOTSPOT_EXTRA_SYSDEFS)"; \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(VARIANT).make"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(COMPILER).make"; \ + ) > $@ + +flags_vm.make: $(BUILDTREE_MAKE) ../shared_dirs.lst + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + [ "$(TARGET)" = profiled ] && \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/optimized.make"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(TARGET).make"; \ + ) > $@ + +../shared_dirs.lst: $(BUILDTREE_MAKE) $(GAMMADIR)/src/share/vm + @echo Creating directory list $@ + $(QUIETLY) if [ -d $(HS_ALT_SRC)/share/vm ]; then \ + find $(HS_ALT_SRC)/share/vm/* -prune \ + -type d \! \( $(TOPLEVEL_EXCLUDE_DIRS) \) -exec find {} \ + \( $(ALWAYS_EXCLUDE_DIRS) \) -prune -o -type d -print \; > $@; \ + fi; + $(QUIETLY) find $(HS_COMMON_SRC)/share/vm/* -prune \ + -type d \! \( $(TOPLEVEL_EXCLUDE_DIRS) \) -exec find {} \ + \( $(ALWAYS_EXCLUDE_DIRS) \) -prune -o -type d -print \; >> $@ + +Makefile: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo include flags.make; \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/top.make"; \ + ) > $@ + +vm.make: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo include flags.make; \ + echo include flags_vm.make; \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ + ) > $@ + +adlc.make: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo include flags.make; \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ + ) > $@ + +jvmti.make: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo include flags.make; \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ + ) > $@ + +sa.make: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo include flags.make; \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ + ) > $@ + +dtrace.make: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo; \ + echo include flags.make; \ + echo; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ + ) > $@ + +env.sh: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + [ -n "$$JAVA_HOME" ] && { echo ": \$${JAVA_HOME:=$${JAVA_HOME}}"; }; \ + { \ + echo "LD_LIBRARY_PATH=.:$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \ + echo "DYLD_LIBRARY_PATH=.:$${DYLD_LIBRARY_PATH:+$$DYLD_LIBRARY_PATH:}\$${JAVA_HOME}/jre/lib/${LIBARCH}/native_threads:\$${JAVA_HOME}/jre/lib/${LIBARCH}:${GCC_LIB}"; \ + echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.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 DYLD_LIBRARY_PATH CLASSPATH HOTSPOT_BUILD_USER"; \ + ) > $@ + +env.csh: env.sh + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + [ -n "$$JAVA_HOME" ] && \ + { echo "if (! \$$?JAVA_HOME) setenv JAVA_HOME \"$$JAVA_HOME\""; }; \ + sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=/setenv \1 /p' $?; \ + ) > $@ + +jdkpath.sh: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo "JDK=${JAVA_HOME}"; \ + ) > $@ + +.dbxrc: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + echo "echo '# Loading $(PLATFORM_DIR)/$(TARGET)/.dbxrc'"; \ + echo "if [ -f \"\$${HOTSPOT_DBXWARE}\" ]"; \ + echo "then"; \ + echo " source \"\$${HOTSPOT_DBXWARE}\""; \ + echo "elif [ -f \"\$$HOME/.dbxrc\" ]"; \ + echo "then"; \ + echo " source \"\$$HOME/.dbxrc\""; \ + echo "fi"; \ + ) > $@ + +# Skip the test for product builds (which only work when installed in a JDK), to +# avoid exiting with an error and causing make to halt. +NO_TEST_MSG = \ + echo "$@: skipping the test--this build must be tested in a JDK." + +NO_JAVA_HOME_MSG = \ + echo "JAVA_HOME must be set to run this test." + +DATA_MODE = $(DATA_MODE/$(BUILDARCH)) +JAVA_FLAG = $(JAVA_FLAG/$(DATA_MODE)) + +DATA_MODE/i486 = 32 +DATA_MODE/sparc = 32 +DATA_MODE/sparcv9 = 64 +DATA_MODE/amd64 = 64 +DATA_MODE/ia64 = 64 +DATA_MODE/zero = $(ARCH_DATA_MODEL) + +JAVA_FLAG/32 = -d32 +JAVA_FLAG/64 = -d64 + +WRONG_DATA_MODE_MSG = \ + echo "JAVA_HOME must point to $(DATA_MODE)bit JDK." + +CROSS_COMPILING_MSG = \ + echo "Cross compiling for ARCH $(CROSS_COMPILE_ARCH), skipping gamma run." + +test_gamma: $(BUILDTREE_MAKE) $(GAMMADIR)/make/test/Queens.java + @echo Creating $@ ... + $(QUIETLY) ( \ + echo '#!/bin/sh'; \ + $(BUILDTREE_COMMENT); \ + echo '. ./env.sh'; \ + echo "if [ \"$(CROSS_COMPILE_ARCH)\" != \"\" ]; then { $(CROSS_COMPILING_MSG); exit 0; }; fi"; \ + echo "if [ -z \$$JAVA_HOME ]; then { $(NO_JAVA_HOME_MSG); exit 0; }; fi"; \ + echo "if ! \$${JAVA_HOME}/bin/java $(JAVA_FLAG) -fullversion 2>&1 > /dev/null"; \ + echo "then"; \ + echo " $(WRONG_DATA_MODE_MSG); exit 0;"; \ + echo "fi"; \ + echo "rm -f Queens.class"; \ + echo "\$${JAVA_HOME}/bin/javac -d . $(GAMMADIR)/make/test/Queens.java"; \ + echo '[ -f gamma_g ] && { gamma=gamma_g; }'; \ + echo './$${gamma:-gamma} $(TESTFLAGS) Queens < /dev/null'; \ + $(TEST_GAMMA_STATUS) \ + ) > $@ + $(QUIETLY) chmod +x $@ + +FORCE: + +.PHONY: all FORCE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/compiler1.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,31 @@ +# +# Copyright (c) 1999, 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. +# +# + +# Sets make macros for making client version of VM + +TYPE=COMPILER1 + +VM_SUBDIR = client + +CFLAGS += -DCOMPILER1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/compiler2.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,31 @@ +# +# Copyright (c) 1999, 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. +# +# + +# Sets make macros for making server version of VM + +TYPE=COMPILER2 + +VM_SUBDIR = server + +CFLAGS += -DCOMPILER2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/core.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,33 @@ +# +# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 core version of VM + +# Select which files to use (in top.make) +TYPE=CORE + +# There is no "core" directory in JDK. Install core build in server directory. +VM_SUBDIR = server + +# Note: macros.hpp defines CORE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/cscope.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,160 @@ +# +# Copyright (c) 2005, 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. +# +# + +# +# The cscope.out file is made in the current directory and spans the entire +# source tree. +# +# Things to note: +# 1. We use relative names for cscope. +# 2. We *don't* remove the old cscope.out file, because cscope is smart +# enough to only build what has changed. It can be confused, however, +# if files are renamed or removed, so it may be necessary to manually +# remove cscope.out if a lot of reorganization has occurred. +# + +include $(GAMMADIR)/make/scm.make + +NAWK = awk +RM = rm -f +HG = hg +CS_TOP = ../.. + +CSDIRS = $(CS_TOP)/src $(CS_TOP)/build +CSINCS = $(CSDIRS:%=-I%) + +CSCOPE = cscope +CSCOPE_FLAGS = -b + +# Allow .java files to be added from the environment (CSCLASSES=yes). +ifdef CSCLASSES +ADDCLASSES= -o -name '*.java' +endif + +# Adding CClassHeaders also pushes the file count of a full workspace up about +# 200 files (these files also don't exist in a new workspace, and thus will +# cause the recreation of the database as they get created, which might seem +# a little confusing). Thus allow these files to be added from the environment +# (CSHEADERS=yes). +ifndef CSHEADERS +RMCCHEADERS= -o -name CClassHeaders +endif + +# Use CS_GENERATED=x to include auto-generated files in the build directories. +ifdef CS_GENERATED +CS_ADD_GENERATED = -o -name '*.incl' +else +CS_PRUNE_GENERATED = -o -name '${OS}_*_core' -o -name '${OS}_*_compiler?' +endif + +# OS-specific files for other systems are excluded by default. Use CS_OS=yes +# to include platform-specific files for other platforms. +ifndef CS_OS +CS_OS = linux macos solaris win32 bsd +CS_PRUNE_OS = $(patsubst %,-o -name '*%*',$(filter-out ${OS},${CS_OS})) +endif + +# Processor-specific files for other processors are excluded by default. Use +# CS_CPU=x to include platform-specific files for other platforms. +ifndef CS_CPU +CS_CPU = i486 sparc amd64 ia64 +CS_PRUNE_CPU = $(patsubst %,-o -name '*%*',$(filter-out ${SRCARCH},${CS_CPU})) +endif + +# What files should we include? A simple rule might be just those files under +# SCCS control, however this would miss files we create like the opcodes and +# CClassHeaders. The following attempts to find everything that is *useful*. +# (.del files are created by sccsrm, demo directories contain many .java files +# that probably aren't useful for development, and the pkgarchive may contain +# duplicates of files within the source hierarchy). + +# Directories to exclude. +CS_PRUNE_STD = $(SCM_DIRS) \ + -o -name '.del-*' \ + -o -name '*demo' \ + -o -name pkgarchive + +CS_PRUNE = $(CS_PRUNE_STD) \ + $(CS_PRUNE_OS) \ + $(CS_PRUNE_CPU) \ + $(CS_PRUNE_GENERATED) \ + $(RMCCHEADERS) + +# File names to include. +CSFILENAMES = -name '*.[ch]pp' \ + -o -name '*.[Ccshlxy]' \ + $(CS_ADD_GENERATED) \ + -o -name '*.il' \ + -o -name '*.cc' \ + -o -name '*[Mm]akefile*' \ + -o -name '*.gmk' \ + -o -name '*.make' \ + -o -name '*.ad' \ + $(ADDCLASSES) + +.PRECIOUS: cscope.out + +cscope cscope.out: cscope.files FORCE + $(CSCOPE) $(CSCOPE_FLAGS) + +# The .raw file is reordered here in an attempt to make cscope display the most +# relevant files first. +cscope.files: .cscope.files.raw + echo "$(CSINCS)" > $@ + -egrep -v "\.java|\/make\/" $< >> $@ + -fgrep ".java" $< >> $@ + -fgrep "/make/" $< >> $@ + +.cscope.files.raw: .nametable.files + -find $(CSDIRS) -type d \( $(CS_PRUNE) \) -prune -o \ + -type f \( $(CSFILENAMES) \) -print > $@ + +cscope.clean: nametable.clean + -$(RM) cscope.out cscope.files .cscope.files.raw + +TAGS: cscope.files FORCE + egrep -v '^-|^$$' $< | etags --members - + +TAGS.clean: nametable.clean + -$(RM) TAGS + +# .nametable.files and .nametable.files.tmp are used to determine if any files +# were added to/deleted from/renamed in the workspace. If not, then there's +# normally no need to rebuild the cscope database. To force a rebuild of +# the cscope database: gmake nametable.clean. +.nametable.files: .nametable.files.tmp + ( cmp -s $@ $< ) || ( cp $< $@ ) + -$(RM) $< + +# `hg status' is slightly faster than `hg fstatus'. Both are +# quite a bit slower on an NFS mounted file system, so this is +# really geared towards repos on local file systems. +.nametable.files.tmp: + -$(HG) fstatus -acmn > $@ +nametable.clean: + -$(RM) .nametable.files .nametable.files.tmp + +FORCE: + +.PHONY: cscope cscope.clean TAGS.clean nametable.clean FORCE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/debug.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,44 @@ +# +# Copyright (c) 1999, 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. +# +# + +# Sets make macros for making debug version of VM + +# Compiler specific DEBUG_CFLAGS are passed in from gcc.make, sparcWorks.make +DEBUG_CFLAGS/DEFAULT= $(DEBUG_CFLAGS) +DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@)) +CFLAGS += $(DEBUG_CFLAGS/BYFILE) + +# Linker mapfile +MAPFILE = $(GAMMADIR)/make/bsd/makefiles/mapfile-vers-debug + +_JUNK_ := $(shell echo -e >&2 ""\ + "----------------------------------------------------------------------\n" \ + "WARNING: 'make debug' is deprecated. It will be removed in the future.\n" \ + "Please use 'make jvmg' to build debug JVM. \n" \ + "----------------------------------------------------------------------\n") + +G_SUFFIX = _g +VERSION = debug +SYSDEFS += -DASSERT -DDEBUG +PICFLAGS = DEFAULT
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/defs.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,180 @@ +# +# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# The common definitions for hotspot bsd builds. +# Include the top level defs.make under make directory instead of this one. +# This file is included into make/defs.make. + +SLASH_JAVA ?= /java + +# Need PLATFORM (os-arch combo names) for jdk and hotspot, plus libarch name +ARCH:=$(shell uname -m) +PATH_SEP = : +ifeq ($(LP64), 1) + ARCH_DATA_MODEL ?= 64 +else + ARCH_DATA_MODEL ?= 32 +endif + +# zero +ifeq ($(ZERO_BUILD), true) + ifeq ($(ARCH_DATA_MODEL), 64) + MAKE_ARGS += LP64=1 + endif + PLATFORM = bsd-zero + VM_PLATFORM = bsd_$(subst i386,i486,$(ZERO_LIBARCH)) + HS_ARCH = zero + ARCH = zero +endif + +# ia64 +ifeq ($(ARCH), ia64) + ARCH_DATA_MODEL = 64 + MAKE_ARGS += LP64=1 + PLATFORM = bsd-ia64 + VM_PLATFORM = bsd_ia64 + HS_ARCH = ia64 +endif + +# sparc +ifeq ($(ARCH), sparc64) + ifeq ($(ARCH_DATA_MODEL), 64) + ARCH_DATA_MODEL = 64 + MAKE_ARGS += LP64=1 + PLATFORM = bsd-sparcv9 + VM_PLATFORM = bsd_sparcv9 + else + ARCH_DATA_MODEL = 32 + PLATFORM = bsd-sparc + VM_PLATFORM = bsd_sparc + endif + HS_ARCH = sparc +endif + +# amd64 +ifneq (,$(findstring $(ARCH), amd64 x86_64)) + ifeq ($(ARCH_DATA_MODEL), 64) + ARCH_DATA_MODEL = 64 + MAKE_ARGS += LP64=1 + PLATFORM = bsd-amd64 + VM_PLATFORM = bsd_amd64 + HS_ARCH = x86 + else + ARCH_DATA_MODEL = 32 + PLATFORM = bsd-i586 + VM_PLATFORM = bsd_i486 + HS_ARCH = x86 + # We have to reset ARCH to i386 since SRCARCH relies on it + ARCH = i386 + endif +endif + +# i386 +ifeq ($(ARCH), i386) + ifeq ($(ARCH_DATA_MODEL), 64) + ARCH_DATA_MODEL = 64 + MAKE_ARGS += LP64=1 + PLATFORM = bsd-amd64 + VM_PLATFORM = bsd_amd64 + HS_ARCH = x86 + # We have to reset ARCH to amd64 since SRCARCH relies on it + ARCH = amd64 + else + ARCH_DATA_MODEL = 32 + PLATFORM = bsd-i586 + VM_PLATFORM = bsd_i486 + HS_ARCH = x86 + endif +endif + +# ARM +ifeq ($(ARCH), arm) + ARCH_DATA_MODEL = 32 + PLATFORM = bsd-arm + VM_PLATFORM = bsd_arm + HS_ARCH = arm +endif + +# PPC +ifeq ($(ARCH), ppc) + ARCH_DATA_MODEL = 32 + PLATFORM = bsd-ppc + VM_PLATFORM = bsd_ppc + HS_ARCH = ppc +endif + +JDK_INCLUDE_SUBDIR=bsd + +# Library suffix +OS_VENDOR:=$(shell uname -s) +ifeq ($(OS_VENDOR),Darwin) + LIBRARY_SUFFIX=dylib +else + LIBRARY_SUFFIX=so +endif + +# FIXUP: The subdirectory for a debug build is NOT the same on all platforms +VM_DEBUG=jvmg + +EXPORT_LIST += $(EXPORT_DOCS_DIR)/platform/jvmti/jvmti.html + +# client and server subdirectories have symbolic links to ../libjsig.so +EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.$(LIBRARY_SUFFIX) +EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server + +ifndef BUILD_CLIENT_ONLY +EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt +EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX) +endif + +ifneq ($(ZERO_BUILD), true) + ifeq ($(ARCH_DATA_MODEL), 32) + EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX) + endif +endif + +# Serviceability Binaries +# No SA Support for PPC, IA64, ARM or zero +ADD_SA_BINARIES/x86 = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.$(LIBRARY_SUFFIX) \ + $(EXPORT_LIB_DIR)/sa-jdi.jar +ADD_SA_BINARIES/sparc = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.$(LIBRARY_SUFFIX) \ + $(EXPORT_LIB_DIR)/sa-jdi.jar +ADD_SA_BINARIES/universal = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.$(LIBRARY_SUFFIX) \ + $(EXPORT_LIB_DIR)/sa-jdi.jar +ADD_SA_BINARIES/ppc = +ADD_SA_BINARIES/ia64 = +ADD_SA_BINARIES/arm = +ADD_SA_BINARIES/zero = + +EXPORT_LIST += $(ADD_SA_BINARIES/$(HS_ARCH)) + +UNIVERSAL_LIPO_LIST += $(EXPORT_JRE_LIB_DIR)/libjsig.$(LIBRARY_SUFFIX) +UNIVERSAL_LIPO_LIST += $(EXPORT_JRE_LIB_DIR)/libsaproc.$(LIBRARY_SUFFIX) +UNIVERSAL_LIPO_LIST += $(EXPORT_JRE_LIB_DIR)/server/libjvm.$(LIBRARY_SUFFIX) + +UNIVERSAL_COPY_LIST += $(EXPORT_JRE_LIB_DIR)/server/Xusage.txt +UNIVERSAL_COPY_LIST += $(EXPORT_JRE_LIB_DIR)/client/Xusage.txt +UNIVERSAL_COPY_LIST += $(EXPORT_JRE_LIB_DIR)/client/libjvm.$(LIBRARY_SUFFIX)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/dtrace.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,303 @@ +# +# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 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. + +ifneq ("${TYPE}", "CORE") +ifneq ("${TYPE}", "KERNEL") + +ifeq ($(OS_VENDOR), Darwin) +# we build dtrace for macosx using USDT2 probes + +DtraceOutDir = $(GENERATED)/dtracefiles + +# Bsd does not build libjvm_db, does not compile on macosx +# disabled in build: rule in vm.make +JVM_DB = libjvm_db +#LIBJVM_DB = libjvm_db.dylib +LIBJVM_DB = libjvm$(G_SUFFIX)_db.dylib + +JVM_DTRACE = jvm_dtrace +#LIBJVM_DTRACE = libjvm_dtrace.dylib +LIBJVM_DTRACE = libjvm$(G_SUFFIX)_dtrace.dylib + +JVMOFFS = JvmOffsets +JVMOFFS.o = $(JVMOFFS).o +GENOFFS = generate$(JVMOFFS) + +DTRACE_SRCDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/dtrace +DTRACE = dtrace +DTRACE.o = $(DTRACE).o + +# to remove '-g' option which causes link problems +# also '-z nodefs' is used as workaround +GENOFFS_CFLAGS = $(shell echo $(CFLAGS) | sed -e 's/ -g / /g' -e 's/ -g0 / /g';) + +ifdef LP64 +DTRACE_OPTS = -D_LP64 +endif + +# making libjvm_db + +# Use mapfile with libjvm_db.so +LIBJVM_DB_MAPFILE = # no mapfile for usdt2 # $(MAKEFILES_DIR)/mapfile-vers-jvm_db +#LFLAGS_JVM_DB += $(MAPFLAG:FILENAME=$(LIBJVM_DB_MAPFILE)) + +# Use mapfile with libjvm_dtrace.so +LIBJVM_DTRACE_MAPFILE = # no mapfile for usdt2 # $(MAKEFILES_DIR)/mapfile-vers-jvm_dtrace +#LFLAGS_JVM_DTRACE += $(MAPFLAG:FILENAME=$(LIBJVM_DTRACE_MAPFILE)) + +LFLAGS_JVM_DB += $(PICFLAG) # -D_REENTRANT +LFLAGS_JVM_DTRACE += $(PICFLAG) # -D_REENTRANT + +ISA = $(subst i386,i486,$(BUILDARCH)) + +# Making 64/libjvm_db.so: 64-bit version of libjvm_db.so which handles 32-bit libjvm.so +ifneq ("${ISA}","${BUILDARCH}") + +XLIBJVM_DB = 64/$(LIBJVM_DB) +XLIBJVM_DB_G = 64/$(LIBJVM_DB_G) +XLIBJVM_DTRACE = 64/$(LIBJVM_DTRACE) +XLIBJVM_DTRACE_G = 64/$(LIBJVM_DTRACE_G) +XARCH = $(subst sparcv9,v9,$(shell echo $(ISA))) + +$(XLIBJVM_DB): $(DTRACE_SRCDIR)/$(JVM_DB).c $(JVMOFFS).h $(LIBJVM_DB_MAPFILE) + @echo Making $@ + $(QUIETLY) mkdir -p 64/ ; \ + $(CC) $(SYMFLAG) -xarch=$(XARCH) -D$(TYPE) -I. -I$(GENERATED) \ + $(SHARED_FLAG) $(LFLAGS_JVM_DB) -o $@ $(DTRACE_SRCDIR)/$(JVM_DB).c #-lc +# [ -f $(XLIBJVM_DB_G) ] || { ln -s $(LIBJVM_DB) $(XLIBJVM_DB_G); } + +$(XLIBJVM_DTRACE): $(DTRACE_SRCDIR)/$(JVM_DTRACE).c $(DTRACE_SRCDIR)/$(JVM_DTRACE).h $(LIBJVM_DTRACE_MAPFILE) + @echo Making $@ + $(QUIETLY) mkdir -p 64/ ; \ + $(CC) $(SYMFLAG) -xarch=$(XARCH) -D$(TYPE) -I. \ + $(SHARED_FLAG) $(LFLAGS_JVM_DTRACE) -o $@ $(DTRACE_SRCDIR)/$(JVM_DTRACE).c #-lc -lthread -ldoor +# [ -f $(XLIBJVM_DTRACE_G) ] || { ln -s $(LIBJVM_DTRACE) $(XLIBJVM_DTRACE_G); } + +endif # ifneq ("${ISA}","${BUILDARCH}") + +LFLAGS_GENOFFS += -L. + +lib$(GENOFFS).dylib: $(DTRACE_SRCDIR)/$(GENOFFS).cpp $(DTRACE_SRCDIR)/$(GENOFFS).h \ + $(LIBJVM.o) + $(QUIETLY) $(CCC) $(CPPFLAGS) $(GENOFFS_CFLAGS) $(SHARED_FLAG) $(PICFLAG) \ + $(LFLAGS_GENOFFS) -o $@ $(DTRACE_SRCDIR)/$(GENOFFS).cpp -ljvm + +$(GENOFFS): $(DTRACE_SRCDIR)/$(GENOFFS)Main.c lib$(GENOFFS).dylib + $(QUIETLY) $(LINK.CC) -o $@ $(DTRACE_SRCDIR)/$(GENOFFS)Main.c \ + ./lib$(GENOFFS).dylib + +# $@.tmp is created first to avoid an empty $(JVMOFFS).h if an error occurs. +$(JVMOFFS).h: $(GENOFFS) + $(QUIETLY) DYLD_LIBRARY_PATH=. ./$(GENOFFS) -header > $@.tmp; touch $@; \ + if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \ + then rm -f $@; mv $@.tmp $@; \ + else rm -f $@.tmp; \ + fi + +$(JVMOFFS)Index.h: $(GENOFFS) + $(QUIETLY) DYLD_LIBRARY_PATH=. ./$(GENOFFS) -index > $@.tmp; touch $@; \ + if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \ + then rm -f $@; mv $@.tmp $@; \ + else rm -f $@.tmp; \ + fi + +$(JVMOFFS).cpp: $(GENOFFS) $(JVMOFFS).h $(JVMOFFS)Index.h + $(QUIETLY) DYLD_LIBRARY_PATH=. ./$(GENOFFS) -table > $@.tmp; touch $@; \ + if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \ + then rm -f $@; mv $@.tmp $@; \ + else rm -f $@.tmp; \ + fi + +$(JVMOFFS.o): $(JVMOFFS).h $(JVMOFFS).cpp + $(QUIETLY) $(CCC) -c -I. -o $@ $(ARCHFLAG) -D$(TYPE) $(JVMOFFS).cpp + +$(LIBJVM_DB): $(DTRACE_SRCDIR)/$(JVM_DB).c $(JVMOFFS.o) $(XLIBJVM_DB) $(LIBJVM_DB_MAPFILE) + @echo Making $@ + $(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) -D$(TYPE) -I. -I$(GENERATED) \ + $(SHARED_FLAG) $(LFLAGS_JVM_DB) -o $@ $(DTRACE_SRCDIR)/$(JVM_DB).c -Wall # -lc +# [ -f $(LIBJVM_DB_G) ] || { ln -s $@ $(LIBJVM_DB_G); } + +$(LIBJVM_DTRACE): $(DTRACE_SRCDIR)/$(JVM_DTRACE).c $(XLIBJVM_DTRACE) $(DTRACE_SRCDIR)/$(JVM_DTRACE).h $(LIBJVM_DTRACE_MAPFILE) + @echo Making $@ + $(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) -D$(TYPE) -I. \ + $(SHARED_FLAG) $(LFLAGS_JVM_DTRACE) -o $@ $(DTRACE_SRCDIR)/$(JVM_DTRACE).c #-lc -lthread -ldoor +# [ -f $(LIBJVM_DTRACE_G) ] || { ln -s $@ $(LIBJVM_DTRACE_G); } + +#$(DTRACE).d: $(DTRACE_SRCDIR)/hotspot.d $(DTRACE_SRCDIR)/hotspot_jni.d \ +# $(DTRACE_SRCDIR)/hs_private.d $(DTRACE_SRCDIR)/jhelper.d +# $(QUIETLY) cat $^ > $@ + +$(DtraceOutDir): + mkdir $(DtraceOutDir) + +$(DtraceOutDir)/hotspot.h: $(DTRACE_SRCDIR)/hotspot.d | $(DtraceOutDir) + $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_SRCDIR)/hotspot.d + +$(DtraceOutDir)/hotspot_jni.h: $(DTRACE_SRCDIR)/hotspot_jni.d | $(DtraceOutDir) + $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_SRCDIR)/hotspot_jni.d + +$(DtraceOutDir)/hs_private.h: $(DTRACE_SRCDIR)/hs_private.d | $(DtraceOutDir) + $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_SRCDIR)/hs_private.d + +$(DtraceOutDir)/jhelper.h: $(DTRACE_SRCDIR)/jhelper.d $(JVMOFFS).o | $(DtraceOutDir) + $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_SRCDIR)/jhelper.d + +# jhelper currently disabled +dtrace_gen_headers: $(DtraceOutDir)/hotspot.h $(DtraceOutDir)/hotspot_jni.h $(DtraceOutDir)/hs_private.h + +DTraced_Files = ciEnv.o \ + classLoadingService.o \ + compileBroker.o \ + hashtable.o \ + instanceKlass.o \ + java.o \ + jni.o \ + jvm.o \ + memoryManager.o \ + nmethod.o \ + objectMonitor.o \ + runtimeService.o \ + sharedRuntime.o \ + synchronizer.o \ + thread.o \ + unsafe.o \ + vmThread.o \ + vmCMSOperations.o \ + vmPSOperations.o \ + vmGCOperations.o \ + +# Dtrace is available, so we build $(DTRACE.o) +#$(DTRACE.o): $(DTRACE).d $(JVMOFFS).h $(JVMOFFS)Index.h $(DTraced_Files) +# @echo Compiling $(DTRACE).d + +# $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -G -xlazyload -o $@ -s $(DTRACE).d \ +# $(DTraced_Files) ||\ +# STATUS=$$?;\ +# if [ x"$$STATUS" = x"1" -a \ +# x`uname -r` = x"5.10" -a \ +# x`uname -p` = x"sparc" ]; then\ +# echo "*****************************************************************";\ +# echo "* If you are building server compiler, and the error message is ";\ +# echo "* \"incorrect ELF machine type...\", you have run into solaris bug ";\ +# echo "* 6213962, \"dtrace -G doesn't work on sparcv8+ object files\".";\ +# echo "* Either patch/upgrade your system (>= S10u1_15), or set the ";\ +# echo "* environment variable HOTSPOT_DISABLE_DTRACE_PROBES to disable ";\ +# echo "* dtrace probes for this build.";\ +# echo "*****************************************************************";\ +# fi;\ +# exit $$STATUS + # Since some DTraced_Files are in LIBJVM.o and they are touched by this + # command, and libgenerateJvmOffsets.so depends on LIBJVM.o, 'make' will + # think it needs to rebuild libgenerateJvmOffsets.so and thus JvmOffsets* + # files, but it doesn't, so we touch the necessary files to prevent later + # recompilation. Note: we only touch the necessary files if they already + # exist in order to close a race where an empty file can be created + # before the real build rule is executed. + # But, we can't touch the *.h files: This rule depends + # on them, and that would cause an infinite cycle of rebuilding. + # Neither the *.h or *.ccp files need to be touched, since they have + # rules which do not update them when the generator file has not + # changed their contents. +# $(QUIETLY) if [ -f lib$(GENOFFS).so ]; then touch lib$(GENOFFS).so; fi +# $(QUIETLY) if [ -f $(GENOFFS) ]; then touch $(GENOFFS); fi +# $(QUIETLY) if [ -f $(JVMOFFS.o) ]; then touch $(JVMOFFS.o); fi + +.PHONY: dtraceCheck + +#SYSTEM_DTRACE_H = /usr/include/dtrace.h +SYSTEM_DTRACE_PROG = /usr/sbin/dtrace +#PATCH_DTRACE_PROG = /opt/SUNWdtrd/sbin/dtrace +systemDtraceFound := $(wildcard ${SYSTEM_DTRACE_PROG}) +#patchDtraceFound := $(wildcard ${PATCH_DTRACE_PROG}) +#systemDtraceHdrFound := $(wildcard $(SYSTEM_DTRACE_H)) + +#ifneq ("$(systemDtraceHdrFound)", "") +#CFLAGS += -DHAVE_DTRACE_H +#endif + +#ifneq ("$(patchDtraceFound)", "") +#DTRACE_PROG=$(PATCH_DTRACE_PROG) +#DTRACE_INCL=-I/opt/SUNWdtrd/include +#else +ifneq ("$(systemDtraceFound)", "") +DTRACE_PROG=$(SYSTEM_DTRACE_PROG) +else + +endif # ifneq ("$(systemDtraceFound)", "") +#endif # ifneq ("$(patchDtraceFound)", "") + +ifneq ("${DTRACE_PROG}", "") +ifeq ("${HOTSPOT_DISABLE_DTRACE_PROBES}", "") + +DTRACE_OBJS = $(DTRACE.o) #$(JVMOFFS.o) +CFLAGS += -DDTRACE_ENABLED #$(DTRACE_INCL) +#clangCFLAGS += -DDTRACE_ENABLED -fno-optimize-sibling-calls +#MAPFILE_DTRACE_OPT = $(MAPFILE_DTRACE) + + +dtraceCheck: + +dtrace_stuff: dtrace_gen_headers + $(QUIETLY) echo "dtrace headers generated" + + +else # manually disabled + +dtraceCheck: + $(QUIETLY) echo "**NOTICE** Dtrace support disabled via environment variable" + +dtrace_stuff: + +endif # ifeq ("${HOTSPOT_DISABLE_DTRACE_PROBES}", "") + +else # No dtrace program found + +dtraceCheck: + $(QUIETLY) echo "**NOTICE** Dtrace support disabled: not supported by system" + +dtrace_stuff: + +endif # ifneq ("${dtraceFound}", "") + +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: + $(QUIETLY) echo "**NOTICE** Dtrace support disabled for CORE builds" + +endif # ifneq ("${TYPE}", "CORE")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/fastdebug.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,64 @@ +# +# Copyright (c) 1999, 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. +# +# + +# Sets make macros for making debug version of VM + +# Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make +OPT_CFLAGS/DEFAULT= $(OPT_CFLAGS) +OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@)) + +# (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files) + +ifeq ($(BUILDARCH), ia64) + # Bug in GCC, causes hang. -O1 will override the -O3 specified earlier + OPT_CFLAGS/callGenerator.o += -O1 + OPT_CFLAGS/ciTypeFlow.o += -O1 + OPT_CFLAGS/compile.o += -O1 + OPT_CFLAGS/concurrentMarkSweepGeneration.o += -O1 + OPT_CFLAGS/doCall.o += -O1 + OPT_CFLAGS/generateOopMap.o += -O1 + OPT_CFLAGS/generateOptoStub.o += -O1 + OPT_CFLAGS/graphKit.o += -O1 + OPT_CFLAGS/instanceKlass.o += -O1 + OPT_CFLAGS/interpreterRT_ia64.o += -O1 + OPT_CFLAGS/output.o += -O1 + OPT_CFLAGS/parse1.o += -O1 + OPT_CFLAGS/runtime.o += -O1 + OPT_CFLAGS/synchronizer.o += -O1 +endif + + +# If you set HOTSPARC_GENERIC=yes, you disable all OPT_CFLAGS settings +CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE) + +# Set the environment variable HOTSPARC_GENERIC to "true" +# to inhibit the effect of the previous line on CFLAGS. + +# Linker mapfile +MAPFILE = $(GAMMADIR)/make/bsd/makefiles/mapfile-vers-debug + +G_SUFFIX = _g +VERSION = optimized +SYSDEFS += -DASSERT -DFASTDEBUG +PICFLAGS = DEFAULT
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/gcc.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,307 @@ +# +# Copyright (c) 1999, 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. +# +# + +OS_VENDOR = $(shell uname -s) + +#------------------------------------------------------------------------ +# CC, CPP & AS + +# When cross-compiling the ALT_COMPILER_PATH points +# to the cross-compilation toolset +ifdef CROSS_COMPILE_ARCH + CPP = $(ALT_COMPILER_PATH)/g++ + CC = $(ALT_COMPILER_PATH)/gcc + HOSTCPP = g++ + HOSTCC = gcc +else ifneq ($(OS_VENDOR), Darwin) + CXX = g++ + CPP = $(CXX) + CC = gcc + HOSTCPP = $(CPP) + HOSTCC = $(CC) +endif + +# i486 hotspot requires -mstackrealign on Darwin. +# llvm-gcc supports this in Xcode 3.2.6 and 4.0. +# gcc-4.0 supports this on earlier versions. +# Prefer llvm-gcc where available. +ifeq ($(OS_VENDOR), Darwin) + ifeq ($(origin CXX), default) + CXX = llvm-g++ + endif + ifeq ($(origin CC), default) + CC = llvm-gcc + endif + CPP = $(CXX) + + ifeq ($(ARCH), i486) + LLVM_SUPPORTS_STACKREALIGN := $(shell \ + [ "0"`llvm-gcc -v 2>&1 | grep LLVM | sed -E "s/.*LLVM build ([0-9]+).*/\1/"` -gt "2333" ] \ + && echo true || echo false) + + ifeq ($(LLVM_SUPPORTS_STACKREALIGN), true) + CXX32 ?= llvm-g++ + CC32 ?= llvm-gcc + else + CXX32 ?= g++-4.0 + CC32 ?= gcc-4.0 + endif + CPP = $(CXX32) + CC = $(CC32) + endif + + HOSTCPP = $(CPP) + HOSTCC = $(CC) +endif + +AS = $(CC) -c -x assembler-with-cpp + +# -dumpversion in gcc-2.91 shows "egcs-2.91.66". In later version, it only +# prints the numbers (e.g. "2.95", "3.2.1") +CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1) +CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2) + +# check for precompiled headers support +ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) \| \( \( $(CC_VER_MAJOR) = 3 \) \& \( $(CC_VER_MINOR) \>= 4 \) \))" "0" +# Allow the user to turn off precompiled headers from the command line. +ifneq ($(USE_PRECOMPILED_HEADER),0) +USE_PRECOMPILED_HEADER=1 +PRECOMPILED_HEADER_DIR=. +PRECOMPILED_HEADER_SRC=$(GAMMADIR)/src/share/vm/precompiled.hpp +PRECOMPILED_HEADER=$(PRECOMPILED_HEADER_DIR)/precompiled.hpp.gch +endif +endif + + +#------------------------------------------------------------------------ +# Compiler flags + +# position-independent code +PICFLAG = -fPIC + +VM_PICFLAG/LIBJVM = $(PICFLAG) +VM_PICFLAG/AOUT = +VM_PICFLAG = $(VM_PICFLAG/$(LINK_INTO)) + +ifeq ($(ZERO_BUILD), true) +CFLAGS += $(LIBFFI_CFLAGS) +endif +ifeq ($(SHARK_BUILD), true) +CFLAGS += $(LLVM_CFLAGS) +endif +CFLAGS += $(VM_PICFLAG) +CFLAGS += -fno-rtti +CFLAGS += -fno-exceptions +CFLAGS += -pthread +CFLAGS += -fcheck-new +# version 4 and above support fvisibility=hidden (matches jni_x86.h file) +# except 4.1.2 gives pointless warnings that can't be disabled (afaik) +ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0" +CFLAGS += -fvisibility=hidden +endif + +ARCHFLAG = $(ARCHFLAG/$(BUILDARCH)) +ARCHFLAG/i486 = -m32 -march=i586 +ARCHFLAG/amd64 = -m64 +ARCHFLAG/ia64 = +ARCHFLAG/sparc = -m32 -mcpu=v9 +ARCHFLAG/sparcv9 = -m64 -mcpu=v9 +ARCHFLAG/zero = $(ZERO_ARCHFLAG) + +# Darwin-specific build flags +ifeq ($(OS_VENDOR), Darwin) + # Ineffecient 16-byte stack re-alignment on Darwin/IA32 + ARCHFLAG/i486 += -mstackrealign +endif + +CFLAGS += $(ARCHFLAG) +AOUT_FLAGS += $(ARCHFLAG) +LFLAGS += $(ARCHFLAG) +ASFLAGS += $(ARCHFLAG) + +ifdef E500V2 +CFLAGS += -DE500V2 +endif + +# Use C++ Interpreter +ifdef CC_INTERP + CFLAGS += -DCC_INTERP +endif + +# Build for embedded targets +ifdef JAVASE_EMBEDDED + CFLAGS += -DJAVASE_EMBEDDED +endif + +# Keep temporary files (.ii, .s) +ifdef NEED_ASM + CFLAGS += -save-temps +else + CFLAGS += -pipe +endif + +# Compiler warnings are treated as errors +ifneq ($(COMPILER_WARNINGS_FATAL),false) + WARNINGS_ARE_ERRORS = -Werror +endif + +# Except for a few acceptable ones +# Since GCC 4.3, -Wconversion has changed its meanings to warn these implicit +# conversions which might affect the values. To avoid that, we need to turn +# it off explicitly. +ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0" +ACCEPTABLE_WARNINGS = -Wpointer-arith -Wsign-compare +else +ACCEPTABLE_WARNINGS = -Wpointer-arith -Wconversion -Wsign-compare +endif + +CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(ACCEPTABLE_WARNINGS) +# Special cases +CFLAGS_WARN/BYFILE = $(CFLAGS_WARN/$@)$(CFLAGS_WARN/DEFAULT$(CFLAGS_WARN/$@)) +# XXXDARWIN: for _dyld_bind_fully_image_containing_address +ifeq ($(OS_VENDOR), Darwin) + CFLAGS_WARN/os_bsd.o = $(CFLAGS_WARN/DEFAULT) -Wno-deprecated-declarations +endif + + +# The flags to use for an Optimized g++ build +ifeq ($(OS_VENDOR), Darwin) + # use -Os by default, unless -O3 can be proved to be worth the cost, as per policy + # <http://wikis.sun.com/display/OpenJDK/Mac+OS+X+Port+Compilers> + OPT_CFLAGS += -Os +else + OPT_CFLAGS += -O3 +endif + +# Hotspot uses very unstrict aliasing turn this optimization off +OPT_CFLAGS += -fno-strict-aliasing + +# The gcc compiler segv's on ia64 when compiling bytecodeInterpreter.cpp +# if we use expensive-optimizations +ifeq ($(BUILDARCH), ia64) +OPT_CFLAGS += -fno-expensive-optimizations +endif + +OPT_CFLAGS/NOOPT=-O0 + +# 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation. +ifneq "$(shell expr \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) = 3 \) \))" "0" +OPT_CFLAGS/mulnode.o += -O0 +endif + +# Flags for generating make dependency flags. +ifneq ("${CC_VER_MAJOR}", "2") +DEPFLAGS = -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d) +endif + +# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp. +ifneq ($(USE_PRECOMPILED_HEADER),1) +CFLAGS += -DDONT_USE_PRECOMPILED_HEADER +endif + +#------------------------------------------------------------------------ +# Linker flags + +# statically link libstdc++.so, work with gcc but ignored by g++ +STATIC_STDCXX = -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic + +# statically link libgcc and/or libgcc_s, libgcc does not exist before gcc-3.x. +ifneq ("${CC_VER_MAJOR}", "2") +STATIC_LIBGCC += -static-libgcc +endif + +ifeq ($(BUILDARCH), ia64) +LFLAGS += -Wl,-relax +endif + +# Use $(MAPFLAG:FILENAME=real_file_name) to specify a map file. +MAPFLAG = -Xlinker --version-script=FILENAME + +# +# Shared Library +# +ifeq ($(OS_VENDOR), Darwin) + # Standard linker flags + LFLAGS += + + # Darwin doesn't use ELF and doesn't support version scripts + LDNOMAP = true + + # Use $(SONAMEFLAG:SONAME=soname) to specify the intrinsic name of a shared obj + SONAMEFLAG = + + # Build shared library + SHARED_FLAG = -Wl,-install_name,@rpath/$(@F) -dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $(VM_PICFLAG) + + # Keep symbols even they are not used + #AOUT_FLAGS += -Xlinker -export-dynamic +else + # Enable linker optimization + LFLAGS += -Xlinker -O1 + + # Use $(SONAMEFLAG:SONAME=soname) to specify the intrinsic name of a shared obj + SONAMEFLAG = -Xlinker -soname=SONAME + + # Build shared library + SHARED_FLAG = -shared $(VM_PICFLAG) + + # Keep symbols even they are not used + AOUT_FLAGS += -Xlinker -export-dynamic +endif + +#------------------------------------------------------------------------ +# Debug flags + +# Use the stabs format for debugging information (this is the default +# on gcc-2.91). It's good enough, has all the information about line +# numbers and local variables, and libjvm_g.so is only about 16M. +# Change this back to "-g" if you want the most expressive format. +# (warning: that could easily inflate libjvm_g.so to 150M!) +# Note: The Itanium gcc compiler crashes when using -gstabs. +DEBUG_CFLAGS/ia64 = -g +DEBUG_CFLAGS/amd64 = -g +DEBUG_CFLAGS/arm = -g +DEBUG_CFLAGS/ppc = -g +DEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH)) +ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),) +DEBUG_CFLAGS += -gstabs +endif + +# DEBUG_BINARIES overrides everything, use full -g debug information +ifeq ($(DEBUG_BINARIES), true) + DEBUG_CFLAGS = -g + CFLAGS += $(DEBUG_CFLAGS) +endif + +# If we are building HEADLESS, pass on to VM +# so it can set the java.awt.headless property +ifdef HEADLESS +CFLAGS += -DHEADLESS +endif + +# We are building Embedded for a small device +# favor code space over speed +ifdef MINIMIZE_RAM_USAGE +CFLAGS += -DMINIMIZE_RAM_USAGE +endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/hp.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,29 @@ +# +# Copyright (c) 1999, 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. +# +# + +# Sets make macros for making premium version of VM + +TYPE=HP + +CFLAGS += -DCOMPILER2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/hp1.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,29 @@ +# +# Copyright (c) 1999, 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. +# +# + +# Sets make macros for making premium version of VM + +TYPE=HP1 + +CFLAGS += -DCOMPILER1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/i486.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,34 @@ +# +# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# TLS helper, assembled from .s file + +# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized +OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT) +# The copied fdlibm routines in sharedRuntimeTrans.o must not be optimized +OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT) +# Must also specify if CPU is little endian +CFLAGS += -DVM_LITTLE_ENDIAN + +OPT_CFLAGS/compactingPermGenGen.o = -O1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/ia64.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,43 @@ +# +# Copyright (c) 2005, 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. +# +# + +# +# IA64 only uses c++ based interpreter +CFLAGS += -DCC_INTERP -D_LP64=1 -DVM_LITTLE_ENDIAN +# Hotspot uses very unstrict aliasing turn this optimization off +OPT_CFLAGS += -fno-strict-aliasing +ifeq ($(VERSION),debug) +ASM_FLAGS= -DDEBUG +else +ASM_FLAGS= +endif +# workaround gcc bug in compiling varargs +OPT_CFLAGS/jni.o = -O0 + +# gcc/ia64 has a bug that internal gcc functions linked with libjvm.so +# are made public. Hiding those symbols will cause undefined symbol error +# when VM is dropped into older JDK. We probably will need an IA64 +# mapfile to include those symbols as a workaround. Disable linker mapfile +# for now. +LDNOMAP=true
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/jsig.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,67 @@ +# +# Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 signal interposition library, used by vm.make + +# libjsig[_g].so: signal interposition library +JSIG = jsig +JSIG_G = $(JSIG)$(G_SUFFIX) + +ifeq ($(OS_VENDOR), Darwin) + LIBJSIG = lib$(JSIG).dylib + LIBJSIG_G = lib$(JSIG_G).dylib +else + LIBJSIG = lib$(JSIG).so + LIBJSIG_G = lib$(JSIG_G).so +endif + +JSIGSRCDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/vm + +DEST_JSIG = $(JDK_LIBDIR)/$(LIBJSIG) + +LIBJSIG_MAPFILE = $(MAKEFILES_DIR)/mapfile-vers-jsig + +# On Bsd we really dont want a mapfile, as this library is small +# and preloaded using LD_PRELOAD, making functions private will +# cause problems with interposing. See CR: 6466665 +# LFLAGS_JSIG += $(MAPFLAG:FILENAME=$(LIBJSIG_MAPFILE)) + +LFLAGS_JSIG += -D_GNU_SOURCE -pthread $(LDFLAGS_HASH_STYLE) + +# DEBUG_BINARIES overrides everything, use full -g debug information +ifeq ($(DEBUG_BINARIES), true) + JSIG_DEBUG_CFLAGS = -g +endif + +$(LIBJSIG): $(JSIGSRCDIR)/jsig.c $(LIBJSIG_MAPFILE) + @echo Making signal interposition lib... + $(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \ + $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) -o $@ $< + $(QUIETLY) [ -f $(LIBJSIG_G) ] || { ln -s $@ $(LIBJSIG_G); } + +install_jsig: $(LIBJSIG) + @echo "Copying $(LIBJSIG) to $(DEST_JSIG)" + $(QUIETLY) cp -f $(LIBJSIG) $(DEST_JSIG) && echo "Done" + +.PHONY: install_jsig
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/jvmg.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,41 @@ +# +# Copyright (c) 1999, 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. +# +# + +# Sets make macros for making debug version of VM + +# Compiler specific DEBUG_CFLAGS are passed in from gcc.make, sparcWorks.make +DEBUG_CFLAGS/DEFAULT= $(DEBUG_CFLAGS) +DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@)) +CFLAGS += $(DEBUG_CFLAGS/BYFILE) + +# Set the environment variable HOTSPARC_GENERIC to "true" +# to inhibit the effect of the previous line on CFLAGS. + +# Linker mapfile +MAPFILE = $(GAMMADIR)/make/bsd/makefiles/mapfile-vers-debug + +G_SUFFIX = _g +VERSION = debug +SYSDEFS += -DASSERT -DDEBUG +PICFLAGS = DEFAULT
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/jvmti.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,117 @@ +# +# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 (jvmti.make) is included from the jvmti.make in the +# build directories. +# +# It knows how to build and run the tools to generate jvmti. + +include $(GAMMADIR)/make/bsd/makefiles/rules.make + +# ######################################################################### + +TOPDIR = $(shell echo `pwd`) +GENERATED = $(TOPDIR)/../generated +JvmtiOutDir = $(GENERATED)/jvmtifiles + +JvmtiSrcDir = $(GAMMADIR)/src/share/vm/prims +InterpreterSrcDir = $(GAMMADIR)/src/share/vm/interpreter + +# set VPATH so make knows where to look for source files +Src_Dirs_V += $(JvmtiSrcDir) +VPATH += $(Src_Dirs_V:%=%:) + +JvmtiGeneratedNames = \ + jvmtiEnv.hpp \ + jvmtiEnter.cpp \ + jvmtiEnterTrace.cpp \ + jvmtiEnvRecommended.cpp \ + bytecodeInterpreterWithChecks.cpp \ + jvmti.h \ + +JvmtiEnvFillSource = $(JvmtiSrcDir)/jvmtiEnvFill.java +JvmtiEnvFillClass = $(JvmtiOutDir)/jvmtiEnvFill.class + +JvmtiGenSource = $(JvmtiSrcDir)/jvmtiGen.java +JvmtiGenClass = $(JvmtiOutDir)/jvmtiGen.class + +JvmtiGeneratedFiles = $(JvmtiGeneratedNames:%=$(JvmtiOutDir)/%) + +XSLT = $(QUIETLY) $(REMOTE) $(RUN.JAVA) -classpath $(JvmtiOutDir) jvmtiGen + +.PHONY: all jvmtidocs clean cleanall + +# ######################################################################### + +all: $(JvmtiGeneratedFiles) + +both = $(JvmtiGenClass) $(JvmtiSrcDir)/jvmti.xml $(JvmtiSrcDir)/jvmtiLib.xsl + +$(JvmtiGenClass): $(JvmtiGenSource) + $(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -d $(JvmtiOutDir) $(JvmtiGenSource) + +$(JvmtiEnvFillClass): $(JvmtiEnvFillSource) + $(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -d $(JvmtiOutDir) $(JvmtiEnvFillSource) + +$(JvmtiOutDir)/jvmtiEnter.cpp: $(both) $(JvmtiSrcDir)/jvmtiEnter.xsl + @echo Generating $@ + $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmtiEnter.xsl -OUT $(JvmtiOutDir)/jvmtiEnter.cpp -PARAM interface jvmti + +$(JvmtiOutDir)/bytecodeInterpreterWithChecks.cpp: $(JvmtiGenClass) $(InterpreterSrcDir)/bytecodeInterpreter.cpp $(InterpreterSrcDir)/bytecodeInterpreterWithChecks.xml $(InterpreterSrcDir)/bytecodeInterpreterWithChecks.xsl + @echo Generating $@ + $(XSLT) -IN $(InterpreterSrcDir)/bytecodeInterpreterWithChecks.xml -XSL $(InterpreterSrcDir)/bytecodeInterpreterWithChecks.xsl -OUT $(JvmtiOutDir)/bytecodeInterpreterWithChecks.cpp + +$(JvmtiOutDir)/jvmtiEnterTrace.cpp: $(both) $(JvmtiSrcDir)/jvmtiEnter.xsl + @echo Generating $@ + $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmtiEnter.xsl -OUT $(JvmtiOutDir)/jvmtiEnterTrace.cpp -PARAM interface jvmti -PARAM trace Trace + +$(JvmtiOutDir)/jvmtiEnvRecommended.cpp: $(both) $(JvmtiSrcDir)/jvmtiEnv.xsl $(JvmtiSrcDir)/jvmtiEnv.cpp $(JvmtiEnvFillClass) + @echo Generating $@ + $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmtiEnv.xsl -OUT $(JvmtiOutDir)/jvmtiEnvStub.cpp + $(QUIETLY) $(REMOTE) $(RUN.JAVA) -classpath $(JvmtiOutDir) jvmtiEnvFill $(JvmtiSrcDir)/jvmtiEnv.cpp $(JvmtiOutDir)/jvmtiEnvStub.cpp $(JvmtiOutDir)/jvmtiEnvRecommended.cpp + +$(JvmtiOutDir)/jvmtiEnv.hpp: $(both) $(JvmtiSrcDir)/jvmtiHpp.xsl + @echo Generating $@ + $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmtiHpp.xsl -OUT $(JvmtiOutDir)/jvmtiEnv.hpp + +$(JvmtiOutDir)/jvmti.h: $(both) $(JvmtiSrcDir)/jvmtiH.xsl + @echo Generating $@ + $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmtiH.xsl -OUT $(JvmtiOutDir)/jvmti.h + +jvmtidocs: $(JvmtiOutDir)/jvmti.html + +$(JvmtiOutDir)/jvmti.html: $(both) $(JvmtiSrcDir)/jvmti.xsl + @echo Generating $@ + $(XSLT) -IN $(JvmtiSrcDir)/jvmti.xml -XSL $(JvmtiSrcDir)/jvmti.xsl -OUT $(JvmtiOutDir)/jvmti.html + +# ######################################################################### + +clean : + rm $(JvmtiGenClass) $(JvmtiEnvFillClass) $(JvmtiGeneratedFiles) + +cleanall : + rm $(JvmtiGenClass) $(JvmtiEnvFillClass) $(JvmtiGeneratedFiles) + +# ######################################################################### +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/launcher.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,93 @@ +# +# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 gamma launcher, used by vm.make + + +LAUNCHER_SCRIPT = hotspot +LAUNCHER = gamma + +LAUNCHERDIR := $(GAMMADIR)/src/os/posix/launcher +LAUNCHERDIR_SHARE := $(GAMMADIR)/src/share/tools/launcher +LAUNCHERFLAGS := $(ARCHFLAG) \ + -I$(LAUNCHERDIR) -I$(GAMMADIR)/src/share/vm/prims \ + -I$(LAUNCHERDIR_SHARE) \ + -DFULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \ + -DJDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \ + -DJDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \ + -DARCH=\"$(LIBARCH)\" \ + -DGAMMA \ + -DLAUNCHER_TYPE=\"gamma\" \ + -DLINK_INTO_$(LINK_INTO) \ + $(TARGET_DEFINES) + +ifeq ($(LINK_INTO),AOUT) + LAUNCHER.o = launcher.o $(JVM_OBJ_FILES) + LAUNCHER_MAPFILE = mapfile_reorder + LFLAGS_LAUNCHER$(LDNOMAP) += $(MAPFLAG:FILENAME=$(LAUNCHER_MAPFILE)) + LFLAGS_LAUNCHER += $(SONAMEFLAG:SONAME=$(LIBJVM)) $(STATIC_LIBGCC) + LIBS_LAUNCHER += $(STATIC_STDCXX) $(LIBS) +else + LAUNCHER.o = launcher.o + LFLAGS_LAUNCHER += -L`pwd` + LIBS_LAUNCHER += -l$(JVM) $(LIBS) +endif + +LINK_LAUNCHER = $(LINK.c) + +LINK_LAUNCHER/PRE_HOOK = $(LINK_LIB.CC/PRE_HOOK) +LINK_LAUNCHER/POST_HOOK = $(LINK_LIB.CC/POST_HOOK) + +LAUNCHER_OUT = launcher + +SUFFIXES += .d + +SOURCES := $(shell find $(LAUNCHERDIR) -name "*.c") +SOURCES_SHARE := $(shell find $(LAUNCHERDIR_SHARE) -name "*.c") + +OBJS := $(patsubst $(LAUNCHERDIR)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES)) $(patsubst $(LAUNCHERDIR_SHARE)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES_SHARE)) + +DEPFILES := $(patsubst %.o,%.d,$(OBJS)) +-include $(DEPFILES) + +$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR_SHARE)/%.c + $(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); } + $(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CPPFLAGS) + +$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR)/%.c + $(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); } + $(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CPPFLAGS) + +$(LAUNCHER): $(OBJS) $(LIBJVM) $(LAUNCHER_MAPFILE) + $(QUIETLY) echo Linking launcher... + $(QUIETLY) $(LINK_LAUNCHER/PRE_HOOK) + $(QUIETLY) $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(OBJS) $(LIBS_LAUNCHER) + $(QUIETLY) $(LINK_LAUNCHER/POST_HOOK) + +$(LAUNCHER): $(LAUNCHER_SCRIPT) + +$(LAUNCHER_SCRIPT): $(LAUNCHERDIR)/launcher.script + $(QUIETLY) sed -e 's/@@LIBARCH@@/$(LIBARCH)/g' $< > $@ + $(QUIETLY) chmod +x $@ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/mapfile-vers-debug Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,291 @@ +# +# @(#)mapfile-vers-debug 1.18 07/10/25 16:47:35 +# + +# +# Copyright (c) 2002, 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. +# +# + +# Define public interface. + +SUNWprivate_1.1 { + global: + # JNI + JNI_CreateJavaVM; + JNI_GetCreatedJavaVMs; + JNI_GetDefaultJavaVMInitArgs; + + # JVM + JVM_Accept; + JVM_ActiveProcessorCount; + JVM_AllocateNewArray; + JVM_AllocateNewObject; + JVM_ArrayCopy; + JVM_AssertionStatusDirectives; + JVM_Available; + JVM_Bind; + JVM_ClassDepth; + JVM_ClassLoaderDepth; + JVM_Clone; + JVM_Close; + JVM_CX8Field; + JVM_CompileClass; + JVM_CompileClasses; + JVM_CompilerCommand; + JVM_Connect; + JVM_ConstantPoolGetClassAt; + JVM_ConstantPoolGetClassAtIfLoaded; + JVM_ConstantPoolGetDoubleAt; + JVM_ConstantPoolGetFieldAt; + JVM_ConstantPoolGetFieldAtIfLoaded; + JVM_ConstantPoolGetFloatAt; + JVM_ConstantPoolGetIntAt; + JVM_ConstantPoolGetLongAt; + JVM_ConstantPoolGetMethodAt; + JVM_ConstantPoolGetMethodAtIfLoaded; + JVM_ConstantPoolGetMemberRefInfoAt; + JVM_ConstantPoolGetSize; + JVM_ConstantPoolGetStringAt; + JVM_ConstantPoolGetUTF8At; + JVM_CountStackFrames; + JVM_CurrentClassLoader; + JVM_CurrentLoadedClass; + JVM_CurrentThread; + JVM_CurrentTimeMillis; + JVM_DefineClass; + JVM_DefineClassWithSource; + JVM_DefineClassWithSourceCond; + JVM_DesiredAssertionStatus; + JVM_DisableCompiler; + JVM_DoPrivileged; + JVM_DTraceGetVersion; + JVM_DTraceActivate; + JVM_DTraceIsProbeEnabled; + JVM_DTraceIsSupported; + JVM_DTraceDispose; + JVM_DumpAllStacks; + JVM_DumpThreads; + JVM_EnableCompiler; + JVM_Exit; + JVM_FillInStackTrace; + JVM_FindClassFromClass; + JVM_FindClassFromClassLoader; + JVM_FindClassFromBootLoader; + JVM_FindLibraryEntry; + JVM_FindLoadedClass; + JVM_FindPrimitiveClass; + JVM_FindSignal; + JVM_FreeMemory; + JVM_GC; + JVM_GetAllThreads; + JVM_GetArrayElement; + JVM_GetArrayLength; + JVM_GetCPClassNameUTF; + JVM_GetCPFieldClassNameUTF; + JVM_GetCPFieldModifiers; + JVM_GetCPFieldNameUTF; + JVM_GetCPFieldSignatureUTF; + JVM_GetCPMethodClassNameUTF; + JVM_GetCPMethodModifiers; + JVM_GetCPMethodNameUTF; + JVM_GetCPMethodSignatureUTF; + JVM_GetCallerClass; + JVM_GetClassAccessFlags; + JVM_GetClassAnnotations; + JVM_GetClassCPEntriesCount; + JVM_GetClassCPTypes; + JVM_GetClassConstantPool; + JVM_GetClassContext; + JVM_GetClassDeclaredConstructors; + JVM_GetClassDeclaredFields; + JVM_GetClassDeclaredMethods; + JVM_GetClassFieldsCount; + JVM_GetClassInterfaces; + JVM_GetClassLoader; + JVM_GetClassMethodsCount; + JVM_GetClassModifiers; + JVM_GetClassName; + JVM_GetClassNameUTF; + JVM_GetClassSignature; + JVM_GetClassSigners; + JVM_GetComponentType; + JVM_GetDeclaredClasses; + JVM_GetDeclaringClass; + JVM_GetEnclosingMethodInfo; + JVM_GetFieldAnnotations; + JVM_GetFieldIxModifiers; + JVM_GetHostName; + JVM_GetInheritedAccessControlContext; + JVM_GetInterfaceVersion; + JVM_GetLastErrorString; + JVM_GetManagement; + JVM_GetMethodAnnotations; + JVM_GetMethodDefaultAnnotationValue; + JVM_GetMethodIxArgsSize; + JVM_GetMethodIxByteCode; + JVM_GetMethodIxByteCodeLength; + JVM_GetMethodIxExceptionIndexes; + JVM_GetMethodIxExceptionTableEntry; + JVM_GetMethodIxExceptionTableLength; + JVM_GetMethodIxExceptionsCount; + JVM_GetMethodIxLocalsCount; + JVM_GetMethodIxMaxStack; + JVM_GetMethodIxModifiers; + JVM_GetMethodIxNameUTF; + JVM_GetMethodIxSignatureUTF; + JVM_GetMethodParameterAnnotations; + JVM_GetPrimitiveArrayElement; + JVM_GetProtectionDomain; + JVM_GetSockName; + JVM_GetSockOpt; + JVM_GetStackAccessControlContext; + JVM_GetStackTraceDepth; + JVM_GetStackTraceElement; + JVM_GetSystemPackage; + JVM_GetSystemPackages; + JVM_GetThreadStateNames; + JVM_GetThreadStateValues; + JVM_GetVersionInfo; + JVM_Halt; + JVM_HoldsLock; + JVM_IHashCode; + JVM_InitAgentProperties; + JVM_InitProperties; + JVM_InitializeCompiler; + JVM_InitializeSocketLibrary; + JVM_InternString; + JVM_Interrupt; + JVM_InvokeMethod; + JVM_IsArrayClass; + JVM_IsConstructorIx; + JVM_IsInterface; + JVM_IsInterrupted; + JVM_IsNaN; + JVM_IsPrimitiveClass; + JVM_IsSameClassPackage; + JVM_IsSilentCompiler; + JVM_IsSupportedJNIVersion; + JVM_IsThreadAlive; + JVM_LatestUserDefinedLoader; + JVM_Listen; + JVM_LoadClass0; + JVM_LoadLibrary; + JVM_Lseek; + JVM_MaxObjectInspectionAge; + JVM_MaxMemory; + JVM_MonitorNotify; + JVM_MonitorNotifyAll; + JVM_MonitorWait; + JVM_NanoTime; + JVM_NativePath; + JVM_NewArray; + JVM_NewInstanceFromConstructor; + JVM_NewMultiArray; + JVM_OnExit; + JVM_Open; + JVM_PrintStackTrace; + JVM_RaiseSignal; + JVM_RawMonitorCreate; + JVM_RawMonitorDestroy; + JVM_RawMonitorEnter; + JVM_RawMonitorExit; + JVM_Read; + JVM_Recv; + JVM_RecvFrom; + JVM_RegisterSignal; + JVM_ReleaseUTF; + JVM_ResolveClass; + JVM_ResumeThread; + JVM_Send; + JVM_SendTo; + JVM_SetArrayElement; + JVM_SetClassSigners; + JVM_SetLength; + JVM_SetPrimitiveArrayElement; + JVM_SetProtectionDomain; + JVM_SetSockOpt; + JVM_SetThreadPriority; + JVM_Sleep; + JVM_Socket; + JVM_SocketAvailable; + JVM_SocketClose; + JVM_SocketShutdown; + JVM_StartThread; + JVM_StopThread; + JVM_SuspendThread; + JVM_SupportsCX8; + JVM_Sync; + JVM_Timeout; + JVM_TotalMemory; + JVM_TraceInstructions; + JVM_TraceMethodCalls; + JVM_UnloadLibrary; + JVM_Write; + JVM_Yield; + JVM_handle_bsd_signal; + + # Old reflection routines + # These do not need to be present in the product build in JDK 1.4 + # but their code has not been removed yet because there will not + # be a substantial code savings until JVM_InvokeMethod and + # JVM_NewInstanceFromConstructor can also be removed; see + # reflectionCompat.hpp. + JVM_GetClassConstructor; + JVM_GetClassConstructors; + JVM_GetClassField; + JVM_GetClassFields; + JVM_GetClassMethod; + JVM_GetClassMethods; + JVM_GetField; + JVM_GetPrimitiveField; + JVM_NewInstance; + JVM_SetField; + JVM_SetPrimitiveField; + + # debug JVM + JVM_AccessVMBooleanFlag; + JVM_AccessVMIntFlag; + JVM_VMBreakPoint; + + # miscellaneous functions + jio_fprintf; + jio_printf; + jio_snprintf; + jio_vfprintf; + jio_vsnprintf; + fork1; + numa_warn; + numa_error; + + # Needed because there is no JVM interface for this. + sysThreadAvailableStackWithSlack; + + # This is for Forte Analyzer profiling support. + AsyncGetCallTrace; + + # INSERT VTABLE SYMBOLS HERE + + local: + *; +}; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/mapfile-vers-jsig Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,40 @@ +# + +# +# Copyright (c) 2005, 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. +# +# + +# Define library interface. + +SUNWprivate_1.1 { + global: + JVM_begin_signal_setting; + JVM_end_signal_setting; + JVM_get_libjsig_version; + JVM_get_signal_action; + sigaction; + signal; + sigset; + local: + *; +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/mapfile-vers-product Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,286 @@ +# +# @(#)mapfile-vers-product 1.19 08/02/12 10:56:37 +# + +# +# Copyright (c) 2002, 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. +# +# + +# Define public interface. + +SUNWprivate_1.1 { + global: + # JNI + JNI_CreateJavaVM; + JNI_GetCreatedJavaVMs; + JNI_GetDefaultJavaVMInitArgs; + + # JVM + JVM_Accept; + JVM_ActiveProcessorCount; + JVM_AllocateNewArray; + JVM_AllocateNewObject; + JVM_ArrayCopy; + JVM_AssertionStatusDirectives; + JVM_Available; + JVM_Bind; + JVM_ClassDepth; + JVM_ClassLoaderDepth; + JVM_Clone; + JVM_Close; + JVM_CX8Field; + JVM_CompileClass; + JVM_CompileClasses; + JVM_CompilerCommand; + JVM_Connect; + JVM_ConstantPoolGetClassAt; + JVM_ConstantPoolGetClassAtIfLoaded; + JVM_ConstantPoolGetDoubleAt; + JVM_ConstantPoolGetFieldAt; + JVM_ConstantPoolGetFieldAtIfLoaded; + JVM_ConstantPoolGetFloatAt; + JVM_ConstantPoolGetIntAt; + JVM_ConstantPoolGetLongAt; + JVM_ConstantPoolGetMethodAt; + JVM_ConstantPoolGetMethodAtIfLoaded; + JVM_ConstantPoolGetMemberRefInfoAt; + JVM_ConstantPoolGetSize; + JVM_ConstantPoolGetStringAt; + JVM_ConstantPoolGetUTF8At; + JVM_CountStackFrames; + JVM_CurrentClassLoader; + JVM_CurrentLoadedClass; + JVM_CurrentThread; + JVM_CurrentTimeMillis; + JVM_DefineClass; + JVM_DefineClassWithSource; + JVM_DefineClassWithSourceCond; + JVM_DesiredAssertionStatus; + JVM_DisableCompiler; + JVM_DoPrivileged; + JVM_DTraceGetVersion; + JVM_DTraceActivate; + JVM_DTraceIsProbeEnabled; + JVM_DTraceIsSupported; + JVM_DTraceDispose; + JVM_DumpAllStacks; + JVM_DumpThreads; + JVM_EnableCompiler; + JVM_Exit; + JVM_FillInStackTrace; + JVM_FindClassFromClass; + JVM_FindClassFromClassLoader; + JVM_FindClassFromBootLoader; + JVM_FindLibraryEntry; + JVM_FindLoadedClass; + JVM_FindPrimitiveClass; + JVM_FindSignal; + JVM_FreeMemory; + JVM_GC; + JVM_GetAllThreads; + JVM_GetArrayElement; + JVM_GetArrayLength; + JVM_GetCPClassNameUTF; + JVM_GetCPFieldClassNameUTF; + JVM_GetCPFieldModifiers; + JVM_GetCPFieldNameUTF; + JVM_GetCPFieldSignatureUTF; + JVM_GetCPMethodClassNameUTF; + JVM_GetCPMethodModifiers; + JVM_GetCPMethodNameUTF; + JVM_GetCPMethodSignatureUTF; + JVM_GetCallerClass; + JVM_GetClassAccessFlags; + JVM_GetClassAnnotations; + JVM_GetClassCPEntriesCount; + JVM_GetClassCPTypes; + JVM_GetClassConstantPool; + JVM_GetClassContext; + JVM_GetClassDeclaredConstructors; + JVM_GetClassDeclaredFields; + JVM_GetClassDeclaredMethods; + JVM_GetClassFieldsCount; + JVM_GetClassInterfaces; + JVM_GetClassLoader; + JVM_GetClassMethodsCount; + JVM_GetClassModifiers; + JVM_GetClassName; + JVM_GetClassNameUTF; + JVM_GetClassSignature; + JVM_GetClassSigners; + JVM_GetComponentType; + JVM_GetDeclaredClasses; + JVM_GetDeclaringClass; + JVM_GetEnclosingMethodInfo; + JVM_GetFieldAnnotations; + JVM_GetFieldIxModifiers; + JVM_GetHostName; + JVM_GetInheritedAccessControlContext; + JVM_GetInterfaceVersion; + JVM_GetLastErrorString; + JVM_GetManagement; + JVM_GetMethodAnnotations; + JVM_GetMethodDefaultAnnotationValue; + JVM_GetMethodIxArgsSize; + JVM_GetMethodIxByteCode; + JVM_GetMethodIxByteCodeLength; + JVM_GetMethodIxExceptionIndexes; + JVM_GetMethodIxExceptionTableEntry; + JVM_GetMethodIxExceptionTableLength; + JVM_GetMethodIxExceptionsCount; + JVM_GetMethodIxLocalsCount; + JVM_GetMethodIxMaxStack; + JVM_GetMethodIxModifiers; + JVM_GetMethodIxNameUTF; + JVM_GetMethodIxSignatureUTF; + JVM_GetMethodParameterAnnotations; + JVM_GetPrimitiveArrayElement; + JVM_GetProtectionDomain; + JVM_GetSockName; + JVM_GetSockOpt; + JVM_GetStackAccessControlContext; + JVM_GetStackTraceDepth; + JVM_GetStackTraceElement; + JVM_GetSystemPackage; + JVM_GetSystemPackages; + JVM_GetThreadStateNames; + JVM_GetThreadStateValues; + JVM_GetVersionInfo; + JVM_Halt; + JVM_HoldsLock; + JVM_IHashCode; + JVM_InitAgentProperties; + JVM_InitProperties; + JVM_InitializeCompiler; + JVM_InitializeSocketLibrary; + JVM_InternString; + JVM_Interrupt; + JVM_InvokeMethod; + JVM_IsArrayClass; + JVM_IsConstructorIx; + JVM_IsInterface; + JVM_IsInterrupted; + JVM_IsNaN; + JVM_IsPrimitiveClass; + JVM_IsSameClassPackage; + JVM_IsSilentCompiler; + JVM_IsSupportedJNIVersion; + JVM_IsThreadAlive; + JVM_LatestUserDefinedLoader; + JVM_Listen; + JVM_LoadClass0; + JVM_LoadLibrary; + JVM_Lseek; + JVM_MaxObjectInspectionAge; + JVM_MaxMemory; + JVM_MonitorNotify; + JVM_MonitorNotifyAll; + JVM_MonitorWait; + JVM_NanoTime; + JVM_NativePath; + JVM_NewArray; + JVM_NewInstanceFromConstructor; + JVM_NewMultiArray; + JVM_OnExit; + JVM_Open; + JVM_PrintStackTrace; + JVM_RaiseSignal; + JVM_RawMonitorCreate; + JVM_RawMonitorDestroy; + JVM_RawMonitorEnter; + JVM_RawMonitorExit; + JVM_Read; + JVM_Recv; + JVM_RecvFrom; + JVM_RegisterSignal; + JVM_ReleaseUTF; + JVM_ResolveClass; + JVM_ResumeThread; + JVM_Send; + JVM_SendTo; + JVM_SetArrayElement; + JVM_SetClassSigners; + JVM_SetLength; + JVM_SetPrimitiveArrayElement; + JVM_SetProtectionDomain; + JVM_SetSockOpt; + JVM_SetThreadPriority; + JVM_Sleep; + JVM_Socket; + JVM_SocketAvailable; + JVM_SocketClose; + JVM_SocketShutdown; + JVM_StartThread; + JVM_StopThread; + JVM_SuspendThread; + JVM_SupportsCX8; + JVM_Sync; + JVM_Timeout; + JVM_TotalMemory; + JVM_TraceInstructions; + JVM_TraceMethodCalls; + JVM_UnloadLibrary; + JVM_Write; + JVM_Yield; + JVM_handle_bsd_signal; + + # Old reflection routines + # These do not need to be present in the product build in JDK 1.4 + # but their code has not been removed yet because there will not + # be a substantial code savings until JVM_InvokeMethod and + # JVM_NewInstanceFromConstructor can also be removed; see + # reflectionCompat.hpp. + JVM_GetClassConstructor; + JVM_GetClassConstructors; + JVM_GetClassField; + JVM_GetClassFields; + JVM_GetClassMethod; + JVM_GetClassMethods; + JVM_GetField; + JVM_GetPrimitiveField; + JVM_NewInstance; + JVM_SetField; + JVM_SetPrimitiveField; + + # miscellaneous functions + jio_fprintf; + jio_printf; + jio_snprintf; + jio_vfprintf; + jio_vsnprintf; + fork1; + numa_warn; + numa_error; + + # Needed because there is no JVM interface for this. + sysThreadAvailableStackWithSlack; + + # This is for Forte Analyzer profiling support. + AsyncGetCallTrace; + + # INSERT VTABLE SYMBOLS HERE + + local: + *; +}; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/optimized.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,44 @@ +# +# Copyright (c) 1999, 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. +# +# + +# Sets make macros for making optimized version of Gamma VM +# (This is the "product", not the "release" version.) + +# Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make +OPT_CFLAGS/DEFAULT= $(OPT_CFLAGS) +OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@)) + +# (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files) + +# If you set HOTSPARC_GENERIC=yes, you disable all OPT_CFLAGS settings +CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE) + +# Set the environment variable HOTSPARC_GENERIC to "true" +# to inhibit the effect of the previous line on CFLAGS. + +# Linker mapfile +MAPFILE = $(GAMMADIR)/make/bsd/makefiles/mapfile-vers-debug + +G_SUFFIX = +VERSION = optimized
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/ppc.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,30 @@ +# +# Copyright (c) 2004, 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. +# +# + +# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized +OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT) + +# Must also specify if CPU is big endian +CFLAGS += -DVM_BIG_ENDIAN +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/product.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,58 @@ +# +# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 optimized version of Gamma VM +# (This is the "product", not the "release" version.) + +# Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make +OPT_CFLAGS/DEFAULT= $(OPT_CFLAGS) +OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@)) + +# (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files) + +# If you set HOTSPARC_GENERIC=yes, you disable all OPT_CFLAGS settings +CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE) + +# Set the environment variable HOTSPARC_GENERIC to "true" +# to inhibit the effect of the previous line on CFLAGS. + +# Linker mapfile +MAPFILE = $(GAMMADIR)/make/bsd/makefiles/mapfile-vers-product + +G_SUFFIX = +SYSDEFS += -DPRODUCT +VERSION = optimized + +# use -g to strip library as -x will discard its symbol table; -x is fine for +# executables. +ifdef CROSS_COMPILE_ARCH + STRIP = $(ALT_COMPILER_PATH)/strip +else + STRIP = strip +endif +STRIP_LIBJVM = $(STRIP) -g $@ || exit 1; +STRIP_AOUT = $(STRIP) -x $@ || exit 1; + +# Don't strip in VM build; JDK build will strip libraries later +# LINK_LIB.CC/POST_HOOK += $(STRIP_$(LINK_INTO))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/profiled.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,30 @@ +# +# Copyright (c) 1999, 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. +# +# + +# Sets make macros for making profiled version of Gamma VM +# (It is also optimized.) + +CFLAGS += -pg +AOUT_FLAGS += -pg +LDNOMAP = true
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/rules.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,216 @@ +# +# Copyright (c) 2003, 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. +# +# + +# Common rules/macros for the vm, adlc. + +# Tell make that .cpp is important +.SUFFIXES: .cpp $(SUFFIXES) + +# For now. Other makefiles use CPP as the c++ compiler, but that should really +# name the preprocessor. +ifeq ($(CCC),) +CCC = $(CPP) +endif + +DEMANGLER = c++filt +DEMANGLE = $(DEMANGLER) < $@ > .$@ && mv -f .$@ $@ + +# $(CC) is the c compiler (cc/gcc), $(CCC) is the c++ compiler (CC/g++). +C_COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) +CC_COMPILE = $(CCC) $(CPPFLAGS) $(CFLAGS) + +AS.S = $(AS) $(ASFLAGS) + +COMPILE.c = $(C_COMPILE) -c +GENASM.c = $(C_COMPILE) -S +LINK.c = $(CC) $(LFLAGS) $(AOUT_FLAGS) $(PROF_AOUT_FLAGS) +LINK_LIB.c = $(CC) $(LFLAGS) $(SHARED_FLAG) +PREPROCESS.c = $(C_COMPILE) -E + +COMPILE.CC = $(CC_COMPILE) -c +GENASM.CC = $(CC_COMPILE) -S +LINK.CC = $(CCC) $(LFLAGS) $(AOUT_FLAGS) $(PROF_AOUT_FLAGS) +LINK_NOPROF.CC = $(CCC) $(LFLAGS) $(AOUT_FLAGS) +LINK_LIB.CC = $(CCC) $(LFLAGS) $(SHARED_FLAG) +PREPROCESS.CC = $(CC_COMPILE) -E + +# cross compiling the jvm with c2 requires host compilers to build +# adlc tool + +HOST.CC_COMPILE = $(HOSTCPP) $(CPPFLAGS) $(CFLAGS) +HOST.COMPILE.CC = $(HOST.CC_COMPILE) -c +HOST.LINK_NOPROF.CC = $(HOSTCPP) $(LFLAGS) $(AOUT_FLAGS) + + +# Effect of REMOVE_TARGET is to delete out-of-date files during "gnumake -k". +REMOVE_TARGET = rm -f $@ + +# Synonyms. +COMPILE.cpp = $(COMPILE.CC) +GENASM.cpp = $(GENASM.CC) +LINK.cpp = $(LINK.CC) +LINK_LIB.cpp = $(LINK_LIB.CC) +PREPROCESS.cpp = $(PREPROCESS.CC) + +# Note use of ALT_BOOTDIR to explicitly specify location of java and +# javac; this is the same environment variable used in the J2SE build +# process for overriding the default spec, which is BOOTDIR. +# Note also that we fall back to using JAVA_HOME if neither of these is +# specified. + +ifdef ALT_BOOTDIR + +RUN.JAVA = $(ALT_BOOTDIR)/bin/java +RUN.JAVAP = $(ALT_BOOTDIR)/bin/javap +RUN.JAVAH = $(ALT_BOOTDIR)/bin/javah +RUN.JAR = $(ALT_BOOTDIR)/bin/jar +COMPILE.JAVAC = $(ALT_BOOTDIR)/bin/javac +COMPILE.RMIC = $(ALT_BOOTDIR)/bin/rmic +BOOT_JAVA_HOME = $(ALT_BOOTDIR) + +else + +ifdef BOOTDIR + +RUN.JAVA = $(BOOTDIR)/bin/java +RUN.JAVAP = $(BOOTDIR)/bin/javap +RUN.JAVAH = $(BOOTDIR)/bin/javah +RUN.JAR = $(BOOTDIR)/bin/jar +COMPILE.JAVAC = $(BOOTDIR)/bin/javac +COMPILE.RMIC = $(BOOTDIR)/bin/rmic +BOOT_JAVA_HOME = $(BOOTDIR) + +else + +ifdef JAVA_HOME + +RUN.JAVA = $(JAVA_HOME)/bin/java +RUN.JAVAP = $(JAVA_HOME)/bin/javap +RUN.JAVAH = $(JAVA_HOME)/bin/javah +RUN.JAR = $(JAVA_HOME)/bin/jar +COMPILE.JAVAC = $(JAVA_HOME)/bin/javac +COMPILE.RMIC = $(JAVA_HOME)/bin/rmic +BOOT_JAVA_HOME = $(JAVA_HOME) + +else + +# take from the PATH, if ALT_BOOTDIR, BOOTDIR and JAVA_HOME are not defined +# note that this is to support hotspot build without SA. To build +# SA along with hotspot, you need to define ALT_BOOTDIR, BOOTDIR or JAVA_HOME + +RUN.JAVA = java +RUN.JAVAP = javap +RUN.JAVAH = javah +RUN.JAR = jar +COMPILE.JAVAC = javac +COMPILE.RMIC = rmic + +endif +endif +endif + +COMPILE.JAVAC += $(BOOTSTRAP_JAVAC_FLAGS) + +SUM = /usr/bin/sum + +# 'gmake MAKE_VERBOSE=y' gives all the gory details. +QUIETLY$(MAKE_VERBOSE) = @ +RUN.JAR$(MAKE_VERBOSE) += >/dev/null + +# Settings for javac +BOOT_SOURCE_LANGUAGE_VERSION = 6 +BOOT_TARGET_CLASS_VERSION = 6 +JAVAC_FLAGS = -g -encoding ascii +BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION) + +# With parallel makes, print a message at the end of compilation. +ifeq ($(findstring j,$(MFLAGS)),j) +COMPILE_DONE = && { echo Done with $<; } +endif + +# Include $(NONPIC_OBJ_FILES) definition +ifndef LP64 +include $(GAMMADIR)/make/pic.make +endif + +include $(GAMMADIR)/make/altsrc.make + +# The non-PIC object files are only generated for 32 bit platforms. +ifdef LP64 +%.o: %.cpp + @echo Compiling $< + $(QUIETLY) $(REMOVE_TARGET) + $(QUIETLY) $(COMPILE.CC) $(DEPFLAGS) -o $@ $< $(COMPILE_DONE) +else +%.o: %.cpp + @echo Compiling $< + $(QUIETLY) $(REMOVE_TARGET) + $(QUIETLY) $(if $(findstring $@, $(NONPIC_OBJ_FILES)), \ + $(subst $(VM_PICFLAG), ,$(COMPILE.CC)) $(DEPFLAGS) -o $@ $< $(COMPILE_DONE), \ + $(COMPILE.CC) $(DEPFLAGS) -o $@ $< $(COMPILE_DONE)) +endif + +%.o: %.s + @echo Assembling $< + $(QUIETLY) $(REMOVE_TARGET) + $(QUIETLY) $(AS.S) $(DEPFLAGS) -o $@ $< $(COMPILE_DONE) + +%.s: %.cpp + @echo Generating assembly for $< + $(QUIETLY) $(GENASM.CC) -o $@ $< + $(QUIETLY) $(DEMANGLE) $(COMPILE_DONE) + +# Intermediate files (for debugging macros) +%.i: %.cpp + @echo Preprocessing $< to $@ + $(QUIETLY) $(PREPROCESS.CC) $< > $@ $(COMPILE_DONE) + +# Override gnumake built-in rules which do sccs get operations badly. +# (They put the checked out code in the current directory, not in the +# directory of the original file.) Since this is a symptom of a teamware +# failure, and since not all problems can be detected by gnumake due +# to incomplete dependency checking... just complain and stop. +%:: s.% + @echo "=========================================================" + @echo File $@ + @echo is out of date with respect to its SCCS file. + @echo This file may be from an unresolved Teamware conflict. + @echo This is also a symptom of a Teamware bringover/putback failure + @echo in which SCCS files are updated but not checked out. + @echo Check for other out of date files in your workspace. + @echo "=========================================================" + @exit 666 + +%:: SCCS/s.% + @echo "=========================================================" + @echo File $@ + @echo is out of date with respect to its SCCS file. + @echo This file may be from an unresolved Teamware conflict. + @echo This is also a symptom of a Teamware bringover/putback failure + @echo in which SCCS files are updated but not checked out. + @echo Check for other out of date files in your workspace. + @echo "=========================================================" + @exit 666 + +.PHONY: default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/sa.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,117 @@ +# +# Copyright (c) 2003, 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. +# +# + +# This makefile (sa.make) is included from the sa.make in the +# build directories. + +# This makefile is used to build Serviceability Agent java code +# and generate JNI header file for native methods. + +include $(GAMMADIR)/make/bsd/makefiles/rules.make + +AGENT_DIR = $(GAMMADIR)/agent + +include $(GAMMADIR)/make/sa.files + +TOPDIR = $(shell echo `pwd`) +GENERATED = $(TOPDIR)/../generated + +# tools.jar is needed by the JDI - SA binding +ifeq ($(SA_APPLE_BOOT_JAVA),true) + SA_CLASSPATH = $(BOOT_JAVA_HOME)/bundle/Classes/classes.jar +else + SA_CLASSPATH = $(BOOT_JAVA_HOME)/lib/tools.jar +endif + +# TODO: if it's a modules image, check if SA module is installed. +MODULELIB_PATH= $(BOOT_JAVA_HOME)/lib/modules + +AGENT_FILES_LIST := $(GENERATED)/agent.classes.list + +SA_CLASSDIR = $(GENERATED)/saclasses + +SA_BUILD_VERSION_PROP = "sun.jvm.hotspot.runtime.VM.saBuildVersion=$(SA_BUILD_VERSION)" + +SA_PROPERTIES = $(SA_CLASSDIR)/sa.properties + +# if $(AGENT_DIR) does not exist, we don't build SA +# also, we don't build SA on Itanium, PowerPC, ARM or zero. + +all: + if [ -d $(AGENT_DIR) -a "$(SRCARCH)" != "ia64" \ + -a "$(SRCARCH)" != "arm" \ + -a "$(SRCARCH)" != "ppc" \ + -a "$(SRCARCH)" != "zero" ] ; then \ + $(MAKE) -f sa.make $(GENERATED)/sa-jdi.jar; \ + fi + +$(GENERATED)/sa-jdi.jar: $(AGENT_FILES) + $(QUIETLY) echo "Making $@" + $(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \ + echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \ + exit 1; \ + fi + $(QUIETLY) if [ ! -f $(SA_CLASSPATH) -a ! -d $(MODULELIB_PATH) ] ; then \ + echo "Missing $(SA_CLASSPATH) file. Use 1.6.0 or later version of JDK";\ + echo ""; \ + exit 1; \ + fi + $(QUIETLY) if [ ! -d $(SA_CLASSDIR) ] ; then \ + mkdir -p $(SA_CLASSDIR); \ + fi +# Note: When indented, make tries to execute the '$(shell' comment. +# In some environments, cmd processors have limited line length. +# To prevent the javac invocation in the next block from using +# a very long cmd line, we use javac's @file-list option. We +# generate the file lists using make's built-in 'foreach' control +# flow which also avoids cmd processor line length issues. Since +# the 'foreach' is done as part of make's macro expansion phase, +# the initialization of the lists is also done in the same phase +# using '$(shell rm ...' instead of using the more traditional +# 'rm ...' rule. + $(shell rm -rf $(AGENT_FILES_LIST)) +# gnumake 3.78.1 does not accept the *'s that +# are in AGENT_FILES, so use the shell to expand them. +# Be extra carefull to not produce too long command lines in the shell! + $(foreach file,$(AGENT_FILES),$(shell ls -1 $(file) >> $(AGENT_FILES_LIST))) + $(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES_LIST) + $(QUIETLY) $(REMOTE) $(COMPILE.RMIC) -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer + $(QUIETLY) echo "$(SA_BUILD_VERSION_PROP)" > $(SA_PROPERTIES) + $(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql/sa.js + $(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/utilities/soql/sa.js $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql + $(QUIETLY) mkdir -p $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources + $(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources/* + $(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/ui/resources/*.png $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources/ + $(QUIETLY) cp -r $(AGENT_SRC_DIR)/images/* $(SA_CLASSDIR)/ + $(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(SA_CLASSDIR)/ . + $(QUIETLY) $(REMOTE) $(RUN.JAR) uf $@ -C $(AGENT_SRC_DIR) META-INF/services/com.sun.jdi.connect.Connector + $(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.x86.X86ThreadContext + $(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.ia64.IA64ThreadContext + $(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.amd64.AMD64ThreadContext + $(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.sparc.SPARCThreadContext + +clean: + rm -rf $(SA_CLASSDIR) + rm -rf $(GENERATED)/sa-jdi.jar + rm -rf $(AGENT_FILES_LIST)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/saproc.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,124 @@ +# +# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 serviceability agent library, used by vm.make + +# libsaproc[_g].so: serviceability agent +SAPROC = saproc +SAPROC_G = $(SAPROC)$(G_SUFFIX) + +ifeq ($(OS_VENDOR), Darwin) + LIBSAPROC = lib$(SAPROC).dylib + LIBSAPROC_G = lib$(SAPROC_G).dylib +else + LIBSAPROC = lib$(SAPROC).so + LIBSAPROC_G = lib$(SAPROC_G).so +endif + +AGENT_DIR = $(GAMMADIR)/agent + +SASRCDIR = $(AGENT_DIR)/src/os/$(Platform_os_family) + +NON_STUB_SASRCFILES = $(SASRCDIR)/salibelf.c \ + $(SASRCDIR)/symtab.c \ + $(SASRCDIR)/libproc_impl.c \ + $(SASRCDIR)/ps_proc.c \ + $(SASRCDIR)/ps_core.c \ + $(SASRCDIR)/BsdDebuggerLocal.c + +ifeq ($(OS_VENDOR), FreeBSD) + SASRCFILES = $(NON_STUB_SASRCFILES) + SALIBS = -lutil -lthread_db + SAARCH = $(ARCHFLAG) +else + ifeq ($(OS_VENDOR), Darwin) + SASRCFILES = $(SASRCDIR)/MacosxDebuggerLocal.m + SALIBS = -g -framework Foundation -F/System/Library/Frameworks/JavaVM.framework/Frameworks -framework JavaNativeFoundation -framework Security -framework CoreFoundation + #objc compiler blows up on -march=i586, perhaps it should not be included in the macosx intel 32-bit C++ compiles? + SAARCH = $(subst -march=i586,,$(ARCHFLAG)) + else + SASRCFILES = $(SASRCDIR)/StubDebuggerLocal.c + SALIBS = + SAARCH = $(ARCHFLAG) + endif +endif + +SAMAPFILE = $(SASRCDIR)/mapfile + +DEST_SAPROC = $(JDK_LIBDIR)/$(LIBSAPROC) + +# DEBUG_BINARIES overrides everything, use full -g debug information +ifeq ($(DEBUG_BINARIES), true) + SA_DEBUG_CFLAGS = -g +endif + +# if $(AGENT_DIR) does not exist, we don't build SA +# also, we don't build SA on Itanium, PPC, ARM or zero. + +ifneq ($(wildcard $(AGENT_DIR)),) +ifneq ($(filter-out ia64 arm ppc zero,$(SRCARCH)),) + BUILDLIBSAPROC = $(LIBSAPROC) +endif +endif + + +ifneq ($(OS_VENDOR), Darwin) +SA_LFLAGS = $(MAPFLAG:FILENAME=$(SAMAPFILE)) +endif +SA_LFLAGS += $(LDFLAGS_HASH_STYLE) + +ifeq ($(OS_VENDOR), Darwin) + BOOT_JAVA_INCLUDES = -I$(BOOT_JAVA_HOME)/include \ + -I$(BOOT_JAVA_HOME)/include/$(shell uname -s | tr "[:upper:]" "[:lower:]") \ + -I/System/Library/Frameworks/JavaVM.framework/Headers +else + BOOT_JAVA_INCLUDES = -I$(BOOT_JAVA_HOME)/include \ + -I$(BOOT_JAVA_HOME)/include/$(shell uname -s | tr "[:upper:]" "[:lower:]") +endif + +$(LIBSAPROC): $(SASRCFILES) $(SAMAPFILE) + $(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \ + echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \ + exit 1; \ + fi + @echo Making SA debugger back-end... + $(QUIETLY) $(CC) -D$(BUILDARCH) -D_GNU_SOURCE \ + $(SYMFLAG) $(SAARCH) $(SHARED_FLAG) $(PICFLAG) \ + -I$(SASRCDIR) \ + -I$(GENERATED) \ + $(BOOT_JAVA_INCLUDES) \ + $(SASRCFILES) \ + $(SA_LFLAGS) \ + $(SA_DEBUG_CFLAGS) \ + -o $@ \ + $(SALIBS) + $(QUIETLY) [ -f $(LIBSAPROC_G) ] || { ln -s $@ $(LIBSAPROC_G); } + +install_saproc: $(BUILDLIBSAPROC) + $(QUIETLY) if [ -e $(LIBSAPROC) ] ; then \ + echo "Copying $(LIBSAPROC) to $(DEST_SAPROC)"; \ + cp -f $(LIBSAPROC) $(DEST_SAPROC) && echo "Done"; \ + fi + +.PHONY: install_saproc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/shark.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,32 @@ +# +# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2008, 2010 Red Hat, Inc. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 Shark version of VM + +TYPE = SHARK + +VM_SUBDIR = server + +CFLAGS += -DSHARK
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/sparc.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,24 @@ +# +# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/sparcWorks.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,104 @@ +# +# Copyright (c) 1999, 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. +# +# + +#------------------------------------------------------------------------ +# CC, CPP & AS + +CPP = CC +CC = cc +AS = $(CC) -c + +HOSTCPP = $(CPP) +HOSTCC = $(CC) + +ARCHFLAG = $(ARCHFLAG/$(BUILDARCH)) +ARCHFLAG/i486 = -m32 +ARCHFLAG/amd64 = -m64 + +CFLAGS += $(ARCHFLAG) +AOUT_FLAGS += $(ARCHFLAG) +LFLAGS += $(ARCHFLAG) +ASFLAGS += $(ARCHFLAG) + +#------------------------------------------------------------------------ +# Compiler flags + +# position-independent code +PICFLAG = -KPIC + +CFLAGS += $(PICFLAG) +# no more exceptions +CFLAGS += -features=no%except +# Reduce code bloat by reverting back to 5.0 behavior for static initializers +CFLAGS += -features=no%split_init +# allow zero sized arrays +CFLAGS += -features=zla + +# Use C++ Interpreter +ifdef CC_INTERP + CFLAGS += -DCC_INTERP +endif + +# We don't need libCstd.so and librwtools7.so, only libCrun.so +CFLAGS += -library=Crun +LIBS += -lCrun + +CFLAGS += -mt +LFLAGS += -mt + +# Compiler warnings are treated as errors +#WARNINGS_ARE_ERRORS = -errwarn=%all +CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) +# Special cases +CFLAGS_WARN/BYFILE = $(CFLAGS_WARN/$@)$(CFLAGS_WARN/DEFAULT$(CFLAGS_WARN/$@)) + +# The flags to use for an Optimized build +OPT_CFLAGS+=-xO4 +OPT_CFLAGS/NOOPT=-xO0 + +# Flags for creating the dependency files. +ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1) +DEPFLAGS = -xMMD -xMF $(DEP_DIR)/$(@:%=%.d) +endif + +# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp. +CFLAGS += -DDONT_USE_PRECOMPILED_HEADER + +#------------------------------------------------------------------------ +# Linker flags + +# Use $(MAPFLAG:FILENAME=real_file_name) to specify a map file. +MAPFLAG = -Wl,--version-script=FILENAME + +# Use $(SONAMEFLAG:SONAME=soname) to specify the intrinsic name of a shared obj +SONAMEFLAG = -h SONAME + +# Build shared library +SHARED_FLAG = -G + +#------------------------------------------------------------------------ +# Debug flags +DEBUG_CFLAGS += -g +FASTDEBUG_CFLAGS = -g0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/sparcv9.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,27 @@ +# +# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# gcc 4.0 miscompiles this code in -m64 +OPT_CFLAGS/macro.o = -O0 + +CFLAGS += -D_LP64=1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/tiered.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,31 @@ +# +# Copyright (c) 2006, 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. +# +# + +# Sets make macros for making tiered version of VM + +TYPE=TIERED + +VM_SUBDIR = server + +CFLAGS += -DCOMPILER2 -DCOMPILER1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/top.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,151 @@ +# +# Copyright (c) 1999, 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. +# +# + +# top.make is included in the Makefile in the build directories. +# It DOES NOT include the vm dependency info in order to be faster. +# Its main job is to implement the incremental form of make lists. +# It also: +# -builds and runs adlc via adlc.make +# -generates JVMTI source and docs via jvmti.make (JSR-163) +# -generate sa-jdi.jar (JDI binding to core files) + +# It assumes the following flags are set: +# CFLAGS Platform_file, Src_Dirs_I, Src_Dirs_V, SYSDEFS, AOUT, Obj_Files + +# -- D. Ungar (5/97) from a file by Bill Bush + +# Don't override the built-in $(MAKE). +# Instead, use "gmake" (or "gnumake") from the command line. --Rose +#MAKE = gmake + +include $(GAMMADIR)/make/altsrc.make + +TOPDIR = $(shell echo `pwd`) +GENERATED = $(TOPDIR)/../generated +VM = $(GAMMADIR)/src/share/vm +Plat_File = $(Platform_file) +CDG = cd $(GENERATED); + +ifdef USE_PRECOMPILED_HEADER +PrecompiledOption = -DUSE_PRECOMPILED_HEADER +UpdatePCH = $(MAKE) -f vm.make $(PRECOMPILED_HEADER) $(MFLAGS) +else +UpdatePCH = \# precompiled header is not used +PrecompiledOption = +endif + +Cached_plat = $(GENERATED)/platform.current + +AD_Dir = $(GENERATED)/adfiles +ADLC = $(AD_Dir)/adlc +AD_Spec = $(call altsrc-replace,$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm/$(Platform_arch_model).ad) +AD_Src = $(call altsrc-replace,$(HS_COMMON_SRC)/share/vm/adlc) +AD_Names = ad_$(Platform_arch_model).hpp ad_$(Platform_arch_model).cpp +AD_Files = $(AD_Names:%=$(AD_Dir)/%) + +# AD_Files_If_Required/COMPILER1 = ad_stuff +AD_Files_If_Required/COMPILER2 = ad_stuff +AD_Files_If_Required/TIERED = ad_stuff +AD_Files_If_Required = $(AD_Files_If_Required/$(TYPE)) + +# Wierd argument adjustment for "gnumake -j..." +adjust-mflags = $(GENERATED)/adjust-mflags +MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"` + + +# default target: update lists, make vm +# done in stages to force sequential order with parallel make +# + +default: vm_build_preliminaries the_vm + @echo All done. + +# This is an explicit dependency for the sake of parallel makes. +vm_build_preliminaries: checks $(Cached_plat) $(AD_Files_If_Required) jvmti_stuff sa_stuff dtrace_stuff + @# We need a null action here, so implicit rules don't get consulted. + +$(Cached_plat): $(Plat_File) + $(CDG) cp $(Plat_File) $(Cached_plat) + +# make AD files as necessary +ad_stuff: $(Cached_plat) $(adjust-mflags) + @$(MAKE) -f adlc.make $(MFLAGS-adjusted) + +# generate JVMTI files from the spec +jvmti_stuff: $(Cached_plat) $(adjust-mflags) + @$(MAKE) -f jvmti.make $(MFLAGS-adjusted) + +ifeq ($(OS_VENDOR), Darwin) +# generate dtrace header files +dtrace_stuff: $(Cached_plat) $(adjust-mflags) + @$(MAKE) -f dtrace.make dtrace_stuff $(MFLAGS-adjusted) GENERATED=$(GENERATED) +else +dtrace_stuff: + @# We need a null action here, so implicit rules don't get consulted. +endif + +# generate SA jar files and native header +sa_stuff: + @$(MAKE) -f sa.make $(MFLAGS-adjusted) + +# and the VM: must use other makefile with dependencies included + +# We have to go to great lengths to get control over the -jN argument +# to the recursive invocation of vm.make. The problem is that gnumake +# resets -jN to -j1 for recursive runs. (How helpful.) +# Note that the user must specify the desired parallelism level via a +# command-line or environment variable name HOTSPOT_BUILD_JOBS. +$(adjust-mflags): $(GAMMADIR)/make/$(Platform_os_family)/makefiles/adjust-mflags.sh + @+rm -f $@ $@+ + @+cat $< > $@+ + @+chmod +x $@+ + @+mv $@+ $@ + +the_vm: vm_build_preliminaries $(adjust-mflags) + @$(UpdatePCH) + @$(MAKE) -f vm.make $(MFLAGS-adjusted) + +install: the_vm + @$(MAKE) -f vm.make install + +# next rules support "make foo.[ois]" + +%.o %.i %.s: + $(UpdatePCH) + $(MAKE) -f vm.make $(MFLAGS) $@ + #$(MAKE) -f vm.make $@ + +# this should force everything to be rebuilt +clean: + rm -f $(GENERATED)/*.class + $(MAKE) -f vm.make $(MFLAGS) clean + +# just in case it doesn't, this should do it +realclean: + $(MAKE) -f vm.make $(MFLAGS) clean + rm -fr $(GENERATED) + +.PHONY: default vm_build_preliminaries +.PHONY: lists ad_stuff jvmti_stuff sa_stuff the_vm clean realclean +.PHONY: checks check_os_version install
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/vm.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,339 @@ +# +# Copyright (c) 1999, 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. +# +# + +# Rules to build JVM and related libraries, included from vm.make in the build +# directory. + +# Common build rules. +MAKEFILES_DIR=$(GAMMADIR)/make/$(Platform_os_family)/makefiles +include $(MAKEFILES_DIR)/rules.make +include $(GAMMADIR)/make/altsrc.make + +default: build + +#---------------------------------------------------------------------- +# Defs + +GENERATED = ../generated +DEP_DIR = $(GENERATED)/dependencies + +# reads the generated files defining the set of .o's and the .o .h dependencies +-include $(DEP_DIR)/*.d + +# read machine-specific adjustments (%%% should do this via buildtree.make?) +ifeq ($(ZERO_BUILD), true) + include $(MAKEFILES_DIR)/zeroshark.make +else + include $(MAKEFILES_DIR)/$(BUILDARCH).make +endif + +# set VPATH so make knows where to look for source files +# Src_Dirs_V is everything in src/share/vm/*, plus the right os/*/vm and cpu/*/vm +# The adfiles directory contains ad_<arch>.[ch]pp. +# The jvmtifiles directory contains jvmti*.[ch]pp +Src_Dirs_V += $(GENERATED)/adfiles $(GENERATED)/jvmtifiles +VPATH += $(Src_Dirs_V:%=%:) + +# set INCLUDES for C preprocessor. +Src_Dirs_I += $(GENERATED) +# The order is important for the precompiled headers to work. +INCLUDES += $(PRECOMPILED_HEADER_DIR:%=-I%) $(Src_Dirs_I:%=-I%) + +ifeq (${VERSION}, debug) + SYMFLAG = -g +else + SYMFLAG = +endif + +# HOTSPOT_RELEASE_VERSION and HOTSPOT_BUILD_VERSION are defined +# in $(GAMMADIR)/make/defs.make +ifeq ($(HOTSPOT_BUILD_VERSION),) + BUILD_VERSION = -DHOTSPOT_RELEASE_VERSION="\"$(HOTSPOT_RELEASE_VERSION)\"" +else + BUILD_VERSION = -DHOTSPOT_RELEASE_VERSION="\"$(HOTSPOT_RELEASE_VERSION)-$(HOTSPOT_BUILD_VERSION)\"" +endif + +# The following variables are defined in the generated flags.make file. +BUILD_VERSION = -DHOTSPOT_RELEASE_VERSION="\"$(HS_BUILD_VER)\"" +JRE_VERSION = -DJRE_RELEASE_VERSION="\"$(JRE_RELEASE_VER)\"" +HS_LIB_ARCH = -DHOTSPOT_LIB_ARCH=\"$(LIBARCH)\" +BUILD_TARGET = -DHOTSPOT_BUILD_TARGET="\"$(TARGET)\"" +BUILD_USER = -DHOTSPOT_BUILD_USER="\"$(HOTSPOT_BUILD_USER)\"" +VM_DISTRO = -DHOTSPOT_VM_DISTRO="\"$(HOTSPOT_VM_DISTRO)\"" + +CPPFLAGS = \ + ${SYSDEFS} \ + ${INCLUDES} \ + ${BUILD_VERSION} \ + ${BUILD_TARGET} \ + ${BUILD_USER} \ + ${HS_LIB_ARCH} \ + ${JRE_VERSION} \ + ${VM_DISTRO} + +ifdef DEFAULT_LIBPATH +CPPFLAGS += -DDEFAULT_LIBPATH="\"$(DEFAULT_LIBPATH)\"" +endif + +# CFLAGS_WARN holds compiler options to suppress/enable warnings. +CFLAGS += $(CFLAGS_WARN/BYFILE) + +# Do not use C++ exception handling +CFLAGS += $(CFLAGS/NOEX) + +# Extra flags from gnumake's invocation or environment +CFLAGS += $(EXTRA_CFLAGS) +LFLAGS += $(EXTRA_CFLAGS) + +# Don't set excutable bit on stack segment +# the same could be done by separate execstack command +# Darwin is non-executable-stack by default +ifneq ($(OS_VENDOR), Darwin) +LFLAGS += -Xlinker -z -Xlinker noexecstack +endif + +LIBS += -lm -pthread + +# By default, link the *.o into the library, not the executable. +LINK_INTO$(LINK_INTO) = LIBJVM + +JDK_LIBDIR = $(JAVA_HOME)/jre/lib/$(LIBARCH) + +#---------------------------------------------------------------------- +# jvm_db & dtrace +include $(MAKEFILES_DIR)/dtrace.make + +#---------------------------------------------------------------------- +# JVM + +JVM = jvm +ifeq ($(OS_VENDOR), Darwin) + LIBJVM = lib$(JVM).dylib + LIBJVM_G = lib$(JVM)$(G_SUFFIX).dylib + CFLAGS += -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE +else + LIBJVM = lib$(JVM).so + LIBJVM_G = lib$(JVM)$(G_SUFFIX).so +endif + +SPECIAL_PATHS:=adlc c1 gc_implementation opto shark libadt + +SOURCE_PATHS=\ + $(shell find $(HS_COMMON_SRC)/share/vm/* -type d \! \ + \( -name DUMMY $(foreach dir,$(SPECIAL_PATHS),-o -name $(dir)) \)) +SOURCE_PATHS+=$(HS_COMMON_SRC)/os/$(Platform_os_family)/vm +SOURCE_PATHS+=$(HS_COMMON_SRC)/os/posix/vm +SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm +SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm + +CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path)) +CORE_PATHS+=$(GENERATED)/jvmtifiles + +COMPILER1_PATHS := $(call altsrc,$(HS_COMMON_SRC)/share/vm/c1) +COMPILER1_PATHS += $(HS_COMMON_SRC)/share/vm/c1 + +COMPILER2_PATHS := $(call altsrc,$(HS_COMMON_SRC)/share/vm/opto) +COMPILER2_PATHS += $(call altsrc,$(HS_COMMON_SRC)/share/vm/libadt) +COMPILER2_PATHS += $(HS_COMMON_SRC)/share/vm/opto +COMPILER2_PATHS += $(HS_COMMON_SRC)/share/vm/libadt +COMPILER2_PATHS += $(GENERATED)/adfiles + +SHARK_PATHS := $(GAMMADIR)/src/share/vm/shark + +# Include dirs per type. +Src_Dirs/CORE := $(CORE_PATHS) +Src_Dirs/COMPILER1 := $(CORE_PATHS) $(COMPILER1_PATHS) +Src_Dirs/COMPILER2 := $(CORE_PATHS) $(COMPILER2_PATHS) +Src_Dirs/TIERED := $(CORE_PATHS) $(COMPILER1_PATHS) $(COMPILER2_PATHS) +Src_Dirs/ZERO := $(CORE_PATHS) +Src_Dirs/SHARK := $(CORE_PATHS) $(SHARK_PATHS) +Src_Dirs := $(Src_Dirs/$(TYPE)) + +COMPILER2_SPECIFIC_FILES := opto libadt bcEscapeAnalyzer.cpp chaitin\* c2_\* runtime_\* +COMPILER1_SPECIFIC_FILES := c1_\* +SHARK_SPECIFIC_FILES := shark +ZERO_SPECIFIC_FILES := zero + +# Always exclude these. +Src_Files_EXCLUDE := jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp + +# Exclude per type. +Src_Files_EXCLUDE/CORE := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp +Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp +Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) +Src_Files_EXCLUDE/TIERED := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) +Src_Files_EXCLUDE/ZERO := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp +Src_Files_EXCLUDE/SHARK := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) + +Src_Files_EXCLUDE += $(Src_Files_EXCLUDE/$(TYPE)) + +# Special handling of arch model. +ifeq ($(Platform_arch_model), x86_32) +Src_Files_EXCLUDE += \*x86_64\* +endif +ifeq ($(Platform_arch_model), x86_64) +Src_Files_EXCLUDE += \*x86_32\* +endif + +# Locate all source files in the given directory, excluding files in Src_Files_EXCLUDE. +define findsrc + $(notdir $(shell find $(1)/. ! -name . -prune \ + -a \( -name \*.c -o -name \*.cpp -o -name \*.s \) \ + -a ! \( -name DUMMY $(addprefix -o -name ,$(Src_Files_EXCLUDE)) \))) +endef + +Src_Files := $(foreach e,$(Src_Dirs),$(call findsrc,$(e))) + +Obj_Files = $(sort $(addsuffix .o,$(basename $(Src_Files)))) + +JVM_OBJ_FILES = $(Obj_Files) + +vm_version.o: $(filter-out vm_version.o,$(JVM_OBJ_FILES)) + +mapfile : $(MAPFILE) vm.def + rm -f $@ + awk '{ if ($$0 ~ "INSERT VTABLE SYMBOLS HERE") \ + { system ("cat vm.def"); } \ + else \ + { print $$0 } \ + }' > $@ < $(MAPFILE) + +mapfile_reorder : mapfile $(REORDERFILE) + rm -f $@ + cat $^ > $@ + +vm.def: $(Res_Files) $(Obj_Files) + sh $(GAMMADIR)/make/bsd/makefiles/build_vm_def.sh *.o > $@ + +STATIC_CXX = false + +ifeq ($(LINK_INTO),AOUT) + LIBJVM.o = + LIBJVM_MAPFILE = + LIBS_VM = $(LIBS) +else + LIBJVM.o = $(JVM_OBJ_FILES) + LIBJVM_MAPFILE$(LDNOMAP) = mapfile_reorder + LFLAGS_VM$(LDNOMAP) += $(MAPFLAG:FILENAME=$(LIBJVM_MAPFILE)) + LFLAGS_VM += $(SONAMEFLAG:SONAME=$(LIBJVM)) + + ifeq ($(OS_VENDOR), Darwin) + LFLAGS_VM += -Xlinker -rpath -Xlinker @loader_path/. + LFLAGS_VM += -Xlinker -rpath -Xlinker @loader_path/.. + LFLAGS_VM += -Xlinker -install_name -Xlinker @rpath/$(@F) + endif + + # JVM is statically linked with libgcc[_s] and libstdc++; this is needed to + # get around library dependency and compatibility issues. Must use gcc not + # g++ to link. + ifeq ($(STATIC_CXX), true) + LFLAGS_VM += $(STATIC_LIBGCC) + LIBS_VM += $(STATIC_STDCXX) + LINK_VM = $(LINK_LIB.c) + else + LINK_VM = $(LINK_LIB.CC) + endif + + LIBS_VM += $(LIBS) +endif +ifeq ($(ZERO_BUILD), true) + LIBS_VM += $(LIBFFI_LIBS) +endif +ifeq ($(SHARK_BUILD), true) + LFLAGS_VM += $(LLVM_LDFLAGS) + LIBS_VM += $(LLVM_LIBS) +endif + + +# rule for building precompiled header +$(PRECOMPILED_HEADER): + $(QUIETLY) echo Generating precompiled header $@ + $(QUIETLY) mkdir -p $(PRECOMPILED_HEADER_DIR) + $(QUIETLY) $(COMPILE.CC) $(DEPFLAGS) -x c++-header $(PRECOMPILED_HEADER_SRC) -o $@ $(COMPILE_DONE) + +# making the library: + +ifneq ($(JVM_BASE_ADDR),) +# By default shared library is linked at base address == 0. Modify the +# linker script if JVM prefers a different base location. It can also be +# implemented with 'prelink -r'. But 'prelink' is not (yet) available on +# our build platform (AS-2.1). +LD_SCRIPT = libjvm.so.lds +$(LD_SCRIPT): $(LIBJVM_MAPFILE) + $(QUIETLY) { \ + rm -rf $@; \ + $(LINK_VM) -Wl,--verbose $(LFLAGS_VM) 2>&1 | \ + sed -e '/^======/,/^======/!d' \ + -e '/^======/d' \ + -e 's/0\( + SIZEOF_HEADERS\)/$(JVM_BASE_ADDR)\1/' \ + > $@; \ + } +LD_SCRIPT_FLAG = -Wl,-T,$(LD_SCRIPT) +endif + +$(LIBJVM): $(LIBJVM.o) $(LIBJVM_MAPFILE) $(LD_SCRIPT) + $(QUIETLY) { \ + echo Linking vm...; \ + $(LINK_LIB.CC/PRE_HOOK) \ + $(LINK_VM) $(LD_SCRIPT_FLAG) \ + $(LFLAGS_VM) -o $@ $(LIBJVM.o) $(LIBS_VM); \ + $(LINK_LIB.CC/POST_HOOK) \ + rm -f $@.1; ln -s $@ $@.1; \ + [ -f $(LIBJVM_G) ] || { ln -s $@ $(LIBJVM_G); ln -s $@.1 $(LIBJVM_G).1; }; \ + } + +DEST_JVM = $(JDK_LIBDIR)/$(VM_SUBDIR)/$(LIBJVM) + +install_jvm: $(LIBJVM) + @echo "Copying $(LIBJVM) to $(DEST_JVM)" + $(QUIETLY) cp -f $(LIBJVM) $(DEST_JVM) && echo "Done" + +#---------------------------------------------------------------------- +# Other files + +# Gamma launcher +include $(MAKEFILES_DIR)/launcher.make + +# Signal interposition library +include $(MAKEFILES_DIR)/jsig.make + +# Serviceability agent +include $(MAKEFILES_DIR)/saproc.make + +#---------------------------------------------------------------------- + +ifeq ($(OS_VENDOR), Darwin) +$(LIBJVM).dSYM: $(LIBJVM) + dsymutil $(LIBJVM) + +# no launcher or libjvm_db for macosx +build: $(LIBJVM) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck $(LIBJVM).dSYM + echo "Doing vm.make build:" +else +build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) +endif + +install: install_jvm install_jsig install_saproc + +.PHONY: default build install install_jvm
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/zero.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,32 @@ +# +# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2009 Red Hat, Inc. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Setup for Zero (non-Shark) version of VM + +# Select which files to use (in top.make) +TYPE = ZERO + +# Install libjvm.so, etc in in server directory. +VM_SUBDIR = server
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/makefiles/zeroshark.make Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,62 @@ +# +# Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. +# Copyright 2007, 2008 Red Hat, Inc. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Setup common to Zero (non-Shark) and Shark versions of VM + +# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized +OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT) +# The copied fdlibm routines in sharedRuntimeTrans.o must not be optimized +OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT) + +# Specify that the CPU is little endian, if necessary +ifeq ($(ZERO_ENDIANNESS), little) + CFLAGS += -DVM_LITTLE_ENDIAN +endif + +# Specify that the CPU is 64 bit, if necessary +ifeq ($(ARCH_DATA_MODEL), 64) + CFLAGS += -D_LP64=1 +endif + +# Specify the path to the FFI headers +ifdef ALT_PACKAGE_PATH + PACKAGE_PATH = $(ALT_PACKAGE_PATH) +else + ifeq ($(OS_VENDOR),Apple) + PACKAGE_PATH = /opt/local + else + ifeq ($(OS_VENDOR),NetBSD) + PACKAGE_PATH = /usr/pkg + LIBS += -Wl,-R${PACKAGE_PATH}/lib + else + PACKAGE_PATH = /usr/local + endif + endif +endif + +CFLAGS += -I$(PACKAGE_PATH)/include +LIBS += -L$(PACKAGE_PATH)/lib -lffi + +OPT_CFLAGS/compactingPermGenGen.o = -O1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/platform_amd64 Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,15 @@ +os_family = bsd + +arch = x86 + +arch_model = x86_64 + +os_arch = bsd_x86 + +os_arch_model = bsd_x86_64 + +lib_arch = amd64 + +compiler = gcc + +sysdefs = -D_ALLBSD_SOURCE -D_GNU_SOURCE -DAMD64
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/platform_amd64.suncc Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,17 @@ +os_family = bsd + +arch = x86 + +arch_model = x86_64 + +os_arch = bsd_x86 + +os_arch_model = bsd_x86_64 + +lib_arch = amd64 + +compiler = sparcWorks + +gnu_dis_arch = amd64 + +sysdefs = -D_ALLBSD_SOURCE -DSPARC_WORKS -D_GNU_SOURCE -DAMD64
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/platform_i486 Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,15 @@ +os_family = bsd + +arch = x86 + +arch_model = x86_32 + +os_arch = bsd_x86 + +os_arch_model = bsd_x86_32 + +lib_arch = i386 + +compiler = gcc + +sysdefs = -D_ALLBSD_SOURCE -D_GNU_SOURCE -DIA32
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/platform_i486.suncc Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,17 @@ +os_family = bsd + +arch = x86 + +arch_model = x86_32 + +os_arch = bsd_x86 + +os_arch_model = bsd_x86_32 + +lib_arch = i386 + +compiler = sparcWorks + +gnu_dis_arch = i386 + +sysdefs = -D_ALLBSD_SOURCE -DSPARC_WORKS -D_GNU_SOURCE -DIA32
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/platform_ia64 Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,15 @@ +os_family = bsd + +arch = ia64 + +os_arch = bsd_ia64 + +lib_arch = ia64 + +compiler = gcc + +gnu_dis_arch = ia64 + +sysdefs = -D_ALLBSD_SOURCE -D_GNU_SOURCE -DIA64 -DCC_INTERP + +mark_style = alignment
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/platform_sparc Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,15 @@ +os_family = bsd + +arch = sparc + +arch_model = sparc + +os_arch = bsd_sparc + +os_arch_model = bsd_sparc + +lib_arch = sparc + +compiler = gcc + +sysdefs = -D_ALLBSD_SOURCE -D_GNU_SOURCE -DSPARC
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/platform_sparcv9 Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,15 @@ +os_family = bsd + +arch = sparc + +arch_model = sparc + +os_arch = bsd_sparc + +os_arch_model = bsd_sparc + +lib_arch = sparcv9 + +compiler = gcc + +sysdefs = -D_ALLBSD_SOURCE -D_GNU_SOURCE -DSPARC
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/bsd/platform_zero.in Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,17 @@ +os_family = bsd + +arch = zero + +arch_model = zero + +os_arch = bsd_zero + +os_arch_model = bsd_zero + +lib_arch = zero + +compiler = gcc + +gnu_dis_arch = zero + +sysdefs = -D_ALLBSD_SOURCE -D_GNU_SOURCE -DCC_INTERP -DZERO -D@ZERO_ARCHDEF@ -DZERO_LIBARCH=\"@ZERO_LIBARCH@\"
--- a/make/cscope.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/cscope.make Thu Oct 27 12:21:43 2011 -0700 @@ -63,7 +63,7 @@ # space-separated list of identifiers to include only those systems. ifdef CS_OS CS_PRUNE_OS = $(patsubst %,-o -name '*%*',\ - $(filter-out ${CS_OS},linux macos solaris windows)) + $(filter-out ${CS_OS},bsd linux macos solaris windows)) endif # CPU-specific files for all processors are included by default. Set CS_CPU
--- a/make/defs.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/defs.make Thu Oct 27 12:21:43 2011 -0700 @@ -118,13 +118,23 @@ # Windows should have OS predefined ifeq ($(OS),) OS := $(shell uname -s) + ifneq ($(findstring BSD,$(OS)),) + OS=bsd + endif + ifeq ($(OS), Darwin) + OS=bsd + endif HOST := $(shell uname -n) endif -# If not SunOS and not Linux, assume Windows +# If not SunOS, not Linux and not BSD, assume Windows ifneq ($(OS), Linux) ifneq ($(OS), SunOS) - OSNAME=windows + ifneq ($(OS), bsd) + OSNAME=windows + else + OSNAME=bsd + endif else OSNAME=solaris endif @@ -271,6 +281,13 @@ EXPORT_JRE_LIB_DIR = $(EXPORT_JRE_DIR)/lib EXPORT_JRE_LIB_ARCH_DIR = $(EXPORT_JRE_LIB_DIR)/$(LIBARCH) +# non-universal macosx builds need to appear universal +ifeq ($(OS_VENDOR), Darwin) + ifneq ($(MACOSX_UNIVERSAL), true) + EXPORT_JRE_LIB_ARCH_DIR = $(EXPORT_JRE_LIB_DIR) + endif +endif + # Common export list of files EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jvmti.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jvmticmlr.h
--- a/make/hotspot_version Wed Oct 26 12:43:05 2011 -0700 +++ b/make/hotspot_version Thu Oct 27 12:21:43 2011 -0700 @@ -33,9 +33,9 @@ # Don't put quotes (fail windows build). HOTSPOT_VM_COPYRIGHT=Copyright 2011 -HS_MAJOR_VER=22 +HS_MAJOR_VER=23 HS_MINOR_VER=0 -HS_BUILD_NUMBER=06 +HS_BUILD_NUMBER=03 JDK_MAJOR_VER=1 JDK_MINOR_VER=8
--- a/make/linux/Makefile Wed Oct 26 12:43:05 2011 -0700 +++ b/make/linux/Makefile Thu Oct 27 12:21:43 2011 -0700 @@ -210,6 +210,7 @@ BUILDTREE_MAKE = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) BUILDTREE_VARS += HOTSPOT_RELEASE_VERSION=$(HOTSPOT_RELEASE_VERSION) HOTSPOT_BUILD_VERSION=$(HOTSPOT_BUILD_VERSION) JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) +BUILDTREE_VARS += OBJCOPY=$(OBJCOPY) STRIP_POLICY=$(STRIP_POLICY) BUILDTREE = $(MAKE) -f $(BUILDTREE_MAKE) $(BUILDTREE_VARS)
--- a/make/linux/build.sh Wed Oct 26 12:43:05 2011 -0700 +++ b/make/linux/build.sh Thu Oct 27 12:21:43 2011 -0700 @@ -1,6 +1,6 @@ #! /bin/sh # -# Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -45,6 +45,9 @@ i386|i486|i586|i686) mach=i386 ;; + x86_64) + mach=amd64 + ;; *) echo "Unsupported machine: " `uname -m` exit 1
--- a/make/linux/makefiles/arm.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/linux/makefiles/arm.make Thu Oct 27 12:21:43 2011 -0700 @@ -1,6 +1,25 @@ # # Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. -# ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# # Obj_Files += linux_arm.o
--- a/make/linux/makefiles/build_vm_def.sh Wed Oct 26 12:43:05 2011 -0700 +++ b/make/linux/makefiles/build_vm_def.sh Thu Oct 27 12:21:43 2011 -0700 @@ -7,6 +7,10 @@ NM=nm fi -$NM --defined-only $* | awk ' - { if ($3 ~ /^_ZTV/ || $3 ~ /^gHotSpotVM/) print "\t" $3 ";" } - ' +$NM --defined-only $* \ + | awk '{ + if ($3 ~ /^_ZTV/ || $3 ~ /^gHotSpotVM/) print "\t" $3 ";" + if ($3 ~ /^UseSharedSpaces$/) print "\t" $3 ";" + if ($3 ~ /^_ZN9Arguments17SharedArchivePathE$/) print "\t" $3 ";" + }' \ + | sort -u
--- a/make/linux/makefiles/buildtree.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/linux/makefiles/buildtree.make Thu Oct 27 12:21:43 2011 -0700 @@ -233,6 +233,10 @@ echo "$(call gamma-path,commonsrc,os/posix/vm)"; \ [ -n "$(CFLAGS_BROWSE)" ] && \ echo && echo "CFLAGS_BROWSE = $(CFLAGS_BROWSE)"; \ + [ -n "$(OBJCOPY)" ] && \ + echo && echo "OBJCOPY = $(OBJCOPY)"; \ + [ -n "$(STRIP_POLICY)" ] && \ + echo && echo "STRIP_POLICY = $(STRIP_POLICY)"; \ [ -n "$(HOTSPOT_EXTRA_SYSDEFS)" ] && \ echo && \ echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \
--- a/make/linux/makefiles/defs.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/linux/makefiles/defs.make Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 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 @@ -114,36 +114,113 @@ HS_ARCH = ppc endif +# determine if HotSpot is being built in JDK6 or earlier version +JDK6_OR_EARLIER=0 +ifeq "$(shell expr \( '$(JDK_MAJOR_VERSION)' != '' \& '$(JDK_MINOR_VERSION)' != '' \& '$(JDK_MICRO_VERSION)' != '' \))" "1" + # if the longer variable names (newer build style) are set, then check those + ifeq "$(shell expr \( $(JDK_MAJOR_VERSION) = 1 \& $(JDK_MINOR_VERSION) \< 7 \))" "1" + JDK6_OR_EARLIER=1 + endif +else + # the longer variables aren't set so check the shorter variable names + ifeq "$(shell expr \( '$(JDK_MAJOR_VER)' = 1 \& '$(JDK_MINOR_VER)' \< 7 \))" "1" + JDK6_OR_EARLIER=1 + endif +endif + +ifeq ($(JDK6_OR_EARLIER),0) + # Full Debug Symbols is supported on JDK7 or newer + + # Default OBJCOPY comes from GNU Binutils on Linux: + DEF_OBJCOPY=/usr/bin/objcopy + ifdef CROSS_COMPILE_ARCH + # don't try to generate .debuginfo files when cross compiling + _JUNK_ := $(shell \ + echo >&2 "INFO: cross compiling for ARCH $(CROSS_COMPILE_ARCH)," \ + "skipping .debuginfo generation.") + OBJCOPY= + else + OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY)) + ifneq ($(ALT_OBJCOPY),) + _JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)") + # disable .debuginfo support by setting ALT_OBJCOPY to a non-existent path + OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY)) + endif + endif + + ifeq ($(OBJCOPY),) + _JUNK_ := $(shell \ + echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files.") + else + _JUNK_ := $(shell \ + echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.") + + # Library stripping policies for .debuginfo configs: + # all_strip - strips everything from the library + # min_strip - strips most stuff from the library; leaves minimum symbols + # no_strip - does not strip the library at all + # + # Oracle security policy requires "all_strip". A waiver was granted on + # 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE. + # + DEF_STRIP_POLICY="min_strip" + ifeq ($(ALT_STRIP_POLICY),) + STRIP_POLICY=$(DEF_STRIP_POLICY) + else + STRIP_POLICY=$(ALT_STRIP_POLICY) + endif + + _JUNK_ := $(shell \ + echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)") + endif +endif + JDK_INCLUDE_SUBDIR=linux +# Library suffix +LIBRARY_SUFFIX=so + # FIXUP: The subdirectory for a debug build is NOT the same on all platforms VM_DEBUG=jvmg EXPORT_LIST += $(EXPORT_DOCS_DIR)/platform/jvmti/jvmti.html # client and server subdirectories have symbolic links to ../libjsig.so -EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.so +EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.$(LIBRARY_SUFFIX) +ifneq ($(OBJCOPY),) + EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.debuginfo +endif EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client ifndef BUILD_CLIENT_ONLY EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt -EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.so +EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX) + ifneq ($(OBJCOPY),) + EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.debuginfo + endif endif ifneq ($(ZERO_BUILD), true) ifeq ($(ARCH_DATA_MODEL), 32) EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt - EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.so + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX) + ifneq ($(OBJCOPY),) + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo + endif endif endif # Serviceability Binaries # No SA Support for PPC, IA64, ARM or zero -ADD_SA_BINARIES/x86 = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.so \ +ADD_SA_BINARIES/x86 = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.$(LIBRARY_SUFFIX) \ + $(EXPORT_LIB_DIR)/sa-jdi.jar +ADD_SA_BINARIES/sparc = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.$(LIBRARY_SUFFIX) \ $(EXPORT_LIB_DIR)/sa-jdi.jar -ADD_SA_BINARIES/sparc = $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.so \ - $(EXPORT_LIB_DIR)/sa-jdi.jar +ifneq ($(OBJCOPY),) + ADD_SA_BINARIES/x86 += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo + ADD_SA_BINARIES/sparc += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo +endif ADD_SA_BINARIES/ppc = ADD_SA_BINARIES/ia64 = ADD_SA_BINARIES/arm =
--- a/make/linux/makefiles/gcc.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/linux/makefiles/gcc.make Thu Oct 27 12:21:43 2011 -0700 @@ -225,6 +225,26 @@ DEBUG_CFLAGS += -gstabs endif +ifneq ($(OBJCOPY),) + FASTDEBUG_CFLAGS/ia64 = -g + FASTDEBUG_CFLAGS/amd64 = -g + FASTDEBUG_CFLAGS/arm = -g + FASTDEBUG_CFLAGS/ppc = -g + FASTDEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH)) + ifeq ($(FASTDEBUG_CFLAGS/$(BUILDARCH)),) + FASTDEBUG_CFLAGS += -gstabs + endif + + OPT_CFLAGS/ia64 = -g + OPT_CFLAGS/amd64 = -g + OPT_CFLAGS/arm = -g + OPT_CFLAGS/ppc = -g + OPT_CFLAGS += $(OPT_CFLAGS/$(BUILDARCH)) + ifeq ($(OPT_CFLAGS/$(BUILDARCH)),) + OPT_CFLAGS += -gstabs + endif +endif + # DEBUG_BINARIES overrides everything, use full -g debug information ifeq ($(DEBUG_BINARIES), true) DEBUG_CFLAGS = -g @@ -242,3 +262,9 @@ ifdef MINIMIZE_RAM_USAGE CFLAGS += -DMINIMIZE_RAM_USAGE endif + +ifdef CROSS_COMPILE_ARCH + STRIP = $(ALT_COMPILER_PATH)/strip +else + STRIP = strip +endif
--- a/make/linux/makefiles/jsig.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/linux/makefiles/jsig.make Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -31,9 +31,13 @@ JSIG_G = $(JSIG)$(G_SUFFIX) LIBJSIG_G = lib$(JSIG_G).so +LIBJSIG_DEBUGINFO = lib$(JSIG).debuginfo +LIBJSIG_G_DEBUGINFO = lib$(JSIG_G).debuginfo + JSIGSRCDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/vm -DEST_JSIG = $(JDK_LIBDIR)/$(LIBJSIG) +DEST_JSIG = $(JDK_LIBDIR)/$(LIBJSIG) +DEST_JSIG_DEBUGINFO = $(JDK_LIBDIR)/$(LIBJSIG_DEBUGINFO) LIBJSIG_MAPFILE = $(MAKEFILES_DIR)/mapfile-vers-jsig @@ -54,9 +58,24 @@ $(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \ $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) -o $@ $< -ldl $(QUIETLY) [ -f $(LIBJSIG_G) ] || { ln -s $@ $(LIBJSIG_G); } +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJSIG_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJSIG_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -g $@ + # implied else here is no stripping at all + endif + endif + [ -f $(LIBJSIG_G_DEBUGINFO) ] || { ln -s $(LIBJSIG_DEBUGINFO) $(LIBJSIG_G_DEBUGINFO); } +endif install_jsig: $(LIBJSIG) @echo "Copying $(LIBJSIG) to $(DEST_JSIG)" + $(QUIETLY) test -f $(LIBJSIG_DEBUGINFO) && \ + cp -f $(LIBJSIG_DEBUGINFO) $(DEST_JSIG_DEBUGINFO) $(QUIETLY) cp -f $(LIBJSIG) $(DEST_JSIG) && echo "Done" .PHONY: install_jsig
--- a/make/linux/makefiles/ppc.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/linux/makefiles/ppc.make Thu Oct 27 12:21:43 2011 -0700 @@ -1,6 +1,25 @@ # # Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. -# ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# # # The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized
--- a/make/linux/makefiles/product.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/linux/makefiles/product.make Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -46,13 +46,10 @@ # use -g to strip library as -x will discard its symbol table; -x is fine for # executables. -ifdef CROSS_COMPILE_ARCH - STRIP = $(ALT_COMPILER_PATH)/strip -else - STRIP = strip -endif +# Note: these macros are not used in .debuginfo configs STRIP_LIBJVM = $(STRIP) -g $@ || exit 1; STRIP_AOUT = $(STRIP) -x $@ || exit 1; -# Don't strip in VM build; JDK build will strip libraries later +# If we can create .debuginfo files, then the VM is stripped in vm.make +# and this macro is not used. # LINK_LIB.CC/POST_HOOK += $(STRIP_$(LINK_INTO))
--- a/make/linux/makefiles/sa.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/linux/makefiles/sa.make Thu Oct 27 12:21:43 2011 -0700 @@ -43,13 +43,7 @@ # TODO: if it's a modules image, check if SA module is installed. MODULELIB_PATH= $(BOOT_JAVA_HOME)/lib/modules -# gnumake 3.78.1 does not accept the *s that -# are in AGENT_FILES1 and AGENT_FILES2, so use the shell to expand them -AGENT_FILES1 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES1)) -AGENT_FILES2 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES2)) - -AGENT_FILES1_LIST := $(GENERATED)/agent1.classes.list -AGENT_FILES2_LIST := $(GENERATED)/agent2.classes.list +AGENT_FILES_LIST := $(GENERATED)/agent.classes.list SA_CLASSDIR = $(GENERATED)/saclasses @@ -68,7 +62,7 @@ $(MAKE) -f sa.make $(GENERATED)/sa-jdi.jar; \ fi -$(GENERATED)/sa-jdi.jar: $(AGENT_FILES1) $(AGENT_FILES2) +$(GENERATED)/sa-jdi.jar: $(AGENT_FILES) $(QUIETLY) echo "Making $@" $(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \ echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \ @@ -82,7 +76,6 @@ $(QUIETLY) if [ ! -d $(SA_CLASSDIR) ] ; then \ mkdir -p $(SA_CLASSDIR); \ fi - # Note: When indented, make tries to execute the '$(shell' comment. # In some environments, cmd processors have limited line length. # To prevent the javac invocation in the next block from using @@ -93,13 +86,12 @@ # the initialization of the lists is also done in the same phase # using '$(shell rm ...' instead of using the more traditional # 'rm ...' rule. - $(shell rm -rf $(AGENT_FILES1_LIST) $(AGENT_FILES2_LIST)) - $(foreach file,$(AGENT_FILES1),$(shell echo $(file) >> $(AGENT_FILES1_LIST))) - $(foreach file,$(AGENT_FILES2),$(shell echo $(file) >> $(AGENT_FILES2_LIST))) - - $(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES1_LIST) - $(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES2_LIST) - + $(shell rm -rf $(AGENT_FILES_LIST)) +# gnumake 3.78.1 does not accept the *'s that +# are in AGENT_FILES, so use the shell to expand them. +# Be extra carefull to not produce too long command lines in the shell! + $(foreach file,$(AGENT_FILES),$(shell ls -1 $(file) >> $(AGENT_FILES_LIST))) + $(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES_LIST) $(QUIETLY) $(REMOTE) $(COMPILE.RMIC) -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer $(QUIETLY) echo "$(SA_BUILD_VERSION_PROP)" > $(SA_PROPERTIES) $(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql/sa.js @@ -118,4 +110,4 @@ clean: rm -rf $(SA_CLASSDIR) rm -rf $(GENERATED)/sa-jdi.jar - rm -rf $(AGENT_FILES1_LIST) $(AGENT_FILES2_LIST) + rm -rf $(AGENT_FILES_LIST)
--- a/make/linux/makefiles/saproc.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/linux/makefiles/saproc.make Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -32,6 +32,9 @@ SAPROC_G = $(SAPROC)$(G_SUFFIX) LIBSAPROC_G = lib$(SAPROC_G).so +LIBSAPROC_DEBUGINFO = lib$(SAPROC).debuginfo +LIBSAPROC_G_DEBUGINFO = lib$(SAPROC_G).debuginfo + AGENT_DIR = $(GAMMADIR)/agent SASRCDIR = $(AGENT_DIR)/src/os/$(Platform_os_family) @@ -45,7 +48,8 @@ SAMAPFILE = $(SASRCDIR)/mapfile -DEST_SAPROC = $(JDK_LIBDIR)/$(LIBSAPROC) +DEST_SAPROC = $(JDK_LIBDIR)/$(LIBSAPROC) +DEST_SAPROC_DEBUGINFO = $(JDK_LIBDIR)/$(LIBSAPROC_DEBUGINFO) # DEBUG_BINARIES overrides everything, use full -g debug information ifeq ($(DEBUG_BINARIES), true) @@ -82,10 +86,25 @@ -o $@ \ -lthread_db $(QUIETLY) [ -f $(LIBSAPROC_G) ] || { ln -s $@ $(LIBSAPROC_G); } +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBSAPROC_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBSAPROC_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -g $@ + # implied else here is no stripping at all + endif + endif + [ -f $(LIBSAPROC_G_DEBUGINFO) ] || { ln -s $(LIBSAPROC_DEBUGINFO) $(LIBSAPROC_G_DEBUGINFO); } +endif install_saproc: $(BUILDLIBSAPROC) $(QUIETLY) if [ -e $(LIBSAPROC) ] ; then \ echo "Copying $(LIBSAPROC) to $(DEST_SAPROC)"; \ + test -f $(LIBSAPROC_DEBUGINFO) && \ + cp -f $(LIBSAPROC_DEBUGINFO) $(DEST_SAPROC_DEBUGINFO); \ cp -f $(LIBSAPROC) $(DEST_SAPROC) && echo "Done"; \ fi
--- a/make/linux/makefiles/vm.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/linux/makefiles/vm.make Thu Oct 27 12:21:43 2011 -0700 @@ -60,10 +60,16 @@ # The order is important for the precompiled headers to work. INCLUDES += $(PRECOMPILED_HEADER_DIR:%=-I%) $(Src_Dirs_I:%=-I%) -ifeq (${VERSION}, debug) +# SYMFLAG is used by {jsig,saproc}.make +ifneq ($(OBJCOPY),) + # always build with debug info when we can create .debuginfo files SYMFLAG = -g else - SYMFLAG = + ifeq (${VERSION}, debug) + SYMFLAG = -g + else + SYMFLAG = + endif endif # HOTSPOT_RELEASE_VERSION and HOTSPOT_BUILD_VERSION are defined @@ -124,6 +130,9 @@ LIBJVM = lib$(JVM).so LIBJVM_G = lib$(JVM)$(G_SUFFIX).so +LIBJVM_DEBUGINFO = lib$(JVM).debuginfo +LIBJVM_G_DEBUGINFO = lib$(JVM)$(G_SUFFIX).debuginfo + SPECIAL_PATHS:=adlc c1 gc_implementation opto shark libadt SOURCE_PATHS=\ @@ -307,11 +316,30 @@ fi \ fi \ } +ifeq ($(CROSS_COMPILE_ARCH),) + ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJVM_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -g $@ + # implied else here is no stripping at all + endif + endif + $(QUIETLY) [ -f $(LIBJVM_G_DEBUGINFO) ] || ln -s $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO) + endif +endif -DEST_JVM = $(JDK_LIBDIR)/$(VM_SUBDIR)/$(LIBJVM) +DEST_SUBDIR = $(JDK_LIBDIR)/$(VM_SUBDIR) +DEST_JVM = $(DEST_SUBDIR)/$(LIBJVM) +DEST_JVM_DEBUGINFO = $(DEST_SUBDIR)/$(LIBJVM_DEBUGINFO) install_jvm: $(LIBJVM) @echo "Copying $(LIBJVM) to $(DEST_JVM)" + $(QUIETLY) test -f $(LIBJVM_DEBUGINFO) && \ + cp -f $(LIBJVM_DEBUGINFO) $(DEST_JVM_DEBUGINFO) $(QUIETLY) cp -f $(LIBJVM) $(DEST_JVM) && echo "Done" #----------------------------------------------------------------------
--- a/make/sa.files Wed Oct 26 12:43:05 2011 -0700 +++ b/make/sa.files Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 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 @@ -36,7 +36,7 @@ # Splitted the set of files into two sets because on linux plaform # listing or compiling all the files results in 'Argument list too long' error. -AGENT_FILES1 = \ +AGENT_FILES = \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/amd64/*.java \ @@ -51,6 +51,9 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/compiler/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/amd64/*.java \ +$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/bsd/*.java \ +$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/bsd/amd64/*.java \ +$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/bsd/x86/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/basic/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/basic/x86/*.java \ @@ -79,6 +82,7 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/ia64/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/x86/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/x86/*.java \ +$(AGENT_SRC_DIR)/sun/jvm/hotspot/gc_implementation/g1/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/gc_implementation/parallelScavenge/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/gc_implementation/shared/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/gc_interface/*.java \ @@ -88,12 +92,12 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/memory/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/oops/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/opto/*.java \ -$(AGENT_SRC_DIR)/sun/jvm/hotspot/prims/*.java - - -AGENT_FILES2 = \ +$(AGENT_SRC_DIR)/sun/jvm/hotspot/prims/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/amd64/*.java \ +$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/bsd/*.java \ +$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/bsd_amd64/*.java \ +$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/bsd_x86/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/ia64/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_amd64/*.java \
--- a/make/solaris/Makefile Wed Oct 26 12:43:05 2011 -0700 +++ b/make/solaris/Makefile Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 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 @@ -168,6 +168,7 @@ BUILDTREE_MAKE = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) ARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) BUILDTREE_VARS += HOTSPOT_RELEASE_VERSION=$(HOTSPOT_RELEASE_VERSION) HOTSPOT_BUILD_VERSION=$(HOTSPOT_BUILD_VERSION) JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) +BUILDTREE_VARS += OBJCOPY=$(OBJCOPY) STRIP_POLICY=$(STRIP_POLICY) BUILDTREE = $(MAKE) -f $(BUILDTREE_MAKE) $(BUILDTREE_VARS)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/solaris/makefiles/build_vm_def.sh Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,10 @@ +#!/bin/sh + +/usr/ccs/bin/nm -p $* \ + | awk '{ + if ($2 == "U") next + if ($3 ~ /^__1c.*__vtbl_$/ || $3 ~ /^gHotSpotVM/) print "\t" $3 ";" + if ($3 ~ /^UseSharedSpaces$/) print "\t" $3 ";" + if ($3 ~ /^__1cJArgumentsRSharedArchivePath_$/) print "\t" $3 ";" + }' \ + | sort -u
--- a/make/solaris/makefiles/buildtree.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/solaris/makefiles/buildtree.make Thu Oct 27 12:21:43 2011 -0700 @@ -226,6 +226,10 @@ echo "$(call gamma-path,commonsrc,os/posix/vm)"; \ [ -n "$(CFLAGS_BROWSE)" ] && \ echo && echo "CFLAGS_BROWSE = $(CFLAGS_BROWSE)"; \ + [ -n "$(OBJCOPY)" ] && \ + echo && echo "OBJCOPY = $(OBJCOPY)"; \ + [ -n "$(STRIP_POLICY)" ] && \ + echo && echo "STRIP_POLICY = $(STRIP_POLICY)"; \ [ -n "$(HOTSPOT_EXTRA_SYSDEFS)" ] && \ echo && \ echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \
--- a/make/solaris/makefiles/defs.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/solaris/makefiles/defs.make Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 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 @@ -59,37 +59,135 @@ endif endif +# determine if HotSpot is being built in JDK6 or earlier version +JDK6_OR_EARLIER=0 +ifeq "$(shell expr \( '$(JDK_MAJOR_VERSION)' != '' \& '$(JDK_MINOR_VERSION)' != '' \& '$(JDK_MICRO_VERSION)' != '' \))" "1" + # if the longer variable names (newer build style) are set, then check those + ifeq "$(shell expr \( $(JDK_MAJOR_VERSION) = 1 \& $(JDK_MINOR_VERSION) \< 7 \))" "1" + JDK6_OR_EARLIER=1 + endif +else + # the longer variables aren't set so check the shorter variable names + ifeq "$(shell expr \( '$(JDK_MAJOR_VER)' = 1 \& '$(JDK_MINOR_VER)' \< 7 \))" "1" + JDK6_OR_EARLIER=1 + endif +endif + +ifeq ($(JDK6_OR_EARLIER),0) + # Full Debug Symbols is supported on JDK7 or newer + +ifdef ENABLE_FULL_DEBUG_SYMBOLS + # Only check for Full Debug Symbols support on Solaris if it is + # specifically enabled. Hopefully, it can be enabled by default + # once the .debuginfo size issues are worked out. + + # Default OBJCOPY comes from the SUNWbinutils package: + DEF_OBJCOPY=/usr/sfw/bin/gobjcopy + ifeq ($(VM_PLATFORM),solaris_amd64) + # On Solaris AMD64/X64, gobjcopy is not happy and fails: + # + # usr/sfw/bin/gobjcopy --add-gnu-debuglink=<lib>.debuginfo <lib>.so + # BFD: stKPaiop: Not enough room for program headers, try linking with -N + # /usr/sfw/bin/gobjcopy: stKPaiop: Bad value + # BFD: stKPaiop: Not enough room for program headers, try linking with -N + # /usr/sfw/bin/gobjcopy: libsaproc.debuginfo: Bad value + # BFD: stKPaiop: Not enough room for program headers, try linking with -N + # /usr/sfw/bin/gobjcopy: stKPaiop: Bad value + _JUNK_ := $(shell \ + echo >&2 "INFO: $(DEF_OBJCOPY) is not working on Solaris AMD64/X64") + OBJCOPY= + else + OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY)) + ifneq ($(ALT_OBJCOPY),) + _JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)") + # disable .debuginfo support by setting ALT_OBJCOPY to a non-existent path + OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY)) + endif + endif +endif + + ifeq ($(OBJCOPY),) + _JUNK_ := $(shell \ + echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files.") + else + _JUNK_ := $(shell \ + echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.") + + # Library stripping policies for .debuginfo configs: + # all_strip - strips everything from the library + # min_strip - strips most stuff from the library; leaves minimum symbols + # no_strip - does not strip the library at all + # + # Oracle security policy requires "all_strip". A waiver was granted on + # 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE. + # + DEF_STRIP_POLICY="min_strip" + ifeq ($(ALT_STRIP_POLICY),) + STRIP_POLICY=$(DEF_STRIP_POLICY) + else + STRIP_POLICY=$(ALT_STRIP_POLICY) + endif + _JUNK_ := $(shell \ + echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)") + endif +endif + JDK_INCLUDE_SUBDIR=solaris +# Library suffix +LIBRARY_SUFFIX=so + # FIXUP: The subdirectory for a debug build is NOT the same on all platforms VM_DEBUG=jvmg EXPORT_LIST += $(EXPORT_DOCS_DIR)/platform/jvmti/jvmti.html -# client and server subdirectories have symbolic links to ../libjsig.so -EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.so +# client and server subdirectories have symbolic links to ../libjsig.$(LIBRARY_SUFFIX) +EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.$(LIBRARY_SUFFIX) +ifneq ($(OBJCOPY),) + EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libjsig.debuginfo +endif EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client ifneq ($(BUILD_CLIENT_ONLY),true) EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt -EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.so -EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_db.so -EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_dtrace.so +EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX) +EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_db.$(LIBRARY_SUFFIX) +EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_dtrace.$(LIBRARY_SUFFIX) + ifneq ($(OBJCOPY),) + EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.debuginfo + EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_db.debuginfo + EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_dtrace.debuginfo + endif endif ifeq ($(ARCH_DATA_MODEL), 32) EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt - EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.so - EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.so - EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.so - EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.so - EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.so + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX) + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.$(LIBRARY_SUFFIX) + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.$(LIBRARY_SUFFIX) + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.$(LIBRARY_SUFFIX) + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.$(LIBRARY_SUFFIX) + ifneq ($(OBJCOPY),) + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.debuginfo + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.debuginfo + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.debuginfo + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.debuginfo + endif ifneq ($(BUILD_CLIENT_ONLY), true) - EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.so - EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.so + EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.$(LIBRARY_SUFFIX) + EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.$(LIBRARY_SUFFIX) + ifneq ($(OBJCOPY),) + EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.debuginfo + EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.debuginfo + endif endif endif -EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.so +EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.$(LIBRARY_SUFFIX) +ifneq ($(OBJCOPY),) + EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.debuginfo +endif EXPORT_LIST += $(EXPORT_LIB_DIR)/sa-jdi.jar
--- a/make/solaris/makefiles/dtrace.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/solaris/makefiles/dtrace.make Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -41,10 +41,16 @@ LIBJVM_DB = libjvm_db.so LIBJVM_DB_G = libjvm$(G_SUFFIX)_db.so +LIBJVM_DB_DEBUGINFO = libjvm_db.debuginfo +LIBJVM_DB_G_DEBUGINFO = libjvm$(G_SUFFIX)_db.debuginfo + JVM_DTRACE = jvm_dtrace LIBJVM_DTRACE = libjvm_dtrace.so LIBJVM_DTRACE_G = libjvm$(G_SUFFIX)_dtrace.so +LIBJVM_DTRACE_DEBUGINFO = libjvm_dtrace.debuginfo +LIBJVM_DTRACE_G_DEBUGINFO = libjvm$(G_SUFFIX)_dtrace.debuginfo + JVMOFFS = JvmOffsets JVMOFFS.o = $(JVMOFFS).o GENOFFS = generate$(JVMOFFS) @@ -89,12 +95,30 @@ XLIBJVM_DTRACE = 64/$(LIBJVM_DTRACE) XLIBJVM_DTRACE_G = 64/$(LIBJVM_DTRACE_G) +XLIBJVM_DB_DEBUGINFO = 64/$(LIBJVM_DB_DEBUGINFO) +XLIBJVM_DB_G_DEBUGINFO = 64/$(LIBJVM_DB_G_DEBUGINFO) +XLIBJVM_DTRACE_DEBUGINFO = 64/$(LIBJVM_DTRACE_DEBUGINFO) +XLIBJVM_DTRACE_G_DEBUGINFO = 64/$(LIBJVM_DTRACE_G_DEBUGINFO) + $(XLIBJVM_DB): $(DTRACE_SRCDIR)/$(JVM_DB).c $(JVMOFFS).h $(LIBJVM_DB_MAPFILE) @echo Making $@ $(QUIETLY) mkdir -p 64/ ; \ $(CC) $(SYMFLAG) $(ARCHFLAG/$(ISA)) -D$(TYPE) -I. -I$(GENERATED) \ $(SHARED_FLAG) $(LFLAGS_JVM_DB) -o $@ $(DTRACE_SRCDIR)/$(JVM_DB).c -lc [ -f $(XLIBJVM_DB_G) ] || { ln -s $(LIBJVM_DB) $(XLIBJVM_DB_G); } +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(XLIBJVM_DB_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(XLIBJVM_DB_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -x $@ + # implied else here is no stripping at all + endif + endif + [ -f $(XLIBJVM_DB_G_DEBUGINFO) ] || { ln -s $(LIBJVM_DB_DEBUGINFO) $(XLIBJVM_DB_G_DEBUGINFO); } +endif $(XLIBJVM_DTRACE): $(DTRACE_SRCDIR)/$(JVM_DTRACE).c $(DTRACE_SRCDIR)/$(JVM_DTRACE).h $(LIBJVM_DTRACE_MAPFILE) @echo Making $@ @@ -102,6 +126,19 @@ $(CC) $(SYMFLAG) $(ARCHFLAG/$(ISA)) -D$(TYPE) -I. \ $(SHARED_FLAG) $(LFLAGS_JVM_DTRACE) -o $@ $(DTRACE_SRCDIR)/$(JVM_DTRACE).c -lc -lthread -ldoor [ -f $(XLIBJVM_DTRACE_G) ] || { ln -s $(LIBJVM_DTRACE) $(XLIBJVM_DTRACE_G); } +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(XLIBJVM_DTRACE_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(XLIBJVM_DTRACE_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -x $@ + # implied else here is no stripping at all + endif + endif + [ -f $(XLIBJVM_DTRACE_G_DEBUGINFO) ] || { ln -s $(LIBJVM_DTRACE_DEBUGINFO) $(XLIBJVM_DTRACE_G_DEBUGINFO); } +endif endif # ifneq ("${ISA}","${BUILDARCH}") @@ -148,12 +185,38 @@ $(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) -D$(TYPE) -I. -I$(GENERATED) \ $(SHARED_FLAG) $(LFLAGS_JVM_DB) -o $@ $(DTRACE_SRCDIR)/$(JVM_DB).c -lc [ -f $(LIBJVM_DB_G) ] || { ln -s $@ $(LIBJVM_DB_G); } +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJVM_DB_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DB_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -x $@ + # implied else here is no stripping at all + endif + endif + [ -f $(LIBJVM_DB_G_DEBUGINFO) ] || { ln -s $(LIBJVM_DB_DEBUGINFO) $(LIBJVM_DB_G_DEBUGINFO); } +endif $(LIBJVM_DTRACE): $(DTRACE_SRCDIR)/$(JVM_DTRACE).c $(XLIBJVM_DTRACE) $(DTRACE_SRCDIR)/$(JVM_DTRACE).h $(LIBJVM_DTRACE_MAPFILE) @echo Making $@ $(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) -D$(TYPE) -I. \ $(SHARED_FLAG) $(LFLAGS_JVM_DTRACE) -o $@ $(DTRACE_SRCDIR)/$(JVM_DTRACE).c -lc -lthread -ldoor [ -f $(LIBJVM_DTRACE_G) ] || { ln -s $@ $(LIBJVM_DTRACE_G); } +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJVM_DTRACE_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DTRACE_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -x $@ + # implied else here is no stripping at all + endif + endif + [ -f $(LIBJVM_DTRACE_G_DEBUGINFO) ] || { ln -s $(LIBJVM_DTRACE_DEBUGINFO) $(LIBJVM_DTRACE_G_DEBUGINFO); } +endif $(DTRACE).d: $(DTRACE_SRCDIR)/hotspot.d $(DTRACE_SRCDIR)/hotspot_jni.d \ $(DTRACE_SRCDIR)/hs_private.d $(DTRACE_SRCDIR)/jhelper.d
--- a/make/solaris/makefiles/jsig.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/solaris/makefiles/jsig.make Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -31,9 +31,13 @@ JSIG_G = $(JSIG)$(G_SUFFIX) LIBJSIG_G = lib$(JSIG_G).so +LIBJSIG_DEBUGINFO = lib$(JSIG).debuginfo +LIBJSIG_G_DEBUGINFO = lib$(JSIG_G).debuginfo + JSIGSRCDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/vm -DEST_JSIG = $(JDK_LIBDIR)/$(LIBJSIG) +DEST_JSIG = $(JDK_LIBDIR)/$(LIBJSIG) +DEST_JSIG_DEBUGINFO = $(JDK_LIBDIR)/$(LIBJSIG_DEBUGINFO) LIBJSIG_MAPFILE = $(MAKEFILES_DIR)/mapfile-vers-jsig @@ -50,9 +54,24 @@ $(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \ $(LFLAGS_JSIG) -o $@ $< -ldl [ -f $(LIBJSIG_G) ] || { ln -s $@ $(LIBJSIG_G); } +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJSIG_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJSIG_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -x $@ + # implied else here is no stripping at all + endif + endif + [ -f $(LIBJSIG_G_DEBUGINFO) ] || { ln -s $(LIBJSIG_DEBUGINFO) $(LIBJSIG_G_DEBUGINFO); } +endif install_jsig: $(LIBJSIG) @echo "Copying $(LIBJSIG) to $(DEST_JSIG)" + $(QUIETLY) test -f $(LIBJSIG_DEBUGINFO) && \ + cp -f $(LIBJSIG_DEBUGINFO) $(DEST_JSIG_DEBUGINFO) $(QUIETLY) cp -f $(LIBJSIG) $(DEST_JSIG) && echo "Done" .PHONY: install_jsig
--- a/make/solaris/makefiles/mapfile-vers Wed Oct 26 12:43:05 2011 -0700 +++ b/make/solaris/makefiles/mapfile-vers Thu Oct 27 12:21:43 2011 -0700 @@ -3,7 +3,7 @@ # # -# Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 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 @@ -256,6 +256,9 @@ # This is for Forte Analyzer profiling support. AsyncGetCallTrace; + + # INSERT VTABLE SYMBOLS HERE + local: *; };
--- a/make/solaris/makefiles/product.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/solaris/makefiles/product.make Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -68,7 +68,8 @@ REORDERFILE = $(GAMMADIR)/make/solaris/makefiles/reorder_$(TYPE)_$(BUILDARCH) endif -# Don't strip in VM build; JDK build will strip libraries later +# If we can create .debuginfo files, then the VM is stripped in vm.make +# and this macro is not used. # LINK_LIB.CC/POST_HOOK += $(STRIP_LIB.CC/POST_HOOK) G_SUFFIX =
--- a/make/solaris/makefiles/sa.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/solaris/makefiles/sa.make Thu Oct 27 12:21:43 2011 -0700 @@ -39,13 +39,7 @@ # TODO: if it's a modules image, check if SA module is installed. MODULELIB_PATH= $(BOOT_JAVA_HOME)/lib/modules -# gnumake 3.78.1 does not accept the *s that -# are in AGENT_FILES1 and AGENT_FILES2, so use the shell to expand them -AGENT_FILES1 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES1)) -AGENT_FILES2 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES2)) - -AGENT_FILES1_LIST := $(GENERATED)/agent1.classes.list -AGENT_FILES2_LIST := $(GENERATED)/agent2.classes.list +AGENT_FILES_LIST := $(GENERATED)/agent.classes.list SA_CLASSDIR = $(GENERATED)/saclasses @@ -59,7 +53,7 @@ $(MAKE) -f sa.make $(GENERATED)/sa-jdi.jar; \ fi -$(GENERATED)/sa-jdi.jar: $(AGENT_FILES1) $(AGENT_FILES2) +$(GENERATED)/sa-jdi.jar: $(AGENT_FILES) $(QUIETLY) echo "Making $@"; $(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \ echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \ @@ -73,7 +67,6 @@ $(QUIETLY) if [ ! -d $(SA_CLASSDIR) ] ; then \ mkdir -p $(SA_CLASSDIR); \ fi - # Note: When indented, make tries to execute the '$(shell' comment. # In some environments, cmd processors have limited line length. # To prevent the javac invocation in the next block from using @@ -84,13 +77,12 @@ # the initialization of the lists is also done in the same phase # using '$(shell rm ...' instead of using the more traditional # 'rm ...' rule. - $(shell rm -rf $(AGENT_FILES1_LIST) $(AGENT_FILES2_LIST)) - $(foreach file,$(AGENT_FILES1),$(shell echo $(file) >> $(AGENT_FILES1_LIST))) - $(foreach file,$(AGENT_FILES2),$(shell echo $(file) >> $(AGENT_FILES2_LIST))) - - $(QUIETLY) $(COMPILE.JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES1_LIST) - $(QUIETLY) $(COMPILE.JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES2_LIST) - + $(shell rm -rf $(AGENT_FILES_LIST)) +# gnumake 3.78.1 does not accept the *'s that +# are in AGENT_FILES, so use the shell to expand them. +# Be extra carefull to not produce too long command lines in the shell! + $(foreach file,$(AGENT_FILES),$(shell ls -1 $(file) >> $(AGENT_FILES_LIST))) + $(QUIETLY) $(COMPILE.JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) @$(AGENT_FILES_LIST) $(QUIETLY) $(COMPILE.RMIC) -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer $(QUIETLY) echo "$(SA_BUILD_VERSION_PROP)" > $(SA_PROPERTIES) $(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql/sa.js @@ -106,4 +98,4 @@ clean: rm -rf $(SA_CLASSDIR) rm -rf $(GENERATED)/sa-jdi.jar - rm -rf $(AGENT_FILES1_LIST) $(AGENT_FILES2_LIST) + rm -rf $(AGENT_FILES_LIST)
--- a/make/solaris/makefiles/saproc.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/solaris/makefiles/saproc.make Thu Oct 27 12:21:43 2011 -0700 @@ -32,6 +32,9 @@ SAPROC_G = $(SAPROC)$(G_SUFFIX) LIBSAPROC_G = lib$(SAPROC_G).so +LIBSAPROC_DEBUGINFO = lib$(SAPROC).debuginfo +LIBSAPROC_G_DEBUGINFO = lib$(SAPROC_G).debuginfo + AGENT_DIR = $(GAMMADIR)/agent SASRCDIR = $(AGENT_DIR)/src/os/$(Platform_os_family)/proc @@ -40,7 +43,8 @@ SAMAPFILE = $(SASRCDIR)/mapfile -DEST_SAPROC = $(JDK_LIBDIR)/$(LIBSAPROC) +DEST_SAPROC = $(JDK_LIBDIR)/$(LIBSAPROC) +DEST_SAPROC_DEBUGINFO = $(JDK_LIBDIR)/$(LIBSAPROC_DEBUGINFO) # if $(AGENT_DIR) does not exist, we don't build SA @@ -101,10 +105,25 @@ -o $@ \ -ldl -ldemangle -lthread -lc [ -f $(LIBSAPROC_G) ] || { ln -s $@ $(LIBSAPROC_G); } +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBSAPROC_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBSAPROC_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -x $@ + # implied else here is no stripping at all + endif + endif + [ -f $(LIBSAPROC_G_DEBUGINFO) ] || { ln -s $(LIBSAPROC_DEBUGINFO) $(LIBSAPROC_G_DEBUGINFO); } +endif install_saproc: $(BULDLIBSAPROC) $(QUIETLY) if [ -f $(LIBSAPROC) ] ; then \ echo "Copying $(LIBSAPROC) to $(DEST_SAPROC)"; \ + test -f $(LIBSAPROC_DEBUGINFO) && \ + cp -f $(LIBSAPROC_DEBUGINFO) $(DEST_SAPROC_DEBUGINFO); \ cp -f $(LIBSAPROC) $(DEST_SAPROC) && echo "Done"; \ fi
--- a/make/solaris/makefiles/sparcWorks.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/solaris/makefiles/sparcWorks.make Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 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 @@ -481,9 +481,18 @@ endif # Flags for Debugging +# The -g0 setting allows the C++ frontend to inline, which is a big win. +# The -xs setting disables 'lazy debug info' which puts everything in +# the .so instead of requiring the '.o' files. +ifneq ($(OBJCOPY),) + OPT_CFLAGS += -g0 -xs +endif DEBUG_CFLAGS = -g FASTDEBUG_CFLAGS = -g0 -# The -g0 setting allows the C++ frontend to inline, which is a big win. +ifneq ($(OBJCOPY),) + DEBUG_CFLAGS += -xs + FASTDEBUG_CFLAGS += -xs +endif # Special global options for SS12 ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1) @@ -502,6 +511,9 @@ # data using a unique globalization prefix. Instead force the use of # a static globalization prefix based on the source filepath so the # objects from two identical compilations are the same. +# EXTRA_CFLAGS only covers vm_version.cpp for some reason +#EXTRA_CFLAGS += -Qoption ccfe -xglobalstatic +#OPT_CFLAGS += -Qoption ccfe -xglobalstatic #DEBUG_CFLAGS += -Qoption ccfe -xglobalstatic #FASTDEBUG_CFLAGS += -Qoption ccfe -xglobalstatic @@ -562,6 +574,8 @@ # since the hook must terminate itself as a valid command.) # Also, strip debug and line number information (worth about 1.7Mb). +# If we can create .debuginfo files, then the VM is stripped in vm.make +# and this macro is not used. STRIP_LIB.CC/POST_HOOK = $(STRIP) -x $@ || exit 1; # STRIP_LIB.CC/POST_HOOK is incorporated into LINK_LIB.CC/POST_HOOK # in certain configurations, such as product.make. Other configurations,
--- a/make/solaris/makefiles/vm.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/solaris/makefiles/vm.make Thu Oct 27 12:21:43 2011 -0700 @@ -55,10 +55,17 @@ Src_Dirs_I += $(GENERATED) INCLUDES += $(Src_Dirs_I:%=-I%) -ifeq (${VERSION}, debug) - SYMFLAG = -g +# SYMFLAG is used by {dtrace,jsig,saproc}.make. +ifneq ($(OBJCOPY),) + # always build with debug info when we can create .debuginfo files + # and disable 'lazy debug info' so the .so has everything. + SYMFLAG = -g -xs else - SYMFLAG = + ifeq (${VERSION}, debug) + SYMFLAG = -g + else + SYMFLAG = + endif endif # The following variables are defined in the generated flags.make file. @@ -140,6 +147,9 @@ LIBJVM = lib$(JVM).so LIBJVM_G = lib$(JVM)$(G_SUFFIX).so +LIBJVM_DEBUGINFO = lib$(JVM).debuginfo +LIBJVM_G_DEBUGINFO = lib$(JVM)$(G_SUFFIX).debuginfo + SPECIAL_PATHS:=adlc c1 dist gc_implementation opto shark libadt SOURCE_PATHS=\ @@ -212,14 +222,24 @@ vm_version.o: $(filter-out vm_version.o,$(JVM_OBJ_FILES)) -mapfile : $(MAPFILE) $(MAPFILE_DTRACE_OPT) +mapfile : $(MAPFILE) $(MAPFILE_DTRACE_OPT) vm.def rm -f $@ - cat $^ > $@ + cat $(MAPFILE) $(MAPFILE_DTRACE_OPT) \ + | $(NAWK) '{ \ + if ($$0 ~ "INSERT VTABLE SYMBOLS HERE") { \ + system ("cat vm.def"); \ + } else { \ + print $$0; \ + } \ + }' > $@ mapfile_reorder : mapfile $(MAPFILE_DTRACE_OPT) $(REORDERFILE) rm -f $@ cat $^ > $@ +vm.def: $(Obj_Files) + sh $(GAMMADIR)/make/solaris/makefiles/build_vm_def.sh *.o > $@ + ifeq ($(LINK_INTO),AOUT) LIBJVM.o = LIBJVM_MAPFILE = @@ -255,13 +275,30 @@ $(QUIETLY) rm -f $@.1 && ln -s $@ $@.1 $(QUIETLY) [ -f $(LIBJVM_G) ] || ln -s $@ $(LIBJVM_G) $(QUIETLY) [ -f $(LIBJVM_G).1 ] || ln -s $@.1 $(LIBJVM_G).1 +ifneq ($(OBJCOPY),) + $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJVM_DEBUGINFO) + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DEBUGINFO) $@ + ifeq ($(STRIP_POLICY),all_strip) + $(QUIETLY) $(STRIP) $@ + else + ifeq ($(STRIP_POLICY),min_strip) + $(QUIETLY) $(STRIP) -x $@ + # implied else here is no stripping at all + endif + endif + $(QUIETLY) [ -f $(LIBJVM_G_DEBUGINFO) ] || ln -s $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO) +endif endif # filter -sbfast -xsbfast -DEST_JVM = $(JDK_LIBDIR)/$(VM_SUBDIR)/$(LIBJVM) +DEST_SUBDIR = $(JDK_LIBDIR)/$(VM_SUBDIR) +DEST_JVM = $(DEST_SUBDIR)/$(LIBJVM) +DEST_JVM_DEBUGINFO = $(DEST_SUBDIR)/$(LIBJVM_DEBUGINFO) install_jvm: $(LIBJVM) @echo "Copying $(LIBJVM) to $(DEST_JVM)" + $(QUIETLY) test -f $(LIBJVM_DEBUGINFO) && \ + cp -f $(LIBJVM_DEBUGINFO) $(DEST_JVM_DEBUGINFO) $(QUIETLY) cp -f $(LIBJVM) $(DEST_JVM) && echo "Done" #----------------------------------------------------------------------
--- a/make/templates/bsd-header Wed Oct 26 12:43:05 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -Copyright (c) %YEARS%, Oracle and/or its affiliates. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - - Neither the name of Oracle nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- a/make/windows/makefiles/defs.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/windows/makefiles/defs.make Thu Oct 27 12:21:43 2011 -0700 @@ -109,6 +109,9 @@ JDK_INCLUDE_SUBDIR=win32 +# Library suffix +LIBRARY_SUFFIX=dll + # HOTSPOT_RELEASE_VERSION and HOTSPOT_BUILD_VERSION are defined # and added to MAKE_ARGS list in $(GAMMADIR)/make/defs.make. @@ -175,24 +178,24 @@ EXPORT_KERNEL_DIR = $(EXPORT_JRE_BIN_DIR)/kernel EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt -EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.dll +EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.$(LIBRARY_SUFFIX) EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.pdb EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.map EXPORT_LIST += $(EXPORT_LIB_DIR)/jvm.lib ifeq ($(ARCH_DATA_MODEL), 32) EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt - EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.dll + EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.$(LIBRARY_SUFFIX) EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.pdb EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.map # kernel vm EXPORT_LIST += $(EXPORT_KERNEL_DIR)/Xusage.txt - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.dll + EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.$(LIBRARY_SUFFIX) EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.pdb EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.map endif ifeq ($(BUILD_WIN_SA), 1) - EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.dll + EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.$(LIBRARY_SUFFIX) EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.pdb EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.map EXPORT_LIST += $(EXPORT_LIB_DIR)/sa-jdi.jar
--- a/make/windows/makefiles/sa.make Wed Oct 26 12:43:05 2011 -0700 +++ b/make/windows/makefiles/sa.make Thu Oct 27 12:21:43 2011 -0700 @@ -52,12 +52,11 @@ # Remove the space between $(SA_BUILD_VERSION_PROP) and > below as it adds a white space # at the end of SA version string and causes a version mismatch with the target VM version. -$(GENERATED)\sa-jdi.jar: $(AGENT_FILES1:/=\) $(AGENT_FILES2:/=\) +$(GENERATED)\sa-jdi.jar: $(AGENT_FILES:/=\) @if not exist $(SA_CLASSDIR) mkdir $(SA_CLASSDIR) @echo ...Building sa-jdi.jar @echo ...$(COMPILE_JAVAC) -classpath $(SA_CLASSPATH) -d $(SA_CLASSDIR) .... - @$(COMPILE_JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES1:/=\) - @$(COMPILE_JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES2:/=\) + @$(COMPILE_JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES:/=\) $(COMPILE_RMIC) -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer $(QUIETLY) echo $(SA_BUILD_VERSION_PROP)> $(SA_PROPERTIES) $(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql/sa.js
--- a/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -328,7 +328,8 @@ bool use_length = x->length() != NULL; bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT; bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL || - !get_jobject_constant(x->value())->is_null_object()); + !get_jobject_constant(x->value())->is_null_object() || + x->should_profile()); LIRItem array(x->array(), this); LIRItem index(x->index(), this); @@ -382,7 +383,7 @@ LIR_Opr tmp3 = FrameMap::G5_opr; CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info); - __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info); + __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info, x->profiled_method(), x->profiled_bci()); } if (obj_store) {
--- a/src/cpu/sparc/vm/copy_sparc.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/sparc/vm/copy_sparc.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -82,13 +82,35 @@ } static void pd_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) { - // FIXME - (void)memmove(to, from, count << LogBytesPerShort); + if (from > to) { + while (count-- > 0) { + // Copy forwards + *to++ = *from++; + } + } else { + from += count - 1; + to += count - 1; + while (count-- > 0) { + // Copy backwards + *to-- = *from--; + } + } } static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) { - // FIXME - (void)memmove(to, from, count << LogBytesPerInt); + if (from > to) { + while (count-- > 0) { + // Copy forwards + *to++ = *from++; + } + } else { + from += count - 1; + to += count - 1; + while (count-- > 0) { + // Copy backwards + *to-- = *from--; + } + } } static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
--- a/src/cpu/sparc/vm/sparc.ad Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/sparc/vm/sparc.ad Thu Oct 27 12:21:43 2011 -0700 @@ -10476,7 +10476,7 @@ ins_pipe(ialu_reg); %} -instruct countTrailingZerosL(iRegI dst, iRegL src, flagsReg cr) %{ +instruct countTrailingZerosL(iRegIsafe dst, iRegL src, flagsReg cr) %{ predicate(UsePopCountInstruction); // See Matcher::match_rule_supported match(Set dst (CountTrailingZerosL src)); effect(TEMP dst, KILL cr);
--- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -2359,10 +2359,10 @@ for (int off = 0; off < 64; off += 16) { if (use_prefetch && (off & 31) == 0) { if (ArraycopySrcPrefetchDistance > 0) { - __ prefetch(from, ArraycopySrcPrefetchDistance, Assembler::severalReads); + __ prefetch(from, ArraycopySrcPrefetchDistance+off, Assembler::severalReads); } if (ArraycopyDstPrefetchDistance > 0) { - __ prefetch(to, ArraycopyDstPrefetchDistance, Assembler::severalWritesAndPossiblyReads); + __ prefetch(to, ArraycopyDstPrefetchDistance+off, Assembler::severalWritesAndPossiblyReads); } } __ ldx(from, off+0, O4);
--- a/src/cpu/x86/vm/bytes_x86.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/x86/vm/bytes_x86.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -81,6 +81,9 @@ #ifdef TARGET_OS_ARCH_windows_x86 # include "bytes_windows_x86.inline.hpp" #endif +#ifdef TARGET_OS_ARCH_bsd_x86 +# include "bytes_bsd_x86.inline.hpp" +#endif #endif // CPU_X86_VM_BYTES_X86_HPP
--- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -427,8 +427,8 @@ // Fetch the exception from TLS and clear out exception related thread state __ get_thread(rsi); __ movptr(rax, Address(rsi, JavaThread::exception_oop_offset())); - __ movptr(Address(rsi, JavaThread::exception_oop_offset()), (int32_t)NULL_WORD); - __ movptr(Address(rsi, JavaThread::exception_pc_offset()), (int32_t)NULL_WORD); + __ movptr(Address(rsi, JavaThread::exception_oop_offset()), (intptr_t)NULL_WORD); + __ movptr(Address(rsi, JavaThread::exception_pc_offset()), (intptr_t)NULL_WORD); __ bind(_unwind_handler_entry); __ verify_not_null_oop(rax);
--- a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -267,7 +267,8 @@ bool use_length = x->length() != NULL; bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT; bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL || - !get_jobject_constant(x->value())->is_null_object()); + !get_jobject_constant(x->value())->is_null_object() || + x->should_profile()); LIRItem array(x->array(), this); LIRItem index(x->index(), this); @@ -321,7 +322,7 @@ LIR_Opr tmp3 = new_register(objectType); CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info); - __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info); + __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info, x->profiled_method(), x->profiled_bci()); } if (obj_store) {
--- a/src/cpu/x86/vm/copy_x86.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/x86/vm/copy_x86.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -37,6 +37,9 @@ #ifdef TARGET_OS_ARCH_windows_x86 # include "copy_windows_x86.inline.hpp" #endif +#ifdef TARGET_OS_ARCH_bsd_x86 +# include "copy_bsd_x86.inline.hpp" +#endif static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) {
--- a/src/cpu/x86/vm/frame_x86.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/x86/vm/frame_x86.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -232,11 +232,13 @@ void frame::patch_pc(Thread* thread, address pc) { + address* pc_addr = &(((address*) sp())[-1]); if (TracePcPatching) { - tty->print_cr("patch_pc at address" INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "] ", - &((address *)sp())[-1], ((address *)sp())[-1], pc); + tty->print_cr("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "] ", + pc_addr, *pc_addr, pc); } - ((address *)sp())[-1] = pc; + assert(_pc == *pc_addr, err_msg("must be: " INTPTR_FORMAT " == " INTPTR_FORMAT, _pc, *pc_addr)); + *pc_addr = pc; _cb = CodeCache::find_blob(pc); address original_pc = nmethod::get_deopt_original_pc(this); if (original_pc != NULL) { @@ -671,4 +673,3 @@ // used to reset the saved FP return fp(); } -
--- a/src/cpu/x86/vm/globals_x86.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/x86/vm/globals_x86.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -70,7 +70,11 @@ define_pd_global(bool, RewriteBytecodes, true); define_pd_global(bool, RewriteFrequentPairs, true); +#ifdef _ALLBSD_SOURCE +define_pd_global(bool, UseMembar, true); +#else define_pd_global(bool, UseMembar, false); +#endif // GC Ergo Flags define_pd_global(intx, CMSYoungGenPerWorker, 64*M); // default max size of CMS young gen, per GC worker thread
--- a/src/cpu/x86/vm/interp_masm_x86_32.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -45,6 +45,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // Implementation of InterpreterMacroAssembler @@ -1158,7 +1161,7 @@ int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row)); set_mdp_data_at(mdp, recvr_offset, receiver); int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); - movptr(reg2, (int32_t)DataLayout::counter_increment); + movptr(reg2, (intptr_t)DataLayout::counter_increment); set_mdp_data_at(mdp, count_offset, reg2); if (start_row > 0) { jmp(done); @@ -1301,7 +1304,7 @@ test_method_data_pointer(mdp, profile_continue); // Build the base (index * per_case_size_in_bytes()) + case_array_offset_in_bytes() - movptr(reg2, (int32_t)in_bytes(MultiBranchData::per_case_size())); + movptr(reg2, (intptr_t)in_bytes(MultiBranchData::per_case_size())); // index is positive and so should have correct value if this code were // used on 64bits imulptr(index, reg2);
--- a/src/cpu/x86/vm/interp_masm_x86_64.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -45,6 +45,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // Implementation of InterpreterMacroAssembler
--- a/src/cpu/x86/vm/jni_x86.h Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/x86/vm/jni_x86.h Thu Oct 27 12:21:43 2011 -0700 @@ -26,7 +26,7 @@ #ifndef _JAVASOFT_JNI_MD_H_ #define _JAVASOFT_JNI_MD_H_ -#if defined(SOLARIS) || defined(LINUX) +#if defined(SOLARIS) || defined(LINUX) || defined(_ALLBSD_SOURCE) #if defined(__GNUC__) && (__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2) #define JNIEXPORT __attribute__((visibility("default"))) @@ -38,10 +38,14 @@ #define JNICALL typedef int jint; - -#ifdef _LP64 +#if defined(_LP64) && !defined(__APPLE__) typedef long jlong; #else + /* + * On _LP64 __APPLE__ "long" and "long long" are both 64 bits, + * but we use the "long long" typedef to avoid complaints from + * the __APPLE__ compiler about fprintf formats. + */ typedef long long jlong; #endif
--- a/src/cpu/x86/vm/methodHandles_x86.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -410,8 +410,8 @@ void MethodHandles::RicochetFrame::verify() const { verify_offsets(); - assert(magic_number_1() == MAGIC_NUMBER_1, ""); - assert(magic_number_2() == MAGIC_NUMBER_2, ""); + assert(magic_number_1() == MAGIC_NUMBER_1, err_msg(PTR_FORMAT " == " PTR_FORMAT, magic_number_1(), MAGIC_NUMBER_1)); + assert(magic_number_2() == MAGIC_NUMBER_2, err_msg(PTR_FORMAT " == " PTR_FORMAT, magic_number_2(), MAGIC_NUMBER_2)); if (!Universe::heap()->is_gc_active()) { if (saved_args_layout() != NULL) { assert(saved_args_layout()->is_method(), "must be valid oop");
--- a/src/cpu/x86/vm/methodHandles_x86.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/x86/vm/methodHandles_x86.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -132,7 +132,10 @@ intptr_t* sender_link() const { return _sender_link; } address sender_pc() const { return _sender_pc; } - intptr_t* extended_sender_sp() const { return saved_args_base(); } + intptr_t* extended_sender_sp() const { + // The extended sender SP is above the current RicochetFrame. + return (intptr_t*) (((address) this) + sizeof(RicochetFrame)); + } intptr_t return_value_slot_number() const { return adapter_conversion_vminfo(conversion());
--- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -47,6 +47,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifdef COMPILER2 #include "opto/runtime.hpp" #endif
--- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -47,6 +47,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifdef COMPILER2 #include "opto/runtime.hpp" #endif
--- a/src/cpu/x86/vm/stubRoutines_x86_32.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/x86/vm/stubRoutines_x86_32.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // Implementation of the platform-specific part of StubRoutines - for // a description of how to extend it, see the stubRoutines.hpp file.
--- a/src/cpu/x86/vm/stubRoutines_x86_64.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/x86/vm/stubRoutines_x86_64.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // Implementation of the platform-specific part of StubRoutines - for // a description of how to extend it, see the stubRoutines.hpp file.
--- a/src/cpu/x86/vm/vm_version_x86.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/x86/vm/vm_version_x86.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -37,6 +37,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif int VM_Version::_cpu;
--- a/src/cpu/zero/vm/bytes_zero.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/zero/vm/bytes_zero.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -168,6 +168,9 @@ #ifdef TARGET_OS_ARCH_linux_zero # include "bytes_linux_zero.inline.hpp" #endif +#ifdef TARGET_OS_ARCH_bsd_zero +# include "bytes_bsd_zero.inline.hpp" +#endif #endif // VM_LITTLE_ENDIAN
--- a/src/cpu/zero/vm/globals_zero.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/zero/vm/globals_zero.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -52,7 +52,11 @@ define_pd_global(bool, RewriteBytecodes, true); define_pd_global(bool, RewriteFrequentPairs, true); +#ifdef _ALLBSD_SOURCE +define_pd_global(bool, UseMembar, true); +#else define_pd_global(bool, UseMembar, false); +#endif // GC Ergo Flags define_pd_global(intx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread
--- a/src/cpu/zero/vm/interp_masm_zero.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/zero/vm/interp_masm_zero.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -40,5 +40,8 @@ #ifdef TARGET_OS_FAMILY_linux # include "thread_linux.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // This file is intentionally empty
--- a/src/cpu/zero/vm/stubGenerator_zero.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/zero/vm/stubGenerator_zero.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -43,6 +43,9 @@ #ifdef TARGET_OS_FAMILY_linux # include "thread_linux.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifdef COMPILER2 #include "opto/runtime.hpp" #endif
--- a/src/cpu/zero/vm/stubRoutines_zero.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/zero/vm/stubRoutines_zero.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -30,3 +30,6 @@ #ifdef TARGET_OS_FAMILY_linux # include "thread_linux.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif
--- a/src/cpu/zero/vm/vm_version_zero.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/cpu/zero/vm/vm_version_zero.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -32,5 +32,8 @@ #ifdef TARGET_OS_FAMILY_linux # include "os_linux.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif // This file is intentionally empty
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/dtrace/generateJvmOffsets.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2003, 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. + * + */ + +/* + * This is to provide sanity check in jhelper.d which compares SCCS + * versions of generateJvmOffsets.cpp used to create and extract + * contents of __JvmOffsets[] table. + * The __JvmOffsets[] table is located in generated JvmOffsets.cpp. + * + * GENOFFS_SCCS_VER 34 + */ + +#include "generateJvmOffsets.h" + +/* A workaround for private and protected fields */ +#define private public +#define protected public + +// not on macosx #include <proc_service.h> +#include "code/codeBlob.hpp" +#include "code/nmethod.hpp" +#include "code/pcDesc.hpp" +#include "gc_interface/collectedHeap.hpp" +#include "memory/heap.hpp" +#include "memory/memRegion.hpp" +#include "memory/universe.hpp" +#include "oops/constMethodOop.hpp" +#include "oops/klass.hpp" +#include "oops/methodOop.hpp" +#include "oops/oop.hpp" +#include "oops/symbol.hpp" +#include "runtime/virtualspace.hpp" +#include "runtime/vmStructs.hpp" +#include "utilities/accessFlags.hpp" +#include "utilities/globalDefinitions.hpp" + +// These are defined somewhere for Solaris +#define PR_MODEL_ILP32 1 +#define PR_MODEL_LP64 2 + +#ifdef COMPILER1 +#if defined(DEBUG) || defined(FASTDEBUG) + +/* + * To avoid the most part of potential link errors + * we link this program with -z nodefs . + * + * But for 'debug1' and 'fastdebug1' we still have to provide + * a particular workaround for the following symbols bellow. + * It will be good to find out a generic way in the future. + */ + +#pragma weak tty +#pragma weak CMSExpAvgFactor + +#if defined(i386) || defined(__i386) || defined(__amd64) +#pragma weak noreg +#endif /* i386 */ + +LIR_Opr LIR_OprFact::illegalOpr = (LIR_Opr) 0; + +address StubRoutines::_call_stub_return_address = NULL; + +StubQueue* AbstractInterpreter::_code = NULL; + +#endif /* defined(DEBUG) || defined(FASTDEBUG) */ +#endif /* COMPILER1 */ + +#define GEN_OFFS(Type,Name) \ + switch(gen_variant) { \ + case GEN_OFFSET: \ + printf("#define OFFSET_%-33s %ld\n", \ + #Type #Name, offset_of(Type, Name)); \ + break; \ + case GEN_INDEX: \ + printf("#define IDX_OFFSET_%-33s %d\n", \ + #Type #Name, index++); \ + break; \ + case GEN_TABLE: \ + printf("\tOFFSET_%s,\n", #Type #Name); \ + break; \ + } + +#define GEN_SIZE(Type) \ + switch(gen_variant) { \ + case GEN_OFFSET: \ + printf("#define SIZE_%-35s %ld\n", \ + #Type, sizeof(Type)); \ + break; \ + case GEN_INDEX: \ + printf("#define IDX_SIZE_%-35s %d\n", \ + #Type, index++); \ + break; \ + case GEN_TABLE: \ + printf("\tSIZE_%s,\n", #Type); \ + break; \ + } + +#define GEN_VALUE(String,Value) \ + switch(gen_variant) { \ + case GEN_OFFSET: \ + printf("#define %-40s %d\n", #String, Value); \ + break; \ + case GEN_INDEX: \ + printf("#define IDX_%-40s %d\n", #String, index++); \ + break; \ + case GEN_TABLE: \ + printf("\t" #String ",\n"); \ + break; \ + } + +void gen_prologue(GEN_variant gen_variant) { + const char *suffix; + + switch(gen_variant) { + case GEN_OFFSET: suffix = ".h"; break; + case GEN_INDEX: suffix = "Index.h"; break; + case GEN_TABLE: suffix = ".cpp"; break; + } + + printf("/*\n"); + printf(" * JvmOffsets%s !!!DO NOT EDIT!!! \n", suffix); + printf(" * The generateJvmOffsets program generates this file!\n"); + printf(" */\n\n"); + switch(gen_variant) { + + case GEN_OFFSET: + case GEN_INDEX: + break; + + case GEN_TABLE: + printf("#include \"JvmOffsets.h\"\n"); + printf("\n"); + printf("int __JvmOffsets[] = {\n"); + break; + } +} + +void gen_epilogue(GEN_variant gen_variant) { + if (gen_variant != GEN_TABLE) { + return; + } + printf("};\n\n"); + return; +} + +int generateJvmOffsets(GEN_variant gen_variant) { + int index = 0; /* It is used to generate JvmOffsetsIndex.h */ + int pointer_size = sizeof(void *); + int data_model = (pointer_size == 4) ? PR_MODEL_ILP32 : PR_MODEL_LP64; + + gen_prologue(gen_variant); + + GEN_VALUE(DATA_MODEL, data_model); + GEN_VALUE(POINTER_SIZE, pointer_size); +#if defined(TIERED) + GEN_VALUE(COMPILER, 3); +#elif COMPILER1 + GEN_VALUE(COMPILER, 1); +#elif COMPILER2 + GEN_VALUE(COMPILER, 2); +#else + GEN_VALUE(COMPILER, 0); +#endif // COMPILER1 && COMPILER2 + printf("\n"); + + GEN_OFFS(CollectedHeap, _reserved); + GEN_OFFS(MemRegion, _start); + GEN_OFFS(MemRegion, _word_size); + GEN_SIZE(HeapWord); + printf("\n"); + + GEN_OFFS(VMStructEntry, typeName); + GEN_OFFS(VMStructEntry, fieldName); + GEN_OFFS(VMStructEntry, address); + GEN_SIZE(VMStructEntry); + printf("\n"); + + GEN_VALUE(MAX_METHOD_CODE_SIZE, max_method_code_size); +#if defined(sparc) || defined(__sparc) + GEN_VALUE(OFFSET_interpreter_frame_method, 2 * pointer_size); /* L2 in saved window */ + GEN_VALUE(OFFSET_interpreter_frame_sender_sp, 13 * pointer_size); /* I5 in saved window */ + // Fake value for consistency. It is not going to be used. + GEN_VALUE(OFFSET_interpreter_frame_bcx_offset, 0xFFFF); +#elif defined(i386) || defined(__i386) || defined(__amd64) + GEN_VALUE(OFFSET_interpreter_frame_sender_sp, -1 * pointer_size); + GEN_VALUE(OFFSET_interpreter_frame_method, -3 * pointer_size); + GEN_VALUE(OFFSET_interpreter_frame_bcx_offset, -7 * pointer_size); +#endif + + GEN_OFFS(Klass, _name); + GEN_OFFS(constantPoolOopDesc, _pool_holder); + printf("\n"); + + GEN_VALUE(OFFSET_HeapBlockHeader_used, (int) offset_of(HeapBlock::Header, _used)); + GEN_OFFS(oopDesc, _metadata); + printf("\n"); + + GEN_VALUE(AccessFlags_NATIVE, JVM_ACC_NATIVE); + GEN_VALUE(constMethodOopDesc_has_linenumber_table, constMethodOopDesc::_has_linenumber_table); + GEN_OFFS(AccessFlags, _flags); + GEN_OFFS(Symbol, _length); + GEN_OFFS(Symbol, _body); + printf("\n"); + + GEN_OFFS(methodOopDesc, _constMethod); + GEN_OFFS(methodOopDesc, _constants); + GEN_OFFS(methodOopDesc, _access_flags); + printf("\n"); + + GEN_OFFS(constMethodOopDesc, _flags); + GEN_OFFS(constMethodOopDesc, _code_size); + GEN_OFFS(constMethodOopDesc, _name_index); + GEN_OFFS(constMethodOopDesc, _signature_index); + printf("\n"); + + GEN_OFFS(CodeHeap, _memory); + GEN_OFFS(CodeHeap, _segmap); + GEN_OFFS(CodeHeap, _log2_segment_size); + printf("\n"); + + GEN_OFFS(VirtualSpace, _low_boundary); + GEN_OFFS(VirtualSpace, _high_boundary); + GEN_OFFS(VirtualSpace, _low); + GEN_OFFS(VirtualSpace, _high); + printf("\n"); + + GEN_OFFS(CodeBlob, _name); + GEN_OFFS(CodeBlob, _header_size); + GEN_OFFS(CodeBlob, _content_offset); + GEN_OFFS(CodeBlob, _code_offset); + GEN_OFFS(CodeBlob, _data_offset); + GEN_OFFS(CodeBlob, _frame_size); + printf("\n"); + + GEN_OFFS(nmethod, _method); + GEN_OFFS(nmethod, _oops_offset); + GEN_OFFS(nmethod, _scopes_data_offset); + GEN_OFFS(nmethod, _scopes_pcs_offset); + GEN_OFFS(nmethod, _handler_table_offset); + GEN_OFFS(nmethod, _deoptimize_offset); + GEN_OFFS(nmethod, _orig_pc_offset); + + GEN_OFFS(PcDesc, _pc_offset); + GEN_OFFS(PcDesc, _scope_decode_offset); + + printf("\n"); + + GEN_OFFS(NarrowOopStruct, _base); + GEN_OFFS(NarrowOopStruct, _shift); + printf("\n"); + + GEN_VALUE(SIZE_HeapBlockHeader, (int) sizeof(HeapBlock::Header)); + GEN_SIZE(oopDesc); + GEN_SIZE(constantPoolOopDesc); + printf("\n"); + + GEN_SIZE(PcDesc); + GEN_SIZE(methodOopDesc); + GEN_SIZE(constMethodOopDesc); + GEN_SIZE(nmethod); + GEN_SIZE(CodeBlob); + GEN_SIZE(BufferBlob); + GEN_SIZE(SingletonBlob); + GEN_SIZE(RuntimeStub); + GEN_SIZE(SafepointBlob); + + gen_epilogue(gen_variant); + printf("\n"); + + fflush(stdout); + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/dtrace/generateJvmOffsets.h Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_SOLARIS_DTRACE_GENERATEJVMOFFSETS_H +#define OS_SOLARIS_DTRACE_GENERATEJVMOFFSETS_H + +#include <stdio.h> +#include <strings.h> + +typedef enum GEN_variant { + GEN_OFFSET = 0, + GEN_INDEX = 1, + GEN_TABLE = 2 +} GEN_variant; + +extern "C" { + int generateJvmOffsets(GEN_variant gen_var); + void gen_prologue(GEN_variant gen_var); + void gen_epilogue(GEN_variant gen_var); +} + +#endif // OS_SOLARIS_DTRACE_GENERATEJVMOFFSETS_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/dtrace/generateJvmOffsetsMain.c Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "generateJvmOffsets.h" + +const char *HELP = + "HELP: generateJvmOffsets {-header | -index | -table} \n"; + +int main(int argc, const char *argv[]) { + GEN_variant gen_var; + + if (argc != 2) { + printf("%s", HELP); + return 1; + } + + if (0 == strcmp(argv[1], "-header")) { + gen_var = GEN_OFFSET; + } + else if (0 == strcmp(argv[1], "-index")) { + gen_var = GEN_INDEX; + } + else if (0 == strcmp(argv[1], "-table")) { + gen_var = GEN_TABLE; + } + else { + printf("%s", HELP); + return 1; + } + return generateJvmOffsets(gen_var); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/dtrace/hotspot.d Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +provider hotspot { + probe class__loaded(char*, uintptr_t, void*, uintptr_t); + probe class__unloaded(char*, uintptr_t, void*, uintptr_t); + probe class__initialization__required(char*, uintptr_t, void*, intptr_t); + probe class__initialization__recursive(char*, uintptr_t, void*, intptr_t,int); + probe class__initialization__concurrent(char*, uintptr_t, void*, intptr_t,int); + probe class__initialization__erroneous(char*, uintptr_t, void*, intptr_t, int); + probe class__initialization__super__failed(char*, uintptr_t, void*, intptr_t,int); + probe class__initialization__clinit(char*, uintptr_t, void*, intptr_t,int); + probe class__initialization__error(char*, uintptr_t, void*, intptr_t,int); + probe class__initialization__end(char*, uintptr_t, void*, intptr_t,int); + probe vm__init__begin(); + probe vm__init__end(); + probe vm__shutdown(); + probe vmops__request(char*, uintptr_t, int); + probe vmops__begin(char*, uintptr_t, int); + probe vmops__end(char*, uintptr_t, int); + probe gc__begin(uintptr_t); + probe gc__end(); + probe mem__pool__gc__begin( + char*, uintptr_t, char*, uintptr_t, + uintptr_t, uintptr_t, uintptr_t, uintptr_t); + probe mem__pool__gc__end( + char*, uintptr_t, char*, uintptr_t, + uintptr_t, uintptr_t, uintptr_t, uintptr_t); + probe thread__probe__start(char*, uintptr_t, uintptr_t, uintptr_t, uintptr_t); + probe thread__probe__stop(char*, uintptr_t, uintptr_t, uintptr_t, uintptr_t); + probe thread__sleep__begin(long long); + probe thread__sleep__end(int); + probe thread__yield(); + probe thread__park__begin(uintptr_t, int, long long); + probe thread__park__end(uintptr_t); + probe thread__unpark(uintptr_t); + probe method__compile__begin( + const char*, uintptr_t, const char*, uintptr_t, const char*, uintptr_t, const char*, uintptr_t); + probe method__compile__end( + char*, uintptr_t, char*, uintptr_t, char*, uintptr_t, + char*, uintptr_t, uintptr_t); + probe compiled__method__load( + char*, uintptr_t, char*, uintptr_t, char*, uintptr_t, void*, uintptr_t); + probe compiled__method__unload( + char*, uintptr_t, char*, uintptr_t, char*, uintptr_t); + probe monitor__contended__enter(uintptr_t, uintptr_t, char*, uintptr_t); + probe monitor__contended__entered(uintptr_t, uintptr_t, char*, uintptr_t); + probe monitor__contended__exit(uintptr_t, uintptr_t, char*, uintptr_t); + probe monitor__wait(uintptr_t, uintptr_t, char*, uintptr_t, uintptr_t); + probe monitor__probe__waited(uintptr_t, uintptr_t, char*, uintptr_t); + probe monitor__notify(uintptr_t, uintptr_t, char*, uintptr_t); + probe monitor__notifyAll(uintptr_t, uintptr_t, char*, uintptr_t); + + probe object__alloc(int, char*, uintptr_t, uintptr_t); + probe method__entry( + int, char*, int, char*, int, char*, int); + probe method__return( + int, char*, int, char*, int, char*, int); +}; + +#pragma D attributes Evolving/Evolving/Common provider hotspot provider +#pragma D attributes Private/Private/Unknown provider hotspot module +#pragma D attributes Private/Private/Unknown provider hotspot function +#pragma D attributes Evolving/Evolving/Common provider hotspot name +#pragma D attributes Evolving/Evolving/Common provider hotspot args
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/dtrace/hotspot_jni.d Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,506 @@ +/* + * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +provider hotspot_jni { + probe AllocObject__entry(void*, void*); + probe AllocObject__return(void*); + probe AttachCurrentThreadAsDaemon__entry(void*, void**, void*); + probe AttachCurrentThreadAsDaemon__return(uint32_t); + probe AttachCurrentThread__entry(void*, void**, void*); + probe AttachCurrentThread__return(uint32_t); + probe CallBooleanMethodA__entry(void*, void*, uintptr_t); + probe CallBooleanMethodA__return(uintptr_t); + probe CallBooleanMethod__entry(void*, void*, uintptr_t); + probe CallBooleanMethod__return(uintptr_t); + probe CallBooleanMethodV__entry(void*, void*, uintptr_t); + probe CallBooleanMethodV__return(uintptr_t); + probe CallByteMethodA__entry(void*, void*, uintptr_t); + probe CallByteMethodA__return(char); + probe CallByteMethod__entry(void*, void*, uintptr_t); + probe CallByteMethod__return(char); + probe CallByteMethodV__entry(void*, void*, uintptr_t); + probe CallByteMethodV__return(char); + probe CallCharMethodA__entry(void*, void*, uintptr_t); + probe CallCharMethodA__return(uint16_t); + probe CallCharMethod__entry(void*, void*, uintptr_t); + probe CallCharMethod__return(uint16_t); + probe CallCharMethodV__entry(void*, void*, uintptr_t); + probe CallCharMethodV__return(uint16_t); + probe CallDoubleMethodA__entry(void*, void*, uintptr_t); + probe CallDoubleMethodA__return(); + probe CallDoubleMethod__entry(void*, void*, uintptr_t); + probe CallDoubleMethod__return(); + probe CallDoubleMethodV__entry(void*, void*, uintptr_t); + probe CallDoubleMethodV__return(); + probe CallFloatMethodA__entry(void*, void*, uintptr_t); + probe CallFloatMethodA__return(); + probe CallFloatMethod__entry(void*, void*, uintptr_t); + probe CallFloatMethod__return(); + probe CallFloatMethodV__entry(void*, void*, uintptr_t); + probe CallFloatMethodV__return(); + probe CallIntMethodA__entry(void*, void*, uintptr_t); + probe CallIntMethodA__return(uint32_t); + probe CallIntMethod__entry(void*, void*, uintptr_t); + probe CallIntMethod__return(uint32_t); + probe CallIntMethodV__entry(void*, void*, uintptr_t); + probe CallIntMethodV__return(uint32_t); + probe CallLongMethodA__entry(void*, void*, uintptr_t); + probe CallLongMethodA__return(uintptr_t); + probe CallLongMethod__entry(void*, void*, uintptr_t); + probe CallLongMethod__return(uintptr_t); + probe CallLongMethodV__entry(void*, void*, uintptr_t); + probe CallLongMethodV__return(uintptr_t); + probe CallNonvirtualBooleanMethodA__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualBooleanMethodA__return(uintptr_t); + probe CallNonvirtualBooleanMethod__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualBooleanMethod__return(uintptr_t); + probe CallNonvirtualBooleanMethodV__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualBooleanMethodV__return(uintptr_t); + probe CallNonvirtualByteMethodA__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualByteMethodA__return(char); + probe CallNonvirtualByteMethod__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualByteMethod__return(char); + probe CallNonvirtualByteMethodV__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualByteMethodV__return(char); + probe CallNonvirtualCharMethodA__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualCharMethodA__return(uint16_t); + probe CallNonvirtualCharMethod__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualCharMethod__return(uint16_t); + probe CallNonvirtualCharMethodV__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualCharMethodV__return(uint16_t); + probe CallNonvirtualDoubleMethodA__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualDoubleMethodA__return(); + probe CallNonvirtualDoubleMethod__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualDoubleMethod__return(); + probe CallNonvirtualDoubleMethodV__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualDoubleMethodV__return(); + probe CallNonvirtualFloatMethodA__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualFloatMethodA__return(); + probe CallNonvirtualFloatMethod__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualFloatMethod__return(); + probe CallNonvirtualFloatMethodV__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualFloatMethodV__return(); + probe CallNonvirtualIntMethodA__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualIntMethodA__return(uint32_t); + probe CallNonvirtualIntMethod__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualIntMethod__return(uint32_t); + probe CallNonvirtualIntMethodV__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualIntMethodV__return(uint32_t); + probe CallNonvirtualLongMethodA__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualLongMethodA__return(uintptr_t); + probe CallNonvirtualLongMethod__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualLongMethod__return(uintptr_t); + probe CallNonvirtualLongMethodV__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualLongMethodV__return(uintptr_t); + probe CallNonvirtualObjectMethodA__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualObjectMethodA__return(void*); + probe CallNonvirtualObjectMethod__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualObjectMethod__return(void*); + probe CallNonvirtualObjectMethodV__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualObjectMethodV__return(void*); + probe CallNonvirtualShortMethodA__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualShortMethodA__return(uint16_t); + probe CallNonvirtualShortMethod__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualShortMethod__return(uint16_t); + probe CallNonvirtualShortMethodV__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualShortMethodV__return(uint16_t); + probe CallNonvirtualVoidMethodA__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualVoidMethodA__return(); + probe CallNonvirtualVoidMethod__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualVoidMethod__return(); + probe CallNonvirtualVoidMethodV__entry(void*, void*, void*, uintptr_t); + probe CallNonvirtualVoidMethodV__return(); + probe CallObjectMethodA__entry(void*, void*, uintptr_t); + probe CallObjectMethodA__return(void*); + probe CallObjectMethod__entry(void*, void*, uintptr_t); + probe CallObjectMethod__return(void*); + probe CallObjectMethodV__entry(void*, void*, uintptr_t); + probe CallObjectMethodV__return(void*); + probe CallShortMethodA__entry(void*, void*, uintptr_t); + probe CallShortMethodA__return(uint16_t); + probe CallShortMethod__entry(void*, void*, uintptr_t); + probe CallShortMethod__return(uint16_t); + probe CallShortMethodV__entry(void*, void*, uintptr_t); + probe CallShortMethodV__return(uint16_t); + probe CallStaticBooleanMethodA__entry(void*, void*, uintptr_t); + probe CallStaticBooleanMethodA__return(uintptr_t); + probe CallStaticBooleanMethod__entry(void*, void*, uintptr_t); + probe CallStaticBooleanMethod__return(uintptr_t); + probe CallStaticBooleanMethodV__entry(void*, void*, uintptr_t); + probe CallStaticBooleanMethodV__return(uintptr_t); + probe CallStaticByteMethodA__entry(void*, void*, uintptr_t); + probe CallStaticByteMethodA__return(char); + probe CallStaticByteMethod__entry(void*, void*, uintptr_t); + probe CallStaticByteMethod__return(char); + probe CallStaticByteMethodV__entry(void*, void*, uintptr_t); + probe CallStaticByteMethodV__return(char); + probe CallStaticCharMethodA__entry(void*, void*, uintptr_t); + probe CallStaticCharMethodA__return(uint16_t); + probe CallStaticCharMethod__entry(void*, void*, uintptr_t); + probe CallStaticCharMethod__return(uint16_t); + probe CallStaticCharMethodV__entry(void*, void*, uintptr_t); + probe CallStaticCharMethodV__return(uint16_t); + probe CallStaticDoubleMethodA__entry(void*, void*, uintptr_t); + probe CallStaticDoubleMethodA__return(); + probe CallStaticDoubleMethod__entry(void*, void*, uintptr_t); + probe CallStaticDoubleMethod__return(); + probe CallStaticDoubleMethodV__entry(void*, void*, uintptr_t); + probe CallStaticDoubleMethodV__return(); + probe CallStaticFloatMethodA__entry(void*, void*, uintptr_t); + probe CallStaticFloatMethodA__return(); + probe CallStaticFloatMethod__entry(void*, void*, uintptr_t); + probe CallStaticFloatMethod__return(); + probe CallStaticFloatMethodV__entry(void*, void*, uintptr_t); + probe CallStaticFloatMethodV__return(); + probe CallStaticIntMethodA__entry(void*, void*, uintptr_t); + probe CallStaticIntMethodA__return(uint32_t); + probe CallStaticIntMethod__entry(void*, void*, uintptr_t); + probe CallStaticIntMethod__return(uint32_t); + probe CallStaticIntMethodV__entry(void*, void*, uintptr_t); + probe CallStaticIntMethodV__return(uint32_t); + probe CallStaticLongMethodA__entry(void*, void*, uintptr_t); + probe CallStaticLongMethodA__return(uintptr_t); + probe CallStaticLongMethod__entry(void*, void*, uintptr_t); + probe CallStaticLongMethod__return(uintptr_t); + probe CallStaticLongMethodV__entry(void*, void*, uintptr_t); + probe CallStaticLongMethodV__return(uintptr_t); + probe CallStaticObjectMethodA__entry(void*, void*, uintptr_t); + probe CallStaticObjectMethodA__return(void*); + probe CallStaticObjectMethod__entry(void*, void*, uintptr_t); + probe CallStaticObjectMethod__return(void*); + probe CallStaticObjectMethodV__entry(void*, void*, uintptr_t); + probe CallStaticObjectMethodV__return(void*); + probe CallStaticShortMethodA__entry(void*, void*, uintptr_t); + probe CallStaticShortMethodA__return(uint16_t); + probe CallStaticShortMethod__entry(void*, void*, uintptr_t); + probe CallStaticShortMethod__return(uint16_t); + probe CallStaticShortMethodV__entry(void*, void*, uintptr_t); + probe CallStaticShortMethodV__return(uint16_t); + probe CallStaticVoidMethodA__entry(void*, void*, uintptr_t); + probe CallStaticVoidMethodA__return(); + probe CallStaticVoidMethod__entry(void*, void*, uintptr_t); + probe CallStaticVoidMethod__return(); + probe CallStaticVoidMethodV__entry(void*, void*, uintptr_t); + probe CallStaticVoidMethodV__return(); + probe CallVoidMethodA__entry(void*, void*, uintptr_t); + probe CallVoidMethodA__return(); + probe CallVoidMethod__entry(void*, void*, uintptr_t); + probe CallVoidMethod__return(); + probe CallVoidMethodV__entry(void*, void*, uintptr_t); + probe CallVoidMethodV__return(); + probe CreateJavaVM__entry(void**, void**, void*); + probe CreateJavaVM__return(uint32_t); + probe DefineClass__entry(void*, const char*, void*, char*, uintptr_t); + probe DefineClass__return(void*); + probe DeleteGlobalRef__entry(void*, void*); + probe DeleteGlobalRef__return(); + probe DeleteLocalRef__entry(void*, void*); + probe DeleteLocalRef__return(); + probe DeleteWeakGlobalRef__entry(void*, void*); + probe DeleteWeakGlobalRef__return(); + probe DestroyJavaVM__entry(void*); + probe DestroyJavaVM__return(uint32_t); + probe DetachCurrentThread__entry(void*); + probe DetachCurrentThread__return(uint32_t); + probe EnsureLocalCapacity__entry(void*, uint32_t); + probe EnsureLocalCapacity__return(uint32_t); + probe ExceptionCheck__entry(void*); + probe ExceptionCheck__return(uintptr_t); + probe ExceptionClear__entry(void*); + probe ExceptionClear__return(); + probe ExceptionDescribe__entry(void*); + probe ExceptionDescribe__return(); + probe ExceptionOccurred__entry(void*); + probe ExceptionOccurred__return(void*); + probe FatalError__entry(void* env, const char*); + probe FindClass__entry(void*, const char*); + probe FindClass__return(void*); + probe FromReflectedField__entry(void*, void*); + probe FromReflectedField__return(uintptr_t); + probe FromReflectedMethod__entry(void*, void*); + probe FromReflectedMethod__return(uintptr_t); + probe GetArrayLength__entry(void*, void*); + probe GetArrayLength__return(uintptr_t); + probe GetBooleanArrayElements__entry(void*, void*, uintptr_t*); + probe GetBooleanArrayElements__return(uintptr_t*); + probe GetBooleanArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, uintptr_t*); + probe GetBooleanArrayRegion__return(); + probe GetBooleanField__entry(void*, void*, uintptr_t); + probe GetBooleanField__return(uintptr_t); + probe GetByteArrayElements__entry(void*, void*, uintptr_t*); + probe GetByteArrayElements__return(char*); + probe GetByteArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, char*); + probe GetByteArrayRegion__return(); + probe GetByteField__entry(void*, void*, uintptr_t); + probe GetByteField__return(char); + probe GetCharArrayElements__entry(void*, void*, uintptr_t*); + probe GetCharArrayElements__return(uint16_t*); + probe GetCharArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, uint16_t*); + probe GetCharArrayRegion__return(); + probe GetCharField__entry(void*, void*, uintptr_t); + probe GetCharField__return(uint16_t); + probe GetCreatedJavaVMs__entry(void**, uintptr_t, uintptr_t*); + probe GetCreatedJavaVMs__return(uintptr_t); + probe GetDefaultJavaVMInitArgs__entry(void*); + probe GetDefaultJavaVMInitArgs__return(uint32_t); + probe GetDirectBufferAddress__entry(void*, void*); + probe GetDirectBufferAddress__return(void*); + probe GetDirectBufferCapacity__entry(void*, void*); + probe GetDirectBufferCapacity__return(uintptr_t); + probe GetDoubleArrayElements__entry(void*, void*, uintptr_t*); + probe GetDoubleArrayElements__return(double*); + probe GetDoubleArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, double*); + probe GetDoubleArrayRegion__return(); + probe GetDoubleField__entry(void*, void*, uintptr_t); + probe GetDoubleField__return(); + probe GetEnv__entry(void*, void*, uint32_t); + probe GetEnv__return(uint32_t); + probe GetFieldID__entry(void*, void*, const char*, const char*); + probe GetFieldID__return(uintptr_t); + probe GetFloatArrayElements__entry(void*, void*, uintptr_t*); + probe GetFloatArrayElements__return(float*); + probe GetFloatArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, float*); + probe GetFloatArrayRegion__return(); + probe GetFloatField__entry(void*, void*, uintptr_t); + probe GetFloatField__return(); + probe GetIntArrayElements__entry(void*, void*, uintptr_t*); + probe GetIntArrayElements__return(uint32_t*); + probe GetIntArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, uint32_t*); + probe GetIntArrayRegion__return(); + probe GetIntField__entry(void*, void*, uintptr_t); + probe GetIntField__return(uint32_t); + probe GetJavaVM__entry(void*, void**); + probe GetJavaVM__return(uint32_t); + probe GetLongArrayElements__entry(void*, void*, uintptr_t*); + probe GetLongArrayElements__return(uintptr_t*); + probe GetLongArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, uintptr_t*); + probe GetLongArrayRegion__return(); + probe GetLongField__entry(void*, void*, uintptr_t); + probe GetLongField__return(uintptr_t); + probe GetMethodID__entry(void*, void*, const char*, const char*); + probe GetMethodID__return(uintptr_t); + probe GetObjectArrayElement__entry(void*, void*, uintptr_t); + probe GetObjectArrayElement__return(void*); + probe GetObjectClass__entry(void*, void*); + probe GetObjectClass__return(void*); + probe GetObjectField__entry(void*, void*, uintptr_t); + probe GetObjectField__return(void*); + probe GetObjectRefType__entry(void*, void*); + probe GetObjectRefType__return(void*); + probe GetPrimitiveArrayCritical__entry(void*, void*, uintptr_t*); + probe GetPrimitiveArrayCritical__return(void*); + probe GetShortArrayElements__entry(void*, void*, uintptr_t*); + probe GetShortArrayElements__return(uint16_t*); + probe GetShortArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, uint16_t*); + probe GetShortArrayRegion__return(); + probe GetShortField__entry(void*, void*, uintptr_t); + probe GetShortField__return(uint16_t); + probe GetStaticBooleanField__entry(void*, void*, uintptr_t); + probe GetStaticBooleanField__return(uintptr_t); + probe GetStaticByteField__entry(void*, void*, uintptr_t); + probe GetStaticByteField__return(char); + probe GetStaticCharField__entry(void*, void*, uintptr_t); + probe GetStaticCharField__return(uint16_t); + probe GetStaticDoubleField__entry(void*, void*, uintptr_t); + probe GetStaticDoubleField__return(); + probe GetStaticFieldID__entry(void*, void*, const char*, const char*); + probe GetStaticFieldID__return(uintptr_t); + probe GetStaticFloatField__entry(void*, void*, uintptr_t); + probe GetStaticFloatField__return(); + probe GetStaticIntField__entry(void*, void*, uintptr_t); + probe GetStaticIntField__return(uint32_t); + probe GetStaticLongField__entry(void*, void*, uintptr_t); + probe GetStaticLongField__return(uintptr_t); + probe GetStaticMethodID__entry(void*, void*, const char*, const char*); + probe GetStaticMethodID__return(uintptr_t); + probe GetStaticObjectField__entry(void*, void*, uintptr_t); + probe GetStaticObjectField__return(void*); + probe GetStaticShortField__entry(void*, void*, uintptr_t); + probe GetStaticShortField__return(uint16_t); + probe GetStringChars__entry(void*, void*, uintptr_t*); + probe GetStringChars__return(const uint16_t*); + probe GetStringCritical__entry(void*, void*, uintptr_t*); + probe GetStringCritical__return(const uint16_t*); + probe GetStringLength__entry(void*, void*); + probe GetStringLength__return(uintptr_t); + probe GetStringRegion__entry(void*, void*, uintptr_t, uintptr_t, uint16_t*); + probe GetStringRegion__return(); + probe GetStringUTFChars__entry(void*, void*, uintptr_t*); + probe GetStringUTFChars__return(const char*); + probe GetStringUTFLength__entry(void*, void*); + probe GetStringUTFLength__return(uintptr_t); + probe GetStringUTFRegion__entry(void*, void*, uintptr_t, uintptr_t, char*); + probe GetStringUTFRegion__return(); + probe GetSuperclass__entry(void*, void*); + probe GetSuperclass__return(void*); + probe GetVersion__entry(void*); + probe GetVersion__return(uint32_t); + probe IsAssignableFrom__entry(void*, void*, void*); + probe IsAssignableFrom__return(uintptr_t); + probe IsInstanceOf__entry(void*, void*, void*); + probe IsInstanceOf__return(uintptr_t); + probe IsSameObject__entry(void*, void*, void*); + probe IsSameObject__return(uintptr_t); + probe MonitorEnter__entry(void*, void*); + probe MonitorEnter__return(uint32_t); + probe MonitorExit__entry(void*, void*); + probe MonitorExit__return(uint32_t); + probe NewBooleanArray__entry(void*, uintptr_t); + probe NewBooleanArray__return(void*); + probe NewByteArray__entry(void*, uintptr_t); + probe NewByteArray__return(void*); + probe NewCharArray__entry(void*, uintptr_t); + probe NewCharArray__return(void*); + probe NewDirectByteBuffer__entry(void*, void*, uintptr_t); + probe NewDirectByteBuffer__return(void*); + probe NewDoubleArray__entry(void*, uintptr_t); + probe NewDoubleArray__return(void*); + probe NewFloatArray__entry(void*, uintptr_t); + probe NewFloatArray__return(void*); + probe NewGlobalRef__entry(void*, void*); + probe NewGlobalRef__return(void*); + probe NewIntArray__entry(void*, uintptr_t); + probe NewIntArray__return(void*); + probe NewLocalRef__entry(void*, void*); + probe NewLocalRef__return(void*); + probe NewLongArray__entry(void*, uintptr_t); + probe NewLongArray__return(void*); + probe NewObjectA__entry(void*, void*, uintptr_t); + probe NewObjectA__return(void*); + probe NewObjectArray__entry(void*, uintptr_t, void*, void*); + probe NewObjectArray__return(void*); + probe NewObject__entry(void*, void*, uintptr_t); + probe NewObject__return(void*); + probe NewObjectV__entry(void*, void*, uintptr_t); + probe NewObjectV__return(void*); + probe NewShortArray__entry(void*, uintptr_t); + probe NewShortArray__return(void*); + probe NewString__entry(void*, const uint16_t*, uintptr_t); + probe NewString__return(void*); + probe NewStringUTF__entry(void*, const char*); + probe NewStringUTF__return(void*); + probe NewWeakGlobalRef__entry(void*, void*); + probe NewWeakGlobalRef__return(void*); + probe PopLocalFrame__entry(void*, void*); + probe PopLocalFrame__return(void*); + probe PushLocalFrame__entry(void*, uint32_t); + probe PushLocalFrame__return(uint32_t); + probe RegisterNatives__entry(void*, void*, const void*, uint32_t); + probe RegisterNatives__return(uint32_t); + probe ReleaseBooleanArrayElements__entry(void*, void*, uintptr_t*, uint32_t); + probe ReleaseBooleanArrayElements__return(); + probe ReleaseByteArrayElements__entry(void*, void*, char*, uint32_t); + probe ReleaseByteArrayElements__return(); + probe ReleaseCharArrayElements__entry(void*, void*, uint16_t*, uint32_t); + probe ReleaseCharArrayElements__return(); + probe ReleaseDoubleArrayElements__entry(void*, void*, double*, uint32_t); + probe ReleaseDoubleArrayElements__return(); + probe ReleaseFloatArrayElements__entry(void*, void*, float*, uint32_t); + probe ReleaseFloatArrayElements__return(); + probe ReleaseIntArrayElements__entry(void*, void*, uint32_t*, uint32_t); + probe ReleaseIntArrayElements__return(); + probe ReleaseLongArrayElements__entry(void*, void*, uintptr_t*, uint32_t); + probe ReleaseLongArrayElements__return(); + probe ReleasePrimitiveArrayCritical__entry(void*, void*, void*, uint32_t); + probe ReleasePrimitiveArrayCritical__return(); + probe ReleaseShortArrayElements__entry(void*, void*, uint16_t*, uint32_t); + probe ReleaseShortArrayElements__return(); + probe ReleaseStringChars__entry(void*, void*, const uint16_t*); + probe ReleaseStringChars__return(); + probe ReleaseStringCritical__entry(void*, void*, const uint16_t*); + probe ReleaseStringCritical__return(); + probe ReleaseStringUTFChars__entry(void*, void*, const char*); + probe ReleaseStringUTFChars__return(); + probe SetBooleanArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, const uintptr_t*); + probe SetBooleanArrayRegion__return(); + probe SetBooleanField__entry(void*, void*, uintptr_t, uintptr_t); + probe SetBooleanField__return(); + probe SetByteArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, const char*); + probe SetByteArrayRegion__return(); + probe SetByteField__entry(void*, void*, uintptr_t, char); + probe SetByteField__return(); + probe SetCharArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, const uint16_t*); + probe SetCharArrayRegion__return(); + probe SetCharField__entry(void*, void*, uintptr_t, uint16_t); + probe SetCharField__return(); + probe SetDoubleArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, const double*); + probe SetDoubleArrayRegion__return(); + probe SetDoubleField__entry(void*, void*, uintptr_t); + probe SetDoubleField__return(); + probe SetFloatArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, const float*); + probe SetFloatArrayRegion__return(); + probe SetFloatField__entry(void*, void*, uintptr_t); + probe SetFloatField__return(); + probe SetIntArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, const uint32_t*); + probe SetIntArrayRegion__return(); + probe SetIntField__entry(void*, void*, uintptr_t, uint32_t); + probe SetIntField__return(); + probe SetLongArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, const uintptr_t*); + probe SetLongArrayRegion__return(); + probe SetLongField__entry(void*, void*, uintptr_t, uintptr_t); + probe SetLongField__return(); + probe SetObjectArrayElement__entry(void*, void*, uintptr_t, void*); + probe SetObjectArrayElement__return(); + probe SetObjectField__entry(void*, void*, uintptr_t, void*); + probe SetObjectField__return(); + probe SetShortArrayRegion__entry(void*, void*, uintptr_t, uintptr_t, const uint16_t*); + probe SetShortArrayRegion__return(); + probe SetShortField__entry(void*, void*, uintptr_t, uint16_t); + probe SetShortField__return(); + probe SetStaticBooleanField__entry(void*, void*, uintptr_t, uintptr_t); + probe SetStaticBooleanField__return(); + probe SetStaticByteField__entry(void*, void*, uintptr_t, char); + probe SetStaticByteField__return(); + probe SetStaticCharField__entry(void*, void*, uintptr_t, uint16_t); + probe SetStaticCharField__return(); + probe SetStaticDoubleField__entry(void*, void*, uintptr_t); + probe SetStaticDoubleField__return(); + probe SetStaticFloatField__entry(void*, void*, uintptr_t); + probe SetStaticFloatField__return(); + probe SetStaticIntField__entry(void*, void*, uintptr_t, uint32_t); + probe SetStaticIntField__return(); + probe SetStaticLongField__entry(void*, void*, uintptr_t, uintptr_t); + probe SetStaticLongField__return(); + probe SetStaticObjectField__entry(void*, void*, uintptr_t, void*); + probe SetStaticObjectField__return(); + probe SetStaticShortField__entry(void*, void*, uintptr_t, uint16_t); + probe SetStaticShortField__return(); + probe Throw__entry(void*, void*); + probe Throw__return(intptr_t); + probe ThrowNew__entry(void*, void*, const char*); + probe ThrowNew__return(intptr_t); + probe ToReflectedField__entry(void*, void*, uintptr_t, uintptr_t); + probe ToReflectedField__return(void*); + probe ToReflectedMethod__entry(void*, void*, uintptr_t, uintptr_t); + probe ToReflectedMethod__return(void*); + probe UnregisterNatives__entry(void*, void*); + probe UnregisterNatives__return(uint32_t); +}; + +#pragma D attributes Standard/Standard/Common provider hotspot_jni provider +#pragma D attributes Private/Private/Unknown provider hotspot_jni module +#pragma D attributes Private/Private/Unknown provider hotspot_jni function +#pragma D attributes Standard/Standard/Common provider hotspot_jni name +#pragma D attributes Evolving/Evolving/Common provider hotspot_jni args +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/dtrace/hs_private.d Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +provider hs_private { + probe hashtable__new_entry(void*, uint32_t, uintptr_t, void*); + probe safepoint__begin(); + probe safepoint__end(); + probe cms__initmark__begin(); + probe cms__initmark__end(); + probe cms__remark__begin(); + probe cms__remark__end(); +}; + +#pragma D attributes Private/Private/Common provider hs_private provider +#pragma D attributes Private/Private/Unknown provider hs_private module +#pragma D attributes Private/Private/Unknown provider hs_private function +#pragma D attributes Private/Private/Common provider hs_private name +#pragma D attributes Private/Private/Common provider hs_private args +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/dtrace/jhelper.d Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2003, 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. + * + */ + +/* This file is auto-generated */ +#include "JvmOffsetsIndex.h" + +#define DEBUG + +#ifdef DEBUG +#define MARK_LINE this->line = __LINE__ +#else +#define MARK_LINE +#endif + +#ifdef _LP64 +#define STACK_BIAS 0x7ff +#define pointer uint64_t +#else +#define STACK_BIAS 0 +#define pointer uint32_t +#endif + +extern pointer __JvmOffsets; + +extern pointer __1cJCodeCacheF_heap_; +extern pointer __1cIUniverseP_methodKlassObj_; +extern pointer __1cIUniverseO_collectedHeap_; +extern pointer __1cIUniverseL_narrow_oop_; +#ifdef _LP64 +extern pointer UseCompressedOops; +#endif + +extern pointer __1cHnmethodG__vtbl_; +extern pointer __1cKBufferBlobG__vtbl_; + +#define copyin_ptr(ADDR) *(pointer*) copyin((pointer) (ADDR), sizeof(pointer)) +#define copyin_uchar(ADDR) *(uchar_t*) copyin((pointer) (ADDR), sizeof(uchar_t)) +#define copyin_uint16(ADDR) *(uint16_t*) copyin((pointer) (ADDR), sizeof(uint16_t)) +#define copyin_uint32(ADDR) *(uint32_t*) copyin((pointer) (ADDR), sizeof(uint32_t)) +#define copyin_int32(ADDR) *(int32_t*) copyin((pointer) (ADDR), sizeof(int32_t)) +#define copyin_uint8(ADDR) *(uint8_t*) copyin((pointer) (ADDR), sizeof(uint8_t)) + +#define SAME(x) x +#define copyin_offset(JVM_CONST) JVM_CONST = \ + copyin_int32(JvmOffsetsPtr + SAME(IDX_)JVM_CONST * sizeof(int32_t)) + +int init_done; + +dtrace:helper:ustack: +{ + MARK_LINE; + this->done = 0; + /* + * TBD: + * Here we initialize init_done, otherwise jhelper does not work. + * Therefore, copyin_offset() statements work multiple times now. + * There is a hope we could avoid it in the future, and so, + * this initialization can be removed. + */ + init_done = 0; + this->error = (char *) NULL; + this->result = (char *) NULL; + this->methodOop = 0; + this->codecache = 0; + this->klass = (pointer) NULL; + this->vtbl = (pointer) NULL; + this->suffix = '\0'; +} + +dtrace:helper:ustack: +{ + MARK_LINE; + /* Initialization of JvmOffsets constants */ + JvmOffsetsPtr = (pointer) &``__JvmOffsets; +} + +dtrace:helper:ustack: +/!init_done && !this->done/ +{ + MARK_LINE; + init_done = 1; + + copyin_offset(COMPILER); + copyin_offset(OFFSET_CollectedHeap_reserved); + copyin_offset(OFFSET_MemRegion_start); + copyin_offset(OFFSET_MemRegion_word_size); + copyin_offset(SIZE_HeapWord); + + copyin_offset(OFFSET_interpreter_frame_method); + copyin_offset(OFFSET_Klass_name); + copyin_offset(OFFSET_constantPoolOopDesc_pool_holder); + + copyin_offset(OFFSET_HeapBlockHeader_used); + copyin_offset(OFFSET_oopDesc_metadata); + + copyin_offset(OFFSET_Symbol_length); + copyin_offset(OFFSET_Symbol_body); + + copyin_offset(OFFSET_methodOopDesc_constMethod); + copyin_offset(OFFSET_methodOopDesc_constants); + copyin_offset(OFFSET_constMethodOopDesc_name_index); + copyin_offset(OFFSET_constMethodOopDesc_signature_index); + + copyin_offset(OFFSET_CodeHeap_memory); + copyin_offset(OFFSET_CodeHeap_segmap); + copyin_offset(OFFSET_CodeHeap_log2_segment_size); + + copyin_offset(OFFSET_VirtualSpace_low); + copyin_offset(OFFSET_VirtualSpace_high); + + copyin_offset(OFFSET_CodeBlob_name); + + copyin_offset(OFFSET_nmethod_method); + copyin_offset(SIZE_HeapBlockHeader); + copyin_offset(SIZE_oopDesc); + copyin_offset(SIZE_constantPoolOopDesc); + + copyin_offset(OFFSET_NarrowOopStruct_base); + copyin_offset(OFFSET_NarrowOopStruct_shift); + + /* + * The PC to translate is in arg0. + */ + this->pc = arg0; + + /* + * The methodOopPtr is in %l2 on SPARC. This can be found at + * offset 8 from the frame pointer on 32-bit processes. + */ +#if defined(__sparc) + this->methodOopPtr = copyin_ptr(arg1 + 2 * sizeof(pointer) + STACK_BIAS); +#elif defined(__i386) || defined(__amd64) + this->methodOopPtr = copyin_ptr(arg1 + OFFSET_interpreter_frame_method); +#else +#error "Don't know architecture" +#endif + + this->Universe_methodKlassOop = copyin_ptr(&``__1cIUniverseP_methodKlassObj_); + this->CodeCache_heap_address = copyin_ptr(&``__1cJCodeCacheF_heap_); + + /* Reading volatile values */ +#ifdef _LP64 + this->Use_Compressed_Oops = copyin_uint8(&``UseCompressedOops); +#else + this->Use_Compressed_Oops = 0; +#endif + + this->Universe_narrow_oop_base = copyin_ptr(&``__1cIUniverseL_narrow_oop_ + + OFFSET_NarrowOopStruct_base); + this->Universe_narrow_oop_shift = copyin_int32(&``__1cIUniverseL_narrow_oop_ + + OFFSET_NarrowOopStruct_shift); + + this->CodeCache_low = copyin_ptr(this->CodeCache_heap_address + + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low); + + this->CodeCache_high = copyin_ptr(this->CodeCache_heap_address + + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high); + + this->CodeCache_segmap_low = copyin_ptr(this->CodeCache_heap_address + + OFFSET_CodeHeap_segmap + OFFSET_VirtualSpace_low); + + this->CodeCache_segmap_high = copyin_ptr(this->CodeCache_heap_address + + OFFSET_CodeHeap_segmap + OFFSET_VirtualSpace_high); + + this->CodeHeap_log2_segment_size = copyin_uint32( + this->CodeCache_heap_address + OFFSET_CodeHeap_log2_segment_size); + + /* + * Get Java heap bounds + */ + this->Universe_collectedHeap = copyin_ptr(&``__1cIUniverseO_collectedHeap_); + this->heap_start = copyin_ptr(this->Universe_collectedHeap + + OFFSET_CollectedHeap_reserved + + OFFSET_MemRegion_start); + this->heap_size = SIZE_HeapWord * + copyin_ptr(this->Universe_collectedHeap + + OFFSET_CollectedHeap_reserved + + OFFSET_MemRegion_word_size + ); + this->heap_end = this->heap_start + this->heap_size; +} + +dtrace:helper:ustack: +/!this->done && +this->CodeCache_low <= this->pc && this->pc < this->CodeCache_high/ +{ + MARK_LINE; + this->codecache = 1; + + /* + * Find start. + */ + this->segment = (this->pc - this->CodeCache_low) >> + this->CodeHeap_log2_segment_size; + this->block = this->CodeCache_segmap_low; + this->tag = copyin_uchar(this->block + this->segment); + "second"; +} + +dtrace:helper:ustack: +/!this->done && this->codecache && this->tag > 0/ +{ + MARK_LINE; + this->tag = copyin_uchar(this->block + this->segment); + this->segment = this->segment - this->tag; +} + +dtrace:helper:ustack: +/!this->done && this->codecache && this->tag > 0/ +{ + MARK_LINE; + this->tag = copyin_uchar(this->block + this->segment); + this->segment = this->segment - this->tag; +} + +dtrace:helper:ustack: +/!this->done && this->codecache && this->tag > 0/ +{ + MARK_LINE; + this->tag = copyin_uchar(this->block + this->segment); + this->segment = this->segment - this->tag; +} + +dtrace:helper:ustack: +/!this->done && this->codecache && this->tag > 0/ +{ + MARK_LINE; + this->tag = copyin_uchar(this->block + this->segment); + this->segment = this->segment - this->tag; +} + +dtrace:helper:ustack: +/!this->done && this->codecache && this->tag > 0/ +{ + MARK_LINE; + this->tag = copyin_uchar(this->block + this->segment); + this->segment = this->segment - this->tag; +} + +dtrace:helper:ustack: +/!this->done && this->codecache && this->tag > 0/ +{ + MARK_LINE; + this->error = "<couldn't find start>"; + this->done = 1; +} + +dtrace:helper:ustack: +/!this->done && this->codecache/ +{ + MARK_LINE; + this->block = this->CodeCache_low + + (this->segment << this->CodeHeap_log2_segment_size); + this->used = copyin_uint32(this->block + OFFSET_HeapBlockHeader_used); +} + +dtrace:helper:ustack: +/!this->done && this->codecache && !this->used/ +{ + MARK_LINE; + this->error = "<block not in use>"; + this->done = 1; +} + +dtrace:helper:ustack: +/!this->done && this->codecache/ +{ + MARK_LINE; + this->start = this->block + SIZE_HeapBlockHeader; + this->vtbl = copyin_ptr(this->start); + + this->nmethod_vtbl = (pointer) &``__1cHnmethodG__vtbl_; + this->BufferBlob_vtbl = (pointer) &``__1cKBufferBlobG__vtbl_; +} + +dtrace:helper:ustack: +/!this->done && this->vtbl == this->nmethod_vtbl/ +{ + MARK_LINE; + this->methodOopPtr = copyin_ptr(this->start + OFFSET_nmethod_method); + this->suffix = '*'; + this->methodOop = 1; +} + +dtrace:helper:ustack: +/!this->done && this->vtbl == this->BufferBlob_vtbl/ +{ + MARK_LINE; + this->name = copyin_ptr(this->start + OFFSET_CodeBlob_name); +} + +dtrace:helper:ustack: +/!this->done && this->vtbl == this->BufferBlob_vtbl && +this->Use_Compressed_Oops == 0 && +this->methodOopPtr > this->heap_start && this->methodOopPtr < this->heap_end/ +{ + MARK_LINE; + this->klass = copyin_ptr(this->methodOopPtr + OFFSET_oopDesc_metadata); + this->methodOop = this->klass == this->Universe_methodKlassOop; + this->done = !this->methodOop; +} + +dtrace:helper:ustack: +/!this->done && this->vtbl == this->BufferBlob_vtbl && +this->Use_Compressed_Oops != 0 && +this->methodOopPtr > this->heap_start && this->methodOopPtr < this->heap_end/ +{ + MARK_LINE; + /* + * Read compressed pointer and decode heap oop, same as oop.inline.hpp + */ + this->cklass = copyin_uint32(this->methodOopPtr + OFFSET_oopDesc_metadata); + this->klass = (uint64_t)((uintptr_t)this->Universe_narrow_oop_base + + ((uintptr_t)this->cklass << this->Universe_narrow_oop_shift)); + this->methodOop = this->klass == this->Universe_methodKlassOop; + this->done = !this->methodOop; +} + +dtrace:helper:ustack: +/!this->done && !this->methodOop/ +{ + MARK_LINE; + this->name = copyin_ptr(this->start + OFFSET_CodeBlob_name); + this->result = this->name != 0 ? copyinstr(this->name) : "<CodeBlob>"; + this->done = 1; +} + +dtrace:helper:ustack: +/!this->done && this->methodOop/ +{ + MARK_LINE; + this->constMethod = copyin_ptr(this->methodOopPtr + + OFFSET_methodOopDesc_constMethod); + + this->nameIndex = copyin_uint16(this->constMethod + + OFFSET_constMethodOopDesc_name_index); + + this->signatureIndex = copyin_uint16(this->constMethod + + OFFSET_constMethodOopDesc_signature_index); + + this->constantPool = copyin_ptr(this->methodOopPtr + + OFFSET_methodOopDesc_constants); + + this->nameSymbol = copyin_ptr(this->constantPool + + this->nameIndex * sizeof (pointer) + SIZE_constantPoolOopDesc); + + this->nameSymbolLength = copyin_uint16(this->nameSymbol + + OFFSET_Symbol_length); + + this->signatureSymbol = copyin_ptr(this->constantPool + + this->signatureIndex * sizeof (pointer) + SIZE_constantPoolOopDesc); + + this->signatureSymbolLength = copyin_uint16(this->signatureSymbol + + OFFSET_Symbol_length); + + this->klassPtr = copyin_ptr(this->constantPool + + OFFSET_constantPoolOopDesc_pool_holder); + + this->klassSymbol = copyin_ptr(this->klassPtr + + OFFSET_Klass_name + SIZE_oopDesc); + + this->klassSymbolLength = copyin_uint16(this->klassSymbol + + OFFSET_Symbol_length); + + /* + * Enough for three strings, plus the '.', plus the trailing '\0'. + */ + this->result = (char *) alloca(this->klassSymbolLength + + this->nameSymbolLength + + this->signatureSymbolLength + 2 + 1); + + copyinto(this->klassSymbol + OFFSET_Symbol_body, + this->klassSymbolLength, this->result); + + /* + * Add the '.' between the class and the name. + */ + this->result[this->klassSymbolLength] = '.'; + + copyinto(this->nameSymbol + OFFSET_Symbol_body, + this->nameSymbolLength, + this->result + this->klassSymbolLength + 1); + + copyinto(this->signatureSymbol + OFFSET_Symbol_body, + this->signatureSymbolLength, + this->result + this->klassSymbolLength + + this->nameSymbolLength + 1); + + /* + * Now we need to add a trailing '\0' and possibly a tag character. + */ + this->result[this->klassSymbolLength + 1 + + this->nameSymbolLength + + this->signatureSymbolLength] = this->suffix; + this->result[this->klassSymbolLength + 2 + + this->nameSymbolLength + + this->signatureSymbolLength] = '\0'; + + this->done = 1; +} + +dtrace:helper:ustack: +/this->done && this->error == (char *) NULL/ +{ + this->result; +} + +dtrace:helper:ustack: +/this->done && this->error != (char *) NULL/ +{ + this->error; +} + +dtrace:helper:ustack: +/!this->done && this->codecache/ +{ + this->done = 1; + "error"; +} + + +dtrace:helper:ustack: +/!this->done/ +{ + NULL; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/dtrace/jvm_dtrace.c Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,565 @@ +/* + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 <door.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <poll.h> +#include <signal.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <thread.h> +#include <unistd.h> +#include "jvm_dtrace.h" + +// NOTE: These constants are used in JVM code as well. +// KEEP JVM CODE IN SYNC if you are going to change these... + +#define DTRACE_ALLOC_PROBES 0x1 +#define DTRACE_METHOD_PROBES 0x2 +#define DTRACE_MONITOR_PROBES 0x4 +#define DTRACE_ALL_PROBES -1 + +// generic error messages +#define JVM_ERR_OUT_OF_MEMORY "out of memory (native heap)" +#define JVM_ERR_INVALID_PARAM "invalid input parameter(s)" +#define JVM_ERR_NULL_PARAM "input paramater is NULL" + +// error messages for attach +#define JVM_ERR_CANT_OPEN_DOOR "cannot open door file" +#define JVM_ERR_CANT_CREATE_ATTACH_FILE "cannot create attach file" +#define JVM_ERR_DOOR_FILE_PERMISSION "door file is not secure" +#define JVM_ERR_CANT_SIGNAL "cannot send SIGQUIT to target" + +// error messages for enable probe +#define JVM_ERR_DOOR_CMD_SEND "door command send failed" +#define JVM_ERR_DOOR_CANT_READ_STATUS "cannot read door command status" +#define JVM_ERR_DOOR_CMD_STATUS "door command error status" + +// error message for detach +#define JVM_ERR_CANT_CLOSE_DOOR "cannot close door file" + +#define RESTARTABLE(_cmd, _result) do { \ + do { \ + _result = _cmd; \ + } while((_result == -1) && (errno == EINTR)); \ +} while(0) + +struct _jvm_t { + pid_t pid; + int door_fd; +}; + +static int libjvm_dtrace_debug; +static void print_debug(const char* fmt,...) { + if (libjvm_dtrace_debug) { + va_list alist; + va_start(alist, fmt); + fputs("libjvm_dtrace DEBUG: ", stderr); + vfprintf(stderr, fmt, alist); + va_end(alist); + } +} + +/* Key for thread local error message */ +static thread_key_t jvm_error_key; + +/* init function for this library */ +static void init_jvm_dtrace() { + /* check for env. var for debug mode */ + libjvm_dtrace_debug = getenv("LIBJVM_DTRACE_DEBUG") != NULL; + /* create key for thread local error message */ + if (thr_keycreate(&jvm_error_key, NULL) != 0) { + print_debug("can't create thread_key_t for jvm error key\n"); + // exit(1); ? + } +} + +#pragma init(init_jvm_dtrace) + +/* set thread local error message */ +static void set_jvm_error(const char* msg) { + thr_setspecific(jvm_error_key, (void*)msg); +} + +/* clear thread local error message */ +static void clear_jvm_error() { + thr_setspecific(jvm_error_key, NULL); +} + +/* file handling functions that can handle interrupt */ + +static int file_open(const char* path, int flag) { + int ret; + RESTARTABLE(open(path, flag), ret); + return ret; +} + +static int file_close(int fd) { + int ret; + RESTARTABLE(close(fd), ret); + return ret; +} + +static int file_read(int fd, char* buf, int len) { + int ret; + RESTARTABLE(read(fd, buf, len), ret); + return ret; +} + +/* send SIGQUIT signal to given process */ +static int send_sigquit(pid_t pid) { + int ret; + RESTARTABLE(kill(pid, SIGQUIT), ret); + return ret; +} + +/* called to check permissions on attach file */ +static int check_permission(const char* path) { + struct stat64 sb; + uid_t uid, gid; + int res; + + /* + * Check that the path is owned by the effective uid/gid of this + * process. Also check that group/other access is not allowed. + */ + uid = geteuid(); + gid = getegid(); + + res = stat64(path, &sb); + if (res != 0) { + print_debug("stat failed for %s\n", path); + return -1; + } + + if ((sb.st_uid != uid) || (sb.st_gid != gid) || + ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0)) { + print_debug("well-known file %s is not secure\n", path); + return -1; + } + return 0; +} + +#define ATTACH_FILE_PATTERN "/tmp/.attach_pid%d" + +/* fill-in the name of attach file name in given buffer */ +static void fill_attach_file_name(char* path, int len, pid_t pid) { + memset(path, 0, len); + sprintf(path, ATTACH_FILE_PATTERN, pid); +} + +#define DOOR_FILE_PATTERN "/tmp/.java_pid%d" + +/* open door file for the given JVM */ +static int open_door(pid_t pid) { + char path[PATH_MAX + 1]; + int fd; + + sprintf(path, DOOR_FILE_PATTERN, pid); + fd = file_open(path, O_RDONLY); + if (fd < 0) { + set_jvm_error(JVM_ERR_CANT_OPEN_DOOR); + print_debug("cannot open door file %s\n", path); + return -1; + } + print_debug("opened door file %s\n", path); + if (check_permission(path) != 0) { + set_jvm_error(JVM_ERR_DOOR_FILE_PERMISSION); + print_debug("check permission failed for %s\n", path); + file_close(fd); + fd = -1; + } + return fd; +} + +/* create attach file for given process */ +static int create_attach_file(pid_t pid) { + char path[PATH_MAX + 1]; + int fd; + fill_attach_file_name(path, sizeof(path), pid); + fd = file_open(path, O_CREAT | O_RDWR); + if (fd < 0) { + set_jvm_error(JVM_ERR_CANT_CREATE_ATTACH_FILE); + print_debug("cannot create file %s\n", path); + } else { + print_debug("created attach file %s\n", path); + } + return fd; +} + +/* delete attach file for given process */ +static void delete_attach_file(pid_t pid) { + char path[PATH_MAX + 1]; + fill_attach_file_name(path, sizeof(path), pid); + int res = unlink(path); + if (res) { + print_debug("cannot delete attach file %s\n", path); + } else { + print_debug("deleted attach file %s\n", path); + } +} + +/* attach to given JVM */ +jvm_t* jvm_attach(pid_t pid) { + jvm_t* jvm; + int door_fd, attach_fd, i; + + jvm = (jvm_t*) calloc(1, sizeof(jvm_t)); + if (jvm == NULL) { + set_jvm_error(JVM_ERR_OUT_OF_MEMORY); + print_debug("calloc failed in %s at %d\n", __FILE__, __LINE__); + return NULL; + } + jvm->pid = pid; + attach_fd = -1; + + door_fd = open_door(pid); + if (door_fd < 0) { + print_debug("trying to create attach file\n"); + if ((attach_fd = create_attach_file(pid)) < 0) { + goto quit; + } + + /* send QUIT signal to the target so that it will + * check for the attach file. + */ + if (send_sigquit(pid) != 0) { + set_jvm_error(JVM_ERR_CANT_SIGNAL); + print_debug("sending SIGQUIT failed\n"); + goto quit; + } + + /* give the target VM time to start the attach mechanism */ + do { + int res; + RESTARTABLE(poll(0, 0, 200), res); + door_fd = open_door(pid); + i++; + } while (i <= 50 && door_fd == -1); + if (door_fd < 0) { + print_debug("Unable to open door to process %d\n", pid); + goto quit; + } + } + +quit: + if (attach_fd >= 0) { + file_close(attach_fd); + delete_attach_file(jvm->pid); + } + if (door_fd >= 0) { + jvm->door_fd = door_fd; + clear_jvm_error(); + } else { + free(jvm); + jvm = NULL; + } + return jvm; +} + +/* return the last thread local error message */ +const char* jvm_get_last_error() { + const char* res = NULL; + thr_getspecific(jvm_error_key, (void**)&res); + return res; +} + +/* detach the givenb JVM */ +int jvm_detach(jvm_t* jvm) { + if (jvm) { + int res; + if (jvm->door_fd != -1) { + if (file_close(jvm->door_fd) != 0) { + set_jvm_error(JVM_ERR_CANT_CLOSE_DOOR); + res = -1; + } else { + clear_jvm_error(); + res = 0; + } + } + free(jvm); + return res; + } else { + set_jvm_error(JVM_ERR_NULL_PARAM); + print_debug("jvm_t* is NULL\n"); + return -1; + } +} + +/* + * A simple table to translate some known errors into reasonable + * error messages + */ +static struct { + int err; + const char* msg; +} const error_messages[] = { + { 100, "Bad request" }, + { 101, "Protocol mismatch" }, + { 102, "Resource failure" }, + { 103, "Internal error" }, + { 104, "Permission denied" }, +}; + +/* + * Lookup the given error code and return the appropriate + * message. If not found return NULL. + */ +static const char* translate_error(int err) { + int table_size = sizeof(error_messages) / sizeof(error_messages[0]); + int i; + + for (i=0; i<table_size; i++) { + if (err == error_messages[i].err) { + return error_messages[i].msg; + } + } + return NULL; +} + +/* + * Current protocol version + */ +static const char* PROTOCOL_VERSION = "1"; + +#define RES_BUF_SIZE 128 + +/* + * Enqueue attach-on-demand command to the given JVM + */ +static +int enqueue_command(jvm_t* jvm, const char* cstr, int arg_count, const char** args) { + size_t size; + door_arg_t door_args; + char res_buffer[RES_BUF_SIZE]; + int rc, i; + char* buf = NULL; + int result = -1; + + /* + * First we get the command string and create the start of the + * argument string to send to the target VM: + * <ver>\0<cmd>\0 + */ + if (cstr == NULL) { + print_debug("command name is NULL\n"); + goto quit; + } + size = strlen(PROTOCOL_VERSION) + strlen(cstr) + 2; + buf = (char*)malloc(size); + if (buf != NULL) { + char* pos = buf; + strcpy(buf, PROTOCOL_VERSION); + pos += strlen(PROTOCOL_VERSION)+1; + strcpy(pos, cstr); + } else { + set_jvm_error(JVM_ERR_OUT_OF_MEMORY); + print_debug("malloc failed at %d in %s\n", __LINE__, __FILE__); + goto quit; + } + + /* + * Next we iterate over the arguments and extend the buffer + * to include them. + */ + for (i=0; i<arg_count; i++) { + cstr = args[i]; + if (cstr != NULL) { + size_t len = strlen(cstr); + char* newbuf = (char*)realloc(buf, size+len+1); + if (newbuf == NULL) { + set_jvm_error(JVM_ERR_OUT_OF_MEMORY); + print_debug("realloc failed in %s at %d\n", __FILE__, __LINE__); + goto quit; + } + buf = newbuf; + strcpy(buf+size, cstr); + size += len+1; + } + } + + /* + * The arguments to the door function are in 'buf' so we now + * do the door call + */ + door_args.data_ptr = buf; + door_args.data_size = size; + door_args.desc_ptr = NULL; + door_args.desc_num = 0; + door_args.rbuf = (char*)&res_buffer; + door_args.rsize = sizeof(res_buffer); + + RESTARTABLE(door_call(jvm->door_fd, &door_args), rc); + + /* + * door_call failed + */ + if (rc == -1) { + print_debug("door_call failed\n"); + } else { + /* + * door_call succeeded but the call didn't return the the expected jint. + */ + if (door_args.data_size < sizeof(int)) { + print_debug("Enqueue error - reason unknown as result is truncated!"); + } else { + int* res = (int*)(door_args.data_ptr); + if (*res != 0) { + const char* msg = translate_error(*res); + if (msg == NULL) { + print_debug("Unable to enqueue command to target VM: %d\n", *res); + } else { + print_debug("Unable to enqueue command to target VM: %s\n", msg); + } + } else { + /* + * The door call should return a file descriptor to one end of + * a socket pair + */ + if ((door_args.desc_ptr != NULL) && + (door_args.desc_num == 1) && + (door_args.desc_ptr->d_attributes & DOOR_DESCRIPTOR)) { + result = door_args.desc_ptr->d_data.d_desc.d_descriptor; + } else { + print_debug("Reply from enqueue missing descriptor!\n"); + } + } + } + } + +quit: + if (buf) free(buf); + return result; +} + +/* read status code for a door command */ +static int read_status(int fd) { + char ch, buf[16]; + int index = 0; + + while (1) { + if (file_read(fd, &ch, sizeof(ch)) != sizeof(ch)) { + set_jvm_error(JVM_ERR_DOOR_CANT_READ_STATUS); + print_debug("door cmd status: read status failed\n"); + return -1; + } + buf[index++] = ch; + if (ch == '\n') { + buf[index - 1] = '\0'; + return atoi(buf); + } + if (index == sizeof(buf)) { + set_jvm_error(JVM_ERR_DOOR_CANT_READ_STATUS); + print_debug("door cmd status: read status overflow\n"); + return -1; + } + } +} + +static const char* ENABLE_DPROBES_CMD = "enabledprobes"; + +/* enable one or more DTrace probes for a given JVM */ +int jvm_enable_dtprobes(jvm_t* jvm, int num_probe_types, const char** probe_types) { + int fd, status = 0; + char ch; + const char* args[1]; + char buf[16]; + int probe_type = 0, index; + int count = 0; + + if (jvm == NULL) { + set_jvm_error(JVM_ERR_NULL_PARAM); + print_debug("jvm_t* is NULL\n"); + return -1; + } + + if (num_probe_types == 0 || probe_types == NULL || + probe_types[0] == NULL) { + set_jvm_error(JVM_ERR_INVALID_PARAM); + print_debug("invalid probe type argument(s)\n"); + return -1; + } + + for (index = 0; index < num_probe_types; index++) { + const char* p = probe_types[index]; + if (strcmp(p, JVM_DTPROBE_OBJECT_ALLOC) == 0) { + probe_type |= DTRACE_ALLOC_PROBES; + count++; + } else if (strcmp(p, JVM_DTPROBE_METHOD_ENTRY) == 0 || + strcmp(p, JVM_DTPROBE_METHOD_RETURN) == 0) { + probe_type |= DTRACE_METHOD_PROBES; + count++; + } else if (strcmp(p, JVM_DTPROBE_MONITOR_ENTER) == 0 || + strcmp(p, JVM_DTPROBE_MONITOR_ENTERED) == 0 || + strcmp(p, JVM_DTPROBE_MONITOR_EXIT) == 0 || + strcmp(p, JVM_DTPROBE_MONITOR_WAIT) == 0 || + strcmp(p, JVM_DTPROBE_MONITOR_WAITED) == 0 || + strcmp(p, JVM_DTPROBE_MONITOR_NOTIFY) == 0 || + strcmp(p, JVM_DTPROBE_MONITOR_NOTIFYALL) == 0) { + probe_type |= DTRACE_MONITOR_PROBES; + count++; + } else if (strcmp(p, JVM_DTPROBE_ALL) == 0) { + probe_type |= DTRACE_ALL_PROBES; + count++; + } + } + + if (count == 0) { + return count; + } + sprintf(buf, "%d", probe_type); + args[0] = buf; + + fd = enqueue_command(jvm, ENABLE_DPROBES_CMD, 1, args); + if (fd < 0) { + set_jvm_error(JVM_ERR_DOOR_CMD_SEND); + return -1; + } + + status = read_status(fd); + // non-zero status is error + if (status) { + set_jvm_error(JVM_ERR_DOOR_CMD_STATUS); + print_debug("%s command failed (status: %d) in target JVM\n", + ENABLE_DPROBES_CMD, status); + file_close(fd); + return -1; + } + // read from stream until EOF + while (file_read(fd, &ch, sizeof(ch)) == sizeof(ch)) { + if (libjvm_dtrace_debug) { + printf("%c", ch); + } + } + + file_close(fd); + clear_jvm_error(); + return count; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/dtrace/jvm_dtrace.h Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 _JVM_DTRACE_H_ +#define _JVM_DTRACE_H_ + +/* + * Interface to dynamically turn on probes in Hotspot JVM. Currently, + * this interface can be used to dynamically enable certain DTrace + * probe points that are costly to have "always on". + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/types.h> + + +struct _jvm_t; +typedef struct _jvm_t jvm_t; + + +/* Attach to the given JVM process. Returns NULL on failure. + jvm_get_last_error() returns last error message. */ +jvm_t* jvm_attach(pid_t pid); + +/* Returns the last error message from this library or NULL if none. */ +const char* jvm_get_last_error(); + +/* few well-known probe type constants for 'probe_types' param below */ + +#define JVM_DTPROBE_METHOD_ENTRY "method-entry" +#define JVM_DTPROBE_METHOD_RETURN "method-return" +#define JVM_DTPROBE_MONITOR_ENTER "monitor-contended-enter" +#define JVM_DTPROBE_MONITOR_ENTERED "monitor-contended-entered" +#define JVM_DTPROBE_MONITOR_EXIT "monitor-contended-exit" +#define JVM_DTPROBE_MONITOR_WAIT "monitor-wait" +#define JVM_DTPROBE_MONITOR_WAITED "monitor-waited" +#define JVM_DTPROBE_MONITOR_NOTIFY "monitor-notify" +#define JVM_DTPROBE_MONITOR_NOTIFYALL "monitor-notifyall" +#define JVM_DTPROBE_OBJECT_ALLOC "object-alloc" +#define JVM_DTPROBE_ALL "*" + +/* Enable the specified DTrace probes of given probe types on + * the specified JVM. Returns >= 0 on success, -1 on failure. + * On success, this returns number of probe_types enabled. + * On failure, jvm_get_last_error() returns the last error message. + */ +int jvm_enable_dtprobes(jvm_t* jvm, int num_probe_types, const char** probe_types); + +/* Note: There is no jvm_disable_dtprobes function. Probes are automatically + * disabled when there are no more clients requiring those probes. + */ + +/* Detach the given JVM. Returns 0 on success, -1 on failure. + * jvm_get_last_error() returns the last error message. + */ +int jvm_detach(jvm_t* jvm); + +#ifdef __cplusplus +} +#endif + +#endif /* _JVM_DTRACE_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/dtrace/libjvm_db.c Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,1548 @@ +/* + * Copyright (c) 2003, 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +// not available on macosx #include <gelf.h> + +#include "libjvm_db.h" +#include "JvmOffsets.h" + +#define LIBJVM_SO "libjvm.so" + +#if defined(i386) || defined(__i386) || defined(__amd64) +#ifdef COMPILER2 +#define X86_COMPILER2 +#endif /* COMPILER2 */ +#endif /* i386 */ + +typedef struct { + short vf_cnt; /* number of recognized java vframes */ + short bci; /* current frame method byte code index */ + int line; /* current frame method source line */ + uint64_t new_fp; /* fp for the next frame */ + uint64_t new_pc; /* pc for the next frame */ + uint64_t new_sp; /* "raw" sp for the next frame (includes extension by interpreter/adapter */ + char locinf; /* indicates there is valid location info */ +} Jframe_t; + +int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name, + size_t size, Jframe_t *jframe); + +int main(int arg) { return arg; } + +static int debug = 0; + +static void failed(int err, const char * file, int line) { + if (debug) { + fprintf(stderr, "failed %d at %s:%d\n", err, file, line); + } +} + +static void warn(const char * file, int line, const char * msg) { + if (debug) { + fprintf(stderr, "warning: %s at %s:%d\n", msg, file, line); + } +} + +static void warn1(const char * file, int line, const char * msg, intptr_t arg1) { + if (debug) { + fprintf(stderr, "warning: "); + fprintf(stderr, msg, arg1); + fprintf(stderr, " at %s:%d\n", file, line); + } +} + +#define CHECK_FAIL(err) \ + if (err != PS_OK) { failed(err, __FILE__, __LINE__); goto fail; } +#define WARN(msg) warn(__FILE__, __LINE__, msg) +#define WARN1(msg, arg1) warn1(__FILE__, __LINE__, msg, arg1) + +typedef struct VMStructEntry { + const char * typeName; /* The type name containing the given field (example: "Klass") */ + const char * fieldName; /* The field name within the type (example: "_name") */ + uint64_t address; /* Address of field; only used for static fields */ + /* ("offset" can not be reused because of apparent SparcWorks compiler bug */ + /* in generation of initializer data) */ +} VMStructEntry; + +/* Prototyping inlined methods */ + +int sprintf(char *s, const char *format, ...); + +#define SZ16 sizeof(int16_t) +#define SZ32 sizeof(int32_t) + +#define COMP_METHOD_SIGN '*' + +#define MAX_VFRAMES_CNT 256 + +typedef struct vframe { + uint64_t methodOop; + int32_t sender_decode_offset; + int32_t methodIdx; + int32_t bci; + int32_t line; +} Vframe_t; + +typedef struct frame { + uintptr_t fp; + uintptr_t pc; + uintptr_t sp; + uintptr_t sender_sp; // The unextended sp of the caller +} Frame_t; + +typedef struct Nmethod_t { + struct jvm_agent* J; + Jframe_t *jframe; + + uint64_t nm; /* _nmethod */ + uint64_t pc; + uint64_t pc_desc; + + int32_t orig_pc_offset; /* _orig_pc_offset */ + int32_t instrs_beg; /* _code_offset */ + int32_t instrs_end; + int32_t deopt_beg; /* _deoptimize_offset */ + int32_t scopes_data_beg; /* _scopes_data_offset */ + int32_t scopes_data_end; + int32_t oops_beg; /* _oops_offset */ + int32_t oops_end; + int32_t scopes_pcs_beg; /* _scopes_pcs_offset */ + int32_t scopes_pcs_end; + + int vf_cnt; + Vframe_t vframes[MAX_VFRAMES_CNT]; +} Nmethod_t; + +struct jvm_agent { + struct ps_prochandle* P; + + uint64_t nmethod_vtbl; + uint64_t CodeBlob_vtbl; + uint64_t BufferBlob_vtbl; + uint64_t RuntimeStub_vtbl; + + uint64_t Use_Compressed_Oops_address; + uint64_t Universe_methodKlassObj_address; + uint64_t Universe_narrow_oop_base_address; + uint64_t Universe_narrow_oop_shift_address; + uint64_t CodeCache_heap_address; + + /* Volatiles */ + uint8_t Use_Compressed_Oops; + uint64_t Universe_methodKlassObj; + uint64_t Universe_narrow_oop_base; + uint32_t Universe_narrow_oop_shift; + uint64_t CodeCache_low; + uint64_t CodeCache_high; + uint64_t CodeCache_segmap_low; + uint64_t CodeCache_segmap_high; + + int32_t SIZE_CodeCache_log2_segment; + + uint64_t methodOopPtr; + uint64_t bcx; + + Nmethod_t *N; /*Inlined methods support */ + Frame_t prev_fr; + Frame_t curr_fr; +}; + +static int +read_string(struct ps_prochandle *P, + char *buf, /* caller's buffer */ + size_t size, /* upper limit on bytes to read */ + uintptr_t addr) /* address in process */ +{ + int err = PS_OK; + while (size-- > 1 && err == PS_OK) { + err = ps_pread(P, addr, buf, 1); + if (*buf == '\0') { + return PS_OK; + } + addr += 1; + buf += 1; + } + return -1; +} + +static int read_compressed_pointer(jvm_agent_t* J, uint64_t base, uint32_t *ptr) { + int err = -1; + uint32_t ptr32; + err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t)); + *ptr = ptr32; + return err; +} + +static int read_pointer(jvm_agent_t* J, uint64_t base, uint64_t* ptr) { + int err = -1; + uint32_t ptr32; + + switch (DATA_MODEL) { + case PR_MODEL_LP64: + err = ps_pread(J->P, base, ptr, sizeof(uint64_t)); + break; + case PR_MODEL_ILP32: + err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t)); + *ptr = ptr32; + break; + } + + return err; +} + +static int read_string_pointer(jvm_agent_t* J, uint64_t base, const char ** stringp) { + uint64_t ptr; + int err; + char buffer[1024]; + + *stringp = NULL; + err = read_pointer(J, base, &ptr); + CHECK_FAIL(err); + if (ptr != 0) { + err = read_string(J->P, buffer, sizeof(buffer), ptr); + CHECK_FAIL(err); + *stringp = strdup(buffer); + } + return PS_OK; + + fail: + return err; +} + +static int parse_vmstruct_entry(jvm_agent_t* J, uint64_t base, VMStructEntry* vmp) { + uint64_t ptr; + int err; + + err = read_string_pointer(J, base + OFFSET_VMStructEntrytypeName, &vmp->typeName); + CHECK_FAIL(err); + err = read_string_pointer(J, base + OFFSET_VMStructEntryfieldName, &vmp->fieldName); + CHECK_FAIL(err); + err = read_pointer(J, base + OFFSET_VMStructEntryaddress, &vmp->address); + CHECK_FAIL(err); + + return PS_OK; + + fail: + if (vmp->typeName != NULL) free((void*)vmp->typeName); + if (vmp->fieldName != NULL) free((void*)vmp->fieldName); + return err; +} + +static int parse_vmstructs(jvm_agent_t* J) { + VMStructEntry vmVar; + VMStructEntry* vmp = &vmVar; + uint64_t gHotSpotVMStructs; + psaddr_t sym_addr; + uint64_t base; + int err; + + err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr); + CHECK_FAIL(err); + err = read_pointer(J, sym_addr, &gHotSpotVMStructs); + CHECK_FAIL(err); + base = gHotSpotVMStructs; + + err = PS_OK; + while (err == PS_OK) { + memset(vmp, 0, sizeof(VMStructEntry)); + err = parse_vmstruct_entry(J, base, vmp); + if (err != PS_OK || vmp->typeName == NULL) { + break; + } + + if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) { + if (strcmp("_heap", vmp->fieldName) == 0) { + err = read_pointer(J, vmp->address, &J->CodeCache_heap_address); + } + } else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) { + if (strcmp("_methodKlassObj", vmp->fieldName) == 0) { + J->Universe_methodKlassObj_address = vmp->address; + } + if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) { + J->Universe_narrow_oop_base_address = vmp->address; + } + if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) { + J->Universe_narrow_oop_shift_address = vmp->address; + } + } + CHECK_FAIL(err); + + base += SIZE_VMStructEntry; + if (vmp->typeName != NULL) free((void*)vmp->typeName); + if (vmp->fieldName != NULL) free((void*)vmp->fieldName); + } + + return PS_OK; + + fail: + if (vmp->typeName != NULL) free((void*)vmp->typeName); + if (vmp->fieldName != NULL) free((void*)vmp->fieldName); + return -1; +} + +static int find_symbol(jvm_agent_t* J, const char *name, uint64_t* valuep) { + psaddr_t sym_addr; + int err; + + err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr); + if (err != PS_OK) goto fail; + *valuep = sym_addr; + return PS_OK; + + fail: + return err; +} + +static int read_volatiles(jvm_agent_t* J) { + uint64_t ptr; + int err; + + err = find_symbol(J, "UseCompressedOops", &J->Use_Compressed_Oops_address); + if (err == PS_OK) { + err = ps_pread(J->P, J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t)); + CHECK_FAIL(err); + } else { + J->Use_Compressed_Oops = 0; + } + + err = read_pointer(J, J->Universe_methodKlassObj_address, &J->Universe_methodKlassObj); + CHECK_FAIL(err); + + err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base); + CHECK_FAIL(err); + err = ps_pread(J->P, J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t)); + CHECK_FAIL(err); + + err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory + + OFFSET_VirtualSpace_low, &J->CodeCache_low); + CHECK_FAIL(err); + err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory + + OFFSET_VirtualSpace_high, &J->CodeCache_high); + CHECK_FAIL(err); + err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap + + OFFSET_VirtualSpace_low, &J->CodeCache_segmap_low); + CHECK_FAIL(err); + err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap + + OFFSET_VirtualSpace_high, &J->CodeCache_segmap_high); + CHECK_FAIL(err); + + err = ps_pread(J->P, J->CodeCache_heap_address + OFFSET_CodeHeap_log2_segment_size, + &J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment)); + CHECK_FAIL(err); + + return PS_OK; + + fail: + return err; +} + + +static int codecache_contains(jvm_agent_t* J, uint64_t ptr) { + /* make sure the code cache is up to date */ + return (J->CodeCache_low <= ptr && ptr < J->CodeCache_high); +} + +static uint64_t segment_for(jvm_agent_t* J, uint64_t p) { + return (p - J->CodeCache_low) >> J->SIZE_CodeCache_log2_segment; +} + +static uint64_t block_at(jvm_agent_t* J, int i) { + return J->CodeCache_low + (i << J->SIZE_CodeCache_log2_segment); +} + +static int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) { + int err; + + *startp = 0; + if (J->CodeCache_low <= ptr && ptr < J->CodeCache_high) { + int32_t used; + uint64_t segment = segment_for(J, ptr); + uint64_t block = J->CodeCache_segmap_low; + uint8_t tag; + err = ps_pread(J->P, block + segment, &tag, sizeof(tag)); + CHECK_FAIL(err); + if (tag == 0xff) + return PS_OK; + while (tag > 0) { + err = ps_pread(J->P, block + segment, &tag, sizeof(tag)); + CHECK_FAIL(err); + segment -= tag; + } + block = block_at(J, segment); + err = ps_pread(J->P, block + OFFSET_HeapBlockHeader_used, &used, sizeof(used)); + CHECK_FAIL(err); + if (used) { + *startp = block + SIZE_HeapBlockHeader; + } + } + return PS_OK; + + fail: + return -1; +} + +static int find_jlong_constant(jvm_agent_t* J, const char *name, uint64_t* valuep) { + psaddr_t sym_addr; + int err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr); + if (err == PS_OK) { + err = ps_pread(J->P, sym_addr, valuep, sizeof(uint64_t)); + return err; + } + *valuep = -1; + return -1; +} + +jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers) { + jvm_agent_t* J; + int err; + + if (vers != JVM_DB_VERSION) { + errno = ENOTSUP; + return NULL; + } + + J = (jvm_agent_t*)calloc(sizeof(struct jvm_agent), 1); + + debug = getenv("LIBJVMDB_DEBUG") != NULL; + if (debug) debug = 3; + + if (debug) { + fprintf(stderr, "Jagent_create: debug=%d\n", debug); +#ifdef X86_COMPILER2 + fprintf(stderr, "Jagent_create: R_SP=%d, R_FP=%d, POINTER_SIZE=%d\n", R_SP, R_FP, POINTER_SIZE); +#endif /* X86_COMPILER2 */ + } + + J->P = P; + + // Initialize the initial previous frame + + J->prev_fr.fp = 0; + J->prev_fr.pc = 0; + J->prev_fr.sp = 0; + J->prev_fr.sender_sp = 0; + + err = find_symbol(J, "__1cHnmethodG__vtbl_", &J->nmethod_vtbl); + CHECK_FAIL(err); + err = find_symbol(J, "__1cKBufferBlobG__vtbl_", &J->BufferBlob_vtbl); + if (err != PS_OK) J->BufferBlob_vtbl = 0; + err = find_symbol(J, "__1cICodeBlobG__vtbl_", &J->CodeBlob_vtbl); + CHECK_FAIL(err); + err = find_symbol(J, "__1cLRuntimeStubG__vtbl_", &J->RuntimeStub_vtbl); + CHECK_FAIL(err); + + err = parse_vmstructs(J); + CHECK_FAIL(err); + err = read_volatiles(J); + CHECK_FAIL(err); + + return J; + + fail: + Jagent_destroy(J); + return NULL; +} + +void Jagent_destroy(jvm_agent_t *J) { + if (J != NULL) { + free(J); + } +} + +static int is_methodOop(jvm_agent_t* J, uint64_t methodOopPtr) { + uint64_t klass; + int err; + // If UseCompressedOops, this was a compressed oop. + if (J->Use_Compressed_Oops != 0) { + uint32_t cklass; + err = read_compressed_pointer(J, methodOopPtr + OFFSET_oopDesc_metadata, + &cklass); + // decode heap oop, same as oop.inline.hpp + klass = (uint64_t)((uintptr_t)J->Universe_narrow_oop_base + + ((uintptr_t)cklass << J->Universe_narrow_oop_shift)); + } else { + err = read_pointer(J, methodOopPtr + OFFSET_oopDesc_metadata, &klass); + } + if (err != PS_OK) goto fail; + return klass == J->Universe_methodKlassObj; + + fail: + return 0; +} + +static int +name_for_methodOop(jvm_agent_t* J, uint64_t methodOopPtr, char * result, size_t size) +{ + short nameIndex; + short signatureIndex; + uint64_t constantPool; + uint64_t constMethod; + uint64_t nameSymbol; + uint64_t signatureSymbol; + uint64_t klassPtr; + uint64_t klassSymbol; + short klassSymbolLength; + short nameSymbolLength; + short signatureSymbolLength; + char * nameString = NULL; + char * klassString = NULL; + char * signatureString = NULL; + int err; + + err = read_pointer(J, methodOopPtr + OFFSET_methodOopDesc_constants, &constantPool); + CHECK_FAIL(err); + err = read_pointer(J, methodOopPtr + OFFSET_methodOopDesc_constMethod, &constMethod); + CHECK_FAIL(err); + + /* To get name string */ + err = ps_pread(J->P, constMethod + OFFSET_constMethodOopDesc_name_index, &nameIndex, 2); + CHECK_FAIL(err); + err = read_pointer(J, constantPool + nameIndex * POINTER_SIZE + SIZE_constantPoolOopDesc, &nameSymbol); + CHECK_FAIL(err); + // The symbol is a CPSlot and has lower bit set to indicate metadata + nameSymbol &= (~1); // remove metadata lsb + err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2); + CHECK_FAIL(err); + nameString = (char*)calloc(nameSymbolLength + 1, 1); + err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength); + CHECK_FAIL(err); + + /* To get signature string */ + err = ps_pread(J->P, constMethod + OFFSET_constMethodOopDesc_signature_index, &signatureIndex, 2); + CHECK_FAIL(err); + err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_constantPoolOopDesc, &signatureSymbol); + CHECK_FAIL(err); + signatureSymbol &= (~1); // remove metadata lsb + err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2); + CHECK_FAIL(err); + signatureString = (char*)calloc(signatureSymbolLength + 1, 1); + err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength); + CHECK_FAIL(err); + + /* To get klass string */ + err = read_pointer(J, constantPool + OFFSET_constantPoolOopDesc_pool_holder, &klassPtr); + CHECK_FAIL(err); + err = read_pointer(J, klassPtr + OFFSET_Klass_name + SIZE_oopDesc, &klassSymbol); + CHECK_FAIL(err); + err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2); + CHECK_FAIL(err); + klassString = (char*)calloc(klassSymbolLength + 1, 1); + err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength); + CHECK_FAIL(err); + + result[0] = '\0'; + strncat(result, klassString, size); + size -= strlen(klassString); + strncat(result, ".", size); + size -= 1; + strncat(result, nameString, size); + size -= strlen(nameString); + strncat(result, signatureString, size); + + if (nameString != NULL) free(nameString); + if (klassString != NULL) free(klassString); + if (signatureString != NULL) free(signatureString); + + return PS_OK; + + fail: + if (debug) { + fprintf(stderr, "name_for_methodOop: FAIL \n\n"); + } + if (nameString != NULL) free(nameString); + if (klassString != NULL) free(klassString); + if (signatureString != NULL) free(signatureString); + return -1; +} + +static int nmethod_info(Nmethod_t *N) +{ + jvm_agent_t *J = N->J; + uint64_t nm = N->nm; + int32_t err; + + if (debug > 2 ) + fprintf(stderr, "\t nmethod_info: BEGIN \n"); + + /* Instructions */ + err = ps_pread(J->P, nm + OFFSET_CodeBlob_code_offset, &N->instrs_beg, SZ32); + CHECK_FAIL(err); + err = ps_pread(J->P, nm + OFFSET_CodeBlob_data_offset, &N->instrs_end, SZ32); + CHECK_FAIL(err); + err = ps_pread(J->P, nm + OFFSET_nmethod_deoptimize_offset, &N->deopt_beg, SZ32); + CHECK_FAIL(err); + err = ps_pread(J->P, nm + OFFSET_nmethod_orig_pc_offset, &N->orig_pc_offset, SZ32); + CHECK_FAIL(err); + + /* Oops */ + err = ps_pread(J->P, nm + OFFSET_nmethod_oops_offset, &N->oops_beg, SZ32); + CHECK_FAIL(err); + err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->oops_end, SZ32); + CHECK_FAIL(err); + + /* scopes_pcs */ + err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_pcs_offset, &N->scopes_pcs_beg, SZ32); + CHECK_FAIL(err); + err = ps_pread(J->P, nm + OFFSET_nmethod_handler_table_offset, &N->scopes_pcs_end, SZ32); + CHECK_FAIL(err); + + /* scopes_data */ + err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->scopes_data_beg, SZ32); + CHECK_FAIL(err); + + if (debug > 2 ) { + N->scopes_data_end = N->scopes_pcs_beg; + + fprintf(stderr, "\t nmethod_info: instrs_beg: %#x, instrs_end: %#x\n", + N->instrs_beg, N->instrs_end); + + fprintf(stderr, "\t nmethod_info: deopt_beg: %#x \n", + N->deopt_beg); + + fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n", + N->orig_pc_offset); + + fprintf(stderr, "\t nmethod_info: oops_beg: %#x, oops_end: %#x\n", + N->oops_beg, N->oops_end); + + fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n", + N->scopes_data_beg, N->scopes_data_end); + + fprintf(stderr, "\t nmethod_info: scopes_pcs_beg: %#x, scopes_pcs_end: %#x\n", + N->scopes_pcs_beg, N->scopes_pcs_end); + + fprintf(stderr, "\t nmethod_info: END \n\n"); + } + return PS_OK; + + fail: + return err; +} + +static int +raw_read_int(jvm_agent_t* J, uint64_t *buffer, int32_t *val) +{ + int shift = 0; + int value = 0; + uint8_t ch = 0; + int32_t err; + int32_t sum; + // Constants for UNSIGNED5 coding of Pack200 + // see compressedStream.hpp + enum { + lg_H = 6, + H = 1<<lg_H, + BitsPerByte = 8, + L = (1<<BitsPerByte)-H, + }; + int i; + + err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t)); + CHECK_FAIL(err); + if (debug > 2) + fprintf(stderr, "\t\t\t raw_read_int: *buffer: %#llx, ch: %#x\n", *buffer, ch); + + sum = ch; + if ( sum >= L ) { + int32_t lg_H_i = lg_H; + // Read maximum of 5 total bytes (we've already read 1). + // See CompressedReadStream::read_int_mb + for ( i = 0; i < 4; i++) { + err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t)); + CHECK_FAIL(err); + sum += ch << lg_H_i; + if (ch < L ) { + *val = sum; + return PS_OK; + } + lg_H_i += lg_H; + } + } + *val = sum; + return PS_OK; + + fail: + return err; +} + +static int +read_pair(jvm_agent_t* J, uint64_t *buffer, int32_t *bci, int32_t *line) +{ + uint8_t next = 0; + int32_t bci_delta; + int32_t line_delta; + int32_t err; + + if (debug > 2) + fprintf(stderr, "\t\t read_pair: BEGIN\n"); + + err = ps_pread(J->P, (*buffer)++, &next, sizeof(uint8_t)); + CHECK_FAIL(err); + + if (next == 0) { + if (debug > 2) + fprintf(stderr, "\t\t read_pair: END: next == 0\n"); + return 1; /* stream terminated */ + } + if (next == 0xFF) { + if (debug > 2) + fprintf(stderr, "\t\t read_pair: END: next == 0xFF\n"); + + /* Escape character, regular compression used */ + + err = raw_read_int(J, buffer, &bci_delta); + CHECK_FAIL(err); + + err = raw_read_int(J, buffer, &line_delta); + CHECK_FAIL(err); + + *bci += bci_delta; + *line += line_delta; + + if (debug > 2) { + fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n", + line_delta, bci_delta); + fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n", + *line, *bci); + } + } else { + /* Single byte compression used */ + *bci += next >> 3; + *line += next & 0x7; + if (debug > 2) { + fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n", + next & 0x7, next >> 3); + fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n", + *line, *bci); + } + } + if (debug > 2) + fprintf(stderr, "\t\t read_pair: END\n"); + return PS_OK; + + fail: + if (debug) + fprintf(stderr, "\t\t read_pair: FAIL\n"); + return err; +} + +static int +line_number_from_bci(jvm_agent_t* J, Vframe_t *vf) +{ + uint64_t buffer; + uint16_t code_size; + uint64_t code_end_delta; + uint64_t constMethod; + int8_t access_flags; + int32_t best_bci = 0; + int32_t stream_bci = 0; + int32_t stream_line = 0; + int32_t err; + + if (debug > 2) { + char name[256]; + err = name_for_methodOop(J, vf->methodOop, name, 256); + CHECK_FAIL(err); + fprintf(stderr, "\t line_number_from_bci: BEGIN, method name: %s, targ bci: %d\n", + name, vf->bci); + } + + err = read_pointer(J, vf->methodOop + OFFSET_methodOopDesc_constMethod, &constMethod); + CHECK_FAIL(err); + + vf->line = 0; + err = ps_pread(J->P, constMethod + OFFSET_constMethodOopDesc_flags, &access_flags, sizeof(int8_t)); + CHECK_FAIL(err); + + if (!(access_flags & constMethodOopDesc_has_linenumber_table)) { + if (debug > 2) + fprintf(stderr, "\t line_number_from_bci: END: !HAS_LINE_NUMBER_TABLE \n\n"); + return PS_OK; + } + + /* The line numbers are a short array of 2-tuples [start_pc, line_number]. + * Not necessarily sorted and not necessarily one-to-one. + */ + + err = ps_pread(J->P, constMethod + OFFSET_constMethodOopDesc_code_size, &code_size, SZ16); + CHECK_FAIL(err); + + /* inlined_table_start() */ + code_end_delta = (uint64_t) (access_flags & AccessFlags_NATIVE) ? 2*POINTER_SIZE : 0; + buffer = constMethod + (uint64_t) SIZE_constMethodOopDesc + (uint64_t) code_size + code_end_delta; + + if (debug > 2) { + fprintf(stderr, "\t\t line_number_from_bci: methodOop: %#llx, native: %d\n", + vf->methodOop, (access_flags & AccessFlags_NATIVE)); + fprintf(stderr, "\t\t line_number_from_bci: buffer: %#llx, code_size: %d\n", + buffer, (int) code_size); + } + + while (read_pair(J, &buffer, &stream_bci, &stream_line) == 0) { + if (stream_bci == vf->bci) { + /* perfect match */ + if (debug > 2) + fprintf(stderr, "\t line_number_from_bci: END: exact line: %ld \n\n", vf->line); + vf->line = stream_line; + return PS_OK; + } else { + /* update best_bci/line */ + if (stream_bci < vf->bci && stream_bci >= best_bci) { + best_bci = stream_bci; + vf->line = stream_line; + if (debug > 2) { + fprintf(stderr, "\t line_number_from_bci: best_bci: %ld, best_line: %ld\n", + best_bci, vf->line); + } + } + } + } + if (debug > 2) + fprintf(stderr, "\t line_number_from_bci: END: line: %ld \n\n", vf->line); + return PS_OK; + + fail: + if (debug) + fprintf(stderr, "\t line_number_from_bci: FAIL\n"); + return err; +} + +static int +get_real_pc(Nmethod_t *N, uint64_t pc_desc, uint64_t *real_pc) +{ + int32_t pc_offset; + int32_t err; + + err = ps_pread(N->J->P, pc_desc + OFFSET_PcDesc_pc_offset, &pc_offset, SZ32); + CHECK_FAIL(err); + + *real_pc = N->nm + N->instrs_beg + pc_offset; + if (debug > 2) { + fprintf(stderr, "\t\t get_real_pc: pc_offset: %lx, real_pc: %llx\n", + pc_offset, *real_pc); + } + return PS_OK; + + fail: + return err; +} + +/* Finds a PcDesc with real-pc equal to N->pc */ +static int pc_desc_at(Nmethod_t *N) +{ + uint64_t pc_diff; + int32_t offs; + int32_t err; + + if (debug > 2) + fprintf(stderr, "\t pc_desc_at: BEGIN\n"); + + N->vf_cnt = 0; + N->pc_desc = 0; + + for (offs = N->scopes_pcs_beg; offs < N->scopes_pcs_end; offs += SIZE_PcDesc) { + uint64_t pd; + uint64_t best_pc_diff = 16; /* some approximation */ + uint64_t real_pc = 0; + + pd = N->nm + offs; + err = get_real_pc(N, pd, &real_pc); + CHECK_FAIL(err); + + pc_diff = real_pc - N->pc; + + /* In general, this fragment should work */ + if (pc_diff == 0) { + N->pc_desc = pd; + if (debug) { + fprintf(stderr, "\t pc_desc_at: END: pc_desc: FOUND: %#lx \n\n", pd); + } + return PS_OK; + } + /* This fragment is to be able to find out an appropriate + * pc_desc entry even if pc_desc info is inaccurate. + */ + if (best_pc_diff > pc_diff && pc_diff > 0) { + best_pc_diff = pc_diff; + N->pc_desc = pd; + } + } + if (debug) { + fprintf(stderr, "\t pc_desc_at: END: pc_desc NOT FOUND"); + if (pc_diff < 20) + fprintf(stderr, ", best pc_diff: %d\n\n", pc_diff); + else + fprintf(stderr, "\n\n"); + } + return PS_OK; + + fail: + return err; +} + +static int +scope_desc_at(Nmethod_t *N, int32_t decode_offset, Vframe_t *vf) +{ + uint64_t buffer; + int32_t err; + + if (debug > 2) { + fprintf(stderr, "\t\t scope_desc_at: BEGIN \n"); + } + + buffer = N->nm + N->scopes_data_beg + decode_offset; + + err = raw_read_int(N->J, &buffer, &vf->sender_decode_offset); + CHECK_FAIL(err); + + err = raw_read_int(N->J, &buffer, &vf->methodIdx); + CHECK_FAIL(err); + + err = raw_read_int(N->J, &buffer, &vf->bci); + CHECK_FAIL(err); + + if (debug > 2) { + fprintf(stderr, "\t\t scope_desc_at: sender_decode_offset: %#x\n", + vf->sender_decode_offset); + fprintf(stderr, "\t\t scope_desc_at: methodIdx: %d\n", vf->methodIdx); + fprintf(stderr, "\t\t scope_desc_at: bci: %d\n", vf->bci); + + fprintf(stderr, "\t\t scope_desc_at: END \n\n"); + } + return PS_OK; + + fail: + return err; +} + +static int scopeDesc_chain(Nmethod_t *N) { + int32_t decode_offset = 0; + int32_t err; + + if (debug > 2) { + fprintf(stderr, "\t scopeDesc_chain: BEGIN\n"); + } + + err = ps_pread(N->J->P, N->pc_desc + OFFSET_PcDesc_scope_decode_offset, + &decode_offset, SZ32); + CHECK_FAIL(err); + + while (decode_offset > 0) { + Vframe_t *vf = &N->vframes[N->vf_cnt]; + + if (debug > 2) { + fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset); + } + + err = scope_desc_at(N, decode_offset, vf); + CHECK_FAIL(err); + + if (vf->methodIdx > ((N->oops_end - N->oops_beg) / POINTER_SIZE)) { + fprintf(stderr, "\t scopeDesc_chain: (methodIdx > oops length) !\n"); + return -1; + } + err = read_pointer(N->J, N->nm + N->oops_beg + (vf->methodIdx-1)*POINTER_SIZE, + &vf->methodOop); + CHECK_FAIL(err); + + if (vf->methodOop) { + N->vf_cnt++; + err = line_number_from_bci(N->J, vf); + CHECK_FAIL(err); + if (debug > 2) { + fprintf(stderr, "\t scopeDesc_chain: methodOop: %#8llx, line: %ld\n", + vf->methodOop, vf->line); + } + } + decode_offset = vf->sender_decode_offset; + } + if (debug > 2) { + fprintf(stderr, "\t scopeDesc_chain: END \n\n"); + } + return PS_OK; + + fail: + if (debug) { + fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n"); + } + return err; +} + + +static int +name_for_nmethod(jvm_agent_t* J, + uint64_t nm, + uint64_t pc, + uint64_t methodOop, + char *result, + size_t size, + Jframe_t *jframe +) { + Nmethod_t *N; + Vframe_t *vf; + int32_t err; + int deoptimized = 0; + + if (debug) { + fprintf(stderr, "name_for_nmethod: BEGIN: nmethod: %#llx, pc: %#llx\n", nm, pc); + } + if (J->N == NULL) { + J->N = (Nmethod_t *) malloc(sizeof(Nmethod_t)); + } + memset(J->N, 0, sizeof(Nmethod_t)); /* Initial stat: all values are zeros */ + N = J->N; + N->J = J; + N->nm = nm; + N->pc = pc; + N->jframe = jframe; + + err = nmethod_info(N); + CHECK_FAIL(err); + if (debug) { + fprintf(stderr, "name_for_nmethod: pc: %#llx, deopt_pc: %#llx\n", + pc, N->nm + N->deopt_beg); + } + + /* check for a deoptimized frame */ + if ( pc == N->nm + N->deopt_beg) { + uint64_t base; + if (debug) { + fprintf(stderr, "name_for_nmethod: found deoptimized frame\n"); + } + if (J->prev_fr.sender_sp != 0) { + base = J->prev_fr.sender_sp + N->orig_pc_offset; + } else { + base = J->curr_fr.sp + N->orig_pc_offset; + } + err = read_pointer(J, base, &N->pc); + CHECK_FAIL(err); + if (debug) { + fprintf(stderr, "name_for_nmethod: found deoptimized frame converting pc from %#8llx to %#8llx\n", + pc, N->pc); + } + deoptimized = 1; + } + + err = pc_desc_at(N); + CHECK_FAIL(err); + + if (N->pc_desc > 0) { + jframe->locinf = 1; + err = scopeDesc_chain(N); + CHECK_FAIL(err); + } + result[0] = COMP_METHOD_SIGN; + vf = &N->vframes[0]; + if (N->vf_cnt > 0) { + jframe->vf_cnt = N->vf_cnt; + jframe->bci = vf->bci; + jframe->line = vf->line; + err = name_for_methodOop(J, N->vframes[0].methodOop, result+1, size-1); + CHECK_FAIL(err); + } else { + err = name_for_methodOop(J, methodOop, result+1, size-1); + CHECK_FAIL(err); + } + if (deoptimized) { + strncat(result + 1, " [deoptimized frame]; ", size-1); + } else { + strncat(result + 1, " [compiled] ", size-1); + } + if (debug) + fprintf(stderr, "name_for_nmethod: END: method name: %s, vf_cnt: %d\n\n", + result, N->vf_cnt); + return PS_OK; + + fail: + if (debug) + fprintf(stderr, "name_for_nmethod: FAIL \n\n"); + return err; +} + +int is_bci(intptr_t bcx) { + switch (DATA_MODEL) { + case PR_MODEL_LP64: + return ((uintptr_t) bcx) <= ((uintptr_t) MAX_METHOD_CODE_SIZE) ; + case PR_MODEL_ILP32: + default: + return 0 <= bcx && bcx <= MAX_METHOD_CODE_SIZE; + } +} + +static int +name_for_imethod(jvm_agent_t* J, + uint64_t bcx, + uint64_t methodOop, + char *result, + size_t size, + Jframe_t *jframe +) { + uint64_t bci; + uint64_t constMethod; + Vframe_t vframe = {0}; + Vframe_t *vf = &vframe; + int32_t err; + + err = read_pointer(J, methodOop + OFFSET_methodOopDesc_constMethod, &constMethod); + CHECK_FAIL(err); + + bci = is_bci(bcx) ? bcx : bcx - (constMethod + (uint64_t) SIZE_constMethodOopDesc); + + if (debug) + fprintf(stderr, "\t name_for_imethod: BEGIN: methodOop: %#llx\n", methodOop); + + err = name_for_methodOop(J, methodOop, result, size); + CHECK_FAIL(err); + if (debug) + fprintf(stderr, "\t name_for_imethod: method name: %s\n", result); + + if (bci > 0) { + vf->methodOop = methodOop; + vf->bci = bci; + err = line_number_from_bci(J, vf); + CHECK_FAIL(err); + } + jframe->bci = vf->bci; + jframe->line = vf->line; + jframe->locinf = 1; + + if (debug) { + fprintf(stderr, "\t name_for_imethod: END: bci: %d, line: %d\n\n", + vf->bci, vf->line); + } + return PS_OK; + + fail: + if (debug) + fprintf(stderr, "\t name_for_imethod: FAIL\n"); + return err; +} + +static int +name_for_codecache(jvm_agent_t* J, uint64_t fp, uint64_t pc, char * result, + size_t size, Jframe_t *jframe, int* is_interpreted) +{ + uint64_t start; + uint64_t vtbl; + int32_t err; + *is_interpreted = 0; + + result[0] = '\0'; + + err = find_start(J, pc, &start); + CHECK_FAIL(err); + + err = read_pointer(J, start, &vtbl); + CHECK_FAIL(err); + + if (vtbl == J->nmethod_vtbl) { + uint64_t methodOop; + + err = read_pointer(J, start + OFFSET_nmethod_method, &methodOop); + CHECK_FAIL(err); + + if (debug) { + fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, methodOop: %#8llx \n", + start, pc, methodOop); + } + err = name_for_nmethod(J, start, pc, methodOop, result, size, jframe); + CHECK_FAIL(err); + } else if (vtbl == J->BufferBlob_vtbl) { + const char * name; + + err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name); + + /* + * Temporary usage of string "Interpreter". + * We need some other way to distinguish "StubRoutines" + * and regular interpreted frames. + */ + if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) { + *is_interpreted = 1; + if (is_methodOop(J, J->methodOopPtr)) { + return name_for_imethod(J, J->bcx, J->methodOopPtr, result, size, jframe); + } + } + + if (err == PS_OK) { + strncpy(result, name, size); + free((void*)name); + } else { + strncpy(result, "<unknown BufferBlob>", size); + } + /* return PS_OK; */ + } else { + const char * name; + + err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name); + if (err == PS_OK) { + strncpy(result, name, size); + free((void*)name); + } else { + strncpy(result, "<unknown CodeBlob>", size); + WARN1("unknown CodeBlob: vtbl = 0x%x", vtbl); + } + } + result[size-1] = '\0'; + +#ifdef X86_COMPILER2 + if (vtbl != J->RuntimeStub_vtbl) { + uint64_t trial_pc; + int frame_size; + err = ps_pread(J->P, start + OFFSET_CodeBlob_frame_size, + &frame_size, SZ32); + CHECK_FAIL(err); + + // frame_size is in words, we want bytes. + frame_size *= POINTER_SIZE; /* word => byte conversion */ + + /* + Because c2 doesn't use FP as a framepointer the value of sp/fp we receive + in the initial entry to a set of stack frames containing server frames + will pretty much be nonsense. We can detect that nonsense by looking to + see if the PC we received is correct if we look at the expected storage + location in relation to the FP (ie. POINTER_SIZE(FP) ) + */ + + err = read_pointer(J, fp + POINTER_SIZE , &trial_pc); + if ( (err != PS_OK || trial_pc != pc) && frame_size > 0 ) { + // Either we couldn't even read at the "fp" or the pc didn't match + // both are sure clues that the fp is bogus. We no search the stack + // for a reasonable number of words trying to find the bogus fp + // and the current pc in adjacent words. The we will be able to + // deduce an approximation of the frame pointer and actually get + // the correct stack pointer. Which we can then unwind for the + // next frame. + int i; + uint64_t check; + uint64_t base = J->curr_fr.sp; + uint64_t prev_fp = 0; + for ( i = 0; i < frame_size * 5 ; i++, base += POINTER_SIZE ) { + err = read_pointer(J, base , &check); + CHECK_FAIL(err); + if (check == fp) { + base += POINTER_SIZE; + err = read_pointer(J, base , &check); + CHECK_FAIL(err); + if (check == pc) { + if (debug) { + fprintf(stderr, "name_for_codecache: found matching fp/pc combo at 0x%llx\n", base - POINTER_SIZE); + } + prev_fp = base - 2 * POINTER_SIZE; + break; + } + } + } + if ( prev_fp != 0 ) { + // real_sp is the sp we should have received for this frame + uint64_t real_sp = prev_fp + 2 * POINTER_SIZE; + // +POINTER_SIZE because callee owns the return address so caller's sp is +1 word + jframe->new_sp = real_sp + frame_size + POINTER_SIZE; + err = read_pointer(J, jframe->new_sp - POINTER_SIZE , &jframe->new_pc); + CHECK_FAIL(err); + err = read_pointer(J, jframe->new_sp - 2*POINTER_SIZE, &jframe->new_fp); + CHECK_FAIL(err); + return PS_OK; + } + } + + /* A prototype to workaround FP absence */ + /* + * frame_size can be 0 for StubRoutines (1) frame. + * In this case it should work with fp as usual. + */ + if (frame_size > 0) { + jframe->new_fp = J->prev_fr.fp + frame_size; + jframe->new_sp = jframe->new_fp + 2 * POINTER_SIZE; + } else { + memset(&J->curr_fr, 0, sizeof(Frame_t)); + err = read_pointer(J, fp, &jframe->new_fp); + CHECK_FAIL(err); + + err = read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc); + CHECK_FAIL(err); + } + if (debug) { + fprintf(stderr, "name_for_codecache: %s, frame_size=%#lx\n", + result, frame_size); + fprintf(stderr, "name_for_codecache: prev_fr.fp=%#lx, fp=%#lx\n", + J->prev_fr.fp, jframe->new_fp); + } + } +#endif /* X86_COMPILER2 */ + + return PS_OK; + + fail: + return err; +} + +int Jget_vframe(jvm_agent_t* J, int vframe_no, + char *name, size_t size, Jframe_t *jframe) +{ + Nmethod_t *N = J->N; + Vframe_t *vf; + int32_t err; + + if (vframe_no >= N->vf_cnt) { + (void) sprintf(name, "Wrong inlinedMethod%1d()", vframe_no); + return -1; + } + vf = N->vframes + vframe_no; + name[0] = COMP_METHOD_SIGN; + err = name_for_methodOop(J, vf->methodOop, name + 1, size); + CHECK_FAIL(err); + + jframe->bci = vf->bci; + jframe->line = vf->line; + if (debug) { + fprintf(stderr, "\t Jget_vframe: method name: %s, line: %ld\n", + name, vf->line); + } + return PS_OK; + + fail: + if (debug) { + fprintf(stderr, "\t Jget_vframe: FAIL\n"); + } + return err; +} + +#define MAX_SYM_SIZE 256 + +int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name, + size_t size, Jframe_t *jframe) { + uintptr_t fp; + uintptr_t pc; + /* arguments given to read_pointer need to be worst case sized */ + uint64_t methodOopPtr = 0; + uint64_t sender_sp; + uint64_t bcx = 0; + int is_interpreted = 0; + int result = PS_OK; + int err = PS_OK; + + if (J == NULL) { + return -1; + } + + jframe->vf_cnt = 1; + jframe->new_fp = 0; + jframe->new_pc = 0; + jframe->line = 0; + jframe->bci = 0; + jframe->locinf = 0; + + read_volatiles(J); + pc = (uintptr_t) regs[R_PC]; + J->curr_fr.pc = pc; + J->curr_fr.fp = regs[R_FP]; + J->curr_fr.sp = regs[R_SP]; + + if (debug) + fprintf(stderr, "Jlookup_by_regs: BEGINs: fp=%#lx, pc=%#lx\n", regs[R_FP], pc); + +#if defined(sparc) || defined(__sparc) + /* The following workaround is for SPARC. CALL instruction occupates 8 bytes. + * In the pcDesc structure return pc offset is recorded for CALL instructions. + * regs[R_PC] contains a CALL instruction pc offset. + */ + pc += 8; + bcx = (uintptr_t) regs[R_L1]; + methodOopPtr = (uintptr_t) regs[R_L2]; + sender_sp = regs[R_I5]; + if (debug > 2) { + fprintf(stderr, "\nregs[R_I1]=%lx, regs[R_I2]=%lx, regs[R_I5]=%lx, regs[R_L1]=%lx, regs[R_L2]=%lx\n", + regs[R_I1], regs[R_I2], regs[R_I5], regs[R_L1], regs[R_L2]); + } +#elif defined(i386) || defined(__i386) || defined(__amd64) + + fp = (uintptr_t) regs[R_FP]; + if (J->prev_fr.fp == 0) { +#ifdef X86_COMPILER2 + /* A workaround for top java frames */ + J->prev_fr.fp = (uintptr_t)(regs[R_SP] - 2 * POINTER_SIZE); +#else + J->prev_fr.fp = (uintptr_t)(regs[R_SP] - POINTER_SIZE); +#endif /* COMPILER2 */ + } + if (debug > 2) { + printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp); + } + + if (read_pointer(J, fp + OFFSET_interpreter_frame_method, &methodOopPtr) != PS_OK) { + methodOopPtr = 0; + } + if (read_pointer(J, fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) { + sender_sp = 0; + } + if (read_pointer(J, fp + OFFSET_interpreter_frame_bcx_offset, &bcx) != PS_OK) { + bcx = 0; + } +#endif /* i386 */ + + J->methodOopPtr = methodOopPtr; + J->bcx = bcx; + + /* On x86 with C2 JVM: native frame may have wrong regs[R_FP] + * For example: JVM_SuspendThread frame poins to the top interpreted frame. + * If we call is_methodOop(J, methodOopPtr) before codecache_contains(J, pc) + * then we go over and omit both: nmethod and I2CAdapter frames. + * Note, that regs[R_PC] is always correct if frame defined correctly. + * So it is better to call codecache_contains(J, pc) from the beginning. + */ +#ifndef X86_COMPILER2 + if (is_methodOop(J, J->methodOopPtr)) { + result = name_for_imethod(J, bcx, J->methodOopPtr, name, size, jframe); + /* If the methodOopPtr is a method then this is highly likely to be + an interpreter frame */ + if (result >= 0) { + is_interpreted = 1; + } + } else +#endif /* ! X86_COMPILER2 */ + + if (codecache_contains(J, pc)) { + result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted); + } +#ifdef X86_COMPILER2 + else if (is_methodOop(J, J->methodOopPtr)) { + result = name_for_imethod(J, bcx, J->methodOopPtr, name, size, jframe); + /* If the methodOopPtr is a method then this is highly likely to be + an interpreter frame */ + if (result >= 0) { + is_interpreted = 1; + } + } +#endif /* X86_COMPILER2 */ + else { + if (debug) { + fprintf(stderr, "Jlookup_by_regs: END with -1\n\n"); + } + result = -1; + } + if (!is_interpreted) { + sender_sp = 0; + } + J->curr_fr.sender_sp = sender_sp; + +#ifdef X86_COMPILER2 + if (!J->curr_fr.fp) { + J->curr_fr.fp = (jframe->new_fp) ? jframe->new_fp : (uintptr_t)regs[R_FP]; + } + if (!jframe->new_pc && jframe->new_fp) { + // This seems dubious + read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc); + CHECK_FAIL(err); + if (debug > 2) { + printf("Jlookup_by_regs: (update pc) jframe->new_fp: %#llx, jframe->new_pc: %#llx\n", + jframe->new_fp, jframe->new_pc); + } + } + +#endif /* X86_COMPILER2 */ + J->prev_fr = J->curr_fr; + + if (debug) + fprintf(stderr, "Jlookup_by_regs: END\n\n"); + + return result; + + fail: + return err; +} + +void update_gregs(prgregset_t gregs, Jframe_t jframe) { +#ifdef X86_COMPILER2 + if (debug > 0) { + fprintf(stderr, "update_gregs: before update sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]); + } + /* + * A workaround for java C2 frames with unconventional FP. + * may have to modify regset with new values for FP/PC/SP when needed. + */ + if (jframe.new_sp) { + *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) jframe.new_sp; + } else { + // *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) gregs[R_FP] + 2 * POINTER_SIZE; + } + + if (jframe.new_fp) { + *((uintptr_t *) &gregs[R_FP]) = (uintptr_t) jframe.new_fp; + } + if (jframe.new_pc) { + *((uintptr_t *) &gregs[R_PC]) = (uintptr_t) jframe.new_pc; + } + if (debug > 0) { + fprintf(stderr, "update_gregs: after update sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]); + } +#endif /* X86_COMPILER2 */ +} + +/* + * Iterates over java frames at current location given by 'gregs'. + * + * Returns -1 if no java frames are present or if an error is encountered. + * Returns the result of calling 'func' if the return value is non-zero. + * Returns 0 otherwise. + */ +int Jframe_iter(jvm_agent_t *J, prgregset_t gregs, java_stack_f *func, void* cld) { + char buf[MAX_SYM_SIZE + 1]; + Jframe_t jframe; + int i = 0, res; +#ifdef X86_COMPILER2 + if (debug > 0) { + fprintf(stderr, "Jframe_iter: Entry sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]); + } +#endif /* X86_COMPILER2 */ + + memset(&jframe, 0, sizeof(Jframe_t)); + memset(buf, 0, sizeof(buf)); + res = Jlookup_by_regs(J, gregs, buf, sizeof(buf), &jframe); + if (res != PS_OK) + return (-1); + + + res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1, + jframe.line, NULL); + if (res != 0) { + update_gregs(gregs, jframe); + return (res); + } + for (i = 1; i < jframe.vf_cnt; i++) { + Jget_vframe(J, i, buf, sizeof(buf), &jframe); + res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1, + jframe.line, NULL); + if (res != 0) { + update_gregs(gregs, jframe); + return (res); + } + } + update_gregs(gregs, jframe); + return (0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/dtrace/libjvm_db.h Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_SOLARIS_DTRACE_LIBJVM_DB_H +#define OS_SOLARIS_DTRACE_LIBJVM_DB_H + +// not available on macosx #include <proc_service.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct jvm_agent jvm_agent_t; + +#define JVM_DB_VERSION 1 + +jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers); + +/* + * Called from Jframe_iter() for each java frame. If it returns 0, then + * Jframe_iter() proceeds to the next frame. Otherwise, the return value is + * immediately returned to the caller of Jframe_iter(). + * + * Parameters: + * 'cld' is client supplied data (to maintain iterator state, if any). + * 'name' is java method name. + * 'bci' is byte code index. it will be -1 if not available. + * 'line' is java source line number. it will be 0 if not available. + * 'handle' is an abstract client handle, reserved for future expansions + */ + +typedef int java_stack_f(void *cld, const prgregset_t regs, const char* name, int bci, int line, void *handle); + +/* + * Iterates over the java frames at the current location. Returns -1 if no java + * frames were found, or if there was some unrecoverable error. Otherwise, + * returns the last value returned from 'func'. + */ +int Jframe_iter(jvm_agent_t *agent, prgregset_t gregs, java_stack_f *func, void* cld); + +void Jagent_destroy(jvm_agent_t *J); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif // OS_SOLARIS_DTRACE_LIBJVM_DB_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/attachListener_bsd.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,520 @@ +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "runtime/interfaceSupport.hpp" +#include "runtime/os.hpp" +#include "services/attachListener.hpp" +#include "services/dtraceAttacher.hpp" + +#include <unistd.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/stat.h> + +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *)0)->sun_path) +#endif + +// The attach mechanism on Bsd uses a UNIX domain socket. An attach listener +// thread is created at startup or is created on-demand via a signal from +// the client tool. The attach listener creates a socket and binds it to a file +// in the filesystem. The attach listener then acts as a simple (single- +// threaded) server - it waits for a client to connect, reads the request, +// executes it, and returns the response to the client via the socket +// connection. +// +// As the socket is a UNIX domain socket it means that only clients on the +// local machine can connect. In addition there are two other aspects to +// the security: +// 1. The well known file that the socket is bound to has permission 400 +// 2. When a client connect, the SO_PEERCRED socket option is used to +// obtain the credentials of client. We check that the effective uid +// of the client matches this process. + +// forward reference +class BsdAttachOperation; + +class BsdAttachListener: AllStatic { + private: + // the path to which we bind the UNIX domain socket + static char _path[UNIX_PATH_MAX]; + static bool _has_path; + + // the file descriptor for the listening socket + static int _listener; + + static void set_path(char* path) { + if (path == NULL) { + _has_path = false; + } else { + strncpy(_path, path, UNIX_PATH_MAX); + _path[UNIX_PATH_MAX-1] = '\0'; + _has_path = true; + } + } + + static void set_listener(int s) { _listener = s; } + + // reads a request from the given connected socket + static BsdAttachOperation* read_request(int s); + + public: + enum { + ATTACH_PROTOCOL_VER = 1 // protocol version + }; + enum { + ATTACH_ERROR_BADVERSION = 101 // error codes + }; + + // initialize the listener, returns 0 if okay + static int init(); + + static char* path() { return _path; } + static bool has_path() { return _has_path; } + static int listener() { return _listener; } + + // write the given buffer to a socket + static int write_fully(int s, char* buf, int len); + + static BsdAttachOperation* dequeue(); +}; + +class BsdAttachOperation: public AttachOperation { + private: + // the connection to the client + int _socket; + + public: + void complete(jint res, bufferedStream* st); + + void set_socket(int s) { _socket = s; } + int socket() const { return _socket; } + + BsdAttachOperation(char* name) : AttachOperation(name) { + set_socket(-1); + } +}; + +// statics +char BsdAttachListener::_path[UNIX_PATH_MAX]; +bool BsdAttachListener::_has_path; +int BsdAttachListener::_listener = -1; + +// Supporting class to help split a buffer into individual components +class ArgumentIterator : public StackObj { + private: + char* _pos; + char* _end; + public: + ArgumentIterator(char* arg_buffer, size_t arg_size) { + _pos = arg_buffer; + _end = _pos + arg_size - 1; + } + char* next() { + if (*_pos == '\0') { + return NULL; + } + char* res = _pos; + char* next_pos = strchr(_pos, '\0'); + if (next_pos < _end) { + next_pos++; + } + _pos = next_pos; + return res; + } +}; + + +// atexit hook to stop listener and unlink the file that it is +// bound too. +extern "C" { + static void listener_cleanup() { + static int cleanup_done; + if (!cleanup_done) { + cleanup_done = 1; + int s = BsdAttachListener::listener(); + if (s != -1) { + ::close(s); + } + if (BsdAttachListener::has_path()) { + ::unlink(BsdAttachListener::path()); + } + } + } +} + +// Initialization - create a listener socket and bind it to a file + +int BsdAttachListener::init() { + char path[UNIX_PATH_MAX]; // socket file + char initial_path[UNIX_PATH_MAX]; // socket file during setup + int listener; // listener socket (file descriptor) + + // register function to cleanup + ::atexit(listener_cleanup); + + int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d", + os::get_temp_directory(), os::current_process_id()); + if (n < (int)UNIX_PATH_MAX) { + n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path); + } + if (n >= (int)UNIX_PATH_MAX) { + return -1; + } + + // create the listener socket + listener = ::socket(PF_UNIX, SOCK_STREAM, 0); + if (listener == -1) { + return -1; + } + + // bind socket + struct sockaddr_un addr; + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, initial_path); + ::unlink(initial_path); + int res = ::bind(listener, (struct sockaddr*)&addr, sizeof(addr)); + if (res == -1) { + RESTARTABLE(::close(listener), res); + return -1; + } + + // put in listen mode, set permissions, and rename into place + res = ::listen(listener, 5); + if (res == 0) { + RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res); + if (res == 0) { + res = ::rename(initial_path, path); + } + } + if (res == -1) { + RESTARTABLE(::close(listener), res); + ::unlink(initial_path); + return -1; + } + set_path(path); + set_listener(listener); + + return 0; +} + +// Given a socket that is connected to a peer we read the request and +// create an AttachOperation. As the socket is blocking there is potential +// for a denial-of-service if the peer does not response. However this happens +// after the peer credentials have been checked and in the worst case it just +// means that the attach listener thread is blocked. +// +BsdAttachOperation* BsdAttachListener::read_request(int s) { + char ver_str[8]; + sprintf(ver_str, "%d", ATTACH_PROTOCOL_VER); + + // The request is a sequence of strings so we first figure out the + // expected count and the maximum possible length of the request. + // The request is: + // <ver>0<cmd>0<arg>0<arg>0<arg>0 + // where <ver> is the protocol version (1), <cmd> is the command + // name ("load", "datadump", ...), and <arg> is an argument + int expected_str_count = 2 + AttachOperation::arg_count_max; + const int max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) + + AttachOperation::arg_count_max*(AttachOperation::arg_length_max + 1); + + char buf[max_len]; + int str_count = 0; + + // Read until all (expected) strings have been read, the buffer is + // full, or EOF. + + int off = 0; + int left = max_len; + + do { + int n; + RESTARTABLE(read(s, buf+off, left), n); + if (n == -1) { + return NULL; // reset by peer or other error + } + if (n == 0) { + break; + } + for (int i=0; i<n; i++) { + if (buf[off+i] == 0) { + // EOS found + str_count++; + + // The first string is <ver> so check it now to + // check for protocol mis-match + if (str_count == 1) { + if ((strlen(buf) != strlen(ver_str)) || + (atoi(buf) != ATTACH_PROTOCOL_VER)) { + char msg[32]; + sprintf(msg, "%d\n", ATTACH_ERROR_BADVERSION); + write_fully(s, msg, strlen(msg)); + return NULL; + } + } + } + } + off += n; + left -= n; + } while (left > 0 && str_count < expected_str_count); + + if (str_count != expected_str_count) { + return NULL; // incomplete request + } + + // parse request + + ArgumentIterator args(buf, (max_len)-left); + + // version already checked + char* v = args.next(); + + char* name = args.next(); + if (name == NULL || strlen(name) > AttachOperation::name_length_max) { + return NULL; + } + + BsdAttachOperation* op = new BsdAttachOperation(name); + + for (int i=0; i<AttachOperation::arg_count_max; i++) { + char* arg = args.next(); + if (arg == NULL) { + op->set_arg(i, NULL); + } else { + if (strlen(arg) > AttachOperation::arg_length_max) { + delete op; + return NULL; + } + op->set_arg(i, arg); + } + } + + op->set_socket(s); + return op; +} + + +// Dequeue an operation +// +// In the Bsd implementation there is only a single operation and clients +// cannot queue commands (except at the socket level). +// +BsdAttachOperation* BsdAttachListener::dequeue() { + for (;;) { + int s; + + // wait for client to connect + struct sockaddr addr; + socklen_t len = sizeof(addr); + RESTARTABLE(::accept(listener(), &addr, &len), s); + if (s == -1) { + return NULL; // log a warning? + } + + // get the credentials of the peer and check the effective uid/guid + // - check with jeff on this. +#ifdef _ALLBSD_SOURCE + uid_t puid; + gid_t pgid; + if (::getpeereid(s, &puid, &pgid) != 0) { + int res; + RESTARTABLE(::close(s), res); + continue; + } +#else + struct ucred cred_info; + socklen_t optlen = sizeof(cred_info); + if (::getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void*)&cred_info, &optlen) == -1) { + int res; + RESTARTABLE(::close(s), res); + continue; + } + uid_t puid = cred_info.uid; + gid_t pgid = cred_info.gid; +#endif + uid_t euid = geteuid(); + gid_t egid = getegid(); + + if (puid != euid || pgid != egid) { + int res; + RESTARTABLE(::close(s), res); + continue; + } + + // peer credential look okay so we read the request + BsdAttachOperation* op = read_request(s); + if (op == NULL) { + int res; + RESTARTABLE(::close(s), res); + continue; + } else { + return op; + } + } +} + +// write the given buffer to the socket +int BsdAttachListener::write_fully(int s, char* buf, int len) { + do { + int n = ::write(s, buf, len); + if (n == -1) { + if (errno != EINTR) return -1; + } else { + buf += n; + len -= n; + } + } + while (len > 0); + return 0; +} + +// Complete an operation by sending the operation result and any result +// output to the client. At this time the socket is in blocking mode so +// potentially we can block if there is a lot of data and the client is +// non-responsive. For most operations this is a non-issue because the +// default send buffer is sufficient to buffer everything. In the future +// if there are operations that involves a very big reply then it the +// socket could be made non-blocking and a timeout could be used. + +void BsdAttachOperation::complete(jint result, bufferedStream* st) { + JavaThread* thread = JavaThread::current(); + ThreadBlockInVM tbivm(thread); + + thread->set_suspend_equivalent(); + // cleared by handle_special_suspend_equivalent_condition() or + // java_suspend_self() via check_and_wait_while_suspended() + + // write operation result + char msg[32]; + sprintf(msg, "%d\n", result); + int rc = BsdAttachListener::write_fully(this->socket(), msg, strlen(msg)); + + // write any result data + if (rc == 0) { + BsdAttachListener::write_fully(this->socket(), (char*) st->base(), st->size()); + ::shutdown(this->socket(), 2); + } + + // done + RESTARTABLE(::close(this->socket()), rc); + + // were we externally suspended while we were waiting? + thread->check_and_wait_while_suspended(); + + delete this; +} + + +// AttachListener functions + +AttachOperation* AttachListener::dequeue() { + JavaThread* thread = JavaThread::current(); + ThreadBlockInVM tbivm(thread); + + thread->set_suspend_equivalent(); + // cleared by handle_special_suspend_equivalent_condition() or + // java_suspend_self() via check_and_wait_while_suspended() + + AttachOperation* op = BsdAttachListener::dequeue(); + + // were we externally suspended while we were waiting? + thread->check_and_wait_while_suspended(); + + return op; +} + +int AttachListener::pd_init() { + JavaThread* thread = JavaThread::current(); + ThreadBlockInVM tbivm(thread); + + thread->set_suspend_equivalent(); + // cleared by handle_special_suspend_equivalent_condition() or + // java_suspend_self() via check_and_wait_while_suspended() + + int ret_code = BsdAttachListener::init(); + + // were we externally suspended while we were waiting? + thread->check_and_wait_while_suspended(); + + return ret_code; +} + +// Attach Listener is started lazily except in the case when +// +ReduseSignalUsage is used +bool AttachListener::init_at_startup() { + if (ReduceSignalUsage) { + return true; + } else { + return false; + } +} + +// If the file .attach_pid<pid> exists in the working directory +// or /tmp then this is the trigger to start the attach mechanism +bool AttachListener::is_init_trigger() { + if (init_at_startup() || is_initialized()) { + return false; // initialized at startup or already initialized + } + char path[PATH_MAX + 1]; + int ret; + struct stat st; + + snprintf(path, PATH_MAX + 1, "%s/.attach_pid%d", + os::get_temp_directory(), os::current_process_id()); + RESTARTABLE(::stat(path, &st), ret); + if (ret == 0) { + // simple check to avoid starting the attach mechanism when + // a bogus user creates the file + if (st.st_uid == geteuid()) { + init(); + return true; + } + } + return false; +} + +// if VM aborts then remove listener +void AttachListener::abort() { + listener_cleanup(); +} + +void AttachListener::pd_data_dump() { + os::signal_notify(SIGQUIT); +} + +AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* n) { + return NULL; +} + +jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) { + out->print_cr("flag '%s' cannot be changed", op->arg(0)); + return JNI_ERR; +} + +void AttachListener::pd_detachall() { + // do nothing for now +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/c1_globals_bsd.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_BSD_VM_C1_GLOBALS_BSD_HPP +#define OS_BSD_VM_C1_GLOBALS_BSD_HPP + +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" + +// +// Sets the default values for operating system dependent flags used by the +// client compiler. (see c1_globals.hpp) +// + +#endif // OS_BSD_VM_C1_GLOBALS_BSD_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/c2_globals_bsd.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_BSD_VM_C2_GLOBALS_BSD_HPP +#define OS_BSD_VM_C2_GLOBALS_BSD_HPP + +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" + +// +// Sets the default values for operating system dependent flags used by the +// server compiler. (see c2_globals.hpp) +// + +#endif // OS_BSD_VM_C2_GLOBALS_BSD_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/chaitin_bsd.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "opto/chaitin.hpp" +#include "opto/machnode.hpp" + +void PhaseRegAlloc::pd_preallocate_hook() { + // no action +} + +#ifdef ASSERT +void PhaseRegAlloc::pd_postallocate_verify_hook() { + // no action +} +#endif + + +// Reconciliation History +// chaitin_solaris.cpp 1.7 99/07/12 23:54:22 +// End
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/decoder_bsd.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "prims/jvm.h" +#include "utilities/decoder.hpp" + +#include <cxxabi.h> + +#ifdef __APPLE__ + +void Decoder::initialize() { + _initialized = true; +} + +void Decoder::uninitialize() { + _initialized = false; +} + +bool Decoder::can_decode_C_frame_in_vm() { + return false; +} + +Decoder::decoder_status Decoder::decode(address addr, const char* filepath, char *buf, int buflen, int *offset) { + return symbol_not_found; +} + + +#endif + +bool Decoder::demangle(const char* symbol, char *buf, int buflen) { + int status; + char* result; + size_t size = (size_t)buflen; + + // Don't pass buf to __cxa_demangle. In case of the 'buf' is too small, + // __cxa_demangle will call system "realloc" for additional memory, which + // may use different malloc/realloc mechanism that allocates 'buf'. + if ((result = abi::__cxa_demangle(symbol, NULL, NULL, &status)) != NULL) { + jio_snprintf(buf, buflen, "%s", result); + // call c library's free + ::free(result); + return true; + } + return false; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/dtraceJSDT_bsd.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/javaClasses.hpp" +#include "code/codeBlob.hpp" +#include "memory/allocation.hpp" +#include "prims/jvm.h" +#include "runtime/dtraceJSDT.hpp" +#include "runtime/jniHandles.hpp" +#include "runtime/os.hpp" +#include "runtime/signature.hpp" +#include "utilities/globalDefinitions.hpp" + +/* + * JSDT java dtrace probes have never been implemented in macosx. It is unknown if the solaris implementation + * is close or if significant implementation work is necessary. The future of the solaris implementation also + * appears to be unclear since compiling code with JSDT probes produces the following warning: + * "warning: ProviderFactory is internal proprietary API and may be removed in a future release" + */ + +int DTraceJSDT::pd_activate( + void* baseAddress, jstring module, + jint providers_count, JVM_DTraceProvider* providers) { + return -1; +} + +void DTraceJSDT::pd_dispose(int handle) { +} + +jboolean DTraceJSDT::pd_is_supported() { + return false; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/globals_bsd.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2005, 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. + * + */ + +#ifndef OS_BSD_VM_GLOBALS_BSD_HPP +#define OS_BSD_VM_GLOBALS_BSD_HPP + +// +// Defines Bsd specific flags. They are not available on other platforms. +// +#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \ + product(bool, UseOprofile, false, \ + "enable support for Oprofile profiler") \ + \ + product(bool, UseBsdPosixThreadCPUClocks, true, \ + "enable fast Bsd Posix clocks where available") \ +/* NB: The default value of UseBsdPosixThreadCPUClocks may be \ + overridden in Arguments::parse_each_vm_init_arg. */ \ + \ + product(bool, UseHugeTLBFS, false, \ + "Use MAP_HUGETLB for large pages") \ + \ + product(bool, UseSHM, false, \ + "Use SYSV shared memory for large pages") + +// +// Defines Bsd-specific default values. The flags are available on all +// platforms, but they may have different default values on other platforms. +// +define_pd_global(bool, UseLargePages, false); +define_pd_global(bool, UseLargePagesIndividualAllocation, false); +define_pd_global(bool, UseOSErrorReporting, false); +define_pd_global(bool, UseThreadPriorities, true) ; + +#endif // OS_BSD_VM_GLOBALS_BSD_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/interfaceSupport_bsd.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_BSD_VM_INTERFACESUPPORT_BSD_HPP +#define OS_BSD_VM_INTERFACESUPPORT_BSD_HPP + +// Contains inlined functions for class InterfaceSupport + +static inline void serialize_memory(JavaThread *thread) { + os::write_memory_serialize_page(thread); +} + +#endif // OS_BSD_VM_INTERFACESUPPORT_BSD_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/jsig.c Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* CopyrightVersion 1.2 */ + +/* This is a special library that should be loaded before libc & + * libthread to interpose the signal handler installation functions: + * sigaction(), signal(), sigset(). + * Used for signal-chaining. See RFE 4381843. + */ + +#include <signal.h> +#include <dlfcn.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> + +#define MAXSIGNUM 32 +#define MASK(sig) ((unsigned int)1 << sig) + +static struct sigaction sact[MAXSIGNUM]; /* saved signal handlers */ +static unsigned int jvmsigs = 0; /* signals used by jvm */ + +/* used to synchronize the installation of signal handlers */ +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +static pthread_t tid = 0; + +typedef void (*sa_handler_t)(int); +typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); +typedef sa_handler_t (*signal_t)(int, sa_handler_t); +typedef int (*sigaction_t)(int, const struct sigaction *, struct sigaction *); + +static signal_t os_signal = 0; /* os's version of signal()/sigset() */ +static sigaction_t os_sigaction = 0; /* os's version of sigaction() */ + +static bool jvm_signal_installing = false; +static bool jvm_signal_installed = false; + +static void signal_lock() { + pthread_mutex_lock(&mutex); + /* When the jvm is installing its set of signal handlers, threads + * other than the jvm thread should wait */ + if (jvm_signal_installing) { + if (tid != pthread_self()) { + pthread_cond_wait(&cond, &mutex); + } + } +} + +static void signal_unlock() { + pthread_mutex_unlock(&mutex); +} + +static sa_handler_t call_os_signal(int sig, sa_handler_t disp, + bool is_sigset) { + if (os_signal == NULL) { + if (!is_sigset) { + os_signal = (signal_t)dlsym(RTLD_NEXT, "signal"); + } else { + os_signal = (signal_t)dlsym(RTLD_NEXT, "sigset"); + } + if (os_signal == NULL) { + printf("%s\n", dlerror()); + exit(0); + } + } + return (*os_signal)(sig, disp); +} + +static void save_signal_handler(int sig, sa_handler_t disp) { + sigset_t set; + sact[sig].sa_handler = disp; + sigemptyset(&set); + sact[sig].sa_mask = set; + sact[sig].sa_flags = 0; +} + +static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) { + sa_handler_t oldhandler; + bool sigused; + + signal_lock(); + + sigused = (MASK(sig) & jvmsigs) != 0; + if (jvm_signal_installed && sigused) { + /* jvm has installed its signal handler for this signal. */ + /* Save the handler. Don't really install it. */ + oldhandler = sact[sig].sa_handler; + save_signal_handler(sig, disp); + + signal_unlock(); + return oldhandler; + } else if (jvm_signal_installing) { + /* jvm is installing its signal handlers. Install the new + * handlers and save the old ones. jvm uses sigaction(). + * Leave the piece here just in case. */ + oldhandler = call_os_signal(sig, disp, is_sigset); + save_signal_handler(sig, oldhandler); + + /* Record the signals used by jvm */ + jvmsigs |= MASK(sig); + + signal_unlock(); + return oldhandler; + } else { + /* jvm has no relation with this signal (yet). Install the + * the handler. */ + oldhandler = call_os_signal(sig, disp, is_sigset); + + signal_unlock(); + return oldhandler; + } +} + +sa_handler_t signal(int sig, sa_handler_t disp) { + return set_signal(sig, disp, false); +} + +sa_handler_t sigset(int sig, sa_handler_t disp) { + printf("sigset() is not supported by BSD"); + exit(0); + } + +static int call_os_sigaction(int sig, const struct sigaction *act, + struct sigaction *oact) { + if (os_sigaction == NULL) { + os_sigaction = (sigaction_t)dlsym(RTLD_NEXT, "sigaction"); + if (os_sigaction == NULL) { + printf("%s\n", dlerror()); + exit(0); + } + } + return (*os_sigaction)(sig, act, oact); +} + +int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { + int res; + bool sigused; + struct sigaction oldAct; + + signal_lock(); + + sigused = (MASK(sig) & jvmsigs) != 0; + if (jvm_signal_installed && sigused) { + /* jvm has installed its signal handler for this signal. */ + /* Save the handler. Don't really install it. */ + if (oact != NULL) { + *oact = sact[sig]; + } + if (act != NULL) { + sact[sig] = *act; + } + + signal_unlock(); + return 0; + } else if (jvm_signal_installing) { + /* jvm is installing its signal handlers. Install the new + * handlers and save the old ones. */ + res = call_os_sigaction(sig, act, &oldAct); + sact[sig] = oldAct; + if (oact != NULL) { + *oact = oldAct; + } + + /* Record the signals used by jvm */ + jvmsigs |= MASK(sig); + + signal_unlock(); + return res; + } else { + /* jvm has no relation with this signal (yet). Install the + * the handler. */ + res = call_os_sigaction(sig, act, oact); + + signal_unlock(); + return res; + } +} + +/* The three functions for the jvm to call into */ +void JVM_begin_signal_setting() { + signal_lock(); + jvm_signal_installing = true; + tid = pthread_self(); + signal_unlock(); +} + +void JVM_end_signal_setting() { + signal_lock(); + jvm_signal_installed = true; + jvm_signal_installing = false; + pthread_cond_broadcast(&cond); + signal_unlock(); +} + +struct sigaction *JVM_get_signal_action(int sig) { + /* Does race condition make sense here? */ + if ((MASK(sig) & jvmsigs) != 0) { + return &sact[sig]; + } + return NULL; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/jvm_bsd.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,192 @@ +/* + * Copyright (c) 1999, 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. + * + */ + +#include "precompiled.hpp" +#include "prims/jvm.h" +#include "runtime/interfaceSupport.hpp" +#include "runtime/osThread.hpp" + +#include <signal.h> + + +// sun.misc.Signal /////////////////////////////////////////////////////////// +// Signal code is mostly copied from classic vm, signals_md.c 1.4 98/08/23 +/* + * This function is included primarily as a debugging aid. If Java is + * running in a console window, then pressing <CTRL-\\> will cause + * the current state of all active threads and monitors to be written + * to the console window. + */ + +JVM_ENTRY_NO_ENV(void*, JVM_RegisterSignal(jint sig, void* handler)) + // Copied from classic vm + // signals_md.c 1.4 98/08/23 + void* newHandler = handler == (void *)2 + ? os::user_handler() + : handler; + switch (sig) { + /* The following are already used by the VM. */ + case INTERRUPT_SIGNAL: + case SIGFPE: + case SIGILL: + case SIGSEGV: + + /* The following signal is used by the VM to dump thread stacks unless + ReduceSignalUsage is set, in which case the user is allowed to set + his own _native_ handler for this signal; thus, in either case, + we do not allow JVM_RegisterSignal to change the handler. */ + case BREAK_SIGNAL: + return (void *)-1; + + /* The following signals are used for Shutdown Hooks support. However, if + ReduceSignalUsage (-Xrs) is set, Shutdown Hooks must be invoked via + System.exit(), Java is not allowed to use these signals, and the the + user is allowed to set his own _native_ handler for these signals and + invoke System.exit() as needed. Terminator.setup() is avoiding + registration of these signals when -Xrs is present. + - If the HUP signal is ignored (from the nohup) command, then Java + is not allowed to use this signal. + */ + + case SHUTDOWN1_SIGNAL: + case SHUTDOWN2_SIGNAL: + case SHUTDOWN3_SIGNAL: + if (ReduceSignalUsage) return (void*)-1; + if (os::Bsd::is_sig_ignored(sig)) return (void*)1; + } + + void* oldHandler = os::signal(sig, newHandler); + if (oldHandler == os::user_handler()) { + return (void *)2; + } else { + return oldHandler; + } +JVM_END + + +JVM_ENTRY_NO_ENV(jboolean, JVM_RaiseSignal(jint sig)) + if (ReduceSignalUsage) { + // do not allow SHUTDOWN1_SIGNAL,SHUTDOWN2_SIGNAL,SHUTDOWN3_SIGNAL, + // BREAK_SIGNAL to be raised when ReduceSignalUsage is set, since + // no handler for them is actually registered in JVM or via + // JVM_RegisterSignal. + if (sig == SHUTDOWN1_SIGNAL || sig == SHUTDOWN2_SIGNAL || + sig == SHUTDOWN3_SIGNAL || sig == BREAK_SIGNAL) { + return JNI_FALSE; + } + } + else if ((sig == SHUTDOWN1_SIGNAL || sig == SHUTDOWN2_SIGNAL || + sig == SHUTDOWN3_SIGNAL) && os::Bsd::is_sig_ignored(sig)) { + // do not allow SHUTDOWN1_SIGNAL to be raised when SHUTDOWN1_SIGNAL + // is ignored, since no handler for them is actually registered in JVM + // or via JVM_RegisterSignal. + // This also applies for SHUTDOWN2_SIGNAL and SHUTDOWN3_SIGNAL + return JNI_FALSE; + } + + os::signal_raise(sig); + return JNI_TRUE; +JVM_END + +/* + All the defined signal names for Bsd. + + NOTE that not all of these names are accepted by our Java implementation + + Via an existing claim by the VM, sigaction restrictions, or + the "rules of Unix" some of these names will be rejected at runtime. + For example the VM sets up to handle USR1, sigaction returns EINVAL for + STOP, and Bsd simply doesn't allow catching of KILL. + + Here are the names currently accepted by a user of sun.misc.Signal with + 1.4.1 (ignoring potential interaction with use of chaining, etc): + + HUP, INT, TRAP, ABRT, IOT, BUS, USR2, PIPE, ALRM, TERM, STKFLT, + CLD, CHLD, CONT, TSTP, TTIN, TTOU, URG, XCPU, XFSZ, VTALRM, PROF, + WINCH, POLL, IO, PWR, SYS + +*/ + +struct siglabel { + const char *name; + int number; +}; + +struct siglabel siglabels[] = { + /* derived from /usr/include/bits/signum.h on RH7.2 */ + "HUP", SIGHUP, /* Hangup (POSIX). */ + "INT", SIGINT, /* Interrupt (ANSI). */ + "QUIT", SIGQUIT, /* Quit (POSIX). */ + "ILL", SIGILL, /* Illegal instruction (ANSI). */ + "TRAP", SIGTRAP, /* Trace trap (POSIX). */ + "ABRT", SIGABRT, /* Abort (ANSI). */ + "EMT", SIGEMT, /* EMT trap */ + "FPE", SIGFPE, /* Floating-point exception (ANSI). */ + "KILL", SIGKILL, /* Kill, unblockable (POSIX). */ + "BUS", SIGBUS, /* BUS error (4.2 BSD). */ + "SEGV", SIGSEGV, /* Segmentation violation (ANSI). */ + "SYS", SIGSYS, /* Bad system call. Only on some Bsden! */ + "PIPE", SIGPIPE, /* Broken pipe (POSIX). */ + "ALRM", SIGALRM, /* Alarm clock (POSIX). */ + "TERM", SIGTERM, /* Termination (ANSI). */ + "URG", SIGURG, /* Urgent condition on socket (4.2 BSD). */ + "STOP", SIGSTOP, /* Stop, unblockable (POSIX). */ + "TSTP", SIGTSTP, /* Keyboard stop (POSIX). */ + "CONT", SIGCONT, /* Continue (POSIX). */ + "CHLD", SIGCHLD, /* Child status has changed (POSIX). */ + "TTIN", SIGTTIN, /* Background read from tty (POSIX). */ + "TTOU", SIGTTOU, /* Background write to tty (POSIX). */ + "IO", SIGIO, /* I/O now possible (4.2 BSD). */ + "XCPU", SIGXCPU, /* CPU limit exceeded (4.2 BSD). */ + "XFSZ", SIGXFSZ, /* File size limit exceeded (4.2 BSD). */ + "VTALRM", SIGVTALRM, /* Virtual alarm clock (4.2 BSD). */ + "PROF", SIGPROF, /* Profiling alarm clock (4.2 BSD). */ + "WINCH", SIGWINCH, /* Window size change (4.3 BSD, Sun). */ + "INFO", SIGINFO, /* Information request. */ + "USR1", SIGUSR1, /* User-defined signal 1 (POSIX). */ + "USR2", SIGUSR2 /* User-defined signal 2 (POSIX). */ + }; + +JVM_ENTRY_NO_ENV(jint, JVM_FindSignal(const char *name)) + + /* find and return the named signal's number */ + + for(uint i=0; i<ARRAY_SIZE(siglabels); i++) + if(!strcmp(name, siglabels[i].name)) + return siglabels[i].number; + + return -1; + +JVM_END + +// used by os::exception_name() +extern bool signal_name(int signo, char* buf, size_t len) { + for(uint i = 0; i < ARRAY_SIZE(siglabels); i++) { + if (signo == siglabels[i].number) { + jio_snprintf(buf, len, "SIG%s", siglabels[i].name); + return true; + } + } + return false; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/jvm_bsd.h Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,135 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_BSD_VM_JVM_BSD_H +#define OS_BSD_VM_JVM_BSD_H + +/* +// HotSpot integration note: +// +// This is derived from the JDK classic file: +// "$JDK/src/solaris/javavm/export/jvm_md.h":15 (ver. 1.10 98/04/22) +// All local includes have been commented out. +*/ + + +#ifndef JVM_MD_H +#define JVM_MD_H + +/* + * This file is currently collecting system-specific dregs for the + * JNI conversion, which should be sorted out later. + */ +#ifdef __NetBSD__ +/* + * Since we are compiling with c++, we need the following to make c macros + * visible. + */ +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS 1 +# endif +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS 1 +# endif +# if !defined(__STDC_FORMAT_MACROS) +# define __STDC_FORMAT_MACROS 1 +# endif +#endif + +#include <dirent.h> /* For DIR */ +#include <sys/param.h> /* For MAXPATHLEN */ +#include <unistd.h> /* For F_OK, R_OK, W_OK */ + +#define JNI_ONLOAD_SYMBOLS {"JNI_OnLoad"} +#define JNI_ONUNLOAD_SYMBOLS {"JNI_OnUnload"} +#define JVM_ONLOAD_SYMBOLS {"JVM_OnLoad"} +#define AGENT_ONLOAD_SYMBOLS {"Agent_OnLoad"} +#define AGENT_ONUNLOAD_SYMBOLS {"Agent_OnUnload"} +#define AGENT_ONATTACH_SYMBOLS {"Agent_OnAttach"} + +#define JNI_LIB_PREFIX "lib" +#ifdef __APPLE__ +#define JNI_LIB_SUFFIX ".dylib" +#else +#define JNI_LIB_SUFFIX ".so" +#endif + +// Hack: MAXPATHLEN is 4095 on some Bsd and 4096 on others. This may +// cause problems if JVM and the rest of JDK are built on different +// Bsd releases. Here we define JVM_MAXPATHLEN to be MAXPATHLEN + 1, +// so buffers declared in VM are always >= 4096. +#define JVM_MAXPATHLEN MAXPATHLEN + 1 + +#define JVM_R_OK R_OK +#define JVM_W_OK W_OK +#define JVM_X_OK X_OK +#define JVM_F_OK F_OK + +/* + * File I/O + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +/* O Flags */ + +#define JVM_O_RDONLY O_RDONLY +#define JVM_O_WRONLY O_WRONLY +#define JVM_O_RDWR O_RDWR +#define JVM_O_O_APPEND O_APPEND +#define JVM_O_EXCL O_EXCL +#define JVM_O_CREAT O_CREAT + +/* Signal definitions */ + +#define BREAK_SIGNAL SIGQUIT /* Thread dumping support. */ +#define INTERRUPT_SIGNAL SIGUSR1 /* Interruptible I/O support. */ +#define SHUTDOWN1_SIGNAL SIGHUP /* Shutdown Hooks support. */ +#define SHUTDOWN2_SIGNAL SIGINT +#define SHUTDOWN3_SIGNAL SIGTERM + +#ifndef SIGRTMIN +#ifdef __OpenBSD__ +#define SIGRTMIN 1 +#else +#define SIGRTMIN 33 +#endif +#endif +#ifndef SIGRTMAX +#ifdef __OpenBSD__ +#define SIGRTMAX 31 +#else +#define SIGRTMAX 63 +#endif +#endif +#endif /* JVM_MD_H */ + +// Reconciliation History +// jvm_solaris.h 1.6 99/06/22 16:38:47 +// End + +#endif // OS_BSD_VM_JVM_BSD_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/mutex_bsd.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "mutex_bsd.inline.hpp" +#include "runtime/interfaceSupport.hpp" +#include "runtime/mutex.hpp" +#include "thread_bsd.inline.hpp" +#include "utilities/events.hpp" + +// put OS-includes here +# include <signal.h>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/mutex_bsd.inline.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_BSD_VM_MUTEX_BSD_INLINE_HPP +#define OS_BSD_VM_MUTEX_BSD_INLINE_HPP + +#include "os_bsd.inline.hpp" +#include "runtime/interfaceSupport.hpp" +#include "thread_bsd.inline.hpp" + + +// Reconciliation History +// mutex_solaris.inline.hpp 1.5 99/06/22 16:38:49 +// End + +#endif // OS_BSD_VM_MUTEX_BSD_INLINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/osThread_bsd.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1999, 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. + * + */ + +// no precompiled headers +#include "runtime/atomic.hpp" +#include "runtime/handles.inline.hpp" +#include "runtime/mutexLocker.hpp" +#include "runtime/os.hpp" +#include "runtime/osThread.hpp" +#include "runtime/safepoint.hpp" +#include "runtime/vmThread.hpp" +#ifdef TARGET_ARCH_x86 +# include "assembler_x86.inline.hpp" +#endif +#ifdef TARGET_ARCH_sparc +# include "assembler_sparc.inline.hpp" +#endif +#ifdef TARGET_ARCH_zero +# include "assembler_zero.inline.hpp" +#endif +#ifdef TARGET_ARCH_arm +# include "assembler_arm.inline.hpp" +#endif +#ifdef TARGET_ARCH_ppc +# include "assembler_ppc.inline.hpp" +#endif + + +void OSThread::pd_initialize() { + assert(this != NULL, "check"); + _thread_id = NULL; + _pthread_id = NULL; + _siginfo = NULL; + _ucontext = NULL; + _expanding_stack = 0; + _alt_sig_stack = NULL; + + sigemptyset(&_caller_sigmask); + + _startThread_lock = new Monitor(Mutex::event, "startThread_lock", true); + assert(_startThread_lock !=NULL, "check"); +} + +void OSThread::pd_destroy() { + delete _startThread_lock; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/osThread_bsd.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,165 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_BSD_VM_OSTHREAD_BSD_HPP +#define OS_BSD_VM_OSTHREAD_BSD_HPP + + private: + int _thread_type; + + public: + + int thread_type() const { + return _thread_type; + } + void set_thread_type(int type) { + _thread_type = type; + } + + private: + +#ifdef _ALLBSD_SOURCE + // _thread_id and _pthread_id are the same on BSD + // keep both to minimize code divergence in os_bsd.cpp + pthread_t _thread_id; + pthread_t _pthread_id; +#else + // _thread_id is kernel thread id (similar to LWP id on Solaris). Each + // thread has a unique thread_id (BsdThreads or NPTL). It can be used + // to access /proc. + pid_t _thread_id; + + // _pthread_id is the pthread id, which is used by library calls + // (e.g. pthread_kill). + pthread_t _pthread_id; +#endif + + sigset_t _caller_sigmask; // Caller's signal mask + + public: + + // Methods to save/restore caller's signal mask + sigset_t caller_sigmask() const { return _caller_sigmask; } + void set_caller_sigmask(sigset_t sigmask) { _caller_sigmask = sigmask; } + +#ifdef _ALLBSD_SOURCE + pthread_t thread_id() const { + return _thread_id; + } +#else + pid_t thread_id() const { + return _thread_id; + } +#endif +#ifndef PRODUCT + // Used for debugging, return a unique integer for each thread. + intptr_t thread_identifier() const { return (intptr_t)_pthread_id; } +#endif +#ifdef ASSERT + // We expect no reposition failures so kill vm if we get one. + // + bool valid_reposition_failure() { + return false; + } +#endif // ASSERT +#ifdef _ALLBSD_SOURCE + void set_thread_id(pthread_t id) { + _thread_id = id; + } +#else + void set_thread_id(pid_t id) { + _thread_id = id; + } +#endif + pthread_t pthread_id() const { + return _pthread_id; + } + void set_pthread_id(pthread_t tid) { + _pthread_id = tid; + } + + // *************************************************************** + // suspension support. + // *************************************************************** + +public: + // flags that support signal based suspend/resume on Bsd are in a + // separate class to avoid confusion with many flags in OSThread that + // are used by VM level suspend/resume. + os::Bsd::SuspendResume sr; + + // _ucontext and _siginfo are used by SR_handler() to save thread context, + // and they will later be used to walk the stack or reposition thread PC. + // If the thread is not suspended in SR_handler() (e.g. self suspend), + // the value in _ucontext is meaningless, so we must use the last Java + // frame information as the frame. This will mean that for threads + // that are parked on a mutex the profiler (and safepoint mechanism) + // will see the thread as if it were still in the Java frame. This + // not a problem for the profiler since the Java frame is a close + // enough result. For the safepoint mechanism when the give it the + // Java frame we are not at a point where the safepoint needs the + // frame to that accurate (like for a compiled safepoint) since we + // should be in a place where we are native and will block ourselves + // if we transition. +private: + void* _siginfo; + ucontext_t* _ucontext; + int _expanding_stack; /* non zero if manually expanding stack */ + address _alt_sig_stack; /* address of base of alternate signal stack */ + +public: + void* siginfo() const { return _siginfo; } + void set_siginfo(void* ptr) { _siginfo = ptr; } + ucontext_t* ucontext() const { return _ucontext; } + void set_ucontext(ucontext_t* ptr) { _ucontext = ptr; } + void set_expanding_stack(void) { _expanding_stack = 1; } + void clear_expanding_stack(void) { _expanding_stack = 0; } + int expanding_stack(void) { return _expanding_stack; } + + void set_alt_sig_stack(address val) { _alt_sig_stack = val; } + address alt_sig_stack(void) { return _alt_sig_stack; } + +private: + Monitor* _startThread_lock; // sync parent and child in thread creation + +public: + + Monitor* startThread_lock() const { + return _startThread_lock; + } + + // *************************************************************** + // Platform dependent initialization and cleanup + // *************************************************************** + +private: + + void pd_initialize(); + void pd_destroy(); + +// Reconciliation History +// osThread_solaris.hpp 1.24 99/08/27 13:11:54 +// End + +#endif // OS_BSD_VM_OSTHREAD_BSD_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/os_bsd.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,5816 @@ +/* + * Copyright (c) 1999, 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. + * + */ + +// no precompiled headers +#include "classfile/classLoader.hpp" +#include "classfile/systemDictionary.hpp" +#include "classfile/vmSymbols.hpp" +#include "code/icBuffer.hpp" +#include "code/vtableStubs.hpp" +#include "compiler/compileBroker.hpp" +#include "interpreter/interpreter.hpp" +#include "jvm_bsd.h" +#include "memory/allocation.inline.hpp" +#include "memory/filemap.hpp" +#include "mutex_bsd.inline.hpp" +#include "oops/oop.inline.hpp" +#include "os_share_bsd.hpp" +#include "prims/jniFastGetField.hpp" +#include "prims/jvm.h" +#include "prims/jvm_misc.hpp" +#include "runtime/arguments.hpp" +#include "runtime/extendedPC.hpp" +#include "runtime/globals.hpp" +#include "runtime/interfaceSupport.hpp" +#include "runtime/java.hpp" +#include "runtime/javaCalls.hpp" +#include "runtime/mutexLocker.hpp" +#include "runtime/objectMonitor.hpp" +#include "runtime/osThread.hpp" +#include "runtime/perfMemory.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/statSampler.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/threadCritical.hpp" +#include "runtime/timer.hpp" +#include "services/attachListener.hpp" +#include "services/runtimeService.hpp" +#include "thread_bsd.inline.hpp" +#include "utilities/decoder.hpp" +#include "utilities/defaultStream.hpp" +#include "utilities/events.hpp" +#include "utilities/growableArray.hpp" +#include "utilities/vmError.hpp" +#ifdef TARGET_ARCH_x86 +# include "assembler_x86.inline.hpp" +# include "nativeInst_x86.hpp" +#endif +#ifdef TARGET_ARCH_sparc +# include "assembler_sparc.inline.hpp" +# include "nativeInst_sparc.hpp" +#endif +#ifdef TARGET_ARCH_zero +# include "assembler_zero.inline.hpp" +# include "nativeInst_zero.hpp" +#endif +#ifdef TARGET_ARCH_arm +# include "assembler_arm.inline.hpp" +# include "nativeInst_arm.hpp" +#endif +#ifdef TARGET_ARCH_ppc +# include "assembler_ppc.inline.hpp" +# include "nativeInst_ppc.hpp" +#endif +#ifdef COMPILER1 +#include "c1/c1_Runtime1.hpp" +#endif +#ifdef COMPILER2 +#include "opto/runtime.hpp" +#endif + +// put OS-includes here +# include <sys/types.h> +# include <sys/mman.h> +# include <sys/stat.h> +# include <sys/select.h> +# include <pthread.h> +# include <signal.h> +# include <errno.h> +# include <dlfcn.h> +# include <stdio.h> +# include <unistd.h> +# include <sys/resource.h> +# include <pthread.h> +# include <sys/stat.h> +# include <sys/time.h> +# include <sys/times.h> +# include <sys/utsname.h> +# include <sys/socket.h> +# include <sys/wait.h> +# include <time.h> +# include <pwd.h> +# include <poll.h> +# include <semaphore.h> +# include <fcntl.h> +# include <string.h> +#ifdef _ALLBSD_SOURCE +# include <sys/param.h> +# include <sys/sysctl.h> +#else +# include <syscall.h> +# include <sys/sysinfo.h> +# include <gnu/libc-version.h> +#endif +# include <sys/ipc.h> +# include <sys/shm.h> +#ifndef __APPLE__ +# include <link.h> +#endif +# include <stdint.h> +# include <inttypes.h> +# include <sys/ioctl.h> + +#if defined(__FreeBSD__) || defined(__NetBSD__) +# include <elf.h> +#endif + +#ifdef __APPLE__ +# include <mach/mach.h> // semaphore_* API +# include <mach-o/dyld.h> +# include <sys/proc_info.h> +# include <objc/objc-auto.h> +#endif + +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + +#define MAX_PATH (2 * K) + +// for timer info max values which include all bits +#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) +#define SEC_IN_NANOSECS 1000000000LL + +#define LARGEPAGES_BIT (1 << 6) +//////////////////////////////////////////////////////////////////////////////// +// global variables +julong os::Bsd::_physical_memory = 0; + +#ifndef _ALLBSD_SOURCE +address os::Bsd::_initial_thread_stack_bottom = NULL; +uintptr_t os::Bsd::_initial_thread_stack_size = 0; +#endif + +int (*os::Bsd::_clock_gettime)(clockid_t, struct timespec *) = NULL; +#ifndef _ALLBSD_SOURCE +int (*os::Bsd::_pthread_getcpuclockid)(pthread_t, clockid_t *) = NULL; +Mutex* os::Bsd::_createThread_lock = NULL; +#endif +pthread_t os::Bsd::_main_thread; +int os::Bsd::_page_size = -1; +#ifndef _ALLBSD_SOURCE +bool os::Bsd::_is_floating_stack = false; +bool os::Bsd::_is_NPTL = false; +bool os::Bsd::_supports_fast_thread_cpu_time = false; +const char * os::Bsd::_glibc_version = NULL; +const char * os::Bsd::_libpthread_version = NULL; +#endif + +static jlong initial_time_count=0; + +static int clock_tics_per_sec = 100; + +// For diagnostics to print a message once. see run_periodic_checks +static sigset_t check_signal_done; +static bool check_signals = true;; + +static pid_t _initial_pid = 0; + +/* Signal number used to suspend/resume a thread */ + +/* do not use any signal number less than SIGSEGV, see 4355769 */ +static int SR_signum = SIGUSR2; +sigset_t SR_sigset; + + +//////////////////////////////////////////////////////////////////////////////// +// utility functions + +static int SR_initialize(); +static int SR_finalize(); + +julong os::available_memory() { + return Bsd::available_memory(); +} + +julong os::Bsd::available_memory() { +#ifdef _ALLBSD_SOURCE + // XXXBSD: this is just a stopgap implementation + return physical_memory() >> 2; +#else + // values in struct sysinfo are "unsigned long" + struct sysinfo si; + sysinfo(&si); + + return (julong)si.freeram * si.mem_unit; +#endif +} + +julong os::physical_memory() { + return Bsd::physical_memory(); +} + +julong os::allocatable_physical_memory(julong size) { +#ifdef _LP64 + return size; +#else + julong result = MIN2(size, (julong)3800*M); + if (!is_allocatable(result)) { + // See comments under solaris for alignment considerations + julong reasonable_size = (julong)2*G - 2 * os::vm_page_size(); + result = MIN2(size, reasonable_size); + } + return result; +#endif // _LP64 +} + +//////////////////////////////////////////////////////////////////////////////// +// environment support + +bool os::getenv(const char* name, char* buf, int len) { + const char* val = ::getenv(name); + if (val != NULL && strlen(val) < (size_t)len) { + strcpy(buf, val); + return true; + } + if (len > 0) buf[0] = 0; // return a null string + return false; +} + + +// Return true if user is running as root. + +bool os::have_special_privileges() { + static bool init = false; + static bool privileges = false; + if (!init) { + privileges = (getuid() != geteuid()) || (getgid() != getegid()); + init = true; + } + return privileges; +} + + +#ifndef _ALLBSD_SOURCE +#ifndef SYS_gettid +// i386: 224, ia64: 1105, amd64: 186, sparc 143 +#ifdef __ia64__ +#define SYS_gettid 1105 +#elif __i386__ +#define SYS_gettid 224 +#elif __amd64__ +#define SYS_gettid 186 +#elif __sparc__ +#define SYS_gettid 143 +#else +#error define gettid for the arch +#endif +#endif +#endif + +// Cpu architecture string +#if defined(ZERO) +static char cpu_arch[] = ZERO_LIBARCH; +#elif defined(IA64) +static char cpu_arch[] = "ia64"; +#elif defined(IA32) +static char cpu_arch[] = "i386"; +#elif defined(AMD64) +static char cpu_arch[] = "amd64"; +#elif defined(ARM) +static char cpu_arch[] = "arm"; +#elif defined(PPC) +static char cpu_arch[] = "ppc"; +#elif defined(SPARC) +# ifdef _LP64 +static char cpu_arch[] = "sparcv9"; +# else +static char cpu_arch[] = "sparc"; +# endif +#else +#error Add appropriate cpu_arch setting +#endif + + +#ifndef _ALLBSD_SOURCE +// pid_t gettid() +// +// Returns the kernel thread id of the currently running thread. Kernel +// thread id is used to access /proc. +// +// (Note that getpid() on BsdThreads returns kernel thread id too; but +// on NPTL, it returns the same pid for all threads, as required by POSIX.) +// +pid_t os::Bsd::gettid() { + int rslt = syscall(SYS_gettid); + if (rslt == -1) { + // old kernel, no NPTL support + return getpid(); + } else { + return (pid_t)rslt; + } +} + +// Most versions of bsd have a bug where the number of processors are +// determined by looking at the /proc file system. In a chroot environment, +// the system call returns 1. This causes the VM to act as if it is +// a single processor and elide locking (see is_MP() call). +static bool unsafe_chroot_detected = false; +static const char *unstable_chroot_error = "/proc file system not found.\n" + "Java may be unstable running multithreaded in a chroot " + "environment on Bsd when /proc filesystem is not mounted."; +#endif + +#ifdef _ALLBSD_SOURCE +void os::Bsd::initialize_system_info() { + int mib[2]; + size_t len; + int cpu_val; + u_long mem_val; + + /* get processors count via hw.ncpus sysctl */ + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + len = sizeof(cpu_val); + if (sysctl(mib, 2, &cpu_val, &len, NULL, 0) != -1 && cpu_val >= 1) { + set_processor_count(cpu_val); + } + else { + set_processor_count(1); // fallback + } + + /* get physical memory via hw.usermem sysctl (hw.usermem is used + * instead of hw.physmem because we need size of allocatable memory + */ + mib[0] = CTL_HW; + mib[1] = HW_USERMEM; + len = sizeof(mem_val); + if (sysctl(mib, 2, &mem_val, &len, NULL, 0) != -1) + _physical_memory = mem_val; + else + _physical_memory = 256*1024*1024; // fallback (XXXBSD?) + +#ifdef __OpenBSD__ + { + // limit _physical_memory memory view on OpenBSD since + // datasize rlimit restricts us anyway. + struct rlimit limits; + getrlimit(RLIMIT_DATA, &limits); + _physical_memory = MIN2(_physical_memory, (julong)limits.rlim_cur); + } +#endif +} +#else +void os::Bsd::initialize_system_info() { + set_processor_count(sysconf(_SC_NPROCESSORS_CONF)); + if (processor_count() == 1) { + pid_t pid = os::Bsd::gettid(); + char fname[32]; + jio_snprintf(fname, sizeof(fname), "/proc/%d", pid); + FILE *fp = fopen(fname, "r"); + if (fp == NULL) { + unsafe_chroot_detected = true; + } else { + fclose(fp); + } + } + _physical_memory = (julong)sysconf(_SC_PHYS_PAGES) * (julong)sysconf(_SC_PAGESIZE); + assert(processor_count() > 0, "bsd error"); +} +#endif + +#ifdef __APPLE__ +static const char *get_home() { + const char *home_dir = ::getenv("HOME"); + if ((home_dir == NULL) || (*home_dir == '\0')) { + struct passwd *passwd_info = getpwuid(geteuid()); + if (passwd_info != NULL) { + home_dir = passwd_info->pw_dir; + } + } + + return home_dir; +} +#endif + +void os::init_system_properties_values() { +// char arch[12]; +// sysinfo(SI_ARCHITECTURE, arch, sizeof(arch)); + + // The next steps are taken in the product version: + // + // Obtain the JAVA_HOME value from the location of libjvm[_g].so. + // This library should be located at: + // <JAVA_HOME>/jre/lib/<arch>/{client|server}/libjvm[_g].so. + // + // If "/jre/lib/" appears at the right place in the path, then we + // assume libjvm[_g].so is installed in a JDK and we use this path. + // + // Otherwise exit with message: "Could not create the Java virtual machine." + // + // The following extra steps are taken in the debugging version: + // + // If "/jre/lib/" does NOT appear at the right place in the path + // instead of exit check for $JAVA_HOME environment variable. + // + // If it is defined and we are able to locate $JAVA_HOME/jre/lib/<arch>, + // then we append a fake suffix "hotspot/libjvm[_g].so" to this path so + // it looks like libjvm[_g].so is installed there + // <JAVA_HOME>/jre/lib/<arch>/hotspot/libjvm[_g].so. + // + // Otherwise exit. + // + // Important note: if the location of libjvm.so changes this + // code needs to be changed accordingly. + + // The next few definitions allow the code to be verbatim: +#define malloc(n) (char*)NEW_C_HEAP_ARRAY(char, (n)) +#define getenv(n) ::getenv(n) + +/* + * See ld(1): + * The linker uses the following search paths to locate required + * shared libraries: + * 1: ... + * ... + * 7: The default directories, normally /lib and /usr/lib. + */ +#ifndef DEFAULT_LIBPATH +#define DEFAULT_LIBPATH "/lib:/usr/lib" +#endif + +#define EXTENSIONS_DIR "/lib/ext" +#define ENDORSED_DIR "/lib/endorsed" +#define REG_DIR "/usr/java/packages" + +#ifdef __APPLE__ +#define SYS_EXTENSIONS_DIR "/Library/Java/Extensions" +#define SYS_EXTENSIONS_DIRS SYS_EXTENSIONS_DIR ":/Network" SYS_EXTENSIONS_DIR ":/System" SYS_EXTENSIONS_DIR ":/usr/lib/java" + const char *user_home_dir = get_home(); + // the null in SYS_EXTENSIONS_DIRS counts for the size of the colon after user_home_dir + int system_ext_size = strlen(user_home_dir) + sizeof(SYS_EXTENSIONS_DIR) + + sizeof(SYS_EXTENSIONS_DIRS); +#endif + + { + /* sysclasspath, java_home, dll_dir */ + { + char *home_path; + char *dll_path; + char *pslash; + char buf[MAXPATHLEN]; + os::jvm_path(buf, sizeof(buf)); + + // Found the full path to libjvm.so. + // Now cut the path to <java_home>/jre if we can. + *(strrchr(buf, '/')) = '\0'; /* get rid of /libjvm.so */ + pslash = strrchr(buf, '/'); + if (pslash != NULL) + *pslash = '\0'; /* get rid of /{client|server|hotspot} */ + dll_path = malloc(strlen(buf) + 1); + if (dll_path == NULL) + return; + strcpy(dll_path, buf); + Arguments::set_dll_dir(dll_path); + + if (pslash != NULL) { + pslash = strrchr(buf, '/'); + if (pslash != NULL) { + *pslash = '\0'; /* get rid of /<arch> (/lib on macosx) */ +#ifndef __APPLE__ + pslash = strrchr(buf, '/'); + if (pslash != NULL) + *pslash = '\0'; /* get rid of /lib */ +#endif + } + } + + home_path = malloc(strlen(buf) + 1); + if (home_path == NULL) + return; + strcpy(home_path, buf); + Arguments::set_java_home(home_path); + + if (!set_boot_path('/', ':')) + return; + } + + /* + * Where to look for native libraries + * + * Note: Due to a legacy implementation, most of the library path + * is set in the launcher. This was to accomodate linking restrictions + * on legacy Bsd implementations (which are no longer supported). + * Eventually, all the library path setting will be done here. + * + * However, to prevent the proliferation of improperly built native + * libraries, the new path component /usr/java/packages is added here. + * Eventually, all the library path setting will be done here. + */ + { + char *ld_library_path; + + /* + * Construct the invariant part of ld_library_path. Note that the + * space for the colon and the trailing null are provided by the + * nulls included by the sizeof operator (so actually we allocate + * a byte more than necessary). + */ +#ifdef __APPLE__ + ld_library_path = (char *) malloc(system_ext_size); + sprintf(ld_library_path, "%s" SYS_EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS, user_home_dir); +#else + ld_library_path = (char *) malloc(sizeof(REG_DIR) + sizeof("/lib/") + + strlen(cpu_arch) + sizeof(DEFAULT_LIBPATH)); + sprintf(ld_library_path, REG_DIR "/lib/%s:" DEFAULT_LIBPATH, cpu_arch); +#endif + + /* + * Get the user setting of LD_LIBRARY_PATH, and prepended it. It + * should always exist (until the legacy problem cited above is + * addressed). + */ +#ifdef __APPLE__ + // Prepend the default path with the JAVA_LIBRARY_PATH so that the app launcher code can specify a directory inside an app wrapper + char *l = getenv("JAVA_LIBRARY_PATH"); + if (l != NULL) { + char *t = ld_library_path; + /* That's +1 for the colon and +1 for the trailing '\0' */ + ld_library_path = (char *) malloc(strlen(l) + 1 + strlen(t) + 1); + sprintf(ld_library_path, "%s:%s", l, t); + free(t); + } + + char *v = getenv("DYLD_LIBRARY_PATH"); +#else + char *v = getenv("LD_LIBRARY_PATH"); +#endif + if (v != NULL) { + char *t = ld_library_path; + /* That's +1 for the colon and +1 for the trailing '\0' */ + ld_library_path = (char *) malloc(strlen(v) + 1 + strlen(t) + 1); + sprintf(ld_library_path, "%s:%s", v, t); + free(t); + } + Arguments::set_library_path(ld_library_path); + } + + /* + * Extensions directories. + * + * Note that the space for the colon and the trailing null are provided + * by the nulls included by the sizeof operator (so actually one byte more + * than necessary is allocated). + */ + { +#ifdef __APPLE__ + char *buf = malloc(strlen(Arguments::get_java_home()) + + sizeof(EXTENSIONS_DIR) + system_ext_size); + sprintf(buf, "%s" SYS_EXTENSIONS_DIR ":%s" EXTENSIONS_DIR ":" + SYS_EXTENSIONS_DIRS, user_home_dir, Arguments::get_java_home()); +#else + char *buf = malloc(strlen(Arguments::get_java_home()) + + sizeof(EXTENSIONS_DIR) + sizeof(REG_DIR) + sizeof(EXTENSIONS_DIR)); + sprintf(buf, "%s" EXTENSIONS_DIR ":" REG_DIR EXTENSIONS_DIR, + Arguments::get_java_home()); +#endif + + Arguments::set_ext_dirs(buf); + } + + /* Endorsed standards default directory. */ + { + char * buf; + buf = malloc(strlen(Arguments::get_java_home()) + sizeof(ENDORSED_DIR)); + sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home()); + Arguments::set_endorsed_dirs(buf); + } + } + +#ifdef __APPLE__ +#undef SYS_EXTENSIONS_DIR +#endif +#undef malloc +#undef getenv +#undef EXTENSIONS_DIR +#undef ENDORSED_DIR + + // Done + return; +} + +//////////////////////////////////////////////////////////////////////////////// +// breakpoint support + +void os::breakpoint() { + BREAKPOINT; +} + +extern "C" void breakpoint() { + // use debugger to set breakpoint here +} + +//////////////////////////////////////////////////////////////////////////////// +// signal support + +debug_only(static bool signal_sets_initialized = false); +static sigset_t unblocked_sigs, vm_sigs, allowdebug_blocked_sigs; + +bool os::Bsd::is_sig_ignored(int sig) { + struct sigaction oact; + sigaction(sig, (struct sigaction*)NULL, &oact); + void* ohlr = oact.sa_sigaction ? CAST_FROM_FN_PTR(void*, oact.sa_sigaction) + : CAST_FROM_FN_PTR(void*, oact.sa_handler); + if (ohlr == CAST_FROM_FN_PTR(void*, SIG_IGN)) + return true; + else + return false; +} + +void os::Bsd::signal_sets_init() { + // Should also have an assertion stating we are still single-threaded. + assert(!signal_sets_initialized, "Already initialized"); + // Fill in signals that are necessarily unblocked for all threads in + // the VM. Currently, we unblock the following signals: + // SHUTDOWN{1,2,3}_SIGNAL: for shutdown hooks support (unless over-ridden + // by -Xrs (=ReduceSignalUsage)); + // BREAK_SIGNAL which is unblocked only by the VM thread and blocked by all + // other threads. The "ReduceSignalUsage" boolean tells us not to alter + // the dispositions or masks wrt these signals. + // Programs embedding the VM that want to use the above signals for their + // own purposes must, at this time, use the "-Xrs" option to prevent + // interference with shutdown hooks and BREAK_SIGNAL thread dumping. + // (See bug 4345157, and other related bugs). + // In reality, though, unblocking these signals is really a nop, since + // these signals are not blocked by default. + sigemptyset(&unblocked_sigs); + sigemptyset(&allowdebug_blocked_sigs); + sigaddset(&unblocked_sigs, SIGILL); + sigaddset(&unblocked_sigs, SIGSEGV); + sigaddset(&unblocked_sigs, SIGBUS); + sigaddset(&unblocked_sigs, SIGFPE); + sigaddset(&unblocked_sigs, SR_signum); + + if (!ReduceSignalUsage) { + if (!os::Bsd::is_sig_ignored(SHUTDOWN1_SIGNAL)) { + sigaddset(&unblocked_sigs, SHUTDOWN1_SIGNAL); + sigaddset(&allowdebug_blocked_sigs, SHUTDOWN1_SIGNAL); + } + if (!os::Bsd::is_sig_ignored(SHUTDOWN2_SIGNAL)) { + sigaddset(&unblocked_sigs, SHUTDOWN2_SIGNAL); + sigaddset(&allowdebug_blocked_sigs, SHUTDOWN2_SIGNAL); + } + if (!os::Bsd::is_sig_ignored(SHUTDOWN3_SIGNAL)) { + sigaddset(&unblocked_sigs, SHUTDOWN3_SIGNAL); + sigaddset(&allowdebug_blocked_sigs, SHUTDOWN3_SIGNAL); + } + } + // Fill in signals that are blocked by all but the VM thread. + sigemptyset(&vm_sigs); + if (!ReduceSignalUsage) + sigaddset(&vm_sigs, BREAK_SIGNAL); + debug_only(signal_sets_initialized = true); + +} + +// These are signals that are unblocked while a thread is running Java. +// (For some reason, they get blocked by default.) +sigset_t* os::Bsd::unblocked_signals() { + assert(signal_sets_initialized, "Not initialized"); + return &unblocked_sigs; +} + +// These are the signals that are blocked while a (non-VM) thread is +// running Java. Only the VM thread handles these signals. +sigset_t* os::Bsd::vm_signals() { + assert(signal_sets_initialized, "Not initialized"); + return &vm_sigs; +} + +// These are signals that are blocked during cond_wait to allow debugger in +sigset_t* os::Bsd::allowdebug_blocked_signals() { + assert(signal_sets_initialized, "Not initialized"); + return &allowdebug_blocked_sigs; +} + +void os::Bsd::hotspot_sigmask(Thread* thread) { + + //Save caller's signal mask before setting VM signal mask + sigset_t caller_sigmask; + pthread_sigmask(SIG_BLOCK, NULL, &caller_sigmask); + + OSThread* osthread = thread->osthread(); + osthread->set_caller_sigmask(caller_sigmask); + + pthread_sigmask(SIG_UNBLOCK, os::Bsd::unblocked_signals(), NULL); + + if (!ReduceSignalUsage) { + if (thread->is_VM_thread()) { + // Only the VM thread handles BREAK_SIGNAL ... + pthread_sigmask(SIG_UNBLOCK, vm_signals(), NULL); + } else { + // ... all other threads block BREAK_SIGNAL + pthread_sigmask(SIG_BLOCK, vm_signals(), NULL); + } + } +} + +#ifndef _ALLBSD_SOURCE +////////////////////////////////////////////////////////////////////////////// +// detecting pthread library + +void os::Bsd::libpthread_init() { + // Save glibc and pthread version strings. Note that _CS_GNU_LIBC_VERSION + // and _CS_GNU_LIBPTHREAD_VERSION are supported in glibc >= 2.3.2. Use a + // generic name for earlier versions. + // Define macros here so we can build HotSpot on old systems. +# ifndef _CS_GNU_LIBC_VERSION +# define _CS_GNU_LIBC_VERSION 2 +# endif +# ifndef _CS_GNU_LIBPTHREAD_VERSION +# define _CS_GNU_LIBPTHREAD_VERSION 3 +# endif + + size_t n = confstr(_CS_GNU_LIBC_VERSION, NULL, 0); + if (n > 0) { + char *str = (char *)malloc(n); + confstr(_CS_GNU_LIBC_VERSION, str, n); + os::Bsd::set_glibc_version(str); + } else { + // _CS_GNU_LIBC_VERSION is not supported, try gnu_get_libc_version() + static char _gnu_libc_version[32]; + jio_snprintf(_gnu_libc_version, sizeof(_gnu_libc_version), + "glibc %s %s", gnu_get_libc_version(), gnu_get_libc_release()); + os::Bsd::set_glibc_version(_gnu_libc_version); + } + + n = confstr(_CS_GNU_LIBPTHREAD_VERSION, NULL, 0); + if (n > 0) { + char *str = (char *)malloc(n); + confstr(_CS_GNU_LIBPTHREAD_VERSION, str, n); + // Vanilla RH-9 (glibc 2.3.2) has a bug that confstr() always tells + // us "NPTL-0.29" even we are running with BsdThreads. Check if this + // is the case. BsdThreads has a hard limit on max number of threads. + // So sysconf(_SC_THREAD_THREADS_MAX) will return a positive value. + // On the other hand, NPTL does not have such a limit, sysconf() + // will return -1 and errno is not changed. Check if it is really NPTL. + if (strcmp(os::Bsd::glibc_version(), "glibc 2.3.2") == 0 && + strstr(str, "NPTL") && + sysconf(_SC_THREAD_THREADS_MAX) > 0) { + free(str); + os::Bsd::set_libpthread_version("bsdthreads"); + } else { + os::Bsd::set_libpthread_version(str); + } + } else { + // glibc before 2.3.2 only has BsdThreads. + os::Bsd::set_libpthread_version("bsdthreads"); + } + + if (strstr(libpthread_version(), "NPTL")) { + os::Bsd::set_is_NPTL(); + } else { + os::Bsd::set_is_BsdThreads(); + } + + // BsdThreads have two flavors: floating-stack mode, which allows variable + // stack size; and fixed-stack mode. NPTL is always floating-stack. + if (os::Bsd::is_NPTL() || os::Bsd::supports_variable_stack_size()) { + os::Bsd::set_is_floating_stack(); + } +} + +///////////////////////////////////////////////////////////////////////////// +// thread stack + +// Force Bsd kernel to expand current thread stack. If "bottom" is close +// to the stack guard, caller should block all signals. +// +// MAP_GROWSDOWN: +// A special mmap() flag that is used to implement thread stacks. It tells +// kernel that the memory region should extend downwards when needed. This +// allows early versions of BsdThreads to only mmap the first few pages +// when creating a new thread. Bsd kernel will automatically expand thread +// stack as needed (on page faults). +// +// However, because the memory region of a MAP_GROWSDOWN stack can grow on +// demand, if a page fault happens outside an already mapped MAP_GROWSDOWN +// region, it's hard to tell if the fault is due to a legitimate stack +// access or because of reading/writing non-exist memory (e.g. buffer +// overrun). As a rule, if the fault happens below current stack pointer, +// Bsd kernel does not expand stack, instead a SIGSEGV is sent to the +// application (see Bsd kernel fault.c). +// +// This Bsd feature can cause SIGSEGV when VM bangs thread stack for +// stack overflow detection. +// +// Newer version of BsdThreads (since glibc-2.2, or, RH-7.x) and NPTL do +// not use this flag. However, the stack of initial thread is not created +// by pthread, it is still MAP_GROWSDOWN. Also it's possible (though +// unlikely) that user code can create a thread with MAP_GROWSDOWN stack +// and then attach the thread to JVM. +// +// To get around the problem and allow stack banging on Bsd, we need to +// manually expand thread stack after receiving the SIGSEGV. +// +// There are two ways to expand thread stack to address "bottom", we used +// both of them in JVM before 1.5: +// 1. adjust stack pointer first so that it is below "bottom", and then +// touch "bottom" +// 2. mmap() the page in question +// +// Now alternate signal stack is gone, it's harder to use 2. For instance, +// if current sp is already near the lower end of page 101, and we need to +// call mmap() to map page 100, it is possible that part of the mmap() frame +// will be placed in page 100. When page 100 is mapped, it is zero-filled. +// That will destroy the mmap() frame and cause VM to crash. +// +// The following code works by adjusting sp first, then accessing the "bottom" +// page to force a page fault. Bsd kernel will then automatically expand the +// stack mapping. +// +// _expand_stack_to() assumes its frame size is less than page size, which +// should always be true if the function is not inlined. + +#if __GNUC__ < 3 // gcc 2.x does not support noinline attribute +#define NOINLINE +#else +#define NOINLINE __attribute__ ((noinline)) +#endif + +static void _expand_stack_to(address bottom) NOINLINE; + +static void _expand_stack_to(address bottom) { + address sp; + size_t size; + volatile char *p; + + // Adjust bottom to point to the largest address within the same page, it + // gives us a one-page buffer if alloca() allocates slightly more memory. + bottom = (address)align_size_down((uintptr_t)bottom, os::Bsd::page_size()); + bottom += os::Bsd::page_size() - 1; + + // sp might be slightly above current stack pointer; if that's the case, we + // will alloca() a little more space than necessary, which is OK. Don't use + // os::current_stack_pointer(), as its result can be slightly below current + // stack pointer, causing us to not alloca enough to reach "bottom". + sp = (address)&sp; + + if (sp > bottom) { + size = sp - bottom; + p = (volatile char *)alloca(size); + assert(p != NULL && p <= (volatile char *)bottom, "alloca problem?"); + p[0] = '\0'; + } +} + +bool os::Bsd::manually_expand_stack(JavaThread * t, address addr) { + assert(t!=NULL, "just checking"); + assert(t->osthread()->expanding_stack(), "expand should be set"); + assert(t->stack_base() != NULL, "stack_base was not initialized"); + + if (addr < t->stack_base() && addr >= t->stack_yellow_zone_base()) { + sigset_t mask_all, old_sigset; + sigfillset(&mask_all); + pthread_sigmask(SIG_SETMASK, &mask_all, &old_sigset); + _expand_stack_to(addr); + pthread_sigmask(SIG_SETMASK, &old_sigset, NULL); + return true; + } + return false; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// create new thread + +static address highest_vm_reserved_address(); + +// check if it's safe to start a new thread +static bool _thread_safety_check(Thread* thread) { +#ifdef _ALLBSD_SOURCE + return true; +#else + if (os::Bsd::is_BsdThreads() && !os::Bsd::is_floating_stack()) { + // Fixed stack BsdThreads (SuSE Bsd/x86, and some versions of Redhat) + // Heap is mmap'ed at lower end of memory space. Thread stacks are + // allocated (MAP_FIXED) from high address space. Every thread stack + // occupies a fixed size slot (usually 2Mbytes, but user can change + // it to other values if they rebuild BsdThreads). + // + // Problem with MAP_FIXED is that mmap() can still succeed even part of + // the memory region has already been mmap'ed. That means if we have too + // many threads and/or very large heap, eventually thread stack will + // collide with heap. + // + // Here we try to prevent heap/stack collision by comparing current + // stack bottom with the highest address that has been mmap'ed by JVM + // plus a safety margin for memory maps created by native code. + // + // This feature can be disabled by setting ThreadSafetyMargin to 0 + // + if (ThreadSafetyMargin > 0) { + address stack_bottom = os::current_stack_base() - os::current_stack_size(); + + // not safe if our stack extends below the safety margin + return stack_bottom - ThreadSafetyMargin >= highest_vm_reserved_address(); + } else { + return true; + } + } else { + // Floating stack BsdThreads or NPTL: + // Unlike fixed stack BsdThreads, thread stacks are not MAP_FIXED. When + // there's not enough space left, pthread_create() will fail. If we come + // here, that means enough space has been reserved for stack. + return true; + } +#endif +} + +#ifdef __APPLE__ +// library handle for calling objc_registerThreadWithCollector() +// without static linking to the libobjc library +#define OBJC_LIB "/usr/lib/libobjc.dylib" +#define OBJC_GCREGISTER "objc_registerThreadWithCollector" +typedef void (*objc_registerThreadWithCollector_t)(); +extern "C" objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFunction; +objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFunction = NULL; +#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. + // This helps when threads of the same stack traces evict each other's + // cache lines. The threads can be either from the same JVM instance, or + // from different JVM instances. The benefit is especially true for + // processors with hyperthreading technology. + static int counter = 0; + int pid = os::current_process_id(); + alloca(((pid ^ counter++) & 7) * 128); + + ThreadLocalStorage::set_thread(thread); + + OSThread* osthread = thread->osthread(); + Monitor* sync = osthread->startThread_lock(); + + // non floating stack BsdThreads needs extra check, see above + if (!_thread_safety_check(thread)) { + // notify parent thread + MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag); + osthread->set_state(ZOMBIE); + sync->notify_all(); + return NULL; + } + +#ifdef _ALLBSD_SOURCE + // thread_id is pthread_id on BSD + osthread->set_thread_id(::pthread_self()); +#else + // thread_id is kernel thread id (similar to Solaris LWP id) + osthread->set_thread_id(os::Bsd::gettid()); + + if (UseNUMA) { + int lgrp_id = os::numa_get_group_id(); + if (lgrp_id != -1) { + thread->set_lgrp_id(lgrp_id); + } + } +#endif + // initialize signal mask for this thread + os::Bsd::hotspot_sigmask(thread); + + // initialize floating point control register + os::Bsd::init_thread_fpu_state(); + +#ifdef __APPLE__ + // register thread with objc gc + if (objc_registerThreadWithCollectorFunction != NULL) { + objc_registerThreadWithCollectorFunction(); + } +#endif + + // handshaking with parent thread + { + MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag); + + // notify parent thread + osthread->set_state(INITIALIZED); + sync->notify_all(); + + // wait until os::start_thread() + while (osthread->get_state() == INITIALIZED) { + sync->wait(Mutex::_no_safepoint_check_flag); + } + } + + // call one more level start routine + thread->run(); + + return 0; +} + +bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { + assert(thread->osthread() == NULL, "caller responsible"); + + // Allocate the OSThread object + OSThread* osthread = new OSThread(NULL, NULL); + if (osthread == NULL) { + return false; + } + + // set the correct thread state + osthread->set_thread_type(thr_type); + + // Initial state is ALLOCATED but not INITIALIZED + osthread->set_state(ALLOCATED); + + thread->set_osthread(osthread); + + // init thread attributes + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + // stack size + if (os::Bsd::supports_variable_stack_size()) { + // calculate stack size if it's not specified by caller + if (stack_size == 0) { + stack_size = os::Bsd::default_stack_size(thr_type); + + switch (thr_type) { + case os::java_thread: + // Java threads use ThreadStackSize which default value can be + // changed with the flag -Xss + assert (JavaThread::stack_size_at_create() > 0, "this should be set"); + stack_size = JavaThread::stack_size_at_create(); + break; + case os::compiler_thread: + if (CompilerThreadStackSize > 0) { + stack_size = (size_t)(CompilerThreadStackSize * K); + break; + } // else fall through: + // use VMThreadStackSize if CompilerThreadStackSize is not defined + case os::vm_thread: + case os::pgc_thread: + case os::cgc_thread: + case os::watcher_thread: + if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K); + break; + } + } + + stack_size = MAX2(stack_size, os::Bsd::min_stack_allowed); + pthread_attr_setstacksize(&attr, stack_size); + } else { + // let pthread_create() pick the default value. + } + +#ifndef _ALLBSD_SOURCE + // glibc guard page + pthread_attr_setguardsize(&attr, os::Bsd::default_guard_size(thr_type)); +#endif + + ThreadState state; + + { + +#ifndef _ALLBSD_SOURCE + // Serialize thread creation if we are running with fixed stack BsdThreads + bool lock = os::Bsd::is_BsdThreads() && !os::Bsd::is_floating_stack(); + if (lock) { + os::Bsd::createThread_lock()->lock_without_safepoint_check(); + } +#endif + + pthread_t tid; + int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread); + + pthread_attr_destroy(&attr); + + if (ret != 0) { + if (PrintMiscellaneous && (Verbose || WizardMode)) { + perror("pthread_create()"); + } + // Need to clean up stuff we've allocated so far + thread->set_osthread(NULL); + delete osthread; +#ifndef _ALLBSD_SOURCE + if (lock) os::Bsd::createThread_lock()->unlock(); +#endif + return false; + } + + // Store pthread info into the OSThread + osthread->set_pthread_id(tid); + + // Wait until child thread is either initialized or aborted + { + Monitor* sync_with_child = osthread->startThread_lock(); + MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag); + while ((state = osthread->get_state()) == ALLOCATED) { + sync_with_child->wait(Mutex::_no_safepoint_check_flag); + } + } + +#ifndef _ALLBSD_SOURCE + if (lock) { + os::Bsd::createThread_lock()->unlock(); + } +#endif + } + + // Aborted due to thread limit being reached + if (state == ZOMBIE) { + thread->set_osthread(NULL); + delete osthread; + return false; + } + + // The thread is returned suspended (in state INITIALIZED), + // and is started higher up in the call chain + assert(state == INITIALIZED, "race condition"); + return true; +} + +///////////////////////////////////////////////////////////////////////////// +// attach existing thread + +// bootstrap the main thread +bool os::create_main_thread(JavaThread* thread) { + assert(os::Bsd::_main_thread == pthread_self(), "should be called inside main thread"); + return create_attached_thread(thread); +} + +bool os::create_attached_thread(JavaThread* thread) { +#ifdef ASSERT + thread->verify_not_published(); +#endif + + // Allocate the OSThread object + OSThread* osthread = new OSThread(NULL, NULL); + + if (osthread == NULL) { + return false; + } + + // Store pthread info into the OSThread +#ifdef _ALLBSD_SOURCE + osthread->set_thread_id(::pthread_self()); +#else + osthread->set_thread_id(os::Bsd::gettid()); +#endif + osthread->set_pthread_id(::pthread_self()); + + // initialize floating point control register + os::Bsd::init_thread_fpu_state(); + + // Initial thread state is RUNNABLE + osthread->set_state(RUNNABLE); + + thread->set_osthread(osthread); + +#ifndef _ALLBSD_SOURCE + if (UseNUMA) { + int lgrp_id = os::numa_get_group_id(); + if (lgrp_id != -1) { + thread->set_lgrp_id(lgrp_id); + } + } + + if (os::Bsd::is_initial_thread()) { + // If current thread is initial thread, its stack is mapped on demand, + // see notes about MAP_GROWSDOWN. Here we try to force kernel to map + // the entire stack region to avoid SEGV in stack banging. + // It is also useful to get around the heap-stack-gap problem on SuSE + // kernel (see 4821821 for details). We first expand stack to the top + // of yellow zone, then enable stack yellow zone (order is significant, + // enabling yellow zone first will crash JVM on SuSE Bsd), so there + // is no gap between the last two virtual memory regions. + + JavaThread *jt = (JavaThread *)thread; + address addr = jt->stack_yellow_zone_base(); + assert(addr != NULL, "initialization problem?"); + assert(jt->stack_available(addr) > 0, "stack guard should not be enabled"); + + osthread->set_expanding_stack(); + os::Bsd::manually_expand_stack(jt, addr); + osthread->clear_expanding_stack(); + } +#endif + + // initialize signal mask for this thread + // and save the caller's signal mask + os::Bsd::hotspot_sigmask(thread); + + return true; +} + +void os::pd_start_thread(Thread* thread) { + OSThread * osthread = thread->osthread(); + assert(osthread->get_state() != INITIALIZED, "just checking"); + Monitor* sync_with_child = osthread->startThread_lock(); + MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag); + sync_with_child->notify(); +} + +// Free Bsd resources related to the OSThread +void os::free_thread(OSThread* osthread) { + assert(osthread != NULL, "osthread not set"); + + if (Thread::current()->osthread() == osthread) { + // Restore caller's signal mask + sigset_t sigmask = osthread->caller_sigmask(); + pthread_sigmask(SIG_SETMASK, &sigmask, NULL); + } + + delete osthread; +} + +////////////////////////////////////////////////////////////////////////////// +// thread local storage + +int os::allocate_thread_local_storage() { + pthread_key_t key; + int rslt = pthread_key_create(&key, NULL); + assert(rslt == 0, "cannot allocate thread local storage"); + return (int)key; +} + +// Note: This is currently not used by VM, as we don't destroy TLS key +// on VM exit. +void os::free_thread_local_storage(int index) { + int rslt = pthread_key_delete((pthread_key_t)index); + assert(rslt == 0, "invalid index"); +} + +void os::thread_local_storage_at_put(int index, void* value) { + int rslt = pthread_setspecific((pthread_key_t)index, value); + assert(rslt == 0, "pthread_setspecific failed"); +} + +extern "C" Thread* get_thread() { + return ThreadLocalStorage::thread(); +} + +////////////////////////////////////////////////////////////////////////////// +// initial thread + +#ifndef _ALLBSD_SOURCE +// Check if current thread is the initial thread, similar to Solaris thr_main. +bool os::Bsd::is_initial_thread(void) { + char dummy; + // If called before init complete, thread stack bottom will be null. + // Can be called if fatal error occurs before initialization. + if (initial_thread_stack_bottom() == NULL) return false; + assert(initial_thread_stack_bottom() != NULL && + initial_thread_stack_size() != 0, + "os::init did not locate initial thread's stack region"); + if ((address)&dummy >= initial_thread_stack_bottom() && + (address)&dummy < initial_thread_stack_bottom() + initial_thread_stack_size()) + return true; + else return false; +} + +// Find the virtual memory area that contains addr +static bool find_vma(address addr, address* vma_low, address* vma_high) { + FILE *fp = fopen("/proc/self/maps", "r"); + if (fp) { + address low, high; + while (!feof(fp)) { + if (fscanf(fp, "%p-%p", &low, &high) == 2) { + if (low <= addr && addr < high) { + if (vma_low) *vma_low = low; + if (vma_high) *vma_high = high; + fclose (fp); + return true; + } + } + for (;;) { + int ch = fgetc(fp); + if (ch == EOF || ch == (int)'\n') break; + } + } + fclose(fp); + } + return false; +} + +// Locate initial thread stack. This special handling of initial thread stack +// is needed because pthread_getattr_np() on most (all?) Bsd distros returns +// bogus value for initial thread. +void os::Bsd::capture_initial_stack(size_t max_size) { + // stack size is the easy part, get it from RLIMIT_STACK + size_t stack_size; + struct rlimit rlim; + getrlimit(RLIMIT_STACK, &rlim); + stack_size = rlim.rlim_cur; + + // 6308388: a bug in ld.so will relocate its own .data section to the + // lower end of primordial stack; reduce ulimit -s value a little bit + // so we won't install guard page on ld.so's data section. + stack_size -= 2 * page_size(); + + // 4441425: avoid crash with "unlimited" stack size on SuSE 7.1 or Redhat + // 7.1, in both cases we will get 2G in return value. + // 4466587: glibc 2.2.x compiled w/o "--enable-kernel=2.4.0" (RH 7.0, + // SuSE 7.2, Debian) can not handle alternate signal stack correctly + // 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 + + // 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 + // a global variable "__libc_stack_end", which is then used by system + // libraries. __libc_stack_end should be pretty close to stack top. The + // variable is available since the very early days. However, because it is + // a private interface, it could disappear in the future. + // + // Bsd kernel saves start_stack information in /proc/<pid>/stat. Similar + // to __libc_stack_end, it is very close to stack top, but isn't the real + // stack top. Note that /proc may not exist if VM is running as a chroot + // program, so reading /proc/<pid>/stat could fail. Also the contents of + // /proc/<pid>/stat could change in the future (though unlikely). + // + // We try __libc_stack_end first. If that doesn't work, look for + // /proc/<pid>/stat. If neither of them works, we use current stack pointer + // as a hint, which should work well in most cases. + + uintptr_t stack_start; + + // try __libc_stack_end first + uintptr_t *p = (uintptr_t *)dlsym(RTLD_DEFAULT, "__libc_stack_end"); + if (p && *p) { + stack_start = *p; + } else { + // see if we can get the start_stack field from /proc/self/stat + FILE *fp; + int pid; + char state; + int ppid; + int pgrp; + int session; + int nr; + int tpgrp; + unsigned long flags; + unsigned long minflt; + unsigned long cminflt; + unsigned long majflt; + unsigned long cmajflt; + unsigned long utime; + unsigned long stime; + long cutime; + long cstime; + long prio; + long nice; + long junk; + long it_real; + uintptr_t start; + uintptr_t vsize; + intptr_t rss; + uintptr_t rsslim; + uintptr_t scodes; + uintptr_t ecode; + int i; + + // Figure what the primordial thread stack base is. Code is inspired + // by email from Hans Boehm. /proc/self/stat begins with current pid, + // followed by command name surrounded by parentheses, state, etc. + char stat[2048]; + int statlen; + + fp = fopen("/proc/self/stat", "r"); + if (fp) { + statlen = fread(stat, 1, 2047, fp); + stat[statlen] = '\0'; + fclose(fp); + + // Skip pid and the command string. Note that we could be dealing with + // weird command names, e.g. user could decide to rename java launcher + // to "java 1.4.2 :)", then the stat file would look like + // 1234 (java 1.4.2 :)) R ... ... + // 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. + char * s = strrchr(stat, ')'); + + i = 0; + if (s) { + // Skip blank chars + do s++; while (isspace(*s)); + +#define _UFM UINTX_FORMAT +#define _DFM INTX_FORMAT + + /* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 */ + /* 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 */ + i = sscanf(s, "%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld " _UFM _UFM _DFM _UFM _UFM _UFM _UFM, + &state, /* 3 %c */ + &ppid, /* 4 %d */ + &pgrp, /* 5 %d */ + &session, /* 6 %d */ + &nr, /* 7 %d */ + &tpgrp, /* 8 %d */ + &flags, /* 9 %lu */ + &minflt, /* 10 %lu */ + &cminflt, /* 11 %lu */ + &majflt, /* 12 %lu */ + &cmajflt, /* 13 %lu */ + &utime, /* 14 %lu */ + &stime, /* 15 %lu */ + &cutime, /* 16 %ld */ + &cstime, /* 17 %ld */ + &prio, /* 18 %ld */ + &nice, /* 19 %ld */ + &junk, /* 20 %ld */ + &it_real, /* 21 %ld */ + &start, /* 22 UINTX_FORMAT */ + &vsize, /* 23 UINTX_FORMAT */ + &rss, /* 24 INTX_FORMAT */ + &rsslim, /* 25 UINTX_FORMAT */ + &scodes, /* 26 UINTX_FORMAT */ + &ecode, /* 27 UINTX_FORMAT */ + &stack_start); /* 28 UINTX_FORMAT */ + } + +#undef _UFM +#undef _DFM + + if (i != 28 - 2) { + assert(false, "Bad conversion from /proc/self/stat"); + // product mode - assume we are the initial thread, good luck in the + // embedded case. + warning("Can't detect initial thread stack location - bad conversion"); + stack_start = (uintptr_t) &rlim; + } + } else { + // For some reason we can't open /proc/self/stat (for example, running on + // FreeBSD with a Bsd emulator, or inside chroot), this should work for + // most cases, so don't abort: + warning("Can't detect initial thread stack location - no /proc/self/stat"); + stack_start = (uintptr_t) &rlim; + } + } + + // Now we have a pointer (stack_start) very close to the stack top, the + // next thing to do is to figure out the exact location of stack top. We + // can find out the virtual memory area that contains stack_start by + // reading /proc/self/maps, it should be the last vma in /proc/self/maps, + // and its upper limit is the real stack top. (again, this would fail if + // running inside chroot, because /proc may not exist.) + + uintptr_t stack_top; + address low, high; + if (find_vma((address)stack_start, &low, &high)) { + // success, "high" is the true stack top. (ignore "low", because initial + // thread stack grows on demand, its real bottom is high - RLIMIT_STACK.) + stack_top = (uintptr_t)high; + } else { + // failed, likely because /proc/self/maps does not exist + warning("Can't detect initial thread stack location - find_vma failed"); + // best effort: stack_start is normally within a few pages below the real + // stack top, use it as stack top, and reduce stack size so we won't put + // guard page outside stack. + stack_top = stack_start; + stack_size -= 16 * page_size(); + } + + // stack_top could be partially down the page so align it + stack_top = align_size_up(stack_top, page_size()); + + if (max_size && stack_size > max_size) { + _initial_thread_stack_size = max_size; + } else { + _initial_thread_stack_size = stack_size; + } + + _initial_thread_stack_size = align_size_down(_initial_thread_stack_size, page_size()); + _initial_thread_stack_bottom = (address)stack_top - _initial_thread_stack_size; +} +#endif + +//////////////////////////////////////////////////////////////////////////////// +// time support + +// Time since start-up in seconds to a fine granularity. +// Used by VMSelfDestructTimer and the MemProfiler. +double os::elapsedTime() { + + return (double)(os::elapsed_counter()) * 0.000001; +} + +jlong os::elapsed_counter() { + timeval time; + int status = gettimeofday(&time, NULL); + return jlong(time.tv_sec) * 1000 * 1000 + jlong(time.tv_usec) - initial_time_count; +} + +jlong os::elapsed_frequency() { + return (1000 * 1000); +} + +// XXX: For now, code this as if BSD does not support vtime. +bool os::supports_vtime() { return false; } +bool os::enable_vtime() { return false; } +bool os::vtime_enabled() { return false; } +double os::elapsedVTime() { + // better than nothing, but not much + return elapsedTime(); +} + +jlong os::javaTimeMillis() { + timeval time; + int status = gettimeofday(&time, NULL); + assert(status != -1, "bsd error"); + return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000); +} + +#ifndef CLOCK_MONOTONIC +#define CLOCK_MONOTONIC (1) +#endif + +#ifdef __APPLE__ +void os::Bsd::clock_init() { + // XXXDARWIN: Investigate replacement monotonic clock +} +#elif defined(_ALLBSD_SOURCE) +void os::Bsd::clock_init() { + struct timespec res; + struct timespec tp; + if (::clock_getres(CLOCK_MONOTONIC, &res) == 0 && + ::clock_gettime(CLOCK_MONOTONIC, &tp) == 0) { + // yes, monotonic clock is supported + _clock_gettime = ::clock_gettime; + } +} +#else +void os::Bsd::clock_init() { + // we do dlopen's in this particular order due to bug in bsd + // dynamical loader (see 6348968) leading to crash on exit + void* handle = dlopen("librt.so.1", RTLD_LAZY); + if (handle == NULL) { + handle = dlopen("librt.so", RTLD_LAZY); + } + + if (handle) { + int (*clock_getres_func)(clockid_t, struct timespec*) = + (int(*)(clockid_t, struct timespec*))dlsym(handle, "clock_getres"); + int (*clock_gettime_func)(clockid_t, struct timespec*) = + (int(*)(clockid_t, struct timespec*))dlsym(handle, "clock_gettime"); + if (clock_getres_func && clock_gettime_func) { + // See if monotonic clock is supported by the kernel. Note that some + // early implementations simply return kernel jiffies (updated every + // 1/100 or 1/1000 second). It would be bad to use such a low res clock + // for nano time (though the monotonic property is still nice to have). + // It's fixed in newer kernels, however clock_getres() still returns + // 1/HZ. We check if clock_getres() works, but will ignore its reported + // resolution for now. Hopefully as people move to new kernels, this + // won't be a problem. + struct timespec res; + struct timespec tp; + if (clock_getres_func (CLOCK_MONOTONIC, &res) == 0 && + clock_gettime_func(CLOCK_MONOTONIC, &tp) == 0) { + // yes, monotonic clock is supported + _clock_gettime = clock_gettime_func; + } else { + // close librt if there is no monotonic clock + dlclose(handle); + } + } + } +} +#endif + +#ifndef _ALLBSD_SOURCE +#ifndef SYS_clock_getres + +#if defined(IA32) || defined(AMD64) +#define SYS_clock_getres IA32_ONLY(266) AMD64_ONLY(229) +#define sys_clock_getres(x,y) ::syscall(SYS_clock_getres, x, y) +#else +#warning "SYS_clock_getres not defined for this platform, disabling fast_thread_cpu_time" +#define sys_clock_getres(x,y) -1 +#endif + +#else +#define sys_clock_getres(x,y) ::syscall(SYS_clock_getres, x, y) +#endif + +void os::Bsd::fast_thread_clock_init() { + if (!UseBsdPosixThreadCPUClocks) { + return; + } + clockid_t clockid; + struct timespec tp; + int (*pthread_getcpuclockid_func)(pthread_t, clockid_t *) = + (int(*)(pthread_t, clockid_t *)) dlsym(RTLD_DEFAULT, "pthread_getcpuclockid"); + + // Switch to using fast clocks for thread cpu time if + // the sys_clock_getres() returns 0 error code. + // Note, that some kernels may support the current thread + // clock (CLOCK_THREAD_CPUTIME_ID) but not the clocks + // returned by the pthread_getcpuclockid(). + // If the fast Posix clocks are supported then the sys_clock_getres() + // must return at least tp.tv_sec == 0 which means a resolution + // better than 1 sec. This is extra check for reliability. + + if(pthread_getcpuclockid_func && + pthread_getcpuclockid_func(_main_thread, &clockid) == 0 && + sys_clock_getres(clockid, &tp) == 0 && tp.tv_sec == 0) { + + _supports_fast_thread_cpu_time = true; + _pthread_getcpuclockid = pthread_getcpuclockid_func; + } +} +#endif + +jlong os::javaTimeNanos() { + if (Bsd::supports_monotonic_clock()) { + struct timespec tp; + int status = Bsd::clock_gettime(CLOCK_MONOTONIC, &tp); + assert(status == 0, "gettime error"); + jlong result = jlong(tp.tv_sec) * (1000 * 1000 * 1000) + jlong(tp.tv_nsec); + return result; + } else { + timeval time; + int status = gettimeofday(&time, NULL); + assert(status != -1, "bsd error"); + jlong usecs = jlong(time.tv_sec) * (1000 * 1000) + jlong(time.tv_usec); + return 1000 * usecs; + } +} + +void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) { + if (Bsd::supports_monotonic_clock()) { + info_ptr->max_value = ALL_64_BITS; + + // CLOCK_MONOTONIC - amount of time since some arbitrary point in the past + info_ptr->may_skip_backward = false; // not subject to resetting or drifting + info_ptr->may_skip_forward = false; // not subject to resetting or drifting + } else { + // gettimeofday - based on time in seconds since the Epoch thus does not wrap + info_ptr->max_value = ALL_64_BITS; + + // gettimeofday is a real time clock so it skips + info_ptr->may_skip_backward = true; + info_ptr->may_skip_forward = true; + } + + info_ptr->kind = JVMTI_TIMER_ELAPSED; // elapsed not CPU time +} + +// Return the real, user, and system times in seconds from an +// arbitrary fixed point in the past. +bool os::getTimesSecs(double* process_real_time, + double* process_user_time, + double* process_system_time) { + struct tms ticks; + clock_t real_ticks = times(&ticks); + + if (real_ticks == (clock_t) (-1)) { + return false; + } else { + double ticks_per_second = (double) clock_tics_per_sec; + *process_user_time = ((double) ticks.tms_utime) / ticks_per_second; + *process_system_time = ((double) ticks.tms_stime) / ticks_per_second; + *process_real_time = ((double) real_ticks) / ticks_per_second; + + return true; + } +} + + +char * os::local_time_string(char *buf, size_t buflen) { + struct tm t; + time_t long_time; + time(&long_time); + localtime_r(&long_time, &t); + jio_snprintf(buf, buflen, "%d-%02d-%02d %02d:%02d:%02d", + t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, + t.tm_hour, t.tm_min, t.tm_sec); + return buf; +} + +struct tm* os::localtime_pd(const time_t* clock, struct tm* res) { + return localtime_r(clock, res); +} + +//////////////////////////////////////////////////////////////////////////////// +// runtime exit support + +// Note: os::shutdown() might be called very early during initialization, or +// called from signal handler. Before adding something to os::shutdown(), make +// sure it is async-safe and can handle partially initialized VM. +void os::shutdown() { + + // allow PerfMemory to attempt cleanup of any persistent resources + perfMemory_exit(); + + // needs to remove object in file system + AttachListener::abort(); + + // flush buffered output, finish log files + ostream_abort(); + + // Check for abort hook + abort_hook_t abort_hook = Arguments::abort_hook(); + if (abort_hook != NULL) { + abort_hook(); + } + +} + +// Note: os::abort() might be called very early during initialization, or +// called from signal handler. Before adding something to os::abort(), make +// sure it is async-safe and can handle partially initialized VM. +void os::abort(bool dump_core) { + os::shutdown(); + if (dump_core) { +#ifndef PRODUCT + fdStream out(defaultStream::output_fd()); + out.print_raw("Current thread is "); + char buf[16]; + jio_snprintf(buf, sizeof(buf), UINTX_FORMAT, os::current_thread_id()); + out.print_raw_cr(buf); + out.print_raw_cr("Dumping core ..."); +#endif + ::abort(); // dump core + } + + ::exit(1); +} + +// Die immediately, no exit hook, no abort hook, no cleanup. +void os::die() { + // _exit() on BsdThreads only kills current thread + ::abort(); +} + +// unused on bsd for now. +void os::set_error_file(const char *logfile) {} + + +// This method is a copy of JDK's sysGetLastErrorString +// from src/solaris/hpi/src/system_md.c + +size_t os::lasterror(char *buf, size_t len) { + + if (errno == 0) return 0; + + const char *s = ::strerror(errno); + size_t n = ::strlen(s); + if (n >= len) { + n = len - 1; + } + ::strncpy(buf, s, n); + buf[n] = '\0'; + return n; +} + +intx os::current_thread_id() { return (intx)pthread_self(); } +int os::current_process_id() { + + // Under the old bsd thread library, bsd gives each thread + // its own process id. Because of this each thread will return + // a different pid if this method were to return the result + // of getpid(2). Bsd provides no api that returns the pid + // of the launcher thread for the vm. This implementation + // returns a unique pid, the pid of the launcher thread + // that starts the vm 'process'. + + // Under the NPTL, getpid() returns the same pid as the + // launcher thread rather than a unique pid per thread. + // Use gettid() if you want the old pre NPTL behaviour. + + // if you are looking for the result of a call to getpid() that + // returns a unique pid for the calling thread, then look at the + // OSThread::thread_id() method in osThread_bsd.hpp file + + return (int)(_initial_pid ? _initial_pid : getpid()); +} + +// DLL functions + +#define JNI_LIB_PREFIX "lib" +#ifdef __APPLE__ +#define JNI_LIB_SUFFIX ".dylib" +#else +#define JNI_LIB_SUFFIX ".so" +#endif + +const char* os::dll_file_extension() { return JNI_LIB_SUFFIX; } + +// This must be hard coded because it's the system's temporary +// directory not the java application's temp directory, ala java.io.tmpdir. +#ifdef __APPLE__ +// macosx has a secure per-user temporary directory +char temp_path_storage[PATH_MAX]; +const char* os::get_temp_directory() { + static char *temp_path = NULL; + if (temp_path == NULL) { + int pathSize = confstr(_CS_DARWIN_USER_TEMP_DIR, temp_path_storage, PATH_MAX); + if (pathSize == 0 || pathSize > PATH_MAX) { + strlcpy(temp_path_storage, "/tmp/", sizeof(temp_path_storage)); + } + temp_path = temp_path_storage; + } + return temp_path; +} +#else /* __APPLE__ */ +const char* os::get_temp_directory() { return "/tmp"; } +#endif /* __APPLE__ */ + +static bool file_exists(const char* filename) { + struct stat statbuf; + if (filename == NULL || strlen(filename) == 0) { + return false; + } + return os::stat(filename, &statbuf) == 0; +} + +void os::dll_build_name(char* buffer, size_t buflen, + const char* pname, const char* fname) { + // Copied from libhpi + const size_t pnamelen = pname ? strlen(pname) : 0; + + // Quietly truncate on buffer overflow. Should be an error. + if (pnamelen + strlen(fname) + strlen(JNI_LIB_PREFIX) + strlen(JNI_LIB_SUFFIX) + 2 > buflen) { + *buffer = '\0'; + return; + } + + if (pnamelen == 0) { + snprintf(buffer, buflen, JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, fname); + } else if (strchr(pname, *os::path_separator()) != NULL) { + int n; + char** pelements = split_path(pname, &n); + for (int i = 0 ; i < n ; i++) { + // Really shouldn't be NULL, but check can't hurt + if (pelements[i] == NULL || strlen(pelements[i]) == 0) { + continue; // skip the empty path values + } + snprintf(buffer, buflen, "%s/" JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, + pelements[i], fname); + if (file_exists(buffer)) { + break; + } + } + // release the storage + for (int i = 0 ; i < n ; i++) { + if (pelements[i] != NULL) { + FREE_C_HEAP_ARRAY(char, pelements[i]); + } + } + if (pelements != NULL) { + FREE_C_HEAP_ARRAY(char*, pelements); + } + } else { + snprintf(buffer, buflen, "%s/" JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, pname, fname); + } +} + +const char* os::get_current_directory(char *buf, int buflen) { + return getcwd(buf, buflen); +} + +// check if addr is inside libjvm[_g].so +bool os::address_is_in_vm(address addr) { + static address libjvm_base_addr; + Dl_info dlinfo; + + if (libjvm_base_addr == NULL) { + dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo); + libjvm_base_addr = (address)dlinfo.dli_fbase; + assert(libjvm_base_addr !=NULL, "Cannot obtain base address for libjvm"); + } + + if (dladdr((void *)addr, &dlinfo)) { + if (libjvm_base_addr == (address)dlinfo.dli_fbase) return true; + } + + return false; +} + +bool os::dll_address_to_function_name(address addr, char *buf, + int buflen, int *offset) { + Dl_info dlinfo; + + if (dladdr((void*)addr, &dlinfo) && dlinfo.dli_sname != NULL) { + if (buf != NULL) { + if(!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) { + jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname); + } + } + if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr; + return true; + } else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) { + if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), + dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) { + return true; + } + } + + if (buf != NULL) buf[0] = '\0'; + if (offset != NULL) *offset = -1; + return false; +} + +#ifdef _ALLBSD_SOURCE +// ported from solaris version +bool os::dll_address_to_library_name(address addr, char* buf, + int buflen, int* offset) { + Dl_info dlinfo; + + if (dladdr((void*)addr, &dlinfo)){ + if (buf) jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname); + if (offset) *offset = addr - (address)dlinfo.dli_fbase; + return true; + } else { + if (buf) buf[0] = '\0'; + if (offset) *offset = -1; + return false; + } +} +#else +struct _address_to_library_name { + address addr; // input : memory address + size_t buflen; // size of fname + char* fname; // output: library name + address base; // library base addr +}; + +static int address_to_library_name_callback(struct dl_phdr_info *info, + size_t size, void *data) { + int i; + bool found = false; + address libbase = NULL; + struct _address_to_library_name * d = (struct _address_to_library_name *)data; + + // iterate through all loadable segments + for (i = 0; i < info->dlpi_phnum; i++) { + address segbase = (address)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr); + if (info->dlpi_phdr[i].p_type == PT_LOAD) { + // base address of a library is the lowest address of its loaded + // segments. + if (libbase == NULL || libbase > segbase) { + libbase = segbase; + } + // see if 'addr' is within current segment + if (segbase <= d->addr && + d->addr < segbase + info->dlpi_phdr[i].p_memsz) { + found = true; + } + } + } + + // dlpi_name is NULL or empty if the ELF file is executable, return 0 + // so dll_address_to_library_name() can fall through to use dladdr() which + // can figure out executable name from argv[0]. + if (found && info->dlpi_name && info->dlpi_name[0]) { + d->base = libbase; + if (d->fname) { + jio_snprintf(d->fname, d->buflen, "%s", info->dlpi_name); + } + return 1; + } + return 0; +} + +bool os::dll_address_to_library_name(address addr, char* buf, + int buflen, int* offset) { + Dl_info dlinfo; + struct _address_to_library_name data; + + // There is a bug in old glibc dladdr() implementation that it could resolve + // to wrong library name if the .so file has a base address != NULL. Here + // we iterate through the program headers of all loaded libraries to find + // out which library 'addr' really belongs to. This workaround can be + // removed once the minimum requirement for glibc is moved to 2.3.x. + data.addr = addr; + data.fname = buf; + data.buflen = buflen; + data.base = NULL; + int rslt = dl_iterate_phdr(address_to_library_name_callback, (void *)&data); + + if (rslt) { + // buf already contains library name + if (offset) *offset = addr - data.base; + return true; + } else if (dladdr((void*)addr, &dlinfo)){ + if (buf) jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname); + if (offset) *offset = addr - (address)dlinfo.dli_fbase; + return true; + } else { + if (buf) buf[0] = '\0'; + if (offset) *offset = -1; + return false; + } +} +#endif + + // Loads .dll/.so and + // in case of error it checks if .dll/.so was built for the + // same architecture as Hotspot is running on + +#ifdef __APPLE__ +void * os::dll_load(const char *filename, char *ebuf, int ebuflen) { + void * result= ::dlopen(filename, RTLD_LAZY); + if (result != NULL) { + // Successful loading + return result; + } + + // Read system error message into ebuf + ::strncpy(ebuf, ::dlerror(), ebuflen-1); + ebuf[ebuflen-1]='\0'; + + return NULL; +} +#else +void * os::dll_load(const char *filename, char *ebuf, int ebuflen) +{ + void * result= ::dlopen(filename, RTLD_LAZY); + if (result != NULL) { + // Successful loading + return result; + } + + Elf32_Ehdr elf_head; + + // Read system error message into ebuf + // It may or may not be overwritten below + ::strncpy(ebuf, ::dlerror(), ebuflen-1); + ebuf[ebuflen-1]='\0'; + int diag_msg_max_length=ebuflen-strlen(ebuf); + char* diag_msg_buf=ebuf+strlen(ebuf); + + if (diag_msg_max_length==0) { + // No more space in ebuf for additional diagnostics message + return NULL; + } + + + int file_descriptor= ::open(filename, O_RDONLY | O_NONBLOCK); + + if (file_descriptor < 0) { + // Can't open library, report dlerror() message + return NULL; + } + + bool failed_to_read_elf_head= + (sizeof(elf_head)!= + (::read(file_descriptor, &elf_head,sizeof(elf_head)))) ; + + ::close(file_descriptor); + if (failed_to_read_elf_head) { + // file i/o error - report dlerror() msg + return NULL; + } + + typedef struct { + Elf32_Half code; // Actual value as defined in elf.h + Elf32_Half compat_class; // Compatibility of archs at VM's sense + char elf_class; // 32 or 64 bit + char endianess; // MSB or LSB + char* name; // String representation + } arch_t; + + #ifndef EM_486 + #define EM_486 6 /* Intel 80486 */ + #endif + + #ifndef EM_MIPS_RS3_LE + #define EM_MIPS_RS3_LE 10 /* MIPS */ + #endif + + #ifndef EM_PPC64 + #define EM_PPC64 21 /* PowerPC64 */ + #endif + + #ifndef EM_S390 + #define EM_S390 22 /* IBM System/390 */ + #endif + + #ifndef EM_IA_64 + #define EM_IA_64 50 /* HP/Intel IA-64 */ + #endif + + #ifndef EM_X86_64 + #define EM_X86_64 62 /* AMD x86-64 */ + #endif + + static const arch_t arch_array[]={ + {EM_386, EM_386, ELFCLASS32, ELFDATA2LSB, (char*)"IA 32"}, + {EM_486, EM_386, ELFCLASS32, ELFDATA2LSB, (char*)"IA 32"}, + {EM_IA_64, EM_IA_64, ELFCLASS64, ELFDATA2LSB, (char*)"IA 64"}, + {EM_X86_64, EM_X86_64, ELFCLASS64, ELFDATA2LSB, (char*)"AMD 64"}, + {EM_SPARC, EM_SPARC, ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"}, + {EM_SPARC32PLUS, EM_SPARC, ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"}, + {EM_SPARCV9, EM_SPARCV9, ELFCLASS64, ELFDATA2MSB, (char*)"Sparc v9 64"}, + {EM_PPC, EM_PPC, ELFCLASS32, ELFDATA2MSB, (char*)"Power PC 32"}, + {EM_PPC64, EM_PPC64, ELFCLASS64, ELFDATA2MSB, (char*)"Power PC 64"}, + {EM_ARM, EM_ARM, ELFCLASS32, ELFDATA2LSB, (char*)"ARM"}, + {EM_S390, EM_S390, ELFCLASSNONE, ELFDATA2MSB, (char*)"IBM System/390"}, + {EM_ALPHA, EM_ALPHA, ELFCLASS64, ELFDATA2LSB, (char*)"Alpha"}, + {EM_MIPS_RS3_LE, EM_MIPS_RS3_LE, ELFCLASS32, ELFDATA2LSB, (char*)"MIPSel"}, + {EM_MIPS, EM_MIPS, ELFCLASS32, ELFDATA2MSB, (char*)"MIPS"}, + {EM_PARISC, EM_PARISC, ELFCLASS32, ELFDATA2MSB, (char*)"PARISC"}, + {EM_68K, EM_68K, ELFCLASS32, ELFDATA2MSB, (char*)"M68k"} + }; + + #if (defined IA32) + static Elf32_Half running_arch_code=EM_386; + #elif (defined AMD64) + static Elf32_Half running_arch_code=EM_X86_64; + #elif (defined IA64) + static Elf32_Half running_arch_code=EM_IA_64; + #elif (defined __sparc) && (defined _LP64) + static Elf32_Half running_arch_code=EM_SPARCV9; + #elif (defined __sparc) && (!defined _LP64) + static Elf32_Half running_arch_code=EM_SPARC; + #elif (defined __powerpc64__) + static Elf32_Half running_arch_code=EM_PPC64; + #elif (defined __powerpc__) + static Elf32_Half running_arch_code=EM_PPC; + #elif (defined ARM) + static Elf32_Half running_arch_code=EM_ARM; + #elif (defined S390) + static Elf32_Half running_arch_code=EM_S390; + #elif (defined ALPHA) + static Elf32_Half running_arch_code=EM_ALPHA; + #elif (defined MIPSEL) + static Elf32_Half running_arch_code=EM_MIPS_RS3_LE; + #elif (defined PARISC) + static Elf32_Half running_arch_code=EM_PARISC; + #elif (defined MIPS) + static Elf32_Half running_arch_code=EM_MIPS; + #elif (defined M68K) + static Elf32_Half running_arch_code=EM_68K; + #else + #error Method os::dll_load requires that one of following is defined:\ + IA32, AMD64, IA64, __sparc, __powerpc__, ARM, S390, ALPHA, MIPS, MIPSEL, PARISC, M68K + #endif + + // Identify compatability class for VM's architecture and library's architecture + // Obtain string descriptions for architectures + + arch_t lib_arch={elf_head.e_machine,0,elf_head.e_ident[EI_CLASS], elf_head.e_ident[EI_DATA], NULL}; + int running_arch_index=-1; + + for (unsigned int i=0 ; i < ARRAY_SIZE(arch_array) ; i++ ) { + if (running_arch_code == arch_array[i].code) { + running_arch_index = i; + } + if (lib_arch.code == arch_array[i].code) { + lib_arch.compat_class = arch_array[i].compat_class; + lib_arch.name = arch_array[i].name; + } + } + + assert(running_arch_index != -1, + "Didn't find running architecture code (running_arch_code) in arch_array"); + if (running_arch_index == -1) { + // Even though running architecture detection failed + // we may still continue with reporting dlerror() message + return NULL; + } + + if (lib_arch.endianess != arch_array[running_arch_index].endianess) { + ::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: endianness mismatch)"); + return NULL; + } + +#ifndef S390 + if (lib_arch.elf_class != arch_array[running_arch_index].elf_class) { + ::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: architecture word width mismatch)"); + return NULL; + } +#endif // !S390 + + if (lib_arch.compat_class != arch_array[running_arch_index].compat_class) { + if ( lib_arch.name!=NULL ) { + ::snprintf(diag_msg_buf, diag_msg_max_length-1, + " (Possible cause: can't load %s-bit .so on a %s-bit platform)", + lib_arch.name, arch_array[running_arch_index].name); + } else { + ::snprintf(diag_msg_buf, diag_msg_max_length-1, + " (Possible cause: can't load this .so (machine code=0x%x) on a %s-bit platform)", + lib_arch.code, + arch_array[running_arch_index].name); + } + } + + return NULL; +} +#endif /* !__APPLE__ */ + +// XXX: Do we need a lock around this as per Linux? +void* os::dll_lookup(void* handle, const char* name) { + return dlsym(handle, name); +} + + +static bool _print_ascii_file(const char* filename, outputStream* st) { + int fd = ::open(filename, O_RDONLY); + if (fd == -1) { + return false; + } + + char buf[32]; + int bytes; + while ((bytes = ::read(fd, buf, sizeof(buf))) > 0) { + st->print_raw(buf, bytes); + } + + ::close(fd); + + return true; +} + +void os::print_dll_info(outputStream *st) { + st->print_cr("Dynamic libraries:"); +#ifdef _ALLBSD_SOURCE +#ifdef RTLD_DI_LINKMAP + Dl_info dli; + void *handle; + Link_map *map; + Link_map *p; + + if (!dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli)) { + st->print_cr("Error: Cannot print dynamic libraries."); + return; + } + handle = dlopen(dli.dli_fname, RTLD_LAZY); + if (handle == NULL) { + st->print_cr("Error: Cannot print dynamic libraries."); + return; + } + dlinfo(handle, RTLD_DI_LINKMAP, &map); + if (map == NULL) { + st->print_cr("Error: Cannot print dynamic libraries."); + return; + } + + while (map->l_prev != NULL) + map = map->l_prev; + + while (map != NULL) { + st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name); + map = map->l_next; + } + + dlclose(handle); +#elif defined(__APPLE__) + uint32_t count; + uint32_t i; + + count = _dyld_image_count(); + for (i = 1; i < count; i++) { + const char *name = _dyld_get_image_name(i); + intptr_t slide = _dyld_get_image_vmaddr_slide(i); + st->print_cr(PTR_FORMAT " \t%s", slide, name); + } +#else + st->print_cr("Error: Cannot print dynamic libraries."); +#endif +#else + char fname[32]; + pid_t pid = os::Bsd::gettid(); + + jio_snprintf(fname, sizeof(fname), "/proc/%d/maps", pid); + + if (!_print_ascii_file(fname, st)) { + st->print("Can not get library information for pid = %d\n", pid); + } +#endif +} + + +void os::print_os_info(outputStream* st) { + st->print("OS:"); + + // Try to identify popular distros. + // Most Bsd distributions have /etc/XXX-release file, which contains + // the OS version string. Some have more than one /etc/XXX-release file + // (e.g. Mandrake has both /etc/mandrake-release and /etc/redhat-release.), + // so the order is important. + if (!_print_ascii_file("/etc/mandrake-release", st) && + !_print_ascii_file("/etc/sun-release", st) && + !_print_ascii_file("/etc/redhat-release", st) && + !_print_ascii_file("/etc/SuSE-release", st) && + !_print_ascii_file("/etc/turbobsd-release", st) && + !_print_ascii_file("/etc/gentoo-release", st) && + !_print_ascii_file("/etc/debian_version", st) && + !_print_ascii_file("/etc/ltib-release", st) && + !_print_ascii_file("/etc/angstrom-version", st)) { + st->print("Bsd"); + } + st->cr(); + + // kernel + st->print("uname:"); + struct utsname name; + uname(&name); + st->print(name.sysname); st->print(" "); + st->print(name.release); st->print(" "); + st->print(name.version); st->print(" "); + st->print(name.machine); + st->cr(); + +#ifndef _ALLBSD_SOURCE + // Print warning if unsafe chroot environment detected + if (unsafe_chroot_detected) { + st->print("WARNING!! "); + st->print_cr(unstable_chroot_error); + } + + // libc, pthread + st->print("libc:"); + st->print(os::Bsd::glibc_version()); st->print(" "); + st->print(os::Bsd::libpthread_version()); st->print(" "); + if (os::Bsd::is_BsdThreads()) { + st->print("(%s stack)", os::Bsd::is_floating_stack() ? "floating" : "fixed"); + } + st->cr(); +#endif + + // rlimit + st->print("rlimit:"); + struct rlimit rlim; + + st->print(" STACK "); + getrlimit(RLIMIT_STACK, &rlim); + if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity"); + else st->print("%uk", rlim.rlim_cur >> 10); + + st->print(", CORE "); + getrlimit(RLIMIT_CORE, &rlim); + if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity"); + else st->print("%uk", rlim.rlim_cur >> 10); + + st->print(", NPROC "); + getrlimit(RLIMIT_NPROC, &rlim); + if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity"); + else st->print("%d", rlim.rlim_cur); + + st->print(", NOFILE "); + getrlimit(RLIMIT_NOFILE, &rlim); + if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity"); + else st->print("%d", rlim.rlim_cur); + +#ifndef _ALLBSD_SOURCE + st->print(", AS "); + getrlimit(RLIMIT_AS, &rlim); + if (rlim.rlim_cur == RLIM_INFINITY) st->print("infinity"); + else st->print("%uk", rlim.rlim_cur >> 10); + st->cr(); + + // load average + st->print("load average:"); + double loadavg[3]; + os::loadavg(loadavg, 3); + st->print("%0.02f %0.02f %0.02f", loadavg[0], loadavg[1], loadavg[2]); + st->cr(); +#endif +} + +void os::pd_print_cpu_info(outputStream* st) { + // Nothing to do for now. +} + +void os::print_memory_info(outputStream* st) { + + st->print("Memory:"); + st->print(" %dk page", os::vm_page_size()>>10); + +#ifndef _ALLBSD_SOURCE + // values in struct sysinfo are "unsigned long" + struct sysinfo si; + sysinfo(&si); +#endif + + st->print(", physical " UINT64_FORMAT "k", + os::physical_memory() >> 10); + st->print("(" UINT64_FORMAT "k free)", + os::available_memory() >> 10); +#ifndef _ALLBSD_SOURCE + st->print(", swap " UINT64_FORMAT "k", + ((jlong)si.totalswap * si.mem_unit) >> 10); + st->print("(" UINT64_FORMAT "k free)", + ((jlong)si.freeswap * si.mem_unit) >> 10); +#endif + st->cr(); + + // meminfo + st->print("\n/proc/meminfo:\n"); + _print_ascii_file("/proc/meminfo", st); + st->cr(); +} + +// Taken from /usr/include/bits/siginfo.h Supposed to be architecture specific +// but they're the same for all the bsd arch that we support +// and they're the same for solaris but there's no common place to put this. +const char *ill_names[] = { "ILL0", "ILL_ILLOPC", "ILL_ILLOPN", "ILL_ILLADR", + "ILL_ILLTRP", "ILL_PRVOPC", "ILL_PRVREG", + "ILL_COPROC", "ILL_BADSTK" }; + +const char *fpe_names[] = { "FPE0", "FPE_INTDIV", "FPE_INTOVF", "FPE_FLTDIV", + "FPE_FLTOVF", "FPE_FLTUND", "FPE_FLTRES", + "FPE_FLTINV", "FPE_FLTSUB", "FPE_FLTDEN" }; + +const char *segv_names[] = { "SEGV0", "SEGV_MAPERR", "SEGV_ACCERR" }; + +const char *bus_names[] = { "BUS0", "BUS_ADRALN", "BUS_ADRERR", "BUS_OBJERR" }; + +void os::print_siginfo(outputStream* st, void* siginfo) { + st->print("siginfo:"); + + const int buflen = 100; + char buf[buflen]; + siginfo_t *si = (siginfo_t*)siginfo; + st->print("si_signo=%s: ", os::exception_name(si->si_signo, buf, buflen)); + if (si->si_errno != 0 && strerror_r(si->si_errno, buf, buflen) == 0) { + st->print("si_errno=%s", buf); + } else { + st->print("si_errno=%d", si->si_errno); + } + const int c = si->si_code; + assert(c > 0, "unexpected si_code"); + switch (si->si_signo) { + case SIGILL: + st->print(", si_code=%d (%s)", c, c > 8 ? "" : ill_names[c]); + st->print(", si_addr=" PTR_FORMAT, si->si_addr); + break; + case SIGFPE: + st->print(", si_code=%d (%s)", c, c > 9 ? "" : fpe_names[c]); + st->print(", si_addr=" PTR_FORMAT, si->si_addr); + break; + case SIGSEGV: + st->print(", si_code=%d (%s)", c, c > 2 ? "" : segv_names[c]); + st->print(", si_addr=" PTR_FORMAT, si->si_addr); + break; + case SIGBUS: + st->print(", si_code=%d (%s)", c, c > 3 ? "" : bus_names[c]); + st->print(", si_addr=" PTR_FORMAT, si->si_addr); + break; + default: + st->print(", si_code=%d", si->si_code); + // no si_addr + } + + if ((si->si_signo == SIGBUS || si->si_signo == SIGSEGV) && + UseSharedSpaces) { + FileMapInfo* mapinfo = FileMapInfo::current_info(); + if (mapinfo->is_in_shared_space(si->si_addr)) { + st->print("\n\nError accessing class data sharing archive." \ + " Mapped file inaccessible during execution, " \ + " possible disk/network problem."); + } + } + st->cr(); +} + + +static void print_signal_handler(outputStream* st, int sig, + char* buf, size_t buflen); + +void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) { + st->print_cr("Signal Handlers:"); + print_signal_handler(st, SIGSEGV, buf, buflen); + print_signal_handler(st, SIGBUS , buf, buflen); + print_signal_handler(st, SIGFPE , buf, buflen); + print_signal_handler(st, SIGPIPE, buf, buflen); + print_signal_handler(st, SIGXFSZ, buf, buflen); + print_signal_handler(st, SIGILL , buf, buflen); + print_signal_handler(st, INTERRUPT_SIGNAL, buf, buflen); + print_signal_handler(st, SR_signum, buf, buflen); + print_signal_handler(st, SHUTDOWN1_SIGNAL, buf, buflen); + print_signal_handler(st, SHUTDOWN2_SIGNAL , buf, buflen); + print_signal_handler(st, SHUTDOWN3_SIGNAL , buf, buflen); + print_signal_handler(st, BREAK_SIGNAL, buf, buflen); +} + +static char saved_jvm_path[MAXPATHLEN] = {0}; + +// Find the full path to the current module, libjvm.so or libjvm_g.so +void os::jvm_path(char *buf, jint buflen) { + // Error checking. + if (buflen < MAXPATHLEN) { + assert(false, "must use a large-enough buffer"); + buf[0] = '\0'; + return; + } + // Lazy resolve the path to current module. + if (saved_jvm_path[0] != 0) { + strcpy(buf, saved_jvm_path); + return; + } + + char dli_fname[MAXPATHLEN]; + bool ret = dll_address_to_library_name( + CAST_FROM_FN_PTR(address, os::jvm_path), + dli_fname, sizeof(dli_fname), NULL); + assert(ret != 0, "cannot locate libjvm"); + char *rp = realpath(dli_fname, buf); + if (rp == NULL) + return; + + if (Arguments::created_by_gamma_launcher()) { + // Support for the gamma launcher. Typical value for buf is + // "<JAVA_HOME>/jre/lib/<arch>/<vmtype>/libjvm.so". If "/jre/lib/" appears at + // the right place in the string, then assume we are installed in a JDK and + // we're done. Otherwise, check for a JAVA_HOME environment variable and fix + // up the path so it looks like libjvm.so is installed there (append a + // fake suffix hotspot/libjvm.so). + const char *p = buf + strlen(buf) - 1; + for (int count = 0; p > buf && count < 5; ++count) { + for (--p; p > buf && *p != '/'; --p) + /* empty */ ; + } + + if (strncmp(p, "/jre/lib/", 9) != 0) { + // Look for JAVA_HOME in the environment. + char* java_home_var = ::getenv("JAVA_HOME"); + if (java_home_var != NULL && java_home_var[0] != 0) { + char* jrelib_p; + int len; + + // Check the current module name "libjvm.so" or "libjvm_g.so". + p = strrchr(buf, '/'); + assert(strstr(p, "/libjvm") == p, "invalid library name"); + p = strstr(p, "_g") ? "_g" : ""; + + rp = realpath(java_home_var, buf); + if (rp == NULL) + return; + + // determine if this is a legacy image or modules image + // modules image doesn't have "jre" subdirectory + len = strlen(buf); + jrelib_p = buf + len; + snprintf(jrelib_p, buflen-len, "/jre/lib/%s", cpu_arch); + if (0 != access(buf, F_OK)) { + snprintf(jrelib_p, buflen-len, "/lib/%s", cpu_arch); + } + + if (0 == access(buf, F_OK)) { + // Use current module name "libjvm[_g].so" instead of + // "libjvm"debug_only("_g")".so" since for fastdebug version + // we should have "libjvm.so" but debug_only("_g") adds "_g"! + len = strlen(buf); + snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p); + } else { + // Go back to path of .so + rp = realpath(dli_fname, buf); + if (rp == NULL) + return; + } + } + } + } + + strcpy(saved_jvm_path, buf); +} + +void os::print_jni_name_prefix_on(outputStream* st, int args_size) { + // no prefix required, not even "_" +} + +void os::print_jni_name_suffix_on(outputStream* st, int args_size) { + // no suffix required +} + +//////////////////////////////////////////////////////////////////////////////// +// sun.misc.Signal support + +static volatile jint sigint_count = 0; + +static void +UserHandler(int sig, void *siginfo, void *context) { + // 4511530 - sem_post is serialized and handled by the manager thread. When + // the program is interrupted by Ctrl-C, SIGINT is sent to every thread. We + // don't want to flood the manager thread with sem_post requests. + if (sig == SIGINT && Atomic::add(1, &sigint_count) > 1) + return; + + // Ctrl-C is pressed during error reporting, likely because the error + // handler fails to abort. Let VM die immediately. + if (sig == SIGINT && is_error_reported()) { + os::die(); + } + + os::signal_notify(sig); +} + +void* os::user_handler() { + return CAST_FROM_FN_PTR(void*, UserHandler); +} + +extern "C" { + typedef void (*sa_handler_t)(int); + typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); +} + +void* os::signal(int signal_number, void* handler) { + struct sigaction sigAct, oldSigAct; + + sigfillset(&(sigAct.sa_mask)); + sigAct.sa_flags = SA_RESTART|SA_SIGINFO; + sigAct.sa_handler = CAST_TO_FN_PTR(sa_handler_t, handler); + + if (sigaction(signal_number, &sigAct, &oldSigAct)) { + // -1 means registration failed + return (void *)-1; + } + + return CAST_FROM_FN_PTR(void*, oldSigAct.sa_handler); +} + +void os::signal_raise(int signal_number) { + ::raise(signal_number); +} + +/* + * The following code is moved from os.cpp for making this + * code platform specific, which it is by its very nature. + */ + +// Will be modified when max signal is changed to be dynamic +int os::sigexitnum_pd() { + return NSIG; +} + +// a counter for each possible signal value +static volatile jint pending_signals[NSIG+1] = { 0 }; + +// Bsd(POSIX) specific hand shaking semaphore. +#ifdef __APPLE__ +static semaphore_t sig_sem; +#define SEM_INIT(sem, value) semaphore_create(mach_task_self(), &sem, SYNC_POLICY_FIFO, value) +#define SEM_WAIT(sem) semaphore_wait(sem); +#define SEM_POST(sem) semaphore_signal(sem); +#else +static sem_t sig_sem; +#define SEM_INIT(sem, value) sem_init(&sem, 0, value) +#define SEM_WAIT(sem) sem_wait(&sem); +#define SEM_POST(sem) sem_post(&sem); +#endif + +void os::signal_init_pd() { + // Initialize signal structures + ::memset((void*)pending_signals, 0, sizeof(pending_signals)); + + // Initialize signal semaphore + ::SEM_INIT(sig_sem, 0); +} + +void os::signal_notify(int sig) { + Atomic::inc(&pending_signals[sig]); + ::SEM_POST(sig_sem); +} + +static int check_pending_signals(bool wait) { + Atomic::store(0, &sigint_count); + for (;;) { + for (int i = 0; i < NSIG + 1; i++) { + jint n = pending_signals[i]; + if (n > 0 && n == Atomic::cmpxchg(n - 1, &pending_signals[i], n)) { + return i; + } + } + if (!wait) { + return -1; + } + JavaThread *thread = JavaThread::current(); + ThreadBlockInVM tbivm(thread); + + bool threadIsSuspended; + do { + thread->set_suspend_equivalent(); + // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() + ::SEM_WAIT(sig_sem); + + // were we externally suspended while we were waiting? + threadIsSuspended = thread->handle_special_suspend_equivalent_condition(); + if (threadIsSuspended) { + // + // The semaphore has been incremented, but while we were waiting + // another thread suspended us. We don't want to continue running + // while suspended because that would surprise the thread that + // suspended us. + // + ::SEM_POST(sig_sem); + + thread->java_suspend_self(); + } + } while (threadIsSuspended); + } +} + +int os::signal_lookup() { + return check_pending_signals(false); +} + +int os::signal_wait() { + return check_pending_signals(true); +} + +//////////////////////////////////////////////////////////////////////////////// +// Virtual Memory + +int os::vm_page_size() { + // Seems redundant as all get out + assert(os::Bsd::page_size() != -1, "must call os::init"); + return os::Bsd::page_size(); +} + +// Solaris allocates memory by pages. +int os::vm_allocation_granularity() { + assert(os::Bsd::page_size() != -1, "must call os::init"); + return os::Bsd::page_size(); +} + +// Rationale behind this function: +// current (Mon Apr 25 20:12:18 MSD 2005) oprofile drops samples without executable +// mapping for address (see lookup_dcookie() in the kernel module), thus we cannot get +// samples for JITted code. Here we create private executable mapping over the code cache +// and then we can use standard (well, almost, as mapping can change) way to provide +// info for the reporting script by storing timestamp and location of symbol +void bsd_wrap_code(char* base, size_t size) { + static volatile jint cnt = 0; + + if (!UseOprofile) { + return; + } + + char buf[PATH_MAX + 1]; + int num = Atomic::add(1, &cnt); + + snprintf(buf, PATH_MAX + 1, "%s/hs-vm-%d-%d", + os::get_temp_directory(), os::current_process_id(), num); + unlink(buf); + + int fd = ::open(buf, O_CREAT | O_RDWR, S_IRWXU); + + if (fd != -1) { + off_t rv = ::lseek(fd, size-2, SEEK_SET); + if (rv != (off_t)-1) { + if (::write(fd, "", 1) == 1) { + mmap(base, size, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE, fd, 0); + } + } + ::close(fd); + unlink(buf); + } +} + +// NOTE: Bsd kernel does not really reserve the pages for us. +// All it does is to check if there are enough free pages +// left at the time of mmap(). This could be a potential +// problem. +bool os::commit_memory(char* addr, size_t size, bool exec) { + int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; +#ifdef __OpenBSD__ + // XXX: Work-around mmap/MAP_FIXED bug temporarily on OpenBSD + return ::mprotect(addr, size, prot) == 0; +#else + uintptr_t res = (uintptr_t) ::mmap(addr, size, prot, + MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); + return res != (uintptr_t) MAP_FAILED; +#endif +} + +#ifndef _ALLBSD_SOURCE +// Define MAP_HUGETLB here so we can build HotSpot on old systems. +#ifndef MAP_HUGETLB +#define MAP_HUGETLB 0x40000 +#endif + +// Define MADV_HUGEPAGE here so we can build HotSpot on old systems. +#ifndef MADV_HUGEPAGE +#define MADV_HUGEPAGE 14 +#endif +#endif + +bool os::commit_memory(char* addr, size_t size, size_t alignment_hint, + bool exec) { +#ifndef _ALLBSD_SOURCE + if (UseHugeTLBFS && alignment_hint > (size_t)vm_page_size()) { + int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; + uintptr_t res = + (uintptr_t) ::mmap(addr, size, prot, + MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_HUGETLB, + -1, 0); + return res != (uintptr_t) MAP_FAILED; + } +#endif + + return commit_memory(addr, size, exec); +} + +void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { +#ifndef _ALLBSD_SOURCE + if (UseHugeTLBFS && alignment_hint > (size_t)vm_page_size()) { + // We don't check the return value: madvise(MADV_HUGEPAGE) may not + // be supported or the memory may already be backed by huge pages. + ::madvise(addr, bytes, MADV_HUGEPAGE); + } +#endif +} + +void os::free_memory(char *addr, size_t bytes) { + ::madvise(addr, bytes, MADV_DONTNEED); +} + +void os::numa_make_global(char *addr, size_t bytes) { +} + +void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { +} + +bool os::numa_topology_changed() { return false; } + +size_t os::numa_get_groups_num() { + return 1; +} + +int os::numa_get_group_id() { + return 0; +} + +size_t os::numa_get_leaf_groups(int *ids, size_t size) { + if (size > 0) { + ids[0] = 0; + return 1; + } + return 0; +} + +bool os::get_page_info(char *start, page_info* info) { + return false; +} + +char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info* page_found) { + return end; +} + +#ifndef _ALLBSD_SOURCE +// Something to do with the numa-aware allocator needs these symbols +extern "C" JNIEXPORT void numa_warn(int number, char *where, ...) { } +extern "C" JNIEXPORT void numa_error(char *where) { } +extern "C" JNIEXPORT int fork1() { return fork(); } + + +// If we are running with libnuma version > 2, then we should +// be trying to use symbols with versions 1.1 +// If we are running with earlier version, which did not have symbol versions, +// we should use the base version. +void* os::Bsd::libnuma_dlsym(void* handle, const char *name) { + void *f = dlvsym(handle, name, "libnuma_1.1"); + if (f == NULL) { + f = dlsym(handle, name); + } + return f; +} + +bool os::Bsd::libnuma_init() { + // sched_getcpu() should be in libc. + set_sched_getcpu(CAST_TO_FN_PTR(sched_getcpu_func_t, + dlsym(RTLD_DEFAULT, "sched_getcpu"))); + + if (sched_getcpu() != -1) { // Does it work? + void *handle = dlopen("libnuma.so.1", RTLD_LAZY); + if (handle != NULL) { + set_numa_node_to_cpus(CAST_TO_FN_PTR(numa_node_to_cpus_func_t, + libnuma_dlsym(handle, "numa_node_to_cpus"))); + set_numa_max_node(CAST_TO_FN_PTR(numa_max_node_func_t, + libnuma_dlsym(handle, "numa_max_node"))); + set_numa_available(CAST_TO_FN_PTR(numa_available_func_t, + libnuma_dlsym(handle, "numa_available"))); + set_numa_tonode_memory(CAST_TO_FN_PTR(numa_tonode_memory_func_t, + libnuma_dlsym(handle, "numa_tonode_memory"))); + set_numa_interleave_memory(CAST_TO_FN_PTR(numa_interleave_memory_func_t, + libnuma_dlsym(handle, "numa_interleave_memory"))); + + + if (numa_available() != -1) { + set_numa_all_nodes((unsigned long*)libnuma_dlsym(handle, "numa_all_nodes")); + // Create a cpu -> node mapping + _cpu_to_node = new (ResourceObj::C_HEAP) GrowableArray<int>(0, true); + rebuild_cpu_to_node_map(); + return true; + } + } + } + return false; +} + +// rebuild_cpu_to_node_map() constructs a table mapping cpud id to node id. +// The table is later used in get_node_by_cpu(). +void os::Bsd::rebuild_cpu_to_node_map() { + const size_t NCPUS = 32768; // Since the buffer size computation is very obscure + // in libnuma (possible values are starting from 16, + // and continuing up with every other power of 2, but less + // than the maximum number of CPUs supported by kernel), and + // is a subject to change (in libnuma version 2 the requirements + // are more reasonable) we'll just hardcode the number they use + // in the library. + const size_t BitsPerCLong = sizeof(long) * CHAR_BIT; + + size_t cpu_num = os::active_processor_count(); + size_t cpu_map_size = NCPUS / BitsPerCLong; + size_t cpu_map_valid_size = + MIN2((cpu_num + BitsPerCLong - 1) / BitsPerCLong, cpu_map_size); + + cpu_to_node()->clear(); + cpu_to_node()->at_grow(cpu_num - 1); + size_t node_num = numa_get_groups_num(); + + unsigned long *cpu_map = NEW_C_HEAP_ARRAY(unsigned long, cpu_map_size); + for (size_t i = 0; i < node_num; i++) { + if (numa_node_to_cpus(i, cpu_map, cpu_map_size * sizeof(unsigned long)) != -1) { + for (size_t j = 0; j < cpu_map_valid_size; j++) { + if (cpu_map[j] != 0) { + for (size_t k = 0; k < BitsPerCLong; k++) { + if (cpu_map[j] & (1UL << k)) { + cpu_to_node()->at_put(j * BitsPerCLong + k, i); + } + } + } + } + } + } + FREE_C_HEAP_ARRAY(unsigned long, cpu_map); +} + +int os::Bsd::get_node_by_cpu(int cpu_id) { + if (cpu_to_node() != NULL && cpu_id >= 0 && cpu_id < cpu_to_node()->length()) { + return cpu_to_node()->at(cpu_id); + } + return -1; +} + +GrowableArray<int>* os::Bsd::_cpu_to_node; +os::Bsd::sched_getcpu_func_t os::Bsd::_sched_getcpu; +os::Bsd::numa_node_to_cpus_func_t os::Bsd::_numa_node_to_cpus; +os::Bsd::numa_max_node_func_t os::Bsd::_numa_max_node; +os::Bsd::numa_available_func_t os::Bsd::_numa_available; +os::Bsd::numa_tonode_memory_func_t os::Bsd::_numa_tonode_memory; +os::Bsd::numa_interleave_memory_func_t os::Bsd::_numa_interleave_memory; +unsigned long* os::Bsd::_numa_all_nodes; +#endif + +bool os::uncommit_memory(char* addr, size_t size) { +#ifdef __OpenBSD__ + // XXX: Work-around mmap/MAP_FIXED bug temporarily on OpenBSD + return ::mprotect(addr, size, PROT_NONE) == 0; +#else + uintptr_t res = (uintptr_t) ::mmap(addr, size, PROT_NONE, + MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0); + return res != (uintptr_t) MAP_FAILED; +#endif +} + +bool os::create_stack_guard_pages(char* addr, size_t size) { + return os::commit_memory(addr, size); +} + +// If this is a growable mapping, remove the guard pages entirely by +// munmap()ping them. If not, just call uncommit_memory(). +bool os::remove_stack_guard_pages(char* addr, size_t size) { + return os::uncommit_memory(addr, size); +} + +static address _highest_vm_reserved_address = NULL; + +// If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory +// at 'requested_addr'. If there are existing memory mappings at the same +// location, however, they will be overwritten. If 'fixed' is false, +// 'requested_addr' is only treated as a hint, the return value may or +// may not start from the requested address. Unlike Bsd mmap(), this +// function returns NULL to indicate failure. +static char* anon_mmap(char* requested_addr, size_t bytes, bool fixed) { + char * addr; + int flags; + + flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS; + if (fixed) { + assert((uintptr_t)requested_addr % os::Bsd::page_size() == 0, "unaligned address"); + flags |= MAP_FIXED; + } + + // Map uncommitted pages PROT_READ and PROT_WRITE, change access + // to PROT_EXEC if executable when we commit the page. + addr = (char*)::mmap(requested_addr, bytes, PROT_READ|PROT_WRITE, + flags, -1, 0); + + if (addr != MAP_FAILED) { + // anon_mmap() should only get called during VM initialization, + // don't need lock (actually we can skip locking even it can be called + // from multiple threads, because _highest_vm_reserved_address is just a + // hint about the upper limit of non-stack memory regions.) + if ((address)addr + bytes > _highest_vm_reserved_address) { + _highest_vm_reserved_address = (address)addr + bytes; + } + } + + return addr == MAP_FAILED ? NULL : addr; +} + +// Don't update _highest_vm_reserved_address, because there might be memory +// regions above addr + size. If so, releasing a memory region only creates +// a hole in the address space, it doesn't help prevent heap-stack collision. +// +static int anon_munmap(char * addr, size_t size) { + return ::munmap(addr, size) == 0; +} + +char* os::reserve_memory(size_t bytes, char* requested_addr, + size_t alignment_hint) { + return anon_mmap(requested_addr, bytes, (requested_addr != NULL)); +} + +bool os::release_memory(char* addr, size_t size) { + return anon_munmap(addr, size); +} + +static address highest_vm_reserved_address() { + return _highest_vm_reserved_address; +} + +static bool bsd_mprotect(char* addr, size_t size, int prot) { + // Bsd wants the mprotect address argument to be page aligned. + char* bottom = (char*)align_size_down((intptr_t)addr, os::Bsd::page_size()); + + // According to SUSv3, mprotect() should only be used with mappings + // established by mmap(), and mmap() always maps whole pages. Unaligned + // 'addr' likely indicates problem in the VM (e.g. trying to change + // protection of malloc'ed or statically allocated memory). Check the + // caller if you hit this assert. + assert(addr == bottom, "sanity check"); + + size = align_size_up(pointer_delta(addr, bottom, 1) + size, os::Bsd::page_size()); + return ::mprotect(bottom, size, prot) == 0; +} + +// Set protections specified +bool os::protect_memory(char* addr, size_t bytes, ProtType prot, + bool is_committed) { + unsigned int p = 0; + switch (prot) { + case MEM_PROT_NONE: p = PROT_NONE; break; + case MEM_PROT_READ: p = PROT_READ; break; + case MEM_PROT_RW: p = PROT_READ|PROT_WRITE; break; + case MEM_PROT_RWX: p = PROT_READ|PROT_WRITE|PROT_EXEC; break; + default: + ShouldNotReachHere(); + } + // is_committed is unused. + return bsd_mprotect(addr, bytes, p); +} + +bool os::guard_memory(char* addr, size_t size) { + return bsd_mprotect(addr, size, PROT_NONE); +} + +bool os::unguard_memory(char* addr, size_t size) { + return bsd_mprotect(addr, size, PROT_READ|PROT_WRITE); +} + +bool os::Bsd::hugetlbfs_sanity_check(bool warn, size_t page_size) { + bool result = false; +#ifndef _ALLBSD_SOURCE + void *p = mmap (NULL, page_size, PROT_READ|PROT_WRITE, + MAP_ANONYMOUS|MAP_PRIVATE|MAP_HUGETLB, + -1, 0); + + if (p != (void *) -1) { + // We don't know if this really is a huge page or not. + FILE *fp = fopen("/proc/self/maps", "r"); + if (fp) { + while (!feof(fp)) { + char chars[257]; + long x = 0; + if (fgets(chars, sizeof(chars), fp)) { + if (sscanf(chars, "%lx-%*x", &x) == 1 + && x == (long)p) { + if (strstr (chars, "hugepage")) { + result = true; + break; + } + } + } + } + fclose(fp); + } + munmap (p, page_size); + if (result) + return true; + } + + if (warn) { + warning("HugeTLBFS is not supported by the operating system."); + } +#endif + + return result; +} + +/* +* Set the coredump_filter bits to include largepages in core dump (bit 6) +* +* From the coredump_filter documentation: +* +* - (bit 0) anonymous private memory +* - (bit 1) anonymous shared memory +* - (bit 2) file-backed private memory +* - (bit 3) file-backed shared memory +* - (bit 4) ELF header pages in file-backed private memory areas (it is +* effective only if the bit 2 is cleared) +* - (bit 5) hugetlb private memory +* - (bit 6) hugetlb shared memory +*/ +static void set_coredump_filter(void) { + FILE *f; + long cdm; + + if ((f = fopen("/proc/self/coredump_filter", "r+")) == NULL) { + return; + } + + if (fscanf(f, "%lx", &cdm) != 1) { + fclose(f); + return; + } + + rewind(f); + + if ((cdm & LARGEPAGES_BIT) == 0) { + cdm |= LARGEPAGES_BIT; + fprintf(f, "%#lx", cdm); + } + + fclose(f); +} + +// Large page support + +static size_t _large_page_size = 0; + +void os::large_page_init() { +#ifndef _ALLBSD_SOURCE + if (!UseLargePages) { + UseHugeTLBFS = false; + UseSHM = false; + return; + } + + if (FLAG_IS_DEFAULT(UseHugeTLBFS) && FLAG_IS_DEFAULT(UseSHM)) { + // If UseLargePages is specified on the command line try both methods, + // if it's default, then try only HugeTLBFS. + if (FLAG_IS_DEFAULT(UseLargePages)) { + UseHugeTLBFS = true; + } else { + UseHugeTLBFS = UseSHM = true; + } + } + + if (LargePageSizeInBytes) { + _large_page_size = LargePageSizeInBytes; + } else { + // large_page_size on Bsd is used to round up heap size. x86 uses either + // 2M or 4M page, depending on whether PAE (Physical Address Extensions) + // mode is enabled. AMD64/EM64T uses 2M page in 64bit mode. IA64 can use + // page as large as 256M. + // + // Here we try to figure out page size by parsing /proc/meminfo and looking + // for a line with the following format: + // Hugepagesize: 2048 kB + // + // If we can't determine the value (e.g. /proc is not mounted, or the text + // format has been changed), we'll use the largest page size supported by + // the processor. + +#ifndef ZERO + _large_page_size = IA32_ONLY(4 * M) AMD64_ONLY(2 * M) IA64_ONLY(256 * M) SPARC_ONLY(4 * M) + ARM_ONLY(2 * M) PPC_ONLY(4 * M); +#endif // ZERO + + FILE *fp = fopen("/proc/meminfo", "r"); + if (fp) { + while (!feof(fp)) { + int x = 0; + char buf[16]; + if (fscanf(fp, "Hugepagesize: %d", &x) == 1) { + if (x && fgets(buf, sizeof(buf), fp) && strcmp(buf, " kB\n") == 0) { + _large_page_size = x * K; + break; + } + } else { + // skip to next line + for (;;) { + int ch = fgetc(fp); + if (ch == EOF || ch == (int)'\n') break; + } + } + } + fclose(fp); + } + } + + // print a warning if any large page related flag is specified on command line + bool warn_on_failure = !FLAG_IS_DEFAULT(UseHugeTLBFS); + + const size_t default_page_size = (size_t)Bsd::page_size(); + if (_large_page_size > default_page_size) { + _page_sizes[0] = _large_page_size; + _page_sizes[1] = default_page_size; + _page_sizes[2] = 0; + } + UseHugeTLBFS = UseHugeTLBFS && + Bsd::hugetlbfs_sanity_check(warn_on_failure, _large_page_size); + + if (UseHugeTLBFS) + UseSHM = false; + + UseLargePages = UseHugeTLBFS || UseSHM; + + set_coredump_filter(); +#endif +} + +#ifndef _ALLBSD_SOURCE +#ifndef SHM_HUGETLB +#define SHM_HUGETLB 04000 +#endif +#endif + +char* os::reserve_memory_special(size_t bytes, char* req_addr, bool exec) { + // "exec" is passed in but not used. Creating the shared image for + // the code cache doesn't have an SHM_X executable permission to check. + assert(UseLargePages && UseSHM, "only for SHM large pages"); + + key_t key = IPC_PRIVATE; + char *addr; + + bool warn_on_failure = UseLargePages && + (!FLAG_IS_DEFAULT(UseLargePages) || + !FLAG_IS_DEFAULT(LargePageSizeInBytes) + ); + char msg[128]; + + // Create a large shared memory region to attach to based on size. + // Currently, size is the total size of the heap +#ifndef _ALLBSD_SOURCE + int shmid = shmget(key, bytes, SHM_HUGETLB|IPC_CREAT|SHM_R|SHM_W); +#else + int shmid = shmget(key, bytes, IPC_CREAT|SHM_R|SHM_W); +#endif + if (shmid == -1) { + // Possible reasons for shmget failure: + // 1. shmmax is too small for Java heap. + // > check shmmax value: cat /proc/sys/kernel/shmmax + // > increase shmmax value: echo "0xffffffff" > /proc/sys/kernel/shmmax + // 2. not enough large page memory. + // > check available large pages: cat /proc/meminfo + // > increase amount of large pages: + // echo new_value > /proc/sys/vm/nr_hugepages + // Note 1: different Bsd may use different name for this property, + // e.g. on Redhat AS-3 it is "hugetlb_pool". + // Note 2: it's possible there's enough physical memory available but + // they are so fragmented after a long run that they can't + // coalesce into large pages. Try to reserve large pages when + // the system is still "fresh". + if (warn_on_failure) { + jio_snprintf(msg, sizeof(msg), "Failed to reserve shared memory (errno = %d).", errno); + warning(msg); + } + return NULL; + } + + // attach to the region + addr = (char*)shmat(shmid, req_addr, 0); + int err = errno; + + // Remove shmid. If shmat() is successful, the actual shared memory segment + // will be deleted when it's detached by shmdt() or when the process + // terminates. If shmat() is not successful this will remove the shared + // segment immediately. + shmctl(shmid, IPC_RMID, NULL); + + if ((intptr_t)addr == -1) { + if (warn_on_failure) { + jio_snprintf(msg, sizeof(msg), "Failed to attach shared memory (errno = %d).", err); + warning(msg); + } + return NULL; + } + + return addr; +} + +bool os::release_memory_special(char* base, size_t bytes) { + // detaching the SHM segment will also delete it, see reserve_memory_special() + int rslt = shmdt(base); + return rslt == 0; +} + +size_t os::large_page_size() { + return _large_page_size; +} + +// HugeTLBFS allows application to commit large page memory on demand; +// with SysV SHM the entire memory region must be allocated as shared +// memory. +bool os::can_commit_large_page_memory() { + return UseHugeTLBFS; +} + +bool os::can_execute_large_page_memory() { + return UseHugeTLBFS; +} + +// Reserve memory at an arbitrary address, only if that area is +// available (and not reserved for something else). + +char* os::attempt_reserve_memory_at(size_t bytes, char* requested_addr) { + const int max_tries = 10; + char* base[max_tries]; + size_t size[max_tries]; + const size_t gap = 0x000000; + + // Assert only that the size is a multiple of the page size, since + // that's all that mmap requires, and since that's all we really know + // about at this low abstraction level. If we need higher alignment, + // we can either pass an alignment to this method or verify alignment + // in one of the methods further up the call chain. See bug 5044738. + assert(bytes % os::vm_page_size() == 0, "reserving unexpected size block"); + + // Repeatedly allocate blocks until the block is allocated at the + // right spot. Give up after max_tries. Note that reserve_memory() will + // automatically update _highest_vm_reserved_address if the call is + // successful. The variable tracks the highest memory address every reserved + // by JVM. It is used to detect heap-stack collision if running with + // fixed-stack BsdThreads. Because here we may attempt to reserve more + // space than needed, it could confuse the collision detecting code. To + // solve the problem, save current _highest_vm_reserved_address and + // calculate the correct value before return. + address old_highest = _highest_vm_reserved_address; + + // Bsd mmap allows caller to pass an address as hint; give it a try first, + // if kernel honors the hint then we can return immediately. + char * addr = anon_mmap(requested_addr, bytes, false); + if (addr == requested_addr) { + return requested_addr; + } + + if (addr != NULL) { + // mmap() is successful but it fails to reserve at the requested address + anon_munmap(addr, bytes); + } + + int i; + for (i = 0; i < max_tries; ++i) { + base[i] = reserve_memory(bytes); + + if (base[i] != NULL) { + // Is this the block we wanted? + if (base[i] == requested_addr) { + size[i] = bytes; + break; + } + + // Does this overlap the block we wanted? Give back the overlapped + // parts and try again. + + size_t top_overlap = requested_addr + (bytes + gap) - base[i]; + if (top_overlap >= 0 && top_overlap < bytes) { + unmap_memory(base[i], top_overlap); + base[i] += top_overlap; + size[i] = bytes - top_overlap; + } else { + size_t bottom_overlap = base[i] + bytes - requested_addr; + if (bottom_overlap >= 0 && bottom_overlap < bytes) { + unmap_memory(requested_addr, bottom_overlap); + size[i] = bytes - bottom_overlap; + } else { + size[i] = bytes; + } + } + } + } + + // Give back the unused reserved pieces. + + for (int j = 0; j < i; ++j) { + if (base[j] != NULL) { + unmap_memory(base[j], size[j]); + } + } + + if (i < max_tries) { + _highest_vm_reserved_address = MAX2(old_highest, (address)requested_addr + bytes); + return requested_addr; + } else { + _highest_vm_reserved_address = old_highest; + return NULL; + } +} + +size_t os::read(int fd, void *buf, unsigned int nBytes) { + RESTARTABLE_RETURN_INT(::read(fd, buf, nBytes)); +} + +// TODO-FIXME: reconcile Solaris' os::sleep with the bsd variation. +// Solaris uses poll(), bsd uses park(). +// Poll() is likely a better choice, assuming that Thread.interrupt() +// generates a SIGUSRx signal. Note that SIGUSR1 can interfere with +// SIGSEGV, see 4355769. + +const int NANOSECS_PER_MILLISECS = 1000000; + +int os::sleep(Thread* thread, jlong millis, bool interruptible) { + assert(thread == Thread::current(), "thread consistency check"); + + ParkEvent * const slp = thread->_SleepEvent ; + slp->reset() ; + OrderAccess::fence() ; + + if (interruptible) { + jlong prevtime = javaTimeNanos(); + + for (;;) { + if (os::is_interrupted(thread, true)) { + return OS_INTRPT; + } + + jlong newtime = javaTimeNanos(); + + if (newtime - prevtime < 0) { + // time moving backwards, should only happen if no monotonic clock + // not a guarantee() because JVM should not abort on kernel/glibc bugs + assert(!Bsd::supports_monotonic_clock(), "time moving backwards"); + } else { + millis -= (newtime - prevtime) / NANOSECS_PER_MILLISECS; + } + + if(millis <= 0) { + return OS_OK; + } + + prevtime = newtime; + + { + assert(thread->is_Java_thread(), "sanity check"); + JavaThread *jt = (JavaThread *) thread; + ThreadBlockInVM tbivm(jt); + OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */); + + jt->set_suspend_equivalent(); + // cleared by handle_special_suspend_equivalent_condition() or + // java_suspend_self() via check_and_wait_while_suspended() + + slp->park(millis); + + // were we externally suspended while we were waiting? + jt->check_and_wait_while_suspended(); + } + } + } else { + OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); + jlong prevtime = javaTimeNanos(); + + for (;;) { + // It'd be nice to avoid the back-to-back javaTimeNanos() calls on + // the 1st iteration ... + jlong newtime = javaTimeNanos(); + + if (newtime - prevtime < 0) { + // time moving backwards, should only happen if no monotonic clock + // not a guarantee() because JVM should not abort on kernel/glibc bugs + assert(!Bsd::supports_monotonic_clock(), "time moving backwards"); + } else { + millis -= (newtime - prevtime) / NANOSECS_PER_MILLISECS; + } + + if(millis <= 0) break ; + + prevtime = newtime; + slp->park(millis); + } + return OS_OK ; + } +} + +int os::naked_sleep() { + // %% make the sleep time an integer flag. for now use 1 millisec. + return os::sleep(Thread::current(), 1, false); +} + +// Sleep forever; naked call to OS-specific sleep; use with CAUTION +void os::infinite_sleep() { + while (true) { // sleep forever ... + ::sleep(100); // ... 100 seconds at a time + } +} + +// Used to convert frequent JVM_Yield() to nops +bool os::dont_yield() { + return DontYieldALot; +} + +void os::yield() { + sched_yield(); +} + +os::YieldResult os::NakedYield() { sched_yield(); return os::YIELD_UNKNOWN ;} + +void os::yield_all(int attempts) { + // Yields to all threads, including threads with lower priorities + // Threads on Bsd are all with same priority. The Solaris style + // os::yield_all() with nanosleep(1ms) is not necessary. + sched_yield(); +} + +// Called from the tight loops to possibly influence time-sharing heuristics +void os::loop_breaker(int attempts) { + os::yield_all(attempts); +} + +//////////////////////////////////////////////////////////////////////////////// +// thread priority support + +// Note: Normal Bsd applications are run with SCHED_OTHER policy. SCHED_OTHER +// only supports dynamic priority, static priority must be zero. For real-time +// applications, Bsd supports SCHED_RR which allows static priority (1-99). +// However, for large multi-threaded applications, SCHED_RR is not only slower +// than SCHED_OTHER, but also very unstable (my volano tests hang hard 4 out +// of 5 runs - Sep 2005). +// +// The following code actually changes the niceness of kernel-thread/LWP. It +// has an assumption that setpriority() only modifies one kernel-thread/LWP, +// not the entire user process, and user level threads are 1:1 mapped to kernel +// threads. It has always been the case, but could change in the future. For +// this reason, the code should not be used as default (ThreadPriorityPolicy=0). +// It is only used when ThreadPriorityPolicy=1 and requires root privilege. + +#if defined(_ALLBSD_SOURCE) && !defined(__APPLE__) +int os::java_to_os_priority[MaxPriority + 1] = { + 19, // 0 Entry should never be used + + 0, // 1 MinPriority + 3, // 2 + 6, // 3 + + 10, // 4 + 15, // 5 NormPriority + 18, // 6 + + 21, // 7 + 25, // 8 + 28, // 9 NearMaxPriority + + 31 // 10 MaxPriority +}; +#elif defined(__APPLE__) +/* Using Mach high-level priority assignments */ +int os::java_to_os_priority[MaxPriority + 1] = { + 0, // 0 Entry should never be used (MINPRI_USER) + + 27, // 1 MinPriority + 28, // 2 + 29, // 3 + + 30, // 4 + 31, // 5 NormPriority (BASEPRI_DEFAULT) + 32, // 6 + + 33, // 7 + 34, // 8 + 35, // 9 NearMaxPriority + + 36 // 10 MaxPriority +}; +#else +int os::java_to_os_priority[MaxPriority + 1] = { + 19, // 0 Entry should never be used + + 4, // 1 MinPriority + 3, // 2 + 2, // 3 + + 1, // 4 + 0, // 5 NormPriority + -1, // 6 + + -2, // 7 + -3, // 8 + -4, // 9 NearMaxPriority + + -5 // 10 MaxPriority +}; +#endif + +static int prio_init() { + if (ThreadPriorityPolicy == 1) { + // Only root can raise thread priority. Don't allow ThreadPriorityPolicy=1 + // if effective uid is not root. Perhaps, a more elegant way of doing + // this is to test CAP_SYS_NICE capability, but that will require libcap.so + if (geteuid() != 0) { + if (!FLAG_IS_DEFAULT(ThreadPriorityPolicy)) { + warning("-XX:ThreadPriorityPolicy requires root privilege on Bsd"); + } + ThreadPriorityPolicy = 0; + } + } + return 0; +} + +OSReturn os::set_native_priority(Thread* thread, int newpri) { + if ( !UseThreadPriorities || ThreadPriorityPolicy == 0 ) return OS_OK; + +#ifdef __OpenBSD__ + // OpenBSD pthread_setprio starves low priority threads + return OS_OK; +#elif defined(__FreeBSD__) + int ret = pthread_setprio(thread->osthread()->pthread_id(), newpri); +#elif defined(__APPLE__) || defined(__NetBSD__) + struct sched_param sp; + int policy; + pthread_t self = pthread_self(); + + if (pthread_getschedparam(self, &policy, &sp) != 0) + return OS_ERR; + + sp.sched_priority = newpri; + if (pthread_setschedparam(self, policy, &sp) != 0) + return OS_ERR; + + return OS_OK; +#else + int ret = setpriority(PRIO_PROCESS, thread->osthread()->thread_id(), newpri); + return (ret == 0) ? OS_OK : OS_ERR; +#endif +} + +OSReturn os::get_native_priority(const Thread* const thread, int *priority_ptr) { + if ( !UseThreadPriorities || ThreadPriorityPolicy == 0 ) { + *priority_ptr = java_to_os_priority[NormPriority]; + return OS_OK; + } + + errno = 0; +#if defined(__OpenBSD__) || defined(__FreeBSD__) + *priority_ptr = pthread_getprio(thread->osthread()->pthread_id()); +#elif defined(__APPLE__) || defined(__NetBSD__) + int policy; + struct sched_param sp; + + pthread_getschedparam(pthread_self(), &policy, &sp); + *priority_ptr = sp.sched_priority; +#else + *priority_ptr = getpriority(PRIO_PROCESS, thread->osthread()->thread_id()); +#endif + return (*priority_ptr != -1 || errno == 0 ? OS_OK : OS_ERR); +} + +// Hint to the underlying OS that a task switch would not be good. +// Void return because it's a hint and can fail. +void os::hint_no_preempt() {} + +//////////////////////////////////////////////////////////////////////////////// +// suspend/resume support + +// the low-level signal-based suspend/resume support is a remnant from the +// old VM-suspension that used to be for java-suspension, safepoints etc, +// within hotspot. Now there is a single use-case for this: +// - calling get_thread_pc() on the VMThread by the flat-profiler task +// that runs in the watcher thread. +// The remaining code is greatly simplified from the more general suspension +// code that used to be used. +// +// The protocol is quite simple: +// - suspend: +// - sends a signal to the target thread +// - polls the suspend state of the osthread using a yield loop +// - target thread signal handler (SR_handler) sets suspend state +// and blocks in sigsuspend until continued +// - resume: +// - sets target osthread state to continue +// - sends signal to end the sigsuspend loop in the SR_handler +// +// Note that the SR_lock plays no role in this suspend/resume protocol. +// + +static void resume_clear_context(OSThread *osthread) { + osthread->set_ucontext(NULL); + osthread->set_siginfo(NULL); + + // notify the suspend action is completed, we have now resumed + osthread->sr.clear_suspended(); +} + +static void suspend_save_context(OSThread *osthread, siginfo_t* siginfo, ucontext_t* context) { + osthread->set_ucontext(context); + osthread->set_siginfo(siginfo); +} + +// +// Handler function invoked when a thread's execution is suspended or +// resumed. We have to be careful that only async-safe functions are +// called here (Note: most pthread functions are not async safe and +// should be avoided.) +// +// Note: sigwait() is a more natural fit than sigsuspend() from an +// interface point of view, but sigwait() prevents the signal hander +// from being run. libpthread would get very confused by not having +// its signal handlers run and prevents sigwait()'s use with the +// mutex granting granting signal. +// +// Currently only ever called on the VMThread +// +static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) { + // Save and restore errno to avoid confusing native code with EINTR + // after sigsuspend. + int old_errno = errno; + + Thread* thread = Thread::current(); + OSThread* osthread = thread->osthread(); + assert(thread->is_VM_thread(), "Must be VMThread"); + // read current suspend action + int action = osthread->sr.suspend_action(); + if (action == SR_SUSPEND) { + suspend_save_context(osthread, siginfo, context); + + // Notify the suspend action is about to be completed. do_suspend() + // waits until SR_SUSPENDED is set and then returns. We will wait + // here for a resume signal and that completes the suspend-other + // action. do_suspend/do_resume is always called as a pair from + // the same thread - so there are no races + + // notify the caller + osthread->sr.set_suspended(); + + sigset_t suspend_set; // signals for sigsuspend() + + // get current set of blocked signals and unblock resume signal + pthread_sigmask(SIG_BLOCK, NULL, &suspend_set); + sigdelset(&suspend_set, SR_signum); + + // wait here until we are resumed + do { + sigsuspend(&suspend_set); + // ignore all returns until we get a resume signal + } while (osthread->sr.suspend_action() != SR_CONTINUE); + + resume_clear_context(osthread); + + } else { + assert(action == SR_CONTINUE, "unexpected sr action"); + // nothing special to do - just leave the handler + } + + errno = old_errno; +} + + +static int SR_initialize() { + struct sigaction act; + char *s; + /* Get signal number to use for suspend/resume */ + if ((s = ::getenv("_JAVA_SR_SIGNUM")) != 0) { + int sig = ::strtol(s, 0, 10); + if (sig > 0 || sig < NSIG) { + SR_signum = sig; + } + } + + assert(SR_signum > SIGSEGV && SR_signum > SIGBUS, + "SR_signum must be greater than max(SIGSEGV, SIGBUS), see 4355769"); + + sigemptyset(&SR_sigset); + sigaddset(&SR_sigset, SR_signum); + + /* Set up signal handler for suspend/resume */ + act.sa_flags = SA_RESTART|SA_SIGINFO; + act.sa_handler = (void (*)(int)) SR_handler; + + // SR_signum is blocked by default. + // 4528190 - We also need to block pthread restart signal (32 on all + // supported Bsd platforms). Note that BsdThreads need to block + // this signal for all threads to work properly. So we don't have + // to use hard-coded signal number when setting up the mask. + pthread_sigmask(SIG_BLOCK, NULL, &act.sa_mask); + + if (sigaction(SR_signum, &act, 0) == -1) { + return -1; + } + + // Save signal flag + os::Bsd::set_our_sigflags(SR_signum, act.sa_flags); + return 0; +} + +static int SR_finalize() { + return 0; +} + + +// returns true on success and false on error - really an error is fatal +// but this seems the normal response to library errors +static bool do_suspend(OSThread* osthread) { + // mark as suspended and send signal + osthread->sr.set_suspend_action(SR_SUSPEND); + int status = pthread_kill(osthread->pthread_id(), SR_signum); + assert_status(status == 0, status, "pthread_kill"); + + // check status and wait until notified of suspension + if (status == 0) { + for (int i = 0; !osthread->sr.is_suspended(); i++) { + os::yield_all(i); + } + osthread->sr.set_suspend_action(SR_NONE); + return true; + } + else { + osthread->sr.set_suspend_action(SR_NONE); + return false; + } +} + +static void do_resume(OSThread* osthread) { + assert(osthread->sr.is_suspended(), "thread should be suspended"); + osthread->sr.set_suspend_action(SR_CONTINUE); + + int status = pthread_kill(osthread->pthread_id(), SR_signum); + assert_status(status == 0, status, "pthread_kill"); + // check status and wait unit notified of resumption + if (status == 0) { + for (int i = 0; osthread->sr.is_suspended(); i++) { + os::yield_all(i); + } + } + osthread->sr.set_suspend_action(SR_NONE); +} + +//////////////////////////////////////////////////////////////////////////////// +// interrupt support + +void os::interrupt(Thread* thread) { + assert(Thread::current() == thread || Threads_lock->owned_by_self(), + "possibility of dangling Thread pointer"); + + OSThread* osthread = thread->osthread(); + + if (!osthread->interrupted()) { + osthread->set_interrupted(true); + // More than one thread can get here with the same value of osthread, + // resulting in multiple notifications. We do, however, want the store + // to interrupted() to be visible to other threads before we execute unpark(). + OrderAccess::fence(); + ParkEvent * const slp = thread->_SleepEvent ; + if (slp != NULL) slp->unpark() ; + } + + // For JSR166. Unpark even if interrupt status already was set + if (thread->is_Java_thread()) + ((JavaThread*)thread)->parker()->unpark(); + + ParkEvent * ev = thread->_ParkEvent ; + if (ev != NULL) ev->unpark() ; + +} + +bool os::is_interrupted(Thread* thread, bool clear_interrupted) { + assert(Thread::current() == thread || Threads_lock->owned_by_self(), + "possibility of dangling Thread pointer"); + + OSThread* osthread = thread->osthread(); + + bool interrupted = osthread->interrupted(); + + if (interrupted && clear_interrupted) { + osthread->set_interrupted(false); + // consider thread->_SleepEvent->reset() ... optional optimization + } + + return interrupted; +} + +/////////////////////////////////////////////////////////////////////////////////// +// signal handling (except suspend/resume) + +// This routine may be used by user applications as a "hook" to catch signals. +// The user-defined signal handler must pass unrecognized signals to this +// routine, and if it returns true (non-zero), then the signal handler must +// return immediately. If the flag "abort_if_unrecognized" is true, then this +// routine will never retun false (zero), but instead will execute a VM panic +// routine kill the process. +// +// If this routine returns false, it is OK to call it again. This allows +// the user-defined signal handler to perform checks either before or after +// the VM performs its own checks. Naturally, the user code would be making +// a serious error if it tried to handle an exception (such as a null check +// or breakpoint) that the VM was generating for its own correct operation. +// +// This routine may recognize any of the following kinds of signals: +// SIGBUS, SIGSEGV, SIGILL, SIGFPE, SIGQUIT, SIGPIPE, SIGXFSZ, SIGUSR1. +// It should be consulted by handlers for any of those signals. +// +// The caller of this routine must pass in the three arguments supplied +// to the function referred to in the "sa_sigaction" (not the "sa_handler") +// field of the structure passed to sigaction(). This routine assumes that +// the sa_flags field passed to sigaction() includes SA_SIGINFO and SA_RESTART. +// +// Note that the VM will print warnings if it detects conflicting signal +// handlers, unless invoked with the option "-XX:+AllowUserSignalHandlers". +// +extern "C" JNIEXPORT int +JVM_handle_bsd_signal(int signo, siginfo_t* siginfo, + void* ucontext, int abort_if_unrecognized); + +void signalHandler(int sig, siginfo_t* info, void* uc) { + assert(info != NULL && uc != NULL, "it must be old kernel"); + JVM_handle_bsd_signal(sig, info, uc, true); +} + + +// This boolean allows users to forward their own non-matching signals +// to JVM_handle_bsd_signal, harmlessly. +bool os::Bsd::signal_handlers_are_installed = false; + +// For signal-chaining +struct sigaction os::Bsd::sigact[MAXSIGNUM]; +unsigned int os::Bsd::sigs = 0; +bool os::Bsd::libjsig_is_loaded = false; +typedef struct sigaction *(*get_signal_t)(int); +get_signal_t os::Bsd::get_signal_action = NULL; + +struct sigaction* os::Bsd::get_chained_signal_action(int sig) { + struct sigaction *actp = NULL; + + if (libjsig_is_loaded) { + // Retrieve the old signal handler from libjsig + actp = (*get_signal_action)(sig); + } + if (actp == NULL) { + // Retrieve the preinstalled signal handler from jvm + actp = get_preinstalled_handler(sig); + } + + return actp; +} + +static bool call_chained_handler(struct sigaction *actp, int sig, + siginfo_t *siginfo, void *context) { + // Call the old signal handler + if (actp->sa_handler == SIG_DFL) { + // It's more reasonable to let jvm treat it as an unexpected exception + // instead of taking the default action. + return false; + } else if (actp->sa_handler != SIG_IGN) { + if ((actp->sa_flags & SA_NODEFER) == 0) { + // automaticlly block the signal + sigaddset(&(actp->sa_mask), sig); + } + + sa_handler_t hand; + sa_sigaction_t sa; + bool siginfo_flag_set = (actp->sa_flags & SA_SIGINFO) != 0; + // retrieve the chained handler + if (siginfo_flag_set) { + sa = actp->sa_sigaction; + } else { + hand = actp->sa_handler; + } + + if ((actp->sa_flags & SA_RESETHAND) != 0) { + actp->sa_handler = SIG_DFL; + } + + // try to honor the signal mask + sigset_t oset; + pthread_sigmask(SIG_SETMASK, &(actp->sa_mask), &oset); + + // call into the chained handler + if (siginfo_flag_set) { + (*sa)(sig, siginfo, context); + } else { + (*hand)(sig); + } + + // restore the signal mask + pthread_sigmask(SIG_SETMASK, &oset, 0); + } + // Tell jvm's signal handler the signal is taken care of. + return true; +} + +bool os::Bsd::chained_handler(int sig, siginfo_t* siginfo, void* context) { + bool chained = false; + // signal-chaining + if (UseSignalChaining) { + struct sigaction *actp = get_chained_signal_action(sig); + if (actp != NULL) { + chained = call_chained_handler(actp, sig, siginfo, context); + } + } + return chained; +} + +struct sigaction* os::Bsd::get_preinstalled_handler(int sig) { + if ((( (unsigned int)1 << sig ) & sigs) != 0) { + return &sigact[sig]; + } + return NULL; +} + +void os::Bsd::save_preinstalled_handler(int sig, struct sigaction& oldAct) { + assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range"); + sigact[sig] = oldAct; + sigs |= (unsigned int)1 << sig; +} + +// for diagnostic +int os::Bsd::sigflags[MAXSIGNUM]; + +int os::Bsd::get_our_sigflags(int sig) { + assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range"); + return sigflags[sig]; +} + +void os::Bsd::set_our_sigflags(int sig, int flags) { + assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range"); + sigflags[sig] = flags; +} + +void os::Bsd::set_signal_handler(int sig, bool set_installed) { + // Check for overwrite. + struct sigaction oldAct; + sigaction(sig, (struct sigaction*)NULL, &oldAct); + + void* oldhand = oldAct.sa_sigaction + ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction) + : CAST_FROM_FN_PTR(void*, oldAct.sa_handler); + if (oldhand != CAST_FROM_FN_PTR(void*, SIG_DFL) && + oldhand != CAST_FROM_FN_PTR(void*, SIG_IGN) && + oldhand != CAST_FROM_FN_PTR(void*, (sa_sigaction_t)signalHandler)) { + if (AllowUserSignalHandlers || !set_installed) { + // Do not overwrite; user takes responsibility to forward to us. + return; + } else if (UseSignalChaining) { + // save the old handler in jvm + save_preinstalled_handler(sig, oldAct); + // libjsig also interposes the sigaction() call below and saves the + // old sigaction on it own. + } else { + fatal(err_msg("Encountered unexpected pre-existing sigaction handler " + "%#lx for signal %d.", (long)oldhand, sig)); + } + } + + struct sigaction sigAct; + sigfillset(&(sigAct.sa_mask)); + sigAct.sa_handler = SIG_DFL; + if (!set_installed) { + sigAct.sa_flags = SA_SIGINFO|SA_RESTART; + } else { + sigAct.sa_sigaction = signalHandler; + sigAct.sa_flags = SA_SIGINFO|SA_RESTART; + } + // Save flags, which are set by ours + assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range"); + sigflags[sig] = sigAct.sa_flags; + + int ret = sigaction(sig, &sigAct, &oldAct); + assert(ret == 0, "check"); + + void* oldhand2 = oldAct.sa_sigaction + ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction) + : CAST_FROM_FN_PTR(void*, oldAct.sa_handler); + assert(oldhand2 == oldhand, "no concurrent signal handler installation"); +} + +// install signal handlers for signals that HotSpot needs to +// handle in order to support Java-level exception handling. + +void os::Bsd::install_signal_handlers() { + if (!signal_handlers_are_installed) { + signal_handlers_are_installed = true; + + // signal-chaining + typedef void (*signal_setting_t)(); + signal_setting_t begin_signal_setting = NULL; + signal_setting_t end_signal_setting = NULL; + begin_signal_setting = CAST_TO_FN_PTR(signal_setting_t, + dlsym(RTLD_DEFAULT, "JVM_begin_signal_setting")); + if (begin_signal_setting != NULL) { + end_signal_setting = CAST_TO_FN_PTR(signal_setting_t, + dlsym(RTLD_DEFAULT, "JVM_end_signal_setting")); + get_signal_action = CAST_TO_FN_PTR(get_signal_t, + dlsym(RTLD_DEFAULT, "JVM_get_signal_action")); + libjsig_is_loaded = true; + assert(UseSignalChaining, "should enable signal-chaining"); + } + if (libjsig_is_loaded) { + // Tell libjsig jvm is setting signal handlers + (*begin_signal_setting)(); + } + + set_signal_handler(SIGSEGV, true); + set_signal_handler(SIGPIPE, true); + set_signal_handler(SIGBUS, true); + set_signal_handler(SIGILL, true); + set_signal_handler(SIGFPE, true); + set_signal_handler(SIGXFSZ, true); + +#if defined(__APPLE__) + // In Mac OS X 10.4, CrashReporter will write a crash log for all 'fatal' signals, including + // signals caught and handled by the JVM. To work around this, we reset the mach task + // signal handler that's placed on our process by CrashReporter. This disables + // CrashReporter-based reporting. + // + // This work-around is not necessary for 10.5+, as CrashReporter no longer intercedes + // on caught fatal signals. + // + // Additionally, gdb installs both standard BSD signal handlers, and mach exception + // handlers. By replacing the existing task exception handler, we disable gdb's mach + // exception handling, while leaving the standard BSD signal handlers functional. + kern_return_t kr; + kr = task_set_exception_ports(mach_task_self(), + EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, + MACH_PORT_NULL, + EXCEPTION_STATE_IDENTITY, + MACHINE_THREAD_STATE); + + assert(kr == KERN_SUCCESS, "could not set mach task signal handler"); +#endif + + if (libjsig_is_loaded) { + // Tell libjsig jvm finishes setting signal handlers + (*end_signal_setting)(); + } + + // We don't activate signal checker if libjsig is in place, we trust ourselves + // and if UserSignalHandler is installed all bets are off + if (CheckJNICalls) { + if (libjsig_is_loaded) { + tty->print_cr("Info: libjsig is activated, all active signal checking is disabled"); + check_signals = false; + } + if (AllowUserSignalHandlers) { + tty->print_cr("Info: AllowUserSignalHandlers is activated, all active signal checking is disabled"); + check_signals = false; + } + } + } +} + +#ifndef _ALLBSD_SOURCE +// This is the fastest way to get thread cpu time on Bsd. +// Returns cpu time (user+sys) for any thread, not only for current. +// POSIX compliant clocks are implemented in the kernels 2.6.16+. +// It might work on 2.6.10+ with a special kernel/glibc patch. +// For reference, please, see IEEE Std 1003.1-2004: +// http://www.unix.org/single_unix_specification + +jlong os::Bsd::fast_thread_cpu_time(clockid_t clockid) { + struct timespec tp; + int rc = os::Bsd::clock_gettime(clockid, &tp); + assert(rc == 0, "clock_gettime is expected to return 0 code"); + + return (tp.tv_sec * SEC_IN_NANOSECS) + tp.tv_nsec; +} +#endif + +///// +// glibc on Bsd platform uses non-documented flag +// to indicate, that some special sort of signal +// trampoline is used. +// We will never set this flag, and we should +// ignore this flag in our diagnostic +#ifdef SIGNIFICANT_SIGNAL_MASK +#undef SIGNIFICANT_SIGNAL_MASK +#endif +#define SIGNIFICANT_SIGNAL_MASK (~0x04000000) + +static const char* get_signal_handler_name(address handler, + char* buf, int buflen) { + int offset; + bool found = os::dll_address_to_library_name(handler, buf, buflen, &offset); + if (found) { + // skip directory names + const char *p1, *p2; + p1 = buf; + size_t len = strlen(os::file_separator()); + while ((p2 = strstr(p1, os::file_separator())) != NULL) p1 = p2 + len; + jio_snprintf(buf, buflen, "%s+0x%x", p1, offset); + } else { + jio_snprintf(buf, buflen, PTR_FORMAT, handler); + } + return buf; +} + +static void print_signal_handler(outputStream* st, int sig, + char* buf, size_t buflen) { + struct sigaction sa; + + sigaction(sig, NULL, &sa); + + // See comment for SIGNIFICANT_SIGNAL_MASK define + sa.sa_flags &= SIGNIFICANT_SIGNAL_MASK; + + st->print("%s: ", os::exception_name(sig, buf, buflen)); + + address handler = (sa.sa_flags & SA_SIGINFO) + ? CAST_FROM_FN_PTR(address, sa.sa_sigaction) + : CAST_FROM_FN_PTR(address, sa.sa_handler); + + if (handler == CAST_FROM_FN_PTR(address, SIG_DFL)) { + st->print("SIG_DFL"); + } else if (handler == CAST_FROM_FN_PTR(address, SIG_IGN)) { + st->print("SIG_IGN"); + } else { + st->print("[%s]", get_signal_handler_name(handler, buf, buflen)); + } + + st->print(", sa_mask[0]=" PTR32_FORMAT, *(uint32_t*)&sa.sa_mask); + + address rh = VMError::get_resetted_sighandler(sig); + // May be, handler was resetted by VMError? + if(rh != NULL) { + handler = rh; + sa.sa_flags = VMError::get_resetted_sigflags(sig) & SIGNIFICANT_SIGNAL_MASK; + } + + st->print(", sa_flags=" PTR32_FORMAT, sa.sa_flags); + + // Check: is it our handler? + if(handler == CAST_FROM_FN_PTR(address, (sa_sigaction_t)signalHandler) || + handler == CAST_FROM_FN_PTR(address, (sa_sigaction_t)SR_handler)) { + // It is our signal handler + // check for flags, reset system-used one! + if((int)sa.sa_flags != os::Bsd::get_our_sigflags(sig)) { + st->print( + ", flags was changed from " PTR32_FORMAT ", consider using jsig library", + os::Bsd::get_our_sigflags(sig)); + } + } + st->cr(); +} + + +#define DO_SIGNAL_CHECK(sig) \ + if (!sigismember(&check_signal_done, sig)) \ + os::Bsd::check_signal_handler(sig) + +// This method is a periodic task to check for misbehaving JNI applications +// under CheckJNI, we can add any periodic checks here + +void os::run_periodic_checks() { + + if (check_signals == false) return; + + // SEGV and BUS if overridden could potentially prevent + // generation of hs*.log in the event of a crash, debugging + // such a case can be very challenging, so we absolutely + // check the following for a good measure: + DO_SIGNAL_CHECK(SIGSEGV); + DO_SIGNAL_CHECK(SIGILL); + DO_SIGNAL_CHECK(SIGFPE); + DO_SIGNAL_CHECK(SIGBUS); + DO_SIGNAL_CHECK(SIGPIPE); + DO_SIGNAL_CHECK(SIGXFSZ); + + + // ReduceSignalUsage allows the user to override these handlers + // see comments at the very top and jvm_solaris.h + if (!ReduceSignalUsage) { + DO_SIGNAL_CHECK(SHUTDOWN1_SIGNAL); + DO_SIGNAL_CHECK(SHUTDOWN2_SIGNAL); + DO_SIGNAL_CHECK(SHUTDOWN3_SIGNAL); + DO_SIGNAL_CHECK(BREAK_SIGNAL); + } + + DO_SIGNAL_CHECK(SR_signum); + DO_SIGNAL_CHECK(INTERRUPT_SIGNAL); +} + +typedef int (*os_sigaction_t)(int, const struct sigaction *, struct sigaction *); + +static os_sigaction_t os_sigaction = NULL; + +void os::Bsd::check_signal_handler(int sig) { + char buf[O_BUFLEN]; + address jvmHandler = NULL; + + + struct sigaction act; + if (os_sigaction == NULL) { + // only trust the default sigaction, in case it has been interposed + os_sigaction = (os_sigaction_t)dlsym(RTLD_DEFAULT, "sigaction"); + if (os_sigaction == NULL) return; + } + + os_sigaction(sig, (struct sigaction*)NULL, &act); + + + act.sa_flags &= SIGNIFICANT_SIGNAL_MASK; + + address thisHandler = (act.sa_flags & SA_SIGINFO) + ? CAST_FROM_FN_PTR(address, act.sa_sigaction) + : CAST_FROM_FN_PTR(address, act.sa_handler) ; + + + switch(sig) { + case SIGSEGV: + case SIGBUS: + case SIGFPE: + case SIGPIPE: + case SIGILL: + case SIGXFSZ: + jvmHandler = CAST_FROM_FN_PTR(address, (sa_sigaction_t)signalHandler); + break; + + case SHUTDOWN1_SIGNAL: + case SHUTDOWN2_SIGNAL: + case SHUTDOWN3_SIGNAL: + case BREAK_SIGNAL: + jvmHandler = (address)user_handler(); + break; + + case INTERRUPT_SIGNAL: + jvmHandler = CAST_FROM_FN_PTR(address, SIG_DFL); + break; + + default: + if (sig == SR_signum) { + jvmHandler = CAST_FROM_FN_PTR(address, (sa_sigaction_t)SR_handler); + } else { + return; + } + break; + } + + if (thisHandler != jvmHandler) { + tty->print("Warning: %s handler ", exception_name(sig, buf, O_BUFLEN)); + tty->print("expected:%s", get_signal_handler_name(jvmHandler, buf, O_BUFLEN)); + tty->print_cr(" found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN)); + // No need to check this sig any longer + sigaddset(&check_signal_done, sig); + } else if(os::Bsd::get_our_sigflags(sig) != 0 && (int)act.sa_flags != os::Bsd::get_our_sigflags(sig)) { + tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN)); + tty->print("expected:" PTR32_FORMAT, os::Bsd::get_our_sigflags(sig)); + tty->print_cr(" found:" PTR32_FORMAT, act.sa_flags); + // No need to check this sig any longer + sigaddset(&check_signal_done, sig); + } + + // Dump all the signal + if (sigismember(&check_signal_done, sig)) { + print_signal_handlers(tty, buf, O_BUFLEN); + } +} + +extern void report_error(char* file_name, int line_no, char* title, char* format, ...); + +extern bool signal_name(int signo, char* buf, size_t len); + +const char* os::exception_name(int exception_code, char* buf, size_t size) { + if (0 < exception_code && exception_code <= SIGRTMAX) { + // signal + if (!signal_name(exception_code, buf, size)) { + jio_snprintf(buf, size, "SIG%d", exception_code); + } + return buf; + } else { + return NULL; + } +} + +// this is called _before_ the most of global arguments have been parsed +void os::init(void) { + char dummy; /* used to get a guess on initial stack address */ +// first_hrtime = gethrtime(); + + // With BsdThreads the JavaMain thread pid (primordial thread) + // is different than the pid of the java launcher thread. + // So, on Bsd, the launcher thread pid is passed to the VM + // via the sun.java.launcher.pid property. + // Use this property instead of getpid() if it was correctly passed. + // See bug 6351349. + pid_t java_launcher_pid = (pid_t) Arguments::sun_java_launcher_pid(); + + _initial_pid = (java_launcher_pid > 0) ? java_launcher_pid : getpid(); + + clock_tics_per_sec = CLK_TCK; + + init_random(1234567); + + ThreadCritical::initialize(); + + Bsd::set_page_size(getpagesize()); + if (Bsd::page_size() == -1) { + fatal(err_msg("os_bsd.cpp: os::init: sysconf failed (%s)", + strerror(errno))); + } + init_page_sizes((size_t) Bsd::page_size()); + + Bsd::initialize_system_info(); + + // main_thread points to the aboriginal thread + Bsd::_main_thread = pthread_self(); + + Bsd::clock_init(); + initial_time_count = os::elapsed_counter(); + +#ifdef __APPLE__ + // XXXDARWIN + // Work around the unaligned VM callbacks in hotspot's + // sharedRuntime. The callbacks don't use SSE2 instructions, and work on + // Linux, Solaris, and FreeBSD. On Mac OS X, dyld (rightly so) enforces + // alignment when doing symbol lookup. To work around this, we force early + // binding of all symbols now, thus binding when alignment is known-good. + _dyld_bind_fully_image_containing_address((const void *) &os::init); +#endif +} + +// To install functions for atexit system call +extern "C" { + static void perfMemory_exit_helper() { + perfMemory_exit(); + } +} + +// this is called _after_ the global arguments have been parsed +jint os::init_2(void) +{ +#ifndef _ALLBSD_SOURCE + Bsd::fast_thread_clock_init(); +#endif + + // Allocate a single page and mark it as readable for safepoint polling + address polling_page = (address) ::mmap(NULL, Bsd::page_size(), PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + guarantee( polling_page != MAP_FAILED, "os::init_2: failed to allocate polling page" ); + + os::set_polling_page( polling_page ); + +#ifndef PRODUCT + if(Verbose && PrintMiscellaneous) + tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", (intptr_t)polling_page); +#endif + + if (!UseMembar) { + address mem_serialize_page = (address) ::mmap(NULL, Bsd::page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + guarantee( mem_serialize_page != NULL, "mmap Failed for memory serialize page"); + os::set_memory_serialize_page( mem_serialize_page ); + +#ifndef PRODUCT + if(Verbose && PrintMiscellaneous) + tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page); +#endif + } + + os::large_page_init(); + + // initialize suspend/resume support - must do this before signal_sets_init() + if (SR_initialize() != 0) { + perror("SR_initialize failed"); + return JNI_ERR; + } + + Bsd::signal_sets_init(); + Bsd::install_signal_handlers(); + + // Check minimum allowable stack size for thread creation and to initialize + // the java system classes, including StackOverflowError - depends on page + // size. Add a page for compiler2 recursion in main thread. + // Add in 2*BytesPerWord times page size to account for VM stack during + // class initialization depending on 32 or 64 bit VM. + os::Bsd::min_stack_allowed = MAX2(os::Bsd::min_stack_allowed, + (size_t)(StackYellowPages+StackRedPages+StackShadowPages+ + 2*BytesPerWord COMPILER2_PRESENT(+1)) * Bsd::page_size()); + + size_t threadStackSizeInBytes = ThreadStackSize * K; + if (threadStackSizeInBytes != 0 && + threadStackSizeInBytes < os::Bsd::min_stack_allowed) { + tty->print_cr("\nThe stack size specified is too small, " + "Specify at least %dk", + os::Bsd::min_stack_allowed/ K); + return JNI_ERR; + } + + // Make the stack size a multiple of the page size so that + // the yellow/red zones can be guarded. + JavaThread::set_stack_size_at_create(round_to(threadStackSizeInBytes, + vm_page_size())); + +#ifndef _ALLBSD_SOURCE + Bsd::capture_initial_stack(JavaThread::stack_size_at_create()); + + Bsd::libpthread_init(); + if (PrintMiscellaneous && (Verbose || WizardMode)) { + tty->print_cr("[HotSpot is running with %s, %s(%s)]\n", + Bsd::glibc_version(), Bsd::libpthread_version(), + Bsd::is_floating_stack() ? "floating stack" : "fixed stack"); + } + + if (UseNUMA) { + if (!Bsd::libnuma_init()) { + UseNUMA = false; + } else { + if ((Bsd::numa_max_node() < 1)) { + // There's only one node(they start from 0), disable NUMA. + UseNUMA = false; + } + } + // With SHM large pages we cannot uncommit a page, so there's not way + // we can make the adaptive lgrp chunk resizing work. If the user specified + // both UseNUMA and UseLargePages (or UseSHM) on the command line - warn and + // disable adaptive resizing. + if (UseNUMA && UseLargePages && UseSHM) { + if (!FLAG_IS_DEFAULT(UseNUMA)) { + if (FLAG_IS_DEFAULT(UseLargePages) && FLAG_IS_DEFAULT(UseSHM)) { + UseLargePages = false; + } else { + warning("UseNUMA is not fully compatible with SHM large pages, disabling adaptive resizing"); + UseAdaptiveSizePolicy = false; + UseAdaptiveNUMAChunkSizing = false; + } + } else { + UseNUMA = false; + } + } + if (!UseNUMA && ForceNUMA) { + UseNUMA = true; + } + } +#endif + + if (MaxFDLimit) { + // set the number of file descriptors to max. print out error + // if getrlimit/setrlimit fails but continue regardless. + struct rlimit nbr_files; + int status = getrlimit(RLIMIT_NOFILE, &nbr_files); + if (status != 0) { + if (PrintMiscellaneous && (Verbose || WizardMode)) + perror("os::init_2 getrlimit failed"); + } else { + nbr_files.rlim_cur = nbr_files.rlim_max; + +#ifdef __APPLE__ + // Darwin returns RLIM_INFINITY for rlim_max, but fails with EINVAL if + // you attempt to use RLIM_INFINITY. As per setrlimit(2), OPEN_MAX must + // be used instead + nbr_files.rlim_cur = MIN(OPEN_MAX, nbr_files.rlim_cur); +#endif + + status = setrlimit(RLIMIT_NOFILE, &nbr_files); + if (status != 0) { + if (PrintMiscellaneous && (Verbose || WizardMode)) + perror("os::init_2 setrlimit failed"); + } + } + } + +#ifndef _ALLBSD_SOURCE + // Initialize lock used to serialize thread creation (see os::create_thread) + Bsd::set_createThread_lock(new Mutex(Mutex::leaf, "createThread_lock", false)); +#endif + + // at-exit methods are called in the reverse order of their registration. + // atexit functions are called on return from main or as a result of a + // call to exit(3C). There can be only 32 of these functions registered + // and atexit() does not set errno. + + if (PerfAllowAtExitRegistration) { + // only register atexit functions if PerfAllowAtExitRegistration is set. + // atexit functions can be delayed until process exit time, which + // can be problematic for embedded VM situations. Embedded VMs should + // call DestroyJavaVM() to assure that VM resources are released. + + // note: perfMemory_exit_helper atexit function may be removed in + // the future if the appropriate cleanup code can be added to the + // VM_Exit VMOperation's doit method. + if (atexit(perfMemory_exit_helper) != 0) { + warning("os::init2 atexit(perfMemory_exit_helper) failed"); + } + } + + // initialize thread priority policy + prio_init(); + +#ifdef __APPLE__ + // dynamically link to objective c gc registration + void *handleLibObjc = dlopen(OBJC_LIB, RTLD_LAZY); + if (handleLibObjc != NULL) { + objc_registerThreadWithCollectorFunction = (objc_registerThreadWithCollector_t) dlsym(handleLibObjc, OBJC_GCREGISTER); + } +#endif + + return JNI_OK; +} + +// this is called at the end of vm_initialization +void os::init_3(void) { } + +// Mark the polling page as unreadable +void os::make_polling_page_unreadable(void) { + if( !guard_memory((char*)_polling_page, Bsd::page_size()) ) + fatal("Could not disable polling page"); +}; + +// Mark the polling page as readable +void os::make_polling_page_readable(void) { + if( !bsd_mprotect((char *)_polling_page, Bsd::page_size(), PROT_READ)) { + fatal("Could not enable polling page"); + } +}; + +int os::active_processor_count() { +#ifdef _ALLBSD_SOURCE + return _processor_count; +#else + // Bsd doesn't yet have a (official) notion of processor sets, + // so just return the number of online processors. + int online_cpus = ::sysconf(_SC_NPROCESSORS_ONLN); + assert(online_cpus > 0 && online_cpus <= processor_count(), "sanity check"); + return online_cpus; +#endif +} + +void os::set_native_thread_name(const char *name) { +#if defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5 + // This is only supported in Snow Leopard and beyond + if (name != NULL) { + // Add a "Java: " prefix to the name + char buf[MAXTHREADNAMESIZE]; + snprintf(buf, sizeof(buf), "Java: %s", name); + pthread_setname_np(buf); + } +#endif +} + +bool os::distribute_processes(uint length, uint* distribution) { + // Not yet implemented. + return false; +} + +bool os::bind_to_processor(uint processor_id) { + // Not yet implemented. + return false; +} + +/// + +// Suspends the target using the signal mechanism and then grabs the PC before +// resuming the target. Used by the flat-profiler only +ExtendedPC os::get_thread_pc(Thread* thread) { + // Make sure that it is called by the watcher for the VMThread + assert(Thread::current()->is_Watcher_thread(), "Must be watcher"); + assert(thread->is_VM_thread(), "Can only be called for VMThread"); + + ExtendedPC epc; + + OSThread* osthread = thread->osthread(); + if (do_suspend(osthread)) { + if (osthread->ucontext() != NULL) { + epc = os::Bsd::ucontext_get_pc(osthread->ucontext()); + } else { + // NULL context is unexpected, double-check this is the VMThread + guarantee(thread->is_VM_thread(), "can only be called for VMThread"); + } + do_resume(osthread); + } + // failure means pthread_kill failed for some reason - arguably this is + // a fatal problem, but such problems are ignored elsewhere + + return epc; +} + +int os::Bsd::safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime) +{ +#ifdef _ALLBSD_SOURCE + return pthread_cond_timedwait(_cond, _mutex, _abstime); +#else + if (is_NPTL()) { + return pthread_cond_timedwait(_cond, _mutex, _abstime); + } else { +#ifndef IA64 + // 6292965: BsdThreads 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; + } +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +// debug support + +static address same_page(address x, address y) { + int page_bits = -os::vm_page_size(); + if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) + return x; + else if (x > y) + return (address)(intptr_t(y) | ~page_bits) + 1; + else + return (address)(intptr_t(y) & page_bits); +} + +bool os::find(address addr, outputStream* st) { + Dl_info dlinfo; + memset(&dlinfo, 0, sizeof(dlinfo)); + if (dladdr(addr, &dlinfo)) { + st->print(PTR_FORMAT ": ", addr); + if (dlinfo.dli_sname != NULL) { + st->print("%s+%#x", dlinfo.dli_sname, + addr - (intptr_t)dlinfo.dli_saddr); + } else if (dlinfo.dli_fname) { + st->print("<offset %#x>", addr - (intptr_t)dlinfo.dli_fbase); + } else { + st->print("<absolute address>"); + } + if (dlinfo.dli_fname) { + st->print(" in %s", dlinfo.dli_fname); + } + if (dlinfo.dli_fbase) { + st->print(" at " PTR_FORMAT, dlinfo.dli_fbase); + } + st->cr(); + + if (Verbose) { + // decode some bytes around the PC + address begin = same_page(addr-40, addr); + address end = same_page(addr+40, addr); + address lowest = (address) dlinfo.dli_sname; + if (!lowest) lowest = (address) dlinfo.dli_fbase; + if (begin < lowest) begin = lowest; + Dl_info dlinfo2; + if (dladdr(end, &dlinfo2) && dlinfo2.dli_saddr != dlinfo.dli_saddr + && end > dlinfo2.dli_saddr && dlinfo2.dli_saddr > begin) + end = (address) dlinfo2.dli_saddr; + Disassembler::decode(begin, end, st); + } + return true; + } + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// misc + +// This does not do anything on Bsd. 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, + JavaCallArguments* args, Thread* thread) { + f(value, method, args, thread); +} + +void os::print_statistics() { +} + +int os::message_box(const char* title, const char* message) { + int i; + fdStream err(defaultStream::error_fd()); + for (i = 0; i < 78; i++) err.print_raw("="); + err.cr(); + err.print_raw_cr(title); + for (i = 0; i < 78; i++) err.print_raw("-"); + err.cr(); + err.print_raw_cr(message); + for (i = 0; i < 78; i++) err.print_raw("="); + err.cr(); + + char buf[16]; + // Prevent process from exiting upon "read error" without consuming all CPU + while (::read(0, buf, sizeof(buf)) <= 0) { ::sleep(100); } + + return buf[0] == 'y' || buf[0] == 'Y'; +} + +int os::stat(const char *path, struct stat *sbuf) { + char pathbuf[MAX_PATH]; + if (strlen(path) > MAX_PATH - 1) { + errno = ENAMETOOLONG; + return -1; + } + os::native_path(strcpy(pathbuf, path)); + return ::stat(pathbuf, sbuf); +} + +bool os::check_heap(bool force) { + return true; +} + +int local_vsnprintf(char* buf, size_t count, const char* format, va_list args) { + return ::vsnprintf(buf, count, format, args); +} + +// Is a (classpath) directory empty? +bool os::dir_is_empty(const char* path) { + DIR *dir = NULL; + struct dirent *ptr; + + dir = opendir(path); + if (dir == NULL) return true; + + /* Scan the directory */ + bool result = true; + char buf[sizeof(struct dirent) + MAX_PATH]; + while (result && (ptr = ::readdir(dir)) != NULL) { + if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) { + result = false; + } + } + closedir(dir); + return result; +} + +// This code originates from JDK's sysOpen and open64_w +// from src/solaris/hpi/src/system_md.c + +#ifndef O_DELETE +#define O_DELETE 0x10000 +#endif + +// Open a file. Unlink the file immediately after open returns +// if the specified oflag has the O_DELETE flag set. +// O_DELETE is used only in j2se/src/share/native/java/util/zip/ZipFile.c + +int os::open(const char *path, int oflag, int mode) { + + if (strlen(path) > MAX_PATH - 1) { + errno = ENAMETOOLONG; + return -1; + } + int fd; + int o_delete = (oflag & O_DELETE); + oflag = oflag & ~O_DELETE; + + fd = ::open(path, oflag, mode); + if (fd == -1) return -1; + + //If the open succeeded, the file might still be a directory + { + struct stat buf; + int ret = ::fstat(fd, &buf); + int st_mode = buf.st_mode; + + if (ret != -1) { + if ((st_mode & S_IFMT) == S_IFDIR) { + errno = EISDIR; + ::close(fd); + return -1; + } + } else { + ::close(fd); + return -1; + } + } + + /* + * All file descriptors that are opened in the JVM and not + * specifically destined for a subprocess should have the + * close-on-exec flag set. If we don't set it, then careless 3rd + * party native code might fork and exec without closing all + * appropriate file descriptors (e.g. as we do in closeDescriptors in + * UNIXProcess.c), and this in turn might: + * + * - cause end-of-file to fail to be detected on some file + * descriptors, resulting in mysterious hangs, or + * + * - might cause an fopen in the subprocess to fail on a system + * suffering from bug 1085341. + * + * (Yes, the default setting of the close-on-exec flag is a Unix + * design flaw) + * + * See: + * 1085341: 32-bit stdio routines should support file descriptors >255 + * 4843136: (process) pipe file descriptor from Runtime.exec not being closed + * 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9 + */ +#ifdef FD_CLOEXEC + { + int flags = ::fcntl(fd, F_GETFD); + if (flags != -1) + ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC); + } +#endif + + if (o_delete != 0) { + ::unlink(path); + } + return fd; +} + + +// create binary file, rewriting existing file if required +int os::create_binary_file(const char* path, bool rewrite_existing) { + int oflags = O_WRONLY | O_CREAT; + if (!rewrite_existing) { + oflags |= O_EXCL; + } + return ::open(path, oflags, S_IREAD | S_IWRITE); +} + +// return current position of file pointer +jlong os::current_file_offset(int fd) { + return (jlong)::lseek(fd, (off_t)0, SEEK_CUR); +} + +// move file pointer to the specified offset +jlong os::seek_to_file_offset(int fd, jlong offset) { + return (jlong)::lseek(fd, (off_t)offset, SEEK_SET); +} + +// This code originates from JDK's sysAvailable +// from src/solaris/hpi/src/native_threads/src/sys_api_td.c + +int os::available(int fd, jlong *bytes) { + jlong cur, end; + int mode; + struct stat buf; + + if (::fstat(fd, &buf) >= 0) { + mode = buf.st_mode; + if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { + /* + * XXX: is the following call interruptible? If so, this might + * need to go through the INTERRUPT_IO() wrapper as for other + * blocking, interruptible calls in this file. + */ + int n; + if (::ioctl(fd, FIONREAD, &n) >= 0) { + *bytes = n; + return 1; + } + } + } + if ((cur = ::lseek(fd, 0L, SEEK_CUR)) == -1) { + return 0; + } else if ((end = ::lseek(fd, 0L, SEEK_END)) == -1) { + return 0; + } else if (::lseek(fd, cur, SEEK_SET) == -1) { + return 0; + } + *bytes = end - cur; + return 1; +} + +int os::socket_available(int fd, jint *pbytes) { + if (fd < 0) + return OS_OK; + + int ret; + + RESTARTABLE(::ioctl(fd, FIONREAD, pbytes), ret); + + //%% note ioctl can return 0 when successful, JVM_SocketAvailable + // is expected to return 0 on failure and 1 on success to the jdk. + + return (ret == OS_ERR) ? 0 : 1; +} + +// Map a block of memory. +char* os::map_memory(int fd, const char* file_name, size_t file_offset, + char *addr, size_t bytes, bool read_only, + bool allow_exec) { + int prot; + int flags; + + if (read_only) { + prot = PROT_READ; + flags = MAP_SHARED; + } else { + prot = PROT_READ | PROT_WRITE; + flags = MAP_PRIVATE; + } + + if (allow_exec) { + prot |= PROT_EXEC; + } + + if (addr != NULL) { + flags |= MAP_FIXED; + } + + char* mapped_address = (char*)mmap(addr, (size_t)bytes, prot, flags, + fd, file_offset); + if (mapped_address == MAP_FAILED) { + return NULL; + } + return mapped_address; +} + + +// Remap a block of memory. +char* os::remap_memory(int fd, const char* file_name, size_t file_offset, + char *addr, size_t bytes, bool read_only, + bool allow_exec) { + // same as map_memory() on this OS + return os::map_memory(fd, file_name, file_offset, addr, bytes, read_only, + allow_exec); +} + + +// Unmap a block of memory. +bool os::unmap_memory(char* addr, size_t bytes) { + return munmap(addr, bytes) == 0; +} + +#ifndef _ALLBSD_SOURCE +static jlong slow_thread_cpu_time(Thread *thread, bool user_sys_cpu_time); + +static clockid_t thread_cpu_clockid(Thread* thread) { + pthread_t tid = thread->osthread()->pthread_id(); + clockid_t clockid; + + // Get thread clockid + int rc = os::Bsd::pthread_getcpuclockid(tid, &clockid); + assert(rc == 0, "pthread_getcpuclockid is expected to return 0 code"); + return clockid; +} +#endif + +// current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool) +// are used by JVM M&M and JVMTI to get user+sys or user CPU time +// of a thread. +// +// current_thread_cpu_time() and thread_cpu_time(Thread*) returns +// the fast estimate available on the platform. + +jlong os::current_thread_cpu_time() { +#ifdef __APPLE__ + return os::thread_cpu_time(Thread::current(), true /* user + sys */); +#elif !defined(_ALLBSD_SOURCE) + if (os::Bsd::supports_fast_thread_cpu_time()) { + return os::Bsd::fast_thread_cpu_time(CLOCK_THREAD_CPUTIME_ID); + } else { + // return user + sys since the cost is the same + return slow_thread_cpu_time(Thread::current(), true /* user + sys */); + } +#endif +} + +jlong os::thread_cpu_time(Thread* thread) { +#ifndef _ALLBSD_SOURCE + // consistent with what current_thread_cpu_time() returns + if (os::Bsd::supports_fast_thread_cpu_time()) { + return os::Bsd::fast_thread_cpu_time(thread_cpu_clockid(thread)); + } else { + return slow_thread_cpu_time(thread, true /* user + sys */); + } +#endif +} + +jlong os::current_thread_cpu_time(bool user_sys_cpu_time) { +#ifdef __APPLE__ + return os::thread_cpu_time(Thread::current(), user_sys_cpu_time); +#elif !defined(_ALLBSD_SOURCE) + if (user_sys_cpu_time && os::Bsd::supports_fast_thread_cpu_time()) { + return os::Bsd::fast_thread_cpu_time(CLOCK_THREAD_CPUTIME_ID); + } else { + return slow_thread_cpu_time(Thread::current(), user_sys_cpu_time); + } +#endif +} + +jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) { +#ifdef __APPLE__ + struct thread_basic_info tinfo; + mach_msg_type_number_t tcount = THREAD_INFO_MAX; + kern_return_t kr; + mach_port_t mach_thread; + + mach_thread = pthread_mach_thread_np(thread->osthread()->thread_id()); + kr = thread_info(mach_thread, THREAD_BASIC_INFO, (thread_info_t)&tinfo, &tcount); + if (kr != KERN_SUCCESS) + return -1; + + if (user_sys_cpu_time) { + jlong nanos; + nanos = ((jlong) tinfo.system_time.seconds + tinfo.user_time.seconds) * (jlong)1000000000; + nanos += ((jlong) tinfo.system_time.microseconds + (jlong) tinfo.user_time.microseconds) * (jlong)1000; + return nanos; + } else { + return ((jlong)tinfo.user_time.seconds * 1000000000) + ((jlong)tinfo.user_time.microseconds * (jlong)1000); + } +#elif !defined(_ALLBSD_SOURCE) + if (user_sys_cpu_time && os::Bsd::supports_fast_thread_cpu_time()) { + return os::Bsd::fast_thread_cpu_time(thread_cpu_clockid(thread)); + } else { + return slow_thread_cpu_time(thread, user_sys_cpu_time); + } +#endif +} + +#ifndef _ALLBSD_SOURCE +// +// -1 on error. +// + +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 (bsd 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 Bsd 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. + if (proc_task_unchecked && os::Bsd::is_NPTL()) { + // This is executed only once + proc_task_unchecked = false; + fp = fopen("/proc/self/task", "r"); + if (fp != NULL) { + proc_stat_path = "/proc/self/task/%d/stat"; + fclose(fp); + } + } + + sprintf(proc_name, proc_stat_path, tid); + fp = fopen(proc_name, "r"); + if ( fp == NULL ) return -1; + statlen = fread(stat, 1, 2047, fp); + stat[statlen] = '\0'; + fclose(fp); + + // Skip pid and the command string. Note that we could be dealing with + // weird command names, e.g. user could decide to rename java launcher + // to "java 1.4.2 :)", then the stat file would look like + // 1234 (java 1.4.2 :)) R ... ... + // 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 + do s++; while (isspace(*s)); + + count = sscanf(s,"%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu", + &cdummy, &idummy, &idummy, &idummy, &idummy, &idummy, + &ldummy, &ldummy, &ldummy, &ldummy, &ldummy, + &user_time, &sys_time); + if ( count != 13 ) 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); + } +} +#endif + +void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) { + info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits + info_ptr->may_skip_backward = false; // elapsed time not wall time + info_ptr->may_skip_forward = false; // elapsed time not wall time + info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned +} + +void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) { + info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits + info_ptr->may_skip_backward = false; // elapsed time not wall time + info_ptr->may_skip_forward = false; // elapsed time not wall time + info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned +} + +bool os::is_thread_cpu_time_supported() { +#ifdef __APPLE__ + return true; +#elif defined(_ALLBSD_SOURCE) + return false; +#else + return true; +#endif +} + +// System loadavg support. Returns -1 if load average cannot be obtained. +// Bsd doesn't yet have a (official) notion of processor sets, +// so just return the system wide load average. +int os::loadavg(double loadavg[], int nelem) { + return ::getloadavg(loadavg, nelem); +} + +void os::pause() { + char filename[MAX_PATH]; + if (PauseAtStartupFile && PauseAtStartupFile[0]) { + jio_snprintf(filename, MAX_PATH, PauseAtStartupFile); + } else { + jio_snprintf(filename, MAX_PATH, "./vm.paused.%d", current_process_id()); + } + + int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd != -1) { + struct stat buf; + ::close(fd); + while (::stat(filename, &buf) == 0) { + (void)::poll(NULL, 0, 100); + } + } else { + jio_fprintf(stderr, + "Could not open pause file '%s', continuing immediately.\n", filename); + } +} + + +// Refer to the comments in os_solaris.cpp park-unpark. +// +// Beware -- Some versions of NPTL embody a flaw where pthread_cond_timedwait() can +// hang indefinitely. For instance NPTL 0.60 on 2.4.21-4ELsmp is vulnerable. +// For specifics regarding the bug see GLIBC BUGID 261237 : +// http://www.mail-archive.com/debian-glibc@lists.debian.org/msg10837.html. +// Briefly, pthread_cond_timedwait() calls with an expiry time that's not in the future +// will either hang or corrupt the condvar, resulting in subsequent hangs if the condvar +// is used. (The simple C test-case provided in the GLIBC bug report manifests the +// hang). The JVM is vulernable via sleep(), Object.wait(timo), LockSupport.parkNanos() +// and monitorenter when we're using 1-0 locking. All those operations may result in +// calls to pthread_cond_timedwait(). Using LD_ASSUME_KERNEL to use an older version +// of libpthread avoids the problem, but isn't practical. +// +// Possible remedies: +// +// 1. Establish a minimum relative wait time. 50 to 100 msecs seems to work. +// This is palliative and probabilistic, however. If the thread is preempted +// between the call to compute_abstime() and pthread_cond_timedwait(), more +// than the minimum period may have passed, and the abstime may be stale (in the +// past) resultin in a hang. Using this technique reduces the odds of a hang +// but the JVM is still vulnerable, particularly on heavily loaded systems. +// +// 2. Modify park-unpark to use per-thread (per ParkEvent) pipe-pairs instead +// of the usual flag-condvar-mutex idiom. The write side of the pipe is set +// NDELAY. unpark() reduces to write(), park() reduces to read() and park(timo) +// reduces to poll()+read(). This works well, but consumes 2 FDs per extant +// thread. +// +// 3. Embargo pthread_cond_timedwait() and implement a native "chron" thread +// that manages timeouts. We'd emulate pthread_cond_timedwait() by enqueuing +// a timeout request to the chron thread and then blocking via pthread_cond_wait(). +// This also works well. In fact it avoids kernel-level scalability impediments +// on certain platforms that don't handle lots of active pthread_cond_timedwait() +// timers in a graceful fashion. +// +// 4. When the abstime value is in the past it appears that control returns +// correctly from pthread_cond_timedwait(), but the condvar is left corrupt. +// Subsequent timedwait/wait calls may hang indefinitely. Given that, we +// can avoid the problem by reinitializing the condvar -- by cond_destroy() +// followed by cond_init() -- after all calls to pthread_cond_timedwait(). +// It may be possible to avoid reinitialization by checking the return +// value from pthread_cond_timedwait(). In addition to reinitializing the +// condvar we must establish the invariant that cond_signal() is only called +// within critical sections protected by the adjunct mutex. This prevents +// cond_signal() from "seeing" a condvar that's in the midst of being +// reinitialized or that is corrupt. Sadly, this invariant obviates the +// desirable signal-after-unlock optimization that avoids futile context switching. +// +// I'm also concerned that some versions of NTPL might allocate an auxilliary +// structure when a condvar is used or initialized. cond_destroy() would +// release the helper structure. Our reinitialize-after-timedwait fix +// put excessive stress on malloc/free and locks protecting the c-heap. +// +// We currently use (4). See the WorkAroundNTPLTimedWaitHang flag. +// It may be possible to refine (4) by checking the kernel and NTPL verisons +// and only enabling the work-around for vulnerable environments. + +// utility to compute the abstime argument to timedwait: +// millis is the relative timeout time +// abstime will be the absolute timeout time +// TODO: replace compute_abstime() with unpackTime() + +static struct timespec* compute_abstime(struct timespec* abstime, jlong millis) { + if (millis < 0) millis = 0; + struct timeval now; + int status = gettimeofday(&now, NULL); + assert(status == 0, "gettimeofday"); + jlong seconds = millis / 1000; + millis %= 1000; + if (seconds > 50000000) { // see man cond_timedwait(3T) + seconds = 50000000; + } + abstime->tv_sec = now.tv_sec + seconds; + long usec = now.tv_usec + millis * 1000; + if (usec >= 1000000) { + abstime->tv_sec += 1; + usec -= 1000000; + } + abstime->tv_nsec = usec * 1000; + return abstime; +} + + +// Test-and-clear _Event, always leaves _Event set to 0, returns immediately. +// Conceptually TryPark() should be equivalent to park(0). + +int os::PlatformEvent::TryPark() { + for (;;) { + const int v = _Event ; + guarantee ((v == 0) || (v == 1), "invariant") ; + if (Atomic::cmpxchg (0, &_Event, v) == v) return v ; + } +} + +void os::PlatformEvent::park() { // AKA "down()" + // Invariant: Only the thread associated with the Event/PlatformEvent + // may call park(). + // TODO: assert that _Assoc != NULL or _Assoc == Self + int v ; + for (;;) { + v = _Event ; + if (Atomic::cmpxchg (v-1, &_Event, v) == v) break ; + } + guarantee (v >= 0, "invariant") ; + if (v == 0) { + // Do this the hard way by blocking ... + int status = pthread_mutex_lock(_mutex); + assert_status(status == 0, status, "mutex_lock"); + guarantee (_nParked == 0, "invariant") ; + ++ _nParked ; + while (_Event < 0) { + status = pthread_cond_wait(_cond, _mutex); + // for some reason, under 2.7 lwp_cond_wait() may return ETIME ... + // Treat this the same as if the wait was interrupted + if (status == ETIMEDOUT) { status = EINTR; } + assert_status(status == 0 || status == EINTR, status, "cond_wait"); + } + -- _nParked ; + + // In theory we could move the ST of 0 into _Event past the unlock(), + // but then we'd need a MEMBAR after the ST. + _Event = 0 ; + status = pthread_mutex_unlock(_mutex); + assert_status(status == 0, status, "mutex_unlock"); + } + guarantee (_Event >= 0, "invariant") ; +} + +int os::PlatformEvent::park(jlong millis) { + guarantee (_nParked == 0, "invariant") ; + + int v ; + for (;;) { + v = _Event ; + if (Atomic::cmpxchg (v-1, &_Event, v) == v) break ; + } + guarantee (v >= 0, "invariant") ; + if (v != 0) return OS_OK ; + + // We do this the hard way, by blocking the thread. + // Consider enforcing a minimum timeout value. + struct timespec abst; + compute_abstime(&abst, millis); + + int ret = OS_TIMEOUT; + int status = pthread_mutex_lock(_mutex); + assert_status(status == 0, status, "mutex_lock"); + guarantee (_nParked == 0, "invariant") ; + ++_nParked ; + + // Object.wait(timo) will return because of + // (a) notification + // (b) timeout + // (c) thread.interrupt + // + // Thread.interrupt and object.notify{All} both call Event::set. + // That is, we treat thread.interrupt as a special case of notification. + // The underlying Solaris implementation, cond_timedwait, admits + // spurious/premature wakeups, but the JLS/JVM spec prevents the + // JVM from making those visible to Java code. As such, we must + // filter out spurious wakeups. We assume all ETIME returns are valid. + // + // TODO: properly differentiate simultaneous notify+interrupt. + // In that case, we should propagate the notify to another waiter. + + while (_Event < 0) { + status = os::Bsd::safe_cond_timedwait(_cond, _mutex, &abst); + if (status != 0 && WorkAroundNPTLTimedWaitHang) { + pthread_cond_destroy (_cond); + pthread_cond_init (_cond, NULL) ; + } + assert_status(status == 0 || status == EINTR || + status == ETIMEDOUT, + status, "cond_timedwait"); + if (!FilterSpuriousWakeups) break ; // previous semantics + if (status == ETIMEDOUT) break ; + // We consume and ignore EINTR and spurious wakeups. + } + --_nParked ; + if (_Event >= 0) { + ret = OS_OK; + } + _Event = 0 ; + status = pthread_mutex_unlock(_mutex); + assert_status(status == 0, status, "mutex_unlock"); + assert (_nParked == 0, "invariant") ; + return ret; +} + +void os::PlatformEvent::unpark() { + int v, AnyWaiters ; + for (;;) { + v = _Event ; + if (v > 0) { + // The LD of _Event could have reordered or be satisfied + // by a read-aside from this processor's write buffer. + // To avoid problems execute a barrier and then + // ratify the value. + OrderAccess::fence() ; + if (_Event == v) return ; + continue ; + } + if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ; + } + if (v < 0) { + // Wait for the thread associated with the event to vacate + int status = pthread_mutex_lock(_mutex); + assert_status(status == 0, status, "mutex_lock"); + AnyWaiters = _nParked ; + assert (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ; + if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { + AnyWaiters = 0 ; + pthread_cond_signal (_cond); + } + status = pthread_mutex_unlock(_mutex); + assert_status(status == 0, status, "mutex_unlock"); + if (AnyWaiters != 0) { + status = pthread_cond_signal(_cond); + assert_status(status == 0, status, "cond_signal"); + } + } + + // Note that we signal() _after dropping the lock for "immortal" Events. + // This is safe and avoids a common class of futile wakeups. In rare + // circumstances this can cause a thread to return prematurely from + // cond_{timed}wait() but the spurious wakeup is benign and the victim will + // simply re-test the condition and re-park itself. +} + + +// JSR166 +// ------------------------------------------------------- + +/* + * The solaris and bsd implementations of park/unpark are fairly + * conservative for now, but can be improved. They currently use a + * mutex/condvar pair, plus a a count. + * Park decrements count if > 0, else does a condvar wait. Unpark + * sets count to 1 and signals condvar. Only one thread ever waits + * on the condvar. Contention seen when trying to park implies that someone + * is unparking you, so don't wait. And spurious returns are fine, so there + * is no need to track notifications. + */ + + +#define NANOSECS_PER_SEC 1000000000 +#define NANOSECS_PER_MILLISEC 1000000 +#define MAX_SECS 100000000 +/* + * This code is common to bsd and solaris and will be moved to a + * common place in dolphin. + * + * The passed in time value is either a relative time in nanoseconds + * or an absolute time in milliseconds. Either way it has to be unpacked + * into suitable seconds and nanoseconds components and stored in the + * given timespec structure. + * Given time is a 64-bit value and the time_t used in the timespec is only + * a signed-32-bit value (except on 64-bit Bsd) we have to watch for + * overflow if times way in the future are given. Further on Solaris versions + * prior to 10 there is a restriction (see cond_timedwait) that the specified + * number of seconds, in abstime, is less than current_time + 100,000,000. + * As it will be 28 years before "now + 100000000" will overflow we can + * ignore overflow and just impose a hard-limit on seconds using the value + * of "now + 100,000,000". This places a limit on the timeout of about 3.17 + * years from "now". + */ + +static void unpackTime(struct timespec* absTime, bool isAbsolute, jlong time) { + assert (time > 0, "convertTime"); + + struct timeval now; + int status = gettimeofday(&now, NULL); + assert(status == 0, "gettimeofday"); + + time_t max_secs = now.tv_sec + MAX_SECS; + + if (isAbsolute) { + jlong secs = time / 1000; + if (secs > max_secs) { + absTime->tv_sec = max_secs; + } + else { + absTime->tv_sec = secs; + } + absTime->tv_nsec = (time % 1000) * NANOSECS_PER_MILLISEC; + } + else { + jlong secs = time / NANOSECS_PER_SEC; + if (secs >= MAX_SECS) { + absTime->tv_sec = max_secs; + absTime->tv_nsec = 0; + } + else { + absTime->tv_sec = now.tv_sec + secs; + absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_usec*1000; + if (absTime->tv_nsec >= NANOSECS_PER_SEC) { + absTime->tv_nsec -= NANOSECS_PER_SEC; + ++absTime->tv_sec; // note: this must be <= max_secs + } + } + } + assert(absTime->tv_sec >= 0, "tv_sec < 0"); + assert(absTime->tv_sec <= max_secs, "tv_sec > max_secs"); + assert(absTime->tv_nsec >= 0, "tv_nsec < 0"); + assert(absTime->tv_nsec < NANOSECS_PER_SEC, "tv_nsec >= nanos_per_sec"); +} + +void Parker::park(bool isAbsolute, jlong time) { + // Optional fast-path check: + // Return immediately if a permit is available. + if (_counter > 0) { + _counter = 0 ; + OrderAccess::fence(); + return ; + } + + Thread* thread = Thread::current(); + assert(thread->is_Java_thread(), "Must be JavaThread"); + JavaThread *jt = (JavaThread *)thread; + + // Optional optimization -- avoid state transitions if there's an interrupt pending. + // Check interrupt before trying to wait + if (Thread::is_interrupted(thread, false)) { + return; + } + + // Next, demultiplex/decode time arguments + struct timespec absTime; + if (time < 0 || (isAbsolute && time == 0) ) { // don't wait at all + return; + } + if (time > 0) { + unpackTime(&absTime, isAbsolute, time); + } + + + // Enter safepoint region + // Beware of deadlocks such as 6317397. + // The per-thread Parker:: mutex is a classic leaf-lock. + // In particular a thread must never block on the Threads_lock while + // holding the Parker:: mutex. If safepoints are pending both the + // the ThreadBlockInVM() CTOR and DTOR may grab Threads_lock. + ThreadBlockInVM tbivm(jt); + + // Don't wait if cannot get lock since interference arises from + // unblocking. Also. check interrupt before trying wait + if (Thread::is_interrupted(thread, false) || pthread_mutex_trylock(_mutex) != 0) { + return; + } + + int status ; + if (_counter > 0) { // no wait needed + _counter = 0; + status = pthread_mutex_unlock(_mutex); + assert (status == 0, "invariant") ; + OrderAccess::fence(); + return; + } + +#ifdef ASSERT + // Don't catch signals while blocked; let the running threads have the signals. + // (This allows a debugger to break into the running thread.) + sigset_t oldsigs; + sigset_t* allowdebug_blocked = os::Bsd::allowdebug_blocked_signals(); + pthread_sigmask(SIG_BLOCK, allowdebug_blocked, &oldsigs); +#endif + + OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); + jt->set_suspend_equivalent(); + // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() + + if (time == 0) { + status = pthread_cond_wait (_cond, _mutex) ; + } else { + status = os::Bsd::safe_cond_timedwait (_cond, _mutex, &absTime) ; + if (status != 0 && WorkAroundNPTLTimedWaitHang) { + pthread_cond_destroy (_cond) ; + pthread_cond_init (_cond, NULL); + } + } + assert_status(status == 0 || status == EINTR || + status == ETIMEDOUT, + status, "cond_timedwait"); + +#ifdef ASSERT + pthread_sigmask(SIG_SETMASK, &oldsigs, NULL); +#endif + + _counter = 0 ; + status = pthread_mutex_unlock(_mutex) ; + assert_status(status == 0, status, "invariant") ; + // If externally suspended while waiting, re-suspend + if (jt->handle_special_suspend_equivalent_condition()) { + jt->java_suspend_self(); + } + + OrderAccess::fence(); +} + +void Parker::unpark() { + int s, status ; + status = pthread_mutex_lock(_mutex); + assert (status == 0, "invariant") ; + s = _counter; + _counter = 1; + if (s < 1) { + if (WorkAroundNPTLTimedWaitHang) { + status = pthread_cond_signal (_cond) ; + assert (status == 0, "invariant") ; + status = pthread_mutex_unlock(_mutex); + assert (status == 0, "invariant") ; + } else { + status = pthread_mutex_unlock(_mutex); + assert (status == 0, "invariant") ; + status = pthread_cond_signal (_cond) ; + assert (status == 0, "invariant") ; + } + } else { + pthread_mutex_unlock(_mutex); + assert (status == 0, "invariant") ; + } +} + + +/* Darwin has no "environ" in a dynamic library. */ +#ifdef __APPLE__ +#include <crt_externs.h> +#define environ (*_NSGetEnviron()) +#else +extern char** environ; +#endif + +// Run the specified command in a separate process. Return its exit value, +// or -1 on failure (e.g. can't fork a new process). +// Unlike system(), this function can be called from signal handler. It +// doesn't block SIGINT et al. +int os::fork_and_exec(char* cmd) { + const char * argv[4] = {"sh", "-c", cmd, NULL}; + + // fork() in BsdThreads/NPTL is not async-safe. It needs to run + // pthread_atfork handlers and reset pthread library. All we need is a + // separate process to execve. Make a direct syscall to fork process. + // On IA64 there's no fork syscall, we have to use fork() and hope for + // the best... + pid_t pid = fork(); + + if (pid < 0) { + // fork failed + return -1; + + } else if (pid == 0) { + // child process + + // execve() in BsdThreads will call pthread_kill_other_threads_np() + // first to kill every thread on the thread list. Because this list is + // not reset by fork() (see notes above), execve() will instead kill + // every thread in the parent process. We know this is the only thread + // in the new process, so make a system call directly. + // IA64 should use normal execve() from glibc to match the glibc fork() + // above. + execve("/bin/sh", (char* const*)argv, environ); + + // execve failed + _exit(-1); + + } else { + // copied from J2SE ..._waitForProcessExit() in UNIXProcess_md.c; we don't + // care about the actual exit code, for now. + + int status; + + // Wait for the child process to exit. This returns immediately if + // the child has already exited. */ + while (waitpid(pid, &status, 0) < 0) { + switch (errno) { + case ECHILD: return 0; + case EINTR: break; + default: return -1; + } + } + + if (WIFEXITED(status)) { + // The child exited normally; get its exit code. + return WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) { + // The child exited because of a signal + // The best value to return is 0x80 + signal number, + // because that is what all Unix shells do, and because + // it allows callers to distinguish between process exit and + // process death by signal. + return 0x80 + WTERMSIG(status); + } else { + // Unknown exit code; pass it through + return status; + } + } +} + +// is_headless_jre() +// +// Test for the existence of libmawt in motif21 or xawt directories +// in order to report if we are running in a headless jre +// +bool os::is_headless_jre() { + struct stat statbuf; + char buf[MAXPATHLEN]; + char libmawtpath[MAXPATHLEN]; + const char *xawtstr = "/xawt/libmawt" JNI_LIB_SUFFIX; + const char *motifstr = "/motif21/libmawt" JNI_LIB_SUFFIX; + char *p; + + // Get path to libjvm.so + os::jvm_path(buf, sizeof(buf)); + + // Get rid of libjvm.so + p = strrchr(buf, '/'); + if (p == NULL) return false; + else *p = '\0'; + + // Get rid of client or server + p = strrchr(buf, '/'); + if (p == NULL) return false; + else *p = '\0'; + + // check xawt/libmawt.so + strcpy(libmawtpath, buf); + strcat(libmawtpath, xawtstr); + if (::stat(libmawtpath, &statbuf) == 0) return false; + + // check motif21/libmawt.so + strcpy(libmawtpath, buf); + strcat(libmawtpath, motifstr); + if (::stat(libmawtpath, &statbuf) == 0) return false; + + return true; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/os_bsd.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,368 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_BSD_VM_OS_BSD_HPP +#define OS_BSD_VM_OS_BSD_HPP + +// Bsd_OS defines the interface to Bsd operating systems + +/* pthread_getattr_np comes with BsdThreads-0.9-7 on RedHat 7.1 */ +typedef int (*pthread_getattr_func_type) (pthread_t, pthread_attr_t *); + +#ifdef __APPLE__ +// Mac OS X doesn't support clock_gettime. Stub out the type, it is +// unused +typedef int clockid_t; +#endif + +class Bsd { + friend class os; + + // For signal-chaining +#define MAXSIGNUM 32 + static struct sigaction sigact[MAXSIGNUM]; // saved preinstalled sigactions + static unsigned int sigs; // mask of signals that have + // preinstalled signal handlers + static bool libjsig_is_loaded; // libjsig that interposes sigaction(), + // __sigaction(), signal() is loaded + static struct sigaction *(*get_signal_action)(int); + static struct sigaction *get_preinstalled_handler(int); + static void save_preinstalled_handler(int, struct sigaction&); + + static void check_signal_handler(int sig); + + // For signal flags diagnostics + static int sigflags[MAXSIGNUM]; + + static int (*_clock_gettime)(clockid_t, struct timespec *); +#ifndef _ALLBSD_SOURCE + static int (*_pthread_getcpuclockid)(pthread_t, clockid_t *); + + static address _initial_thread_stack_bottom; + static uintptr_t _initial_thread_stack_size; + + static const char *_glibc_version; + static const char *_libpthread_version; + + static bool _is_floating_stack; + static bool _is_NPTL; + static bool _supports_fast_thread_cpu_time; +#endif + + static GrowableArray<int>* _cpu_to_node; + + protected: + + static julong _physical_memory; + static pthread_t _main_thread; +#ifndef _ALLBSD_SOURCE + static Mutex* _createThread_lock; +#endif + static int _page_size; + + static julong available_memory(); + static julong physical_memory() { return _physical_memory; } + static void initialize_system_info(); + +#ifndef _ALLBSD_SOURCE + static void set_glibc_version(const char *s) { _glibc_version = s; } + static void set_libpthread_version(const char *s) { _libpthread_version = s; } +#endif + + static bool supports_variable_stack_size(); + +#ifndef _ALLBSD_SOURCE + static void set_is_NPTL() { _is_NPTL = true; } + static void set_is_BsdThreads() { _is_NPTL = false; } + static void set_is_floating_stack() { _is_floating_stack = true; } +#endif + + static void rebuild_cpu_to_node_map(); + static GrowableArray<int>* cpu_to_node() { return _cpu_to_node; } + + static bool hugetlbfs_sanity_check(bool warn, size_t page_size); + + public: + + static void init_thread_fpu_state(); +#ifndef _ALLBSD_SOURCE + static int get_fpu_control_word(); + static void set_fpu_control_word(int fpu_control); +#endif + static pthread_t main_thread(void) { return _main_thread; } + +#ifndef _ALLBSD_SOURCE + // returns kernel thread id (similar to LWP id on Solaris), which can be + // used to access /proc + static pid_t gettid(); + static void set_createThread_lock(Mutex* lk) { _createThread_lock = lk; } + static Mutex* createThread_lock(void) { return _createThread_lock; } +#endif + static void hotspot_sigmask(Thread* thread); + +#ifndef _ALLBSD_SOURCE + static address initial_thread_stack_bottom(void) { return _initial_thread_stack_bottom; } + static uintptr_t initial_thread_stack_size(void) { return _initial_thread_stack_size; } +#endif + static bool is_initial_thread(void); + + static int page_size(void) { return _page_size; } + static void set_page_size(int val) { _page_size = val; } + + static address ucontext_get_pc(ucontext_t* uc); + static intptr_t* ucontext_get_sp(ucontext_t* uc); + static intptr_t* ucontext_get_fp(ucontext_t* uc); + + // For Analyzer Forte AsyncGetCallTrace profiling support: + // + // This interface should be declared in os_bsd_i486.hpp, but + // that file provides extensions to the os class and not the + // Bsd class. + static ExtendedPC fetch_frame_from_ucontext(Thread* thread, ucontext_t* uc, + intptr_t** ret_sp, intptr_t** ret_fp); + + // This boolean allows users to forward their own non-matching signals + // to JVM_handle_bsd_signal, harmlessly. + static bool signal_handlers_are_installed; + + static int get_our_sigflags(int); + static void set_our_sigflags(int, int); + static void signal_sets_init(); + static void install_signal_handlers(); + static void set_signal_handler(int, bool); + static bool is_sig_ignored(int sig); + + static sigset_t* unblocked_signals(); + static sigset_t* vm_signals(); + static sigset_t* allowdebug_blocked_signals(); + + // For signal-chaining + static struct sigaction *get_chained_signal_action(int sig); + static bool chained_handler(int sig, siginfo_t* siginfo, void* context); + +#ifndef _ALLBSD_SOURCE + // GNU libc and libpthread version strings + static const char *glibc_version() { return _glibc_version; } + static const char *libpthread_version() { return _libpthread_version; } + + // NPTL or BsdThreads? + static bool is_BsdThreads() { return !_is_NPTL; } + static bool is_NPTL() { return _is_NPTL; } + + // NPTL is always floating stack. BsdThreads could be using floating + // stack or fixed stack. + static bool is_floating_stack() { return _is_floating_stack; } + + static void libpthread_init(); + static bool libnuma_init(); + static void* libnuma_dlsym(void* handle, const char* name); +#endif + // Minimum stack size a thread can be created with (allowing + // the VM to completely create the thread and enter user code) + static size_t min_stack_allowed; + + // Return default stack size or guard size for the specified thread type + static size_t default_stack_size(os::ThreadType thr_type); + static size_t default_guard_size(os::ThreadType thr_type); + +#ifndef _ALLBSD_SOURCE + static void capture_initial_stack(size_t max_size); + + // Stack overflow handling + static bool manually_expand_stack(JavaThread * t, address addr); + static int max_register_window_saves_before_flushing(); +#endif + + // Real-time clock functions + static void clock_init(void); + +#ifndef _ALLBSD_SOURCE + // fast POSIX clocks support + static void fast_thread_clock_init(void); +#endif + + static bool supports_monotonic_clock() { + return _clock_gettime != NULL; + } + + static int clock_gettime(clockid_t clock_id, struct timespec *tp) { + return _clock_gettime ? _clock_gettime(clock_id, tp) : -1; + } + +#ifndef _ALLBSD_SOURCE + static int pthread_getcpuclockid(pthread_t tid, clockid_t *clock_id) { + return _pthread_getcpuclockid ? _pthread_getcpuclockid(tid, clock_id) : -1; + } + + static bool supports_fast_thread_cpu_time() { + return _supports_fast_thread_cpu_time; + } + + static jlong fast_thread_cpu_time(clockid_t clockid); +#endif + + // Stack repair handling + + // none present + + // BsdThreads work-around for 6292965 + static int safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime); + + + // Bsd suspend/resume support - this helper is a shadow of its former + // self now that low-level suspension is barely used, and old workarounds + // for BsdThreads are no longer needed. + class SuspendResume { + private: + volatile int _suspend_action; + // values for suspend_action: + #define SR_NONE (0x00) + #define SR_SUSPEND (0x01) // suspend request + #define SR_CONTINUE (0x02) // resume request + + volatile jint _state; + // values for _state: + SR_NONE + #define SR_SUSPENDED (0x20) + public: + SuspendResume() { _suspend_action = SR_NONE; _state = SR_NONE; } + + int suspend_action() const { return _suspend_action; } + void set_suspend_action(int x) { _suspend_action = x; } + + // atomic updates for _state + void set_suspended() { + jint temp, temp2; + do { + temp = _state; + temp2 = Atomic::cmpxchg(temp | SR_SUSPENDED, &_state, temp); + } while (temp2 != temp); + } + void clear_suspended() { + jint temp, temp2; + do { + temp = _state; + temp2 = Atomic::cmpxchg(temp & ~SR_SUSPENDED, &_state, temp); + } while (temp2 != temp); + } + bool is_suspended() { return _state & SR_SUSPENDED; } + + #undef SR_SUSPENDED + }; + +private: + typedef int (*sched_getcpu_func_t)(void); + typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen); + typedef int (*numa_max_node_func_t)(void); + typedef int (*numa_available_func_t)(void); + typedef int (*numa_tonode_memory_func_t)(void *start, size_t size, int node); + typedef void (*numa_interleave_memory_func_t)(void *start, size_t size, unsigned long *nodemask); + + static sched_getcpu_func_t _sched_getcpu; + static numa_node_to_cpus_func_t _numa_node_to_cpus; + static numa_max_node_func_t _numa_max_node; + static numa_available_func_t _numa_available; + static numa_tonode_memory_func_t _numa_tonode_memory; + static numa_interleave_memory_func_t _numa_interleave_memory; + static unsigned long* _numa_all_nodes; + + static void set_sched_getcpu(sched_getcpu_func_t func) { _sched_getcpu = func; } + static void set_numa_node_to_cpus(numa_node_to_cpus_func_t func) { _numa_node_to_cpus = func; } + static void set_numa_max_node(numa_max_node_func_t func) { _numa_max_node = func; } + static void set_numa_available(numa_available_func_t func) { _numa_available = func; } + static void set_numa_tonode_memory(numa_tonode_memory_func_t func) { _numa_tonode_memory = func; } + static void set_numa_interleave_memory(numa_interleave_memory_func_t func) { _numa_interleave_memory = func; } + static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes = ptr; } +public: + static int sched_getcpu() { return _sched_getcpu != NULL ? _sched_getcpu() : -1; } + static int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) { + return _numa_node_to_cpus != NULL ? _numa_node_to_cpus(node, buffer, bufferlen) : -1; + } + static int numa_max_node() { return _numa_max_node != NULL ? _numa_max_node() : -1; } + static int numa_available() { return _numa_available != NULL ? _numa_available() : -1; } + static int numa_tonode_memory(void *start, size_t size, int node) { + return _numa_tonode_memory != NULL ? _numa_tonode_memory(start, size, node) : -1; + } + static void numa_interleave_memory(void *start, size_t size) { + if (_numa_interleave_memory != NULL && _numa_all_nodes != NULL) { + _numa_interleave_memory(start, size, _numa_all_nodes); + } + } + static int get_node_by_cpu(int cpu_id); +}; + + +class PlatformEvent : public CHeapObj { + private: + double CachePad [4] ; // increase odds that _mutex is sole occupant of cache line + volatile int _Event ; + volatile int _nParked ; + pthread_mutex_t _mutex [1] ; + pthread_cond_t _cond [1] ; + double PostPad [2] ; + Thread * _Assoc ; + + public: // TODO-FIXME: make dtor private + ~PlatformEvent() { guarantee (0, "invariant") ; } + + public: + PlatformEvent() { + int status; + status = pthread_cond_init (_cond, NULL); + assert_status(status == 0, status, "cond_init"); + status = pthread_mutex_init (_mutex, NULL); + assert_status(status == 0, status, "mutex_init"); + _Event = 0 ; + _nParked = 0 ; + _Assoc = NULL ; + } + + // Use caution with reset() and fired() -- they may require MEMBARs + void reset() { _Event = 0 ; } + int fired() { return _Event; } + void park () ; + void unpark () ; + int TryPark () ; + int park (jlong millis) ; + void SetAssociation (Thread * a) { _Assoc = a ; } +} ; + +class PlatformParker : public CHeapObj { + protected: + pthread_mutex_t _mutex [1] ; + pthread_cond_t _cond [1] ; + + public: // TODO-FIXME: make dtor private + ~PlatformParker() { guarantee (0, "invariant") ; } + + public: + PlatformParker() { + int status; + status = pthread_cond_init (_cond, NULL); + assert_status(status == 0, status, "cond_init"); + status = pthread_mutex_init (_mutex, NULL); + assert_status(status == 0, status, "mutex_init"); + } +} ; + +#endif // OS_BSD_VM_OS_BSD_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/os_bsd.inline.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,302 @@ +/* + * Copyright (c) 1999, 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. + * + */ + +#ifndef OS_BSD_VM_OS_BSD_INLINE_HPP +#define OS_BSD_VM_OS_BSD_INLINE_HPP + +#include "runtime/atomic.hpp" +#include "runtime/os.hpp" +#ifdef TARGET_OS_ARCH_bsd_x86 +# include "atomic_bsd_x86.inline.hpp" +# include "orderAccess_bsd_x86.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_bsd_zero +# include "atomic_bsd_zero.inline.hpp" +# include "orderAccess_bsd_zero.inline.hpp" +#endif + +// System includes + +#include <unistd.h> +#include <sys/socket.h> +#include <sys/poll.h> +#include <netdb.h> + +inline void* os::thread_local_storage_at(int index) { + return pthread_getspecific((pthread_key_t)index); +} + +inline const char* os::file_separator() { + return "/"; +} + +inline const char* os::line_separator() { + return "\n"; +} + +inline const char* os::path_separator() { + return ":"; +} + +inline const char* os::jlong_format_specifier() { + return "%lld"; +} + +inline const char* os::julong_format_specifier() { + return "%llu"; +} + +// File names are case-sensitive on windows only +inline int os::file_name_strcmp(const char* s1, const char* s2) { + return strcmp(s1, s2); +} + +inline bool os::obsolete_option(const JavaVMOption *option) { + return false; +} + +inline bool os::uses_stack_guard_pages() { + return true; +} + +inline bool os::allocate_stack_guard_pages() { + assert(uses_stack_guard_pages(), "sanity check"); +#if !defined(__FreeBSD__) || __FreeBSD__ < 5 + // Since FreeBSD 4 uses malloc() for allocating the thread stack + // there is no need to do anything extra to allocate the guard pages + return false; +#else + // FreeBSD 5+ uses mmap MAP_STACK for allocating the thread stacks. + // Must 'allocate' them or guard pages are ignored. + return true; +#endif +} + + +// On Bsd, reservations are made on a page by page basis, nothing to do. +inline void os::split_reserved_memory(char *base, size_t size, + size_t split, bool realloc) { +} + + +// Bang the shadow pages if they need to be touched to be mapped. +inline void os::bang_stack_shadow_pages() { +} + +inline void os::dll_unload(void *lib) { + ::dlclose(lib); +} + +inline const int os::default_file_open_flags() { return 0;} + +inline DIR* os::opendir(const char* dirname) +{ + assert(dirname != NULL, "just checking"); + return ::opendir(dirname); +} + +inline int os::readdir_buf_size(const char *path) +{ + return NAME_MAX + sizeof(dirent) + 1; +} + +inline jlong os::lseek(int fd, jlong offset, int whence) { + return (jlong) ::lseek(fd, offset, whence); +} + +inline int os::fsync(int fd) { + return ::fsync(fd); +} + +inline char* os::native_path(char *path) { + return path; +} + +inline int os::ftruncate(int fd, jlong length) { + return ::ftruncate(fd, length); +} + +inline struct dirent* os::readdir(DIR* dirp, dirent *dbuf) +{ + dirent* p; + int status; + assert(dirp != NULL, "just checking"); + + // NOTE: Bsd readdir_r (on RH 6.2 and 7.2 at least) is NOT like the POSIX + // version. Here is the doc for this function: + // http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_262.html + + if((status = ::readdir_r(dirp, dbuf, &p)) != 0) { + errno = status; + return NULL; + } else + return p; +} + +inline int os::closedir(DIR *dirp) { + assert(dirp != NULL, "argument is NULL"); + return ::closedir(dirp); +} + +// macros for restartable system calls + +#define RESTARTABLE(_cmd, _result) do { \ + _result = _cmd; \ + } while(((int)_result == OS_ERR) && (errno == EINTR)) + +#define RESTARTABLE_RETURN_INT(_cmd) do { \ + int _result; \ + RESTARTABLE(_cmd, _result); \ + return _result; \ +} while(false) + +inline bool os::numa_has_static_binding() { return true; } +inline bool os::numa_has_group_homing() { return false; } + +inline size_t os::restartable_read(int fd, void *buf, unsigned int nBytes) { + size_t res; + RESTARTABLE( (size_t) ::read(fd, buf, (size_t) nBytes), res); + return res; +} + +inline size_t os::write(int fd, const void *buf, unsigned int nBytes) { + size_t res; + RESTARTABLE((size_t) ::write(fd, buf, (size_t) nBytes), res); + return res; +} + +inline int os::close(int fd) { + RESTARTABLE_RETURN_INT(::close(fd)); +} + +inline int os::socket_close(int fd) { + RESTARTABLE_RETURN_INT(::close(fd)); +} + +inline int os::socket(int domain, int type, int protocol) { + return ::socket(domain, type, protocol); +} + +inline int os::recv(int fd, char *buf, int nBytes, int flags) { + RESTARTABLE_RETURN_INT(::recv(fd, buf, nBytes, (unsigned int) flags)); +} + +inline int os::send(int fd, char *buf, int nBytes, int flags) { + RESTARTABLE_RETURN_INT(::send(fd, buf, nBytes, (unsigned int) flags)); +} + +inline int os::raw_send(int fd, char *buf, int nBytes, int flags) { + return os::send(fd, buf, nBytes, flags); +} + +inline int os::timeout(int fd, long timeout) { + julong prevtime,newtime; + struct timeval t; + + gettimeofday(&t, NULL); + prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000; + + for(;;) { + struct pollfd pfd; + + pfd.fd = fd; + pfd.events = POLLIN | POLLERR; + + int res = ::poll(&pfd, 1, timeout); + + if (res == OS_ERR && errno == EINTR) { + + // On Bsd any value < 0 means "forever" + + if(timeout >= 0) { + gettimeofday(&t, NULL); + newtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000; + timeout -= newtime - prevtime; + if(timeout <= 0) + return OS_OK; + prevtime = newtime; + } + } else + return res; + } +} + +inline int os::listen(int fd, int count) { + return ::listen(fd, count); +} + +inline int os::connect(int fd, struct sockaddr *him, int len) { + RESTARTABLE_RETURN_INT(::connect(fd, him, len)); +} + +inline int os::accept(int fd, struct sockaddr *him, int *len) { + // This cast is from int to unsigned int on bsd. Since we + // only pass the parameter "len" around the vm and don't try to + // fetch it's value, this cast is safe for now. The java.net group + // may need and want to change this interface someday if socklen_t goes + // to 64 bits on some platform that we support. + + // At least OpenBSD and FreeBSD can return EINTR from accept. + RESTARTABLE_RETURN_INT(::accept(fd, him, (socklen_t *)len)); +} + +inline int os::recvfrom(int fd, char *buf, int nBytes, int flags, + sockaddr *from, int *fromlen) { + RESTARTABLE_RETURN_INT(::recvfrom(fd, buf, nBytes, (unsigned int) flags, from, (socklen_t *)fromlen)); +} + +inline int os::sendto(int fd, char *buf, int len, int flags, + struct sockaddr *to, int tolen) { + RESTARTABLE_RETURN_INT(::sendto(fd, buf, len, (unsigned int) flags, to, tolen)); +} + +inline int os::socket_shutdown(int fd, int howto){ + return ::shutdown(fd, howto); +} + +inline int os::bind(int fd, struct sockaddr *him, int len){ + return ::bind(fd, him, len); +} + +inline int os::get_sock_name(int fd, struct sockaddr *him, int *len){ + return ::getsockname(fd, him, (socklen_t *)len); +} + +inline int os::get_host_name(char* name, int namelen){ + return ::gethostname(name, namelen); +} + +inline struct hostent* os::get_host_by_name(char* name) { + return ::gethostbyname(name); +} +inline int os::get_sock_opt(int fd, int level, int optname, + char *optval, int* optlen){ + return ::getsockopt(fd, level, optname, optval, (socklen_t *)optlen); +} + +inline int os::set_sock_opt(int fd, int level, int optname, + const char *optval, int optlen){ + return ::setsockopt(fd, level, optname, optval, optlen); +} +#endif // OS_BSD_VM_OS_BSD_INLINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/os_share_bsd.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_BSD_VM_OS_SHARE_BSD_HPP +#define OS_BSD_VM_OS_SHARE_BSD_HPP + +// misc +void signalHandler(int, siginfo_t*, ucontext_t*); +void handle_unexpected_exception(Thread* thread, int sig, siginfo_t* info, address pc, address adjusted_pc); +#ifndef PRODUCT +void continue_with_dump(void); +#endif + +#define PROCFILE_LENGTH 128 + +#endif // OS_BSD_VM_OS_SHARE_BSD_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/perfMemory_bsd.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,1041 @@ +/* + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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/vmSymbols.hpp" +#include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" +#include "oops/oop.inline.hpp" +#include "os_bsd.inline.hpp" +#include "runtime/handles.inline.hpp" +#include "runtime/perfMemory.hpp" +#include "utilities/exceptions.hpp" + +// put OS-includes here +# include <sys/types.h> +# include <sys/mman.h> +# include <errno.h> +# include <stdio.h> +# include <unistd.h> +# include <sys/stat.h> +# include <signal.h> +# include <pwd.h> + +static char* backing_store_file_name = NULL; // name of the backing store + // file, if successfully created. + +// Standard Memory Implementation Details + +// create the PerfData memory region in standard memory. +// +static char* create_standard_memory(size_t size) { + + // allocate an aligned chuck of memory + char* mapAddress = os::reserve_memory(size); + + if (mapAddress == NULL) { + return NULL; + } + + // commit memory + if (!os::commit_memory(mapAddress, size)) { + if (PrintMiscellaneous && Verbose) { + warning("Could not commit PerfData memory\n"); + } + os::release_memory(mapAddress, size); + return NULL; + } + + return mapAddress; +} + +// delete the PerfData memory region +// +static void delete_standard_memory(char* addr, size_t size) { + + // there are no persistent external resources to cleanup for standard + // memory. since DestroyJavaVM does not support unloading of the JVM, + // cleanup of the memory resource is not performed. The memory will be + // reclaimed by the OS upon termination of the process. + // + return; +} + +// save the specified memory region to the given file +// +// Note: this function might be called from signal handler (by os::abort()), +// don't allocate heap memory. +// +static void save_memory_to_file(char* addr, size_t size) { + + const char* destfile = PerfMemory::get_perfdata_file_path(); + assert(destfile[0] != '\0', "invalid PerfData file path"); + + int result; + + RESTARTABLE(::open(destfile, O_CREAT|O_WRONLY|O_TRUNC, S_IREAD|S_IWRITE), + result);; + if (result == OS_ERR) { + if (PrintMiscellaneous && Verbose) { + warning("Could not create Perfdata save file: %s: %s\n", + destfile, strerror(errno)); + } + } else { + int fd = result; + + for (size_t remaining = size; remaining > 0;) { + + RESTARTABLE(::write(fd, addr, remaining), result); + if (result == OS_ERR) { + if (PrintMiscellaneous && Verbose) { + warning("Could not write Perfdata save file: %s: %s\n", + destfile, strerror(errno)); + } + break; + } + + remaining -= (size_t)result; + addr += result; + } + + RESTARTABLE(::close(fd), result); + if (PrintMiscellaneous && Verbose) { + if (result == OS_ERR) { + warning("Could not close %s: %s\n", destfile, strerror(errno)); + } + } + } + FREE_C_HEAP_ARRAY(char, destfile); +} + + +// Shared Memory Implementation Details + +// Note: the solaris and bsd shared memory implementation uses the mmap +// interface with a backing store file to implement named shared memory. +// Using the file system as the name space for shared memory allows a +// common name space to be supported across a variety of platforms. It +// also provides a name space that Java applications can deal with through +// simple file apis. +// +// The solaris and bsd implementations store the backing store file in +// a user specific temporary directory located in the /tmp file system, +// which is always a local file system and is sometimes a RAM based file +// system. + +// return the user specific temporary directory name. +// +// the caller is expected to free the allocated memory. +// +static char* get_user_tmp_dir(const char* user) { + + const char* tmpdir = os::get_temp_directory(); + const char* perfdir = PERFDATA_NAME; + size_t nbytes = strlen(tmpdir) + strlen(perfdir) + strlen(user) + 3; + char* dirname = NEW_C_HEAP_ARRAY(char, nbytes); + + // construct the path name to user specific tmp directory + snprintf(dirname, nbytes, "%s/%s_%s", tmpdir, perfdir, user); + + return dirname; +} + +// convert the given file name into a process id. if the file +// does not meet the file naming constraints, return 0. +// +static pid_t filename_to_pid(const char* filename) { + + // a filename that doesn't begin with a digit is not a + // candidate for conversion. + // + if (!isdigit(*filename)) { + return 0; + } + + // check if file name can be converted to an integer without + // any leftover characters. + // + char* remainder = NULL; + errno = 0; + pid_t pid = (pid_t)strtol(filename, &remainder, 10); + + if (errno != 0) { + return 0; + } + + // check for left over characters. If any, then the filename is + // not a candidate for conversion. + // + if (remainder != NULL && *remainder != '\0') { + return 0; + } + + // successful conversion, return the pid + return pid; +} + + +// check if the given path is considered a secure directory for +// the backing store files. Returns true if the directory exists +// and is considered a secure location. Returns false if the path +// is a symbolic link or if an error occurred. +// +static bool is_directory_secure(const char* path) { + struct stat statbuf; + int result = 0; + + RESTARTABLE(::lstat(path, &statbuf), result); + if (result == OS_ERR) { + return false; + } + + // the path exists, now check it's mode + if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) { + // the path represents a link or some non-directory file type, + // which is not what we expected. declare it insecure. + // + return false; + } + else { + // we have an existing directory, check if the permissions are safe. + // + if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) { + // the directory is open for writing and could be subjected + // to a symlnk attack. declare it insecure. + // + return false; + } + } + return true; +} + + +// return the user name for the given user id +// +// the caller is expected to free the allocated memory. +// +static char* get_user_name(uid_t uid) { + + struct passwd pwent; + + // determine the max pwbuf size from sysconf, and hardcode + // a default if this not available through sysconf. + // + long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (bufsize == -1) + bufsize = 1024; + + char* pwbuf = NEW_C_HEAP_ARRAY(char, bufsize); + + // POSIX interface to getpwuid_r is used on LINUX + struct passwd* p; + int result = getpwuid_r(uid, &pwent, pwbuf, (size_t)bufsize, &p); + + if (result != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') { + if (PrintMiscellaneous && Verbose) { + if (result != 0) { + warning("Could not retrieve passwd entry: %s\n", + strerror(result)); + } + else if (p == NULL) { + // this check is added to protect against an observed problem + // with getpwuid_r() on RedHat 9 where getpwuid_r returns 0, + // indicating success, but has p == NULL. This was observed when + // inserting a file descriptor exhaustion fault prior to the call + // getpwuid_r() call. In this case, error is set to the appropriate + // error condition, but this is undocumented behavior. This check + // is safe under any condition, but the use of errno in the output + // message may result in an erroneous message. + // Bug Id 89052 was opened with RedHat. + // + warning("Could not retrieve passwd entry: %s\n", + strerror(errno)); + } + else { + warning("Could not determine user name: %s\n", + p->pw_name == NULL ? "pw_name = NULL" : + "pw_name zero length"); + } + } + FREE_C_HEAP_ARRAY(char, pwbuf); + return NULL; + } + + char* user_name = NEW_C_HEAP_ARRAY(char, strlen(p->pw_name) + 1); + strcpy(user_name, p->pw_name); + + FREE_C_HEAP_ARRAY(char, pwbuf); + return user_name; +} + +// return the name of the user that owns the process identified by vmid. +// +// This method uses a slow directory search algorithm to find the backing +// store file for the specified vmid and returns the user name, as determined +// by the user name suffix of the hsperfdata_<username> directory name. +// +// the caller is expected to free the allocated memory. +// +static char* get_user_name_slow(int vmid, TRAPS) { + + // short circuit the directory search if the process doesn't even exist. + if (kill(vmid, 0) == OS_ERR) { + if (errno == ESRCH) { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), + "Process not found"); + } + else /* EPERM */ { + THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno)); + } + } + + // directory search + char* oldest_user = NULL; + time_t oldest_ctime = 0; + + const char* tmpdirname = os::get_temp_directory(); + + DIR* tmpdirp = os::opendir(tmpdirname); + + if (tmpdirp == NULL) { + return NULL; + } + + // for each entry in the directory that matches the pattern hsperfdata_*, + // open the directory and check if the file for the given vmid exists. + // The file with the expected name and the latest creation date is used + // to determine the user name for the process id. + // + struct dirent* dentry; + char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname)); + errno = 0; + while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) { + + // check if the directory entry is a hsperfdata file + if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) { + continue; + } + + char* usrdir_name = NEW_C_HEAP_ARRAY(char, + strlen(tmpdirname) + strlen(dentry->d_name) + 2); + strcpy(usrdir_name, tmpdirname); + strcat(usrdir_name, "/"); + strcat(usrdir_name, dentry->d_name); + + DIR* subdirp = os::opendir(usrdir_name); + + if (subdirp == NULL) { + FREE_C_HEAP_ARRAY(char, usrdir_name); + continue; + } + + // Since we don't create the backing store files in directories + // pointed to by symbolic links, we also don't follow them when + // looking for the files. We check for a symbolic link after the + // call to opendir in order to eliminate a small window where the + // symlink can be exploited. + // + if (!is_directory_secure(usrdir_name)) { + FREE_C_HEAP_ARRAY(char, usrdir_name); + os::closedir(subdirp); + continue; + } + + struct dirent* udentry; + char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name)); + errno = 0; + while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) { + + if (filename_to_pid(udentry->d_name) == vmid) { + struct stat statbuf; + int result; + + char* filename = NEW_C_HEAP_ARRAY(char, + strlen(usrdir_name) + strlen(udentry->d_name) + 2); + + strcpy(filename, usrdir_name); + strcat(filename, "/"); + strcat(filename, udentry->d_name); + + // don't follow symbolic links for the file + RESTARTABLE(::lstat(filename, &statbuf), result); + if (result == OS_ERR) { + FREE_C_HEAP_ARRAY(char, filename); + continue; + } + + // skip over files that are not regular files. + if (!S_ISREG(statbuf.st_mode)) { + FREE_C_HEAP_ARRAY(char, filename); + continue; + } + + // compare and save filename with latest creation time + if (statbuf.st_size > 0 && statbuf.st_ctime > oldest_ctime) { + + if (statbuf.st_ctime > oldest_ctime) { + char* user = strchr(dentry->d_name, '_') + 1; + + if (oldest_user != NULL) FREE_C_HEAP_ARRAY(char, oldest_user); + oldest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1); + + strcpy(oldest_user, user); + oldest_ctime = statbuf.st_ctime; + } + } + + FREE_C_HEAP_ARRAY(char, filename); + } + } + os::closedir(subdirp); + FREE_C_HEAP_ARRAY(char, udbuf); + FREE_C_HEAP_ARRAY(char, usrdir_name); + } + os::closedir(tmpdirp); + FREE_C_HEAP_ARRAY(char, tdbuf); + + return(oldest_user); +} + +// return the name of the user that owns the JVM indicated by the given vmid. +// +static char* get_user_name(int vmid, TRAPS) { + return get_user_name_slow(vmid, CHECK_NULL); +} + +// return the file name of the backing store file for the named +// shared memory region for the given user name and vmid. +// +// the caller is expected to free the allocated memory. +// +static char* get_sharedmem_filename(const char* dirname, int vmid) { + + // add 2 for the file separator and a null terminator. + size_t nbytes = strlen(dirname) + UINT_CHARS + 2; + + char* name = NEW_C_HEAP_ARRAY(char, nbytes); + snprintf(name, nbytes, "%s/%d", dirname, vmid); + + return name; +} + + +// remove file +// +// this method removes the file specified by the given path +// +static void remove_file(const char* path) { + + int result; + + // if the file is a directory, the following unlink will fail. since + // we don't expect to find directories in the user temp directory, we + // won't try to handle this situation. even if accidentially or + // maliciously planted, the directory's presence won't hurt anything. + // + RESTARTABLE(::unlink(path), result); + if (PrintMiscellaneous && Verbose && result == OS_ERR) { + if (errno != ENOENT) { + warning("Could not unlink shared memory backing" + " store file %s : %s\n", path, strerror(errno)); + } + } +} + + +// remove file +// +// this method removes the file with the given file name in the +// named directory. +// +static void remove_file(const char* dirname, const char* filename) { + + size_t nbytes = strlen(dirname) + strlen(filename) + 2; + char* path = NEW_C_HEAP_ARRAY(char, nbytes); + + strcpy(path, dirname); + strcat(path, "/"); + strcat(path, filename); + + remove_file(path); + + FREE_C_HEAP_ARRAY(char, path); +} + + +// cleanup stale shared memory resources +// +// This method attempts to remove all stale shared memory files in +// the named user temporary directory. It scans the named directory +// for files matching the pattern ^$[0-9]*$. For each file found, the +// process id is extracted from the file name and a test is run to +// determine if the process is alive. If the process is not alive, +// any stale file resources are removed. +// +static void cleanup_sharedmem_resources(const char* dirname) { + + // open the user temp directory + DIR* dirp = os::opendir(dirname); + + if (dirp == NULL) { + // directory doesn't exist, so there is nothing to cleanup + return; + } + + if (!is_directory_secure(dirname)) { + // the directory is not a secure directory + return; + } + + // for each entry in the directory that matches the expected file + // name pattern, determine if the file resources are stale and if + // so, remove the file resources. Note, instrumented HotSpot processes + // for this user may start and/or terminate during this search and + // remove or create new files in this directory. The behavior of this + // loop under these conditions is dependent upon the implementation of + // opendir/readdir. + // + struct dirent* entry; + char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname)); + errno = 0; + while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) { + + pid_t pid = filename_to_pid(entry->d_name); + + if (pid == 0) { + + if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { + + // attempt to remove all unexpected files, except "." and ".." + remove_file(dirname, entry->d_name); + } + + errno = 0; + continue; + } + + // we now have a file name that converts to a valid integer + // that could represent a process id . if this process id + // matches the current process id or the process is not running, + // then remove the stale file resources. + // + // process liveness is detected by sending signal number 0 to + // the process id (see kill(2)). if kill determines that the + // process does not exist, then the file resources are removed. + // if kill determines that that we don't have permission to + // signal the process, then the file resources are assumed to + // be stale and are removed because the resources for such a + // process should be in a different user specific directory. + // + if ((pid == os::current_process_id()) || + (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) { + + remove_file(dirname, entry->d_name); + } + errno = 0; + } + os::closedir(dirp); + FREE_C_HEAP_ARRAY(char, dbuf); +} + +// make the user specific temporary directory. Returns true if +// the directory exists and is secure upon return. Returns false +// if the directory exists but is either a symlink, is otherwise +// insecure, or if an error occurred. +// +static bool make_user_tmp_dir(const char* dirname) { + + // create the directory with 0755 permissions. note that the directory + // will be owned by euid::egid, which may not be the same as uid::gid. + // + if (mkdir(dirname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) == OS_ERR) { + if (errno == EEXIST) { + // The directory already exists and was probably created by another + // JVM instance. However, this could also be the result of a + // deliberate symlink. Verify that the existing directory is safe. + // + if (!is_directory_secure(dirname)) { + // directory is not secure + if (PrintMiscellaneous && Verbose) { + warning("%s directory is insecure\n", dirname); + } + return false; + } + } + else { + // we encountered some other failure while attempting + // to create the directory + // + if (PrintMiscellaneous && Verbose) { + warning("could not create directory %s: %s\n", + dirname, strerror(errno)); + } + return false; + } + } + return true; +} + +// create the shared memory file resources +// +// This method creates the shared memory file with the given size +// This method also creates the user specific temporary directory, if +// it does not yet exist. +// +static int create_sharedmem_resources(const char* dirname, const char* filename, size_t size) { + + // make the user temporary directory + if (!make_user_tmp_dir(dirname)) { + // could not make/find the directory or the found directory + // was not secure + return -1; + } + + int result; + + RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result); + if (result == OS_ERR) { + if (PrintMiscellaneous && Verbose) { + warning("could not create file %s: %s\n", filename, strerror(errno)); + } + return -1; + } + + // save the file descriptor + int fd = result; + + // set the file size + RESTARTABLE(::ftruncate(fd, (off_t)size), result); + if (result == OS_ERR) { + if (PrintMiscellaneous && Verbose) { + warning("could not set shared memory file size: %s\n", strerror(errno)); + } + RESTARTABLE(::close(fd), result); + return -1; + } + + // Verify that we have enough disk space for this file. + // We'll get random SIGBUS crashes on memory accesses if + // we don't. + + for (size_t seekpos = 0; seekpos < size; seekpos += os::vm_page_size()) { + int zero_int = 0; + result = (int)os::seek_to_file_offset(fd, (jlong)(seekpos)); + if (result == -1 ) break; + RESTARTABLE(::write(fd, &zero_int, 1), result); + if (result != 1) { + if (errno == ENOSPC) { + warning("Insufficient space for shared memory file:\n %s\nTry using the -Djava.io.tmpdir= option to select an alternate temp location.\n", filename); + } + break; + } + } + + if (result != -1) { + return fd; + } else { + RESTARTABLE(::close(fd), result); + return -1; + } +} + +// open the shared memory file for the given user and vmid. returns +// the file descriptor for the open file or -1 if the file could not +// be opened. +// +static int open_sharedmem_file(const char* filename, int oflags, TRAPS) { + + // open the file + int result; + RESTARTABLE(::open(filename, oflags), result); + if (result == OS_ERR) { + if (errno == ENOENT) { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), + "Process not found"); + } + else if (errno == EACCES) { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), + "Permission denied"); + } + else { + THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno)); + } + } + + return result; +} + +// create a named shared memory region. returns the address of the +// memory region on success or NULL on failure. A return value of +// NULL will ultimately disable the shared memory feature. +// +// On Solaris and Bsd, the name space for shared memory objects +// is the file system name space. +// +// A monitoring application attaching to a JVM does not need to know +// the file system name of the shared memory object. However, it may +// be convenient for applications to discover the existence of newly +// created and terminating JVMs by watching the file system name space +// for files being created or removed. +// +static char* mmap_create_shared(size_t size) { + + int result; + int fd; + char* mapAddress; + + int vmid = os::current_process_id(); + + char* user_name = get_user_name(geteuid()); + + if (user_name == NULL) + return NULL; + + char* dirname = get_user_tmp_dir(user_name); + char* filename = get_sharedmem_filename(dirname, vmid); + + // cleanup any stale shared memory files + cleanup_sharedmem_resources(dirname); + + assert(((size > 0) && (size % os::vm_page_size() == 0)), + "unexpected PerfMemory region size"); + + fd = create_sharedmem_resources(dirname, filename, size); + + FREE_C_HEAP_ARRAY(char, user_name); + FREE_C_HEAP_ARRAY(char, dirname); + + if (fd == -1) { + FREE_C_HEAP_ARRAY(char, filename); + return NULL; + } + + mapAddress = (char*)::mmap((char*)0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + + // attempt to close the file - restart it if it was interrupted, + // but ignore other failures + RESTARTABLE(::close(fd), result); + assert(result != OS_ERR, "could not close file"); + + if (mapAddress == MAP_FAILED) { + if (PrintMiscellaneous && Verbose) { + warning("mmap failed - %s\n", strerror(errno)); + } + remove_file(filename); + FREE_C_HEAP_ARRAY(char, filename); + return NULL; + } + + // save the file name for use in delete_shared_memory() + backing_store_file_name = filename; + + // clear the shared memory region + (void)::memset((void*) mapAddress, 0, size); + + return mapAddress; +} + +// release a named shared memory region +// +static void unmap_shared(char* addr, size_t bytes) { + os::release_memory(addr, bytes); +} + +// create the PerfData memory region in shared memory. +// +static char* create_shared_memory(size_t size) { + + // create the shared memory region. + return mmap_create_shared(size); +} + +// delete the shared PerfData memory region +// +static void delete_shared_memory(char* addr, size_t size) { + + // cleanup the persistent shared memory resources. since DestroyJavaVM does + // not support unloading of the JVM, unmapping of the memory resource is + // not performed. The memory will be reclaimed by the OS upon termination of + // the process. The backing store file is deleted from the file system. + + assert(!PerfDisableSharedMem, "shouldn't be here"); + + if (backing_store_file_name != NULL) { + remove_file(backing_store_file_name); + // Don't.. Free heap memory could deadlock os::abort() if it is called + // from signal handler. OS will reclaim the heap memory. + // FREE_C_HEAP_ARRAY(char, backing_store_file_name); + backing_store_file_name = NULL; + } +} + +// return the size of the file for the given file descriptor +// or 0 if it is not a valid size for a shared memory file +// +static size_t sharedmem_filesize(int fd, TRAPS) { + + struct stat statbuf; + int result; + + RESTARTABLE(::fstat(fd, &statbuf), result); + if (result == OS_ERR) { + if (PrintMiscellaneous && Verbose) { + warning("fstat failed: %s\n", strerror(errno)); + } + THROW_MSG_0(vmSymbols::java_io_IOException(), + "Could not determine PerfMemory size"); + } + + if ((statbuf.st_size == 0) || + ((size_t)statbuf.st_size % os::vm_page_size() != 0)) { + THROW_MSG_0(vmSymbols::java_lang_Exception(), + "Invalid PerfMemory size"); + } + + return (size_t)statbuf.st_size; +} + +// attach to a named shared memory region. +// +static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemoryMode mode, char** addr, size_t* sizep, TRAPS) { + + char* mapAddress; + int result; + int fd; + size_t size; + const char* luser = NULL; + + int mmap_prot; + int file_flags; + + ResourceMark rm; + + // map the high level access mode to the appropriate permission + // constructs for the file and the shared memory mapping. + if (mode == PerfMemory::PERF_MODE_RO) { + mmap_prot = PROT_READ; + file_flags = O_RDONLY; + } + else if (mode == PerfMemory::PERF_MODE_RW) { +#ifdef LATER + mmap_prot = PROT_READ | PROT_WRITE; + file_flags = O_RDWR; +#else + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Unsupported access mode"); +#endif + } + else { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Illegal access mode"); + } + + if (user == NULL || strlen(user) == 0) { + luser = get_user_name(vmid, CHECK); + } + else { + luser = user; + } + + if (luser == NULL) { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Could not map vmid to user Name"); + } + + char* dirname = get_user_tmp_dir(luser); + + // since we don't follow symbolic links when creating the backing + // store file, we don't follow them when attaching either. + // + if (!is_directory_secure(dirname)) { + FREE_C_HEAP_ARRAY(char, dirname); + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Process not found"); + } + + char* filename = get_sharedmem_filename(dirname, vmid); + + // copy heap memory to resource memory. the open_sharedmem_file + // method below need to use the filename, but could throw an + // exception. using a resource array prevents the leak that + // would otherwise occur. + char* rfilename = NEW_RESOURCE_ARRAY(char, strlen(filename) + 1); + strcpy(rfilename, filename); + + // free the c heap resources that are no longer needed + if (luser != user) FREE_C_HEAP_ARRAY(char, luser); + FREE_C_HEAP_ARRAY(char, dirname); + FREE_C_HEAP_ARRAY(char, filename); + + // open the shared memory file for the give vmid + fd = open_sharedmem_file(rfilename, file_flags, CHECK); + assert(fd != OS_ERR, "unexpected value"); + + if (*sizep == 0) { + size = sharedmem_filesize(fd, CHECK); + assert(size != 0, "unexpected size"); + } + + mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED, fd, 0); + + // attempt to close the file - restart if it gets interrupted, + // but ignore other failures + RESTARTABLE(::close(fd), result); + assert(result != OS_ERR, "could not close file"); + + if (mapAddress == MAP_FAILED) { + if (PrintMiscellaneous && Verbose) { + warning("mmap failed: %s\n", strerror(errno)); + } + THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), + "Could not map PerfMemory"); + } + + *addr = mapAddress; + *sizep = size; + + if (PerfTraceMemOps) { + tty->print("mapped " SIZE_FORMAT " bytes for vmid %d at " + INTPTR_FORMAT "\n", size, vmid, (void*)mapAddress); + } +} + + + + +// create the PerfData memory region +// +// This method creates the memory region used to store performance +// data for the JVM. The memory may be created in standard or +// shared memory. +// +void PerfMemory::create_memory_region(size_t size) { + + if (PerfDisableSharedMem) { + // do not share the memory for the performance data. + _start = create_standard_memory(size); + } + else { + _start = create_shared_memory(size); + if (_start == NULL) { + + // creation of the shared memory region failed, attempt + // to create a contiguous, non-shared memory region instead. + // + if (PrintMiscellaneous && Verbose) { + warning("Reverting to non-shared PerfMemory region.\n"); + } + PerfDisableSharedMem = true; + _start = create_standard_memory(size); + } + } + + if (_start != NULL) _capacity = size; + +} + +// delete the PerfData memory region +// +// This method deletes the memory region used to store performance +// data for the JVM. The memory region indicated by the <address, size> +// tuple will be inaccessible after a call to this method. +// +void PerfMemory::delete_memory_region() { + + assert((start() != NULL && capacity() > 0), "verify proper state"); + + // If user specifies PerfDataSaveFile, it will save the performance data + // to the specified file name no matter whether PerfDataSaveToFile is specified + // or not. In other word, -XX:PerfDataSaveFile=.. overrides flag + // -XX:+PerfDataSaveToFile. + if (PerfDataSaveToFile || PerfDataSaveFile != NULL) { + save_memory_to_file(start(), capacity()); + } + + if (PerfDisableSharedMem) { + delete_standard_memory(start(), capacity()); + } + else { + delete_shared_memory(start(), capacity()); + } +} + +// attach to the PerfData memory region for another JVM +// +// This method returns an <address, size> tuple that points to +// a memory buffer that is kept reasonably synchronized with +// the PerfData memory region for the indicated JVM. This +// buffer may be kept in synchronization via shared memory +// or some other mechanism that keeps the buffer updated. +// +// If the JVM chooses not to support the attachability feature, +// this method should throw an UnsupportedOperation exception. +// +// This implementation utilizes named shared memory to map +// the indicated process's PerfData memory region into this JVMs +// address space. +// +void PerfMemory::attach(const char* user, int vmid, PerfMemoryMode mode, char** addrp, size_t* sizep, TRAPS) { + + if (vmid == 0 || vmid == os::current_process_id()) { + *addrp = start(); + *sizep = capacity(); + return; + } + + mmap_attach_shared(user, vmid, mode, addrp, sizep, CHECK); +} + +// detach from the PerfData memory region of another JVM +// +// This method detaches the PerfData memory region of another +// JVM, specified as an <address, size> tuple of a buffer +// in this process's address space. This method may perform +// arbitrary actions to accomplish the detachment. The memory +// region specified by <address, size> will be inaccessible after +// a call to this method. +// +// If the JVM chooses not to support the attachability feature, +// this method should throw an UnsupportedOperation exception. +// +// This implementation utilizes named shared memory to detach +// the indicated process's PerfData memory region from this +// process's address space. +// +void PerfMemory::detach(char* addr, size_t bytes, TRAPS) { + + assert(addr != 0, "address sanity check"); + assert(bytes > 0, "capacity sanity check"); + + if (PerfMemory::contains(addr) || PerfMemory::contains(addr + bytes - 1)) { + // prevent accidental detachment of this process's PerfMemory region + return; + } + + unmap_shared(addr, bytes); +} + +char* PerfMemory::backing_store_filename() { + return backing_store_file_name; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/stubRoutines_bsd.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "runtime/os.hpp" +#include "runtime/stubRoutines.hpp"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/threadCritical_bsd.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "runtime/threadCritical.hpp" +#include "thread_bsd.inline.hpp" + +// put OS-includes here +# include <pthread.h> + +// +// See threadCritical.hpp for details of this class. +// + +static pthread_t tc_owner = 0; +static pthread_mutex_t tc_mutex = PTHREAD_MUTEX_INITIALIZER; +static int tc_count = 0; + +void ThreadCritical::initialize() { +} + +void ThreadCritical::release() { +} + +ThreadCritical::ThreadCritical() { + pthread_t self = pthread_self(); + if (self != tc_owner) { + int ret = pthread_mutex_lock(&tc_mutex); + guarantee(ret == 0, "fatal error with pthread_mutex_lock()"); + assert(tc_count == 0, "Lock acquired with illegal reentry count."); + tc_owner = self; + } + tc_count++; +} + +ThreadCritical::~ThreadCritical() { + assert(tc_owner == pthread_self(), "must have correct owner"); + assert(tc_count > 0, "must have correct count"); + + tc_count--; + if (tc_count == 0) { + tc_owner = 0; + int ret = pthread_mutex_unlock(&tc_mutex); + guarantee(ret == 0, "fatal error with pthread_mutex_unlock()"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/thread_bsd.inline.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2002, 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. + * + */ + +#ifndef OS_BSD_VM_THREAD_BSD_INLINE_HPP +#define OS_BSD_VM_THREAD_BSD_INLINE_HPP + +#include "runtime/atomic.hpp" +#include "runtime/prefetch.hpp" +#include "runtime/thread.hpp" +#include "runtime/threadLocalStorage.hpp" +#ifdef TARGET_OS_ARCH_bsd_x86 +# include "atomic_bsd_x86.inline.hpp" +# include "orderAccess_bsd_x86.inline.hpp" +# include "prefetch_bsd_x86.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_bsd_zero +# include "atomic_bsd_zero.inline.hpp" +# include "orderAccess_bsd_zero.inline.hpp" +# include "prefetch_bsd_zero.inline.hpp" +#endif + +// Contains inlined functions for class Thread and ThreadLocalStorage + +inline void ThreadLocalStorage::pd_invalidate_all() {} // nothing to do + +#endif // OS_BSD_VM_THREAD_BSD_INLINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/vmError_bsd.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "runtime/arguments.hpp" +#include "runtime/os.hpp" +#include "runtime/thread.hpp" +#include "utilities/vmError.hpp" + +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/syscall.h> +#include <unistd.h> +#include <signal.h> + +void VMError::show_message_box(char *buf, int buflen) { + bool yes; + do { + error_string(buf, buflen); + int len = (int)strlen(buf); + char *p = &buf[len]; + + jio_snprintf(p, buflen - len, + "\n\n" + "Do you want to debug the problem?\n\n" + "To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " INTX_FORMAT " (" INTPTR_FORMAT ")\n" + "Enter 'yes' to launch gdb automatically (PATH must include gdb)\n" + "Otherwise, press RETURN to abort...", + os::current_process_id(), os::current_process_id(), + os::current_thread_id(), os::current_thread_id()); + + yes = os::message_box("Unexpected Error", buf); + + if (yes) { + // yes, user asked VM to launch debugger + jio_snprintf(buf, buflen, "gdb /proc/%d/exe %d", + os::current_process_id(), os::current_process_id()); + + os::fork_and_exec(buf); + yes = false; + } + } while (yes); +} + +// Space for our "saved" signal flags and handlers +static int resettedSigflags[2]; +static address resettedSighandler[2]; + +static void save_signal(int idx, int sig) +{ + struct sigaction sa; + sigaction(sig, NULL, &sa); + resettedSigflags[idx] = sa.sa_flags; + resettedSighandler[idx] = (sa.sa_flags & SA_SIGINFO) + ? CAST_FROM_FN_PTR(address, sa.sa_sigaction) + : CAST_FROM_FN_PTR(address, sa.sa_handler); +} + +int VMError::get_resetted_sigflags(int sig) { + if(SIGSEGV == sig) { + return resettedSigflags[0]; + } else if(SIGBUS == sig) { + return resettedSigflags[1]; + } + return -1; +} + +address VMError::get_resetted_sighandler(int sig) { + if(SIGSEGV == sig) { + return resettedSighandler[0]; + } else if(SIGBUS == sig) { + return resettedSighandler[1]; + } + return NULL; +} + +static void crash_handler(int sig, siginfo_t* info, void* ucVoid) { + // unmask current signal + sigset_t newset; + sigemptyset(&newset); + sigaddset(&newset, sig); + sigprocmask(SIG_UNBLOCK, &newset, NULL); + + VMError err(NULL, sig, NULL, info, ucVoid); + err.report_and_die(); +} + +void VMError::reset_signal_handlers() { + // Save sigflags for resetted signals + save_signal(0, SIGSEGV); + save_signal(1, SIGBUS); + os::signal(SIGSEGV, CAST_FROM_FN_PTR(void *, crash_handler)); + os::signal(SIGBUS, CAST_FROM_FN_PTR(void *, crash_handler)); +}
--- a/src/os/linux/vm/os_linux.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/os/linux/vm/os_linux.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -22,8 +22,6 @@ * */ -# define __STDC_FORMAT_MACROS - // no precompiled headers #include "classfile/classLoader.hpp" #include "classfile/systemDictionary.hpp" @@ -3895,14 +3893,19 @@ } // We don't activate signal checker if libjsig is in place, we trust ourselves - // and if UserSignalHandler is installed all bets are off + // and if UserSignalHandler is installed all bets are off. + // Log that signal checking is off only if -verbose:jni is specified. if (CheckJNICalls) { if (libjsig_is_loaded) { - tty->print_cr("Info: libjsig is activated, all active signal checking is disabled"); + if (PrintJNIResolving) { + tty->print_cr("Info: libjsig is activated, all active signal checking is disabled"); + } check_signals = false; } if (AllowUserSignalHandlers) { - tty->print_cr("Info: AllowUserSignalHandlers is activated, all active signal checking is disabled"); + if (PrintJNIResolving) { + tty->print_cr("Info: AllowUserSignalHandlers is activated, all active signal checking is disabled"); + } check_signals = false; } } @@ -4354,6 +4357,11 @@ return online_cpus; } +void os::set_native_thread_name(const char *name) { + // Not yet implemented. + return; +} + bool os::distribute_processes(uint length, uint* distribution) { // Not yet implemented. return false;
--- a/src/os/posix/launcher/java_md.c Wed Oct 26 12:43:05 2011 -0700 +++ b/src/os/posix/launcher/java_md.c Thu Oct 27 12:21:43 2011 -0700 @@ -41,14 +41,21 @@ #include "version_comp.h" #endif -#ifdef __linux__ +#if defined(__linux__) || defined(_ALLBSD_SOURCE) #include <pthread.h> #else #include <thread.h> #endif +#ifdef __APPLE__ +#define JVM_DLL "libjvm.dylib" +#define JAVA_DLL "libjava.dylib" +#define LD_LIBRARY_PATH "DYLD_LIBRARY_PATH" +#else #define JVM_DLL "libjvm.so" #define JAVA_DLL "libjava.so" +#define LD_LIBRARY_PATH "LD_LIBRARY_PATH" +#endif #ifndef GAMMA /* launcher.make defines ARCH */ /* @@ -423,10 +430,10 @@ * If not on Solaris, assume only a single LD_LIBRARY_PATH * variable. */ - runpath = getenv("LD_LIBRARY_PATH"); + runpath = getenv(LD_LIBRARY_PATH); #endif /* __sun */ -#ifdef __linux +#if defined(__linux__) /* * On linux, if a binary is running as sgid or suid, glibc sets * LD_LIBRARY_PATH to the empty string for security purposes. (In @@ -442,6 +449,22 @@ if((getgid() != getegid()) || (getuid() != geteuid()) ) { return; } +#elif defined(_ALLBSD_SOURCE) + /* + * On BSD, if a binary is running as sgid or suid, libc sets + * LD_LIBRARY_PATH to the empty string for security purposes. (In + * contrast, on Solaris the LD_LIBRARY_PATH variable for a + * privileged binary does not lose its settings; but the dynamic + * linker does apply more scrutiny to the path.) The launcher uses + * the value of LD_LIBRARY_PATH to prevent an exec loop. + * Therefore, if we are running sgid or suid, this function's + * setting of LD_LIBRARY_PATH will be ineffective and we should + * return from the function now. Getting the right libraries to + * be found must be handled through other mechanisms. + */ + if(issetugid()) { + return; + } #endif /* runpath contains current effective LD_LIBRARY_PATH setting */ @@ -450,7 +473,7 @@ new_runpath = JLI_MemAlloc( ((runpath!=NULL)?strlen(runpath):0) + 2*strlen(jrepath) + 2*strlen(arch) + strlen(jvmpath) + 52); - newpath = new_runpath + strlen("LD_LIBRARY_PATH="); + newpath = new_runpath + strlen(LD_LIBRARY_PATH "="); /* @@ -465,7 +488,7 @@ /* jvmpath, ((running != wanted)?((wanted==64)?"/"LIBARCH64NAME:"/.."):""), */ - sprintf(new_runpath, "LD_LIBRARY_PATH=" + sprintf(new_runpath, LD_LIBRARY_PATH "=" "%s:" "%s/lib/%s:" "%s/../lib/%s", @@ -792,7 +815,7 @@ jboolean GetApplicationHome(char *buf, jint bufsize) { -#ifdef __linux__ +#if defined(__linux__) || defined(_ALLBSD_SOURCE) char *execname = GetExecname(); if (execname) { strncpy(buf, execname, bufsize-1); @@ -1175,7 +1198,7 @@ #endif /* __sun && i586 */ -#if defined(__linux__) && defined(i586) +#if (defined(__linux__) || defined(_ALLBSD_SOURCE)) && defined(i586) /* * A utility method for asking the CPU about itself. @@ -1452,6 +1475,39 @@ #endif /* __linux__ && i586 */ +#if defined(_ALLBSD_SOURCE) && defined(i586) + +/* The definition of a server-class machine for bsd-i586 */ +jboolean +bsd_i586_ServerClassMachine(void) { + jboolean result = JNI_FALSE; + /* How big is a server class machine? */ + const unsigned long server_processors = 2UL; + const uint64_t server_memory = 2UL * GB; + /* + * We seem not to get our full complement of memory. + * We allow some part (1/8?) of the memory to be "missing", + * based on the sizes of DIMMs, and maybe graphics cards. + */ + const uint64_t missing_memory = 256UL * MB; + const uint64_t actual_memory = physical_memory(); + + /* Is this a server class machine? */ + if (actual_memory >= (server_memory - missing_memory)) { + const unsigned long actual_processors = physical_processors(); + if (actual_processors >= server_processors) { + result = JNI_TRUE; + } + } + if (_launcher_debug) { + printf("linux_" LIBARCHNAME "_ServerClassMachine: %s\n", + (result == JNI_TRUE ? "true" : "false")); + } + return result; +} + +#endif /* _ALLBSD_SOURCE && i586 */ + /* Dispatch to the platform-specific definition of "server-class" */ jboolean ServerClassMachine(void) { @@ -1466,6 +1522,8 @@ result = solaris_i586_ServerClassMachine(); #elif defined(__linux__) && defined(i586) result = linux_i586_ServerClassMachine(); +#elif defined(_ALLBSD_SOURCE) && defined(i586) + result = bsd_i586_ServerClassMachine(); #else if (_launcher_debug) { printf("ServerClassMachine: returns default value of %s\n", @@ -1821,7 +1879,7 @@ int ContinueInNewThread(int (JNICALL *continuation)(void *), jlong stack_size, void * args) { int rslt; -#ifdef __linux__ +#if defined(__linux__) || defined(_ALLBSD_SOURCE) pthread_t tid; pthread_attr_t attr; pthread_attr_init(&attr);
--- a/src/os/posix/launcher/launcher.script Wed Oct 26 12:43:05 2011 -0700 +++ b/src/os/posix/launcher/launcher.script Thu Oct 27 12:21:43 2011 -0700 @@ -1,6 +1,6 @@ -#!/bin/bash +#!/bin/sh -# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 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 @@ -69,8 +69,8 @@ # # Make sure the paths are fully specified, i.e. they must begin with /. -SCRIPT=$(cd $(dirname $0) && pwd)/$(basename $0) -RUNDIR=$(pwd) +REL_MYDIR=`dirname $0` +MYDIR=`cd $REL_MYDIR && pwd` # Look whether the user wants to run inside gdb case "$1" in @@ -95,12 +95,9 @@ ;; esac -# Find out the absolute path to this script -MYDIR=$(cd $(dirname $SCRIPT) && pwd) - JDK= if [ "${ALT_JAVA_HOME}" = "" ]; then - source ${MYDIR}/jdkpath.sh + . ${MYDIR}/jdkpath.sh else JDK=${ALT_JAVA_HOME%%/jre}; fi @@ -119,9 +116,6 @@ JAVA_HOME=$JDK ARCH=@@LIBARCH@@ -# Find out the absolute path to this script -MYDIR=$(cd $(dirname $SCRIPT) && pwd) - SBP=${MYDIR}:${JRE}/lib/${ARCH} # Set up a suitable LD_LIBRARY_PATH @@ -146,7 +140,7 @@ fi GDBSRCDIR=$MYDIR -BASEDIR=$(cd $MYDIR/../../.. && pwd) +BASEDIR=`cd $MYDIR/../../.. && pwd` init_gdb() { # Create a gdb script in case we should run inside gdb @@ -179,7 +173,7 @@ init_gdb # First find out what emacs version we're using, so that we can # use the new pretty GDB mode if emacs -version >= 22.1 - case $($EMACS -version 2> /dev/null) in + case `$EMACS -version 2> /dev/null` in *GNU\ Emacs\ 2[23]*) emacs_gud_cmd="gdba" emacs_gud_args="--annotate=3"
--- a/src/os/solaris/vm/os_solaris.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/os/solaris/vm/os_solaris.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -669,6 +669,11 @@ return true; } +void os::set_native_thread_name(const char *name) { + // Not yet implemented. + return; +} + bool os::distribute_processes(uint length, uint* distribution) { bool result = false; // Find the processor id's of all the available CPUs. @@ -4592,14 +4597,19 @@ } // We don't activate signal checker if libjsig is in place, we trust ourselves - // and if UserSignalHandler is installed all bets are off + // and if UserSignalHandler is installed all bets are off. + // Log that signal checking is off only if -verbose:jni is specified. if (CheckJNICalls) { if (libjsig_is_loaded) { - tty->print_cr("Info: libjsig is activated, all active signal checking is disabled"); + if (PrintJNIResolving) { + tty->print_cr("Info: libjsig is activated, all active signal checking is disabled"); + } check_signals = false; } if (AllowUserSignalHandlers) { - tty->print_cr("Info: AllowUserSignalHandlers is activated, all active signal checking is disabled"); + if (PrintJNIResolving) { + tty->print_cr("Info: AllowUserSignalHandlers is activated, all active signal checking is disabled"); + } check_signals = false; } }
--- a/src/os/windows/vm/os_windows.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/os/windows/vm/os_windows.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -710,6 +710,11 @@ } } +void os::set_native_thread_name(const char *name) { + // Not yet implemented. + return; +} + bool os::distribute_processes(uint length, uint* distribution) { // Not yet implemented. return false;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/assembler_bsd_x86.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "asm/assembler.hpp" +#include "assembler_x86.inline.hpp" +#include "runtime/os.hpp" +#include "runtime/threadLocalStorage.hpp" + +#ifndef _LP64 +void MacroAssembler::int3() { + call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); +} + +void MacroAssembler::get_thread(Register thread) { + movl(thread, rsp); + shrl(thread, PAGE_SHIFT); + + ExternalAddress tls_base((address)ThreadLocalStorage::sp_map_addr()); + Address index(noreg, thread, Address::times_4); + ArrayAddress tls(tls_base, index); + + movptr(thread, tls); +} +#else +void MacroAssembler::int3() { + call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); +} + +void MacroAssembler::get_thread(Register thread) { + // call pthread_getspecific + // void * pthread_getspecific(pthread_key_t key); + if (thread != rax) { + push(rax); + } + push(rdi); + push(rsi); + push(rdx); + push(rcx); + push(r8); + push(r9); + push(r10); + // XXX + mov(r10, rsp); + andq(rsp, -16); + push(r10); + push(r11); + + movl(rdi, ThreadLocalStorage::thread_index()); + call(RuntimeAddress(CAST_FROM_FN_PTR(address, pthread_getspecific))); + + pop(r11); + pop(rsp); + pop(r10); + pop(r9); + pop(r8); + pop(rcx); + pop(rdx); + pop(rsi); + pop(rdi); + if (thread != rax) { + mov(thread, rax); + pop(rax); + } +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.inline.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,221 @@ +/* + * Copyright (c) 1999, 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. + * + */ + +#ifndef OS_CPU_BSD_X86_VM_ATOMIC_BSD_X86_INLINE_HPP +#define OS_CPU_BSD_X86_VM_ATOMIC_BSD_X86_INLINE_HPP + +#include "orderAccess_bsd_x86.inline.hpp" +#include "runtime/atomic.hpp" +#include "runtime/os.hpp" +#include "vm_version_x86.hpp" + +// Implementation of class atomic + +inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; } +inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; } +inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; } +inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; } +inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; } + +inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; } +inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; } +inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; } +inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; } +inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; } + + +// Adding a lock prefix to an instruction on MP machine +#define LOCK_IF_MP(mp) "cmp $0, " #mp "; je 1f; lock; 1: " + +inline jint Atomic::add (jint add_value, volatile jint* dest) { + jint addend = add_value; + int mp = os::is_MP(); + __asm__ volatile ( LOCK_IF_MP(%3) "xaddl %0,(%2)" + : "=r" (addend) + : "0" (addend), "r" (dest), "r" (mp) + : "cc", "memory"); + return addend + add_value; +} + +inline void Atomic::inc (volatile jint* dest) { + int mp = os::is_MP(); + __asm__ volatile (LOCK_IF_MP(%1) "addl $1,(%0)" : + : "r" (dest), "r" (mp) : "cc", "memory"); +} + +inline void Atomic::inc_ptr(volatile void* dest) { + inc_ptr((volatile intptr_t*)dest); +} + +inline void Atomic::dec (volatile jint* dest) { + int mp = os::is_MP(); + __asm__ volatile (LOCK_IF_MP(%1) "subl $1,(%0)" : + : "r" (dest), "r" (mp) : "cc", "memory"); +} + +inline void Atomic::dec_ptr(volatile void* dest) { + dec_ptr((volatile intptr_t*)dest); +} + +inline jint Atomic::xchg (jint exchange_value, volatile jint* dest) { + __asm__ volatile ( "xchgl (%2),%0" + : "=r" (exchange_value) + : "0" (exchange_value), "r" (dest) + : "memory"); + return exchange_value; +} + +inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* dest) { + return (void*)xchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest); +} + + +inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { + int mp = os::is_MP(); + __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)" + : "=a" (exchange_value) + : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) + : "cc", "memory"); + return exchange_value; +} + +#ifdef AMD64 +inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; } +inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; } + +inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) { + intptr_t addend = add_value; + bool mp = os::is_MP(); + __asm__ __volatile__ (LOCK_IF_MP(%3) "xaddq %0,(%2)" + : "=r" (addend) + : "0" (addend), "r" (dest), "r" (mp) + : "cc", "memory"); + return addend + add_value; +} + +inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) { + return (void*)add_ptr(add_value, (volatile intptr_t*)dest); +} + +inline void Atomic::inc_ptr(volatile intptr_t* dest) { + bool mp = os::is_MP(); + __asm__ __volatile__ (LOCK_IF_MP(%1) "addq $1,(%0)" + : + : "r" (dest), "r" (mp) + : "cc", "memory"); +} + +inline void Atomic::dec_ptr(volatile intptr_t* dest) { + bool mp = os::is_MP(); + __asm__ __volatile__ (LOCK_IF_MP(%1) "subq $1,(%0)" + : + : "r" (dest), "r" (mp) + : "cc", "memory"); +} + +inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) { + __asm__ __volatile__ ("xchgq (%2),%0" + : "=r" (exchange_value) + : "0" (exchange_value), "r" (dest) + : "memory"); + return exchange_value; +} + +inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { + bool mp = os::is_MP(); + __asm__ __volatile__ (LOCK_IF_MP(%4) "cmpxchgq %1,(%3)" + : "=a" (exchange_value) + : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) + : "cc", "memory"); + return exchange_value; +} + +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { + return (intptr_t)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +} + +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { + return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); +} + +inline jlong Atomic::load(volatile jlong* src) { return *src; } + +#else // !AMD64 + +inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) { + return (intptr_t)Atomic::add((jint)add_value, (volatile jint*)dest); +} + +inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) { + return (void*)Atomic::add((jint)add_value, (volatile jint*)dest); +} + + +inline void Atomic::inc_ptr(volatile intptr_t* dest) { + inc((volatile jint*)dest); +} + +inline void Atomic::dec_ptr(volatile intptr_t* dest) { + dec((volatile jint*)dest); +} + +inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) { + return (intptr_t)xchg((jint)exchange_value, (volatile jint*)dest); +} + +extern "C" { + // defined in bsd_x86.s + jlong _Atomic_cmpxchg_long(jlong, volatile jlong*, jlong, bool); + void _Atomic_move_long(volatile jlong* src, volatile jlong* dst); +} + +inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { + return _Atomic_cmpxchg_long(exchange_value, dest, compare_value, os::is_MP()); +} + +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { + return (intptr_t)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); +} + +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { + return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); +} + +inline jlong Atomic::load(volatile jlong* src) { + volatile jlong dest; + _Atomic_move_long(src, &dest); + return dest; +} + +inline void Atomic::store(jlong store_value, jlong* dest) { + _Atomic_move_long((volatile jlong*)&store_value, (volatile jlong*)dest); +} + +inline void Atomic::store(jlong store_value, volatile jlong* dest) { + _Atomic_move_long((volatile jlong*)&store_value, dest); +} + +#endif // AMD64 + +#endif // OS_CPU_BSD_X86_VM_ATOMIC_BSD_X86_INLINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/bsd_x86_32.ad Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,160 @@ +// +// Copyright (c) 1999, 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. +// +// + +// X86 Bsd Architecture Description File + +//----------OS-DEPENDENT ENCODING BLOCK----------------------------------------------------- +// This block specifies the encoding classes used by the compiler to output +// byte streams. Encoding classes generate functions which are called by +// Machine Instruction Nodes in order to generate the bit encoding of the +// instruction. Operands specify their base encoding interface with the +// interface keyword. There are currently supported four interfaces, +// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an +// operand to generate a function which returns its register number when +// queried. CONST_INTER causes an operand to generate a function which +// returns the value of the constant when queried. MEMORY_INTER causes an +// operand to generate four functions which return the Base Register, the +// Index Register, the Scale Value, and the Offset Value of the operand when +// queried. COND_INTER causes an operand to generate six functions which +// return the encoding code (ie - encoding bits for the instruction) +// associated with each basic boolean condition for a conditional instruction. +// Instructions specify two basic values for encoding. They use the +// ins_encode keyword to specify their encoding class (which must be one of +// the class names specified in the encoding block), and they use the +// opcode keyword to specify, in order, their primary, secondary, and +// tertiary opcode. Only the opcode sections which a particular instruction +// needs for encoding need to be specified. +encode %{ + // Build emit functions for each basic byte or larger field in the intel + // encoding scheme (opcode, rm, sib, immediate), and call them from C++ + // code in the enc_class source block. Emit functions will live in the + // main source block for now. In future, we can generalize this by + // adding a syntax that specifies the sizes of fields in an order, + // so that the adlc can build the emit functions automagically + + enc_class bsd_tlsencode (eRegP dst) %{ + Register dstReg = as_Register($dst$$reg); + MacroAssembler* masm = new MacroAssembler(&cbuf); + masm->get_thread(dstReg); + %} + + enc_class bsd_breakpoint %{ + MacroAssembler* masm = new MacroAssembler(&cbuf); + masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); + %} + + enc_class call_epilog %{ + if( VerifyStackAtCalls ) { + // Check that stack depth is unchanged: find majik cookie on stack + int framesize = ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP,-3*VMRegImpl::slots_per_word)); + if(framesize >= 128) { + emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood + emit_d8(cbuf,0xBC); + emit_d8(cbuf,0x24); + emit_d32(cbuf,framesize); // Find majik cookie from ESP + emit_d32(cbuf, 0xbadb100d); + } + else { + emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood + emit_d8(cbuf,0x7C); + emit_d8(cbuf,0x24); + emit_d8(cbuf,framesize); // Find majik cookie from ESP + emit_d32(cbuf, 0xbadb100d); + } + // jmp EQ around INT3 + // QQQ TODO + const int jump_around = 5; // size of call to breakpoint, 1 for CC + emit_opcode(cbuf,0x74); + emit_d8(cbuf, jump_around); + // QQQ temporary + emit_break(cbuf); + // Die if stack mismatch + // emit_opcode(cbuf,0xCC); + } + %} + +%} + +// INSTRUCTIONS -- Platform dependent + +//----------OS and Locking Instructions---------------------------------------- + +// This name is KNOWN by the ADLC and cannot be changed. +// The ADLC forces a 'TypeRawPtr::BOTTOM' output type +// for this guy. +instruct tlsLoadP(eRegP dst, eFlagsReg cr) %{ + match(Set dst (ThreadLocal)); + effect(DEF dst, KILL cr); + + format %{ "MOV $dst, Thread::current()" %} + ins_encode( bsd_tlsencode(dst) ); + ins_pipe( ialu_reg_fat ); +%} + +instruct TLS(eRegP dst) %{ + match(Set dst (ThreadLocal)); + + expand %{ + tlsLoadP(dst); + %} +%} + +// Die now +instruct ShouldNotReachHere( ) +%{ + match(Halt); + + // Use the following format syntax + format %{ "INT3 ; ShouldNotReachHere" %} + // QQQ TODO for now call breakpoint + // opcode(0xCC); + // ins_encode(Opc); + ins_encode(bsd_breakpoint); + ins_pipe( pipe_slow ); +%} + + + +// Platform dependent source + +source %{ + +// emit an interrupt that is caught by the debugger +void emit_break(CodeBuffer &cbuf) { + + // Debugger doesn't really catch this but best we can do so far QQQ + MacroAssembler* masm = new MacroAssembler(&cbuf); + masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); +} + +void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { + emit_break(cbuf); +} + + +uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { + return 5; +} + +%}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/bsd_x86_32.s Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,689 @@ +# +# Copyright (c) 2004, 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. +# + + +#ifdef __APPLE__ +# Darwin uses _ prefixed global symbols +#define SYMBOL(s) _ ## s +#define ELF_TYPE(name, description) +#else +#define SYMBOL(s) s +#define ELF_TYPE(name, description) .type name,description +#endif + + .globl SYMBOL(fixcw) + + # NOTE WELL! The _Copy functions are called directly + # from server-compiler-generated code via CallLeafNoFP, + # which means that they *must* either not use floating + # point or use it in the same manner as does the server + # compiler. + + .globl SYMBOL(_Copy_conjoint_bytes) + .globl SYMBOL(_Copy_arrayof_conjoint_bytes) + .globl SYMBOL(_Copy_conjoint_jshorts_atomic) + .globl SYMBOL(_Copy_arrayof_conjoint_jshorts) + .globl SYMBOL(_Copy_conjoint_jints_atomic) + .globl SYMBOL(_Copy_arrayof_conjoint_jints) + .globl SYMBOL(_Copy_conjoint_jlongs_atomic) + .globl SYMBOL(_mmx_Copy_arrayof_conjoint_jshorts) + + .globl SYMBOL(_Atomic_cmpxchg_long) + .globl SYMBOL(_Atomic_move_long) + + .text + +# Support for void os::Solaris::init_thread_fpu_state() in os_solaris_i486.cpp +# Set fpu to 53 bit precision. This happens too early to use a stub. +# ported from solaris_x86_32.s + .p2align 4,,15 +SYMBOL(fixcw): + pushl $0x27f + fldcw 0(%esp) + popl %eax + ret + + .globl SYMBOL(SafeFetch32), SYMBOL(Fetch32PFI), SYMBOL(Fetch32Resume) + .globl SYMBOL(SafeFetchN) + ## TODO: avoid exposing Fetch32PFI and Fetch32Resume. + ## Instead, the signal handler would call a new SafeFetchTriage(FaultingEIP) + ## routine to vet the address. If the address is the faulting LD then + ## SafeFetchTriage() would return the resume-at EIP, otherwise null. + ELF_TYPE(SafeFetch32,@function) + .p2align 4,,15 +SYMBOL(SafeFetch32): +SYMBOL(SafeFetchN): + movl 0x8(%esp), %eax + movl 0x4(%esp), %ecx +SYMBOL(Fetch32PFI): + movl (%ecx), %eax +SYMBOL(Fetch32Resume): + ret + + + .globl SYMBOL(SpinPause) + ELF_TYPE(SpinPause,@function) + .p2align 4,,15 +SYMBOL(SpinPause): + rep + nop + movl $1, %eax + ret + + # Support for void Copy::conjoint_bytes(void* from, + # void* to, + # size_t count) + .p2align 4,,15 + ELF_TYPE(_Copy_conjoint_bytes,@function) +SYMBOL(_Copy_conjoint_bytes): + pushl %esi + movl 4+12(%esp),%ecx # count + pushl %edi + movl 8+ 4(%esp),%esi # from + movl 8+ 8(%esp),%edi # to + cmpl %esi,%edi + leal -1(%esi,%ecx),%eax # from + count - 1 + jbe cb_CopyRight + cmpl %eax,%edi + jbe cb_CopyLeft + # copy from low to high +cb_CopyRight: + cmpl $3,%ecx + jbe 5f # <= 3 bytes + # align source address at dword address boundary + movl %ecx,%eax # original count + movl $4,%ecx + subl %esi,%ecx + andl $3,%ecx # prefix byte count + jz 1f # no prefix + subl %ecx,%eax # byte count less prefix + # copy prefix + subl %esi,%edi +0: movb (%esi),%dl + movb %dl,(%edi,%esi,1) + addl $1,%esi + subl $1,%ecx + jnz 0b + addl %esi,%edi +1: movl %eax,%ecx # byte count less prefix + shrl $2,%ecx # dword count + jz 4f # no dwords to move + cmpl $32,%ecx + jbe 2f # <= 32 dwords + # copy aligned dwords + rep; smovl + jmp 4f + # copy aligned dwords +2: subl %esi,%edi + .p2align 4,,15 +3: movl (%esi),%edx + movl %edx,(%edi,%esi,1) + addl $4,%esi + subl $1,%ecx + jnz 3b + addl %esi,%edi +4: movl %eax,%ecx # byte count less prefix +5: andl $3,%ecx # suffix byte count + jz 7f # no suffix + # copy suffix + xorl %eax,%eax +6: movb (%esi,%eax,1),%dl + movb %dl,(%edi,%eax,1) + addl $1,%eax + subl $1,%ecx + jnz 6b +7: popl %edi + popl %esi + ret + # copy from high to low +cb_CopyLeft: + std + leal -4(%edi,%ecx),%edi # to + count - 4 + movl %eax,%esi # from + count - 1 + movl %ecx,%eax + subl $3,%esi # from + count - 4 + cmpl $3,%ecx + jbe 5f # <= 3 bytes +1: shrl $2,%ecx # dword count + jz 4f # no dwords to move + cmpl $32,%ecx + ja 3f # > 32 dwords + # copy dwords, aligned or not + subl %esi,%edi + .p2align 4,,15 +2: movl (%esi),%edx + movl %edx,(%edi,%esi,1) + subl $4,%esi + subl $1,%ecx + jnz 2b + addl %esi,%edi + jmp 4f + # copy dwords, aligned or not +3: rep; smovl +4: movl %eax,%ecx # byte count +5: andl $3,%ecx # suffix byte count + jz 7f # no suffix + # copy suffix + subl %esi,%edi + addl $3,%esi +6: movb (%esi),%dl + movb %dl,(%edi,%esi,1) + subl $1,%esi + subl $1,%ecx + jnz 6b +7: cld + popl %edi + popl %esi + ret + + # Support for void Copy::arrayof_conjoint_bytes(void* from, + # void* to, + # size_t count) + # + # Same as _Copy_conjoint_bytes, except no source alignment check. + .p2align 4,,15 + ELF_TYPE(_Copy_arrayof_conjoint_bytes,@function) +SYMBOL(_Copy_arrayof_conjoint_bytes): + pushl %esi + movl 4+12(%esp),%ecx # count + pushl %edi + movl 8+ 4(%esp),%esi # from + movl 8+ 8(%esp),%edi # to + cmpl %esi,%edi + leal -1(%esi,%ecx),%eax # from + count - 1 + jbe acb_CopyRight + cmpl %eax,%edi + jbe acb_CopyLeft + # copy from low to high +acb_CopyRight: + cmpl $3,%ecx + jbe 5f +1: movl %ecx,%eax + shrl $2,%ecx + jz 4f + cmpl $32,%ecx + ja 3f + # copy aligned dwords + subl %esi,%edi + .p2align 4,,15 +2: movl (%esi),%edx + movl %edx,(%edi,%esi,1) + addl $4,%esi + subl $1,%ecx + jnz 2b + addl %esi,%edi + jmp 4f + # copy aligned dwords +3: rep; smovl +4: movl %eax,%ecx +5: andl $3,%ecx + jz 7f + # copy suffix + xorl %eax,%eax +6: movb (%esi,%eax,1),%dl + movb %dl,(%edi,%eax,1) + addl $1,%eax + subl $1,%ecx + jnz 6b +7: popl %edi + popl %esi + ret +acb_CopyLeft: + std + leal -4(%edi,%ecx),%edi # to + count - 4 + movl %eax,%esi # from + count - 1 + movl %ecx,%eax + subl $3,%esi # from + count - 4 + cmpl $3,%ecx + jbe 5f +1: shrl $2,%ecx + jz 4f + cmpl $32,%ecx + jbe 2f # <= 32 dwords + rep; smovl + jmp 4f + .space 8 +2: subl %esi,%edi + .p2align 4,,15 +3: movl (%esi),%edx + movl %edx,(%edi,%esi,1) + subl $4,%esi + subl $1,%ecx + jnz 3b + addl %esi,%edi +4: movl %eax,%ecx +5: andl $3,%ecx + jz 7f + subl %esi,%edi + addl $3,%esi +6: movb (%esi),%dl + movb %dl,(%edi,%esi,1) + subl $1,%esi + subl $1,%ecx + jnz 6b +7: cld + popl %edi + popl %esi + ret + + # Support for void Copy::conjoint_jshorts_atomic(void* from, + # void* to, + # size_t count) + .p2align 4,,15 + ELF_TYPE(_Copy_conjoint_jshorts_atomic,@function) +SYMBOL(_Copy_conjoint_jshorts_atomic): + pushl %esi + movl 4+12(%esp),%ecx # count + pushl %edi + movl 8+ 4(%esp),%esi # from + movl 8+ 8(%esp),%edi # to + cmpl %esi,%edi + leal -2(%esi,%ecx,2),%eax # from + count*2 - 2 + jbe cs_CopyRight + cmpl %eax,%edi + jbe cs_CopyLeft + # copy from low to high +cs_CopyRight: + # align source address at dword address boundary + movl %esi,%eax # original from + andl $3,%eax # either 0 or 2 + jz 1f # no prefix + # copy prefix + subl $1,%ecx + jl 5f # zero count + movw (%esi),%dx + movw %dx,(%edi) + addl %eax,%esi # %eax == 2 + addl %eax,%edi +1: movl %ecx,%eax # word count less prefix + sarl %ecx # dword count + jz 4f # no dwords to move + cmpl $32,%ecx + jbe 2f # <= 32 dwords + # copy aligned dwords + rep; smovl + jmp 4f + # copy aligned dwords +2: subl %esi,%edi + .p2align 4,,15 +3: movl (%esi),%edx + movl %edx,(%edi,%esi,1) + addl $4,%esi + subl $1,%ecx + jnz 3b + addl %esi,%edi +4: andl $1,%eax # suffix count + jz 5f # no suffix + # copy suffix + movw (%esi),%dx + movw %dx,(%edi) +5: popl %edi + popl %esi + ret + # copy from high to low +cs_CopyLeft: + std + leal -4(%edi,%ecx,2),%edi # to + count*2 - 4 + movl %eax,%esi # from + count*2 - 2 + movl %ecx,%eax + subl $2,%esi # from + count*2 - 4 +1: sarl %ecx # dword count + jz 4f # no dwords to move + cmpl $32,%ecx + ja 3f # > 32 dwords + subl %esi,%edi + .p2align 4,,15 +2: movl (%esi),%edx + movl %edx,(%edi,%esi,1) + subl $4,%esi + subl $1,%ecx + jnz 2b + addl %esi,%edi + jmp 4f +3: rep; smovl +4: andl $1,%eax # suffix count + jz 5f # no suffix + # copy suffix + addl $2,%esi + addl $2,%edi + movw (%esi),%dx + movw %dx,(%edi) +5: cld + popl %edi + popl %esi + ret + + # Support for void Copy::arrayof_conjoint_jshorts(void* from, + # void* to, + # size_t count) + .p2align 4,,15 + ELF_TYPE(_Copy_arrayof_conjoint_jshorts,@function) +SYMBOL(_Copy_arrayof_conjoint_jshorts): + pushl %esi + movl 4+12(%esp),%ecx # count + pushl %edi + movl 8+ 4(%esp),%esi # from + movl 8+ 8(%esp),%edi # to + cmpl %esi,%edi + leal -2(%esi,%ecx,2),%eax # from + count*2 - 2 + jbe acs_CopyRight + cmpl %eax,%edi + jbe acs_CopyLeft +acs_CopyRight: + movl %ecx,%eax # word count + sarl %ecx # dword count + jz 4f # no dwords to move + cmpl $32,%ecx + jbe 2f # <= 32 dwords + # copy aligned dwords + rep; smovl + jmp 4f + # copy aligned dwords + .space 5 +2: subl %esi,%edi + .p2align 4,,15 +3: movl (%esi),%edx + movl %edx,(%edi,%esi,1) + addl $4,%esi + subl $1,%ecx + jnz 3b + addl %esi,%edi +4: andl $1,%eax # suffix count + jz 5f # no suffix + # copy suffix + movw (%esi),%dx + movw %dx,(%edi) +5: popl %edi + popl %esi + ret +acs_CopyLeft: + std + leal -4(%edi,%ecx,2),%edi # to + count*2 - 4 + movl %eax,%esi # from + count*2 - 2 + movl %ecx,%eax + subl $2,%esi # from + count*2 - 4 + sarl %ecx # dword count + jz 4f # no dwords to move + cmpl $32,%ecx + ja 3f # > 32 dwords + subl %esi,%edi + .p2align 4,,15 +2: movl (%esi),%edx + movl %edx,(%edi,%esi,1) + subl $4,%esi + subl $1,%ecx + jnz 2b + addl %esi,%edi + jmp 4f +3: rep; smovl +4: andl $1,%eax # suffix count + jz 5f # no suffix + # copy suffix + addl $2,%esi + addl $2,%edi + movw (%esi),%dx + movw %dx,(%edi) +5: cld + popl %edi + popl %esi + ret + + # Support for void Copy::conjoint_jints_atomic(void* from, + # void* to, + # size_t count) + # Equivalent to + # arrayof_conjoint_jints + .p2align 4,,15 + ELF_TYPE(_Copy_conjoint_jints_atomic,@function) + ELF_TYPE(_Copy_arrayof_conjoint_jints,@function) +SYMBOL(_Copy_conjoint_jints_atomic): +SYMBOL(_Copy_arrayof_conjoint_jints): + pushl %esi + movl 4+12(%esp),%ecx # count + pushl %edi + movl 8+ 4(%esp),%esi # from + movl 8+ 8(%esp),%edi # to + cmpl %esi,%edi + leal -4(%esi,%ecx,4),%eax # from + count*4 - 4 + jbe ci_CopyRight + cmpl %eax,%edi + jbe ci_CopyLeft +ci_CopyRight: + cmpl $32,%ecx + jbe 2f # <= 32 dwords + rep; smovl + popl %edi + popl %esi + ret + .space 10 +2: subl %esi,%edi + jmp 4f + .p2align 4,,15 +3: movl (%esi),%edx + movl %edx,(%edi,%esi,1) + addl $4,%esi +4: subl $1,%ecx + jge 3b + popl %edi + popl %esi + ret +ci_CopyLeft: + std + leal -4(%edi,%ecx,4),%edi # to + count*4 - 4 + cmpl $32,%ecx + ja 4f # > 32 dwords + subl %eax,%edi # eax == from + count*4 - 4 + jmp 3f + .p2align 4,,15 +2: movl (%eax),%edx + movl %edx,(%edi,%eax,1) + subl $4,%eax +3: subl $1,%ecx + jge 2b + cld + popl %edi + popl %esi + ret +4: movl %eax,%esi # from + count*4 - 4 + rep; smovl + cld + popl %edi + popl %esi + ret + + # Support for void Copy::conjoint_jlongs_atomic(jlong* from, + # jlong* to, + # size_t count) + # + # 32-bit + # + # count treated as signed + # + # // if (from > to) { + # while (--count >= 0) { + # *to++ = *from++; + # } + # } else { + # while (--count >= 0) { + # to[count] = from[count]; + # } + # } + .p2align 4,,15 + ELF_TYPE(_Copy_conjoint_jlongs_atomic,@function) +SYMBOL(_Copy_conjoint_jlongs_atomic): + movl 4+8(%esp),%ecx # count + movl 4+0(%esp),%eax # from + movl 4+4(%esp),%edx # to + cmpl %eax,%edx + jae cla_CopyLeft +cla_CopyRight: + subl %eax,%edx + jmp 2f + .p2align 4,,15 +1: fildll (%eax) + fistpll (%edx,%eax,1) + addl $8,%eax +2: subl $1,%ecx + jge 1b + ret + .p2align 4,,15 +3: fildll (%eax,%ecx,8) + fistpll (%edx,%ecx,8) +cla_CopyLeft: + subl $1,%ecx + jge 3b + ret + + # Support for void Copy::arrayof_conjoint_jshorts(void* from, + # void* to, + # size_t count) + .p2align 4,,15 + ELF_TYPE(_mmx_Copy_arrayof_conjoint_jshorts,@function) +SYMBOL(_mmx_Copy_arrayof_conjoint_jshorts): + pushl %esi + movl 4+12(%esp),%ecx + pushl %edi + movl 8+ 4(%esp),%esi + movl 8+ 8(%esp),%edi + cmpl %esi,%edi + leal -2(%esi,%ecx,2),%eax + jbe mmx_acs_CopyRight + cmpl %eax,%edi + jbe mmx_acs_CopyLeft +mmx_acs_CopyRight: + movl %ecx,%eax + sarl %ecx + je 5f + cmpl $33,%ecx + jae 3f +1: subl %esi,%edi + .p2align 4,,15 +2: movl (%esi),%edx + movl %edx,(%edi,%esi,1) + addl $4,%esi + subl $1,%ecx + jnz 2b + addl %esi,%edi + jmp 5f +3: smovl # align to 8 bytes, we know we are 4 byte aligned to start + subl $1,%ecx +4: .p2align 4,,15 + movq 0(%esi),%mm0 + addl $64,%edi + movq 8(%esi),%mm1 + subl $16,%ecx + movq 16(%esi),%mm2 + movq %mm0,-64(%edi) + movq 24(%esi),%mm0 + movq %mm1,-56(%edi) + movq 32(%esi),%mm1 + movq %mm2,-48(%edi) + movq 40(%esi),%mm2 + movq %mm0,-40(%edi) + movq 48(%esi),%mm0 + movq %mm1,-32(%edi) + movq 56(%esi),%mm1 + movq %mm2,-24(%edi) + movq %mm0,-16(%edi) + addl $64,%esi + movq %mm1,-8(%edi) + cmpl $16,%ecx + jge 4b + emms + testl %ecx,%ecx + ja 1b +5: andl $1,%eax + je 7f +6: movw (%esi),%dx + movw %dx,(%edi) +7: popl %edi + popl %esi + ret +mmx_acs_CopyLeft: + std + leal -4(%edi,%ecx,2),%edi + movl %eax,%esi + movl %ecx,%eax + subl $2,%esi + sarl %ecx + je 4f + cmpl $32,%ecx + ja 3f + subl %esi,%edi + .p2align 4,,15 +2: movl (%esi),%edx + movl %edx,(%edi,%esi,1) + subl $4,%esi + subl $1,%ecx + jnz 2b + addl %esi,%edi + jmp 4f +3: rep; smovl +4: andl $1,%eax + je 6f + addl $2,%esi + addl $2,%edi +5: movw (%esi),%dx + movw %dx,(%edi) +6: cld + popl %edi + popl %esi + ret + + + # Support for jlong Atomic::cmpxchg(jlong exchange_value, + # volatile jlong* dest, + # jlong compare_value, + # bool is_MP) + # + .p2align 4,,15 + ELF_TYPE(_Atomic_cmpxchg_long,@function) +SYMBOL(_Atomic_cmpxchg_long): + # 8(%esp) : return PC + pushl %ebx # 4(%esp) : old %ebx + pushl %edi # 0(%esp) : old %edi + movl 12(%esp), %ebx # 12(%esp) : exchange_value (low) + movl 16(%esp), %ecx # 16(%esp) : exchange_value (high) + movl 24(%esp), %eax # 24(%esp) : compare_value (low) + movl 28(%esp), %edx # 28(%esp) : compare_value (high) + movl 20(%esp), %edi # 20(%esp) : dest + cmpl $0, 32(%esp) # 32(%esp) : is_MP + je 1f + lock +1: cmpxchg8b (%edi) + popl %edi + popl %ebx + ret + + + # Support for jlong Atomic::load and Atomic::store. + # void _Atomic_move_long(volatile jlong* src, volatile jlong* dst) + .p2align 4,,15 + ELF_TYPE(_Atomic_move_long,@function) +SYMBOL(_Atomic_move_long): + movl 4(%esp), %eax # src + fildll (%eax) + movl 8(%esp), %eax # dest + fistpll (%eax) + ret +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/bsd_x86_64.ad Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,173 @@ +// +// Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +// or visit www.oracle.com if you need additional information or have any +// questions. +// +// + +// AMD64 Bsd Architecture Description File + +//----------OS-DEPENDENT ENCODING BLOCK---------------------------------------- +// This block specifies the encoding classes used by the compiler to +// output byte streams. Encoding classes generate functions which are +// called by Machine Instruction Nodes in order to generate the bit +// encoding of the instruction. Operands specify their base encoding +// interface with the interface keyword. There are currently +// supported four interfaces, REG_INTER, CONST_INTER, MEMORY_INTER, & +// COND_INTER. REG_INTER causes an operand to generate a function +// which returns its register number when queried. CONST_INTER causes +// an operand to generate a function which returns the value of the +// constant when queried. MEMORY_INTER causes an operand to generate +// four functions which return the Base Register, the Index Register, +// the Scale Value, and the Offset Value of the operand when queried. +// COND_INTER causes an operand to generate six functions which return +// the encoding code (ie - encoding bits for the instruction) +// associated with each basic boolean condition for a conditional +// instruction. Instructions specify two basic values for encoding. +// They use the ins_encode keyword to specify their encoding class +// (which must be one of the class names specified in the encoding +// block), and they use the opcode keyword to specify, in order, their +// primary, secondary, and tertiary opcode. Only the opcode sections +// which a particular instruction needs for encoding need to be +// specified. +encode %{ + // Build emit functions for each basic byte or larger field in the intel + // encoding scheme (opcode, rm, sib, immediate), and call them from C++ + // code in the enc_class source block. Emit functions will live in the + // main source block for now. In future, we can generalize this by + // adding a syntax that specifies the sizes of fields in an order, + // so that the adlc can build the emit functions automagically + + enc_class Java_To_Runtime(method meth) + %{ + // No relocation needed + + // movq r10, <meth> + emit_opcode(cbuf, Assembler::REX_WB); + emit_opcode(cbuf, 0xB8 | (R10_enc - 8)); + emit_d64(cbuf, (int64_t) $meth$$method); + + // call (r10) + emit_opcode(cbuf, Assembler::REX_B); + emit_opcode(cbuf, 0xFF); + emit_opcode(cbuf, 0xD0 | (R10_enc - 8)); + %} + + enc_class bsd_breakpoint + %{ + MacroAssembler* masm = new MacroAssembler(&cbuf); + masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); + %} + + enc_class call_epilog + %{ + if (VerifyStackAtCalls) { + // Check that stack depth is unchanged: find majik cookie on stack + int framesize = + ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP, -3*VMRegImpl::slots_per_word)); + if (framesize) { + if (framesize < 0x80) { + emit_opcode(cbuf, Assembler::REX_W); + emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood + emit_d8(cbuf, 0x7C); + emit_d8(cbuf, 0x24); + emit_d8(cbuf, framesize); // Find majik cookie from ESP + emit_d32(cbuf, 0xbadb100d); + } else { + emit_opcode(cbuf, Assembler::REX_W); + emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood + emit_d8(cbuf, 0xBC); + emit_d8(cbuf, 0x24); + emit_d32(cbuf, framesize); // Find majik cookie from ESP + emit_d32(cbuf, 0xbadb100d); + } + } + // jmp EQ around INT3 + // QQQ TODO + const int jump_around = 5; // size of call to breakpoint, 1 for CC + emit_opcode(cbuf, 0x74); + emit_d8(cbuf, jump_around); + // QQQ temporary + emit_break(cbuf); + // Die if stack mismatch + // emit_opcode(cbuf,0xCC); + } + %} + +%} + +// INSTRUCTIONS -- Platform dependent + +//----------OS and Locking Instructions---------------------------------------- + +// This name is KNOWN by the ADLC and cannot be changed. +// The ADLC forces a 'TypeRawPtr::BOTTOM' output type +// for this guy. +instruct tlsLoadP(r15_RegP dst) +%{ + match(Set dst (ThreadLocal)); + effect(DEF dst); + + size(0); + format %{ "# TLS is in R15" %} + ins_encode( /*empty encoding*/ ); + ins_pipe(ialu_reg_reg); +%} + +// Die now +instruct ShouldNotReachHere() +%{ + match(Halt); + + // Use the following format syntax + format %{ "int3\t# ShouldNotReachHere" %} + // QQQ TODO for now call breakpoint + // opcode(0xCC); + // ins_encode(Opc); + ins_encode(bsd_breakpoint); + ins_pipe(pipe_slow); +%} + + +// Platform dependent source + +source +%{ + +int MachCallRuntimeNode::ret_addr_offset() { + return 13; // movq r10,#addr; callq (r10) +} + +// emit an interrupt that is caught by the debugger +void emit_break(CodeBuffer& cbuf) { + // Debugger doesn't really catch this but best we can do so far QQQ + MacroAssembler* masm = new MacroAssembler(&cbuf); + masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); +} + +void MachBreakpointNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { + emit_break(cbuf); +} + +uint MachBreakpointNode::size(PhaseRegAlloc* ra_) const { + return 5; +} + +%}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/bsd_x86_64.s Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,410 @@ +# +# Copyright (c) 2004, 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. +# + +#ifdef __APPLE__ +# Darwin uses _ prefixed global symbols +#define SYMBOL(s) _ ## s +#define ELF_TYPE(name, description) +#else +#define SYMBOL(s) s +#define ELF_TYPE(name, description) .type name,description +#endif + + # NOTE WELL! The _Copy functions are called directly + # from server-compiler-generated code via CallLeafNoFP, + # which means that they *must* either not use floating + # point or use it in the same manner as does the server + # compiler. + + .globl SYMBOL(_Copy_arrayof_conjoint_bytes) + .globl SYMBOL(_Copy_arrayof_conjoint_jshorts) + .globl SYMBOL(_Copy_conjoint_jshorts_atomic) + .globl SYMBOL(_Copy_arrayof_conjoint_jints) + .globl SYMBOL(_Copy_conjoint_jints_atomic) + .globl SYMBOL(_Copy_arrayof_conjoint_jlongs) + .globl SYMBOL(_Copy_conjoint_jlongs_atomic) + + .text + + .globl SYMBOL(SafeFetch32), SYMBOL(Fetch32PFI), SYMBOL(Fetch32Resume) + .p2align 4,,15 + ELF_TYPE(SafeFetch32,@function) + // Prototype: int SafeFetch32 (int * Adr, int ErrValue) +SYMBOL(SafeFetch32): + movl %esi, %eax +SYMBOL(Fetch32PFI): + movl (%rdi), %eax +SYMBOL(Fetch32Resume): + ret + + .globl SYMBOL(SafeFetchN), SYMBOL(FetchNPFI), SYMBOL(FetchNResume) + .p2align 4,,15 + ELF_TYPE(SafeFetchN,@function) + // Prototype: intptr_t SafeFetchN (intptr_t * Adr, intptr_t ErrValue) +SYMBOL(SafeFetchN): + movq %rsi, %rax +SYMBOL(FetchNPFI): + movq (%rdi), %rax +SYMBOL(FetchNResume): + ret + + .globl SYMBOL(SpinPause) + .p2align 4,,15 + ELF_TYPE(SpinPause,@function) +SYMBOL(SpinPause): + rep + nop + movq $1, %rax + ret + + # Support for void Copy::arrayof_conjoint_bytes(void* from, + # void* to, + # size_t count) + # rdi - from + # rsi - to + # rdx - count, treated as ssize_t + # + .p2align 4,,15 + ELF_TYPE(_Copy_arrayof_conjoint_bytes,@function) +SYMBOL(_Copy_arrayof_conjoint_bytes): + movq %rdx,%r8 # byte count + shrq $3,%rdx # qword count + cmpq %rdi,%rsi + leaq -1(%rdi,%r8,1),%rax # from + bcount*1 - 1 + jbe acb_CopyRight + cmpq %rax,%rsi + jbe acb_CopyLeft +acb_CopyRight: + leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8 + leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8 + negq %rdx + jmp 7f + .p2align 4,,15 +1: movq 8(%rax,%rdx,8),%rsi + movq %rsi,8(%rcx,%rdx,8) + addq $1,%rdx + jnz 1b +2: testq $4,%r8 # check for trailing dword + jz 3f + movl 8(%rax),%esi # copy trailing dword + movl %esi,8(%rcx) + addq $4,%rax + addq $4,%rcx # original %rsi is trashed, so we + # can't use it as a base register +3: testq $2,%r8 # check for trailing word + jz 4f + movw 8(%rax),%si # copy trailing word + movw %si,8(%rcx) + addq $2,%rcx +4: testq $1,%r8 # check for trailing byte + jz 5f + movb -1(%rdi,%r8,1),%al # copy trailing byte + movb %al,8(%rcx) +5: ret + .p2align 4,,15 +6: movq -24(%rax,%rdx,8),%rsi + movq %rsi,-24(%rcx,%rdx,8) + movq -16(%rax,%rdx,8),%rsi + movq %rsi,-16(%rcx,%rdx,8) + movq -8(%rax,%rdx,8),%rsi + movq %rsi,-8(%rcx,%rdx,8) + movq (%rax,%rdx,8),%rsi + movq %rsi,(%rcx,%rdx,8) +7: addq $4,%rdx + jle 6b + subq $4,%rdx + jl 1b + jmp 2b +acb_CopyLeft: + testq $1,%r8 # check for trailing byte + jz 1f + movb -1(%rdi,%r8,1),%cl # copy trailing byte + movb %cl,-1(%rsi,%r8,1) + subq $1,%r8 # adjust for possible trailing word +1: testq $2,%r8 # check for trailing word + jz 2f + movw -2(%rdi,%r8,1),%cx # copy trailing word + movw %cx,-2(%rsi,%r8,1) +2: testq $4,%r8 # check for trailing dword + jz 5f + movl (%rdi,%rdx,8),%ecx # copy trailing dword + movl %ecx,(%rsi,%rdx,8) + jmp 5f + .p2align 4,,15 +3: movq -8(%rdi,%rdx,8),%rcx + movq %rcx,-8(%rsi,%rdx,8) + subq $1,%rdx + jnz 3b + ret + .p2align 4,,15 +4: movq 24(%rdi,%rdx,8),%rcx + movq %rcx,24(%rsi,%rdx,8) + movq 16(%rdi,%rdx,8),%rcx + movq %rcx,16(%rsi,%rdx,8) + movq 8(%rdi,%rdx,8),%rcx + movq %rcx,8(%rsi,%rdx,8) + movq (%rdi,%rdx,8),%rcx + movq %rcx,(%rsi,%rdx,8) +5: subq $4,%rdx + jge 4b + addq $4,%rdx + jg 3b + ret + + # Support for void Copy::arrayof_conjoint_jshorts(void* from, + # void* to, + # size_t count) + # Equivalent to + # conjoint_jshorts_atomic + # + # If 'from' and/or 'to' are aligned on 4- or 2-byte boundaries, we + # let the hardware handle it. The tow or four words within dwords + # or qwords that span cache line boundaries will still be loaded + # and stored atomically. + # + # rdi - from + # rsi - to + # rdx - count, treated as ssize_t + # + .p2align 4,,15 + ELF_TYPE(_Copy_arrayof_conjoint_jshorts,@function) + ELF_TYPE(_Copy_conjoint_jshorts_atomic,@function) +SYMBOL(_Copy_arrayof_conjoint_jshorts): +SYMBOL(_Copy_conjoint_jshorts_atomic): + movq %rdx,%r8 # word count + shrq $2,%rdx # qword count + cmpq %rdi,%rsi + leaq -2(%rdi,%r8,2),%rax # from + wcount*2 - 2 + jbe acs_CopyRight + cmpq %rax,%rsi + jbe acs_CopyLeft +acs_CopyRight: + leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8 + leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8 + negq %rdx + jmp 6f +1: movq 8(%rax,%rdx,8),%rsi + movq %rsi,8(%rcx,%rdx,8) + addq $1,%rdx + jnz 1b +2: testq $2,%r8 # check for trailing dword + jz 3f + movl 8(%rax),%esi # copy trailing dword + movl %esi,8(%rcx) + addq $4,%rcx # original %rsi is trashed, so we + # can't use it as a base register +3: testq $1,%r8 # check for trailing word + jz 4f + movw -2(%rdi,%r8,2),%si # copy trailing word + movw %si,8(%rcx) +4: ret + .p2align 4,,15 +5: movq -24(%rax,%rdx,8),%rsi + movq %rsi,-24(%rcx,%rdx,8) + movq -16(%rax,%rdx,8),%rsi + movq %rsi,-16(%rcx,%rdx,8) + movq -8(%rax,%rdx,8),%rsi + movq %rsi,-8(%rcx,%rdx,8) + movq (%rax,%rdx,8),%rsi + movq %rsi,(%rcx,%rdx,8) +6: addq $4,%rdx + jle 5b + subq $4,%rdx + jl 1b + jmp 2b +acs_CopyLeft: + testq $1,%r8 # check for trailing word + jz 1f + movw -2(%rdi,%r8,2),%cx # copy trailing word + movw %cx,-2(%rsi,%r8,2) +1: testq $2,%r8 # check for trailing dword + jz 4f + movl (%rdi,%rdx,8),%ecx # copy trailing dword + movl %ecx,(%rsi,%rdx,8) + jmp 4f +2: movq -8(%rdi,%rdx,8),%rcx + movq %rcx,-8(%rsi,%rdx,8) + subq $1,%rdx + jnz 2b + ret + .p2align 4,,15 +3: movq 24(%rdi,%rdx,8),%rcx + movq %rcx,24(%rsi,%rdx,8) + movq 16(%rdi,%rdx,8),%rcx + movq %rcx,16(%rsi,%rdx,8) + movq 8(%rdi,%rdx,8),%rcx + movq %rcx,8(%rsi,%rdx,8) + movq (%rdi,%rdx,8),%rcx + movq %rcx,(%rsi,%rdx,8) +4: subq $4,%rdx + jge 3b + addq $4,%rdx + jg 2b + ret + + # Support for void Copy::arrayof_conjoint_jints(jint* from, + # jint* to, + # size_t count) + # Equivalent to + # conjoint_jints_atomic + # + # If 'from' and/or 'to' are aligned on 4-byte boundaries, we let + # the hardware handle it. The two dwords within qwords that span + # cache line boundaries will still be loaded and stored atomically. + # + # rdi - from + # rsi - to + # rdx - count, treated as ssize_t + # + .p2align 4,,15 + ELF_TYPE(_Copy_arrayof_conjoint_jints,@function) + ELF_TYPE(_Copy_conjoint_jints_atomic,@function) +SYMBOL(_Copy_arrayof_conjoint_jints): +SYMBOL(_Copy_conjoint_jints_atomic): + movq %rdx,%r8 # dword count + shrq %rdx # qword count + cmpq %rdi,%rsi + leaq -4(%rdi,%r8,4),%rax # from + dcount*4 - 4 + jbe aci_CopyRight + cmpq %rax,%rsi + jbe aci_CopyLeft +aci_CopyRight: + leaq -8(%rdi,%rdx,8),%rax # from + qcount*8 - 8 + leaq -8(%rsi,%rdx,8),%rcx # to + qcount*8 - 8 + negq %rdx + jmp 5f + .p2align 4,,15 +1: movq 8(%rax,%rdx,8),%rsi + movq %rsi,8(%rcx,%rdx,8) + addq $1,%rdx + jnz 1b +2: testq $1,%r8 # check for trailing dword + jz 3f + movl 8(%rax),%esi # copy trailing dword + movl %esi,8(%rcx) +3: ret + .p2align 4,,15 +4: movq -24(%rax,%rdx,8),%rsi + movq %rsi,-24(%rcx,%rdx,8) + movq -16(%rax,%rdx,8),%rsi + movq %rsi,-16(%rcx,%rdx,8) + movq -8(%rax,%rdx,8),%rsi + movq %rsi,-8(%rcx,%rdx,8) + movq (%rax,%rdx,8),%rsi + movq %rsi,(%rcx,%rdx,8) +5: addq $4,%rdx + jle 4b + subq $4,%rdx + jl 1b + jmp 2b +aci_CopyLeft: + testq $1,%r8 # check for trailing dword + jz 3f + movl -4(%rdi,%r8,4),%ecx # copy trailing dword + movl %ecx,-4(%rsi,%r8,4) + jmp 3f +1: movq -8(%rdi,%rdx,8),%rcx + movq %rcx,-8(%rsi,%rdx,8) + subq $1,%rdx + jnz 1b + ret + .p2align 4,,15 +2: movq 24(%rdi,%rdx,8),%rcx + movq %rcx,24(%rsi,%rdx,8) + movq 16(%rdi,%rdx,8),%rcx + movq %rcx,16(%rsi,%rdx,8) + movq 8(%rdi,%rdx,8),%rcx + movq %rcx,8(%rsi,%rdx,8) + movq (%rdi,%rdx,8),%rcx + movq %rcx,(%rsi,%rdx,8) +3: subq $4,%rdx + jge 2b + addq $4,%rdx + jg 1b + ret + + # Support for void Copy::arrayof_conjoint_jlongs(jlong* from, + # jlong* to, + # size_t count) + # Equivalent to + # conjoint_jlongs_atomic + # arrayof_conjoint_oops + # conjoint_oops_atomic + # + # rdi - from + # rsi - to + # rdx - count, treated as ssize_t + # + .p2align 4,,15 + ELF_TYPE(_Copy_arrayof_conjoint_jlongs,@function) + ELF_TYPE(_Copy_conjoint_jlongs_atomic,@function) +SYMBOL(_Copy_arrayof_conjoint_jlongs): +SYMBOL(_Copy_conjoint_jlongs_atomic): + cmpq %rdi,%rsi + leaq -8(%rdi,%rdx,8),%rax # from + count*8 - 8 + jbe acl_CopyRight + cmpq %rax,%rsi + jbe acl_CopyLeft +acl_CopyRight: + leaq -8(%rsi,%rdx,8),%rcx # to + count*8 - 8 + negq %rdx + jmp 3f +1: movq 8(%rax,%rdx,8),%rsi + movq %rsi,8(%rcx,%rdx,8) + addq $1,%rdx + jnz 1b + ret + .p2align 4,,15 +2: movq -24(%rax,%rdx,8),%rsi + movq %rsi,-24(%rcx,%rdx,8) + movq -16(%rax,%rdx,8),%rsi + movq %rsi,-16(%rcx,%rdx,8) + movq -8(%rax,%rdx,8),%rsi + movq %rsi,-8(%rcx,%rdx,8) + movq (%rax,%rdx,8),%rsi + movq %rsi,(%rcx,%rdx,8) +3: addq $4,%rdx + jle 2b + subq $4,%rdx + jl 1b + ret +4: movq -8(%rdi,%rdx,8),%rcx + movq %rcx,-8(%rsi,%rdx,8) + subq $1,%rdx + jnz 4b + ret + .p2align 4,,15 +5: movq 24(%rdi,%rdx,8),%rcx + movq %rcx,24(%rsi,%rdx,8) + movq 16(%rdi,%rdx,8),%rcx + movq %rcx,16(%rsi,%rdx,8) + movq 8(%rdi,%rdx,8),%rcx + movq %rcx,8(%rsi,%rdx,8) + movq (%rdi,%rdx,8),%rcx + movq %rcx,(%rsi,%rdx,8) +acl_CopyLeft: + subq $4,%rdx + jge 5b + addq $4,%rdx + jg 4b + ret
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/bytes_bsd_x86.inline.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_BSD_X86_VM_BYTES_BSD_X86_INLINE_HPP +#define OS_CPU_BSD_X86_VM_BYTES_BSD_X86_INLINE_HPP + +#ifndef _ALLBSD_SOURCE +#include <byteswap.h> +#endif + +#ifdef __APPLE__ +#include <libkern/OSByteOrder.h> +#endif + +#if defined(AMD64) +# if defined(__APPLE__) +# define bswap_16(x) OSSwapInt16(x) +# define bswap_32(x) OSSwapInt32(x) +# define bswap_64(x) OSSwapInt64(x) +# elif defined(__OpenBSD__) +# define bswap_16(x) swap16(x) +# define bswap_32(x) swap32(x) +# define bswap_64(x) swap64(x) +# elif defined(__NetBSD__) +# define bswap_16(x) bswap16(x) +# define bswap_32(x) bswap32(x) +# define bswap_64(x) bswap64(x) +# else +# define bswap_16(x) __bswap16(x) +# define bswap_32(x) __bswap32(x) +# define bswap_64(x) __bswap64(x) +# endif +#endif + +// Efficient swapping of data bytes from Java byte +// ordering to native byte ordering and vice versa. +inline u2 Bytes::swap_u2(u2 x) { +#ifdef AMD64 + return bswap_16(x); +#else + u2 ret; + __asm__ __volatile__ ( + "movw %0, %%ax;" + "xchg %%al, %%ah;" + "movw %%ax, %0" + :"=r" (ret) // output : register 0 => ret + :"0" (x) // input : x => register 0 + :"ax", "0" // clobbered registers + ); + return ret; +#endif // AMD64 +} + +inline u4 Bytes::swap_u4(u4 x) { +#ifdef AMD64 + return bswap_32(x); +#else + u4 ret; + __asm__ __volatile__ ( + "bswap %0" + :"=r" (ret) // output : register 0 => ret + :"0" (x) // input : x => register 0 + :"0" // clobbered register + ); + return ret; +#endif // AMD64 +} + +#ifdef AMD64 +inline u8 Bytes::swap_u8(u8 x) { +#ifdef SPARC_WORKS + // workaround for SunStudio12 CR6615391 + __asm__ __volatile__ ( + "bswapq %0" + :"=r" (x) // output : register 0 => x + :"0" (x) // input : x => register 0 + :"0" // clobbered register + ); + return x; +#else + return bswap_64(x); +#endif +} +#else +// Helper function for swap_u8 +inline u8 Bytes::swap_u8_base(u4 x, u4 y) { + return (((u8)swap_u4(x))<<32) | swap_u4(y); +} + +inline u8 Bytes::swap_u8(u8 x) { + return swap_u8_base(*(u4*)&x, *(((u4*)&x)+1)); +} +#endif // !AMD64 + +#endif // OS_CPU_BSD_X86_VM_BYTES_BSD_X86_INLINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/copy_bsd_x86.inline.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_BSD_X86_VM_COPY_BSD_X86_INLINE_HPP +#define OS_CPU_BSD_X86_VM_COPY_BSD_X86_INLINE_HPP + +static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) { +#ifdef AMD64 + (void)memmove(to, from, count * HeapWordSize); +#else + // Includes a zero-count check. + intx temp; + __asm__ volatile(" testl %6,%6 ;" + " jz 7f ;" + " cmpl %4,%5 ;" + " leal -4(%4,%6,4),%3;" + " jbe 1f ;" + " cmpl %7,%5 ;" + " jbe 4f ;" + "1: cmpl $32,%6 ;" + " ja 3f ;" + " subl %4,%1 ;" + "2: movl (%4),%3 ;" + " movl %7,(%5,%4,1) ;" + " addl $4,%0 ;" + " subl $1,%2 ;" + " jnz 2b ;" + " jmp 7f ;" + "3: rep; smovl ;" + " jmp 7f ;" + "4: cmpl $32,%2 ;" + " movl %7,%0 ;" + " leal -4(%5,%6,4),%1;" + " ja 6f ;" + " subl %4,%1 ;" + "5: movl (%4),%3 ;" + " movl %7,(%5,%4,1) ;" + " subl $4,%0 ;" + " subl $1,%2 ;" + " jnz 5b ;" + " jmp 7f ;" + "6: std ;" + " rep; smovl ;" + " cld ;" + "7: nop " + : "=S" (from), "=D" (to), "=c" (count), "=r" (temp) + : "0" (from), "1" (to), "2" (count), "3" (temp) + : "memory", "flags"); +#endif // AMD64 +} + +static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) { +#ifdef AMD64 + switch (count) { + case 8: to[7] = from[7]; + case 7: to[6] = from[6]; + case 6: to[5] = from[5]; + case 5: to[4] = from[4]; + case 4: to[3] = from[3]; + case 3: to[2] = from[2]; + case 2: to[1] = from[1]; + case 1: to[0] = from[0]; + case 0: break; + default: + (void)memcpy(to, from, count * HeapWordSize); + break; + } +#else + // Includes a zero-count check. + intx temp; + __asm__ volatile(" testl %6,%6 ;" + " jz 3f ;" + " cmpl $32,%6 ;" + " ja 2f ;" + " subl %4,%1 ;" + "1: movl (%4),%3 ;" + " movl %7,(%5,%4,1);" + " addl $4,%0 ;" + " subl $1,%2 ;" + " jnz 1b ;" + " jmp 3f ;" + "2: rep; smovl ;" + "3: nop " + : "=S" (from), "=D" (to), "=c" (count), "=r" (temp) + : "0" (from), "1" (to), "2" (count), "3" (temp) + : "memory", "cc"); +#endif // AMD64 +} + +static void pd_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count) { +#ifdef AMD64 + switch (count) { + case 8: to[7] = from[7]; + case 7: to[6] = from[6]; + case 6: to[5] = from[5]; + case 5: to[4] = from[4]; + case 4: to[3] = from[3]; + case 3: to[2] = from[2]; + case 2: to[1] = from[1]; + case 1: to[0] = from[0]; + case 0: break; + default: + while (count-- > 0) { + *to++ = *from++; + } + break; + } +#else + // pd_disjoint_words is word-atomic in this implementation. + pd_disjoint_words(from, to, count); +#endif // AMD64 +} + +static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) { + pd_conjoint_words(from, to, count); +} + +static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) { + pd_disjoint_words(from, to, count); +} + +static void pd_conjoint_bytes(void* from, void* to, size_t count) { +#ifdef AMD64 + (void)memmove(to, from, count); +#else + // Includes a zero-count check. + intx temp; + __asm__ volatile(" testl %6,%6 ;" + " jz 13f ;" + " cmpl %4,%5 ;" + " leal -1(%4,%6),%3 ;" + " jbe 1f ;" + " cmpl %7,%5 ;" + " jbe 8f ;" + "1: cmpl $3,%6 ;" + " jbe 6f ;" + " movl %6,%3 ;" + " movl $4,%2 ;" + " subl %4,%2 ;" + " andl $3,%2 ;" + " jz 2f ;" + " subl %6,%3 ;" + " rep; smovb ;" + "2: movl %7,%2 ;" + " shrl $2,%2 ;" + " jz 5f ;" + " cmpl $32,%2 ;" + " ja 4f ;" + " subl %4,%1 ;" + "3: movl (%4),%%edx ;" + " movl %%edx,(%5,%4,1);" + " addl $4,%0 ;" + " subl $1,%2 ;" + " jnz 3b ;" + " addl %4,%1 ;" + " jmp 5f ;" + "4: rep; smovl ;" + "5: movl %7,%2 ;" + " andl $3,%2 ;" + " jz 13f ;" + "6: xorl %7,%3 ;" + "7: movb (%4,%7,1),%%dl ;" + " movb %%dl,(%5,%7,1) ;" + " addl $1,%3 ;" + " subl $1,%2 ;" + " jnz 7b ;" + " jmp 13f ;" + "8: std ;" + " cmpl $12,%2 ;" + " ja 9f ;" + " movl %7,%0 ;" + " leal -1(%6,%5),%1 ;" + " jmp 11f ;" + "9: xchgl %3,%2 ;" + " movl %6,%0 ;" + " addl $1,%2 ;" + " leal -1(%7,%5),%1 ;" + " andl $3,%2 ;" + " jz 10f ;" + " subl %6,%3 ;" + " rep; smovb ;" + "10: movl %7,%2 ;" + " subl $3,%0 ;" + " shrl $2,%2 ;" + " subl $3,%1 ;" + " rep; smovl ;" + " andl $3,%3 ;" + " jz 12f ;" + " movl %7,%2 ;" + " addl $3,%0 ;" + " addl $3,%1 ;" + "11: rep; smovb ;" + "12: cld ;" + "13: nop ;" + : "=S" (from), "=D" (to), "=c" (count), "=r" (temp) + : "0" (from), "1" (to), "2" (count), "3" (temp) + : "memory", "flags", "%edx"); +#endif // AMD64 +} + +static void pd_conjoint_bytes_atomic(void* from, void* to, size_t count) { + pd_conjoint_bytes(from, to, count); +} + +static void pd_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) { + _Copy_conjoint_jshorts_atomic(from, to, count); +} + +static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) { +#ifdef AMD64 + _Copy_conjoint_jints_atomic(from, to, count); +#else + assert(HeapWordSize == BytesPerInt, "heapwords and jints must be the same size"); + // pd_conjoint_words is word-atomic in this implementation. + pd_conjoint_words((HeapWord*)from, (HeapWord*)to, count); +#endif // AMD64 +} + +static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) { +#ifdef AMD64 + _Copy_conjoint_jlongs_atomic(from, to, count); +#else + // Guarantee use of fild/fistp or xmm regs via some asm code, because compilers won't. + if (from > to) { + while (count-- > 0) { + __asm__ volatile("fildll (%0); fistpll (%1)" + : + : "r" (from), "r" (to) + : "memory" ); + ++from; + ++to; + } + } else { + while (count-- > 0) { + __asm__ volatile("fildll (%0,%2,8); fistpll (%1,%2,8)" + : + : "r" (from), "r" (to), "r" (count) + : "memory" ); + } + } +#endif // AMD64 +} + +static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) { +#ifdef AMD64 + assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); + _Copy_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count); +#else + assert(HeapWordSize == BytesPerOop, "heapwords and oops must be the same size"); + // pd_conjoint_words is word-atomic in this implementation. + pd_conjoint_words((HeapWord*)from, (HeapWord*)to, count); +#endif // AMD64 +} + +static void pd_arrayof_conjoint_bytes(HeapWord* from, HeapWord* to, size_t count) { + _Copy_arrayof_conjoint_bytes(from, to, count); +} + +static void pd_arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count) { + _Copy_arrayof_conjoint_jshorts(from, to, count); +} + +static void pd_arrayof_conjoint_jints(HeapWord* from, HeapWord* to, size_t count) { +#ifdef AMD64 + _Copy_arrayof_conjoint_jints(from, to, count); +#else + pd_conjoint_jints_atomic((jint*)from, (jint*)to, count); +#endif // AMD64 +} + +static void pd_arrayof_conjoint_jlongs(HeapWord* from, HeapWord* to, size_t count) { +#ifdef AMD64 + _Copy_arrayof_conjoint_jlongs(from, to, count); +#else + pd_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count); +#endif // AMD64 +} + +static void pd_arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) { +#ifdef AMD64 + assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); + _Copy_arrayof_conjoint_jlongs(from, to, count); +#else + pd_conjoint_oops_atomic((oop*)from, (oop*)to, count); +#endif // AMD64 +} + +#endif // OS_CPU_BSD_X86_VM_COPY_BSD_X86_INLINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_BSD_X86_VM_GLOBALS_BSD_X86_HPP +#define OS_CPU_BSD_X86_VM_GLOBALS_BSD_X86_HPP + +// +// Sets the default values for platform dependent flags used by the runtime system. +// (see globals.hpp) +// +define_pd_global(bool, DontYieldALot, false); +#ifdef AMD64 +define_pd_global(intx, ThreadStackSize, 1024); // 0 => use system default +define_pd_global(intx, VMThreadStackSize, 1024); +#else +// ThreadStackSize 320 allows a couple of test cases to run while +// keeping the number of threads that can be created high. System +// default ThreadStackSize appears to be 512 which is too big. +define_pd_global(intx, ThreadStackSize, 320); +define_pd_global(intx, VMThreadStackSize, 512); +#endif // AMD64 + +define_pd_global(intx, CompilerThreadStackSize, 0); +define_pd_global(intx, SurvivorRatio, 8); + +define_pd_global(uintx, JVMInvokeMethodSlack, 8192); + +// Only used on 64 bit platforms +define_pd_global(uintx, HeapBaseMinAddress, 2*G); +// Only used on 64 bit Windows platforms +define_pd_global(bool, UseVectoredExceptions, false); + +#endif // OS_CPU_BSD_X86_VM_GLOBALS_BSD_X86_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2003, 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. + * + */ + +#ifndef OS_CPU_BSD_X86_VM_ORDERACCESS_BSD_X86_INLINE_HPP +#define OS_CPU_BSD_X86_VM_ORDERACCESS_BSD_X86_INLINE_HPP + +#include "runtime/atomic.hpp" +#include "runtime/orderAccess.hpp" +#include "vm_version_x86.hpp" + +// Implementation of class OrderAccess. + +inline void OrderAccess::loadload() { acquire(); } +inline void OrderAccess::storestore() { release(); } +inline void OrderAccess::loadstore() { acquire(); } +inline void OrderAccess::storeload() { fence(); } + +inline void OrderAccess::acquire() { + volatile intptr_t local_dummy; +#ifdef AMD64 + __asm__ volatile ("movq 0(%%rsp), %0" : "=r" (local_dummy) : : "memory"); +#else + __asm__ volatile ("movl 0(%%esp),%0" : "=r" (local_dummy) : : "memory"); +#endif // AMD64 +} + +inline void OrderAccess::release() { + // Avoid hitting the same cache-line from + // different threads. + volatile jint local_dummy = 0; +} + +inline void OrderAccess::fence() { + if (os::is_MP()) { + // always use locked addl since mfence is sometimes expensive +#ifdef AMD64 + __asm__ volatile ("lock; addl $0,0(%%rsp)" : : : "cc", "memory"); +#else + __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory"); +#endif + } +} + +inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; } +inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; } +inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; } +inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); } +inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; } +inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; } +inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; } +inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); } +inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; } +inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; } + +inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; } +inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; } +inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *(void* const volatile *)p; } + +inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; } +inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; } +inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; } +inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); } +inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; } +inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; } +inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; } +inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); } +inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; } +inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; } + +inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; } +inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; } + +inline void OrderAccess::store_fence(jbyte* p, jbyte v) { + __asm__ volatile ( "xchgb (%2),%0" + : "=q" (v) + : "0" (v), "r" (p) + : "memory"); +} +inline void OrderAccess::store_fence(jshort* p, jshort v) { + __asm__ volatile ( "xchgw (%2),%0" + : "=r" (v) + : "0" (v), "r" (p) + : "memory"); +} +inline void OrderAccess::store_fence(jint* p, jint v) { + __asm__ volatile ( "xchgl (%2),%0" + : "=r" (v) + : "0" (v), "r" (p) + : "memory"); +} + +inline void OrderAccess::store_fence(jlong* p, jlong v) { +#ifdef AMD64 + __asm__ __volatile__ ("xchgq (%2), %0" + : "=r" (v) + : "0" (v), "r" (p) + : "memory"); +#else + *p = v; fence(); +#endif // AMD64 +} + +// AMD64 copied the bodies for the the signed version. 32bit did this. As long as the +// compiler does the inlining this is simpler. +inline void OrderAccess::store_fence(jubyte* p, jubyte v) { store_fence((jbyte*)p, (jbyte)v); } +inline void OrderAccess::store_fence(jushort* p, jushort v) { store_fence((jshort*)p, (jshort)v); } +inline void OrderAccess::store_fence(juint* p, juint v) { store_fence((jint*)p, (jint)v); } +inline void OrderAccess::store_fence(julong* p, julong v) { store_fence((jlong*)p, (jlong)v); } +inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } +inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; fence(); } + +inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { +#ifdef AMD64 + __asm__ __volatile__ ("xchgq (%2), %0" + : "=r" (v) + : "0" (v), "r" (p) + : "memory"); +#else + store_fence((jint*)p, (jint)v); +#endif // AMD64 +} + +inline void OrderAccess::store_ptr_fence(void** p, void* v) { +#ifdef AMD64 + __asm__ __volatile__ ("xchgq (%2), %0" + : "=r" (v) + : "0" (v), "r" (p) + : "memory"); +#else + store_fence((jint*)p, (jint)v); +#endif // AMD64 +} + +// Must duplicate definitions instead of calling store_fence because we don't want to cast away volatile. +inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { + __asm__ volatile ( "xchgb (%2),%0" + : "=q" (v) + : "0" (v), "r" (p) + : "memory"); +} +inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { + __asm__ volatile ( "xchgw (%2),%0" + : "=r" (v) + : "0" (v), "r" (p) + : "memory"); +} +inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { + __asm__ volatile ( "xchgl (%2),%0" + : "=r" (v) + : "0" (v), "r" (p) + : "memory"); +} + +inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { +#ifdef AMD64 + __asm__ __volatile__ ( "xchgq (%2), %0" + : "=r" (v) + : "0" (v), "r" (p) + : "memory"); +#else + release_store(p, v); fence(); +#endif // AMD64 +} + +inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store_fence((volatile jbyte*)p, (jbyte)v); } +inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store_fence((volatile jshort*)p, (jshort)v); } +inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { release_store_fence((volatile jint*)p, (jint)v); } +inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store_fence((volatile jlong*)p, (jlong)v); } + +inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); } +inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); } + +inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { +#ifdef AMD64 + __asm__ __volatile__ ( "xchgq (%2), %0" + : "=r" (v) + : "0" (v), "r" (p) + : "memory"); +#else + release_store_fence((volatile jint*)p, (jint)v); +#endif // AMD64 +} +inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { +#ifdef AMD64 + __asm__ __volatile__ ( "xchgq (%2), %0" + : "=r" (v) + : "0" (v), "r" (p) + : "memory"); +#else + release_store_fence((volatile jint*)p, (jint)v); +#endif // AMD64 +} + +#endif // OS_CPU_BSD_X86_VM_ORDERACCESS_BSD_X86_INLINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,1128 @@ +/* + * Copyright (c) 1999, 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. + * + */ + +// no precompiled headers +#include "assembler_x86.inline.hpp" +#include "classfile/classLoader.hpp" +#include "classfile/systemDictionary.hpp" +#include "classfile/vmSymbols.hpp" +#include "code/icBuffer.hpp" +#include "code/vtableStubs.hpp" +#include "interpreter/interpreter.hpp" +#include "jvm_bsd.h" +#include "memory/allocation.inline.hpp" +#include "mutex_bsd.inline.hpp" +#include "nativeInst_x86.hpp" +#include "os_share_bsd.hpp" +#include "prims/jniFastGetField.hpp" +#include "prims/jvm.h" +#include "prims/jvm_misc.hpp" +#include "runtime/arguments.hpp" +#include "runtime/extendedPC.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/interfaceSupport.hpp" +#include "runtime/java.hpp" +#include "runtime/javaCalls.hpp" +#include "runtime/mutexLocker.hpp" +#include "runtime/osThread.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/timer.hpp" +#include "thread_bsd.inline.hpp" +#include "utilities/events.hpp" +#include "utilities/vmError.hpp" +#ifdef COMPILER1 +#include "c1/c1_Runtime1.hpp" +#endif +#ifdef COMPILER2 +#include "opto/runtime.hpp" +#endif + +// put OS-includes here +# include <sys/types.h> +# include <sys/mman.h> +# include <pthread.h> +# include <signal.h> +# include <errno.h> +# include <dlfcn.h> +# include <stdlib.h> +# include <stdio.h> +# include <unistd.h> +# include <sys/resource.h> +# include <pthread.h> +# include <sys/stat.h> +# include <sys/time.h> +# include <sys/utsname.h> +# include <sys/socket.h> +# include <sys/wait.h> +# include <pwd.h> +# include <poll.h> +#ifndef __OpenBSD__ +# include <ucontext.h> +#endif + +#if defined(_ALLBSD_SOURCE) && !defined(__APPLE__) && !defined(__NetBSD__) +# include <pthread_np.h> +#endif + +#ifdef AMD64 +#define SPELL_REG_SP "rsp" +#define SPELL_REG_FP "rbp" +#else +#define SPELL_REG_SP "esp" +#define SPELL_REG_FP "ebp" +#endif // AMD64 + +#ifdef __FreeBSD__ +# define context_trapno uc_mcontext.mc_trapno +# ifdef AMD64 +# define context_pc uc_mcontext.mc_rip +# define context_sp uc_mcontext.mc_rsp +# define context_fp uc_mcontext.mc_rbp +# define context_rip uc_mcontext.mc_rip +# define context_rsp uc_mcontext.mc_rsp +# define context_rbp uc_mcontext.mc_rbp +# define context_rax uc_mcontext.mc_rax +# define context_rbx uc_mcontext.mc_rbx +# define context_rcx uc_mcontext.mc_rcx +# define context_rdx uc_mcontext.mc_rdx +# define context_rsi uc_mcontext.mc_rsi +# define context_rdi uc_mcontext.mc_rdi +# define context_r8 uc_mcontext.mc_r8 +# define context_r9 uc_mcontext.mc_r9 +# define context_r10 uc_mcontext.mc_r10 +# define context_r11 uc_mcontext.mc_r11 +# define context_r12 uc_mcontext.mc_r12 +# define context_r13 uc_mcontext.mc_r13 +# define context_r14 uc_mcontext.mc_r14 +# define context_r15 uc_mcontext.mc_r15 +# define context_flags uc_mcontext.mc_flags +# define context_err uc_mcontext.mc_err +# else +# define context_pc uc_mcontext.mc_eip +# define context_sp uc_mcontext.mc_esp +# define context_fp uc_mcontext.mc_ebp +# define context_eip uc_mcontext.mc_eip +# define context_esp uc_mcontext.mc_esp +# define context_eax uc_mcontext.mc_eax +# define context_ebx uc_mcontext.mc_ebx +# define context_ecx uc_mcontext.mc_ecx +# define context_edx uc_mcontext.mc_edx +# define context_ebp uc_mcontext.mc_ebp +# define context_esi uc_mcontext.mc_esi +# define context_edi uc_mcontext.mc_edi +# define context_eflags uc_mcontext.mc_eflags +# define context_trapno uc_mcontext.mc_trapno +# endif +#endif + +#ifdef __APPLE__ +# if __DARWIN_UNIX03 && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) + // 10.5 UNIX03 member name prefixes + #define DU3_PREFIX(s, m) __ ## s.__ ## m +# else + #define DU3_PREFIX(s, m) s ## . ## m +# endif + +# ifdef AMD64 +# define context_pc context_rip +# define context_sp context_rsp +# define context_fp context_rbp +# define context_rip uc_mcontext->DU3_PREFIX(ss,rip) +# define context_rsp uc_mcontext->DU3_PREFIX(ss,rsp) +# define context_rax uc_mcontext->DU3_PREFIX(ss,rax) +# define context_rbx uc_mcontext->DU3_PREFIX(ss,rbx) +# define context_rcx uc_mcontext->DU3_PREFIX(ss,rcx) +# define context_rdx uc_mcontext->DU3_PREFIX(ss,rdx) +# define context_rbp uc_mcontext->DU3_PREFIX(ss,rbp) +# define context_rsi uc_mcontext->DU3_PREFIX(ss,rsi) +# define context_rdi uc_mcontext->DU3_PREFIX(ss,rdi) +# define context_r8 uc_mcontext->DU3_PREFIX(ss,r8) +# define context_r9 uc_mcontext->DU3_PREFIX(ss,r9) +# define context_r10 uc_mcontext->DU3_PREFIX(ss,r10) +# define context_r11 uc_mcontext->DU3_PREFIX(ss,r11) +# define context_r12 uc_mcontext->DU3_PREFIX(ss,r12) +# define context_r13 uc_mcontext->DU3_PREFIX(ss,r13) +# define context_r14 uc_mcontext->DU3_PREFIX(ss,r14) +# define context_r15 uc_mcontext->DU3_PREFIX(ss,r15) +# define context_flags uc_mcontext->DU3_PREFIX(ss,rflags) +# define context_trapno uc_mcontext->DU3_PREFIX(es,trapno) +# define context_err uc_mcontext->DU3_PREFIX(es,err) +# else +# define context_pc context_eip +# define context_sp context_esp +# define context_fp context_ebp +# define context_eip uc_mcontext->DU3_PREFIX(ss,eip) +# define context_esp uc_mcontext->DU3_PREFIX(ss,esp) +# define context_eax uc_mcontext->DU3_PREFIX(ss,eax) +# define context_ebx uc_mcontext->DU3_PREFIX(ss,ebx) +# define context_ecx uc_mcontext->DU3_PREFIX(ss,ecx) +# define context_edx uc_mcontext->DU3_PREFIX(ss,edx) +# define context_ebp uc_mcontext->DU3_PREFIX(ss,ebp) +# define context_esi uc_mcontext->DU3_PREFIX(ss,esi) +# define context_edi uc_mcontext->DU3_PREFIX(ss,edi) +# define context_eflags uc_mcontext->DU3_PREFIX(ss,eflags) +# define context_trapno uc_mcontext->DU3_PREFIX(es,trapno) +# endif +#endif + +#ifdef __OpenBSD__ +# define context_trapno sc_trapno +# ifdef AMD64 +# define context_pc sc_rip +# define context_sp sc_rsp +# define context_fp sc_rbp +# define context_rip sc_rip +# define context_rsp sc_rsp +# define context_rbp sc_rbp +# define context_rax sc_rax +# define context_rbx sc_rbx +# define context_rcx sc_rcx +# define context_rdx sc_rdx +# define context_rsi sc_rsi +# define context_rdi sc_rdi +# define context_r8 sc_r8 +# define context_r9 sc_r9 +# define context_r10 sc_r10 +# define context_r11 sc_r11 +# define context_r12 sc_r12 +# define context_r13 sc_r13 +# define context_r14 sc_r14 +# define context_r15 sc_r15 +# define context_flags sc_rflags +# define context_err sc_err +# else +# define context_pc sc_eip +# define context_sp sc_esp +# define context_fp sc_ebp +# define context_eip sc_eip +# define context_esp sc_esp +# define context_eax sc_eax +# define context_ebx sc_ebx +# define context_ecx sc_ecx +# define context_edx sc_edx +# define context_ebp sc_ebp +# define context_esi sc_esi +# define context_edi sc_edi +# define context_eflags sc_eflags +# define context_trapno sc_trapno +# endif +#endif + +#ifdef __NetBSD__ +# define context_trapno uc_mcontext.__gregs[_REG_TRAPNO] +# ifdef AMD64 +# define __register_t __greg_t +# define context_pc uc_mcontext.__gregs[_REG_RIP] +# define context_sp uc_mcontext.__gregs[_REG_URSP] +# define context_fp uc_mcontext.__gregs[_REG_RBP] +# define context_rip uc_mcontext.__gregs[_REG_RIP] +# define context_rsp uc_mcontext.__gregs[_REG_URSP] +# define context_rax uc_mcontext.__gregs[_REG_RAX] +# define context_rbx uc_mcontext.__gregs[_REG_RBX] +# define context_rcx uc_mcontext.__gregs[_REG_RCX] +# define context_rdx uc_mcontext.__gregs[_REG_RDX] +# define context_rbp uc_mcontext.__gregs[_REG_RBP] +# define context_rsi uc_mcontext.__gregs[_REG_RSI] +# define context_rdi uc_mcontext.__gregs[_REG_RDI] +# define context_r8 uc_mcontext.__gregs[_REG_R8] +# define context_r9 uc_mcontext.__gregs[_REG_R9] +# define context_r10 uc_mcontext.__gregs[_REG_R10] +# define context_r11 uc_mcontext.__gregs[_REG_R11] +# define context_r12 uc_mcontext.__gregs[_REG_R12] +# define context_r13 uc_mcontext.__gregs[_REG_R13] +# define context_r14 uc_mcontext.__gregs[_REG_R14] +# define context_r15 uc_mcontext.__gregs[_REG_R15] +# define context_flags uc_mcontext.__gregs[_REG_RFL] +# define context_err uc_mcontext.__gregs[_REG_ERR] +# else +# define context_pc uc_mcontext.__gregs[_REG_EIP] +# define context_sp uc_mcontext.__gregs[_REG_UESP] +# define context_fp uc_mcontext.__gregs[_REG_EBP] +# define context_eip uc_mcontext.__gregs[_REG_EIP] +# define context_esp uc_mcontext.__gregs[_REG_UESP] +# define context_eax uc_mcontext.__gregs[_REG_EAX] +# define context_ebx uc_mcontext.__gregs[_REG_EBX] +# define context_ecx uc_mcontext.__gregs[_REG_ECX] +# define context_edx uc_mcontext.__gregs[_REG_EDX] +# define context_ebp uc_mcontext.__gregs[_REG_EBP] +# define context_esi uc_mcontext.__gregs[_REG_ESI] +# define context_edi uc_mcontext.__gregs[_REG_EDI] +# define context_eflags uc_mcontext.__gregs[_REG_EFL] +# define context_trapno uc_mcontext.__gregs[_REG_TRAPNO] +# endif +#endif + +address os::current_stack_pointer() { +#if defined(__clang__) || defined(__llvm__) + register void *esp; + __asm__("mov %%"SPELL_REG_SP", %0":"=r"(esp)); + return (address) esp; +#elif defined(SPARC_WORKS) + register void *esp; + __asm__("mov %%"SPELL_REG_SP", %0":"=r"(esp)); + return (address) ((char*)esp + sizeof(long)*2); +#else + register void *esp __asm__ (SPELL_REG_SP); + return (address) esp; +#endif +} + +char* os::non_memory_address_word() { + // Must never look like an address returned by reserve_memory, + // even in its subfields (as defined by the CPU immediate fields, + // if the CPU splits constants across multiple instructions). + + return (char*) -1; +} + +void os::initialize_thread() { +// Nothing to do. +} + +address os::Bsd::ucontext_get_pc(ucontext_t * uc) { + return (address)uc->context_pc; +} + +intptr_t* os::Bsd::ucontext_get_sp(ucontext_t * uc) { + return (intptr_t*)uc->context_sp; +} + +intptr_t* os::Bsd::ucontext_get_fp(ucontext_t * uc) { + return (intptr_t*)uc->context_fp; +} + +// For Forte Analyzer AsyncGetCallTrace profiling support - thread +// is currently interrupted by SIGPROF. +// os::Solaris::fetch_frame_from_ucontext() tries to skip nested signal +// frames. Currently we don't do that on Bsd, so it's the same as +// os::fetch_frame_from_context(). +ExtendedPC os::Bsd::fetch_frame_from_ucontext(Thread* thread, + ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) { + + assert(thread != NULL, "just checking"); + assert(ret_sp != NULL, "just checking"); + assert(ret_fp != NULL, "just checking"); + + return os::fetch_frame_from_context(uc, ret_sp, ret_fp); +} + +ExtendedPC os::fetch_frame_from_context(void* ucVoid, + intptr_t** ret_sp, intptr_t** ret_fp) { + + ExtendedPC epc; + ucontext_t* uc = (ucontext_t*)ucVoid; + + if (uc != NULL) { + epc = ExtendedPC(os::Bsd::ucontext_get_pc(uc)); + if (ret_sp) *ret_sp = os::Bsd::ucontext_get_sp(uc); + if (ret_fp) *ret_fp = os::Bsd::ucontext_get_fp(uc); + } else { + // construct empty ExtendedPC for return value checking + epc = ExtendedPC(NULL); + if (ret_sp) *ret_sp = (intptr_t *)NULL; + if (ret_fp) *ret_fp = (intptr_t *)NULL; + } + + return epc; +} + +frame os::fetch_frame_from_context(void* ucVoid) { + intptr_t* sp; + intptr_t* fp; + ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); + return frame(sp, fp, epc.pc()); +} + +// By default, gcc always save frame pointer (%ebp/%rbp) on stack. It may get +// turned off by -fomit-frame-pointer, +frame os::get_sender_for_C_frame(frame* fr) { + return frame(fr->sender_sp(), fr->link(), fr->sender_pc()); +} + +intptr_t* _get_previous_fp() { +#if defined(SPARC_WORKS) || defined(__clang__) + register intptr_t **ebp; + __asm__("mov %%"SPELL_REG_FP", %0":"=r"(ebp)); +#else + register intptr_t **ebp __asm__ (SPELL_REG_FP); +#endif + return (intptr_t*) *ebp; // we want what it points to. +} + + +frame os::current_frame() { + intptr_t* fp = _get_previous_fp(); + frame myframe((intptr_t*)os::current_stack_pointer(), + (intptr_t*)fp, + CAST_FROM_FN_PTR(address, os::current_frame)); + if (os::is_first_C_frame(&myframe)) { + // stack is not walkable + return frame(NULL, NULL, NULL); + } else { + return os::get_sender_for_C_frame(&myframe); + } +} + +// Utility functions + +// From IA32 System Programming Guide +enum { + trap_page_fault = 0xE +}; + +extern "C" void Fetch32PFI () ; +extern "C" void Fetch32Resume () ; +#ifdef AMD64 +extern "C" void FetchNPFI () ; +extern "C" void FetchNResume () ; +#endif // AMD64 + +extern "C" JNIEXPORT int +JVM_handle_bsd_signal(int sig, + siginfo_t* info, + void* ucVoid, + int abort_if_unrecognized) { + ucontext_t* uc = (ucontext_t*) ucVoid; + + Thread* t = ThreadLocalStorage::get_thread_slow(); + + SignalHandlerMark shm(t); + + // Note: it's not uncommon that JNI code uses signal/sigset to install + // then restore certain signal handler (e.g. to temporarily block SIGPIPE, + // or have a SIGILL handler when detecting CPU type). When that happens, + // JVM_handle_bsd_signal() might be invoked with junk info/ucVoid. To + // avoid unnecessary crash when libjsig is not preloaded, try handle signals + // that do not require siginfo/ucontext first. + + if (sig == SIGPIPE || sig == SIGXFSZ) { + // allow chained handler to go first + if (os::Bsd::chained_handler(sig, info, ucVoid)) { + return true; + } else { + if (PrintMiscellaneous && (WizardMode || Verbose)) { + char buf[64]; + warning("Ignoring %s - see bugs 4229104 or 646499219", + os::exception_name(sig, buf, sizeof(buf))); + } + return true; + } + } + + JavaThread* thread = NULL; + VMThread* vmthread = NULL; + if (os::Bsd::signal_handlers_are_installed) { + if (t != NULL ){ + if(t->is_Java_thread()) { + thread = (JavaThread*)t; + } + else if(t->is_VM_thread()){ + vmthread = (VMThread *)t; + } + } + } +/* + NOTE: does not seem to work on bsd. + if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) { + // can't decode this kind of signal + info = NULL; + } else { + assert(sig == info->si_signo, "bad siginfo"); + } +*/ + // decide if this trap can be handled by a stub + address stub = NULL; + + address pc = NULL; + + //%note os_trap_1 + if (info != NULL && uc != NULL && thread != NULL) { + pc = (address) os::Bsd::ucontext_get_pc(uc); + + if (pc == (address) Fetch32PFI) { + uc->context_pc = intptr_t(Fetch32Resume) ; + return 1 ; + } +#ifdef AMD64 + if (pc == (address) FetchNPFI) { + uc->context_pc = intptr_t (FetchNResume) ; + return 1 ; + } +#endif // AMD64 + + // Handle ALL stack overflow variations here + if (sig == SIGSEGV || sig == SIGBUS) { + address addr = (address) info->si_addr; + + // check if fault address is within thread stack + if (addr < thread->stack_base() && + addr >= thread->stack_base() - thread->stack_size()) { + // stack overflow + if (thread->in_stack_yellow_zone(addr)) { + thread->disable_stack_yellow_zone(); + if (thread->thread_state() == _thread_in_Java) { + // Throw a stack overflow exception. Guard pages will be reenabled + // while unwinding the stack. + 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. + return 1; + } + } else if (thread->in_stack_red_zone(addr)) { + // Fatal red zone violation. Disable the guard pages and fall through + // to handle_unexpected_exception way down below. + thread->disable_stack_red_zone(); + tty->print_raw_cr("An irrecoverable stack overflow has occurred."); +#ifndef _ALLBSD_SOURCE + } else { + // Accessing stack address below sp may cause SEGV if current + // thread has MAP_GROWSDOWN stack. This should only happen when + // current thread was created by user code with MAP_GROWSDOWN flag + // and then attached to VM. See notes in os_bsd.cpp. + if (thread->osthread()->expanding_stack() == 0) { + thread->osthread()->set_expanding_stack(); + if (os::Bsd::manually_expand_stack(thread, addr)) { + thread->osthread()->clear_expanding_stack(); + return 1; + } + thread->osthread()->clear_expanding_stack(); + } else { + fatal("recursive segv. expanding stack."); + } +#endif + } + } + } + + if (thread->thread_state() == _thread_in_Java) { + // Java thread running in Java code => find exception handler if any + // a fault inside compiled code, the interpreter, or a stub + + if ((sig == SIGSEGV || sig == SIGBUS) && os::is_poll_address((address)info->si_addr)) { + stub = SharedRuntime::get_poll_stub(pc); +#if defined(__APPLE__) && !defined(AMD64) + // 32-bit Darwin reports a SIGBUS for nearly all memory access exceptions. + // Catching SIGBUS here prevents the implicit SIGBUS NULL check below from + // being called, so only do so if the implicit NULL check is not necessary. + } else if (sig == SIGBUS && MacroAssembler::needs_explicit_null_check((int)info->si_addr)) { +#else + } else if (sig == SIGBUS /* && info->si_code == BUS_OBJERR */) { +#endif + // BugId 4454115: A read from a MappedByteBuffer can fault + // here if the underlying file has been truncated. + // Do not crash the VM in such a case. + CodeBlob* cb = CodeCache::find_blob_unsafe(pc); + nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL; + if (nm != NULL && nm->has_unsafe_access()) { + stub = StubRoutines::handler_for_unsafe_access(); + } + } + else + +#ifdef AMD64 + if (sig == SIGFPE && + (info->si_code == FPE_INTDIV || info->si_code == FPE_FLTDIV)) { + stub = + SharedRuntime:: + continuation_for_implicit_exception(thread, + pc, + SharedRuntime:: + IMPLICIT_DIVIDE_BY_ZERO); +#ifdef __APPLE__ + } else if (sig == SIGFPE && info->si_code == FPE_NOOP) { + int op = pc[0]; + + // Skip REX + if ((pc[0] & 0xf0) == 0x40) { + op = pc[1]; + } else { + op = pc[0]; + } + + // Check for IDIV + if (op == 0xF7) { + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime:: IMPLICIT_DIVIDE_BY_ZERO); + } else { + // TODO: handle more cases if we are using other x86 instructions + // that can generate SIGFPE signal. + tty->print_cr("unknown opcode 0x%X with SIGFPE.", op); + fatal("please update this code."); + } +#endif /* __APPLE__ */ + +#else + if (sig == SIGFPE /* && info->si_code == FPE_INTDIV */) { + // HACK: si_code does not work on bsd 2.2.12-20!!! + int op = pc[0]; + if (op == 0xDB) { + // FIST + // TODO: The encoding of D2I in i486.ad can cause an exception + // prior to the fist instruction if there was an invalid operation + // pending. We want to dismiss that exception. From the win_32 + // side it also seems that if it really was the fist causing + // the exception that we do the d2i by hand with different + // rounding. Seems kind of weird. + // NOTE: that we take the exception at the NEXT floating point instruction. + assert(pc[0] == 0xDB, "not a FIST opcode"); + assert(pc[1] == 0x14, "not a FIST opcode"); + assert(pc[2] == 0x24, "not a FIST opcode"); + return true; + } else if (op == 0xF7) { + // IDIV + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO); + } else { + // TODO: handle more cases if we are using other x86 instructions + // that can generate SIGFPE signal on bsd. + tty->print_cr("unknown opcode 0x%X with SIGFPE.", op); + fatal("please update this code."); + } +#endif // AMD64 + } else if ((sig == SIGSEGV || sig == SIGBUS) && + !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) { + // Determination of interpreter/vtable stub/compiled code null exception + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); + } + } else if (thread->thread_state() == _thread_in_vm && + sig == SIGBUS && /* info->si_code == BUS_OBJERR && */ + thread->doing_unsafe_access()) { + stub = StubRoutines::handler_for_unsafe_access(); + } + + // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in + // and the heap gets shrunk before the field access. + if ((sig == SIGSEGV) || (sig == SIGBUS)) { + address addr = JNI_FastGetField::find_slowcase_pc(pc); + if (addr != (address)-1) { + stub = addr; + } + } + + // Check to see if we caught the safepoint code in the + // process of write protecting the memory serialization page. + // It write enables the page immediately after protecting it + // so we can just return to retry the write. + if ((sig == SIGSEGV || sig == SIGBUS) && + os::is_memory_serialize_page(thread, (address) info->si_addr)) { + // Block current thread until the memory serialize page permission restored. + os::block_on_serialize_page_trap(); + return true; + } + } + +#ifndef AMD64 + // Execution protection violation + // + // This should be kept as the last step in the triage. We don't + // have a dedicated trap number for a no-execute fault, so be + // conservative and allow other handlers the first shot. + // + // Note: We don't test that info->si_code == SEGV_ACCERR here. + // this si_code is so generic that it is almost meaningless; and + // the si_code for this condition may change in the future. + // Furthermore, a false-positive should be harmless. + if (UnguardOnExecutionViolation > 0 && + (sig == SIGSEGV || sig == SIGBUS) && + uc->context_trapno == trap_page_fault) { + int page_size = os::vm_page_size(); + address addr = (address) info->si_addr; + address pc = os::Bsd::ucontext_get_pc(uc); + // Make sure the pc and the faulting address are sane. + // + // If an instruction spans a page boundary, and the page containing + // the beginning of the instruction is executable but the following + // page is not, the pc and the faulting address might be slightly + // different - we still want to unguard the 2nd page in this case. + // + // 15 bytes seems to be a (very) safe value for max instruction size. + bool pc_is_near_addr = + (pointer_delta((void*) addr, (void*) pc, sizeof(char)) < 15); + bool instr_spans_page_boundary = + (align_size_down((intptr_t) pc ^ (intptr_t) addr, + (intptr_t) page_size) > 0); + + if (pc == addr || (pc_is_near_addr && instr_spans_page_boundary)) { + static volatile address last_addr = + (address) os::non_memory_address_word(); + + // In conservative mode, don't unguard unless the address is in the VM + if (addr != last_addr && + (UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) { + + // Set memory to RWX and retry + address page_start = + (address) align_size_down((intptr_t) addr, (intptr_t) page_size); + bool res = os::protect_memory((char*) page_start, page_size, + os::MEM_PROT_RWX); + + if (PrintMiscellaneous && Verbose) { + char buf[256]; + jio_snprintf(buf, sizeof(buf), "Execution protection violation " + "at " INTPTR_FORMAT + ", unguarding " INTPTR_FORMAT ": %s, errno=%d", addr, + page_start, (res ? "success" : "failed"), errno); + tty->print_raw_cr(buf); + } + stub = pc; + + // Set last_addr so if we fault again at the same address, we don't end + // up in an endless loop. + // + // There are two potential complications here. Two threads trapping at + // the same address at the same time could cause one of the threads to + // think it already unguarded, and abort the VM. Likely very rare. + // + // The other race involves two threads alternately trapping at + // different addresses and failing to unguard the page, resulting in + // an endless loop. This condition is probably even more unlikely than + // the first. + // + // Although both cases could be avoided by using locks or thread local + // last_addr, these solutions are unnecessary complication: this + // handler is a best-effort safety net, not a complete solution. It is + // disabled by default and should only be used as a workaround in case + // we missed any no-execute-unsafe VM code. + + last_addr = addr; + } + } + } +#endif // !AMD64 + + if (stub != NULL) { + // save all thread context in case we need to restore it + if (thread != NULL) thread->set_saved_exception_pc(pc); + + uc->context_pc = (intptr_t)stub; + return true; + } + + // signal-chaining + if (os::Bsd::chained_handler(sig, info, ucVoid)) { + return true; + } + + if (!abort_if_unrecognized) { + // caller wants another chance, so give it to him + return false; + } + + if (pc == NULL && uc != NULL) { + pc = os::Bsd::ucontext_get_pc(uc); + } + + // unmask current signal + sigset_t newset; + sigemptyset(&newset); + sigaddset(&newset, sig); + sigprocmask(SIG_UNBLOCK, &newset, NULL); + + VMError err(t, sig, pc, info, ucVoid); + err.report_and_die(); + + ShouldNotReachHere(); +} + +#ifdef _ALLBSD_SOURCE +// From solaris_i486.s ported to bsd_i486.s +extern "C" void fixcw(); +#endif + +void os::Bsd::init_thread_fpu_state(void) { +#ifndef AMD64 +# ifdef _ALLBSD_SOURCE + // Set fpu to 53 bit precision. This happens too early to use a stub. + fixcw(); +# else + // set fpu to 53 bit precision + set_fpu_control_word(0x27f); +# endif +#endif // !AMD64 +} + +#ifndef _ALLBSD_SOURCE +int os::Bsd::get_fpu_control_word(void) { +#ifdef AMD64 + return 0; +#else + int fpu_control; + _FPU_GETCW(fpu_control); + return fpu_control & 0xffff; +#endif // AMD64 +} + +void os::Bsd::set_fpu_control_word(int fpu_control) { +#ifndef AMD64 + _FPU_SETCW(fpu_control); +#endif // !AMD64 +} +#endif + +// Check that the bsd kernel version is 2.4 or higher since earlier +// versions do not support SSE without patches. +bool os::supports_sse() { +#if defined(AMD64) || defined(_ALLBSD_SOURCE) + return true; +#else + struct utsname uts; + if( uname(&uts) != 0 ) return false; // uname fails? + char *minor_string; + int major = strtol(uts.release,&minor_string,10); + int minor = strtol(minor_string+1,NULL,10); + bool result = (major > 2 || (major==2 && minor >= 4)); +#ifndef PRODUCT + if (PrintMiscellaneous && Verbose) { + tty->print("OS version is %d.%d, which %s support SSE/SSE2\n", + major,minor, result ? "DOES" : "does NOT"); + } +#endif + return result; +#endif // AMD64 +} + +bool os::is_allocatable(size_t bytes) { +#ifdef AMD64 + // unused on amd64? + return true; +#else + + if (bytes < 2 * G) { + return true; + } + + char* addr = reserve_memory(bytes, NULL); + + if (addr != NULL) { + release_memory(addr, bytes); + } + + return addr != NULL; +#endif // AMD64 +} + +//////////////////////////////////////////////////////////////////////////////// +// thread stack + +#ifdef AMD64 +size_t os::Bsd::min_stack_allowed = 64 * K; + +// amd64: pthread on amd64 is always in floating stack mode +bool os::Bsd::supports_variable_stack_size() { return true; } +#else +size_t os::Bsd::min_stack_allowed = (48 DEBUG_ONLY(+4))*K; + +#ifdef __GNUC__ +#define GET_GS() ({int gs; __asm__ volatile("movw %%gs, %w0":"=q"(gs)); gs&0xffff;}) +#endif + +#ifdef _ALLBSD_SOURCE +bool os::Bsd::supports_variable_stack_size() { return true; } +#else +// Test if pthread library can support variable thread stack size. BsdThreads +// in fixed stack mode allocates 2M fixed slot for each thread. BsdThreads +// in floating stack mode and NPTL support variable stack size. +bool os::Bsd::supports_variable_stack_size() { + if (os::Bsd::is_NPTL()) { + // NPTL, yes + return true; + + } else { + // Note: We can't control default stack size when creating a thread. + // If we use non-default stack size (pthread_attr_setstacksize), both + // floating stack and non-floating stack BsdThreads will return the + // same value. This makes it impossible to implement this function by + // detecting thread stack size directly. + // + // An alternative approach is to check %gs. Fixed-stack BsdThreads + // do not use %gs, so its value is 0. Floating-stack BsdThreads use + // %gs (either as LDT selector or GDT selector, depending on kernel) + // to access thread specific data. + // + // Note that %gs is a reserved glibc register since early 2001, so + // applications are not allowed to change its value (Ulrich Drepper from + // Redhat confirmed that all known offenders have been modified to use + // either %fs or TSD). In the worst case scenario, when VM is embedded in + // a native application that plays with %gs, we might see non-zero %gs + // even BsdThreads is running in fixed stack mode. As the result, we'll + // return true and skip _thread_safety_check(), so we may not be able to + // detect stack-heap collisions. But otherwise it's harmless. + // +#ifdef __GNUC__ + return (GET_GS() != 0); +#else + return false; +#endif + } +} +#endif +#endif // AMD64 + +// return default stack size for thr_type +size_t os::Bsd::default_stack_size(os::ThreadType thr_type) { + // default stack size (compiler thread needs larger stack) +#ifdef AMD64 + size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M); +#else + size_t s = (thr_type == os::compiler_thread ? 2 * M : 512 * K); +#endif // AMD64 + return s; +} + +size_t os::Bsd::default_guard_size(os::ThreadType thr_type) { + // Creating guard page is very expensive. Java thread has HotSpot + // guard page, only enable glibc guard page for non-Java threads. + return (thr_type == java_thread ? 0 : page_size()); +} + +// Java thread: +// +// Low memory addresses +// +------------------------+ +// | |\ JavaThread created by VM does not have glibc +// | glibc guard page | - guard, attached Java thread usually has +// | |/ 1 page glibc guard. +// P1 +------------------------+ Thread::stack_base() - Thread::stack_size() +// | |\ +// | HotSpot Guard Pages | - red and yellow pages +// | |/ +// +------------------------+ JavaThread::stack_yellow_zone_base() +// | |\ +// | Normal Stack | - +// | |/ +// P2 +------------------------+ Thread::stack_base() +// +// Non-Java thread: +// +// Low memory addresses +// +------------------------+ +// | |\ +// | glibc guard page | - usually 1 page +// | |/ +// P1 +------------------------+ Thread::stack_base() - Thread::stack_size() +// | |\ +// | Normal Stack | - +// | |/ +// P2 +------------------------+ Thread::stack_base() +// +// ** P1 (aka bottom) and size ( P2 = P1 - size) are the address and stack size returned from +// pthread_attr_getstack() + +static void current_stack_region(address * bottom, size_t * size) { +#ifdef __APPLE__ + pthread_t self = pthread_self(); + void *stacktop = pthread_get_stackaddr_np(self); + *size = pthread_get_stacksize_np(self); + *bottom = (address) stacktop - *size; +#elif defined(__OpenBSD__) + stack_t ss; + int rslt = pthread_stackseg_np(pthread_self(), &ss); + + if (rslt != 0) + fatal(err_msg("pthread_stackseg_np failed with err = %d", rslt)); + + *bottom = (address)((char *)ss.ss_sp - ss.ss_size); + *size = ss.ss_size; +#elif defined(_ALLBSD_SOURCE) + pthread_attr_t attr; + + int rslt = pthread_attr_init(&attr); + + // JVM needs to know exact stack location, abort if it fails + if (rslt != 0) + fatal(err_msg("pthread_attr_init failed with err = %d", rslt)); + + rslt = pthread_attr_get_np(pthread_self(), &attr); + + if (rslt != 0) + fatal(err_msg("pthread_attr_get_np failed with err = %d", rslt)); + + if (pthread_attr_getstackaddr(&attr, (void **)bottom) != 0 || + pthread_attr_getstacksize(&attr, size) != 0) { + fatal("Can not locate current stack attributes!"); + } + + pthread_attr_destroy(&attr); +#else + if (os::Bsd::is_initial_thread()) { + // initial thread needs special handling because pthread_getattr_np() + // may return bogus value. + *bottom = os::Bsd::initial_thread_stack_bottom(); + *size = os::Bsd::initial_thread_stack_size(); + } else { + pthread_attr_t attr; + + int rslt = pthread_getattr_np(pthread_self(), &attr); + + // JVM needs to know exact stack location, abort if it fails + if (rslt != 0) { + if (rslt == ENOMEM) { + vm_exit_out_of_memory(0, "pthread_getattr_np"); + } else { + fatal(err_msg("pthread_getattr_np failed with errno = %d", rslt)); + } + } + + if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) { + fatal("Can not locate current stack attributes!"); + } + + pthread_attr_destroy(&attr); + + } +#endif + assert(os::current_stack_pointer() >= *bottom && + os::current_stack_pointer() < *bottom + *size, "just checking"); +} + +address os::current_stack_base() { + address bottom; + size_t size; + current_stack_region(&bottom, &size); + return (bottom + size); +} + +size_t os::current_stack_size() { + // stack size includes normal stack and HotSpot guard pages + address bottom; + size_t size; + current_stack_region(&bottom, &size); + return size; +} + +///////////////////////////////////////////////////////////////////////////// +// helper functions for fatal error handler + +void os::print_context(outputStream *st, void *context) { + if (context == NULL) return; + + ucontext_t *uc = (ucontext_t*)context; + st->print_cr("Registers:"); +#ifdef AMD64 + st->print( "RAX=" INTPTR_FORMAT, uc->context_rax); + st->print(", RBX=" INTPTR_FORMAT, uc->context_rbx); + st->print(", RCX=" INTPTR_FORMAT, uc->context_rcx); + st->print(", RDX=" INTPTR_FORMAT, uc->context_rdx); + st->cr(); + st->print( "RSP=" INTPTR_FORMAT, uc->context_rsp); + st->print(", RBP=" INTPTR_FORMAT, uc->context_rbp); + st->print(", RSI=" INTPTR_FORMAT, uc->context_rsi); + st->print(", RDI=" INTPTR_FORMAT, uc->context_rdi); + st->cr(); + st->print( "R8 =" INTPTR_FORMAT, uc->context_r8); + st->print(", R9 =" INTPTR_FORMAT, uc->context_r9); + st->print(", R10=" INTPTR_FORMAT, uc->context_r10); + st->print(", R11=" INTPTR_FORMAT, uc->context_r11); + st->cr(); + st->print( "R12=" INTPTR_FORMAT, uc->context_r12); + st->print(", R13=" INTPTR_FORMAT, uc->context_r13); + st->print(", R14=" INTPTR_FORMAT, uc->context_r14); + st->print(", R15=" INTPTR_FORMAT, uc->context_r15); + st->cr(); + st->print( "RIP=" INTPTR_FORMAT, uc->context_rip); + st->print(", EFLAGS=" INTPTR_FORMAT, uc->context_flags); + st->print(", ERR=" INTPTR_FORMAT, uc->context_err); + st->cr(); + st->print(" TRAPNO=" INTPTR_FORMAT, uc->context_trapno); +#else + st->print( "EAX=" INTPTR_FORMAT, uc->context_eax); + st->print(", EBX=" INTPTR_FORMAT, uc->context_ebx); + st->print(", ECX=" INTPTR_FORMAT, uc->context_ecx); + st->print(", EDX=" INTPTR_FORMAT, uc->context_edx); + st->cr(); + st->print( "ESP=" INTPTR_FORMAT, uc->context_esp); + st->print(", EBP=" INTPTR_FORMAT, uc->context_ebp); + st->print(", ESI=" INTPTR_FORMAT, uc->context_esi); + st->print(", EDI=" INTPTR_FORMAT, uc->context_edi); + st->cr(); + st->print( "EIP=" INTPTR_FORMAT, uc->context_eip); + st->print(", EFLAGS=" INTPTR_FORMAT, uc->context_eflags); +#endif // AMD64 + st->cr(); + st->cr(); + + intptr_t *sp = (intptr_t *)os::Bsd::ucontext_get_sp(uc); + st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp); + print_hex_dump(st, (address)sp, (address)(sp + 8*sizeof(intptr_t)), sizeof(intptr_t)); + st->cr(); + + // Note: it may be unsafe to inspect memory near pc. For example, pc may + // point to garbage if entry point in an nmethod is corrupted. Leave + // this at the end, and hope for the best. + address pc = os::Bsd::ucontext_get_pc(uc); + st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc); + print_hex_dump(st, pc - 32, pc + 32, sizeof(char)); +} + +void os::print_register_info(outputStream *st, void *context) { + if (context == NULL) return; + + ucontext_t *uc = (ucontext_t*)context; + + st->print_cr("Register to memory mapping:"); + st->cr(); + + // this is horrendously verbose but the layout of the registers in the + // context does not match how we defined our abstract Register set, so + // we can't just iterate through the gregs area + + // this is only for the "general purpose" registers + +#ifdef AMD64 + st->print("RAX="); print_location(st, uc->context_rax); + st->print("RBX="); print_location(st, uc->context_rbx); + st->print("RCX="); print_location(st, uc->context_rcx); + st->print("RDX="); print_location(st, uc->context_rdx); + st->print("RSP="); print_location(st, uc->context_rsp); + st->print("RBP="); print_location(st, uc->context_rbp); + st->print("RSI="); print_location(st, uc->context_rsi); + st->print("RDI="); print_location(st, uc->context_rdi); + st->print("R8 ="); print_location(st, uc->context_r8); + st->print("R9 ="); print_location(st, uc->context_r9); + st->print("R10="); print_location(st, uc->context_r10); + st->print("R11="); print_location(st, uc->context_r11); + st->print("R12="); print_location(st, uc->context_r12); + st->print("R13="); print_location(st, uc->context_r13); + st->print("R14="); print_location(st, uc->context_r14); + st->print("R15="); print_location(st, uc->context_r15); +#else + st->print("EAX="); print_location(st, uc->context_eax); + st->print("EBX="); print_location(st, uc->context_ebx); + st->print("ECX="); print_location(st, uc->context_ecx); + st->print("EDX="); print_location(st, uc->context_edx); + st->print("ESP="); print_location(st, uc->context_esp); + st->print("EBP="); print_location(st, uc->context_ebp); + st->print("ESI="); print_location(st, uc->context_esi); + st->print("EDI="); print_location(st, uc->context_edi); +#endif // AMD64 + + st->cr(); +} + +void os::setup_fpu() { +#ifndef AMD64 + address fpu_cntrl = StubRoutines::addr_fpu_cntrl_wrd_std(); + __asm__ volatile ( "fldcw (%0)" : + : "r" (fpu_cntrl) : "memory"); +#endif // !AMD64 +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/os_bsd_x86.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_BSD_X86_VM_OS_BSD_X86_HPP +#define OS_CPU_BSD_X86_VM_OS_BSD_X86_HPP + + static void setup_fpu(); + static bool supports_sse(); + + static bool is_allocatable(size_t bytes); + + // Used to register dynamic code cache area with the OS + // Note: Currently only used in 64 bit Windows implementations + static bool register_code_area(char *low, char *high) { return true; } + +#endif // OS_CPU_BSD_X86_VM_OS_BSD_X86_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/prefetch_bsd_x86.inline.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_BSD_X86_VM_PREFETCH_BSD_X86_INLINE_HPP +#define OS_CPU_BSD_X86_VM_PREFETCH_BSD_X86_INLINE_HPP + +#include "runtime/prefetch.hpp" + + +inline void Prefetch::read (void *loc, intx interval) { +#ifdef AMD64 + __asm__ ("prefetcht0 (%0,%1,1)" : : "r" (loc), "r" (interval)); +#endif // AMD64 +} + +inline void Prefetch::write(void *loc, intx interval) { +#ifdef AMD64 + + // Do not use the 3dnow prefetchw instruction. It isn't supported on em64t. + // __asm__ ("prefetchw (%0,%1,1)" : : "r" (loc), "r" (interval)); + __asm__ ("prefetcht0 (%0,%1,1)" : : "r" (loc), "r" (interval)); + +#endif // AMD64 +} + +#endif // OS_CPU_BSD_X86_VM_PREFETCH_BSD_X86_INLINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/threadLS_bsd_x86.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "runtime/threadLocalStorage.hpp" +#include "thread_bsd.inline.hpp" + +// Map stack pointer (%esp) to thread pointer for faster TLS access +// +// Here we use a flat table for better performance. Getting current thread +// is down to one memory access (read _sp_map[%esp>>12]) in generated code +// and two in runtime code (-fPIC code needs an extra load for _sp_map). +// +// This code assumes stack page is not shared by different threads. It works +// in 32-bit VM when page size is 4K (or a multiple of 4K, if that matters). +// +// Notice that _sp_map is allocated in the bss segment, which is ZFOD +// (zero-fill-on-demand). While it reserves 4M address space upfront, +// actual memory pages are committed on demand. +// +// If an application creates and destroys a lot of threads, usually the +// stack space freed by a thread will soon get reused by new thread +// (this is especially true in NPTL or BsdThreads in fixed-stack mode). +// No memory page in _sp_map is wasted. +// +// However, it's still possible that we might end up populating & +// committing a large fraction of the 4M table over time, but the actual +// amount of live data in the table could be quite small. The max wastage +// is less than 4M bytes. If it becomes an issue, we could use madvise() +// with MADV_DONTNEED to reclaim unused (i.e. all-zero) pages in _sp_map. +// MADV_DONTNEED on Bsd keeps the virtual memory mapping, but zaps the +// physical memory page (i.e. similar to MADV_FREE on Solaris). + +#ifndef AMD64 +Thread* ThreadLocalStorage::_sp_map[1UL << (SP_BITLENGTH - PAGE_SHIFT)]; +#endif // !AMD64 + +void ThreadLocalStorage::generate_code_for_get_thread() { + // nothing we can do here for user-level thread +} + +void ThreadLocalStorage::pd_init() { +#ifndef AMD64 + assert(align_size_down(os::vm_page_size(), PAGE_SIZE) == os::vm_page_size(), + "page size must be multiple of PAGE_SIZE"); +#endif // !AMD64 +} + +void ThreadLocalStorage::pd_set_thread(Thread* thread) { + os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); + +#ifndef AMD64 + address stack_top = os::current_stack_base(); + size_t stack_size = os::current_stack_size(); + + for (address p = stack_top - stack_size; p < stack_top; p += PAGE_SIZE) { + // pd_set_thread() is called with non-NULL value when a new thread is + // created/attached, or with NULL value when a thread is about to exit. + // If both "thread" and the corresponding _sp_map[] entry are non-NULL, + // they should have the same value. Otherwise it might indicate that the + // stack page is shared by multiple threads. However, a more likely cause + // for this assertion to fail is that an attached thread exited without + // detaching itself from VM, which is a program error and could cause VM + // to crash. + assert(thread == NULL || _sp_map[(uintptr_t)p >> PAGE_SHIFT] == NULL || + thread == _sp_map[(uintptr_t)p >> PAGE_SHIFT], + "thread exited without detaching from VM??"); + _sp_map[(uintptr_t)p >> PAGE_SHIFT] = thread; + } +#endif // !AMD64 +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/threadLS_bsd_x86.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_BSD_X86_VM_THREADLS_BSD_X86_HPP +#define OS_CPU_BSD_X86_VM_THREADLS_BSD_X86_HPP + + // Processor dependent parts of ThreadLocalStorage + +#ifndef AMD64 + // map stack pointer to thread pointer - see notes in threadLS_bsd_x86.cpp + #define SP_BITLENGTH 32 +#ifndef PAGE_SHIFT + #define PAGE_SHIFT 12 + #define PAGE_SIZE (1UL << PAGE_SHIFT) +#endif + static Thread* _sp_map[1UL << (SP_BITLENGTH - PAGE_SHIFT)]; +#endif // !AMD64 + +public: + +#ifndef AMD64 + static Thread** sp_map_addr() { return _sp_map; } +#endif // !AMD64 + + static Thread* thread() { +#ifdef AMD64 + return (Thread*) os::thread_local_storage_at(thread_index()); +#else + uintptr_t sp; + __asm__ volatile ("movl %%esp, %0" : "=r" (sp)); + return _sp_map[sp >> PAGE_SHIFT]; +#endif // AMD64 + } + +#endif // OS_CPU_BSD_X86_VM_THREADLS_BSD_X86_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "runtime/frame.inline.hpp" +#include "thread_bsd.inline.hpp" + +// For Forte Analyzer AsyncGetCallTrace profiling support - thread is +// currently interrupted by SIGPROF +bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, + void* ucontext, bool isInJava) { + + assert(Thread::current() == this, "caller must be current thread"); + assert(this->is_Java_thread(), "must be JavaThread"); + + JavaThread* jt = (JavaThread *)this; + + // If we have a last_Java_frame, then we should use it even if + // isInJava == true. It should be more reliable than ucontext info. + if (jt->has_last_Java_frame()) { + *fr_addr = jt->pd_last_frame(); + return true; + } + + // At this point, we don't have a last_Java_frame, so + // we try to glean some information out of the ucontext + // if we were running Java code when SIGPROF came in. + if (isInJava) { + ucontext_t* uc = (ucontext_t*) ucontext; + + intptr_t* ret_fp; + intptr_t* ret_sp; + ExtendedPC addr = os::Bsd::fetch_frame_from_ucontext(this, uc, + &ret_sp, &ret_fp); + if (addr.pc() == NULL || ret_sp == NULL ) { + // ucontext wasn't useful + return false; + } + + frame ret_frame(ret_sp, ret_fp, addr.pc()); + if (!ret_frame.safe_for_sender(jt)) { +#ifdef COMPILER2 + // C2 uses ebp as a general register see if NULL fp helps + frame ret_frame2(ret_sp, NULL, addr.pc()); + if (!ret_frame2.safe_for_sender(jt)) { + // nothing else to try if the frame isn't good + return false; + } + ret_frame = ret_frame2; +#else + // nothing else to try if the frame isn't good + return false; +#endif /* COMPILER2 */ + } + *fr_addr = ret_frame; + return true; + } + + // nothing else to try + return false; +} + +void JavaThread::cache_global_variables() { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/thread_bsd_x86.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_BSD_X86_VM_THREAD_BSD_X86_HPP +#define OS_CPU_BSD_X86_VM_THREAD_BSD_X86_HPP + + private: + void pd_initialize() { + _anchor.clear(); + } + + frame pd_last_frame() { + assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); + if (_anchor.last_Java_pc() != NULL) { + return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc()); + } else { + // This will pick up pc from sp + return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp()); + } + } + + public: + // Mutators are highly dangerous.... + intptr_t* last_Java_fp() { return _anchor.last_Java_fp(); } + void set_last_Java_fp(intptr_t* fp) { _anchor.set_last_Java_fp(fp); } + + void set_base_of_stack_pointer(intptr_t* base_sp) { + } + + static ByteSize last_Java_fp_offset() { + return byte_offset_of(JavaThread, _anchor) + JavaFrameAnchor::last_Java_fp_offset(); + } + + intptr_t* base_of_stack_pointer() { + return NULL; + } + void record_base_of_stack_pointer() { + } + + bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, + bool isInJava); + + // These routines are only used on cpu architectures that + // have separate register stacks (Itanium). + static bool register_stack_overflow() { return false; } + static void enable_register_stack_guard() {} + static void disable_register_stack_guard() {} + +#endif // OS_CPU_BSD_X86_VM_THREAD_BSD_X86_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_BSD_X86_VM_VMSTRUCTS_BSD_X86_HPP +#define OS_CPU_BSD_X86_VM_VMSTRUCTS_BSD_X86_HPP + +// These are the OS and CPU-specific fields, types and integer +// constants required by the Serviceability Agent. This file is +// referenced by vmStructs.cpp. + +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ + \ + /******************************/ \ + /* Threads (NOTE: incomplete) */ \ + /******************************/ \ + nonstatic_field(OSThread, _thread_id, pthread_t) \ + nonstatic_field(OSThread, _pthread_id, pthread_t) \ + /* This must be the last entry, and must be present */ \ + last_entry() + + +#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, last_entry) \ + \ + /**********************/ \ + /* Posix Thread IDs */ \ + /**********************/ \ + \ + declare_integer_type(pid_t) \ + declare_unsigned_integer_type(pthread_t) \ + \ + /* This must be the last entry, and must be present */ \ + last_entry() + +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ + \ + /* This must be the last entry, and must be present */ \ + last_entry() + +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ + \ + /* This must be the last entry, and must be present */ \ + last_entry() + +#endif // OS_CPU_BSD_X86_VM_VMSTRUCTS_BSD_X86_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_x86/vm/vm_version_bsd_x86.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "runtime/os.hpp" +#include "vm_version_x86.hpp"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_zero/vm/assembler_bsd_zero.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2009 Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "asm/assembler.hpp" +#include "assembler_zero.inline.hpp" +#include "runtime/os.hpp" +#include "runtime/threadLocalStorage.hpp" + +// This file is intentionally empty
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright 2007, 2008, 2011 Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_BSD_ZERO_VM_ATOMIC_BSD_ZERO_INLINE_HPP +#define OS_CPU_BSD_ZERO_VM_ATOMIC_BSD_ZERO_INLINE_HPP + +#include "orderAccess_bsd_zero.inline.hpp" +#include "runtime/atomic.hpp" +#include "runtime/os.hpp" +#include "vm_version_zero.hpp" + +// Implementation of class atomic + +#ifdef M68K + +/* + * __m68k_cmpxchg + * + * Atomically store newval in *ptr if *ptr is equal to oldval for user space. + * Returns newval on success and oldval if no exchange happened. + * This implementation is processor specific and works on + * 68020 68030 68040 and 68060. + * + * It will not work on ColdFire, 68000 and 68010 since they lack the CAS + * instruction. + * Using a kernelhelper would be better for arch complete implementation. + * + */ + +static inline int __m68k_cmpxchg(int oldval, int newval, volatile int *ptr) { + int ret; + __asm __volatile ("cas%.l %0,%2,%1" + : "=d" (ret), "+m" (*(ptr)) + : "d" (newval), "0" (oldval)); + return ret; +} + +/* Perform an atomic compare and swap: if the current value of `*PTR' + is OLDVAL, then write NEWVAL into `*PTR'. Return the contents of + `*PTR' before the operation.*/ +static inline int m68k_compare_and_swap(volatile int *ptr, + int oldval, + int newval) { + for (;;) { + int prev = *ptr; + if (prev != oldval) + return prev; + + if (__m68k_cmpxchg (prev, newval, ptr) == newval) + // Success. + return prev; + + // We failed even though prev == oldval. Try again. + } +} + +/* Atomically add an int to memory. */ +static inline int m68k_add_and_fetch(volatile int *ptr, int add_value) { + for (;;) { + // Loop until success. + + int prev = *ptr; + + if (__m68k_cmpxchg (prev, prev + add_value, ptr) == prev + add_value) + return prev + add_value; + } +} + +/* Atomically write VALUE into `*PTR' and returns the previous + contents of `*PTR'. */ +static inline int m68k_lock_test_and_set(volatile int *ptr, int newval) { + for (;;) { + // Loop until success. + int prev = *ptr; + + if (__m68k_cmpxchg (prev, newval, ptr) == prev) + return prev; + } +} +#endif // M68K + +#ifdef ARM + +/* + * __kernel_cmpxchg + * + * Atomically store newval in *ptr if *ptr is equal to oldval for user space. + * Return zero if *ptr was changed or non-zero if no exchange happened. + * The C flag is also set if *ptr was changed to allow for assembly + * optimization in the calling code. + * + */ + +typedef int (__kernel_cmpxchg_t)(int oldval, int newval, volatile int *ptr); +#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *) 0xffff0fc0) + + + +/* Perform an atomic compare and swap: if the current value of `*PTR' + is OLDVAL, then write NEWVAL into `*PTR'. Return the contents of + `*PTR' before the operation.*/ +static inline int arm_compare_and_swap(volatile int *ptr, + int oldval, + int newval) { + for (;;) { + int prev = *ptr; + if (prev != oldval) + return prev; + + if (__kernel_cmpxchg (prev, newval, ptr) == 0) + // Success. + return prev; + + // We failed even though prev == oldval. Try again. + } +} + +/* Atomically add an int to memory. */ +static inline int arm_add_and_fetch(volatile int *ptr, int add_value) { + for (;;) { + // Loop until a __kernel_cmpxchg succeeds. + + int prev = *ptr; + + if (__kernel_cmpxchg (prev, prev + add_value, ptr) == 0) + return prev + add_value; + } +} + +/* Atomically write VALUE into `*PTR' and returns the previous + contents of `*PTR'. */ +static inline int arm_lock_test_and_set(volatile int *ptr, int newval) { + for (;;) { + // Loop until a __kernel_cmpxchg succeeds. + int prev = *ptr; + + if (__kernel_cmpxchg (prev, newval, ptr) == 0) + return prev; + } +} +#endif // ARM + +inline void Atomic::store(jint store_value, volatile jint* dest) { +#if !defined(ARM) && !defined(M68K) + __sync_synchronize(); +#endif + *dest = store_value; +} + +inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { +#if !defined(ARM) && !defined(M68K) + __sync_synchronize(); +#endif + *dest = store_value; +} + +inline jint Atomic::add(jint add_value, volatile jint* dest) { +#ifdef ARM + return arm_add_and_fetch(dest, add_value); +#else +#ifdef M68K + return m68k_add_and_fetch(dest, add_value); +#else + return __sync_add_and_fetch(dest, add_value); +#endif // M68K +#endif // ARM +} + +inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) { +#ifdef ARM + return arm_add_and_fetch(dest, add_value); +#else +#ifdef M68K + return m68k_add_and_fetch(dest, add_value); +#else + return __sync_add_and_fetch(dest, add_value); +#endif // M68K +#endif // ARM +} + +inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) { + return (void *) add_ptr(add_value, (volatile intptr_t *) dest); +} + +inline void Atomic::inc(volatile jint* dest) { + add(1, dest); +} + +inline void Atomic::inc_ptr(volatile intptr_t* dest) { + add_ptr(1, dest); +} + +inline void Atomic::inc_ptr(volatile void* dest) { + add_ptr(1, dest); +} + +inline void Atomic::dec(volatile jint* dest) { + add(-1, dest); +} + +inline void Atomic::dec_ptr(volatile intptr_t* dest) { + add_ptr(-1, dest); +} + +inline void Atomic::dec_ptr(volatile void* dest) { + add_ptr(-1, dest); +} + +inline jint Atomic::xchg(jint exchange_value, volatile jint* dest) { +#ifdef ARM + return arm_lock_test_and_set(dest, exchange_value); +#else +#ifdef M68K + return m68k_lock_test_and_set(dest, exchange_value); +#else + // __sync_lock_test_and_set is a bizarrely named atomic exchange + // operation. Note that some platforms only support this with the + // limitation that the only valid value to store is the immediate + // constant 1. There is a test for this in JNI_CreateJavaVM(). + return __sync_lock_test_and_set (dest, exchange_value); +#endif // M68K +#endif // ARM +} + +inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, + volatile intptr_t* dest) { +#ifdef ARM + return arm_lock_test_and_set(dest, exchange_value); +#else +#ifdef M68K + return m68k_lock_test_and_set(dest, exchange_value); +#else + return __sync_lock_test_and_set (dest, exchange_value); +#endif // M68K +#endif // ARM +} + +inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* dest) { + return (void *) xchg_ptr((intptr_t) exchange_value, + (volatile intptr_t*) dest); +} + +inline jint Atomic::cmpxchg(jint exchange_value, + volatile jint* dest, + jint compare_value) { +#ifdef ARM + return arm_compare_and_swap(dest, compare_value, exchange_value); +#else +#ifdef M68K + return m68k_compare_and_swap(dest, compare_value, exchange_value); +#else + return __sync_val_compare_and_swap(dest, compare_value, exchange_value); +#endif // M68K +#endif // ARM +} + +inline jlong Atomic::cmpxchg(jlong exchange_value, + volatile jlong* dest, + jlong compare_value) { + + return __sync_val_compare_and_swap(dest, compare_value, exchange_value); +} + +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, + volatile intptr_t* dest, + intptr_t compare_value) { +#ifdef ARM + return arm_compare_and_swap(dest, compare_value, exchange_value); +#else +#ifdef M68K + return m68k_compare_and_swap(dest, compare_value, exchange_value); +#else + return __sync_val_compare_and_swap(dest, compare_value, exchange_value); +#endif // M68K +#endif // ARM +} + +inline void* Atomic::cmpxchg_ptr(void* exchange_value, + volatile void* dest, + void* compare_value) { + + return (void *) cmpxchg_ptr((intptr_t) exchange_value, + (volatile intptr_t*) dest, + (intptr_t) compare_value); +} + +inline jlong Atomic::load(volatile jlong* src) { + volatile jlong dest; + os::atomic_copy64(src, &dest); + return dest; +} + +inline void Atomic::store(jlong store_value, jlong* dest) { + os::atomic_copy64((volatile jlong*)&store_value, (volatile jlong*)dest); +} + +inline void Atomic::store(jlong store_value, volatile jlong* dest) { + os::atomic_copy64((volatile jlong*)&store_value, dest); +} + +#endif // OS_CPU_BSD_ZERO_VM_ATOMIC_BSD_ZERO_INLINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_zero/vm/bytes_bsd_zero.inline.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_BSD_ZERO_VM_BYTES_BSD_ZERO_INLINE_HPP +#define OS_CPU_BSD_ZERO_VM_BYTES_BSD_ZERO_INLINE_HPP + +// Efficient swapping of data bytes from Java byte +// ordering to native byte ordering and vice versa. + +#ifdef __APPLE__ +# include <libkern/OSByteOrder.h> +#else +# include <sys/endian.h> +#endif + +#if defined(__APPLE__) +# define bswap_16(x) OSSwapInt16(x) +# define bswap_32(x) OSSwapInt32(x) +# define bswap_64(x) OSSwapInt64(x) +#elif defined(__OpenBSD__) +# define bswap_16(x) swap16(x) +# define bswap_32(x) swap32(x) +# define bswap_64(x) swap64(x) +#elif defined(__NetBSD__) +# define bswap_16(x) bswap16(x) +# define bswap_32(x) bswap32(x) +# define bswap_64(x) bswap64(x) +#else +# define bswap_16(x) __bswap16(x) +# define bswap_32(x) __bswap32(x) +# define bswap_64(x) __bswap64(x) +#endif + +inline u2 Bytes::swap_u2(u2 x) { + return bswap_16(x); +} + +inline u4 Bytes::swap_u4(u4 x) { + return bswap_32(x); +} + +inline u8 Bytes::swap_u8(u8 x) { + return bswap_64(x); +} + +#endif // OS_CPU_BSD_ZERO_VM_BYTES_BSD_ZERO_INLINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_zero/vm/globals_bsd_zero.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2007, 2008, 2010 Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_BSD_ZERO_VM_GLOBALS_BSD_ZERO_HPP +#define OS_CPU_BSD_ZERO_VM_GLOBALS_BSD_ZERO_HPP + +// +// Set the default values for platform dependent flags used by the +// runtime system. See globals.hpp for details of what they do. +// + +define_pd_global(bool, DontYieldALot, false); +define_pd_global(intx, ThreadStackSize, 1536); +#ifdef _LP64 +define_pd_global(intx, VMThreadStackSize, 1024); +#else +define_pd_global(intx, VMThreadStackSize, 512); +#endif // _LP64 +define_pd_global(intx, CompilerThreadStackSize, 0); +define_pd_global(uintx, JVMInvokeMethodSlack, 8192); + +define_pd_global(bool, UseVectoredExceptions, false); +// Only used on 64 bit platforms +define_pd_global(uintx, HeapBaseMinAddress, 2*G); + +#endif // OS_CPU_BSD_ZERO_VM_GLOBALS_BSD_ZERO_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_zero/vm/orderAccess_bsd_zero.inline.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2007, 2008, 2009 Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_BSD_ZERO_VM_ORDERACCESS_BSD_ZERO_INLINE_HPP +#define OS_CPU_BSD_ZERO_VM_ORDERACCESS_BSD_ZERO_INLINE_HPP + +#include "runtime/orderAccess.hpp" +#include "vm_version_zero.hpp" + +#ifdef ARM + +/* + * ARM Kernel helper for memory barrier. + * Using __asm __volatile ("":::"memory") does not work reliable on ARM + * and gcc __sync_synchronize(); implementation does not use the kernel + * helper for all gcc versions so it is unreliable to use as well. + */ +typedef void (__kernel_dmb_t) (void); +#define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0) + +#define FULL_MEM_BARRIER __kernel_dmb() +#define READ_MEM_BARRIER __kernel_dmb() +#define WRITE_MEM_BARRIER __kernel_dmb() + +#else // ARM + +#define FULL_MEM_BARRIER __sync_synchronize() + +#ifdef PPC + +#ifdef __NO_LWSYNC__ +#define READ_MEM_BARRIER __asm __volatile ("sync":::"memory") +#define WRITE_MEM_BARRIER __asm __volatile ("sync":::"memory") +#else +#define READ_MEM_BARRIER __asm __volatile ("lwsync":::"memory") +#define WRITE_MEM_BARRIER __asm __volatile ("lwsync":::"memory") +#endif + +#else // PPC + +#define READ_MEM_BARRIER __asm __volatile ("":::"memory") +#define WRITE_MEM_BARRIER __asm __volatile ("":::"memory") + +#endif // PPC + +#endif // ARM + + +inline void OrderAccess::loadload() { acquire(); } +inline void OrderAccess::storestore() { release(); } +inline void OrderAccess::loadstore() { acquire(); } +inline void OrderAccess::storeload() { fence(); } + +inline void OrderAccess::acquire() { + READ_MEM_BARRIER; +} + +inline void OrderAccess::release() { + WRITE_MEM_BARRIER; +} + +inline void OrderAccess::fence() { + FULL_MEM_BARRIER; +} + +inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { jbyte data = *p; acquire(); return data; } +inline jshort OrderAccess::load_acquire(volatile jshort* p) { jshort data = *p; acquire(); return data; } +inline jint OrderAccess::load_acquire(volatile jint* p) { jint data = *p; acquire(); return data; } +inline jlong OrderAccess::load_acquire(volatile jlong* p) { + jlong tmp; + os::atomic_copy64(p, &tmp); + acquire(); + return tmp; +} +inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { jubyte data = *p; acquire(); return data; } +inline jushort OrderAccess::load_acquire(volatile jushort* p) { jushort data = *p; acquire(); return data; } +inline juint OrderAccess::load_acquire(volatile juint* p) { juint data = *p; acquire(); return data; } +inline julong OrderAccess::load_acquire(volatile julong* p) { + julong tmp; + os::atomic_copy64(p, &tmp); + acquire(); + return tmp; +} +inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { jfloat data = *p; acquire(); return data; } +inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { + jdouble tmp; + os::atomic_copy64(p, &tmp); + acquire(); + return tmp; +} + +inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { + intptr_t data = *p; + acquire(); + return data; +} +inline void* OrderAccess::load_ptr_acquire(volatile void* p) { + void *data = *(void* volatile *)p; + acquire(); + return data; +} +inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { + void *data = *(void* const volatile *)p; + acquire(); + return data; +} + +inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { release(); *p = v; } +inline void OrderAccess::release_store(volatile jshort* p, jshort v) { release(); *p = v; } +inline void OrderAccess::release_store(volatile jint* p, jint v) { release(); *p = v; } +inline void OrderAccess::release_store(volatile jlong* p, jlong v) +{ release(); os::atomic_copy64(&v, p); } +inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { release(); *p = v; } +inline void OrderAccess::release_store(volatile jushort* p, jushort v) { release(); *p = v; } +inline void OrderAccess::release_store(volatile juint* p, juint v) { release(); *p = v; } +inline void OrderAccess::release_store(volatile julong* p, julong v) +{ release(); os::atomic_copy64(&v, p); } +inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { release(); *p = v; } +inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) +{ release(); os::atomic_copy64(&v, p); } + +inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { release(); *p = v; } +inline void OrderAccess::release_store_ptr(volatile void* p, void* v) +{ release(); *(void* volatile *)p = v; } + +inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; fence(); } +inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; fence(); } +inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; fence(); } +inline void OrderAccess::store_fence(jlong* p, jlong v) { os::atomic_copy64(&v, p); fence(); } +inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; fence(); } +inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; fence(); } +inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; fence(); } +inline void OrderAccess::store_fence(julong* p, julong v) { os::atomic_copy64(&v, p); fence(); } +inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } +inline void OrderAccess::store_fence(jdouble* p, jdouble v) { os::atomic_copy64(&v, p); fence(); } + +inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; fence(); } +inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; fence(); } + +inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { release_store(p, v); fence(); } +inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { release_store(p, v); fence(); } +inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { release_store(p, v); fence(); } +inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); } +inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store(p, v); fence(); } +inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store(p, v); fence(); } +inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { release_store(p, v); fence(); } +inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store(p, v); fence(); } +inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { release_store(p, v); fence(); } +inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store(p, v); fence(); } + +inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { release_store_ptr(p, v); fence(); } +inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { release_store_ptr(p, v); fence(); } + +#endif // OS_CPU_BSD_ZERO_VM_ORDERACCESS_BSD_ZERO_INLINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,564 @@ +/* + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#if defined(_ALLBSD_SOURCE) && !defined(__APPLE__) && !defined(__NetBSD__) +#include <pthread.h> +# include <pthread_np.h> /* For pthread_attr_get_np */ +#endif + +// no precompiled headers +#include "assembler_zero.inline.hpp" +#include "classfile/classLoader.hpp" +#include "classfile/systemDictionary.hpp" +#include "classfile/vmSymbols.hpp" +#include "code/icBuffer.hpp" +#include "code/vtableStubs.hpp" +#include "interpreter/interpreter.hpp" +#include "jvm_bsd.h" +#include "memory/allocation.inline.hpp" +#include "mutex_bsd.inline.hpp" +#include "nativeInst_zero.hpp" +#include "os_share_bsd.hpp" +#include "prims/jniFastGetField.hpp" +#include "prims/jvm.h" +#include "prims/jvm_misc.hpp" +#include "runtime/arguments.hpp" +#include "runtime/extendedPC.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/interfaceSupport.hpp" +#include "runtime/java.hpp" +#include "runtime/javaCalls.hpp" +#include "runtime/mutexLocker.hpp" +#include "runtime/osThread.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/timer.hpp" +#include "thread_bsd.inline.hpp" +#include "utilities/events.hpp" +#include "utilities/vmError.hpp" +#ifdef COMPILER1 +#include "c1/c1_Runtime1.hpp" +#endif +#ifdef COMPILER2 +#include "opto/runtime.hpp" +#endif + +address os::current_stack_pointer() { + address dummy = (address) &dummy; + return dummy; +} + +frame os::get_sender_for_C_frame(frame* fr) { + ShouldNotCallThis(); +} + +frame os::current_frame() { + // The only thing that calls this is the stack printing code in + // VMError::report: + // - Step 110 (printing stack bounds) uses the sp in the frame + // to determine the amount of free space on the stack. We + // set the sp to a close approximation of the real value in + // order to allow this step to complete. + // - Step 120 (printing native stack) tries to walk the stack. + // The frame we create has a NULL pc, which is ignored as an + // invalid frame. + frame dummy = frame(); + dummy.set_sp((intptr_t *) current_stack_pointer()); + return dummy; +} + +char* os::non_memory_address_word() { + // Must never look like an address returned by reserve_memory, + // even in its subfields (as defined by the CPU immediate fields, + // if the CPU splits constants across multiple instructions). +#ifdef SPARC + // On SPARC, 0 != %hi(any real address), because there is no + // allocation in the first 1Kb of the virtual address space. + return (char *) 0; +#else + // This is the value for x86; works pretty well for PPC too. + return (char *) -1; +#endif // SPARC +} + +void os::initialize_thread() { + // Nothing to do. +} + +address os::Bsd::ucontext_get_pc(ucontext_t* uc) { + ShouldNotCallThis(); +} + +ExtendedPC os::fetch_frame_from_context(void* ucVoid, + intptr_t** ret_sp, + intptr_t** ret_fp) { + ShouldNotCallThis(); +} + +frame os::fetch_frame_from_context(void* ucVoid) { + ShouldNotCallThis(); +} + +extern "C" JNIEXPORT int +JVM_handle_bsd_signal(int sig, + siginfo_t* info, + void* ucVoid, + int abort_if_unrecognized) { + ucontext_t* uc = (ucontext_t*) ucVoid; + + Thread* t = ThreadLocalStorage::get_thread_slow(); + + SignalHandlerMark shm(t); + + // Note: it's not uncommon that JNI code uses signal/sigset to + // install then restore certain signal handler (e.g. to temporarily + // block SIGPIPE, or have a SIGILL handler when detecting CPU + // type). When that happens, JVM_handle_bsd_signal() might be + // invoked with junk info/ucVoid. To avoid unnecessary crash when + // libjsig is not preloaded, try handle signals that do not require + // siginfo/ucontext first. + + if (sig == SIGPIPE || sig == SIGXFSZ) { + // allow chained handler to go first + if (os::Bsd::chained_handler(sig, info, ucVoid)) { + return true; + } else { + if (PrintMiscellaneous && (WizardMode || Verbose)) { + char buf[64]; + warning("Ignoring %s - see bugs 4229104 or 646499219", + os::exception_name(sig, buf, sizeof(buf))); + } + return true; + } + } + + JavaThread* thread = NULL; + VMThread* vmthread = NULL; + if (os::Bsd::signal_handlers_are_installed) { + if (t != NULL ){ + if(t->is_Java_thread()) { + thread = (JavaThread*)t; + } + else if(t->is_VM_thread()){ + vmthread = (VMThread *)t; + } + } + } + + if (info != NULL && thread != NULL) { + // Handle ALL stack overflow variations here + if (sig == SIGSEGV || sig == SIGBUS) { + address addr = (address) info->si_addr; + + // check if fault address is within thread stack + if (addr < thread->stack_base() && + addr >= thread->stack_base() - thread->stack_size()) { + // stack overflow + if (thread->in_stack_yellow_zone(addr)) { + thread->disable_stack_yellow_zone(); + ShouldNotCallThis(); + } + else if (thread->in_stack_red_zone(addr)) { + thread->disable_stack_red_zone(); + ShouldNotCallThis(); + } +#ifndef _ALLBSD_SOURCE + else { + // Accessing stack address below sp may cause SEGV if + // current thread has MAP_GROWSDOWN stack. This should + // only happen when current thread was created by user + // code with MAP_GROWSDOWN flag and then attached to VM. + // See notes in os_bsd.cpp. + if (thread->osthread()->expanding_stack() == 0) { + thread->osthread()->set_expanding_stack(); + if (os::Bsd::manually_expand_stack(thread, addr)) { + thread->osthread()->clear_expanding_stack(); + return true; + } + thread->osthread()->clear_expanding_stack(); + } + else { + fatal("recursive segv. expanding stack."); + } + } +#endif + } + } + + /*if (thread->thread_state() == _thread_in_Java) { + ShouldNotCallThis(); + } + else*/ if (thread->thread_state() == _thread_in_vm && + sig == SIGBUS && thread->doing_unsafe_access()) { + ShouldNotCallThis(); + } + + // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC + // kicks in and the heap gets shrunk before the field access. + /*if (sig == SIGSEGV || sig == SIGBUS) { + address addr = JNI_FastGetField::find_slowcase_pc(pc); + if (addr != (address)-1) { + stub = addr; + } + }*/ + + // Check to see if we caught the safepoint code in the process + // of write protecting the memory serialization page. It write + // enables the page immediately after protecting it so we can + // just return to retry the write. + if ((sig == SIGSEGV || sig == SIGBUS) && + os::is_memory_serialize_page(thread, (address) info->si_addr)) { + // Block current thread until permission is restored. + os::block_on_serialize_page_trap(); + return true; + } + } + + // signal-chaining + if (os::Bsd::chained_handler(sig, info, ucVoid)) { + return true; + } + + if (!abort_if_unrecognized) { + // caller wants another chance, so give it to him + return false; + } + +#ifndef PRODUCT + if (sig == SIGSEGV) { + fatal("\n#" + "\n# /--------------------\\" + "\n# | segmentation fault |" + "\n# \\---\\ /--------------/" + "\n# /" + "\n# [-] |\\_/| " + "\n# (+)=C |o o|__ " + "\n# | | =-*-=__\\ " + "\n# OOO c_c_(___)"); + } +#endif // !PRODUCT + + const char *fmt = + "caught unhandled signal " INT32_FORMAT " at address " PTR_FORMAT; + char buf[128]; + + sprintf(buf, fmt, sig, info->si_addr); + fatal(buf); +} + +void os::Bsd::init_thread_fpu_state(void) { + // Nothing to do +} + +#ifndef _ALLBSD_SOURCE +int os::Bsd::get_fpu_control_word() { + ShouldNotCallThis(); +} + +void os::Bsd::set_fpu_control_word(int fpu) { + ShouldNotCallThis(); +} +#endif + +bool os::is_allocatable(size_t bytes) { +#ifdef _LP64 + return true; +#else + if (bytes < 2 * G) { + return true; + } + + char* addr = reserve_memory(bytes, NULL); + + if (addr != NULL) { + release_memory(addr, bytes); + } + + return addr != NULL; +#endif // _LP64 +} + +/////////////////////////////////////////////////////////////////////////////// +// thread stack + +size_t os::Bsd::min_stack_allowed = 64 * K; + +bool os::Bsd::supports_variable_stack_size() { + return true; +} + +size_t os::Bsd::default_stack_size(os::ThreadType thr_type) { +#ifdef _LP64 + size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M); +#else + size_t s = (thr_type == os::compiler_thread ? 2 * M : 512 * K); +#endif // _LP64 + return s; +} + +size_t os::Bsd::default_guard_size(os::ThreadType thr_type) { + // Only enable glibc guard pages for non-Java threads + // (Java threads have HotSpot guard pages) + return (thr_type == java_thread ? 0 : page_size()); +} + +static void current_stack_region(address *bottom, size_t *size) { + address stack_bottom; + address stack_top; + size_t stack_bytes; + +#ifdef __APPLE__ + pthread_t self = pthread_self(); + stack_top = (address) pthread_get_stackaddr_np(self); + stack_bytes = pthread_get_stacksize_np(self); + stack_bottom = stack_top - stack_bytes; +#elif defined(__OpenBSD__) + stack_t ss; + int rslt = pthread_stackseg_np(pthread_self(), &ss); + + if (rslt != 0) + fatal(err_msg("pthread_stackseg_np failed with err = " INT32_FORMAT, + rslt)); + + stack_top = (address) ss.ss_sp; + stack_bytes = ss.ss_size; + stack_bottom = stack_top - stack_bytes; +#elif defined(_ALLBSD_SOURCE) + pthread_attr_t attr; + + int rslt = pthread_attr_init(&attr); + + // JVM needs to know exact stack location, abort if it fails + if (rslt != 0) + fatal(err_msg("pthread_attr_init failed with err = " INT32_FORMAT, rslt)); + + rslt = pthread_attr_get_np(pthread_self(), &attr); + + if (rslt != 0) + fatal(err_msg("pthread_attr_get_np failed with err = " INT32_FORMAT, + rslt)); + + if (pthread_attr_getstackaddr(&attr, (void **) &stack_bottom) != 0 || + pthread_attr_getstacksize(&attr, &stack_bytes) != 0) { + fatal("Can not locate current stack attributes!"); + } + + pthread_attr_destroy(&attr); + + stack_top = stack_bottom + stack_bytes; +#else /* Linux */ + pthread_attr_t attr; + int res = pthread_getattr_np(pthread_self(), &attr); + if (res != 0) { + if (res == ENOMEM) { + vm_exit_out_of_memory(0, "pthread_getattr_np"); + } + else { + fatal(err_msg("pthread_getattr_np failed with errno = " INT32_FORMAT, + res)); + } + } + + res = pthread_attr_getstack(&attr, (void **) &stack_bottom, &stack_bytes); + if (res != 0) { + fatal(err_msg("pthread_attr_getstack failed with errno = " INT32_FORMAT, + res)); + } + stack_top = stack_bottom + stack_bytes; + + // The block of memory returned by pthread_attr_getstack() includes + // guard pages where present. We need to trim these off. + size_t page_bytes = os::Bsd::page_size(); + assert(((intptr_t) stack_bottom & (page_bytes - 1)) == 0, "unaligned stack"); + + size_t guard_bytes; + res = pthread_attr_getguardsize(&attr, &guard_bytes); + if (res != 0) { + fatal(err_msg( + "pthread_attr_getguardsize failed with errno = " INT32_FORMAT, res)); + } + int guard_pages = align_size_up(guard_bytes, page_bytes) / page_bytes; + assert(guard_bytes == guard_pages * page_bytes, "unaligned guard"); + +#ifdef IA64 + // IA64 has two stacks sharing the same area of memory, a normal + // stack growing downwards and a register stack growing upwards. + // Guard pages, if present, are in the centre. This code splits + // the stack in two even without guard pages, though in theory + // there's nothing to stop us allocating more to the normal stack + // or more to the register stack if one or the other were found + // to grow faster. + int total_pages = align_size_down(stack_bytes, page_bytes) / page_bytes; + stack_bottom += (total_pages - guard_pages) / 2 * page_bytes; +#endif // IA64 + + stack_bottom += guard_bytes; + + pthread_attr_destroy(&attr); + + // The initial thread has a growable stack, and the size reported + // by pthread_attr_getstack is the maximum size it could possibly + // be given what currently mapped. This can be huge, so we cap it. + if (os::Bsd::is_initial_thread()) { + stack_bytes = stack_top - stack_bottom; + + if (stack_bytes > JavaThread::stack_size_at_create()) + stack_bytes = JavaThread::stack_size_at_create(); + + stack_bottom = stack_top - stack_bytes; + } +#endif + + assert(os::current_stack_pointer() >= stack_bottom, "should do"); + assert(os::current_stack_pointer() < stack_top, "should do"); + + *bottom = stack_bottom; + *size = stack_top - stack_bottom; +} + +address os::current_stack_base() { + address bottom; + size_t size; + current_stack_region(&bottom, &size); + return bottom + size; +} + +size_t os::current_stack_size() { + // stack size includes normal stack and HotSpot guard pages + address bottom; + size_t size; + current_stack_region(&bottom, &size); + return size; +} + +///////////////////////////////////////////////////////////////////////////// +// helper functions for fatal error handler + +void os::print_context(outputStream* st, void* context) { + ShouldNotCallThis(); +} + +void os::print_register_info(outputStream *st, void *context) { + ShouldNotCallThis(); +} + +///////////////////////////////////////////////////////////////////////////// +// Stubs for things that would be in bsd_zero.s if it existed. +// You probably want to disassemble these monkeys to check they're ok. + +extern "C" { + int SpinPause() { + } + + int SafeFetch32(int *adr, int errValue) { + int value = errValue; + value = *adr; + return value; + } + intptr_t SafeFetchN(intptr_t *adr, intptr_t errValue) { + intptr_t value = errValue; + value = *adr; + return value; + } + + void _Copy_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) { + if (from > to) { + jshort *end = from + count; + while (from < end) + *(to++) = *(from++); + } + else if (from < to) { + jshort *end = from; + from += count - 1; + to += count - 1; + while (from >= end) + *(to--) = *(from--); + } + } + void _Copy_conjoint_jints_atomic(jint* from, jint* to, size_t count) { + if (from > to) { + jint *end = from + count; + while (from < end) + *(to++) = *(from++); + } + else if (from < to) { + jint *end = from; + from += count - 1; + to += count - 1; + while (from >= end) + *(to--) = *(from--); + } + } + void _Copy_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) { + if (from > to) { + jlong *end = from + count; + while (from < end) + os::atomic_copy64(from++, to++); + } + else if (from < to) { + jlong *end = from; + from += count - 1; + to += count - 1; + while (from >= end) + os::atomic_copy64(from--, to--); + } + } + + void _Copy_arrayof_conjoint_bytes(HeapWord* from, + HeapWord* to, + size_t count) { + memmove(to, from, count); + } + void _Copy_arrayof_conjoint_jshorts(HeapWord* from, + HeapWord* to, + size_t count) { + memmove(to, from, count * 2); + } + void _Copy_arrayof_conjoint_jints(HeapWord* from, + HeapWord* to, + size_t count) { + memmove(to, from, count * 4); + } + void _Copy_arrayof_conjoint_jlongs(HeapWord* from, + HeapWord* to, + size_t count) { + memmove(to, from, count * 8); + } +}; + +///////////////////////////////////////////////////////////////////////////// +// Implementations of atomic operations not supported by processors. +// -- http://gcc.gnu.org/onlinedocs/gcc-4.2.1/gcc/Atomic-Builtins.html + +#ifndef _LP64 +extern "C" { + long long unsigned int __sync_val_compare_and_swap_8( + volatile void *ptr, + long long unsigned int oldval, + long long unsigned int newval) { + ShouldNotCallThis(); + } +}; +#endif // !_LP64
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_zero/vm/os_bsd_zero.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2007, 2008, 2010 Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_BSD_ZERO_VM_OS_BSD_ZERO_HPP +#define OS_CPU_BSD_ZERO_VM_OS_BSD_ZERO_HPP + + static void setup_fpu() {} + + static bool is_allocatable(size_t bytes); + + // Used to register dynamic code cache area with the OS + // Note: Currently only used in 64 bit Windows implementations + static bool register_code_area(char *low, char *high) { return true; } + + // Atomically copy 64 bits of data + static void atomic_copy64(volatile void *src, volatile void *dst) { +#if defined(PPC) && !defined(_LP64) + double tmp; + asm volatile ("lfd %0, 0(%1)\n" + "stfd %0, 0(%2)\n" + : "=f"(tmp) + : "b"(src), "b"(dst)); +#elif defined(S390) && !defined(_LP64) + double tmp; + asm volatile ("ld %0, 0(%1)\n" + "std %0, 0(%2)\n" + : "=r"(tmp) + : "a"(src), "a"(dst)); +#else + *(jlong *) dst = *(jlong *) src; +#endif + } + +#endif // OS_CPU_BSD_ZERO_VM_OS_BSD_ZERO_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_zero/vm/prefetch_bsd_zero.inline.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2007, 2008 Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_BSD_ZERO_VM_PREFETCH_BSD_ZERO_INLINE_HPP +#define OS_CPU_BSD_ZERO_VM_PREFETCH_BSD_ZERO_INLINE_HPP + +#include "runtime/prefetch.hpp" + +inline void Prefetch::read(void* loc, intx interval) { +} + +inline void Prefetch::write(void* loc, intx interval) { +} + +#endif // OS_CPU_BSD_ZERO_VM_PREFETCH_BSD_ZERO_INLINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_zero/vm/threadLS_bsd_zero.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2007 Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "runtime/threadLocalStorage.hpp" +#include "thread_bsd.inline.hpp" + +void ThreadLocalStorage::generate_code_for_get_thread() { + // nothing to do +} + +void ThreadLocalStorage::pd_init() { + // nothing to do +} + +void ThreadLocalStorage::pd_set_thread(Thread* thread) { + os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_zero/vm/threadLS_bsd_zero.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_BSD_ZERO_VM_THREADLS_BSD_ZERO_HPP +#define OS_CPU_BSD_ZERO_VM_THREADLS_BSD_ZERO_HPP + +// Processor dependent parts of ThreadLocalStorage + + public: + static Thread* thread() { + return (Thread*) os::thread_local_storage_at(thread_index()); + } + +#endif // OS_CPU_BSD_ZERO_VM_THREADLS_BSD_ZERO_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_zero/vm/thread_bsd_zero.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2009, 2010 Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "runtime/frame.inline.hpp" +#include "thread_bsd.inline.hpp" + +void JavaThread::cache_global_variables() { + // nothing to do +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_zero/vm/thread_bsd_zero.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_BSD_ZERO_VM_THREAD_BSD_ZERO_HPP +#define OS_CPU_BSD_ZERO_VM_THREAD_BSD_ZERO_HPP + + private: + ZeroStack _zero_stack; + ZeroFrame* _top_zero_frame; + + void pd_initialize() { + _top_zero_frame = NULL; + } + + public: + ZeroStack *zero_stack() { + return &_zero_stack; + } + + public: + ZeroFrame *top_zero_frame() { + return _top_zero_frame; + } + void push_zero_frame(ZeroFrame *frame) { + *(ZeroFrame **) frame = _top_zero_frame; + _top_zero_frame = frame; + } + void pop_zero_frame() { + zero_stack()->set_sp((intptr_t *) _top_zero_frame + 1); + _top_zero_frame = *(ZeroFrame **) _top_zero_frame; + } + + public: + static ByteSize zero_stack_offset() { + return byte_offset_of(JavaThread, _zero_stack); + } + static ByteSize top_zero_frame_offset() { + return byte_offset_of(JavaThread, _top_zero_frame); + } + + public: + void record_base_of_stack_pointer() { + assert(top_zero_frame() == NULL, "junk on stack prior to Java call"); + } + void set_base_of_stack_pointer(intptr_t* base_sp) { + assert(base_sp == NULL, "should be"); + assert(top_zero_frame() == NULL, "junk on stack after Java call"); + } + + public: + void set_last_Java_frame() { + set_last_Java_frame(top_zero_frame(), zero_stack()->sp()); + } + void reset_last_Java_frame() { + frame_anchor()->zap(); + } + void set_last_Java_frame(ZeroFrame* fp, intptr_t* sp) { + frame_anchor()->set(sp, NULL, fp); + } + + public: + ZeroFrame* last_Java_fp() { + return frame_anchor()->last_Java_fp(); + } + + private: + frame pd_last_frame() { + assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); + return frame(last_Java_fp(), last_Java_sp()); + } + + public: + static ByteSize last_Java_fp_offset() { + return byte_offset_of(JavaThread, _anchor) + + JavaFrameAnchor::last_Java_fp_offset(); + } + + public: + // Check for pending suspend requests and pending asynchronous + // exceptions. There are separate accessors for these, but + // _suspend_flags is volatile so using them would be unsafe. + bool has_special_condition_for_native_trans() { + return _suspend_flags != 0; + } + + public: + bool pd_get_top_frame_for_signal_handler(frame* fr_addr, + void* ucontext, + bool isInJava) { + ShouldNotCallThis(); + } + + // These routines are only used on cpu architectures that + // have separate register stacks (Itanium). + static bool register_stack_overflow() { return false; } + static void enable_register_stack_guard() {} + static void disable_register_stack_guard() {} + +#endif // OS_CPU_BSD_ZERO_VM_THREAD_BSD_ZERO_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_zero/vm/vmStructs_bsd_zero.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2007 Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 OS_CPU_BSD_ZERO_VM_VMSTRUCTS_BSD_ZERO_HPP +#define OS_CPU_BSD_ZERO_VM_VMSTRUCTS_BSD_ZERO_HPP + +// These are the OS and CPU-specific fields, types and integer +// constants required by the Serviceability Agent. This file is +// referenced by vmStructs.cpp. + +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ + /* This must be the last entry, and must be present */ \ + last_entry() + + +#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, last_entry) \ + /* This must be the last entry, and must be present */ \ + last_entry() + +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ + /* This must be the last entry, and must be present */ \ + last_entry() + +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ + /* This must be the last entry, and must be present */ \ + last_entry() + +#endif // OS_CPU_BSD_ZERO_VM_VMSTRUCTS_BSD_ZERO_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_cpu/bsd_zero/vm/vm_version_bsd_zero.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2009 Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 "runtime/os.hpp" +#include "vm_version_zero.hpp" + +// This file is intentionally empty
--- a/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -38,7 +38,6 @@ #else define_pd_global(intx, VMThreadStackSize, 512); #endif // _LP64 -define_pd_global(intx, SurvivorRatio, 8); define_pd_global(intx, CompilerThreadStackSize, 0); define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
--- a/src/os_cpu/windows_x86/vm/copy_windows_x86.inline.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/os_cpu/windows_x86/vm/copy_windows_x86.inline.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -85,13 +85,35 @@ } static void pd_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) { - // FIXME - (void)memmove(to, from, count << LogBytesPerShort); + if (from > to) { + while (count-- > 0) { + // Copy forwards + *to++ = *from++; + } + } else { + from += count - 1; + to += count - 1; + while (count-- > 0) { + // Copy backwards + *to-- = *from--; + } + } } static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) { - // FIXME - (void)memmove(to, from, count << LogBytesPerInt); + if (from > to) { + while (count-- > 0) { + // Copy forwards + *to++ = *from++; + } + } else { + from += count - 1; + to += count - 1; + while (count-- > 0) { + // Copy backwards + *to-- = *from--; + } + } } static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -37,6 +37,8 @@ private int receiver_count; private String reason; private List<CallSite> calls; + private int endNodes; + private double timeStamp; CallSite() { } @@ -93,18 +95,22 @@ emit(stream, indent); String m = getMethod().getHolder().replace('/', '.') + "::" + getMethod().getName(); if (getReason() == null) { - stream.println(" @ " + getBci() + " " + m + " (" + getMethod().getBytes() + " bytes)"); + stream.print(" @ " + getBci() + " " + m + " (" + getMethod().getBytes() + " bytes)"); } else { if (isCompat()) { - stream.println(" @ " + getBci() + " " + m + " " + getReason()); + stream.print(" @ " + getBci() + " " + m + " " + getReason()); } else { - stream.println("- @ " + getBci() + " " + m + + stream.print("- @ " + getBci() + " " + m + " (" + getMethod().getBytes() + " bytes) " + getReason()); } } + if (getEndNodes() > 0) { + stream.printf(" (end time: %6.4f nodes: %d)", getTimeStamp(), getEndNodes()); + } + stream.println(""); if (getReceiver() != null) { - emit(stream, indent + 3); + emit(stream, indent + 4); // stream.println("type profile " + method.holder + " -> " + receiver + " (" + // receiver_count + "/" + count + "," + (receiver_count * 100 / count) + "%)"); stream.println("type profile " + getMethod().getHolder() + " -> " + getReceiver() + " (" + @@ -180,4 +186,21 @@ public static void setCompat(boolean aCompat) { compat = aCompat; } + + void setEndNodes(int n) { + endNodes = n; + } + + public int getEndNodes() { + return endNodes; + } + + void setTimeStamp(double time) { + timeStamp = time; + } + + public double getTimeStamp() { + return timeStamp; + } + }
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -126,7 +126,6 @@ maxattempts = Math.max(maxattempts,c.getAttempts()); elapsed += c.getElapsedTime(); for (Phase phase : c.getPhases()) { - out.printf("\t%s %6.4f\n", phase.getName(), phase.getElapsedTime()); Double v = phaseTime.get(phase.getName()); if (v == null) { v = Double.valueOf(0.0); @@ -138,6 +137,7 @@ v2 = Integer.valueOf(0); } phaseNodes.put(phase.getName(), Integer.valueOf(v2.intValue() + phase.getNodes())); + out.printf("\t%s %6.4f %d %d\n", phase.getName(), phase.getElapsedTime(), phase.getStartNodes(), phase.getNodes()); } } else if (e instanceof MakeNotEntrantEvent) { MakeNotEntrantEvent mne = (MakeNotEntrantEvent) e;
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -365,7 +365,7 @@ if (currentTrap != null) { currentTrap.addJVMS(atts.getValue("method"), Integer.parseInt(atts.getValue("bci"))); } else { - System.err.println("Missing uncommon_trap for jvms"); + // Ignore <eliminate_allocation type='667'> and <eliminate_lock lock='1'> } } else if (qname.equals("nmethod")) { String id = makeId(atts); @@ -391,6 +391,11 @@ throw new InternalError("call site and parse don't match"); } } + } else if (qname.equals("parse_done")) { + CallSite call = scopes.pop(); + call.setEndNodes(Integer.parseInt(search(atts, "nodes"))); + call.setTimeStamp(Double.parseDouble(search(atts, "stamp"))); + scopes.push(call); } }
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -37,7 +37,7 @@ } int getNodes() { - return getStartNodes(); + return getEndNodes() - getStartNodes(); } void setEndNodes(int n) {
--- a/src/share/vm/adlc/adlc.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/adlc/adlc.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -67,9 +67,9 @@ #endif #endif // _WIN32 -#ifdef LINUX +#if defined(LINUX) || defined(_ALLBSD_SOURCE) #include <inttypes.h> -#endif // LINUX +#endif // LINUX || _ALLBSD_SOURCE // Macros #define uint32 unsigned int
--- a/src/share/vm/adlc/formssel.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/adlc/formssel.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -1225,7 +1225,7 @@ // Handle special constant table variables. if (strcmp(rep_var, "constanttablebase") == 0) { fprintf(fp, "char reg[128]; ra->dump_register(in(mach_constant_base_node_input()), reg);\n"); - fprintf(fp, "st->print(\"%%s\");\n"); + fprintf(fp, " st->print(\"%%s\", reg);\n"); return; } if (strcmp(rep_var, "constantoffset") == 0) {
--- a/src/share/vm/c1/c1_GraphBuilder.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -1165,11 +1165,11 @@ Goto *x = new Goto(block_at(to_bci), to_bci <= from_bci); if (is_profiling()) { compilation()->set_would_profile(true); - } - if (profile_branches()) { - x->set_profiled_method(method()); x->set_profiled_bci(bci()); - x->set_should_profile(true); + if (profile_branches()) { + x->set_profiled_method(method()); + x->set_should_profile(true); + } } append(x); } @@ -1203,9 +1203,9 @@ Goto *goto_node = i->as_Goto(); if (goto_node != NULL) { compilation()->set_would_profile(true); + goto_node->set_profiled_bci(bci()); if (profile_branches()) { goto_node->set_profiled_method(method()); - goto_node->set_profiled_bci(bci()); goto_node->set_should_profile(true); // Find out which successor is used. if (goto_node->default_sux() == tsux) {
--- a/src/share/vm/c1/c1_LIR.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/c1/c1_LIR.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -1394,8 +1394,15 @@ } -void LIR_List::store_check(LIR_Opr object, LIR_Opr array, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, CodeEmitInfo* info_for_exception) { - append(new LIR_OpTypeCheck(lir_store_check, object, array, tmp1, tmp2, tmp3, info_for_exception)); +void LIR_List::store_check(LIR_Opr object, LIR_Opr array, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, + CodeEmitInfo* info_for_exception, ciMethod* profiled_method, int profiled_bci) { + LIR_OpTypeCheck* c = new LIR_OpTypeCheck(lir_store_check, object, array, tmp1, tmp2, tmp3, info_for_exception); + if (profiled_method != NULL) { + c->set_profiled_method(profiled_method); + c->set_profiled_bci(profiled_bci); + c->set_should_profile(true); + } + append(c); }
--- a/src/share/vm/c1/c1_LIR.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/c1/c1_LIR.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -2100,7 +2100,7 @@ void fpop_raw() { append(new LIR_Op0(lir_fpop_raw)); } void instanceof(LIR_Opr result, LIR_Opr object, ciKlass* klass, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, bool fast_check, CodeEmitInfo* info_for_patch, ciMethod* profiled_method, int profiled_bci); - void store_check(LIR_Opr object, LIR_Opr array, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, CodeEmitInfo* info_for_exception); + void store_check(LIR_Opr object, LIR_Opr array, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, CodeEmitInfo* info_for_exception, ciMethod* profiled_method, int profiled_bci); void checkcast (LIR_Opr result, LIR_Opr object, ciKlass* klass, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, bool fast_check,
--- a/src/share/vm/c1/c1_LIRGenerator.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -2493,7 +2493,7 @@ // increment backedge counter if needed CodeEmitInfo* info = state_for(x, state); - increment_backedge_counter(info, info->stack()->bci()); + increment_backedge_counter(info, x->profiled_bci()); CodeEmitInfo* safepoint_info = state_for(x, state); __ safepoint(safepoint_poll_register(), safepoint_info); } @@ -2970,8 +2970,8 @@ // accessors are also always mature. if (!x->inlinee()->is_accessor()) { CodeEmitInfo* info = state_for(x, x->state(), true); - // Increment invocation counter, don't notify the runtime, because we don't inline loops, - increment_event_counter_impl(info, x->inlinee(), 0, InvocationEntryBci, false, false); + // Notify the runtime very infrequently only to take care of counter overflows + increment_event_counter_impl(info, x->inlinee(), (1 << Tier23InlineeNotifyFreqLog) - 1, InvocationEntryBci, false, true); } }
--- a/src/share/vm/c1/c1_LinearScan.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/c1/c1_LinearScan.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -2619,6 +2619,24 @@ Location::Type loc_type = float_saved_as_double ? Location::float_in_dbl : Location::normal; VMReg rname = frame_map()->fpu_regname(opr->fpu_regnr()); +#ifndef __SOFTFP__ +#ifndef VM_LITTLE_ENDIAN + if (! float_saved_as_double) { + // On big endian system, we may have an issue if float registers use only + // the low half of the (same) double registers. + // Both the float and the double could have the same regnr but would correspond + // to two different addresses once saved. + + // get next safely (no assertion checks) + VMReg next = VMRegImpl::as_VMReg(1+rname->value()); + if (next->is_reg() && + (next->as_FloatRegister() == rname->as_FloatRegister())) { + // the back-end does use the same numbering for the double and the float + rname = next; // VMReg for the low bits, e.g. the real VMReg for the float + } + } +#endif +#endif LocationValue* sv = new LocationValue(Location::new_reg_loc(loc_type, rname)); scope_values->append(sv);
--- a/src/share/vm/c1/c1_globals.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/c1/c1_globals.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -47,6 +47,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "c1_globals_windows.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "c1_globals_bsd.hpp" +#endif // // Defines all global flags used by the client compiler.
--- a/src/share/vm/ci/ciEnv.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/ci/ciEnv.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -473,6 +473,7 @@ } if (require_local) return NULL; + // Not yet loaded into the VM, or not governed by loader constraints. // Make a CI representative for it. return get_unloaded_klass(accessing_klass, name); @@ -498,7 +499,7 @@ bool& is_accessible, ciInstanceKlass* accessor) { EXCEPTION_CONTEXT; - KlassHandle klass (THREAD, constantPoolOopDesc::klass_at_if_loaded(cpool, index)); + KlassHandle klass(THREAD, constantPoolOopDesc::klass_at_if_loaded(cpool, index)); Symbol* klass_name = NULL; if (klass.is_null()) { // The klass has not been inserted into the constant pool. @@ -785,17 +786,17 @@ // Either the declared holder was not loaded, or the method could // not be found. Create a dummy ciMethod to represent the failed // lookup. - - return get_unloaded_method(declared_holder, - get_symbol(name_sym), - get_symbol(sig_sym)); + ciSymbol* name = get_symbol(name_sym); + ciSymbol* signature = get_symbol(sig_sym); + return get_unloaded_method(declared_holder, name, signature, accessor); } // ------------------------------------------------------------------ // ciEnv::get_fake_invokedynamic_method_impl ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool, - int index, Bytecodes::Code bc) { + int index, Bytecodes::Code bc, + ciInstanceKlass* accessor) { // Compare the following logic with InterpreterRuntime::resolve_invokedynamic. assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic"); @@ -807,9 +808,10 @@ // Call site might not be resolved yet. We could create a real invoker method from the // compiler, but it is simpler to stop the code path here with an unlinked method. if (!is_resolved) { - ciInstanceKlass* mh_klass = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass(); - ciSymbol* sig_sym = get_symbol(cpool->signature_ref_at(index)); - return get_unloaded_method(mh_klass, ciSymbol::invokeExact_name(), sig_sym); + ciInstanceKlass* holder = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass(); + ciSymbol* name = ciSymbol::invokeExact_name(); + ciSymbol* signature = get_symbol(cpool->signature_ref_at(index)); + return get_unloaded_method(holder, name, signature, accessor); } // Get the invoker methodOop from the constant pool. @@ -850,9 +852,9 @@ int index, Bytecodes::Code bc, ciInstanceKlass* accessor) { if (bc == Bytecodes::_invokedynamic) { - GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(cpool, index, bc);) + GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(cpool, index, bc, accessor);) } else { - GUARDED_VM_ENTRY(return get_method_by_index_impl(cpool, index, bc, accessor);) + GUARDED_VM_ENTRY(return get_method_by_index_impl( cpool, index, bc, accessor);) } } @@ -910,27 +912,37 @@ // dependencies were inserted. Any violated dependences in this // case are dumped to the tty. bool counter_changed = system_dictionary_modification_counter_changed(); - bool test_deps = counter_changed; - DEBUG_ONLY(test_deps = true); - if (!test_deps) return; - bool print_failures = false; - DEBUG_ONLY(print_failures = !counter_changed); - bool keep_going = (print_failures || xtty != NULL); + bool verify_deps = trueInDebug; + if (!counter_changed && !verify_deps) return; + int klass_violations = 0; - for (Dependencies::DepStream deps(dependencies()); deps.next(); ) { if (!deps.is_klass_type()) continue; // skip non-klass dependencies klassOop witness = deps.check_dependency(); if (witness != NULL) { klass_violations++; - if (print_failures) deps.print_dependency(witness, /*verbose=*/ true); + if (!counter_changed) { + // Dependence failed but counter didn't change. Log a message + // describing what failed and allow the assert at the end to + // trigger. + deps.print_dependency(witness); + } else if (xtty == NULL) { + // If we're not logging then a single violation is sufficient, + // otherwise we want to log all the dependences which were + // violated. + break; + } } - // If there's no log and we're not sanity-checking, we're done. - if (!keep_going) break; } if (klass_violations != 0) { +#ifdef ASSERT + if (!counter_changed && !PrintCompilation) { + // Print out the compile task that failed + _task->print_line(); + } +#endif assert(counter_changed, "failed dependencies, but counter didn't change"); record_failure("concurrent class loading"); }
--- a/src/share/vm/ci/ciEnv.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/ci/ciEnv.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -153,7 +153,8 @@ int method_index, Bytecodes::Code bc, ciInstanceKlass* loading_klass); ciMethod* get_fake_invokedynamic_method_impl(constantPoolHandle cpool, - int index, Bytecodes::Code bc); + int index, Bytecodes::Code bc, + ciInstanceKlass* accessor); // Helper methods bool check_klass_accessibility(ciKlass* accessing_klass, @@ -192,13 +193,14 @@ // the result. ciMethod* get_unloaded_method(ciInstanceKlass* holder, ciSymbol* name, - ciSymbol* signature) { - return _factory->get_unloaded_method(holder, name, signature); + ciSymbol* signature, + ciInstanceKlass* accessor) { + return _factory->get_unloaded_method(holder, name, signature, accessor); } // Get a ciKlass representing an unloaded klass. // Ensures uniqueness of the result. - ciKlass* get_unloaded_klass(ciKlass* accessing_klass, + ciKlass* get_unloaded_klass(ciKlass* accessing_klass, ciSymbol* name) { return _factory->get_unloaded_klass(accessing_klass, name, true); } @@ -224,7 +226,7 @@ // See if we already have an unloaded klass for the given name // or return NULL if not. - ciKlass *check_get_unloaded_klass(ciKlass* accessing_klass, ciSymbol* name) { + ciKlass *check_get_unloaded_klass(ciKlass* accessing_klass, ciSymbol* name) { return _factory->get_unloaded_klass(accessing_klass, name, false); }
--- a/src/share/vm/ci/ciMethod.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/ci/ciMethod.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -148,21 +148,27 @@ // // Unloaded method. ciMethod::ciMethod(ciInstanceKlass* holder, - ciSymbol* name, - ciSymbol* signature) : ciObject(ciMethodKlass::make()) { - // These fields are always filled in. - _name = name; - _holder = holder; - _signature = new (CURRENT_ENV->arena()) ciSignature(_holder, constantPoolHandle(), signature); - _intrinsic_id = vmIntrinsics::_none; - _liveness = NULL; - _can_be_statically_bound = false; - _method_blocks = NULL; - _method_data = NULL; + ciSymbol* name, + ciSymbol* signature, + ciInstanceKlass* accessor) : + ciObject(ciMethodKlass::make()), + _name( name), + _holder( holder), + _intrinsic_id( vmIntrinsics::_none), + _liveness( NULL), + _can_be_statically_bound(false), + _method_blocks( NULL), + _method_data( NULL) #if defined(COMPILER2) || defined(SHARK) - _flow = NULL; - _bcea = NULL; + , + _flow( NULL), + _bcea( NULL) #endif // COMPILER2 || SHARK +{ + // Usually holder and accessor are the same type but in some cases + // the holder has the wrong class loader (e.g. invokedynamic call + // sites) so we pass the accessor. + _signature = new (CURRENT_ENV->arena()) ciSignature(accessor, constantPoolHandle(), signature); }
--- a/src/share/vm/ci/ciMethod.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/ci/ciMethod.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -88,7 +88,7 @@ #endif ciMethod(methodHandle h_m); - ciMethod(ciInstanceKlass* holder, ciSymbol* name, ciSymbol* signature); + ciMethod(ciInstanceKlass* holder, ciSymbol* name, ciSymbol* signature, ciInstanceKlass* accessor); methodOop get_methodOop() const { methodOop m = (methodOop)get_oop();
--- a/src/share/vm/ci/ciObjectFactory.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/ci/ciObjectFactory.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -374,20 +374,32 @@ // unloaded method. This may need to change. ciMethod* ciObjectFactory::get_unloaded_method(ciInstanceKlass* holder, ciSymbol* name, - ciSymbol* signature) { - for (int i=0; i<_unloaded_methods->length(); i++) { + ciSymbol* signature, + ciInstanceKlass* accessor) { + ciSignature* that = NULL; + for (int i = 0; i < _unloaded_methods->length(); i++) { ciMethod* entry = _unloaded_methods->at(i); if (entry->holder()->equals(holder) && entry->name()->equals(name) && entry->signature()->as_symbol()->equals(signature)) { - // We've found a match. - return entry; + // Short-circuit slow resolve. + if (entry->signature()->accessing_klass() == accessor) { + // We've found a match. + return entry; + } else { + // Lazily create ciSignature + if (that == NULL) that = new (arena()) ciSignature(accessor, constantPoolHandle(), signature); + if (entry->signature()->equals(that)) { + // We've found a match. + return entry; + } + } } } // This is a new unloaded method. Create it and stick it in // the cache. - ciMethod* new_method = new (arena()) ciMethod(holder, name, signature); + ciMethod* new_method = new (arena()) ciMethod(holder, name, signature, accessor); init_ident_of(new_method); _unloaded_methods->append(new_method);
--- a/src/share/vm/ci/ciObjectFactory.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/ci/ciObjectFactory.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -108,7 +108,8 @@ // Get the ciMethod representing an unloaded/unfound method. ciMethod* get_unloaded_method(ciInstanceKlass* holder, ciSymbol* name, - ciSymbol* signature); + ciSymbol* signature, + ciInstanceKlass* accessor); // Get a ciKlass representing an unloaded klass. ciKlass* get_unloaded_klass(ciKlass* accessing_klass,
--- a/src/share/vm/ci/ciSignature.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/ci/ciSignature.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -80,7 +80,7 @@ } // ------------------------------------------------------------------ -// ciSignature::return_ciType +// ciSignature::return_type // // What is the return type of this signature? ciType* ciSignature::return_type() const { @@ -88,7 +88,7 @@ } // ------------------------------------------------------------------ -// ciSignature::ciType_at +// ciSignature::type_at // // What is the type of the index'th element of this // signature? @@ -99,6 +99,24 @@ } // ------------------------------------------------------------------ +// ciSignature::equals +// +// Compare this signature to another one. Signatures with different +// accessing classes but with signature-types resolved to the same +// types are defined to be equal. +bool ciSignature::equals(ciSignature* that) { + // Compare signature + if (!this->as_symbol()->equals(that->as_symbol())) return false; + // Compare all types of the arguments + for (int i = 0; i < _count; i++) { + if (this->type_at(i) != that->type_at(i)) return false; + } + // Compare the return type + if (this->return_type() != that->return_type()) return false; + return true; +} + +// ------------------------------------------------------------------ // ciSignature::print_signature void ciSignature::print_signature() { _symbol->print_symbol();
--- a/src/share/vm/ci/ciSignature.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/ci/ciSignature.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -43,6 +43,7 @@ int _count; friend class ciMethod; + friend class ciObjectFactory; ciSignature(ciKlass* accessing_klass, constantPoolHandle cpool, ciSymbol* signature); @@ -52,6 +53,7 @@ public: ciSymbol* as_symbol() const { return _symbol; } + ciKlass* accessing_klass() const { return _accessing_klass; } ciType* return_type() const; ciType* type_at(int index) const; @@ -59,6 +61,8 @@ int size() const { return _size; } int count() const { return _count; } + bool equals(ciSignature* that); + void print_signature(); void print(); };
--- a/src/share/vm/classfile/classLoader.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/classfile/classLoader.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -68,6 +68,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif // Entry points in zip.dll for loading zip/jar file entries
--- a/src/share/vm/classfile/javaClasses.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/classfile/javaClasses.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -58,6 +58,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #define INJECTED_FIELD_COMPUTE_OFFSET(klass, name, signature, may_be_java) \ klass::_##name##_offset = JavaClasses::compute_injected_offset(JavaClasses::klass##_##name##_enum); @@ -500,12 +503,8 @@ if (SystemDictionary::Class_klass_loaded() && (k->oop_is_instance() || k->oop_is_javaArray())) { // Allocate mirror (java.lang.Class instance) Handle mirror = instanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK_0); - // Setup indirections - mirror->obj_field_put(_klass_offset, k()); - k->set_java_mirror(mirror()); instanceMirrorKlass* mk = instanceMirrorKlass::cast(mirror->klass()); - java_lang_Class::set_oop_size(mirror(), mk->instance_size(k)); java_lang_Class::set_static_oop_field_count(mirror(), mk->compute_static_oop_field_count(mirror())); // It might also have a component mirror. This mirror must already exist. @@ -568,9 +567,10 @@ assert(aklass != NULL, "correct bootstrap"); set_array_klass(java_class, aklass); } +#ifdef ASSERT instanceMirrorKlass* mk = instanceMirrorKlass::cast(SystemDictionary::Class_klass()); - java_lang_Class::set_oop_size(java_class, mk->instance_size(oop(NULL))); - java_lang_Class::set_static_oop_field_count(java_class, 0); + assert(java_lang_Class::static_oop_field_count(java_class) == 0, "should have been zeroed by allocation"); +#endif return java_class; } @@ -584,6 +584,12 @@ } +void java_lang_Class::set_klass(oop java_class, klassOop klass) { + assert(java_lang_Class::is_instance(java_class), "must be a Class object"); + java_class->obj_field_put(_klass_offset, klass); +} + + void java_lang_Class::print_signature(oop java_class, outputStream* st) { assert(java_lang_Class::is_instance(java_class), "must be a Class object"); Symbol* name = NULL; @@ -1145,7 +1151,7 @@ } nmethod* nm = method->code(); if (WizardMode && nm != NULL) { - sprintf(buf + (int)strlen(buf), "(nmethod " PTR_FORMAT ")", (intptr_t)nm); + sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm); } }
--- a/src/share/vm/classfile/javaClasses.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/classfile/javaClasses.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -188,6 +188,7 @@ static oop create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS); // Conversion static klassOop as_klassOop(oop java_class); + static void set_klass(oop java_class, klassOop klass); static BasicType as_BasicType(oop java_class, klassOop* reference_klass = NULL); static BasicType as_BasicType(oop java_class, KlassHandle* reference_klass) { klassOop refk_oop = NULL;
--- a/src/share/vm/classfile/vmSymbols.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/classfile/vmSymbols.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -967,7 +967,8 @@ // Class vmSymbols class vmSymbols: AllStatic { - friend class vmIntrinsics; + friend class vmIntrinsics; + friend class VMStructs; public: // enum for figuring positions and size of array holding Symbol*s enum SID {
--- a/src/share/vm/code/nmethod.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/code/nmethod.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -50,6 +50,7 @@ // Only bother with this argument setup if dtrace is available +#ifndef USDT2 HS_DTRACE_PROBE_DECL8(hotspot, compiled__method__load, const char*, int, const char*, int, const char*, int, void*, size_t); @@ -69,6 +70,21 @@ signature->bytes(), signature->utf8_length()); \ } \ } +#else /* USDT2 */ +#define DTRACE_METHOD_UNLOAD_PROBE(method) \ + { \ + methodOop m = (method); \ + if (m != NULL) { \ + Symbol* klass_name = m->klass_name(); \ + Symbol* name = m->name(); \ + Symbol* signature = m->signature(); \ + HOTSPOT_COMPILED_METHOD_UNLOAD( \ + (char *) klass_name->bytes(), klass_name->utf8_length(), \ + (char *) name->bytes(), name->utf8_length(), \ + (char *) signature->bytes(), signature->utf8_length()); \ + } \ + } +#endif /* USDT2 */ #else // ndef DTRACE_ENABLED @@ -1473,6 +1489,7 @@ void nmethod::post_compiled_method_load_event() { methodOop moop = method(); +#ifndef USDT2 HS_DTRACE_PROBE8(hotspot, compiled__method__load, moop->klass_name()->bytes(), moop->klass_name()->utf8_length(), @@ -1481,6 +1498,16 @@ moop->signature()->bytes(), moop->signature()->utf8_length(), insts_begin(), insts_size()); +#else /* USDT2 */ + HOTSPOT_COMPILED_METHOD_LOAD( + (char *) moop->klass_name()->bytes(), + moop->klass_name()->utf8_length(), + (char *) moop->name()->bytes(), + moop->name()->utf8_length(), + (char *) moop->signature()->bytes(), + moop->signature()->utf8_length(), + insts_begin(), insts_size()); +#endif /* USDT2 */ if (JvmtiExport::should_post_compiled_method_load() || JvmtiExport::should_post_compiled_method_unload()) {
--- a/src/share/vm/code/stubs.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/code/stubs.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif // The classes in this file provide a simple framework for the // management of little pieces of machine code - or stubs -
--- a/src/share/vm/compiler/compileBroker.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/compiler/compileBroker.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -58,6 +58,7 @@ // Only bother with this argument setup if dtrace is available +#ifndef USDT2 HS_DTRACE_PROBE_DECL8(hotspot, method__compile__begin, char*, intptr_t, char*, intptr_t, char*, intptr_t, char*, intptr_t); HS_DTRACE_PROBE_DECL9(hotspot, method__compile__end, @@ -89,6 +90,35 @@ signature->bytes(), signature->utf8_length(), (success)); \ } +#else /* USDT2 */ + +#define DTRACE_METHOD_COMPILE_BEGIN_PROBE(compiler, method) \ + { \ + char* comp_name = (char*)(compiler)->name(); \ + Symbol* klass_name = (method)->klass_name(); \ + Symbol* name = (method)->name(); \ + Symbol* signature = (method)->signature(); \ + HOTSPOT_METHOD_COMPILE_BEGIN( \ + comp_name, strlen(comp_name), \ + (char *) klass_name->bytes(), klass_name->utf8_length(), \ + (char *) name->bytes(), name->utf8_length(), \ + (char *) signature->bytes(), signature->utf8_length()); \ + } + +#define DTRACE_METHOD_COMPILE_END_PROBE(compiler, method, success) \ + { \ + char* comp_name = (char*)(compiler)->name(); \ + Symbol* klass_name = (method)->klass_name(); \ + Symbol* name = (method)->name(); \ + Symbol* signature = (method)->signature(); \ + HOTSPOT_METHOD_COMPILE_END( \ + comp_name, strlen(comp_name), \ + (char *) klass_name->bytes(), klass_name->utf8_length(), \ + (char *) name->bytes(), name->utf8_length(), \ + (char *) signature->bytes(), signature->utf8_length(), (success)); \ + } +#endif /* USDT2 */ + #else // ndef DTRACE_ENABLED #define DTRACE_METHOD_COMPILE_BEGIN_PROBE(compiler, method)
--- a/src/share/vm/compiler/disassembler.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/compiler/disassembler.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif class decode_env;
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -37,6 +37,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif elapsedTimer CMSAdaptiveSizePolicy::_concurrent_timer; elapsedTimer CMSAdaptiveSizePolicy::_STW_timer;
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -50,6 +50,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // // ConcurrentMarkSweepPolicy methods
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -2004,7 +2004,7 @@ ReferenceProcessorMTDiscoveryMutator rp_mut_discovery(ref_processor(), false); ref_processor()->set_enqueuing_is_done(false); - ref_processor()->enable_discovery(); + ref_processor()->enable_discovery(false /*verify_disabled*/, false /*check_no_refs*/); ref_processor()->setup_policy(clear_all_soft_refs); // If an asynchronous collection finishes, the _modUnionTable is // all clear. If we are assuming the collection from an asynchronous @@ -3490,8 +3490,8 @@ MutexLockerEx x(bitMapLock(), Mutex::_no_safepoint_check_flag); checkpointRootsInitialWork(asynch); - rp->verify_no_references_recorded(); - rp->enable_discovery(); // enable ("weak") refs discovery + // enable ("weak") refs discovery + rp->enable_discovery(true /*verify_disabled*/, true /*check_no_refs*/); _collectorState = Marking; } else { // (Weak) Refs discovery: this is controlled from genCollectedHeap::do_collection @@ -3503,7 +3503,8 @@ "ref discovery for this generation kind"); // already have locks checkpointRootsInitialWork(asynch); - rp->enable_discovery(); // now enable ("weak") refs discovery + // now enable ("weak") refs discovery + rp->enable_discovery(true /*verify_disabled*/, false /*verify_no_refs*/); _collectorState = Marking; } SpecializationStats::print();
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -36,6 +36,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif class ConcurrentMarkSweepGeneration; class CMSCollector;
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -33,6 +33,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifndef PRODUCT Mutex* FreeBlockDictionary::par_lock() const {
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -30,11 +30,15 @@ #include "memory/gcLocker.inline.hpp" #include "runtime/interfaceSupport.hpp" #include "utilities/dtrace.hpp" + + +#ifndef USDT2 HS_DTRACE_PROBE_DECL(hs_private, cms__initmark__begin); HS_DTRACE_PROBE_DECL(hs_private, cms__initmark__end); HS_DTRACE_PROBE_DECL(hs_private, cms__remark__begin); HS_DTRACE_PROBE_DECL(hs_private, cms__remark__end); +#endif /* !USDT2 */ ////////////////////////////////////////////////////////// // Methods in abstract class VM_CMS_Operation @@ -129,7 +133,12 @@ // Nothing to do. return; } +#ifndef USDT2 HS_DTRACE_PROBE(hs_private, cms__initmark__begin); +#else /* USDT2 */ + HS_PRIVATE_CMS_INITMARK_BEGIN( + ); +#endif /* USDT2 */ GenCollectedHeap* gch = GenCollectedHeap::heap(); GCCauseSetter gccs(gch, GCCause::_cms_initial_mark); @@ -140,7 +149,12 @@ _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsInitial); VM_CMS_Operation::verify_after_gc(); +#ifndef USDT2 HS_DTRACE_PROBE(hs_private, cms__initmark__end); +#else /* USDT2 */ + HS_PRIVATE_CMS_INITMARK_END( + ); +#endif /* USDT2 */ } ////////////////////////////////////////////////////////// @@ -151,7 +165,12 @@ // Nothing to do. return; } +#ifndef USDT2 HS_DTRACE_PROBE(hs_private, cms__remark__begin); +#else /* USDT2 */ + HS_PRIVATE_CMS_REMARK_BEGIN( + ); +#endif /* USDT2 */ GenCollectedHeap* gch = GenCollectedHeap::heap(); GCCauseSetter gccs(gch, GCCause::_cms_final_remark); @@ -162,7 +181,12 @@ _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsFinal); VM_CMS_Operation::verify_after_gc(); +#ifndef USDT2 HS_DTRACE_PROBE(hs_private, cms__remark__end); +#else /* USDT2 */ + HS_PRIVATE_CMS_REMARK_END( + ); +#endif /* USDT2 */ } // VM operation to invoke a concurrent collection of a
--- a/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -118,30 +118,6 @@ } } -// this is a bit expensive... but we expect that it should not be called -// to often. -void CSetChooserCache::remove(HeapRegion *hr) { - assert(_occupancy > 0, "cache should not be empty"); - assert(hr->sort_index() < -1, "should already be in the cache"); - int index = get_index(hr->sort_index()); - assert(_cache[index] == hr, "index should be correct"); - int next_index = trim_index(index + 1); - int last_index = trim_index(_first + _occupancy - 1); - while (index != last_index) { - assert(_cache[next_index] != NULL, "should not be null"); - _cache[index] = _cache[next_index]; - _cache[index]->set_sort_index(get_sort_index(index)); - - index = next_index; - next_index = trim_index(next_index+1); - } - assert(index == last_index, "should have reached the last one"); - _cache[index] = NULL; - hr->set_sort_index(-1); - --_occupancy; - assert(verify(), "cache should be consistent"); -} - static inline int orderRegions(HeapRegion* hr1, HeapRegion* hr2) { if (hr1 == NULL) { if (hr2 == NULL) return 0; @@ -197,43 +173,34 @@ HeapRegion *prev = NULL; while (index < _numMarkedRegions) { HeapRegion *curr = _markedRegions.at(index++); - if (curr != NULL) { - int si = curr->sort_index(); - guarantee(!curr->is_young(), "should not be young!"); - guarantee(si > -1 && si == (index-1), "sort index invariant"); - if (prev != NULL) { - guarantee(orderRegions(prev, curr) != 1, "regions should be sorted"); - } - prev = curr; + guarantee(curr != NULL, "Regions in _markedRegions array cannot be NULL"); + int si = curr->sort_index(); + guarantee(!curr->is_young(), "should not be young!"); + guarantee(si > -1 && si == (index-1), "sort index invariant"); + if (prev != NULL) { + guarantee(orderRegions(prev, curr) != 1, "regions should be sorted"); } + prev = curr; } return _cache.verify(); } #endif -bool -CollectionSetChooser::addRegionToCache() { - assert(!_cache.is_full(), "cache should not be full"); - - HeapRegion *hr = NULL; - while (hr == NULL && _curMarkedIndex < _numMarkedRegions) { - hr = _markedRegions.at(_curMarkedIndex++); - } - if (hr == NULL) - return false; - assert(!hr->is_young(), "should not be young!"); - assert(hr->sort_index() == _curMarkedIndex-1, "sort_index invariant"); - _markedRegions.at_put(hr->sort_index(), NULL); - _cache.insert(hr); - assert(!_cache.is_empty(), "cache should not be empty"); - assert(verify(), "cache should be consistent"); - return false; -} - void CollectionSetChooser::fillCache() { - while (!_cache.is_full() && addRegionToCache()) { + while (!_cache.is_full() && (_curMarkedIndex < _numMarkedRegions)) { + HeapRegion* hr = _markedRegions.at(_curMarkedIndex); + assert(hr != NULL, + err_msg("Unexpected NULL hr in _markedRegions at index %d", + _curMarkedIndex)); + _curMarkedIndex += 1; + assert(!hr->is_young(), "should not be young!"); + assert(hr->sort_index() == _curMarkedIndex-1, "sort_index invariant"); + _markedRegions.at_put(hr->sort_index(), NULL); + _cache.insert(hr); + assert(!_cache.is_empty(), "cache should not be empty"); } + assert(verify(), "cache should be consistent"); } void @@ -334,20 +301,6 @@ clearMarkedHeapRegions(); } -void CollectionSetChooser::removeRegion(HeapRegion *hr) { - int si = hr->sort_index(); - assert(si == -1 || hr->is_marked(), "Sort index not valid."); - if (si > -1) { - assert(_markedRegions.at(si) == hr, "Sort index not valid." ); - _markedRegions.at_put(si, NULL); - } else if (si < -1) { - assert(_cache.region_in_cache(hr), "should be in the cache"); - _cache.remove(hr); - assert(hr->sort_index() == -1, "sort index invariant"); - } - hr->set_sort_index(-1); -} - // if time_remaining < 0.0, then this method should try to return // a region, whether it fits within the remaining time or not HeapRegion*
--- a/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -29,6 +29,26 @@ #include "utilities/growableArray.hpp" // We need to sort heap regions by collection desirability. +// This sorting is currently done in two "stages". An initial sort is +// done following a cleanup pause as soon as all of the marked but +// non-empty regions have been identified and the completely empty +// ones reclaimed. +// This gives us a global sort on a GC efficiency metric +// based on predictive data available at that time. However, +// any of these regions that are collected will only be collected +// during a future GC pause, by which time it is possible that newer +// data might allow us to revise and/or refine the earlier +// pause predictions, leading to changes in expected gc efficiency +// order. To somewhat mitigate this obsolescence, more so in the +// case of regions towards the end of the list, which will be +// picked later, these pre-sorted regions from the _markedRegions +// array are not used as is, but a small prefix thereof is +// insertion-sorted again into a small cache, based on more +// recent remembered set information. Regions are then drawn +// from this cache to construct the collection set at each +// incremental GC. +// This scheme and/or its implementation may be subject to +// revision in the future. class CSetChooserCache VALUE_OBJ_CLASS_SPEC { private: @@ -37,8 +57,8 @@ } PrivateConstants; HeapRegion* _cache[CacheLength]; - int _occupancy; // number of region in cache - int _first; // "first" region in the cache + int _occupancy; // number of regions in cache + int _first; // (index of) "first" region in the cache // adding CacheLength to deal with negative values inline int trim_index(int index) { @@ -62,7 +82,6 @@ void clear(void); void insert(HeapRegion *hr); HeapRegion *remove_first(void); - void remove (HeapRegion *hr); inline HeapRegion *get_first(void) { return _cache[_first]; } @@ -102,7 +121,6 @@ void sortMarkedHeapRegions(); void fillCache(); - bool addRegionToCache(void); void addMarkedHeapRegion(HeapRegion *hr); // Must be called before calls to getParMarkedHeapRegionChunk. @@ -122,9 +140,6 @@ void updateAfterFullCollection(); - // Ensure that "hr" is not a member of the marked region array or the cache - void removeRegion(HeapRegion* hr); - bool unmarked_age_1_returned_as_new() { return _unmarked_age_1_returned_as_new; } // Returns true if the used portion of "_markedRegions" is properly
--- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -818,10 +818,10 @@ NoteStartOfMarkHRClosure startcl; g1h->heap_region_iterate(&startcl); - // Start weak-reference discovery. - ReferenceProcessor* rp = g1h->ref_processor(); - rp->verify_no_references_recorded(); - rp->enable_discovery(); // enable ("weak") refs discovery + // Start Concurrent Marking weak-reference discovery. + ReferenceProcessor* rp = g1h->ref_processor_cm(); + // enable ("weak") refs discovery + rp->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); rp->setup_policy(false); // snapshot the soft ref policy to be used in this cycle SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); @@ -1133,6 +1133,7 @@ // world is stopped at this checkpoint assert(SafepointSynchronize::is_at_safepoint(), "world should be stopped"); + G1CollectedHeap* g1h = G1CollectedHeap::heap(); // If a full collection has happened, we shouldn't do this. @@ -1815,9 +1816,7 @@ // this will also free any regions totally full of garbage objects, // and sort the regions. - g1h->g1_policy()->record_concurrent_mark_cleanup_end( - g1_par_note_end_task.freed_bytes(), - g1_par_note_end_task.max_live_bytes()); + g1h->g1_policy()->record_concurrent_mark_cleanup_end(); // Statistics. double end = os::elapsedTime(); @@ -1837,6 +1836,10 @@ size_t cleaned_up_bytes = start_used_bytes - g1h->used(); g1p->decrease_known_garbage_bytes(cleaned_up_bytes); + // Clean up will have freed any regions completely full of garbage. + // Update the soft reference policy with the new heap occupancy. + Universe::update_heap_info_at_gc(); + // We need to make this be a "collection" so any collection pause that // races with it goes around and waits for completeCleanup to finish. g1h->increment_total_collections(); @@ -2072,8 +2075,10 @@ } }; -// Implementation of AbstractRefProcTaskExecutor for G1 -class G1RefProcTaskExecutor: public AbstractRefProcTaskExecutor { +// Implementation of AbstractRefProcTaskExecutor for parallel +// reference processing at the end of G1 concurrent marking + +class G1CMRefProcTaskExecutor: public AbstractRefProcTaskExecutor { private: G1CollectedHeap* _g1h; ConcurrentMark* _cm; @@ -2082,7 +2087,7 @@ int _active_workers; public: - G1RefProcTaskExecutor(G1CollectedHeap* g1h, + G1CMRefProcTaskExecutor(G1CollectedHeap* g1h, ConcurrentMark* cm, CMBitMap* bitmap, WorkGang* workers, @@ -2096,7 +2101,7 @@ virtual void execute(EnqueueTask& task); }; -class G1RefProcTaskProxy: public AbstractGangTask { +class G1CMRefProcTaskProxy: public AbstractGangTask { typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask; ProcessTask& _proc_task; G1CollectedHeap* _g1h; @@ -2104,7 +2109,7 @@ CMBitMap* _bitmap; public: - G1RefProcTaskProxy(ProcessTask& proc_task, + G1CMRefProcTaskProxy(ProcessTask& proc_task, G1CollectedHeap* g1h, ConcurrentMark* cm, CMBitMap* bitmap) : @@ -2122,10 +2127,10 @@ } }; -void G1RefProcTaskExecutor::execute(ProcessTask& proc_task) { +void G1CMRefProcTaskExecutor::execute(ProcessTask& proc_task) { assert(_workers != NULL, "Need parallel worker threads."); - G1RefProcTaskProxy proc_task_proxy(proc_task, _g1h, _cm, _bitmap); + G1CMRefProcTaskProxy proc_task_proxy(proc_task, _g1h, _cm, _bitmap); // We need to reset the phase for each task execution so that // the termination protocol of CMTask::do_marking_step works. @@ -2135,12 +2140,12 @@ _g1h->set_par_threads(0); } -class G1RefEnqueueTaskProxy: public AbstractGangTask { +class G1CMRefEnqueueTaskProxy: public AbstractGangTask { typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask; EnqueueTask& _enq_task; public: - G1RefEnqueueTaskProxy(EnqueueTask& enq_task) : + G1CMRefEnqueueTaskProxy(EnqueueTask& enq_task) : AbstractGangTask("Enqueue reference objects in parallel"), _enq_task(enq_task) { } @@ -2150,10 +2155,10 @@ } }; -void G1RefProcTaskExecutor::execute(EnqueueTask& enq_task) { +void G1CMRefProcTaskExecutor::execute(EnqueueTask& enq_task) { assert(_workers != NULL, "Need parallel worker threads."); - G1RefEnqueueTaskProxy enq_task_proxy(enq_task); + G1CMRefEnqueueTaskProxy enq_task_proxy(enq_task); _g1h->set_par_threads(_active_workers); _workers->run_task(&enq_task_proxy); @@ -2163,71 +2168,84 @@ void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) { ResourceMark rm; HandleMark hm; - G1CollectedHeap* g1h = G1CollectedHeap::heap(); - ReferenceProcessor* rp = g1h->ref_processor(); - - // See the comment in G1CollectedHeap::ref_processing_init() - // about how reference processing currently works in G1. - - // Process weak references. - rp->setup_policy(clear_all_soft_refs); - assert(_markStack.isEmpty(), "mark stack should be empty"); - - G1CMIsAliveClosure g1_is_alive(g1h); - G1CMKeepAliveClosure g1_keep_alive(g1h, this, nextMarkBitMap()); - G1CMDrainMarkingStackClosure - g1_drain_mark_stack(nextMarkBitMap(), &_markStack, &g1_keep_alive); - // We use the work gang from the G1CollectedHeap and we utilize all - // the worker threads. - int active_workers = g1h->workers() ? g1h->workers()->total_workers() : 1; - active_workers = MAX2(MIN2(active_workers, (int)_max_task_num), 1); - - G1RefProcTaskExecutor par_task_executor(g1h, this, nextMarkBitMap(), - 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, + + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + + // Is alive closure. + G1CMIsAliveClosure g1_is_alive(g1h); + + // Inner scope to exclude the cleaning of the string and symbol + // tables from the displayed time. + { + bool verbose = PrintGC && PrintGCDetails; + if (verbose) { + gclog_or_tty->put(' '); + } + TraceTime t("GC ref-proc", verbose, false, gclog_or_tty); + + ReferenceProcessor* rp = g1h->ref_processor_cm(); + + // See the comment in G1CollectedHeap::ref_processing_init() + // about how reference processing currently works in G1. + + // Process weak references. + rp->setup_policy(clear_all_soft_refs); + assert(_markStack.isEmpty(), "mark stack should be empty"); + + G1CMKeepAliveClosure g1_keep_alive(g1h, this, nextMarkBitMap()); + G1CMDrainMarkingStackClosure + g1_drain_mark_stack(nextMarkBitMap(), &_markStack, &g1_keep_alive); + + // We use the work gang from the G1CollectedHeap and we utilize all + // the worker threads. + int active_workers = g1h->workers() ? g1h->workers()->total_workers() : 1; + active_workers = MAX2(MIN2(active_workers, (int)_max_task_num), 1); + + G1CMRefProcTaskExecutor par_task_executor(g1h, this, nextMarkBitMap(), + 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, &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); - + // 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); + } + + 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 + // 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(); + } + + rp->verify_no_references_recorded(); + assert(!rp->discovery_enabled(), "Post condition"); } - 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 - // 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(); - } - - rp->verify_no_references_recorded(); - assert(!rp->discovery_enabled(), "should have been disabled"); - // Now clean up stale oops in StringTable StringTable::unlink(&g1_is_alive); // Clean up unreferenced symbols in symbol table. @@ -3329,7 +3347,7 @@ assert(_ref_processor == NULL, "should be initialized to NULL"); if (G1UseConcMarkReferenceProcessing) { - _ref_processor = g1h->ref_processor(); + _ref_processor = g1h->ref_processor_cm(); assert(_ref_processor != NULL, "should not be NULL"); } } @@ -4564,6 +4582,15 @@ G1PPRL_DOUBLE_H_FORMAT, "type", "address-range", "used", "prev-live", "next-live", "gc-eff"); + _out->print_cr(G1PPRL_LINE_PREFIX + G1PPRL_TYPE_H_FORMAT + G1PPRL_ADDR_BASE_H_FORMAT + G1PPRL_BYTE_H_FORMAT + G1PPRL_BYTE_H_FORMAT + G1PPRL_BYTE_H_FORMAT + G1PPRL_DOUBLE_H_FORMAT, + "", "", + "(bytes)", "(bytes)", "(bytes)", "(bytes/ms)"); } // It takes as a parameter a reference to one of the _hum_* fields, it @@ -4575,7 +4602,7 @@ // The > 0 check is to deal with the prev and next live bytes which // could be 0. if (*hum_bytes > 0) { - bytes = MIN2((size_t) HeapRegion::GrainBytes, *hum_bytes); + bytes = MIN2(HeapRegion::GrainBytes, *hum_bytes); *hum_bytes -= bytes; } return bytes;
--- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -366,8 +366,8 @@ friend class CMConcurrentMarkingTask; friend class G1ParNoteEndTask; friend class CalcLiveObjectsClosure; - friend class G1RefProcTaskProxy; - friend class G1RefProcTaskExecutor; + friend class G1CMRefProcTaskProxy; + friend class G1CMRefProcTaskExecutor; friend class G1CMParKeepAliveAndDrainClosure; friend class G1CMParDrainMarkingStackClosure;
--- a/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -215,20 +215,20 @@ gclog_or_tty->print_cr("[GC concurrent-cleanup-start]"); } - // Now do the remainder of the cleanup operation. + // Now do the concurrent cleanup operation. _cm->completeCleanup(); + // Notify anyone who's waiting that there are no more free - // regions coming. We have to do this before we join the STS, - // otherwise we might deadlock: a GC worker could be blocked - // waiting for the notification whereas this thread will be - // blocked for the pause to finish while it's trying to join - // the STS, which is conditional on the GC workers finishing. + // regions coming. We have to do this before we join the STS + // (in fact, we should not attempt to join the STS in the + // interval between finishing the cleanup pause and clearing + // the free_regions_coming flag) otherwise we might deadlock: + // a GC worker could be blocked waiting for the notification + // whereas this thread will be blocked for the pause to finish + // while it's trying to join the STS, which is conditional on + // the GC workers finishing. g1h->reset_free_regions_coming(); - _sts.join(); - g1_policy->record_concurrent_mark_cleanup_completed(); - _sts.leave(); - double cleanup_end_sec = os::elapsedTime(); if (PrintGC) { gclog_or_tty->date_stamp(PrintGCDateStamps); @@ -240,6 +240,36 @@ guarantee(cm()->cleanup_list_is_empty(), "at this point there should be no regions on the cleanup list"); + // There is a tricky race before recording that the concurrent + // cleanup has completed and a potential Full GC starting around + // the same time. We want to make sure that the Full GC calls + // abort() on concurrent mark after + // record_concurrent_mark_cleanup_completed(), since abort() is + // the method that will reset the concurrent mark state. If we + // end up calling record_concurrent_mark_cleanup_completed() + // after abort() then we might incorrectly undo some of the work + // abort() did. Checking the has_aborted() flag after joining + // the STS allows the correct ordering of the two methods. There + // are two scenarios: + // + // a) If we reach here before the Full GC, the fact that we have + // joined the STS means that the Full GC cannot start until we + // leave the STS, so record_concurrent_mark_cleanup_completed() + // will complete before abort() is called. + // + // b) If we reach here during the Full GC, we'll be held up from + // joining the STS until the Full GC is done, which means that + // abort() will have completed and has_aborted() will return + // true to prevent us from calling + // record_concurrent_mark_cleanup_completed() (and, in fact, it's + // not needed any more as the concurrent mark state has been + // already reset). + _sts.join(); + if (!cm()->has_aborted()) { + g1_policy->record_concurrent_mark_cleanup_completed(); + } + _sts.leave(); + if (cm()->has_aborted()) { if (PrintGC) { gclog_or_tty->date_stamp(PrintGCDateStamps); @@ -248,7 +278,7 @@ } } - // we now want to allow clearing of the marking bitmap to be + // We now want to allow clearing of the marking bitmap to be // suspended by a collection pause. _sts.join(); _cm->clearNextBitmap();
--- a/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -39,6 +39,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif bool DirtyCardQueue::apply_closure(CardTableEntryClosure* cl, bool consume,
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -42,6 +42,7 @@ #include "memory/gcLocker.inline.hpp" #include "memory/genOopClosures.inline.hpp" #include "memory/generationSpec.hpp" +#include "memory/referenceProcessor.hpp" #include "oops/oop.inline.hpp" #include "oops/oop.pcgc.inline.hpp" #include "runtime/aprofiler.hpp" @@ -551,8 +552,7 @@ } HeapRegion* G1CollectedHeap::new_region(size_t word_size, bool do_expand) { - assert(!isHumongous(word_size) || - word_size <= (size_t) HeapRegion::GrainWords, + assert(!isHumongous(word_size) || word_size <= HeapRegion::GrainWords, "the only time we use this to allocate a humongous region is " "when we are allocating a single humongous region"); @@ -815,6 +815,11 @@ result = humongous_obj_allocate_initialize_regions(first, num_regions, word_size); assert(result != NULL, "it should always return a valid result"); + + // A successful humongous object allocation changes the used space + // information of the old generation so we need to recalculate the + // sizes and update the jstat counters here. + g1mm()->update_sizes(); } verify_region_sets_optional(); @@ -1164,7 +1169,7 @@ if (!hr->isHumongous()) { _hr_printer->post_compaction(hr, G1HRPrinter::Old); } else if (hr->startsHumongous()) { - if (hr->capacity() == (size_t) HeapRegion::GrainBytes) { + if (hr->capacity() == HeapRegion::GrainBytes) { // single humongous region _hr_printer->post_compaction(hr, G1HRPrinter::SingleHumongous); } else { @@ -1244,15 +1249,11 @@ COMPILER2_PRESENT(DerivedPointerTable::clear()); - // We want to discover references, but not process them yet. - // This mode is disabled in - // instanceRefKlass::process_discovered_references if the - // generation does some collection work, or - // instanceRefKlass::enqueue_discovered_references if the - // generation returns without doing any work. - ref_processor()->disable_discovery(); - ref_processor()->abandon_partial_discovery(); - ref_processor()->verify_no_references_recorded(); + // Disable discovery and empty the discovered lists + // for the CM ref processor. + ref_processor_cm()->disable_discovery(); + ref_processor_cm()->abandon_partial_discovery(); + ref_processor_cm()->verify_no_references_recorded(); // Abandon current iterations of concurrent marking and concurrent // refinement, if any are in progress. @@ -1280,31 +1281,33 @@ empty_young_list(); g1_policy()->set_full_young_gcs(true); - // See the comment in G1CollectedHeap::ref_processing_init() about + // See the comments in g1CollectedHeap.hpp and + // G1CollectedHeap::ref_processing_init() about // how reference processing currently works in G1. - // Temporarily make reference _discovery_ single threaded (non-MT). - ReferenceProcessorMTDiscoveryMutator rp_disc_ser(ref_processor(), false); - - // Temporarily make refs discovery atomic - ReferenceProcessorAtomicMutator rp_disc_atomic(ref_processor(), true); - - // Temporarily clear _is_alive_non_header - ReferenceProcessorIsAliveMutator rp_is_alive_null(ref_processor(), NULL); - - ref_processor()->enable_discovery(); - ref_processor()->setup_policy(do_clear_all_soft_refs); + // Temporarily make discovery by the STW ref processor single threaded (non-MT). + ReferenceProcessorMTDiscoveryMutator stw_rp_disc_ser(ref_processor_stw(), false); + + // Temporarily clear the STW ref processor's _is_alive_non_header field. + ReferenceProcessorIsAliveMutator stw_rp_is_alive_null(ref_processor_stw(), NULL); + + ref_processor_stw()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); + ref_processor_stw()->setup_policy(do_clear_all_soft_refs); + // Do collection work { HandleMark hm; // Discard invalid handles created during gc - G1MarkSweep::invoke_at_safepoint(ref_processor(), do_clear_all_soft_refs); + G1MarkSweep::invoke_at_safepoint(ref_processor_stw(), do_clear_all_soft_refs); } + assert(free_regions() == 0, "we should not have added any free regions"); rebuild_region_lists(); _summary_bytes_used = recalculate_used(); - ref_processor()->enqueue_discovered_references(); + // Enqueue any discovered reference objects that have + // not been removed from the discovered lists. + ref_processor_stw()->enqueue_discovered_references(); COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); @@ -1319,7 +1322,16 @@ /* option */ VerifyOption_G1UsePrevMarking); } - NOT_PRODUCT(ref_processor()->verify_no_references_recorded()); + + assert(!ref_processor_stw()->discovery_enabled(), "Postcondition"); + ref_processor_stw()->verify_no_references_recorded(); + + // Note: since we've just done a full GC, concurrent + // marking is no longer active. Therefore we need not + // re-enable reference discovery for the CM ref processor. + // That will be done at the start of the next marking cycle. + assert(!ref_processor_cm()->discovery_enabled(), "Postcondition"); + ref_processor_cm()->verify_no_references_recorded(); reset_gc_time_stamp(); // Since everything potentially moved, we will clear all remembered @@ -1414,7 +1426,7 @@ if (PrintHeapAtGC) { Universe::print_heap_after_gc(); } - g1mm()->update_counters(); + g1mm()->update_sizes(); post_full_gc_dump(); return true; @@ -1772,14 +1784,17 @@ _g1_policy(policy_), _dirty_card_queue_set(false), _into_cset_dirty_card_queue_set(false), - _is_alive_closure(this), - _ref_processor(NULL), + _is_alive_closure_cm(this), + _is_alive_closure_stw(this), + _ref_processor_cm(NULL), + _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), + _g1mm(NULL), _refine_cte_cl(NULL), _full_collection(false), _free_list("Master Free List"), @@ -1955,7 +1970,7 @@ size_t max_cards_per_region = ((size_t)1 << (sizeof(CardIdx_t)*BitsPerByte-1)) - 1; guarantee(HeapRegion::CardsPerRegion > 0, "make sure it's initialized"); - guarantee((size_t) HeapRegion::CardsPerRegion < max_cards_per_region, + guarantee(HeapRegion::CardsPerRegion < max_cards_per_region, "too many cards per region"); HeapRegionSet::set_unrealistically_long_length(max_regions() + 1); @@ -1996,8 +2011,6 @@ // Perform any initialization actions delegated to the policy. g1_policy()->init(); - g1_policy()->note_start_of_mark_thread(); - _refine_cte_cl = new RefineCardTableEntryClosure(ConcurrentG1RefineThread::sts(), g1_rem_set(), @@ -2059,7 +2072,7 @@ // Do create of the monitoring and management support so that // values in the heap have been properly initialized. - _g1mm = new G1MonitoringSupport(this, &_g1_storage); + _g1mm = new G1MonitoringSupport(this); return JNI_OK; } @@ -2067,34 +2080,81 @@ void G1CollectedHeap::ref_processing_init() { // Reference processing in G1 currently works as follows: // - // * There is only one reference processor instance that - // 'spans' the entire heap. It is created by the code - // below. - // * Reference discovery is not enabled during an incremental - // pause (see 6484982). - // * Discoverered refs are not enqueued nor are they processed - // during an incremental pause (see 6484982). - // * Reference discovery is enabled at initial marking. - // * Reference discovery is disabled and the discovered - // references processed etc during remarking. - // * Reference discovery is MT (see below). - // * Reference discovery requires a barrier (see below). - // * Reference processing is currently not MT (see 6608385). - // * A full GC enables (non-MT) reference discovery and - // processes any discovered references. + // * There are two reference processor instances. One is + // used to record and process discovered references + // during concurrent marking; the other is used to + // record and process references during STW pauses + // (both full and incremental). + // * Both ref processors need to 'span' the entire heap as + // the regions in the collection set may be dotted around. + // + // * For the concurrent marking ref processor: + // * Reference discovery is enabled at initial marking. + // * Reference discovery is disabled and the discovered + // references processed etc during remarking. + // * Reference discovery is MT (see below). + // * Reference discovery requires a barrier (see below). + // * Reference processing may or may not be MT + // (depending on the value of ParallelRefProcEnabled + // and ParallelGCThreads). + // * A full GC disables reference discovery by the CM + // ref processor and abandons any entries on it's + // discovered lists. + // + // * For the STW processor: + // * Non MT discovery is enabled at the start of a full GC. + // * Processing and enqueueing during a full GC is non-MT. + // * During a full GC, references are processed after marking. + // + // * Discovery (may or may not be MT) is enabled at the start + // of an incremental evacuation pause. + // * References are processed near the end of a STW evacuation pause. + // * For both types of GC: + // * Discovery is atomic - i.e. not concurrent. + // * Reference discovery will not need a barrier. SharedHeap::ref_processing_init(); MemRegion mr = reserved_region(); - _ref_processor = + + // Concurrent Mark ref processor + _ref_processor_cm = new ReferenceProcessor(mr, // span - ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing - (int) ParallelGCThreads, // degree of mt processing - ParallelGCThreads > 1 || ConcGCThreads > 1, // mt discovery - (int) MAX2(ParallelGCThreads, ConcGCThreads), // degree of mt discovery - false, // Reference discovery is not atomic - &_is_alive_closure, // is alive closure for efficiency - true); // Setting next fields of discovered - // lists requires a barrier. + ParallelRefProcEnabled && (ParallelGCThreads > 1), + // mt processing + (int) ParallelGCThreads, + // degree of mt processing + (ParallelGCThreads > 1) || (ConcGCThreads > 1), + // mt discovery + (int) MAX2(ParallelGCThreads, ConcGCThreads), + // degree of mt discovery + false, + // Reference discovery is not atomic + &_is_alive_closure_cm, + // is alive closure + // (for efficiency/performance) + true); + // Setting next fields of discovered + // lists requires a barrier. + + // STW ref processor + _ref_processor_stw = + new ReferenceProcessor(mr, // span + ParallelRefProcEnabled && (ParallelGCThreads > 1), + // mt processing + MAX2((int)ParallelGCThreads, 1), + // degree of mt processing + (ParallelGCThreads > 1), + // mt discovery + MAX2((int)ParallelGCThreads, 1), + // degree of mt discovery + true, + // Reference discovery is atomic + &_is_alive_closure_stw, + // is alive closure + // (for efficiency/performance) + false); + // Setting next fields of discovered + // lists requires a barrier. } size_t G1CollectedHeap::capacity() const { @@ -2988,8 +3048,7 @@ _g1_storage.high(), _g1_storage.high_boundary()); st->cr(); - st->print(" region size " SIZE_FORMAT "K, ", - HeapRegion::GrainBytes/K); + st->print(" region size " SIZE_FORMAT "K, ", HeapRegion::GrainBytes / K); size_t young_regions = _young_list->length(); st->print(SIZE_FORMAT " young (" SIZE_FORMAT "K), ", young_regions, young_regions * HeapRegion::GrainBytes / K); @@ -3117,6 +3176,10 @@ COMPILER2_PRESENT(assert(DerivedPointerTable::is_empty(), "derived pointer present")); // always_do_update_barrier = true; + + // We have just completed a GC. Update the soft reference + // policy with the new heap occupancy + Universe::update_heap_info_at_gc(); } HeapWord* G1CollectedHeap::do_collection_pause(size_t word_size, @@ -3298,6 +3361,14 @@ // for the duration of this pause. g1_policy()->decide_on_conc_mark_initiation(); + // We do not allow initial-mark to be piggy-backed on a + // partially-young GC. + assert(!g1_policy()->during_initial_mark_pause() || + g1_policy()->full_young_gcs(), "sanity"); + + // We also do not allow partially-young GCs during marking. + assert(!mark_in_progress() || g1_policy()->full_young_gcs(), "sanity"); + char verbose_str[128]; sprintf(verbose_str, "GC pause "); if (g1_policy()->full_young_gcs()) { @@ -3354,231 +3425,242 @@ COMPILER2_PRESENT(DerivedPointerTable::clear()); - // Please see comment in G1CollectedHeap::ref_processing_init() - // to see how reference processing currently works in G1. - // - // We want to turn off ref discovery, if necessary, and turn it back on - // on again later if we do. XXX Dubious: why is discovery disabled? - bool was_enabled = ref_processor()->discovery_enabled(); - if (was_enabled) ref_processor()->disable_discovery(); - - // Forget the current alloc region (we might even choose it to be part - // of the collection set!). - release_mutator_alloc_region(); - - // We should call this after we retire the mutator alloc - // region(s) so that all the ALLOC / RETIRE events are generated - // before the start GC event. - _hr_printer.start_gc(false /* full */, (size_t) total_collections()); - - // The elapsed time induced by the start time below deliberately elides - // the possible verification above. - double start_time_sec = os::elapsedTime(); - size_t start_used_bytes = used(); + // Please see comment in g1CollectedHeap.hpp and + // G1CollectedHeap::ref_processing_init() to see how + // reference processing currently works in G1. + + // Enable discovery in the STW reference processor + ref_processor_stw()->enable_discovery(true /*verify_disabled*/, + true /*verify_no_refs*/); + + { + // We want to temporarily turn off discovery by the + // CM ref processor, if necessary, and turn it back on + // on again later if we do. Using a scoped + // NoRefDiscovery object will do this. + NoRefDiscovery no_cm_discovery(ref_processor_cm()); + + // Forget the current alloc region (we might even choose it to be part + // of the collection set!). + release_mutator_alloc_region(); + + // We should call this after we retire the mutator alloc + // region(s) so that all the ALLOC / RETIRE events are generated + // before the start GC event. + _hr_printer.start_gc(false /* full */, (size_t) total_collections()); + + // The elapsed time induced by the start time below deliberately elides + // the possible verification above. + double start_time_sec = os::elapsedTime(); + size_t start_used_bytes = used(); #if YOUNG_LIST_VERBOSE - gclog_or_tty->print_cr("\nBefore recording pause start.\nYoung_list:"); - _young_list->print(); - g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty); + gclog_or_tty->print_cr("\nBefore recording pause start.\nYoung_list:"); + _young_list->print(); + g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty); #endif // YOUNG_LIST_VERBOSE - g1_policy()->record_collection_pause_start(start_time_sec, - start_used_bytes); + g1_policy()->record_collection_pause_start(start_time_sec, + start_used_bytes); #if YOUNG_LIST_VERBOSE - gclog_or_tty->print_cr("\nAfter recording pause start.\nYoung_list:"); - _young_list->print(); + gclog_or_tty->print_cr("\nAfter recording pause start.\nYoung_list:"); + _young_list->print(); #endif // YOUNG_LIST_VERBOSE - if (g1_policy()->during_initial_mark_pause()) { - concurrent_mark()->checkpointRootsInitialPre(); - } - perm_gen()->save_marks(); - - // We must do this before any possible evacuation that should propagate - // marks. - if (mark_in_progress()) { - double start_time_sec = os::elapsedTime(); - - _cm->drainAllSATBBuffers(); - double finish_mark_ms = (os::elapsedTime() - start_time_sec) * 1000.0; - g1_policy()->record_satb_drain_time(finish_mark_ms); - } - // Record the number of elements currently on the mark stack, so we - // only iterate over these. (Since evacuation may add to the mark - // stack, doing more exposes race conditions.) If no mark is in - // progress, this will be zero. - _cm->set_oops_do_bound(); - - if (mark_in_progress()) { - concurrent_mark()->newCSet(); - } + if (g1_policy()->during_initial_mark_pause()) { + concurrent_mark()->checkpointRootsInitialPre(); + } + perm_gen()->save_marks(); + + // We must do this before any possible evacuation that should propagate + // marks. + if (mark_in_progress()) { + double start_time_sec = os::elapsedTime(); + + _cm->drainAllSATBBuffers(); + double finish_mark_ms = (os::elapsedTime() - start_time_sec) * 1000.0; + g1_policy()->record_satb_drain_time(finish_mark_ms); + } + // Record the number of elements currently on the mark stack, so we + // only iterate over these. (Since evacuation may add to the mark + // stack, doing more exposes race conditions.) If no mark is in + // progress, this will be zero. + _cm->set_oops_do_bound(); + + if (mark_in_progress()) { + concurrent_mark()->newCSet(); + } #if YOUNG_LIST_VERBOSE - gclog_or_tty->print_cr("\nBefore choosing collection set.\nYoung_list:"); - _young_list->print(); - g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty); + gclog_or_tty->print_cr("\nBefore choosing collection set.\nYoung_list:"); + _young_list->print(); + g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty); #endif // YOUNG_LIST_VERBOSE - g1_policy()->choose_collection_set(target_pause_time_ms); - - if (_hr_printer.is_active()) { - HeapRegion* hr = g1_policy()->collection_set(); - while (hr != NULL) { - G1HRPrinter::RegionType type; - if (!hr->is_young()) { - type = G1HRPrinter::Old; - } else if (hr->is_survivor()) { - type = G1HRPrinter::Survivor; - } else { - type = G1HRPrinter::Eden; + g1_policy()->choose_collection_set(target_pause_time_ms); + + if (_hr_printer.is_active()) { + HeapRegion* hr = g1_policy()->collection_set(); + while (hr != NULL) { + G1HRPrinter::RegionType type; + if (!hr->is_young()) { + type = G1HRPrinter::Old; + } else if (hr->is_survivor()) { + type = G1HRPrinter::Survivor; + } else { + type = G1HRPrinter::Eden; + } + _hr_printer.cset(hr); + hr = hr->next_in_collection_set(); } - _hr_printer.cset(hr); - hr = hr->next_in_collection_set(); } - } - - // We have chosen the complete collection set. If marking is - // active then, we clear the region fields of any of the - // concurrent marking tasks whose region fields point into - // the collection set as these values will become stale. This - // will cause the owning marking threads to claim a new region - // when marking restarts. - if (mark_in_progress()) { - concurrent_mark()->reset_active_task_region_fields_in_cset(); - } + + // We have chosen the complete collection set. If marking is + // active then, we clear the region fields of any of the + // concurrent marking tasks whose region fields point into + // the collection set as these values will become stale. This + // will cause the owning marking threads to claim a new region + // when marking restarts. + if (mark_in_progress()) { + concurrent_mark()->reset_active_task_region_fields_in_cset(); + } #ifdef ASSERT - VerifyCSetClosure cl; - collection_set_iterate(&cl); + VerifyCSetClosure cl; + collection_set_iterate(&cl); #endif // ASSERT - setup_surviving_young_words(); - - // Initialize the GC alloc regions. - init_gc_alloc_regions(); - - // Actually do the work... - evacuate_collection_set(); - - free_collection_set(g1_policy()->collection_set()); - g1_policy()->clear_collection_set(); - - cleanup_surviving_young_words(); - - // Start a new incremental collection set for the next pause. - g1_policy()->start_incremental_cset_building(); - - // Clear the _cset_fast_test bitmap in anticipation of adding - // regions to the incremental collection set for the next - // evacuation pause. - clear_cset_fast_test(); - - _young_list->reset_sampled_info(); - - // Don't check the whole heap at this point as the - // GC alloc regions from this pause have been tagged - // as survivors and moved on to the survivor list. - // Survivor regions will fail the !is_young() check. - assert(check_young_list_empty(false /* check_heap */), - "young list should be empty"); + setup_surviving_young_words(); + + // Initialize the GC alloc regions. + init_gc_alloc_regions(); + + // Actually do the work... + evacuate_collection_set(); + + free_collection_set(g1_policy()->collection_set()); + g1_policy()->clear_collection_set(); + + cleanup_surviving_young_words(); + + // Start a new incremental collection set for the next pause. + g1_policy()->start_incremental_cset_building(); + + // Clear the _cset_fast_test bitmap in anticipation of adding + // regions to the incremental collection set for the next + // evacuation pause. + clear_cset_fast_test(); + + _young_list->reset_sampled_info(); + + // Don't check the whole heap at this point as the + // GC alloc regions from this pause have been tagged + // as survivors and moved on to the survivor list. + // Survivor regions will fail the !is_young() check. + assert(check_young_list_empty(false /* check_heap */), + "young list should be empty"); #if YOUNG_LIST_VERBOSE - gclog_or_tty->print_cr("Before recording survivors.\nYoung List:"); - _young_list->print(); + gclog_or_tty->print_cr("Before recording survivors.\nYoung List:"); + _young_list->print(); #endif // YOUNG_LIST_VERBOSE - g1_policy()->record_survivor_regions(_young_list->survivor_length(), - _young_list->first_survivor_region(), - _young_list->last_survivor_region()); - - _young_list->reset_auxilary_lists(); - - if (evacuation_failed()) { - _summary_bytes_used = recalculate_used(); - } else { - // The "used" of the the collection set have already been subtracted - // when they were freed. Add in the bytes evacuated. - _summary_bytes_used += g1_policy()->bytes_copied_during_gc(); - } - - if (g1_policy()->during_initial_mark_pause()) { - concurrent_mark()->checkpointRootsInitialPost(); - set_marking_started(); - // CAUTION: after the doConcurrentMark() call below, - // the concurrent marking thread(s) could be running - // concurrently with us. Make sure that anything after - // this point does not assume that we are the only GC thread - // running. Note: of course, the actual marking work will - // not start until the safepoint itself is released in - // ConcurrentGCThread::safepoint_desynchronize(). - doConcurrentMark(); - } - - allocate_dummy_regions(); + g1_policy()->record_survivor_regions(_young_list->survivor_length(), + _young_list->first_survivor_region(), + _young_list->last_survivor_region()); + + _young_list->reset_auxilary_lists(); + + if (evacuation_failed()) { + _summary_bytes_used = recalculate_used(); + } else { + // The "used" of the the collection set have already been subtracted + // when they were freed. Add in the bytes evacuated. + _summary_bytes_used += g1_policy()->bytes_copied_during_gc(); + } + + if (g1_policy()->during_initial_mark_pause()) { + concurrent_mark()->checkpointRootsInitialPost(); + set_marking_started(); + // CAUTION: after the doConcurrentMark() call below, + // the concurrent marking thread(s) could be running + // concurrently with us. Make sure that anything after + // this point does not assume that we are the only GC thread + // running. Note: of course, the actual marking work will + // not start until the safepoint itself is released in + // ConcurrentGCThread::safepoint_desynchronize(). + doConcurrentMark(); + } + + allocate_dummy_regions(); #if YOUNG_LIST_VERBOSE - gclog_or_tty->print_cr("\nEnd of the pause.\nYoung_list:"); - _young_list->print(); - g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty); + gclog_or_tty->print_cr("\nEnd of the pause.\nYoung_list:"); + _young_list->print(); + g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty); #endif // YOUNG_LIST_VERBOSE - init_mutator_alloc_region(); - - { - size_t expand_bytes = g1_policy()->expansion_amount(); - if (expand_bytes > 0) { - size_t bytes_before = capacity(); - if (!expand(expand_bytes)) { - // We failed to expand the heap so let's verify that - // committed/uncommitted amount match the backing store - assert(capacity() == _g1_storage.committed_size(), "committed size mismatch"); - assert(max_capacity() == _g1_storage.reserved_size(), "reserved size mismatch"); + init_mutator_alloc_region(); + + { + size_t expand_bytes = g1_policy()->expansion_amount(); + if (expand_bytes > 0) { + size_t bytes_before = capacity(); + if (!expand(expand_bytes)) { + // We failed to expand the heap so let's verify that + // committed/uncommitted amount match the backing store + assert(capacity() == _g1_storage.committed_size(), "committed size mismatch"); + assert(max_capacity() == _g1_storage.reserved_size(), "reserved size mismatch"); + } } } + + double end_time_sec = os::elapsedTime(); + double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS; + g1_policy()->record_pause_time_ms(pause_time_ms); + g1_policy()->record_collection_pause_end(); + + MemoryService::track_memory_usage(); + + // In prepare_for_verify() below we'll need to scan the deferred + // update buffers to bring the RSets up-to-date if + // G1HRRSFlushLogBuffersOnVerify has been set. While scanning + // the update buffers we'll probably need to scan cards on the + // regions we just allocated to (i.e., the GC alloc + // regions). However, during the last GC we called + // set_saved_mark() on all the GC alloc regions, so card + // scanning might skip the [saved_mark_word()...top()] area of + // those regions (i.e., the area we allocated objects into + // during the last GC). But it shouldn't. Given that + // saved_mark_word() is conditional on whether the GC time stamp + // on the region is current or not, by incrementing the GC time + // stamp here we invalidate all the GC time stamps on all the + // regions and saved_mark_word() will simply return top() for + // all the regions. This is a nicer way of ensuring this rather + // than iterating over the regions and fixing them. In fact, the + // GC time stamp increment here also ensures that + // saved_mark_word() will return top() between pauses, i.e., + // during concurrent refinement. So we don't need the + // is_gc_active() check to decided which top to use when + // scanning cards (see CR 7039627). + increment_gc_time_stamp(); + + if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) { + HandleMark hm; // Discard invalid handles created during verification + gclog_or_tty->print(" VerifyAfterGC:"); + prepare_for_verify(); + Universe::verify(/* allow dirty */ true, + /* silent */ false, + /* option */ VerifyOption_G1UsePrevMarking); + } + + assert(!ref_processor_stw()->discovery_enabled(), "Postcondition"); + ref_processor_stw()->verify_no_references_recorded(); + + // CM reference discovery will be re-enabled if necessary. } - double end_time_sec = os::elapsedTime(); - double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS; - g1_policy()->record_pause_time_ms(pause_time_ms); - g1_policy()->record_collection_pause_end(); - - MemoryService::track_memory_usage(); - - // In prepare_for_verify() below we'll need to scan the deferred - // update buffers to bring the RSets up-to-date if - // G1HRRSFlushLogBuffersOnVerify has been set. While scanning - // the update buffers we'll probably need to scan cards on the - // regions we just allocated to (i.e., the GC alloc - // regions). However, during the last GC we called - // set_saved_mark() on all the GC alloc regions, so card - // scanning might skip the [saved_mark_word()...top()] area of - // those regions (i.e., the area we allocated objects into - // during the last GC). But it shouldn't. Given that - // saved_mark_word() is conditional on whether the GC time stamp - // on the region is current or not, by incrementing the GC time - // stamp here we invalidate all the GC time stamps on all the - // regions and saved_mark_word() will simply return top() for - // all the regions. This is a nicer way of ensuring this rather - // than iterating over the regions and fixing them. In fact, the - // GC time stamp increment here also ensures that - // saved_mark_word() will return top() between pauses, i.e., - // during concurrent refinement. So we don't need the - // is_gc_active() check to decided which top to use when - // scanning cards (see CR 7039627). - increment_gc_time_stamp(); - - if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) { - HandleMark hm; // Discard invalid handles created during verification - gclog_or_tty->print(" VerifyAfterGC:"); - prepare_for_verify(); - Universe::verify(/* allow dirty */ true, - /* silent */ false, - /* option */ VerifyOption_G1UsePrevMarking); - } - - if (was_enabled) ref_processor()->enable_discovery(); - { size_t expand_bytes = g1_policy()->expansion_amount(); if (expand_bytes > 0) { @@ -3630,7 +3712,7 @@ if (PrintHeapAtGC) { Universe::print_heap_after_gc(); } - g1mm()->update_counters(); + g1mm()->update_sizes(); if (G1SummarizeRSetStats && (G1SummarizeRSetStatsPeriod > 0) && @@ -3728,34 +3810,6 @@ _evac_failure_scan_stack = NULL; } -// *** Sequential G1 Evacuation - -class G1IsAliveClosure: public BoolObjectClosure { - G1CollectedHeap* _g1; -public: - G1IsAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} - void do_object(oop p) { assert(false, "Do not call."); } - bool do_object_b(oop p) { - // It is reachable if it is outside the collection set, or is inside - // and forwarded. - return !_g1->obj_in_cs(p) || p->is_forwarded(); - } -}; - -class G1KeepAliveClosure: public OopClosure { - G1CollectedHeap* _g1; -public: - G1KeepAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} - void do_oop(narrowOop* p) { guarantee(false, "Not needed"); } - void do_oop( oop* p) { - oop obj = *p; - if (_g1->obj_in_cs(obj)) { - assert( obj->is_forwarded(), "invariant" ); - *p = obj->forwardee(); - } - } -}; - class UpdateRSetDeferred : public OopsInHeapRegionClosure { private: G1CollectedHeap* _g1; @@ -3904,9 +3958,6 @@ // _next_top_at_mark_start == top, _next_marked_bytes == 0 // _next_marked_bytes == next_marked_bytes. } - - // Now make sure the region has the right index in the sorted array. - g1_policy()->note_change_in_marked_bytes(cur); } cur = cur->next_in_collection_set(); } @@ -3946,7 +3997,8 @@ oop G1CollectedHeap::handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, - oop old) { + oop old, + bool should_mark_root) { assert(obj_in_cs(old), err_msg("obj: "PTR_FORMAT" should still be in the CSet", (HeapWord*) old)); @@ -3954,6 +4006,16 @@ oop forward_ptr = old->forward_to_atomic(old); if (forward_ptr == NULL) { // Forward-to-self succeeded. + + // should_mark_root will be true when this routine is called + // from a root scanning closure during an initial mark pause. + // In this case the thread that succeeds in self-forwarding the + // object is also responsible for marking the object. + if (should_mark_root) { + assert(!oopDesc::is_null(old), "shouldn't be"); + _cm->grayRoot(old); + } + if (_evac_failure_closure != cl) { MutexLockerEx x(EvacFailureStack_lock, Mutex::_no_safepoint_check_flag); assert(!_drain_in_progress, @@ -4175,12 +4237,17 @@ #endif // ASSERT void G1ParScanThreadState::trim_queue() { + assert(_evac_cl != NULL, "not set"); + assert(_evac_failure_cl != NULL, "not set"); + assert(_partial_scan_cl != NULL, "not set"); + StarTask ref; do { // Drain the overflow stack first, so other threads can steal. while (refs()->pop_overflow(ref)) { deal_with_reference(ref); } + while (refs()->pop_local(ref)) { deal_with_reference(ref); } @@ -4208,7 +4275,8 @@ } } -oop G1ParCopyHelper::copy_to_survivor_space(oop old, bool should_mark_copy) { +oop G1ParCopyHelper::copy_to_survivor_space(oop old, bool should_mark_root, + bool should_mark_copy) { size_t word_sz = old->size(); HeapRegion* from_region = _g1->heap_region_containing_raw(old); // +1 to make the -1 indexes valid... @@ -4228,7 +4296,7 @@ // This will either forward-to-self, or detect that someone else has // installed a forwarding pointer. OopsInHeapRegionClosure* cl = _par_scan_state->evac_failure_closure(); - return _g1->handle_evacuation_failure_par(cl, old); + return _g1->handle_evacuation_failure_par(cl, old, should_mark_root); } // We're going to allocate linearly, so might as well prefetch ahead. @@ -4330,11 +4398,26 @@ // we also need to handle marking of roots in the // event of an evacuation failure. In the event of an // evacuation failure, the object is forwarded to itself - // and not copied so let's mark it here. + // and not copied. For root-scanning closures, the + // object would be marked after a successful self-forward + // but an object could be pointed to by both a root and non + // root location and be self-forwarded by a non-root-scanning + // closure. Therefore we also have to attempt to mark the + // self-forwarded root object here. if (do_mark_object && obj->forwardee() == obj) { mark_object(p); } } else { + // During an initial mark pause, objects that are pointed to + // by the roots need to be marked - even in the event of an + // evacuation failure. We pass the template parameter + // do_mark_object (which is true for root scanning closures + // during an initial mark pause) to copy_to_survivor_space + // which will pass it on to the evacuation failure handling + // code. The thread that successfully self-forwards a root + // object to itself is responsible for marking the object. + bool should_mark_root = do_mark_object; + // We need to mark the copied object if we're a root scanning // closure during an initial mark pause (i.e. do_mark_object // will be true), or the object is already marked and we need @@ -4343,7 +4426,8 @@ _during_initial_mark || (_mark_in_progress && !_g1->is_obj_ill(obj)); - oop copy_oop = copy_to_survivor_space(obj, should_mark_copy); + oop copy_oop = copy_to_survivor_space(obj, should_mark_root, + should_mark_copy); oopDesc::encode_store_heap_oop(p, copy_oop); } // When scanning the RS, we only care about objs in CS. @@ -4501,35 +4585,34 @@ ResourceMark rm; HandleMark hm; + ReferenceProcessor* rp = _g1h->ref_processor_stw(); + G1ParScanThreadState pss(_g1h, i); - G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss); - G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss); - G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss); + G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss, rp); + G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, rp); + G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss, rp); pss.set_evac_closure(&scan_evac_cl); pss.set_evac_failure_closure(&evac_failure_cl); pss.set_partial_scan_closure(&partial_scan_cl); - G1ParScanExtRootClosure only_scan_root_cl(_g1h, &pss); - G1ParScanPermClosure only_scan_perm_cl(_g1h, &pss); - G1ParScanHeapRSClosure only_scan_heap_rs_cl(_g1h, &pss); - G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, &pss); - - G1ParScanAndMarkExtRootClosure scan_mark_root_cl(_g1h, &pss); - G1ParScanAndMarkPermClosure scan_mark_perm_cl(_g1h, &pss); - G1ParScanAndMarkHeapRSClosure scan_mark_heap_rs_cl(_g1h, &pss); - - OopsInHeapRegionClosure *scan_root_cl; - OopsInHeapRegionClosure *scan_perm_cl; + G1ParScanExtRootClosure only_scan_root_cl(_g1h, &pss, rp); + G1ParScanPermClosure only_scan_perm_cl(_g1h, &pss, rp); + + G1ParScanAndMarkExtRootClosure scan_mark_root_cl(_g1h, &pss, rp); + G1ParScanAndMarkPermClosure scan_mark_perm_cl(_g1h, &pss, rp); + + OopClosure* scan_root_cl = &only_scan_root_cl; + OopsInHeapRegionClosure* scan_perm_cl = &only_scan_perm_cl; if (_g1h->g1_policy()->during_initial_mark_pause()) { + // We also need to mark copied objects. scan_root_cl = &scan_mark_root_cl; scan_perm_cl = &scan_mark_perm_cl; - } else { - scan_root_cl = &only_scan_root_cl; - scan_perm_cl = &only_scan_perm_cl; } + G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, &pss); + pss.start_strong_roots(); _g1h->g1_process_strong_roots(/* not collecting perm */ false, SharedHeap::SO_AllClasses, @@ -4577,6 +4660,7 @@ OopsInHeapRegionClosure* scan_rs, OopsInGenClosure* scan_perm, int worker_i) { + // First scan the strong roots, including the perm gen. double ext_roots_start = os::elapsedTime(); double closure_app_time_sec = 0.0; @@ -4595,12 +4679,13 @@ &eager_scan_code_roots, &buf_scan_perm); - // Now the ref_processor roots. + // Now the CM ref_processor roots. if (!_process_strong_tasks->is_task_claimed(G1H_PS_refProcessor_oops_do)) { - // We need to treat the discovered reference lists as roots and - // keep entries (which are added by the marking threads) on them - // live until they can be processed at the end of marking. - ref_processor()->weak_oops_do(&buf_scan_non_heap_roots); + // We need to treat the discovered reference lists of the + // concurrent mark ref processor as roots and keep entries + // (which are added by the marking threads) on them live + // until they can be processed at the end of marking. + ref_processor_cm()->weak_oops_do(&buf_scan_non_heap_roots); } // Finish up any enqueued closure apps (attributed as object copy time). @@ -4641,6 +4726,524 @@ SharedHeap::process_weak_roots(root_closure, &roots_in_blobs, non_root_closure); } +// Weak Reference Processing support + +// An always "is_alive" closure that is used to preserve referents. +// If the object is non-null then it's alive. Used in the preservation +// of referent objects that are pointed to by reference objects +// discovered by the CM ref processor. +class G1AlwaysAliveClosure: public BoolObjectClosure { + G1CollectedHeap* _g1; +public: + G1AlwaysAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} + void do_object(oop p) { assert(false, "Do not call."); } + bool do_object_b(oop p) { + if (p != NULL) { + return true; + } + return false; + } +}; + +bool G1STWIsAliveClosure::do_object_b(oop p) { + // An object is reachable if it is outside the collection set, + // or is inside and copied. + return !_g1->obj_in_cs(p) || p->is_forwarded(); +} + +// Non Copying Keep Alive closure +class G1KeepAliveClosure: public OopClosure { + G1CollectedHeap* _g1; +public: + G1KeepAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} + void do_oop(narrowOop* p) { guarantee(false, "Not needed"); } + void do_oop( oop* p) { + oop obj = *p; + + if (_g1->obj_in_cs(obj)) { + assert( obj->is_forwarded(), "invariant" ); + *p = obj->forwardee(); + } + } +}; + +// Copying Keep Alive closure - can be called from both +// serial and parallel code as long as different worker +// threads utilize different G1ParScanThreadState instances +// and different queues. + +class G1CopyingKeepAliveClosure: public OopClosure { + G1CollectedHeap* _g1h; + OopClosure* _copy_non_heap_obj_cl; + OopsInHeapRegionClosure* _copy_perm_obj_cl; + G1ParScanThreadState* _par_scan_state; + +public: + G1CopyingKeepAliveClosure(G1CollectedHeap* g1h, + OopClosure* non_heap_obj_cl, + OopsInHeapRegionClosure* perm_obj_cl, + G1ParScanThreadState* pss): + _g1h(g1h), + _copy_non_heap_obj_cl(non_heap_obj_cl), + _copy_perm_obj_cl(perm_obj_cl), + _par_scan_state(pss) + {} + + 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); + + if (_g1h->obj_in_cs(obj)) { + // If the referent object has been forwarded (either copied + // to a new location or to itself in the event of an + // evacuation failure) then we need to update the reference + // field and, if both reference and referent are in the G1 + // heap, update the RSet for the referent. + // + // If the referent has not been forwarded then we have to keep + // it alive by policy. Therefore we have copy the referent. + // + // If the reference field is in the G1 heap then we can push + // on the PSS queue. When the queue is drained (after each + // phase of reference processing) the object and it's followers + // will be copied, the reference field set to point to the + // new location, and the RSet updated. Otherwise we need to + // use the the non-heap or perm closures directly to copy + // the refernt object and update the pointer, while avoiding + // updating the RSet. + + if (_g1h->is_in_g1_reserved(p)) { + _par_scan_state->push_on_queue(p); + } else { + // The reference field is not in the G1 heap. + if (_g1h->perm_gen()->is_in(p)) { + _copy_perm_obj_cl->do_oop(p); + } else { + _copy_non_heap_obj_cl->do_oop(p); + } + } + } + } +}; + +// Serial drain queue closure. Called as the 'complete_gc' +// closure for each discovered list in some of the +// reference processing phases. + +class G1STWDrainQueueClosure: public VoidClosure { +protected: + G1CollectedHeap* _g1h; + G1ParScanThreadState* _par_scan_state; + + G1ParScanThreadState* par_scan_state() { return _par_scan_state; } + +public: + G1STWDrainQueueClosure(G1CollectedHeap* g1h, G1ParScanThreadState* pss) : + _g1h(g1h), + _par_scan_state(pss) + { } + + void do_void() { + G1ParScanThreadState* const pss = par_scan_state(); + pss->trim_queue(); + } +}; + +// Parallel Reference Processing closures + +// Implementation of AbstractRefProcTaskExecutor for parallel reference +// processing during G1 evacuation pauses. + +class G1STWRefProcTaskExecutor: public AbstractRefProcTaskExecutor { +private: + G1CollectedHeap* _g1h; + RefToScanQueueSet* _queues; + WorkGang* _workers; + int _active_workers; + +public: + G1STWRefProcTaskExecutor(G1CollectedHeap* g1h, + WorkGang* workers, + RefToScanQueueSet *task_queues, + int n_workers) : + _g1h(g1h), + _queues(task_queues), + _workers(workers), + _active_workers(n_workers) + { + assert(n_workers > 0, "shouldn't call this otherwise"); + } + + // Executes the given task using concurrent marking worker threads. + virtual void execute(ProcessTask& task); + virtual void execute(EnqueueTask& task); +}; + +// Gang task for possibly parallel reference processing + +class G1STWRefProcTaskProxy: public AbstractGangTask { + typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask; + ProcessTask& _proc_task; + G1CollectedHeap* _g1h; + RefToScanQueueSet *_task_queues; + ParallelTaskTerminator* _terminator; + +public: + G1STWRefProcTaskProxy(ProcessTask& proc_task, + G1CollectedHeap* g1h, + RefToScanQueueSet *task_queues, + ParallelTaskTerminator* terminator) : + AbstractGangTask("Process reference objects in parallel"), + _proc_task(proc_task), + _g1h(g1h), + _task_queues(task_queues), + _terminator(terminator) + {} + + virtual void work(int i) { + // The reference processing task executed by a single worker. + ResourceMark rm; + HandleMark hm; + + G1STWIsAliveClosure is_alive(_g1h); + + G1ParScanThreadState pss(_g1h, i); + + G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss, NULL); + G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, NULL); + G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss, NULL); + + pss.set_evac_closure(&scan_evac_cl); + pss.set_evac_failure_closure(&evac_failure_cl); + pss.set_partial_scan_closure(&partial_scan_cl); + + G1ParScanExtRootClosure only_copy_non_heap_cl(_g1h, &pss, NULL); + G1ParScanPermClosure only_copy_perm_cl(_g1h, &pss, NULL); + + G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(_g1h, &pss, NULL); + G1ParScanAndMarkPermClosure copy_mark_perm_cl(_g1h, &pss, NULL); + + OopClosure* copy_non_heap_cl = &only_copy_non_heap_cl; + OopsInHeapRegionClosure* copy_perm_cl = &only_copy_perm_cl; + + if (_g1h->g1_policy()->during_initial_mark_pause()) { + // We also need to mark copied objects. + copy_non_heap_cl = ©_mark_non_heap_cl; + copy_perm_cl = ©_mark_perm_cl; + } + + // Keep alive closure. + G1CopyingKeepAliveClosure keep_alive(_g1h, copy_non_heap_cl, copy_perm_cl, &pss); + + // Complete GC closure + G1ParEvacuateFollowersClosure drain_queue(_g1h, &pss, _task_queues, _terminator); + + // Call the reference processing task's work routine. + _proc_task.work(i, is_alive, keep_alive, drain_queue); + + // Note we cannot assert that the refs array is empty here as not all + // of the processing tasks (specifically phase2 - pp2_work) execute + // the complete_gc closure (which ordinarily would drain the queue) so + // the queue may not be empty. + } +}; + +// Driver routine for parallel reference processing. +// Creates an instance of the ref processing gang +// task and has the worker threads execute it. +void G1STWRefProcTaskExecutor::execute(ProcessTask& proc_task) { + assert(_workers != NULL, "Need parallel worker threads."); + + ParallelTaskTerminator terminator(_active_workers, _queues); + G1STWRefProcTaskProxy proc_task_proxy(proc_task, _g1h, _queues, &terminator); + + _g1h->set_par_threads(_active_workers); + _workers->run_task(&proc_task_proxy); + _g1h->set_par_threads(0); +} + +// Gang task for parallel reference enqueueing. + +class G1STWRefEnqueueTaskProxy: public AbstractGangTask { + typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask; + EnqueueTask& _enq_task; + +public: + G1STWRefEnqueueTaskProxy(EnqueueTask& enq_task) : + AbstractGangTask("Enqueue reference objects in parallel"), + _enq_task(enq_task) + { } + + virtual void work(int i) { + _enq_task.work(i); + } +}; + +// Driver routine for parallel reference enqueing. +// Creates an instance of the ref enqueueing gang +// task and has the worker threads execute it. + +void G1STWRefProcTaskExecutor::execute(EnqueueTask& enq_task) { + assert(_workers != NULL, "Need parallel worker threads."); + + G1STWRefEnqueueTaskProxy enq_task_proxy(enq_task); + + _g1h->set_par_threads(_active_workers); + _workers->run_task(&enq_task_proxy); + _g1h->set_par_threads(0); +} + +// End of weak reference support closures + +// Abstract task used to preserve (i.e. copy) any referent objects +// that are in the collection set and are pointed to by reference +// objects discovered by the CM ref processor. + +class G1ParPreserveCMReferentsTask: public AbstractGangTask { +protected: + G1CollectedHeap* _g1h; + RefToScanQueueSet *_queues; + ParallelTaskTerminator _terminator; + int _n_workers; + +public: + G1ParPreserveCMReferentsTask(G1CollectedHeap* g1h,int workers, RefToScanQueueSet *task_queues) : + AbstractGangTask("ParPreserveCMReferents"), + _g1h(g1h), + _queues(task_queues), + _terminator(workers, _queues), + _n_workers(workers) + { } + + void work(int i) { + ResourceMark rm; + HandleMark hm; + + G1ParScanThreadState pss(_g1h, i); + G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss, NULL); + G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, NULL); + G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss, NULL); + + pss.set_evac_closure(&scan_evac_cl); + pss.set_evac_failure_closure(&evac_failure_cl); + pss.set_partial_scan_closure(&partial_scan_cl); + + assert(pss.refs()->is_empty(), "both queue and overflow should be empty"); + + + G1ParScanExtRootClosure only_copy_non_heap_cl(_g1h, &pss, NULL); + G1ParScanPermClosure only_copy_perm_cl(_g1h, &pss, NULL); + + G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(_g1h, &pss, NULL); + G1ParScanAndMarkPermClosure copy_mark_perm_cl(_g1h, &pss, NULL); + + OopClosure* copy_non_heap_cl = &only_copy_non_heap_cl; + OopsInHeapRegionClosure* copy_perm_cl = &only_copy_perm_cl; + + if (_g1h->g1_policy()->during_initial_mark_pause()) { + // We also need to mark copied objects. + copy_non_heap_cl = ©_mark_non_heap_cl; + copy_perm_cl = ©_mark_perm_cl; + } + + // Is alive closure + G1AlwaysAliveClosure always_alive(_g1h); + + // Copying keep alive closure. Applied to referent objects that need + // to be copied. + G1CopyingKeepAliveClosure keep_alive(_g1h, copy_non_heap_cl, copy_perm_cl, &pss); + + ReferenceProcessor* rp = _g1h->ref_processor_cm(); + + int limit = ReferenceProcessor::number_of_subclasses_of_ref() * rp->max_num_q(); + int stride = MIN2(MAX2(_n_workers, 1), limit); + + // limit is set using max_num_q() - which was set using ParallelGCThreads. + // So this must be true - but assert just in case someone decides to + // change the worker ids. + assert(0 <= i && i < limit, "sanity"); + assert(!rp->discovery_is_atomic(), "check this code"); + + // Select discovered lists [i, i+stride, i+2*stride,...,limit) + for (int idx = i; idx < limit; idx += stride) { + DiscoveredList& ref_list = rp->discovered_refs()[idx]; + + DiscoveredListIterator iter(ref_list, &keep_alive, &always_alive); + while (iter.has_next()) { + // Since discovery is not atomic for the CM ref processor, we + // can see some null referent objects. + iter.load_ptrs(DEBUG_ONLY(true)); + oop ref = iter.obj(); + + // This will filter nulls. + if (iter.is_referent_alive()) { + iter.make_referent_alive(); + } + iter.move_to_next(); + } + } + + // Drain the queue - which may cause stealing + G1ParEvacuateFollowersClosure drain_queue(_g1h, &pss, _queues, &_terminator); + drain_queue.do_void(); + // Allocation buffers were retired at the end of G1ParEvacuateFollowersClosure + assert(pss.refs()->is_empty(), "should be"); + } +}; + +// Weak Reference processing during an evacuation pause (part 1). +void G1CollectedHeap::process_discovered_references() { + double ref_proc_start = os::elapsedTime(); + + ReferenceProcessor* rp = _ref_processor_stw; + assert(rp->discovery_enabled(), "should have been enabled"); + + // Any reference objects, in the collection set, that were 'discovered' + // by the CM ref processor should have already been copied (either by + // applying the external root copy closure to the discovered lists, or + // by following an RSet entry). + // + // But some of the referents, that are in the collection set, that these + // reference objects point to may not have been copied: the STW ref + // processor would have seen that the reference object had already + // been 'discovered' and would have skipped discovering the reference, + // but would not have treated the reference object as a regular oop. + // As a reult the copy closure would not have been applied to the + // referent object. + // + // We need to explicitly copy these referent objects - the references + // will be processed at the end of remarking. + // + // We also need to do this copying before we process the reference + // objects discovered by the STW ref processor in case one of these + // referents points to another object which is also referenced by an + // object discovered by the STW ref processor. + + int n_workers = (G1CollectedHeap::use_parallel_gc_threads() ? + workers()->total_workers() : 1); + + set_par_threads(n_workers); + G1ParPreserveCMReferentsTask keep_cm_referents(this, n_workers, _task_queues); + + if (G1CollectedHeap::use_parallel_gc_threads()) { + workers()->run_task(&keep_cm_referents); + } else { + keep_cm_referents.work(0); + } + + set_par_threads(0); + + // Closure to test whether a referent is alive. + G1STWIsAliveClosure is_alive(this); + + // Even when parallel reference processing is enabled, the processing + // of JNI refs is serial and performed serially by the current thread + // rather than by a worker. The following PSS will be used for processing + // JNI refs. + + // Use only a single queue for this PSS. + G1ParScanThreadState pss(this, 0); + + // We do not embed a reference processor in the copying/scanning + // closures while we're actually processing the discovered + // reference objects. + G1ParScanHeapEvacClosure scan_evac_cl(this, &pss, NULL); + G1ParScanHeapEvacFailureClosure evac_failure_cl(this, &pss, NULL); + G1ParScanPartialArrayClosure partial_scan_cl(this, &pss, NULL); + + pss.set_evac_closure(&scan_evac_cl); + pss.set_evac_failure_closure(&evac_failure_cl); + pss.set_partial_scan_closure(&partial_scan_cl); + + assert(pss.refs()->is_empty(), "pre-condition"); + + G1ParScanExtRootClosure only_copy_non_heap_cl(this, &pss, NULL); + G1ParScanPermClosure only_copy_perm_cl(this, &pss, NULL); + + G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(this, &pss, NULL); + G1ParScanAndMarkPermClosure copy_mark_perm_cl(this, &pss, NULL); + + OopClosure* copy_non_heap_cl = &only_copy_non_heap_cl; + OopsInHeapRegionClosure* copy_perm_cl = &only_copy_perm_cl; + + if (_g1h->g1_policy()->during_initial_mark_pause()) { + // We also need to mark copied objects. + copy_non_heap_cl = ©_mark_non_heap_cl; + copy_perm_cl = ©_mark_perm_cl; + } + + // Keep alive closure. + G1CopyingKeepAliveClosure keep_alive(this, copy_non_heap_cl, copy_perm_cl, &pss); + + // Serial Complete GC closure + G1STWDrainQueueClosure drain_queue(this, &pss); + + // Setup the soft refs policy... + rp->setup_policy(false); + + if (!rp->processing_is_mt()) { + // Serial reference processing... + rp->process_discovered_references(&is_alive, + &keep_alive, + &drain_queue, + NULL); + } else { + // Parallel reference processing + int active_workers = (ParallelGCThreads > 0 ? workers()->total_workers() : 1); + assert(rp->num_q() == active_workers, "sanity"); + assert(active_workers <= rp->max_num_q(), "sanity"); + + G1STWRefProcTaskExecutor par_task_executor(this, workers(), _task_queues, active_workers); + rp->process_discovered_references(&is_alive, &keep_alive, &drain_queue, &par_task_executor); + } + + // We have completed copying any necessary live referent objects + // (that were not copied during the actual pause) so we can + // retire any active alloc buffers + pss.retire_alloc_buffers(); + assert(pss.refs()->is_empty(), "both queue and overflow should be empty"); + + double ref_proc_time = os::elapsedTime() - ref_proc_start; + g1_policy()->record_ref_proc_time(ref_proc_time * 1000.0); +} + +// Weak Reference processing during an evacuation pause (part 2). +void G1CollectedHeap::enqueue_discovered_references() { + double ref_enq_start = os::elapsedTime(); + + ReferenceProcessor* rp = _ref_processor_stw; + assert(!rp->discovery_enabled(), "should have been disabled as part of processing"); + + // Now enqueue any remaining on the discovered lists on to + // the pending list. + if (!rp->processing_is_mt()) { + // Serial reference processing... + rp->enqueue_discovered_references(); + } else { + // Parallel reference enqueuing + + int active_workers = (ParallelGCThreads > 0 ? workers()->total_workers() : 1); + assert(rp->num_q() == active_workers, "sanity"); + assert(active_workers <= rp->max_num_q(), "sanity"); + + G1STWRefProcTaskExecutor par_task_executor(this, workers(), _task_queues, active_workers); + rp->enqueue_discovered_references(&par_task_executor); + } + + rp->verify_no_references_recorded(); + assert(!rp->discovery_enabled(), "should have been disabled"); + + // FIXME + // CM's reference processing also cleans up the string and symbol tables. + // Should we do that here also? We could, but it is a serial operation + // and could signicantly increase the pause time. + + double ref_enq_time = os::elapsedTime() - ref_enq_start; + g1_policy()->record_ref_enq_time(ref_enq_time * 1000.0); +} + void G1CollectedHeap::evacuate_collection_set() { set_evacuation_failed(false); @@ -4658,6 +5261,7 @@ assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty"); double start_par = os::elapsedTime(); + if (G1CollectedHeap::use_parallel_gc_threads()) { // The individual threads will set their evac-failure closures. StrongRootsScope srs(this); @@ -4672,15 +5276,23 @@ g1_policy()->record_par_time(par_time); set_par_threads(0); + // Process any discovered reference objects - we have + // to do this _before_ we retire the GC alloc regions + // as we may have to copy some 'reachable' referent + // objects (and their reachable sub-graphs) that were + // not copied during the pause. + process_discovered_references(); + // Weak root processing. // Note: when JSR 292 is enabled and code blobs can contain // non-perm oops then we will need to process the code blobs // here too. { - G1IsAliveClosure is_alive(this); + G1STWIsAliveClosure is_alive(this); G1KeepAliveClosure keep_alive(this); JNIHandles::weak_oops_do(&is_alive, &keep_alive); } + release_gc_alloc_regions(); g1_rem_set()->cleanup_after_oops_into_collection_set_do(); @@ -4702,6 +5314,15 @@ } } + // Enqueue any remaining references remaining on the STW + // reference processor's discovered lists. We need to do + // this after the card table is cleaned (and verified) as + // the act of enqueuing entries on to the pending list + // will log these updates (and dirty their associated + // cards). We need these updates logged to update any + // RSets. + enqueue_discovered_references(); + if (G1DeferredRSUpdate) { RedirtyLoggedCardTableEntryFastClosure redirty; dirty_card_queue_set().set_closure(&redirty); @@ -4902,7 +5523,7 @@ } double elapsed = os::elapsedTime() - start; - g1_policy()->record_clear_ct_time( elapsed * 1000.0); + g1_policy()->record_clear_ct_time(elapsed * 1000.0); #ifndef PRODUCT if (G1VerifyCTCleanup || VerifyAfterGC) { G1VerifyCardTableCleanup cleanup_verifier(this, ct_bs); @@ -5193,7 +5814,6 @@ g1_policy()->update_region_num(true /* next_is_young */); set_region_short_lived_locked(new_alloc_region); _hr_printer.alloc(new_alloc_region, G1HRPrinter::Eden, young_list_full); - g1mm()->update_eden_counters(); return new_alloc_region; } } @@ -5208,6 +5828,10 @@ g1_policy()->add_region_to_incremental_cset_lhs(alloc_region); _summary_bytes_used += allocated_bytes; _hr_printer.retire(alloc_region); + // We update the eden sizes here, when the region is retired, + // instead of when it's allocated, since this is the point that its + // used space has been recored in _summary_bytes_used. + g1mm()->update_eden_size(); } HeapRegion* MutatorAllocRegion::allocate_new_region(size_t word_size,
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -155,6 +155,19 @@ : G1AllocRegion("Mutator Alloc Region", false /* bot_updates */) { } }; +// The G1 STW is alive closure. +// An instance is embedded into the G1CH and used as the +// (optional) _is_alive_non_header closure in the STW +// reference processor. It is also extensively used during +// refence processing during STW evacuation pauses. +class G1STWIsAliveClosure: public BoolObjectClosure { + G1CollectedHeap* _g1; +public: + G1STWIsAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} + void do_object(oop p) { assert(false, "Do not call."); } + bool do_object_b(oop p); +}; + class SurvivorGCAllocRegion : public G1AllocRegion { protected: virtual HeapRegion* allocate_new_region(size_t word_size, bool force); @@ -174,6 +187,7 @@ }; class RefineCardTableEntryClosure; + class G1CollectedHeap : public SharedHeap { friend class VM_G1CollectForAllocation; friend class VM_GenCollectForPermanentAllocation; @@ -573,9 +587,20 @@ // allocated block, or else "NULL". HeapWord* expand_and_allocate(size_t word_size); + // Process any reference objects discovered during + // an incremental evacuation pause. + void process_discovered_references(); + + // Enqueue any remaining discovered references + // after processing. + void enqueue_discovered_references(); + public: - G1MonitoringSupport* g1mm() { return _g1mm; } + G1MonitoringSupport* g1mm() { + assert(_g1mm != NULL, "should have been initialized"); + return _g1mm; + } // Expand the garbage-first heap by at least the given size (in bytes!). // Returns true if the heap was expanded by the requested amount; @@ -822,17 +847,87 @@ void finalize_for_evac_failure(); // An attempt to evacuate "obj" has failed; take necessary steps. - oop handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, oop obj); + oop handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, oop obj, + bool should_mark_root); void handle_evacuation_failure_common(oop obj, markOop m); + // ("Weak") Reference processing support. + // + // G1 has 2 instances of the referece processor class. One + // (_ref_processor_cm) handles reference object discovery + // and subsequent processing during concurrent marking cycles. + // + // The other (_ref_processor_stw) handles reference object + // discovery and processing during full GCs and incremental + // evacuation pauses. + // + // During an incremental pause, reference discovery will be + // temporarily disabled for _ref_processor_cm and will be + // enabled for _ref_processor_stw. At the end of the evacuation + // pause references discovered by _ref_processor_stw will be + // processed and discovery will be disabled. The previous + // setting for reference object discovery for _ref_processor_cm + // will be re-instated. + // + // At the start of marking: + // * Discovery by the CM ref processor is verified to be inactive + // and it's discovered lists are empty. + // * Discovery by the CM ref processor is then enabled. + // + // At the end of marking: + // * Any references on the CM ref processor's discovered + // lists are processed (possibly MT). + // + // At the start of full GC we: + // * Disable discovery by the CM ref processor and + // empty CM ref processor's discovered lists + // (without processing any entries). + // * Verify that the STW ref processor is inactive and it's + // discovered lists are empty. + // * Temporarily set STW ref processor discovery as single threaded. + // * Temporarily clear the STW ref processor's _is_alive_non_header + // field. + // * Finally enable discovery by the STW ref processor. + // + // The STW ref processor is used to record any discovered + // references during the full GC. + // + // At the end of a full GC we: + // * Enqueue any reference objects discovered by the STW ref processor + // that have non-live referents. This has the side-effect of + // making the STW ref processor inactive by disabling discovery. + // * Verify that the CM ref processor is still inactive + // and no references have been placed on it's discovered + // lists (also checked as a precondition during initial marking). + + // The (stw) reference processor... + ReferenceProcessor* _ref_processor_stw; + + // During reference object discovery, the _is_alive_non_header + // closure (if non-null) is applied to the referent object to + // determine whether the referent is live. If so then the + // reference object does not need to be 'discovered' and can + // be treated as a regular oop. This has the benefit of reducing + // the number of 'discovered' reference objects that need to + // be processed. + // + // Instance of the is_alive closure for embedding into the + // STW reference processor as the _is_alive_non_header field. + // Supplying a value for the _is_alive_non_header field is + // optional but doing so prevents unnecessary additions to + // the discovered lists during reference discovery. + G1STWIsAliveClosure _is_alive_closure_stw; + + // The (concurrent marking) reference processor... + ReferenceProcessor* _ref_processor_cm; + // Instance of the concurrent mark is_alive closure for embedding - // into the reference processor as the is_alive_non_header. This - // prevents unnecessary additions to the discovered lists during - // concurrent discovery. - G1CMIsAliveClosure _is_alive_closure; - - // ("Weak") Reference processing support - ReferenceProcessor* _ref_processor; + // into the Concurrent Marking reference processor as the + // _is_alive_non_header field. Supplying a value for the + // _is_alive_non_header field is optional but doing so prevents + // unnecessary additions to the discovered lists during reference + // discovery. + G1CMIsAliveClosure _is_alive_closure_cm; enum G1H_process_strong_roots_tasks { G1H_PS_mark_stack_oops_do, @@ -873,6 +968,7 @@ // specified by the policy object. jint initialize(); + // Initialize weak reference processing. virtual void ref_processing_init(); void set_par_threads(int t) { @@ -924,8 +1020,13 @@ // The shared block offset table array. G1BlockOffsetSharedArray* bot_shared() const { return _bot_shared; } - // Reference Processing accessor - ReferenceProcessor* ref_processor() { return _ref_processor; } + // Reference Processing accessors + + // The STW reference processor.... + ReferenceProcessor* ref_processor_stw() const { return _ref_processor_stw; } + + // The Concurent Marking reference processor... + ReferenceProcessor* ref_processor_cm() const { return _ref_processor_cm; } virtual size_t capacity() const; virtual size_t used() const; @@ -1236,12 +1337,7 @@ // storage in the heap comes from a young region or not. // See ReduceInitialCardMarks. virtual bool can_elide_tlab_store_barriers() const { - // 6920090: Temporarily disabled, because of lingering - // instabilities related to RICM with G1. In the - // interim, the option ReduceInitialCardMarksForG1 - // below is left solely as a debugging device at least - // until 6920109 fixes the instabilities. - return ReduceInitialCardMarksForG1; + return true; } virtual bool card_mark_must_follow_store() const { @@ -1265,8 +1361,6 @@ // update logging post-barrier, we don't maintain remembered set // information for young gen objects. virtual bool can_elide_initializing_store_barrier(oop new_obj) { - // Re 6920090, 6920109 above. - assert(ReduceInitialCardMarksForG1, "Else cannot be here"); return is_in_young(new_obj); }
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -152,8 +152,12 @@ _summary(new Summary()), + _cur_clear_ct_time_ms(0.0), + + _cur_ref_proc_time_ms(0.0), + _cur_ref_enq_time_ms(0.0), + #ifndef PRODUCT - _cur_clear_ct_time_ms(0.0), _min_clear_cc_time_ms(-1.0), _max_clear_cc_time_ms(-1.0), _cur_clear_cc_time_ms(0.0), @@ -221,16 +225,12 @@ _recent_CS_bytes_surviving(new TruncatedSeq(NumPrevPausesForHeuristics)), _recent_avg_pause_time_ratio(0.0), - _num_markings(0), - _n_marks(0), - _n_pauses_at_mark_end(0), _all_full_gc_times_ms(new NumberSeq()), // G1PausesBtwnConcMark defaults to -1 // so the hack is to do the cast QQQ FIXME _pauses_btwn_concurrent_mark((size_t)G1PausesBtwnConcMark), - _n_marks_since_last_pause(0), _initiate_conc_mark_if_possible(false), _during_initial_mark_pause(false), _should_revert_to_full_young_gcs(false), @@ -294,10 +294,10 @@ } // Verify PLAB sizes - const uint region_size = HeapRegion::GrainWords; + const size_t region_size = HeapRegion::GrainWords; if (YoungPLABSize > region_size || OldPLABSize > region_size) { char buffer[128]; - jio_snprintf(buffer, sizeof(buffer), "%sPLABSize should be at most %u", + jio_snprintf(buffer, sizeof(buffer), "%sPLABSize should be at most "SIZE_FORMAT, OldPLABSize > region_size ? "Old" : "Young", region_size); vm_exit_during_initialization(buffer); } @@ -436,6 +436,7 @@ _reserve_regions = 0; initialize_all(); + _collectionSetChooser = new CollectionSetChooser(); } // Increment "i", mod "len" @@ -459,15 +460,16 @@ // ParallelScavengeHeap::initialize()). We might change this in the // future, but it's a good start. class G1YoungGenSizer : public TwoGenerationCollectorPolicy { +private: + size_t size_to_region_num(size_t byte_size) { + return MAX2((size_t) 1, byte_size / HeapRegion::GrainBytes); + } public: G1YoungGenSizer() { initialize_flags(); initialize_size_info(); } - size_t size_to_region_num(size_t byte_size) { - return MAX2((size_t) 1, byte_size / HeapRegion::GrainBytes); - } size_t min_young_region_num() { return size_to_region_num(_min_gen0_size); } @@ -501,11 +503,10 @@ if (FLAG_IS_CMDLINE(NewRatio)) { if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) { - gclog_or_tty->print_cr("-XX:NewSize and -XX:MaxNewSize overrides -XX:NewRatio"); + warning("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio"); } else { // Treat NewRatio as a fixed size that is only recalculated when the heap size changes - size_t heap_regions = sizer.size_to_region_num(_g1->n_regions()); - update_young_list_size_using_newratio(heap_regions); + update_young_list_size_using_newratio(_g1->n_regions()); _using_new_ratio_calculations = true; } } @@ -917,6 +918,7 @@ // Reset survivors SurvRateGroup. _survivor_surv_rate_group->reset(); update_young_list_target_length(); + _collectionSetChooser->updateAfterFullCollection(); } void G1CollectorPolicy::record_stop_world_start() { @@ -1025,39 +1027,7 @@ _mark_cleanup_start_sec = os::elapsedTime(); } -void -G1CollectorPolicy::record_concurrent_mark_cleanup_end(size_t freed_bytes, - size_t max_live_bytes) { - record_concurrent_mark_cleanup_end_work1(freed_bytes, max_live_bytes); - record_concurrent_mark_cleanup_end_work2(); -} - -void -G1CollectorPolicy:: -record_concurrent_mark_cleanup_end_work1(size_t freed_bytes, - size_t max_live_bytes) { - if (_n_marks < 2) { - _n_marks++; - } -} - -// The important thing about this is that it includes "os::elapsedTime". -void G1CollectorPolicy::record_concurrent_mark_cleanup_end_work2() { - double end_time_sec = os::elapsedTime(); - double elapsed_time_ms = (end_time_sec - _mark_cleanup_start_sec)*1000.0; - _concurrent_mark_cleanup_times_ms->add(elapsed_time_ms); - _cur_mark_stop_world_time_ms += elapsed_time_ms; - _prev_collection_pause_end_ms += elapsed_time_ms; - - _mmu_tracker->add_pause(_mark_cleanup_start_sec, end_time_sec, true); - - _num_markings++; - _n_pauses_at_mark_end = _n_pauses; - _n_marks_since_last_pause++; -} - -void -G1CollectorPolicy::record_concurrent_mark_cleanup_completed() { +void G1CollectorPolicy::record_concurrent_mark_cleanup_completed() { _should_revert_to_full_young_gcs = false; _last_full_young_gc = true; _in_marking_window = false; @@ -1479,6 +1449,8 @@ #endif print_stats(1, "Other", other_time_ms); print_stats(2, "Choose CSet", _recorded_young_cset_choice_time_ms); + print_stats(2, "Ref Proc", _cur_ref_proc_time_ms); + print_stats(2, "Ref Enq", _cur_ref_enq_time_ms); for (int i = 0; i < _aux_num; ++i) { if (_cur_aux_times_set[i]) { @@ -1495,11 +1467,9 @@ summary->record_other_time_ms(other_time_ms); } for (int i = 0; i < _aux_num; ++i) - if (_cur_aux_times_set[i]) + if (_cur_aux_times_set[i]) { _all_aux_times_ms[i].add(_cur_aux_times_ms[i]); - - // Reset marks-between-pauses counter. - _n_marks_since_last_pause = 0; + } // Update the efficiency-since-mark vars. double proc_ms = elapsed_ms * (double) _parallel_gc_threads; @@ -1519,11 +1489,17 @@ } if (_last_full_young_gc) { - ergo_verbose2(ErgoPartiallyYoungGCs, - "start partially-young GCs", - ergo_format_byte_perc("known garbage"), - _known_garbage_bytes, _known_garbage_ratio * 100.0); - set_full_young_gcs(false); + if (!last_pause_included_initial_mark) { + ergo_verbose2(ErgoPartiallyYoungGCs, + "start partially-young GCs", + ergo_format_byte_perc("known garbage"), + _known_garbage_bytes, _known_garbage_ratio * 100.0); + set_full_young_gcs(false); + } else { + ergo_verbose0(ErgoPartiallyYoungGCs, + "do not start partially-young GCs", + ergo_format_reason("concurrent cycle is about to start")); + } _last_full_young_gc = false; } @@ -1717,6 +1693,8 @@ double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0; adjust_concurrent_refinement(update_rs_time, update_rs_processed_buffers, update_rs_time_goal_ms); // </NEW PREDICTION> + + assert(assertMarkedBytesDataOK(), "Marked regions not OK at pause end."); } #define EXT_SIZE_FORMAT "%d%s" @@ -2144,10 +2122,6 @@ } } -void G1CollectorPolicy::note_start_of_mark_thread() { - _mark_thread_startup_sec = os::elapsedTime(); -} - class CountCSClosure: public HeapRegionClosure { G1CollectorPolicy* _g1_policy; public: @@ -2434,7 +2408,7 @@ } }; -bool G1CollectorPolicy_BestRegionsFirst::assertMarkedBytesDataOK() { +bool G1CollectorPolicy::assertMarkedBytesDataOK() { HRSortIndexIsOKClosure cl(_collectionSetChooser); _g1->heap_region_iterate(&cl); return true; @@ -2485,6 +2459,13 @@ // initiate a new cycle. set_during_initial_mark_pause(); + // We do not allow non-full young GCs during marking. + if (!full_young_gcs()) { + set_full_young_gcs(true); + ergo_verbose0(ErgoPartiallyYoungGCs, + "end partially-young GCs", + ergo_format_reason("concurrent cycle is about to start")); + } // And we can now clear initiate_conc_mark_if_possible() as // we've already acted on it. @@ -2513,12 +2494,6 @@ } } -void -G1CollectorPolicy_BestRegionsFirst:: -record_collection_pause_start(double start_time_sec, size_t start_used) { - G1CollectorPolicy::record_collection_pause_start(start_time_sec, start_used); -} - class KnownGarbageClosure: public HeapRegionClosure { CollectionSetChooser* _hrSorted; @@ -2626,20 +2601,20 @@ }; void -G1CollectorPolicy_BestRegionsFirst:: -record_concurrent_mark_cleanup_end(size_t freed_bytes, - size_t max_live_bytes) { - double start; - if (G1PrintParCleanupStats) start = os::elapsedTime(); - record_concurrent_mark_cleanup_end_work1(freed_bytes, max_live_bytes); +G1CollectorPolicy::record_concurrent_mark_cleanup_end() { + double start_sec; + if (G1PrintParCleanupStats) { + start_sec = os::elapsedTime(); + } _collectionSetChooser->clearMarkedHeapRegions(); - double clear_marked_end; + double clear_marked_end_sec; if (G1PrintParCleanupStats) { - clear_marked_end = os::elapsedTime(); - gclog_or_tty->print_cr(" clear marked regions + work1: %8.3f ms.", - (clear_marked_end - start)*1000.0); + clear_marked_end_sec = os::elapsedTime(); + gclog_or_tty->print_cr(" clear marked regions: %8.3f ms.", + (clear_marked_end_sec - start_sec) * 1000.0); } + if (G1CollectedHeap::use_parallel_gc_threads()) { const size_t OverpartitionFactor = 4; const size_t MinWorkUnit = 8; @@ -2658,27 +2633,25 @@ KnownGarbageClosure knownGarbagecl(_collectionSetChooser); _g1->heap_region_iterate(&knownGarbagecl); } - double known_garbage_end; + double known_garbage_end_sec; if (G1PrintParCleanupStats) { - known_garbage_end = os::elapsedTime(); + known_garbage_end_sec = os::elapsedTime(); gclog_or_tty->print_cr(" compute known garbage: %8.3f ms.", - (known_garbage_end - clear_marked_end)*1000.0); + (known_garbage_end_sec - clear_marked_end_sec) * 1000.0); } + _collectionSetChooser->sortMarkedHeapRegions(); - double sort_end; + double end_sec = os::elapsedTime(); if (G1PrintParCleanupStats) { - sort_end = os::elapsedTime(); gclog_or_tty->print_cr(" sorting: %8.3f ms.", - (sort_end - known_garbage_end)*1000.0); + (end_sec - known_garbage_end_sec) * 1000.0); } - record_concurrent_mark_cleanup_end_work2(); - double work2_end; - if (G1PrintParCleanupStats) { - work2_end = os::elapsedTime(); - gclog_or_tty->print_cr(" work2: %8.3f ms.", - (work2_end - sort_end)*1000.0); - } + double elapsed_time_ms = (end_sec - _mark_cleanup_start_sec) * 1000.0; + _concurrent_mark_cleanup_times_ms->add(elapsed_time_ms); + _cur_mark_stop_world_time_ms += elapsed_time_ms; + _prev_collection_pause_end_ms += elapsed_time_ms; + _mmu_tracker->add_pause(_mark_cleanup_start_sec, end_sec, true); } // Add the heap region at the head of the non-incremental collection set @@ -2893,9 +2866,7 @@ } #endif // !PRODUCT -void -G1CollectorPolicy_BestRegionsFirst::choose_collection_set( - double target_pause_time_ms) { +void G1CollectorPolicy::choose_collection_set(double target_pause_time_ms) { // Set this here - in case we're not doing young collections. double non_young_start_time_sec = os::elapsedTime(); @@ -3096,14 +3067,3 @@ _recorded_non_young_cset_choice_time_ms = (non_young_end_time_sec - non_young_start_time_sec) * 1000.0; } - -void G1CollectorPolicy_BestRegionsFirst::record_full_collection_end() { - G1CollectorPolicy::record_full_collection_end(); - _collectionSetChooser->updateAfterFullCollection(); -} - -void G1CollectorPolicy_BestRegionsFirst:: -record_collection_pause_end() { - G1CollectorPolicy::record_collection_pause_end(); - assert(assertMarkedBytesDataOK(), "Marked regions not OK at pause end."); -}
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -84,7 +84,7 @@ }; class G1CollectorPolicy: public CollectorPolicy { -protected: +private: // The number of pauses during the execution. long _n_pauses; @@ -106,10 +106,7 @@ initialize_perm_generation(PermGen::MarkSweepCompact); } - virtual size_t default_init_heap_size() { - // Pick some reasonable default. - return 8*M; - } + CollectionSetChooser* _collectionSetChooser; double _cur_collection_start_sec; size_t _cur_collection_pause_used_at_start_bytes; @@ -119,6 +116,8 @@ double _cur_satb_drain_time_ms; double _cur_clear_ct_time_ms; bool _satb_drain_time_set; + double _cur_ref_proc_time_ms; + double _cur_ref_enq_time_ms; #ifndef PRODUCT // Card Table Count Cache stats @@ -314,7 +313,6 @@ double update_rs_processed_buffers, double goal_ms); -protected: double _pause_time_target_ms; double _recorded_young_cset_choice_time_ms; double _recorded_non_young_cset_choice_time_ms; @@ -552,7 +550,7 @@ return _short_lived_surv_rate_group->accum_surv_rate_pred(age); } -protected: +private: void print_stats(int level, const char* str, double value); void print_stats(int level, const char* str, int value); @@ -586,10 +584,6 @@ // Statistics kept per GC stoppage, pause or full. TruncatedSeq* _recent_prev_end_times_for_all_gcs_sec; - // We track markings. - int _num_markings; - double _mark_thread_startup_sec; // Time at startup of marking thread - // Add a new GC of the given duration and end time to the record. void update_recent_gc_times(double end_time_sec, double elapsed_ms); @@ -662,12 +656,6 @@ // young list/collection set). size_t _inc_cset_predicted_bytes_to_copy; - // Info about marking. - int _n_marks; // Sticky at 2, so we know when we've done at least 2. - - // The number of collection pauses at the end of the last mark. - size_t _n_pauses_at_mark_end; - // Stash a pointer to the g1 heap. G1CollectedHeap* _g1; @@ -735,8 +723,6 @@ // Number of pauses between concurrent marking. size_t _pauses_btwn_concurrent_mark; - size_t _n_marks_since_last_pause; - // At the end of a pause we check the heap occupancy and we decide // whether we will start a marking cycle during the next pause. If // we decide that we want to do that, we will set this parameter to @@ -808,6 +794,11 @@ bool predict_will_fit(size_t young_length, double base_time_ms, size_t base_free_regions, double target_pause_time_ms); + // Count the number of bytes used in the CS. + void count_CS_bytes_used(); + + void update_young_list_size_using_newratio(size_t number_of_heap_regions); + public: G1CollectorPolicy(); @@ -834,22 +825,9 @@ // This should be called after the heap is resized. void record_new_heap_size(size_t new_number_of_regions); -protected: - - // Count the number of bytes used in the CS. - void count_CS_bytes_used(); - - // Together these do the base cleanup-recording work. Subclasses might - // want to put something between them. - void record_concurrent_mark_cleanup_end_work1(size_t freed_bytes, - size_t max_live_bytes); - void record_concurrent_mark_cleanup_end_work2(); - - void update_young_list_size_using_newratio(size_t number_of_heap_regions); - public: - virtual void init(); + void init(); // Create jstat counters for the policy. virtual void initialize_gc_policy_counters(); @@ -874,10 +852,9 @@ // start time, where the given number of bytes were used at the start. // This may involve changing the desired size of a collection set. - virtual void record_stop_world_start(); + void record_stop_world_start(); - virtual void record_collection_pause_start(double start_time_sec, - size_t start_used); + void record_collection_pause_start(double start_time_sec, size_t start_used); // Must currently be called while the world is stopped. void record_concurrent_mark_init_end(double @@ -885,23 +862,22 @@ void record_mark_closure_time(double mark_closure_time_ms); - virtual void record_concurrent_mark_remark_start(); - virtual void record_concurrent_mark_remark_end(); + void record_concurrent_mark_remark_start(); + void record_concurrent_mark_remark_end(); - virtual void record_concurrent_mark_cleanup_start(); - virtual void record_concurrent_mark_cleanup_end(size_t freed_bytes, - size_t max_live_bytes); - virtual void record_concurrent_mark_cleanup_completed(); + void record_concurrent_mark_cleanup_start(); + void record_concurrent_mark_cleanup_end(); + void record_concurrent_mark_cleanup_completed(); - virtual void record_concurrent_pause(); - virtual void record_concurrent_pause_end(); + void record_concurrent_pause(); + void record_concurrent_pause_end(); - virtual void record_collection_pause_end(); + void record_collection_pause_end(); void print_heap_transition(); // Record the fact that a full collection occurred. - virtual void record_full_collection_start(); - virtual void record_full_collection_end(); + void record_full_collection_start(); + void record_full_collection_end(); void record_gc_worker_start_time(int worker_i, double ms) { _par_last_gc_worker_start_times_ms[worker_i] = ms; @@ -986,6 +962,14 @@ _cur_aux_times_ms[i] += ms; } + void record_ref_proc_time(double ms) { + _cur_ref_proc_time_ms = ms; + } + + void record_ref_enq_time(double ms) { + _cur_ref_enq_time_ms = ms; + } + #ifndef PRODUCT void record_cc_clear_time(double ms) { if (_min_clear_cc_time_ms < 0.0 || ms <= _min_clear_cc_time_ms) @@ -1012,7 +996,7 @@ // Choose a new collection set. Marks the chosen regions as being // "in_collection_set", and links them together. The head and number of // the collection set are available via access methods. - virtual void choose_collection_set(double target_pause_time_ms) = 0; + void choose_collection_set(double target_pause_time_ms); // The head of the list (via "next_in_collection_set()") representing the // current collection set. @@ -1097,19 +1081,12 @@ // If an expansion would be appropriate, because recent GC overhead had // exceeded the desired limit, return an amount to expand by. - virtual size_t expansion_amount(); - - // note start of mark thread - void note_start_of_mark_thread(); - - // The marked bytes of the "r" has changed; reclassify it's desirability - // for marking. Also asserts that "r" is eligible for a CS. - virtual void note_change_in_marked_bytes(HeapRegion* r) = 0; + size_t expansion_amount(); #ifndef PRODUCT // Check any appropriate marked bytes info, asserting false if // something's wrong, else returning "true". - virtual bool assertMarkedBytesDataOK() = 0; + bool assertMarkedBytesDataOK(); #endif // Print tracing information. @@ -1139,6 +1116,10 @@ return young_list_length < young_list_max_length; } + size_t young_list_max_length() { + return _young_list_max_length; + } + void update_region_num(bool young); bool full_young_gcs() { @@ -1168,10 +1149,10 @@ return ret; } +private: // // Survivor regions policy. // -protected: // Current tenuring threshold, set to 0 if the collector reaches the // maximum amount of suvivors regions. @@ -1251,51 +1232,6 @@ }; -// This encapsulates a particular strategy for a g1 Collector. -// -// Start a concurrent mark when our heap size is n bytes -// greater then our heap size was at the last concurrent -// mark. Where n is a function of the CMSTriggerRatio -// and the MinHeapFreeRatio. -// -// Start a g1 collection pause when we have allocated the -// average number of bytes currently being freed in -// a collection, but only if it is at least one region -// full -// -// Resize Heap based on desired -// allocation space, where desired allocation space is -// a function of survival rate and desired future to size. -// -// Choose collection set by first picking all older regions -// which have a survival rate which beats our projected young -// survival rate. Then fill out the number of needed regions -// with young regions. - -class G1CollectorPolicy_BestRegionsFirst: public G1CollectorPolicy { - CollectionSetChooser* _collectionSetChooser; - - virtual void choose_collection_set(double target_pause_time_ms); - virtual void record_collection_pause_start(double start_time_sec, - size_t start_used); - virtual void record_concurrent_mark_cleanup_end(size_t freed_bytes, - size_t max_live_bytes); - virtual void record_full_collection_end(); - -public: - G1CollectorPolicy_BestRegionsFirst() { - _collectionSetChooser = new CollectionSetChooser(); - } - void record_collection_pause_end(); - // This is not needed any more, after the CSet choosing code was - // changed to use the pause prediction work. But let's leave the - // hook in just in case. - void note_change_in_marked_bytes(HeapRegion* r) { } -#ifndef PRODUCT - bool assertMarkedBytesDataOK(); -#endif -}; - // This should move to some place more general... // If we have "n" measurements, and we've kept track of their "sum" and the
--- a/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -62,6 +62,8 @@ // hook up weak ref data so it can be used during Mark-Sweep assert(GenMarkSweep::ref_processor() == NULL, "no stomping"); assert(rp != NULL, "should be non-NULL"); + assert(rp == G1CollectedHeap::heap()->ref_processor_stw(), "Precondition"); + GenMarkSweep::_ref_processor = rp; rp->setup_policy(clear_all_softrefs); @@ -139,6 +141,8 @@ // Process reference objects found during marking ReferenceProcessor* rp = GenMarkSweep::ref_processor(); + assert(rp == G1CollectedHeap::heap()->ref_processor_stw(), "Sanity"); + rp->setup_policy(clear_all_softrefs); rp->process_discovered_references(&GenMarkSweep::is_alive, &GenMarkSweep::keep_alive, @@ -166,7 +170,6 @@ GenMarkSweep::follow_mdo_weak_refs(); assert(GenMarkSweep::_marking_stack.is_empty(), "just drained"); - // Visit interned string tables and delete unmarked oops StringTable::unlink(&GenMarkSweep::is_alive); // Clean up unreferenced symbols in symbol table. @@ -346,7 +349,8 @@ NULL, // do not touch code cache here &GenMarkSweep::adjust_pointer_closure); - g1h->ref_processor()->weak_oops_do(&GenMarkSweep::adjust_root_pointer_closure); + assert(GenMarkSweep::ref_processor() == g1h->ref_processor_stw(), "Sanity"); + g1h->ref_processor_stw()->weak_oops_do(&GenMarkSweep::adjust_root_pointer_closure); // Now adjust pointers in remaining weak roots. (All of which should // have been cleared if they pointed to non-surviving objects.)
--- a/src/share/vm/gc_implementation/g1/g1MonitoringSupport.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1MonitoringSupport.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -27,19 +27,69 @@ #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1CollectorPolicy.hpp" -G1MonitoringSupport::G1MonitoringSupport(G1CollectedHeap* g1h, - VirtualSpace* g1_storage_addr) : +G1GenerationCounters::G1GenerationCounters(G1MonitoringSupport* g1mm, + const char* name, + int ordinal, int spaces, + size_t min_capacity, + size_t max_capacity, + size_t curr_capacity) + : GenerationCounters(name, ordinal, spaces, min_capacity, + max_capacity, curr_capacity), _g1mm(g1mm) { } + +// We pad the capacity three times given that the young generation +// contains three spaces (eden and two survivors). +G1YoungGenerationCounters::G1YoungGenerationCounters(G1MonitoringSupport* g1mm, + const char* name) + : G1GenerationCounters(g1mm, name, 0 /* ordinal */, 3 /* spaces */, + G1MonitoringSupport::pad_capacity(0, 3) /* min_capacity */, + G1MonitoringSupport::pad_capacity(g1mm->young_gen_max(), 3), + G1MonitoringSupport::pad_capacity(0, 3) /* curr_capacity */) { + update_all(); +} + +G1OldGenerationCounters::G1OldGenerationCounters(G1MonitoringSupport* g1mm, + const char* name) + : G1GenerationCounters(g1mm, name, 1 /* ordinal */, 1 /* spaces */, + G1MonitoringSupport::pad_capacity(0) /* min_capacity */, + G1MonitoringSupport::pad_capacity(g1mm->old_gen_max()), + G1MonitoringSupport::pad_capacity(0) /* curr_capacity */) { + update_all(); +} + +void G1YoungGenerationCounters::update_all() { + size_t committed = + G1MonitoringSupport::pad_capacity(_g1mm->young_gen_committed(), 3); + _current_size->set_value(committed); +} + +void G1OldGenerationCounters::update_all() { + size_t committed = + G1MonitoringSupport::pad_capacity(_g1mm->old_gen_committed()); + _current_size->set_value(committed); +} + +G1MonitoringSupport::G1MonitoringSupport(G1CollectedHeap* g1h) : _g1h(g1h), _incremental_collection_counters(NULL), _full_collection_counters(NULL), - _non_young_collection_counters(NULL), + _old_collection_counters(NULL), _old_space_counters(NULL), _young_collection_counters(NULL), _eden_counters(NULL), _from_counters(NULL), _to_counters(NULL), - _g1_storage_addr(g1_storage_addr) -{ + + _overall_reserved(0), + _overall_committed(0), _overall_used(0), + _young_region_num(0), + _young_gen_committed(0), + _eden_committed(0), _eden_used(0), + _survivor_committed(0), _survivor_used(0), + _old_committed(0), _old_used(0) { + + _overall_reserved = g1h->max_capacity(); + recalculate_sizes(); + // Counters for GC collections // // name "collector.0". In a generational collector this would be the @@ -69,110 +119,147 @@ // generational GC terms. The "1, 1" parameters are for // the n-th generation (=1) with 1 space. // Counters are created from minCapacity, maxCapacity, and capacity - _non_young_collection_counters = - new GenerationCounters("whole heap", 1, 1, _g1_storage_addr); + _old_collection_counters = new G1OldGenerationCounters(this, "old"); // name "generation.1.space.0" // Counters are created from maxCapacity, capacity, initCapacity, // and used. - _old_space_counters = new HSpaceCounters("space", 0, - _g1h->max_capacity(), _g1h->capacity(), _non_young_collection_counters); + _old_space_counters = new HSpaceCounters("space", 0 /* ordinal */, + pad_capacity(overall_reserved()) /* max_capacity */, + pad_capacity(old_space_committed()) /* init_capacity */, + _old_collection_counters); // Young collection set // name "generation.0". This is logically the young generation. // The "0, 3" are paremeters for the n-th genertaion (=0) with 3 spaces. - // See _non_young_collection_counters for additional counters - _young_collection_counters = new GenerationCounters("young", 0, 3, NULL); + // See _old_collection_counters for additional counters + _young_collection_counters = new G1YoungGenerationCounters(this, "young"); - // Replace "max_heap_byte_size() with maximum young gen size for - // g1Collectedheap // name "generation.0.space.0" // See _old_space_counters for additional counters - _eden_counters = new HSpaceCounters("eden", 0, - _g1h->max_capacity(), eden_space_committed(), + _eden_counters = new HSpaceCounters("eden", 0 /* ordinal */, + pad_capacity(overall_reserved()) /* max_capacity */, + pad_capacity(eden_space_committed()) /* init_capacity */, _young_collection_counters); // name "generation.0.space.1" // See _old_space_counters for additional counters // Set the arguments to indicate that this survivor space is not used. - _from_counters = new HSpaceCounters("s0", 1, (long) 0, (long) 0, + _from_counters = new HSpaceCounters("s0", 1 /* ordinal */, + pad_capacity(0) /* max_capacity */, + pad_capacity(0) /* init_capacity */, _young_collection_counters); + // Given that this survivor space is not used, we update it here + // once to reflect that its used space is 0 so that we don't have to + // worry about updating it again later. + _from_counters->update_used(0); // name "generation.0.space.2" // See _old_space_counters for additional counters - _to_counters = new HSpaceCounters("s1", 2, - _g1h->max_capacity(), - survivor_space_committed(), + _to_counters = new HSpaceCounters("s1", 2 /* ordinal */, + pad_capacity(overall_reserved()) /* max_capacity */, + pad_capacity(survivor_space_committed()) /* init_capacity */, _young_collection_counters); } -size_t G1MonitoringSupport::overall_committed() { - return g1h()->capacity(); -} +void G1MonitoringSupport::recalculate_sizes() { + G1CollectedHeap* g1 = g1h(); + + // Recalculate all the sizes from scratch. We assume that this is + // called at a point where no concurrent updates to the various + // values we read here are possible (i.e., at a STW phase at the end + // of a GC). -size_t G1MonitoringSupport::overall_used() { - return g1h()->used_unlocked(); -} + size_t young_list_length = g1->young_list()->length(); + size_t survivor_list_length = g1->g1_policy()->recorded_survivor_regions(); + assert(young_list_length >= survivor_list_length, "invariant"); + size_t eden_list_length = young_list_length - survivor_list_length; + // Max length includes any potential extensions to the young gen + // we'll do when the GC locker is active. + size_t young_list_max_length = g1->g1_policy()->young_list_max_length(); + assert(young_list_max_length >= survivor_list_length, "invariant"); + size_t eden_list_max_length = young_list_max_length - survivor_list_length; -size_t G1MonitoringSupport::eden_space_committed() { - return MAX2(eden_space_used(), (size_t) HeapRegion::GrainBytes); -} + _overall_used = g1->used_unlocked(); + _eden_used = eden_list_length * HeapRegion::GrainBytes; + _survivor_used = survivor_list_length * HeapRegion::GrainBytes; + _young_region_num = young_list_length; + _old_used = subtract_up_to_zero(_overall_used, _eden_used + _survivor_used); + + // First calculate the committed sizes that can be calculated independently. + _survivor_committed = _survivor_used; + _old_committed = HeapRegion::align_up_to_region_byte_size(_old_used); -size_t G1MonitoringSupport::eden_space_used() { - size_t young_list_length = g1h()->young_list()->length(); - size_t eden_used = young_list_length * HeapRegion::GrainBytes; - size_t survivor_used = survivor_space_used(); - eden_used = subtract_up_to_zero(eden_used, survivor_used); - return eden_used; -} + // Next, start with the overall committed size. + _overall_committed = g1->capacity(); + size_t committed = _overall_committed; + + // Remove the committed size we have calculated so far (for the + // survivor and old space). + assert(committed >= (_survivor_committed + _old_committed), "sanity"); + committed -= _survivor_committed + _old_committed; + + // Next, calculate and remove the committed size for the eden. + _eden_committed = eden_list_max_length * HeapRegion::GrainBytes; + // Somewhat defensive: be robust in case there are inaccuracies in + // the calculations + _eden_committed = MIN2(_eden_committed, committed); + committed -= _eden_committed; -size_t G1MonitoringSupport::survivor_space_committed() { - return MAX2(survivor_space_used(), - (size_t) HeapRegion::GrainBytes); -} + // Finally, give the rest to the old space... + _old_committed += committed; + // ..and calculate the young gen committed. + _young_gen_committed = _eden_committed + _survivor_committed; -size_t G1MonitoringSupport::survivor_space_used() { - size_t survivor_num = g1h()->g1_policy()->recorded_survivor_regions(); - size_t survivor_used = survivor_num * HeapRegion::GrainBytes; - return survivor_used; + assert(_overall_committed == + (_eden_committed + _survivor_committed + _old_committed), + "the committed sizes should add up"); + // Somewhat defensive: cap the eden used size to make sure it + // never exceeds the committed size. + _eden_used = MIN2(_eden_used, _eden_committed); + // _survivor_committed and _old_committed are calculated in terms of + // the corresponding _*_used value, so the next two conditions + // should hold. + assert(_survivor_used <= _survivor_committed, "post-condition"); + assert(_old_used <= _old_committed, "post-condition"); } -size_t G1MonitoringSupport::old_space_committed() { - size_t committed = overall_committed(); - size_t eden_committed = eden_space_committed(); - size_t survivor_committed = survivor_space_committed(); - committed = subtract_up_to_zero(committed, eden_committed); - committed = subtract_up_to_zero(committed, survivor_committed); - committed = MAX2(committed, (size_t) HeapRegion::GrainBytes); - return committed; -} +void G1MonitoringSupport::recalculate_eden_size() { + G1CollectedHeap* g1 = g1h(); + + // When a new eden region is allocated, only the eden_used size is + // affected (since we have recalculated everything else at the last GC). -// See the comment near the top of g1MonitoringSupport.hpp for -// an explanation of these calculations for "used" and "capacity". -size_t G1MonitoringSupport::old_space_used() { - size_t used = overall_used(); - size_t eden_used = eden_space_used(); - size_t survivor_used = survivor_space_used(); - used = subtract_up_to_zero(used, eden_used); - used = subtract_up_to_zero(used, survivor_used); - return used; -} - -void G1MonitoringSupport::update_counters() { - if (UsePerfData) { - eden_counters()->update_capacity(eden_space_committed()); - eden_counters()->update_used(eden_space_used()); - to_counters()->update_capacity(survivor_space_committed()); - to_counters()->update_used(survivor_space_used()); - old_space_counters()->update_capacity(old_space_committed()); - old_space_counters()->update_used(old_space_used()); - non_young_collection_counters()->update_all(); + size_t young_region_num = g1h()->young_list()->length(); + if (young_region_num > _young_region_num) { + size_t diff = young_region_num - _young_region_num; + _eden_used += diff * HeapRegion::GrainBytes; + // Somewhat defensive: cap the eden used size to make sure it + // never exceeds the committed size. + _eden_used = MIN2(_eden_used, _eden_committed); + _young_region_num = young_region_num; } } -void G1MonitoringSupport::update_eden_counters() { +void G1MonitoringSupport::update_sizes() { + recalculate_sizes(); if (UsePerfData) { - eden_counters()->update_capacity(eden_space_committed()); + eden_counters()->update_capacity(pad_capacity(eden_space_committed())); + eden_counters()->update_used(eden_space_used()); + // only the to survivor space (s1) is active, so we don't need to + // update the counteres for the from survivor space (s0) + to_counters()->update_capacity(pad_capacity(survivor_space_committed())); + to_counters()->update_used(survivor_space_used()); + old_space_counters()->update_capacity(pad_capacity(old_space_committed())); + old_space_counters()->update_used(old_space_used()); + old_collection_counters()->update_all(); + young_collection_counters()->update_all(); + } +} + +void G1MonitoringSupport::update_eden_size() { + recalculate_eden_size(); + if (UsePerfData) { eden_counters()->update_used(eden_space_used()); } }
--- a/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -28,101 +28,95 @@ #include "gc_implementation/shared/hSpaceCounters.hpp" class G1CollectedHeap; -class G1SpaceMonitoringSupport; -// Class for monitoring logical spaces in G1. -// G1 defines a set of regions as a young -// collection (analogous to a young generation). -// The young collection is a logical generation -// with no fixed chunk (see space.hpp) reflecting -// the address space for the generation. In addition -// to the young collection there is its complement -// the non-young collection that is simply the regions -// not in the young collection. The non-young collection -// is treated here as a logical old generation only -// because the monitoring tools expect a generational -// heap. The monitoring tools expect that a Space -// (see space.hpp) exists that describe the -// address space of young collection and non-young -// collection and such a view is provided here. +// Class for monitoring logical spaces in G1. It provides data for +// both G1's jstat counters as well as G1's memory pools. +// +// G1 splits the heap into heap regions and each heap region belongs +// to one of the following categories: +// +// * eden : regions that have been allocated since the last GC +// * survivors : regions with objects that survived the last few GCs +// * old : long-lived non-humongous regions +// * humongous : humongous regions +// * free : free regions +// +// The combination of eden and survivor regions form the equivalent of +// the young generation in the other GCs. The combination of old and +// humongous regions form the equivalent of the old generation in the +// other GCs. Free regions do not have a good equivalent in the other +// GCs given that they can be allocated as any of the other region types. // -// This class provides interfaces to access -// the value of variables for the young collection -// that include the "capacity" and "used" of the -// young collection along with constant values -// for the minimum and maximum capacities for -// the logical spaces. Similarly for the non-young -// collection. -// -// Also provided are counters for G1 concurrent collections -// and stop-the-world full heap collecitons. +// The monitoring tools expect the heap to contain a number of +// generations (young, old, perm) and each generation to contain a +// number of spaces (young: eden, survivors, old). Given that G1 does +// not maintain those spaces physically (e.g., the set of +// non-contiguous eden regions can be considered as a "logical" +// space), we'll provide the illusion that those generations and +// spaces exist. In reality, each generation and space refers to a set +// of heap regions that are potentially non-contiguous. // -// Below is a description of how "used" and "capactiy" -// (or committed) is calculated for the logical spaces. +// This class provides interfaces to access the min, current, and max +// capacity and current occupancy for each of G1's logical spaces and +// generations we expose to the monitoring tools. Also provided are +// counters for G1 concurrent collections and stop-the-world full heap +// collections. // -// 1) The used space calculation for a pool is not necessarily -// independent of the others. We can easily get from G1 the overall -// used space in the entire heap, the number of regions in the young -// generation (includes both eden and survivors), and the number of -// survivor regions. So, from that we calculate: +// Below is a description of how the various sizes are calculated. // -// survivor_used = survivor_num * region_size -// eden_used = young_region_num * region_size - survivor_used -// old_gen_used = overall_used - eden_used - survivor_used +// * Current Capacity // -// Note that survivor_used and eden_used are upper bounds. To get the -// actual value we would have to iterate over the regions and add up -// ->used(). But that'd be expensive. So, we'll accept some lack of -// accuracy for those two. But, we have to be careful when calculating -// old_gen_used, in case we subtract from overall_used more then the -// actual number and our result goes negative. +// - heap_capacity = current heap capacity (e.g., current committed size) +// - young_gen_capacity = current max young gen target capacity +// (i.e., young gen target capacity + max allowed expansion capacity) +// - survivor_capacity = current survivor region capacity +// - eden_capacity = young_gen_capacity - survivor_capacity +// - old_capacity = heap_capacity - young_gen_capacity +// +// What we do in the above is to distribute the free regions among +// eden_capacity and old_capacity. // -// 2) Calculating the used space is straightforward, as described -// above. However, how do we calculate the committed space, given that -// we allocate space for the eden, survivor, and old gen out of the -// same pool of regions? One way to do this is to use the used value -// as also the committed value for the eden and survivor spaces and -// then calculate the old gen committed space as follows: +// * Occupancy // -// old_gen_committed = overall_committed - eden_committed - survivor_committed +// - young_gen_used = current young region capacity +// - survivor_used = survivor_capacity +// - eden_used = young_gen_used - survivor_used +// - old_used = overall_used - young_gen_used // -// Maybe a better way to do that would be to calculate used for eden -// and survivor as a sum of ->used() over their regions and then -// calculate committed as region_num * region_size (i.e., what we use -// to calculate the used space now). This is something to consider -// in the future. +// Unfortunately, we currently only keep track of the number of +// currently allocated young and survivor regions + the overall used +// bytes in the heap, so the above can be a little inaccurate. +// +// * Min Capacity // -// 3) Another decision that is again not straightforward is what is -// the max size that each memory pool can grow to. One way to do this -// would be to use the committed size for the max for the eden and -// survivors and calculate the old gen max as follows (basically, it's -// a similar pattern to what we use for the committed space, as -// described above): +// We set this to 0 for all spaces. We could consider setting the old +// min capacity to the min capacity of the heap (see 7078465). +// +// * Max Capacity // -// old_gen_max = overall_max - eden_max - survivor_max +// For jstat, we set the max capacity of all spaces to heap_capacity, +// given that we don't always have a reasonably upper bound on how big +// each space can grow. For the memory pools, we actually make the max +// capacity undefined. We could consider setting the old max capacity +// to the max capacity of the heap (see 7078465). // -// Unfortunately, the above makes the max of each pool fluctuate over -// time and, even though this is allowed according to the spec, it -// broke several assumptions in the M&M framework (there were cases -// where used would reach a value greater than max). So, for max we -// use -1, which means "undefined" according to the spec. +// If we had more accurate occupancy / capacity information per +// region set the above calculations would be greatly simplified and +// be made more accurate. // -// 4) Now, there is a very subtle issue with all the above. The -// framework will call get_memory_usage() on the three pools -// asynchronously. As a result, each call might get a different value -// for, say, survivor_num which will yield inconsistent values for -// eden_used, survivor_used, and old_gen_used (as survivor_num is used -// in the calculation of all three). This would normally be -// ok. However, it's possible that this might cause the sum of -// eden_used, survivor_used, and old_gen_used to go over the max heap -// size and this seems to sometimes cause JConsole (and maybe other -// clients) to get confused. There's not a really an easy / clean -// solution to this problem, due to the asynchrounous nature of the -// framework. +// We update all the above synchronously and we store the results in +// fields so that we just read said fields when needed. A subtle point +// is that all the above sizes need to be recalculated when the old +// gen changes capacity (after a GC or after a humongous allocation) +// but only the eden occupancy changes when a new eden region is +// allocated. So, in the latter case we have minimal recalcuation to +// do which is important as we want to keep the eden region allocation +// path as low-overhead as possible. class G1MonitoringSupport : public CHeapObj { + friend class VMStructs; + G1CollectedHeap* _g1h; - VirtualSpace* _g1_storage_addr; // jstat performance counters // incremental collections both fully and partially young @@ -133,9 +127,9 @@ // _from_counters, and _to_counters are associated with // this "generational" counter. GenerationCounters* _young_collection_counters; - // non-young collection set counters. The _old_space_counters + // old collection set counters. The _old_space_counters // below are associated with this "generational" counter. - GenerationCounters* _non_young_collection_counters; + GenerationCounters* _old_collection_counters; // Counters for the capacity and used for // the whole heap HSpaceCounters* _old_space_counters; @@ -145,6 +139,27 @@ HSpaceCounters* _from_counters; HSpaceCounters* _to_counters; + // When it's appropriate to recalculate the various sizes (at the + // end of a GC, when a new eden region is allocated, etc.) we store + // them here so that we can easily report them when needed and not + // have to recalculate them every time. + + size_t _overall_reserved; + size_t _overall_committed; + size_t _overall_used; + + size_t _young_region_num; + size_t _young_gen_committed; + size_t _eden_committed; + size_t _eden_used; + size_t _survivor_committed; + size_t _survivor_used; + + size_t _old_committed; + size_t _old_used; + + G1CollectedHeap* g1h() { return _g1h; } + // It returns x - y if x > y, 0 otherwise. // As described in the comment above, some of the inputs to the // calculations we have to do are obtained concurrently and hence @@ -160,15 +175,35 @@ } } + // Recalculate all the sizes. + void recalculate_sizes(); + // Recalculate only what's necessary when a new eden region is allocated. + void recalculate_eden_size(); + public: - G1MonitoringSupport(G1CollectedHeap* g1h, VirtualSpace* g1_storage_addr); + G1MonitoringSupport(G1CollectedHeap* g1h); - G1CollectedHeap* g1h() { return _g1h; } - VirtualSpace* g1_storage_addr() { return _g1_storage_addr; } + // Unfortunately, the jstat tool assumes that no space has 0 + // capacity. In our case, given that each space is logical, it's + // possible that no regions will be allocated to it, hence to have 0 + // capacity (e.g., if there are no survivor regions, the survivor + // space has 0 capacity). The way we deal with this is to always pad + // each capacity value we report to jstat by a very small amount to + // make sure that it's never zero. Given that we sometimes have to + // report a capacity of a generation that contains several spaces + // (e.g., young gen includes one eden, two survivor spaces), the + // mult parameter is provided in order to adding the appropriate + // padding multiple times so that the capacities add up correctly. + static size_t pad_capacity(size_t size_bytes, size_t mult = 1) { + return size_bytes + MinObjAlignmentInBytes * mult; + } - // Performance Counter accessors - void update_counters(); - void update_eden_counters(); + // Recalculate all the sizes from scratch and update all the jstat + // counters accordingly. + void update_sizes(); + // Recalculate only what's necessary when a new eden region is + // allocated and update any jstat counters that need to be updated. + void update_eden_size(); CollectorCounters* incremental_collection_counters() { return _incremental_collection_counters; @@ -176,8 +211,11 @@ CollectorCounters* full_collection_counters() { return _full_collection_counters; } - GenerationCounters* non_young_collection_counters() { - return _non_young_collection_counters; + GenerationCounters* young_collection_counters() { + return _young_collection_counters; + } + GenerationCounters* old_collection_counters() { + return _old_collection_counters; } HSpaceCounters* old_space_counters() { return _old_space_counters; } HSpaceCounters* eden_counters() { return _eden_counters; } @@ -187,17 +225,45 @@ // Monitoring support used by // MemoryService // jstat counters - size_t overall_committed(); - size_t overall_used(); + + size_t overall_reserved() { return _overall_reserved; } + size_t overall_committed() { return _overall_committed; } + size_t overall_used() { return _overall_used; } - size_t eden_space_committed(); - size_t eden_space_used(); + size_t young_gen_committed() { return _young_gen_committed; } + size_t young_gen_max() { return overall_reserved(); } + size_t eden_space_committed() { return _eden_committed; } + size_t eden_space_used() { return _eden_used; } + size_t survivor_space_committed() { return _survivor_committed; } + size_t survivor_space_used() { return _survivor_used; } + + size_t old_gen_committed() { return old_space_committed(); } + size_t old_gen_max() { return overall_reserved(); } + size_t old_space_committed() { return _old_committed; } + size_t old_space_used() { return _old_used; } +}; - size_t survivor_space_committed(); - size_t survivor_space_used(); +class G1GenerationCounters: public GenerationCounters { +protected: + G1MonitoringSupport* _g1mm; + +public: + G1GenerationCounters(G1MonitoringSupport* g1mm, + const char* name, int ordinal, int spaces, + size_t min_capacity, size_t max_capacity, + size_t curr_capacity); +}; - size_t old_space_committed(); - size_t old_space_used(); +class G1YoungGenerationCounters: public G1GenerationCounters { +public: + G1YoungGenerationCounters(G1MonitoringSupport* g1mm, const char* name); + virtual void update_all(); +}; + +class G1OldGenerationCounters: public G1GenerationCounters { +public: + G1OldGenerationCounters(G1MonitoringSupport* g1mm, const char* name); + virtual void update_all(); }; #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1MONITORINGSUPPORT_HPP
--- a/src/share/vm/gc_implementation/g1/g1OopClosures.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1OopClosures.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -34,6 +34,7 @@ class CMMarkStack; class G1ParScanThreadState; class CMTask; +class ReferenceProcessor; // A class that scans oops in a given heap region (much as OopsInGenClosure // scans oops in a generation.) @@ -59,8 +60,10 @@ class G1ParPushHeapRSClosure : public G1ParClosureSuper { public: - G1ParPushHeapRSClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : + G1ParPushHeapRSClosure(G1CollectedHeap* g1, + G1ParScanThreadState* par_scan_state): G1ParClosureSuper(g1, par_scan_state) { } + template <class T> void do_oop_nv(T* p); virtual void do_oop(oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); } @@ -68,8 +71,13 @@ class G1ParScanClosure : public G1ParClosureSuper { public: - G1ParScanClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : - G1ParClosureSuper(g1, par_scan_state) { } + G1ParScanClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state, ReferenceProcessor* rp) : + G1ParClosureSuper(g1, par_scan_state) + { + assert(_ref_processor == NULL, "sanity"); + _ref_processor = rp; + } + template <class T> void do_oop_nv(T* p); virtual void do_oop(oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); } @@ -92,9 +100,18 @@ class G1ParScanPartialArrayClosure : public G1ParClosureSuper { G1ParScanClosure _scanner; + public: - G1ParScanPartialArrayClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : - G1ParClosureSuper(g1, par_scan_state), _scanner(g1, par_scan_state) { } + G1ParScanPartialArrayClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state, ReferenceProcessor* rp) : + G1ParClosureSuper(g1, par_scan_state), _scanner(g1, par_scan_state, rp) + { + assert(_ref_processor == NULL, "sanity"); + } + + G1ParScanClosure* scanner() { + return &_scanner; + } + template <class T> void do_oop_nv(T* p); virtual void do_oop(oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); } @@ -105,7 +122,8 @@ G1ParScanClosure *_scanner; protected: template <class T> void mark_object(T* p); - oop copy_to_survivor_space(oop obj, bool should_mark_copy); + oop copy_to_survivor_space(oop obj, bool should_mark_root, + bool should_mark_copy); public: G1ParCopyHelper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state, G1ParScanClosure *scanner) : @@ -116,10 +134,20 @@ bool do_mark_object> class G1ParCopyClosure : public G1ParCopyHelper { G1ParScanClosure _scanner; + template <class T> void do_oop_work(T* p); + public: - G1ParCopyClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : - _scanner(g1, par_scan_state), G1ParCopyHelper(g1, par_scan_state, &_scanner) { } + G1ParCopyClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state, + ReferenceProcessor* rp) : + _scanner(g1, par_scan_state, rp), + G1ParCopyHelper(g1, par_scan_state, &_scanner) + { + assert(_ref_processor == NULL, "sanity"); + } + + G1ParScanClosure* scanner() { return &_scanner; } + template <class T> void do_oop_nv(T* p) { do_oop_work(p); } @@ -129,21 +157,25 @@ typedef G1ParCopyClosure<false, G1BarrierNone, false> G1ParScanExtRootClosure; typedef G1ParCopyClosure<true, G1BarrierNone, false> G1ParScanPermClosure; -typedef G1ParCopyClosure<false, G1BarrierRS, false> G1ParScanHeapRSClosure; + typedef G1ParCopyClosure<false, G1BarrierNone, true> G1ParScanAndMarkExtRootClosure; typedef G1ParCopyClosure<true, G1BarrierNone, true> G1ParScanAndMarkPermClosure; -typedef G1ParCopyClosure<false, G1BarrierRS, true> G1ParScanAndMarkHeapRSClosure; + +// The following closure types are no longer used but are retained +// for historical reasons: +// typedef G1ParCopyClosure<false, G1BarrierRS, false> G1ParScanHeapRSClosure; +// typedef G1ParCopyClosure<false, G1BarrierRS, true> G1ParScanAndMarkHeapRSClosure; -// This is the only case when we set skip_cset_test. Basically, this -// closure is (should?) only be called directly while we're draining -// the overflow and task queues. In that case we know that the -// reference in question points into the collection set, otherwise we -// would not have pushed it on the queue. The following is defined in -// g1_specialized_oop_closures.hpp. -// typedef G1ParCopyClosure<false, G1BarrierEvac, false, true> G1ParScanHeapEvacClosure; -// We need a separate closure to handle references during evacuation -// failure processing, as we cannot asume that the reference already -// points into the collection set (like G1ParScanHeapEvacClosure does). +// The following closure type is defined in g1_specialized_oop_closures.hpp: +// +// typedef G1ParCopyClosure<false, G1BarrierEvac, false> G1ParScanHeapEvacClosure; + +// We use a separate closure to handle references during evacuation +// failure processing. +// We could have used another instance of G1ParScanHeapEvacClosure +// (since that closure no longer assumes that the references it +// handles point into the collection set). + typedef G1ParCopyClosure<false, G1BarrierEvac, false> G1ParScanHeapEvacFailureClosure; class FilterIntoCSClosure: public OopClosure { @@ -152,9 +184,10 @@ DirtyCardToOopClosure* _dcto_cl; public: FilterIntoCSClosure( DirtyCardToOopClosure* dcto_cl, - G1CollectedHeap* g1, OopClosure* oc) : - _dcto_cl(dcto_cl), _g1(g1), _oc(oc) - {} + G1CollectedHeap* g1, + OopClosure* oc) : + _dcto_cl(dcto_cl), _g1(g1), _oc(oc) { } + template <class T> void do_oop_nv(T* p); virtual void do_oop(oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
--- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -234,6 +234,7 @@ HeapRegion *startRegion = calculateStartRegion(worker_i); ScanRSClosure scanRScl(oc, worker_i); + _g1->collection_set_iterate_from(startRegion, &scanRScl); scanRScl.set_try_claimed(); _g1->collection_set_iterate_from(startRegion, &scanRScl); @@ -283,6 +284,7 @@ double start = os::elapsedTime(); // Apply the given closure to all remaining log entries. RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq); + _g1->iterate_dirty_card_closure(&into_cset_update_rs_cl, into_cset_dcq, false, worker_i); // Now there should be no dirty cards.
--- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -37,6 +37,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif G1SATBCardTableModRefBS::G1SATBCardTableModRefBS(MemRegion whole_heap, int max_covered_regions) :
--- a/src/share/vm/gc_implementation/g1/g1_globals.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -290,10 +290,6 @@ "each evacuation pause in order to artificially fill up the " \ "heap and stress the marking implementation.") \ \ - develop(bool, ReduceInitialCardMarksForG1, false, \ - "When ReduceInitialCardMarks is true, this flag setting " \ - " controls whether G1 allows the RICM optimization") \ - \ develop(bool, G1ExitOnExpansionFailure, false, \ "Raise a fatal VM exit out of memory failure in the event " \ " that heap expansion fails due to running out of swap.") \
--- a/src/share/vm/gc_implementation/g1/heapRegion.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/heapRegion.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -33,11 +33,11 @@ #include "memory/iterator.hpp" #include "oops/oop.inline.hpp" -int HeapRegion::LogOfHRGrainBytes = 0; -int HeapRegion::LogOfHRGrainWords = 0; -int HeapRegion::GrainBytes = 0; -int HeapRegion::GrainWords = 0; -int HeapRegion::CardsPerRegion = 0; +int HeapRegion::LogOfHRGrainBytes = 0; +int HeapRegion::LogOfHRGrainWords = 0; +size_t HeapRegion::GrainBytes = 0; +size_t HeapRegion::GrainWords = 0; +size_t HeapRegion::CardsPerRegion = 0; HeapRegionDCTOC::HeapRegionDCTOC(G1CollectedHeap* g1, HeapRegion* hr, OopClosure* cl, @@ -45,7 +45,7 @@ FilterKind fk) : ContiguousSpaceDCTOC(hr, cl, precision, NULL), _hr(hr), _fk(fk), _g1(g1) -{} +{ } FilterOutOfRegionClosure::FilterOutOfRegionClosure(HeapRegion* r, OopClosure* oc) : @@ -210,15 +210,17 @@ HeapWord* top, OopClosure* cl) { G1CollectedHeap* g1h = _g1; + int oop_size; + OopClosure* cl2 = NULL; - int oop_size; - - OopClosure* cl2 = cl; FilterIntoCSClosure intoCSFilt(this, g1h, cl); FilterOutOfRegionClosure outOfRegionFilt(_hr, cl); + switch (_fk) { + case NoFilterKind: cl2 = cl; break; case IntoCSFilterKind: cl2 = &intoCSFilt; break; case OutOfRegionFilterKind: cl2 = &outOfRegionFilt; break; + default: ShouldNotReachHere(); } // Start filtering what we add to the remembered set. If the object is @@ -239,16 +241,19 @@ case NoFilterKind: bottom = walk_mem_region_loop(cl, g1h, _hr, bottom, top); break; + case IntoCSFilterKind: { FilterIntoCSClosure filt(this, g1h, cl); bottom = walk_mem_region_loop(&filt, g1h, _hr, bottom, top); break; } + case OutOfRegionFilterKind: { FilterOutOfRegionClosure filt(_hr, cl); bottom = walk_mem_region_loop(&filt, g1h, _hr, bottom, top); break; } + default: ShouldNotReachHere(); } @@ -317,11 +322,11 @@ guarantee(GrainBytes == 0, "we should only set it once"); // The cast to int is safe, given that we've bounded region_size by // MIN_REGION_SIZE and MAX_REGION_SIZE. - GrainBytes = (int) region_size; + GrainBytes = (size_t)region_size; guarantee(GrainWords == 0, "we should only set it once"); GrainWords = GrainBytes >> LogHeapWordSize; - guarantee(1 << LogOfHRGrainWords == GrainWords, "sanity"); + guarantee((size_t)(1 << LogOfHRGrainWords) == GrainWords, "sanity"); guarantee(CardsPerRegion == 0, "we should only set it once"); CardsPerRegion = GrainBytes >> CardTableModRefBS::card_shift; @@ -374,8 +379,7 @@ void HeapRegion::par_clear() { assert(used() == 0, "the region should have been already cleared"); - assert(capacity() == (size_t) HeapRegion::GrainBytes, - "should be back to normal"); + assert(capacity() == HeapRegion::GrainBytes, "should be back to normal"); HeapRegionRemSet* hrrs = rem_set(); hrrs->clear(); CardTableModRefBS* ct_bs = @@ -431,7 +435,7 @@ assert(end() == _orig_end, "sanity"); } - assert(capacity() == (size_t) HeapRegion::GrainBytes, "pre-condition"); + assert(capacity() == HeapRegion::GrainBytes, "pre-condition"); _humongous_type = NotHumongous; _humongous_start_region = NULL; } @@ -483,12 +487,13 @@ HeapRegion(size_t hrs_index, G1BlockOffsetSharedArray* sharedOffsetArray, MemRegion mr, bool is_zeroed) : G1OffsetTableContigSpace(sharedOffsetArray, mr, is_zeroed), - _next_fk(HeapRegionDCTOC::NoFilterKind), _hrs_index(hrs_index), + _hrs_index(hrs_index), _humongous_type(NotHumongous), _humongous_start_region(NULL), _in_collection_set(false), _next_in_special_set(NULL), _orig_end(NULL), _claimed(InitialClaimValue), _evacuation_failed(false), _prev_marked_bytes(0), _next_marked_bytes(0), _sort_index(-1), + _gc_efficiency(0.0), _young_type(NotYoung), _next_young_region(NULL), _next_dirty_cards_region(NULL), _next(NULL), _pending_removal(false), #ifdef ASSERT
--- a/src/share/vm/gc_implementation/g1/heapRegion.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/heapRegion.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -118,7 +118,6 @@ FilterKind fk); }; - // The complicating factor is that BlockOffsetTable diverged // significantly, and we need functionality that is only in the G1 version. // So I copied that code, which led to an alternate G1 version of @@ -223,10 +222,6 @@ ContinuesHumongous }; - // The next filter kind that should be used for a "new_dcto_cl" call with - // the "traditional" signature. - HeapRegionDCTOC::FilterKind _next_fk; - // Requires that the region "mr" be dense with objects, and begin and end // with an object. void oops_in_mr_iterate(MemRegion mr, OopClosure* cl); @@ -351,16 +346,17 @@ G1BlockOffsetSharedArray* sharedOffsetArray, MemRegion mr, bool is_zeroed); - static int LogOfHRGrainBytes; - static int LogOfHRGrainWords; - // The normal type of these should be size_t. However, they used to - // be members of an enum before and they are assumed by the - // compilers to be ints. To avoid going and fixing all their uses, - // I'm declaring them as ints. I'm not anticipating heap region - // sizes to reach anywhere near 2g, so using an int here is safe. - static int GrainBytes; - static int GrainWords; - static int CardsPerRegion; + static int LogOfHRGrainBytes; + static int LogOfHRGrainWords; + + static size_t GrainBytes; + static size_t GrainWords; + static size_t CardsPerRegion; + + static size_t align_up_to_region_byte_size(size_t sz) { + return (sz + (size_t) GrainBytes - 1) & + ~((1 << (size_t) LogOfHRGrainBytes) - 1); + } // It sets up the heap region size (GrainBytes / GrainWords), as // well as other related fields that are based on the heap region @@ -573,40 +569,14 @@ // allocated in the current region before the last call to "save_mark". void oop_before_save_marks_iterate(OopClosure* cl); - // This call determines the "filter kind" argument that will be used for - // the next call to "new_dcto_cl" on this region with the "traditional" - // signature (i.e., the call below.) The default, in the absence of a - // preceding call to this method, is "NoFilterKind", and a call to this - // method is necessary for each such call, or else it reverts to the - // default. - // (This is really ugly, but all other methods I could think of changed a - // lot of main-line code for G1.) - void set_next_filter_kind(HeapRegionDCTOC::FilterKind nfk) { - _next_fk = nfk; - } - DirtyCardToOopClosure* new_dcto_closure(OopClosure* cl, CardTableModRefBS::PrecisionStyle precision, HeapRegionDCTOC::FilterKind fk); -#if WHASSUP - DirtyCardToOopClosure* - new_dcto_closure(OopClosure* cl, - CardTableModRefBS::PrecisionStyle precision, - HeapWord* boundary) { - assert(boundary == NULL, "This arg doesn't make sense here."); - DirtyCardToOopClosure* res = new_dcto_closure(cl, precision, _next_fk); - _next_fk = HeapRegionDCTOC::NoFilterKind; - return res; - } -#endif - - // // Note the start or end of marking. This tells the heap region // that the collector is about to start or has finished (concurrently) // marking the heap. - // // Note the start of a marking phase. Record the // start of the unmarked area of the region here.
--- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -148,7 +148,7 @@ CardIdx_t from_card = (CardIdx_t) hw_offset >> (CardTableModRefBS::card_shift - LogHeapWordSize); - assert(0 <= from_card && from_card < HeapRegion::CardsPerRegion, + assert(0 <= from_card && (size_t)from_card < HeapRegion::CardsPerRegion, "Must be in range."); add_card_work(from_card, par); } @@ -639,7 +639,7 @@ uintptr_t(from_hr->bottom()) >> CardTableModRefBS::card_shift; CardIdx_t card_index = from_card - from_hr_bot_card_index; - assert(0 <= card_index && card_index < HeapRegion::CardsPerRegion, + assert(0 <= card_index && (size_t)card_index < HeapRegion::CardsPerRegion, "Must be in range."); if (G1HRRSUseSparseTable && _sparse_table.add_card(from_hrs_ind, card_index)) { @@ -1066,7 +1066,7 @@ uintptr_t(hr->bottom()) >> CardTableModRefBS::card_shift; assert(from_card >= hr_bot_card_index, "Inv"); CardIdx_t card_index = from_card - hr_bot_card_index; - assert(0 <= card_index && card_index < HeapRegion::CardsPerRegion, + assert(0 <= card_index && (size_t)card_index < HeapRegion::CardsPerRegion, "Must be in range."); return _sparse_table.contains_card(hr_ind, card_index); } @@ -1191,7 +1191,7 @@ _is = Sparse; // Set these values so that we increment to the first region. _coarse_cur_region_index = -1; - _coarse_cur_region_cur_card = (HeapRegion::CardsPerRegion-1);; + _coarse_cur_region_cur_card = (HeapRegion::CardsPerRegion-1); _cur_region_cur_card = 0; @@ -1270,7 +1270,7 @@ bool HeapRegionRemSetIterator::fine_has_next() { return _fine_cur_prt != NULL && - _cur_region_cur_card < (size_t) HeapRegion::CardsPerRegion; + _cur_region_cur_card < HeapRegion::CardsPerRegion; } bool HeapRegionRemSetIterator::has_next(size_t& card_index) {
--- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -395,8 +395,8 @@ // Coarse table iteration fields: // Current region index; - int _coarse_cur_region_index; - int _coarse_cur_region_cur_card; + int _coarse_cur_region_index; + size_t _coarse_cur_region_cur_card; bool coarse_has_next(size_t& card_index);
--- a/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -56,6 +56,7 @@ // and maintain that: _length <= _allocated_length <= _max_length class HeapRegionSeq: public CHeapObj { + friend class VMStructs; // The array that holds the HeapRegions. HeapRegion** _regions;
--- a/src/share/vm/gc_implementation/g1/ptrQueue.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/ptrQueue.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -37,6 +37,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif PtrQueue::PtrQueue(PtrQueueSet* qset, bool perm, bool active) : _qset(qset), _buf(NULL), _index(0), _active(active),
--- a/src/share/vm/gc_implementation/g1/satbQueue.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/g1/satbQueue.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -29,6 +29,7 @@ #include "memory/sharedHeap.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/thread.hpp" +#include "runtime/vmThread.hpp" // This method removes entries from an SATB buffer that will not be // useful to the concurrent marking threads. An entry is removed if it @@ -252,9 +253,18 @@ t->satb_mark_queue().apply_closure(_par_closures[worker]); } } - // We'll have worker 0 do this one. - if (worker == 0) { - shared_satb_queue()->apply_closure(_par_closures[0]); + + // We also need to claim the VMThread so that its parity is updated + // otherwise the next call to Thread::possibly_parallel_oops_do inside + // a StrongRootsScope might skip the VMThread because it has a stale + // parity that matches the parity set by the StrongRootsScope + // + // Whichever worker succeeds in claiming the VMThread gets to do + // the shared queue. + + VMThread* vmt = VMThread::vm_thread(); + if (vmt->claim_oops_do(true, parity)) { + shared_satb_queue()->apply_closure(_par_closures[worker]); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,65 @@ +/* + * 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. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_VMSTRUCTS_G1_HPP +#define SHARE_VM_GC_IMPLEMENTATION_G1_VMSTRUCTS_G1_HPP + +#include "gc_implementation/g1/heapRegion.hpp" +#include "gc_implementation/g1/heapRegionSeq.inline.hpp" +#include "gc_implementation/g1/g1CollectedHeap.inline.hpp" + +#define VM_STRUCTS_G1(nonstatic_field, static_field) \ + \ + static_field(HeapRegion, GrainBytes, size_t) \ + \ + nonstatic_field(HeapRegionSeq, _regions, HeapRegion**) \ + nonstatic_field(HeapRegionSeq, _length, size_t) \ + \ + nonstatic_field(G1CollectedHeap, _hrs, HeapRegionSeq) \ + nonstatic_field(G1CollectedHeap, _g1_committed, MemRegion) \ + nonstatic_field(G1CollectedHeap, _summary_bytes_used, size_t) \ + nonstatic_field(G1CollectedHeap, _g1mm, G1MonitoringSupport*) \ + \ + nonstatic_field(G1MonitoringSupport, _eden_committed, size_t) \ + nonstatic_field(G1MonitoringSupport, _eden_used, size_t) \ + nonstatic_field(G1MonitoringSupport, _survivor_committed, size_t) \ + nonstatic_field(G1MonitoringSupport, _survivor_used, size_t) \ + nonstatic_field(G1MonitoringSupport, _old_committed, size_t) \ + nonstatic_field(G1MonitoringSupport, _old_used, size_t) \ + + +#define VM_TYPES_G1(declare_type, declare_toplevel_type) \ + \ + declare_type(G1CollectedHeap, SharedHeap) \ + \ + declare_type(HeapRegion, ContiguousSpace) \ + declare_toplevel_type(HeapRegionSeq) \ + declare_toplevel_type(G1MonitoringSupport) \ + \ + declare_toplevel_type(G1CollectedHeap*) \ + declare_toplevel_type(HeapRegion*) \ + declare_toplevel_type(G1MonitoringSupport*) \ + + +#endif // SHARE_VM_GC_IMPLEMENTATION_G1_VMSTRUCTS_G1_HPP
--- a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -38,6 +38,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif bool ParMarkBitMap::initialize(MemRegion covered_region)
--- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -198,10 +198,9 @@ allocate_stacks(); - NOT_PRODUCT(ref_processor()->verify_no_references_recorded()); COMPILER2_PRESENT(DerivedPointerTable::clear()); - ref_processor()->enable_discovery(); + ref_processor()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); ref_processor()->setup_policy(clear_all_softrefs); mark_sweep_phase1(clear_all_softrefs);
--- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -2069,10 +2069,9 @@ CodeCache::gc_prologue(); Threads::gc_prologue(); - NOT_PRODUCT(ref_processor()->verify_no_references_recorded()); COMPILER2_PRESENT(DerivedPointerTable::clear()); - ref_processor()->enable_discovery(); + ref_processor()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); ref_processor()->setup_policy(maximum_heap_compaction); bool marked_for_unloading = false;
--- a/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -102,17 +102,15 @@ _state = flushed; } -bool PSPromotionLAB::unallocate_object(oop obj) { +bool PSPromotionLAB::unallocate_object(HeapWord* obj, size_t obj_size) { assert(Universe::heap()->is_in(obj), "Object outside heap"); if (contains(obj)) { - HeapWord* object_end = (HeapWord*)obj + obj->size(); - assert(object_end <= top(), "Object crosses promotion LAB boundary"); + HeapWord* object_end = obj + obj_size; + assert(object_end == top(), "Not matching last allocation"); - if (object_end == top()) { - set_top((HeapWord*)obj); - return true; - } + set_top(obj); + return true; } return false;
--- a/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -73,7 +73,7 @@ bool is_flushed() { return _state == flushed; } - bool unallocate_object(oop obj); + bool unallocate_object(HeapWord* obj, size_t obj_size); // Returns a subregion containing all objects in this space. MemRegion used_region() { return MemRegion(bottom(), top()); }
--- a/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -380,10 +380,10 @@ // deallocate it, so we have to test. If the deallocation fails, // overwrite with a filler object. if (new_obj_is_tenured) { - if (!_old_lab.unallocate_object(new_obj)) { + if (!_old_lab.unallocate_object((HeapWord*) new_obj, new_obj_size)) { CollectedHeap::fill_with_object((HeapWord*) new_obj, new_obj_size); } - } else if (!_young_lab.unallocate_object(new_obj)) { + } else if (!_young_lab.unallocate_object((HeapWord*) new_obj, new_obj_size)) { CollectedHeap::fill_with_object((HeapWord*) new_obj, new_obj_size); }
--- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -350,10 +350,9 @@ } save_to_space_top_before_gc(); - NOT_PRODUCT(reference_processor()->verify_no_references_recorded()); COMPILER2_PRESENT(DerivedPointerTable::clear()); - reference_processor()->enable_discovery(); + reference_processor()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); reference_processor()->setup_policy(false); // We track how much was promoted to the next generation for
--- a/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif // PSVirtualSpace
--- a/src/share/vm/gc_implementation/shared/generationCounters.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/shared/generationCounters.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -26,14 +26,10 @@ #include "gc_implementation/shared/generationCounters.hpp" #include "memory/resourceArea.hpp" - -GenerationCounters::GenerationCounters(const char* name, - int ordinal, int spaces, - VirtualSpace* v): - _virtual_space(v) { - +void GenerationCounters::initialize(const char* name, int ordinal, int spaces, + size_t min_capacity, size_t max_capacity, + size_t curr_capacity) { if (UsePerfData) { - EXCEPTION_MARK; ResourceMark rm; @@ -51,18 +47,37 @@ cname = PerfDataManager::counter_name(_name_space, "minCapacity"); PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes, - _virtual_space == NULL ? 0 : - _virtual_space->committed_size(), CHECK); + min_capacity, CHECK); cname = PerfDataManager::counter_name(_name_space, "maxCapacity"); PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes, - _virtual_space == NULL ? 0 : - _virtual_space->reserved_size(), CHECK); + max_capacity, CHECK); cname = PerfDataManager::counter_name(_name_space, "capacity"); - _current_size = PerfDataManager::create_variable(SUN_GC, cname, - PerfData::U_Bytes, - _virtual_space == NULL ? 0 : - _virtual_space->committed_size(), CHECK); + _current_size = + PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes, + curr_capacity, CHECK); } } + +GenerationCounters::GenerationCounters(const char* name, + int ordinal, int spaces, + VirtualSpace* v) + : _virtual_space(v) { + assert(v != NULL, "don't call this constructor if v == NULL"); + initialize(name, ordinal, spaces, + v->committed_size(), v->reserved_size(), v->committed_size()); +} + +GenerationCounters::GenerationCounters(const char* name, + int ordinal, int spaces, + size_t min_capacity, size_t max_capacity, + size_t curr_capacity) + : _virtual_space(NULL) { + initialize(name, ordinal, spaces, min_capacity, max_capacity, curr_capacity); +} + +void GenerationCounters::update_all() { + assert(_virtual_space != NULL, "otherwise, override this method"); + _current_size->set_value(_virtual_space->committed_size()); +}
--- a/src/share/vm/gc_implementation/shared/generationCounters.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/shared/generationCounters.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -34,6 +34,11 @@ class GenerationCounters: public CHeapObj { friend class VMStructs; +private: + void initialize(const char* name, int ordinal, int spaces, + size_t min_capacity, size_t max_capacity, + size_t curr_capacity); + protected: PerfVariable* _current_size; VirtualSpace* _virtual_space; @@ -48,11 +53,18 @@ char* _name_space; // This constructor is only meant for use with the PSGenerationCounters - // constructor. The need for such an constructor should be eliminated + // constructor. The need for such an constructor should be eliminated // when VirtualSpace and PSVirtualSpace are unified. - GenerationCounters() : _name_space(NULL), _current_size(NULL), _virtual_space(NULL) {} + GenerationCounters() + : _name_space(NULL), _current_size(NULL), _virtual_space(NULL) {} + + // This constructor is used for subclasses that do not have a space + // associated with them (e.g, in G1). + GenerationCounters(const char* name, int ordinal, int spaces, + size_t min_capacity, size_t max_capacity, + size_t curr_capacity); + public: - GenerationCounters(const char* name, int ordinal, int spaces, VirtualSpace* v); @@ -60,10 +72,7 @@ if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space); } - virtual void update_all() { - _current_size->set_value(_virtual_space == NULL ? 0 : - _virtual_space->committed_size()); - } + virtual void update_all(); const char* name_space() const { return _name_space; }
--- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -37,6 +37,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif MutableNUMASpace::MutableNUMASpace(size_t alignment) : MutableSpace(alignment) {
--- a/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -40,20 +40,32 @@ #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #endif +#ifndef USDT2 HS_DTRACE_PROBE_DECL1(hotspot, gc__begin, bool); HS_DTRACE_PROBE_DECL(hotspot, gc__end); +#endif /* !USDT2 */ // The same dtrace probe can't be inserted in two different files, so we // have to call it here, so it's only in one file. Can't create new probes // for the other file anymore. The dtrace probes have to remain stable. void VM_GC_Operation::notify_gc_begin(bool full) { +#ifndef USDT2 HS_DTRACE_PROBE1(hotspot, gc__begin, full); HS_DTRACE_WORKAROUND_TAIL_CALL_BUG(); +#else /* USDT2 */ + HOTSPOT_GC_BEGIN( + full); +#endif /* USDT2 */ } void VM_GC_Operation::notify_gc_end() { +#ifndef USDT2 HS_DTRACE_PROBE(hotspot, gc__end); HS_DTRACE_WORKAROUND_TAIL_CALL_BUG(); +#else /* USDT2 */ + HOTSPOT_GC_END( +); +#endif /* USDT2 */ } void VM_GC_Operation::acquire_pending_list_lock() {
--- a/src/share/vm/gc_interface/collectedHeap.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_interface/collectedHeap.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -28,6 +28,7 @@ #include "gc_interface/collectedHeap.hpp" #include "gc_interface/collectedHeap.inline.hpp" #include "oops/oop.inline.hpp" +#include "oops/instanceMirrorKlass.hpp" #include "runtime/init.hpp" #include "services/heapDumper.hpp" #ifdef TARGET_OS_FAMILY_linux @@ -39,6 +40,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifdef ASSERT @@ -433,3 +437,37 @@ inspector.doit(); } } + +oop CollectedHeap::Class_obj_allocate(KlassHandle klass, int size, KlassHandle real_klass, TRAPS) { + debug_only(check_for_valid_allocation_state()); + assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); + assert(size >= 0, "int won't convert to size_t"); + HeapWord* obj; + if (JavaObjectsInPerm) { + obj = common_permanent_mem_allocate_init(size, CHECK_NULL); + } else { + assert(ScavengeRootsInCode > 0, "must be"); + obj = common_mem_allocate_init(size, CHECK_NULL); + } + post_allocation_setup_common(klass, obj, size); + assert(Universe::is_bootstrapping() || + !((oop)obj)->blueprint()->oop_is_array(), "must not be an array"); + NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size)); + oop mirror = (oop)obj; + + java_lang_Class::set_oop_size(mirror, size); + + // Setup indirections + if (!real_klass.is_null()) { + java_lang_Class::set_klass(mirror, real_klass()); + real_klass->set_java_mirror(mirror); + } + + instanceMirrorKlass* mk = instanceMirrorKlass::cast(mirror->klass()); + assert(size == mk->instance_size(real_klass), "should have been set"); + + // notify jvmti and dtrace + post_allocation_notify(klass, (oop)obj); + + return mirror; +}
--- a/src/share/vm/gc_interface/collectedHeap.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_interface/collectedHeap.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -319,9 +319,13 @@ // VM (then terminate). virtual void preload_and_dump(TRAPS) { ShouldNotReachHere(); } + // Allocate and initialize instances of Class + static oop Class_obj_allocate(KlassHandle klass, int size, KlassHandle real_klass, TRAPS); + // General obj/array allocation facilities. inline static oop obj_allocate(KlassHandle klass, int size, TRAPS); inline static oop array_allocate(KlassHandle klass, int size, int length, TRAPS); + inline static oop array_allocate_nozero(KlassHandle klass, int size, int length, TRAPS); // Special obj/array allocation facilities. // Some heaps may want to manage "permanent" data uniquely. These default
--- a/src/share/vm/gc_interface/collectedHeap.inline.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/gc_interface/collectedHeap.inline.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -43,6 +43,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // Inline allocation implementations. @@ -271,6 +274,23 @@ return (oop)obj; } +oop CollectedHeap::array_allocate_nozero(KlassHandle klass, + int size, + int length, + TRAPS) { + debug_only(check_for_valid_allocation_state()); + assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); + assert(size >= 0, "int won't convert to size_t"); + HeapWord* obj = common_mem_allocate_noinit(size, CHECK_NULL); + ((oop)obj)->set_klass_gap(0); + post_allocation_setup_array(klass, obj, size, length); +#ifndef PRODUCT + const size_t hs = oopDesc::header_size()+1; + Universe::heap()->check_for_non_bad_heap_word_value(obj+hs, size-hs); +#endif + return (oop)obj; +} + oop CollectedHeap::permanent_obj_allocate(KlassHandle klass, int size, TRAPS) { oop obj = permanent_obj_allocate_no_klass_install(klass, size, CHECK_NULL); post_allocation_install_obj_klass(klass, obj, size);
--- a/src/share/vm/interpreter/abstractInterpreter.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/interpreter/abstractInterpreter.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -56,6 +56,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // This file contains the platform-independent parts // of the abstract interpreter and the abstract interpreter generator.
--- a/src/share/vm/interpreter/bytecodeInterpreter.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -65,6 +65,12 @@ #ifdef TARGET_OS_ARCH_linux_ppc # include "orderAccess_linux_ppc.inline.hpp" #endif +#ifdef TARGET_OS_ARCH_bsd_x86 +# include "orderAccess_bsd_x86.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_bsd_zero +# include "orderAccess_bsd_zero.inline.hpp" +#endif // no precompiled headers
--- a/src/share/vm/interpreter/bytecodeTracer.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/interpreter/bytecodeTracer.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -92,7 +92,7 @@ // the incoming method. We could lose a line of trace output. // This is acceptable in a debug-only feature. st->cr(); - st->print("[%d] ", (int) Thread::current()->osthread()->thread_id()); + st->print("[%ld] ", (long) Thread::current()->osthread()->thread_id()); method->print_name(st); st->cr(); _current_method = method(); @@ -106,7 +106,7 @@ } _code = code; int bci = bcp - method->code_base(); - st->print("[%d] ", (int) Thread::current()->osthread()->thread_id()); + st->print("[%ld] ", (long) Thread::current()->osthread()->thread_id()); if (Verbose) { st->print("%8d %4d " INTPTR_FORMAT " " INTPTR_FORMAT " %s", BytecodeCounter::counter_value(), bci, tos, tos2, Bytecodes::name(code));
--- a/src/share/vm/interpreter/interpreterRuntime.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/interpreter/interpreterRuntime.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -41,6 +41,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // The InterpreterRuntime is called by the interpreter for everything // that cannot/should not be dealt with in assembly and needs C support.
--- a/src/share/vm/interpreter/linkResolver.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/interpreter/linkResolver.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -52,6 +52,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif //------------------------------------------------------------------------------------------------------------------------ // Implementation of FieldAccessInfo
--- a/src/share/vm/memory/allocation.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/memory/allocation.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -39,6 +39,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif void* CHeapObj::operator new(size_t size){ return (void *) AllocateHeap(size, "CHeapObj-new");
--- a/src/share/vm/memory/collectorPolicy.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/memory/collectorPolicy.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -47,6 +47,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifndef SERIALGC #include "gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp" #include "gc_implementation/concurrentMarkSweep/cmsGCAdaptivePolicyCounters.hpp"
--- a/src/share/vm/memory/defNewGeneration.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/memory/defNewGeneration.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -48,6 +48,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // // DefNewGeneration functions.
--- a/src/share/vm/memory/gcLocker.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/memory/gcLocker.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -41,6 +41,10 @@ # include "os_windows.inline.hpp" # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +# include "thread_bsd.inline.hpp" +#endif // The direct lock/unlock calls do not force a collection if an unlock // decrements the count to zero. Avoid calling these if at all possible.
--- a/src/share/vm/memory/genCollectedHeap.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/memory/genCollectedHeap.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -599,8 +599,7 @@ // atomic wrt other collectors in this configuration, we // are guaranteed to have empty discovered ref lists. if (rp->discovery_is_atomic()) { - rp->verify_no_references_recorded(); - rp->enable_discovery(); + rp->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); rp->setup_policy(do_clear_all_soft_refs); } else { // collect() below will enable discovery as appropriate
--- a/src/share/vm/memory/genMarkSweep.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/memory/genMarkSweep.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -55,6 +55,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif void GenMarkSweep::invoke_at_safepoint(int level, ReferenceProcessor* rp, bool clear_all_softrefs) {
--- a/src/share/vm/memory/oopFactory.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/memory/oopFactory.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -77,7 +77,14 @@ typeArrayOop oopFactory::new_typeArray(BasicType type, int length, TRAPS) { klassOop type_asKlassOop = Universe::typeArrayKlassObj(type); typeArrayKlass* type_asArrayKlass = typeArrayKlass::cast(type_asKlassOop); - typeArrayOop result = type_asArrayKlass->allocate(length, THREAD); + typeArrayOop result = type_asArrayKlass->allocate_common(length, true, THREAD); + return result; +} + +typeArrayOop oopFactory::new_typeArray_nozero(BasicType type, int length, TRAPS) { + klassOop type_asKlassOop = Universe::typeArrayKlassObj(type); + typeArrayKlass* type_asArrayKlass = typeArrayKlass::cast(type_asKlassOop); + typeArrayOop result = type_asArrayKlass->allocate_common(length, false, THREAD); return result; }
--- a/src/share/vm/memory/oopFactory.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/memory/oopFactory.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -63,6 +63,7 @@ static typeArrayOop new_permanent_intArray (int length, TRAPS); // used for class file structures static typeArrayOop new_typeArray(BasicType type, int length, TRAPS); + static typeArrayOop new_typeArray_nozero(BasicType type, int length, TRAPS); // Constant pools static constantPoolOop new_constantPool (int length,
--- a/src/share/vm/memory/referencePolicy.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/memory/referencePolicy.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -41,8 +41,9 @@ // The oop passed in is the SoftReference object, and not // the object the SoftReference points to. -bool LRUCurrentHeapPolicy::should_clear_reference(oop p) { - jlong interval = java_lang_ref_SoftReference::clock() - java_lang_ref_SoftReference::timestamp(p); +bool LRUCurrentHeapPolicy::should_clear_reference(oop p, + jlong timestamp_clock) { + jlong interval = timestamp_clock - java_lang_ref_SoftReference::timestamp(p); assert(interval >= 0, "Sanity check"); // The interval will be zero if the ref was accessed since the last scavenge/gc. @@ -71,8 +72,9 @@ // The oop passed in is the SoftReference object, and not // the object the SoftReference points to. -bool LRUMaxHeapPolicy::should_clear_reference(oop p) { - jlong interval = java_lang_ref_SoftReference::clock() - java_lang_ref_SoftReference::timestamp(p); +bool LRUMaxHeapPolicy::should_clear_reference(oop p, + jlong timestamp_clock) { + jlong interval = timestamp_clock - java_lang_ref_SoftReference::timestamp(p); assert(interval >= 0, "Sanity check"); // The interval will be zero if the ref was accessed since the last scavenge/gc.
--- a/src/share/vm/memory/referencePolicy.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/memory/referencePolicy.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -31,19 +31,27 @@ class ReferencePolicy : public CHeapObj { public: - virtual bool should_clear_reference(oop p) { ShouldNotReachHere(); return true; } + virtual bool should_clear_reference(oop p, jlong timestamp_clock) { + ShouldNotReachHere(); + return true; + } + // Capture state (of-the-VM) information needed to evaluate the policy virtual void setup() { /* do nothing */ } }; class NeverClearPolicy : public ReferencePolicy { public: - bool should_clear_reference(oop p) { return false; } + virtual bool should_clear_reference(oop p, jlong timestamp_clock) { + return false; + } }; class AlwaysClearPolicy : public ReferencePolicy { public: - bool should_clear_reference(oop p) { return true; } + virtual bool should_clear_reference(oop p, jlong timestamp_clock) { + return true; + } }; class LRUCurrentHeapPolicy : public ReferencePolicy { @@ -55,7 +63,7 @@ // Capture state (of-the-VM) information needed to evaluate the policy void setup(); - bool should_clear_reference(oop p); + virtual bool should_clear_reference(oop p, jlong timestamp_clock); }; class LRUMaxHeapPolicy : public ReferencePolicy { @@ -67,7 +75,7 @@ // Capture state (of-the-VM) information needed to evaluate the policy void setup(); - bool should_clear_reference(oop p); + virtual bool should_clear_reference(oop p, jlong timestamp_clock); }; #endif // SHARE_VM_MEMORY_REFERENCEPOLICY_HPP
--- a/src/share/vm/memory/referenceProcessor.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/memory/referenceProcessor.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -35,49 +35,20 @@ ReferencePolicy* ReferenceProcessor::_always_clear_soft_ref_policy = NULL; ReferencePolicy* ReferenceProcessor::_default_soft_ref_policy = NULL; -const int subclasses_of_ref = REF_PHANTOM - REF_OTHER; bool ReferenceProcessor::_pending_list_uses_discovered_field = false; - -// List of discovered references. -class DiscoveredList { -public: - DiscoveredList() : _len(0), _compressed_head(0), _oop_head(NULL) { } - oop head() const { - return UseCompressedOops ? oopDesc::decode_heap_oop(_compressed_head) : - _oop_head; - } - HeapWord* adr_head() { - return UseCompressedOops ? (HeapWord*)&_compressed_head : - (HeapWord*)&_oop_head; - } - void set_head(oop o) { - if (UseCompressedOops) { - // Must compress the head ptr. - _compressed_head = oopDesc::encode_heap_oop(o); - } else { - _oop_head = o; - } - } - bool empty() const { return head() == NULL; } - size_t length() { return _len; } - void set_length(size_t len) { _len = len; } - void inc_length(size_t inc) { _len += inc; assert(_len > 0, "Error"); } - void dec_length(size_t dec) { _len -= dec; } -private: - // Set value depending on UseCompressedOops. This could be a template class - // but then we have to fix all the instantiations and declarations that use this class. - oop _oop_head; - narrowOop _compressed_head; - size_t _len; -}; +jlong ReferenceProcessor::_soft_ref_timestamp_clock = 0; void referenceProcessor_init() { ReferenceProcessor::init_statics(); } void ReferenceProcessor::init_statics() { - // Initialize the master soft ref clock. - java_lang_ref_SoftReference::set_clock(os::javaTimeMillis()); + jlong now = os::javaTimeMillis(); + + // Initialize the soft ref timestamp clock. + _soft_ref_timestamp_clock = now; + // Also update the soft ref clock in j.l.r.SoftReference + java_lang_ref_SoftReference::set_clock(_soft_ref_timestamp_clock); _always_clear_soft_ref_policy = new AlwaysClearPolicy(); _default_soft_ref_policy = new COMPILER2_PRESENT(LRUMaxHeapPolicy()) @@ -91,6 +62,28 @@ _pending_list_uses_discovered_field = JDK_Version::current().pending_list_uses_discovered_field(); } +void ReferenceProcessor::enable_discovery(bool verify_disabled, bool check_no_refs) { +#ifdef ASSERT + // Verify that we're not currently discovering refs + assert(!verify_disabled || !_discovering_refs, "nested call?"); + + if (check_no_refs) { + // Verify that the discovered lists are empty + verify_no_references_recorded(); + } +#endif // ASSERT + + // Someone could have modified the value of the static + // field in the j.l.r.SoftReference class that holds the + // soft reference timestamp clock using reflection or + // Unsafe between GCs. Unconditionally update the static + // field in ReferenceProcessor here so that we use the new + // value during reference discovery. + + _soft_ref_timestamp_clock = java_lang_ref_SoftReference::clock(); + _discovering_refs = true; +} + ReferenceProcessor::ReferenceProcessor(MemRegion span, bool mt_processing, int mt_processing_degree, @@ -112,18 +105,22 @@ _discovery_is_mt = mt_discovery; _num_q = MAX2(1, mt_processing_degree); _max_num_q = MAX2(_num_q, mt_discovery_degree); - _discoveredSoftRefs = NEW_C_HEAP_ARRAY(DiscoveredList, _max_num_q * subclasses_of_ref); - if (_discoveredSoftRefs == NULL) { + _discovered_refs = NEW_C_HEAP_ARRAY(DiscoveredList, + _max_num_q * number_of_subclasses_of_ref()); + if (_discovered_refs == NULL) { vm_exit_during_initialization("Could not allocated RefProc Array"); } + _discoveredSoftRefs = &_discovered_refs[0]; _discoveredWeakRefs = &_discoveredSoftRefs[_max_num_q]; _discoveredFinalRefs = &_discoveredWeakRefs[_max_num_q]; _discoveredPhantomRefs = &_discoveredFinalRefs[_max_num_q]; - // Initialized all entries to NULL - for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { - _discoveredSoftRefs[i].set_head(NULL); - _discoveredSoftRefs[i].set_length(0); + + // Initialize all entries to NULL + for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { + _discovered_refs[i].set_head(NULL); + _discovered_refs[i].set_length(0); } + // If we do barriers, cache a copy of the barrier set. if (discovered_list_needs_barrier) { _bs = Universe::heap()->barrier_set(); @@ -134,23 +131,19 @@ #ifndef PRODUCT void ReferenceProcessor::verify_no_references_recorded() { guarantee(!_discovering_refs, "Discovering refs?"); - for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { - guarantee(_discoveredSoftRefs[i].empty(), + for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { + guarantee(_discovered_refs[i].is_empty(), "Found non-empty discovered list"); } } #endif void ReferenceProcessor::weak_oops_do(OopClosure* f) { - // Should this instead be - // for (int i = 0; i < subclasses_of_ref; i++_ { - // for (int j = 0; j < _num_q; j++) { - // int index = i * _max_num_q + j; - for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { + for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { if (UseCompressedOops) { - f->do_oop((narrowOop*)_discoveredSoftRefs[i].adr_head()); + f->do_oop((narrowOop*)_discovered_refs[i].adr_head()); } else { - f->do_oop((oop*)_discoveredSoftRefs[i].adr_head()); + f->do_oop((oop*)_discovered_refs[i].adr_head()); } } } @@ -159,17 +152,21 @@ // Update (advance) the soft ref master clock field. This must be done // after processing the soft ref list. jlong now = os::javaTimeMillis(); - jlong clock = java_lang_ref_SoftReference::clock(); + jlong soft_ref_clock = java_lang_ref_SoftReference::clock(); + assert(soft_ref_clock == _soft_ref_timestamp_clock, "soft ref clocks out of sync"); + NOT_PRODUCT( - if (now < clock) { - warning("time warp: %d to %d", clock, now); + if (now < _soft_ref_timestamp_clock) { + warning("time warp: "INT64_FORMAT" to "INT64_FORMAT, + _soft_ref_timestamp_clock, now); } ) // In product mode, protect ourselves from system time being adjusted // externally and going backward; see note in the implementation of // GenCollectedHeap::time_since_last_gc() for the right way to fix // this uniformly throughout the VM; see bug-id 4741166. XXX - if (now > clock) { + if (now > _soft_ref_timestamp_clock) { + _soft_ref_timestamp_clock = now; java_lang_ref_SoftReference::set_clock(now); } // Else leave clock stalled at its old value until time progresses @@ -187,6 +184,16 @@ // Stop treating discovered references specially. disable_discovery(); + // If discovery was concurrent, someone could have modified + // the value of the static field in the j.l.r.SoftReference + // class that holds the soft reference timestamp clock using + // reflection or Unsafe between when discovery was enabled and + // now. Unconditionally update the static field in ReferenceProcessor + // here so that we use the new value during processing of the + // discovered soft refs. + + _soft_ref_timestamp_clock = java_lang_ref_SoftReference::clock(); + bool trace_time = PrintGCDetails && PrintReferenceGC; // Soft references { @@ -404,7 +411,7 @@ // allocated and are indexed into. assert(_n_queues == (int) _ref_processor.max_num_q(), "Different number not expected"); for (int j = 0; - j < subclasses_of_ref; + j < ReferenceProcessor::number_of_subclasses_of_ref(); j++, index += _n_queues) { _ref_processor.enqueue_discovered_reflist( _refs_lists[index], _pending_list_addr); @@ -419,132 +426,20 @@ AbstractRefProcTaskExecutor* task_executor) { if (_processing_is_mt && task_executor != NULL) { // Parallel code - RefProcEnqueueTask tsk(*this, _discoveredSoftRefs, + RefProcEnqueueTask tsk(*this, _discovered_refs, pending_list_addr, _max_num_q); task_executor->execute(tsk); } else { // Serial code: call the parent class's implementation - for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { - enqueue_discovered_reflist(_discoveredSoftRefs[i], pending_list_addr); - _discoveredSoftRefs[i].set_head(NULL); - _discoveredSoftRefs[i].set_length(0); + for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { + enqueue_discovered_reflist(_discovered_refs[i], pending_list_addr); + _discovered_refs[i].set_head(NULL); + _discovered_refs[i].set_length(0); } } } -// Iterator for the list of discovered references. -class DiscoveredListIterator { -public: - inline DiscoveredListIterator(DiscoveredList& refs_list, - OopClosure* keep_alive, - BoolObjectClosure* is_alive); - - // End Of List. - inline bool has_next() const { return _ref != NULL; } - - // Get oop to the Reference object. - inline oop obj() const { return _ref; } - - // Get oop to the referent object. - inline oop referent() const { return _referent; } - - // Returns true if referent is alive. - inline bool is_referent_alive() const; - - // Loads data for the current reference. - // The "allow_null_referent" argument tells us to allow for the possibility - // of a NULL referent in the discovered Reference object. This typically - // happens in the case of concurrent collectors that may have done the - // discovery concurrently, or interleaved, with mutator execution. - inline void load_ptrs(DEBUG_ONLY(bool allow_null_referent)); - - // Move to the next discovered reference. - inline void next(); - - // Remove the current reference from the list - inline void remove(); - - // Make the Reference object active again. - inline void make_active() { java_lang_ref_Reference::set_next(_ref, NULL); } - - // Make the referent alive. - inline void make_referent_alive() { - if (UseCompressedOops) { - _keep_alive->do_oop((narrowOop*)_referent_addr); - } else { - _keep_alive->do_oop((oop*)_referent_addr); - } - } - - // Update the discovered field. - inline void update_discovered() { - // First _prev_next ref actually points into DiscoveredList (gross). - if (UseCompressedOops) { - if (!oopDesc::is_null(*(narrowOop*)_prev_next)) { - _keep_alive->do_oop((narrowOop*)_prev_next); - } - } else { - if (!oopDesc::is_null(*(oop*)_prev_next)) { - _keep_alive->do_oop((oop*)_prev_next); - } - } - } - - // NULL out referent pointer. - inline void clear_referent() { oop_store_raw(_referent_addr, NULL); } - - // Statistics - NOT_PRODUCT( - inline size_t processed() const { return _processed; } - inline size_t removed() const { return _removed; } - ) - - inline void move_to_next(); - -private: - DiscoveredList& _refs_list; - HeapWord* _prev_next; - oop _prev; - oop _ref; - HeapWord* _discovered_addr; - oop _next; - HeapWord* _referent_addr; - oop _referent; - OopClosure* _keep_alive; - BoolObjectClosure* _is_alive; - DEBUG_ONLY( - oop _first_seen; // cyclic linked list check - ) - NOT_PRODUCT( - size_t _processed; - size_t _removed; - ) -}; - -inline DiscoveredListIterator::DiscoveredListIterator(DiscoveredList& refs_list, - OopClosure* keep_alive, - BoolObjectClosure* is_alive) - : _refs_list(refs_list), - _prev_next(refs_list.adr_head()), - _prev(NULL), - _ref(refs_list.head()), -#ifdef ASSERT - _first_seen(refs_list.head()), -#endif -#ifndef PRODUCT - _processed(0), - _removed(0), -#endif - _next(NULL), - _keep_alive(keep_alive), - _is_alive(is_alive) -{ } - -inline bool DiscoveredListIterator::is_referent_alive() const { - return _is_alive->do_object_b(_referent); -} - -inline void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referent)) { +void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referent)) { _discovered_addr = java_lang_ref_Reference::discovered_addr(_ref); oop discovered = java_lang_ref_Reference::discovered(_ref); assert(_discovered_addr && discovered->is_oop_or_null(), @@ -560,13 +455,7 @@ "bad referent"); } -inline void DiscoveredListIterator::next() { - _prev_next = _discovered_addr; - _prev = _ref; - move_to_next(); -} - -inline void DiscoveredListIterator::remove() { +void DiscoveredListIterator::remove() { assert(_ref->is_oop(), "Dropping a bad reference"); oop_store_raw(_discovered_addr, NULL); @@ -592,15 +481,29 @@ _refs_list.dec_length(1); } -inline void DiscoveredListIterator::move_to_next() { - if (_ref == _next) { - // End of the list. - _ref = NULL; +// Make the Reference object active again. +void DiscoveredListIterator::make_active() { + // For G1 we don't want to use set_next - it + // will dirty the card for the next field of + // the reference object and will fail + // CT verification. + if (UseG1GC) { + BarrierSet* bs = oopDesc::bs(); + HeapWord* next_addr = java_lang_ref_Reference::next_addr(_ref); + + if (UseCompressedOops) { + bs->write_ref_field_pre((narrowOop*)next_addr, NULL); + } else { + bs->write_ref_field_pre((oop*)next_addr, NULL); + } + java_lang_ref_Reference::set_next_raw(_ref, NULL); } else { - _ref = _next; + java_lang_ref_Reference::set_next(_ref, NULL); } - assert(_ref != _first_seen, "cyclic ref_list found"); - NOT_PRODUCT(_processed++); +} + +void DiscoveredListIterator::clear_referent() { + oop_store_raw(_referent_addr, NULL); } // NOTE: process_phase*() are largely similar, and at a high level @@ -627,7 +530,8 @@ while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */)); bool referent_is_dead = (iter.referent() != NULL) && !iter.is_referent_alive(); - if (referent_is_dead && !policy->should_clear_reference(iter.obj())) { + if (referent_is_dead && + !policy->should_clear_reference(iter.obj(), _soft_ref_timestamp_clock)) { if (TraceReferenceGC) { gclog_or_tty->print_cr("Dropping reference (" INTPTR_FORMAT ": %s" ") by policy", iter.obj(), iter.obj()->blueprint()->internal_name()); @@ -786,12 +690,11 @@ void ReferenceProcessor::abandon_partial_discovery() { // loop over the lists - for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { + for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) { - gclog_or_tty->print_cr("\nAbandoning %s discovered list", - list_name(i)); + gclog_or_tty->print_cr("\nAbandoning %s discovered list", list_name(i)); } - abandon_partial_discovered_list(_discoveredSoftRefs[i]); + abandon_partial_discovered_list(_discovered_refs[i]); } } @@ -858,6 +761,14 @@ bool _clear_referent; }; +void ReferenceProcessor::set_discovered(oop ref, oop value) { + if (_discovered_list_needs_barrier) { + java_lang_ref_Reference::set_discovered(ref, value); + } else { + java_lang_ref_Reference::set_discovered_raw(ref, value); + } +} + // Balances reference queues. // Move entries from all queues[0, 1, ..., _max_num_q-1] to // queues[0, 1, ..., _num_q-1] because only the first _num_q @@ -915,9 +826,9 @@ // Add the chain to the to list. if (ref_lists[to_idx].head() == NULL) { // to list is empty. Make a loop at the end. - java_lang_ref_Reference::set_discovered(move_tail, move_tail); + set_discovered(move_tail, move_tail); } else { - java_lang_ref_Reference::set_discovered(move_tail, ref_lists[to_idx].head()); + set_discovered(move_tail, ref_lists[to_idx].head()); } ref_lists[to_idx].set_head(move_head); ref_lists[to_idx].inc_length(refs_to_move); @@ -1038,17 +949,13 @@ void ReferenceProcessor::clean_up_discovered_references() { // loop over the lists - // Should this instead be - // for (int i = 0; i < subclasses_of_ref; i++_ { - // for (int j = 0; j < _num_q; j++) { - // int index = i * _max_num_q + j; - for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { + for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) { gclog_or_tty->print_cr( "\nScrubbing %s discovered list of Null referents", list_name(i)); } - clean_up_discovered_reflist(_discoveredSoftRefs[i]); + clean_up_discovered_reflist(_discovered_refs[i]); } } @@ -1255,11 +1162,13 @@ // time-stamp policies advance the soft-ref clock only // at a major collection cycle, this is always currently // accurate. - if (!_current_soft_ref_policy->should_clear_reference(obj)) { + if (!_current_soft_ref_policy->should_clear_reference(obj, _soft_ref_timestamp_clock)) { return false; } } + ResourceMark rm; // Needed for tracing. + HeapWord* const discovered_addr = java_lang_ref_Reference::discovered_addr(obj); const oop discovered = java_lang_ref_Reference::discovered(obj); assert(discovered->is_oop_or_null(), "bad discovered field"); @@ -1472,7 +1381,9 @@ } const char* ReferenceProcessor::list_name(int i) { - assert(i >= 0 && i <= _max_num_q * subclasses_of_ref, "Out of bounds index"); + assert(i >= 0 && i <= _max_num_q * number_of_subclasses_of_ref(), + "Out of bounds index"); + int j = i / _max_num_q; switch (j) { case 0: return "SoftRef"; @@ -1493,8 +1404,8 @@ #ifndef PRODUCT void ReferenceProcessor::clear_discovered_references() { guarantee(!_discovering_refs, "Discovering refs?"); - for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { - clear_discovered_references(_discoveredSoftRefs[i]); + for (int i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { + clear_discovered_references(_discovered_refs[i]); } }
--- a/src/share/vm/memory/referenceProcessor.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/memory/referenceProcessor.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -48,18 +48,177 @@ // forward references class ReferencePolicy; class AbstractRefProcTaskExecutor; -class DiscoveredList; + +// List of discovered references. +class DiscoveredList { +public: + DiscoveredList() : _len(0), _compressed_head(0), _oop_head(NULL) { } + oop head() const { + return UseCompressedOops ? oopDesc::decode_heap_oop(_compressed_head) : + _oop_head; + } + HeapWord* adr_head() { + return UseCompressedOops ? (HeapWord*)&_compressed_head : + (HeapWord*)&_oop_head; + } + void set_head(oop o) { + if (UseCompressedOops) { + // Must compress the head ptr. + _compressed_head = oopDesc::encode_heap_oop(o); + } else { + _oop_head = o; + } + } + bool is_empty() const { return head() == NULL; } + size_t length() { return _len; } + void set_length(size_t len) { _len = len; } + void inc_length(size_t inc) { _len += inc; assert(_len > 0, "Error"); } + void dec_length(size_t dec) { _len -= dec; } +private: + // Set value depending on UseCompressedOops. This could be a template class + // but then we have to fix all the instantiations and declarations that use this class. + oop _oop_head; + narrowOop _compressed_head; + size_t _len; +}; + +// Iterator for the list of discovered references. +class DiscoveredListIterator { +private: + DiscoveredList& _refs_list; + HeapWord* _prev_next; + oop _prev; + oop _ref; + HeapWord* _discovered_addr; + oop _next; + HeapWord* _referent_addr; + oop _referent; + OopClosure* _keep_alive; + BoolObjectClosure* _is_alive; + + DEBUG_ONLY( + oop _first_seen; // cyclic linked list check + ) + + NOT_PRODUCT( + size_t _processed; + size_t _removed; + ) + +public: + inline DiscoveredListIterator(DiscoveredList& refs_list, + OopClosure* keep_alive, + BoolObjectClosure* is_alive): + _refs_list(refs_list), + _prev_next(refs_list.adr_head()), + _prev(NULL), + _ref(refs_list.head()), +#ifdef ASSERT + _first_seen(refs_list.head()), +#endif +#ifndef PRODUCT + _processed(0), + _removed(0), +#endif + _next(NULL), + _keep_alive(keep_alive), + _is_alive(is_alive) +{ } + + // End Of List. + inline bool has_next() const { return _ref != NULL; } + + // Get oop to the Reference object. + inline oop obj() const { return _ref; } + + // Get oop to the referent object. + inline oop referent() const { return _referent; } + + // Returns true if referent is alive. + inline bool is_referent_alive() const { + return _is_alive->do_object_b(_referent); + } + + // Loads data for the current reference. + // The "allow_null_referent" argument tells us to allow for the possibility + // of a NULL referent in the discovered Reference object. This typically + // happens in the case of concurrent collectors that may have done the + // discovery concurrently, or interleaved, with mutator execution. + void load_ptrs(DEBUG_ONLY(bool allow_null_referent)); + + // Move to the next discovered reference. + inline void next() { + _prev_next = _discovered_addr; + _prev = _ref; + move_to_next(); + } + + // Remove the current reference from the list + void remove(); + + // Make the Reference object active again. + void make_active(); + + // Make the referent alive. + inline void make_referent_alive() { + if (UseCompressedOops) { + _keep_alive->do_oop((narrowOop*)_referent_addr); + } else { + _keep_alive->do_oop((oop*)_referent_addr); + } + } + + // Update the discovered field. + inline void update_discovered() { + // First _prev_next ref actually points into DiscoveredList (gross). + if (UseCompressedOops) { + if (!oopDesc::is_null(*(narrowOop*)_prev_next)) { + _keep_alive->do_oop((narrowOop*)_prev_next); + } + } else { + if (!oopDesc::is_null(*(oop*)_prev_next)) { + _keep_alive->do_oop((oop*)_prev_next); + } + } + } + + // NULL out referent pointer. + void clear_referent(); + + // Statistics + NOT_PRODUCT( + inline size_t processed() const { return _processed; } + inline size_t removed() const { return _removed; } + ) + + inline void move_to_next() { + if (_ref == _next) { + // End of the list. + _ref = NULL; + } else { + _ref = _next; + } + assert(_ref != _first_seen, "cyclic ref_list found"); + NOT_PRODUCT(_processed++); + } +}; class ReferenceProcessor : public CHeapObj { protected: // Compatibility with pre-4965777 JDK's static bool _pending_list_uses_discovered_field; - MemRegion _span; // (right-open) interval of heap - // subject to wkref discovery - bool _discovering_refs; // true when discovery enabled - bool _discovery_is_atomic; // if discovery is atomic wrt - // other collectors in configuration - bool _discovery_is_mt; // true if reference discovery is MT. + + // The SoftReference master timestamp clock + static jlong _soft_ref_timestamp_clock; + + MemRegion _span; // (right-open) interval of heap + // subject to wkref discovery + + bool _discovering_refs; // true when discovery enabled + bool _discovery_is_atomic; // if discovery is atomic wrt + // other collectors in configuration + bool _discovery_is_mt; // true if reference discovery is MT. + // If true, setting "next" field of a discovered refs list requires // write barrier(s). (Must be true if used in a collector in which // elements of a discovered list may be moved during discovery: for @@ -67,18 +226,19 @@ // long-term concurrent marking phase that does weak reference // discovery.) bool _discovered_list_needs_barrier; - BarrierSet* _bs; // Cached copy of BarrierSet. - bool _enqueuing_is_done; // true if all weak references enqueued - bool _processing_is_mt; // true during phases when - // reference processing is MT. - int _next_id; // round-robin mod _num_q counter in - // support of work distribution - // For collectors that do not keep GC marking information + BarrierSet* _bs; // Cached copy of BarrierSet. + bool _enqueuing_is_done; // true if all weak references enqueued + bool _processing_is_mt; // true during phases when + // reference processing is MT. + int _next_id; // round-robin mod _num_q counter in + // support of work distribution + + // For collectors that do not keep GC liveness information // in the object header, this field holds a closure that // helps the reference processor determine the reachability - // of an oop (the field is currently initialized to NULL for - // all collectors but the CMS collector). + // of an oop. It is currently initialized to NULL for all + // collectors except for CMS and G1. BoolObjectClosure* _is_alive_non_header; // Soft ref clearing policies @@ -95,17 +255,25 @@ int _num_q; // The maximum MT'ness degree of the queues below int _max_num_q; - // Arrays of lists of oops, one per thread + + // Master array of discovered oops + DiscoveredList* _discovered_refs; + + // Arrays of lists of oops, one per thread (pointers into master array above) DiscoveredList* _discoveredSoftRefs; DiscoveredList* _discoveredWeakRefs; DiscoveredList* _discoveredFinalRefs; DiscoveredList* _discoveredPhantomRefs; public: - int num_q() { return _num_q; } - int max_num_q() { return _max_num_q; } - void set_active_mt_degree(int v) { _num_q = v; } - DiscoveredList* discovered_soft_refs() { return _discoveredSoftRefs; } + static int number_of_subclasses_of_ref() { return (REF_PHANTOM - REF_OTHER); } + + int num_q() { return _num_q; } + int max_num_q() { return _max_num_q; } + void set_active_mt_degree(int v) { _num_q = v; } + + DiscoveredList* discovered_refs() { return _discovered_refs; } + ReferencePolicy* setup_policy(bool always_clear) { _current_soft_ref_policy = always_clear ? _always_clear_soft_ref_policy : _default_soft_ref_policy; @@ -205,6 +373,11 @@ void enqueue_discovered_reflists(HeapWord* pending_list_addr, AbstractRefProcTaskExecutor* task_executor); protected: + // Set the 'discovered' field of the given reference to + // the given value - emitting barriers depending upon + // the value of _discovered_list_needs_barrier. + void set_discovered(oop ref, oop value); + // "Preclean" the given discovered reference list // by removing references with strongly reachable referents. // Currently used in support of CMS only. @@ -243,6 +416,7 @@ // constructor ReferenceProcessor(): _span((HeapWord*)NULL, (HeapWord*)NULL), + _discovered_refs(NULL), _discoveredSoftRefs(NULL), _discoveredWeakRefs(NULL), _discoveredFinalRefs(NULL), _discoveredPhantomRefs(NULL), _discovering_refs(false), @@ -290,7 +464,7 @@ void set_span(MemRegion span) { _span = span; } // start and stop weak ref discovery - void enable_discovery() { _discovering_refs = true; } + void enable_discovery(bool verify_disabled, bool check_no_refs); void disable_discovery() { _discovering_refs = false; } bool discovery_enabled() { return _discovering_refs; } @@ -365,7 +539,7 @@ ~NoRefDiscovery() { if (_was_discovering_refs) { - _rp->enable_discovery(); + _rp->enable_discovery(true /*verify_disabled*/, false /*check_no_refs*/); } } };
--- a/src/share/vm/memory/resourceArea.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/memory/resourceArea.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif //------------------------------ResourceMark----------------------------------- debug_only(int ResourceArea::_warned;) // to suppress multiple warnings
--- a/src/share/vm/memory/resourceArea.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/memory/resourceArea.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // The resource area holds temporary data structures in the VM. // The actual allocation areas are thread local. Typical usage:
--- a/src/share/vm/memory/space.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/memory/space.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -44,6 +44,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif // A space is an abstraction for the "storage units" backing // up the generation abstraction. It includes specific
--- a/src/share/vm/memory/threadLocalAllocBuffer.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/memory/threadLocalAllocBuffer.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -38,6 +38,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // Thread-Local Edens support
--- a/src/share/vm/memory/universe.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/memory/universe.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -89,6 +89,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifndef SERIALGC #include "gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp" #include "gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp" @@ -890,7 +893,7 @@ } else if (UseG1GC) { #ifndef SERIALGC - G1CollectorPolicy* g1p = new G1CollectorPolicy_BestRegionsFirst(); + G1CollectorPolicy* g1p = new G1CollectorPolicy(); G1CollectedHeap* g1h = new G1CollectedHeap(g1p); Universe::_collectedHeap = g1h; #else // SERIALGC
--- a/src/share/vm/oops/constantPoolKlass.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/oops/constantPoolKlass.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -44,6 +44,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifndef SERIALGC #include "gc_implementation/parNew/parOopClosures.inline.hpp" #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
--- a/src/share/vm/oops/constantPoolOop.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/oops/constantPoolOop.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -1355,7 +1355,7 @@ } case JVM_CONSTANT_Long: { u8 val = Bytes::get_Java_u8(bytes); - printf("long "INT64_FORMAT, *(jlong *) &val); + printf("long "INT64_FORMAT, (int64_t) *(jlong *) &val); ent_size = 8; idx++; // Long takes two cpool slots break;
--- a/src/share/vm/oops/instanceKlass.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/oops/instanceKlass.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -61,6 +61,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifndef SERIALGC #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" @@ -77,6 +80,8 @@ #ifdef DTRACE_ENABLED +#ifndef USDT2 + HS_DTRACE_PROBE_DECL4(hotspot, class__initialization__required, char*, intptr_t, oop, intptr_t); HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__recursive, @@ -119,6 +124,42 @@ HS_DTRACE_PROBE5(hotspot, class__initialization__##type, \ data, len, (clss)->class_loader(), thread_type, wait); \ } +#else /* USDT2 */ + +#define HOTSPOT_CLASS_INITIALIZATION_required HOTSPOT_CLASS_INITIALIZATION_REQUIRED +#define HOTSPOT_CLASS_INITIALIZATION_recursive HOTSPOT_CLASS_INITIALIZATION_RECURSIVE +#define HOTSPOT_CLASS_INITIALIZATION_concurrent HOTSPOT_CLASS_INITIALIZATION_CONCURRENT +#define HOTSPOT_CLASS_INITIALIZATION_erroneous HOTSPOT_CLASS_INITIALIZATION_ERRONEOUS +#define HOTSPOT_CLASS_INITIALIZATION_super__failed HOTSPOT_CLASS_INITIALIZATION_SUPER_FAILED +#define HOTSPOT_CLASS_INITIALIZATION_clinit HOTSPOT_CLASS_INITIALIZATION_CLINIT +#define HOTSPOT_CLASS_INITIALIZATION_error HOTSPOT_CLASS_INITIALIZATION_ERROR +#define HOTSPOT_CLASS_INITIALIZATION_end HOTSPOT_CLASS_INITIALIZATION_END +#define DTRACE_CLASSINIT_PROBE(type, clss, thread_type) \ + { \ + char* data = NULL; \ + int len = 0; \ + Symbol* name = (clss)->name(); \ + if (name != NULL) { \ + data = (char*)name->bytes(); \ + len = name->utf8_length(); \ + } \ + HOTSPOT_CLASS_INITIALIZATION_##type( \ + data, len, (clss)->class_loader(), thread_type); \ + } + +#define DTRACE_CLASSINIT_PROBE_WAIT(type, clss, thread_type, wait) \ + { \ + char* data = NULL; \ + int len = 0; \ + Symbol* name = (clss)->name(); \ + if (name != NULL) { \ + data = (char*)name->bytes(); \ + len = name->utf8_length(); \ + } \ + HOTSPOT_CLASS_INITIALIZATION_##type( \ + data, len, (clss)->class_loader(), thread_type, wait); \ + } +#endif /* USDT2 */ #else // ndef DTRACE_ENABLED
--- a/src/share/vm/oops/instanceMirrorKlass.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/oops/instanceMirrorKlass.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -288,15 +288,7 @@ // Query before forming handle. int size = instance_size(k); KlassHandle h_k(THREAD, as_klassOop()); - instanceOop i; - - if (JavaObjectsInPerm) { - i = (instanceOop) CollectedHeap::permanent_obj_allocate(h_k, size, CHECK_NULL); - } else { - assert(ScavengeRootsInCode > 0, "must be"); - i = (instanceOop) CollectedHeap::obj_allocate(h_k, size, CHECK_NULL); - } - + instanceOop i = (instanceOop) CollectedHeap::Class_obj_allocate(h_k, size, k, CHECK_NULL); return i; }
--- a/src/share/vm/oops/markOop.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/oops/markOop.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -33,6 +33,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif void markOopDesc::print_on(outputStream* st) const {
--- a/src/share/vm/oops/oop.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/oops/oop.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -36,6 +36,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif bool always_do_update_barrier = false;
--- a/src/share/vm/oops/oopsHierarchy.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/oops/oopsHierarchy.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -37,6 +37,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifdef CHECK_UNHANDLED_OOPS
--- a/src/share/vm/oops/typeArrayKlass.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/oops/typeArrayKlass.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -76,7 +76,7 @@ return k(); } -typeArrayOop typeArrayKlass::allocate(int length, TRAPS) { +typeArrayOop typeArrayKlass::allocate_common(int length, bool do_zero, TRAPS) { assert(log2_element_size() >= 0, "bad scale"); if (length >= 0) { if (length <= max_length()) { @@ -84,7 +84,11 @@ KlassHandle h_k(THREAD, as_klassOop()); typeArrayOop t; CollectedHeap* ch = Universe::heap(); - t = (typeArrayOop)CollectedHeap::array_allocate(h_k, (int)size, length, CHECK_NULL); + if (do_zero) { + t = (typeArrayOop)CollectedHeap::array_allocate(h_k, (int)size, length, CHECK_NULL); + } else { + t = (typeArrayOop)CollectedHeap::array_allocate_nozero(h_k, (int)size, length, CHECK_NULL); + } assert(t->is_parsable(), "Don't publish unless parsable"); return t; } else {
--- a/src/share/vm/oops/typeArrayKlass.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/oops/typeArrayKlass.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -56,7 +56,8 @@ bool compute_is_subtype_of(klassOop k); // Allocation - typeArrayOop allocate(int length, TRAPS); + typeArrayOop allocate_common(int length, bool do_zero, TRAPS); + typeArrayOop allocate(int length, TRAPS) { return allocate_common(length, true, THREAD); } typeArrayOop allocate_permanent(int length, TRAPS); // used for class file structures oop multi_allocate(int rank, jint* sizes, TRAPS);
--- a/src/share/vm/oops/typeArrayOop.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/oops/typeArrayOop.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -51,6 +51,12 @@ #ifdef TARGET_OS_ARCH_linux_ppc # include "orderAccess_linux_ppc.inline.hpp" #endif +#ifdef TARGET_OS_ARCH_bsd_x86 +# include "orderAccess_bsd_x86.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_bsd_zero +# include "orderAccess_bsd_zero.inline.hpp" +#endif // A typeArrayOop is an array containing basic types (non oop elements). // It is used for arrays of {characters, singles, doubles, bytes, shorts, integers, longs}
--- a/src/share/vm/opto/c2_globals.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/opto/c2_globals.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -44,6 +44,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "c2_globals_windows.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "c2_globals_bsd.hpp" +#endif // // Defines all globals flags used by the server compiler.
--- a/src/share/vm/opto/connode.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/opto/connode.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -721,12 +721,7 @@ if( t == Type::TOP ) return Type::TOP; if( t == Type::FLOAT ) return Type::DOUBLE; const TypeF *tf = t->is_float_constant(); -#ifndef IA64 return TypeD::make( (double)tf->getf() ); -#else - float x = tf->getf(); - return TypeD::make( (x == 0.0f) ? (double)x : (double)x + ia64_double_zero ); -#endif } //=============================================================================
--- a/src/share/vm/opto/library_call.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/opto/library_call.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -4658,6 +4658,7 @@ // "You break it, you buy it." InitializeNode* init = alloc->initialization(); assert(init->is_complete(), "we just did this"); + init->set_complete_with_arraycopy(); assert(dest->is_CheckCastPP(), "sanity"); assert(dest->in(0)->in(0) == init, "dest pinned"); adr_type = TypeRawPtr::BOTTOM; // all initializations are into raw memory
--- a/src/share/vm/opto/macro.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/opto/macro.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -1685,9 +1685,21 @@ void PhaseMacroExpand::expand_allocate_array(AllocateArrayNode *alloc) { Node* length = alloc->in(AllocateNode::ALength); + InitializeNode* init = alloc->initialization(); + Node* klass_node = alloc->in(AllocateNode::KlassNode); + ciKlass* k = _igvn.type(klass_node)->is_klassptr()->klass(); + address slow_call_address; // Address of slow call + if (init != NULL && init->is_complete_with_arraycopy() && + k->is_type_array_klass()) { + // Don't zero type array during slow allocation in VM since + // it will be initialized later by arraycopy in compiled code. + slow_call_address = OptoRuntime::new_array_nozero_Java(); + } else { + slow_call_address = OptoRuntime::new_array_Java(); + } expand_allocate_common(alloc, length, OptoRuntime::new_array_Type(), - OptoRuntime::new_array_Java()); + slow_call_address); } //-----------------------mark_eliminated_locking_nodes-----------------------
--- a/src/share/vm/opto/memnode.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/opto/memnode.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -2847,7 +2847,7 @@ //---------------------------InitializeNode------------------------------------ InitializeNode::InitializeNode(Compile* C, int adr_type, Node* rawoop) - : _is_complete(false), + : _is_complete(Incomplete), MemBarNode(C, adr_type, rawoop) { init_class_id(Class_Initialize); @@ -2885,7 +2885,7 @@ void InitializeNode::set_complete(PhaseGVN* phase) { assert(!is_complete(), "caller responsibility"); - _is_complete = true; + _is_complete = Complete; // After this node is complete, it contains a bunch of // raw-memory initializations. There is no need for
--- a/src/share/vm/opto/memnode.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/opto/memnode.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -942,7 +942,12 @@ class InitializeNode: public MemBarNode { friend class AllocateNode; - bool _is_complete; + enum { + Incomplete = 0, + Complete = 1, + WithArraycopy = 2 + }; + int _is_complete; public: enum { @@ -976,10 +981,12 @@ // An InitializeNode must completed before macro expansion is done. // Completion requires that the AllocateNode must be followed by // initialization of the new memory to zero, then to any initializers. - bool is_complete() { return _is_complete; } + bool is_complete() { return _is_complete != Incomplete; } + bool is_complete_with_arraycopy() { return (_is_complete & WithArraycopy) != 0; } // Mark complete. (Must not yet be complete.) void set_complete(PhaseGVN* phase); + void set_complete_with_arraycopy() { _is_complete = Complete | WithArraycopy; } #ifdef ASSERT // ensure all non-degenerate stores are ordered and non-overlapping
--- a/src/share/vm/opto/phaseX.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/opto/phaseX.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -864,6 +864,10 @@ // Pull from worklist; transform node; // If node has changed: update edge info and put uses on worklist. while( _worklist.size() ) { + if (C->check_node_count(NodeLimitFudgeFactor * 2, + "out of nodes optimizing method")) { + return; + } Node *n = _worklist.pop(); if (++loop_count >= K * C->unique()) { debug_only(n->dump(4);)
--- a/src/share/vm/opto/runtime.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/opto/runtime.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -102,6 +102,7 @@ // Compiled code entry points address OptoRuntime::_new_instance_Java = NULL; address OptoRuntime::_new_array_Java = NULL; +address OptoRuntime::_new_array_nozero_Java = NULL; address OptoRuntime::_multianewarray2_Java = NULL; address OptoRuntime::_multianewarray3_Java = NULL; address OptoRuntime::_multianewarray4_Java = NULL; @@ -151,6 +152,7 @@ // ------------------------------------------------------------------------------------------------------------------------------- gen(env, _new_instance_Java , new_instance_Type , new_instance_C , 0 , true , false, false); gen(env, _new_array_Java , new_array_Type , new_array_C , 0 , true , false, false); + gen(env, _new_array_nozero_Java , new_array_Type , new_array_nozero_C , 0 , true , false, false); gen(env, _multianewarray2_Java , multianewarray2_Type , multianewarray2_C , 0 , true , false, false); gen(env, _multianewarray3_Java , multianewarray3_Type , multianewarray3_C , 0 , true , false, false); gen(env, _multianewarray4_Java , multianewarray4_Type , multianewarray4_C , 0 , true , false, false); @@ -308,6 +310,36 @@ } JRT_END +// array allocation without zeroing +JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_nozero_C(klassOopDesc* array_type, int len, JavaThread *thread)) + JRT_BLOCK; +#ifndef PRODUCT + SharedRuntime::_new_array_ctr++; // new array requires GC +#endif + assert(check_compiled_frame(thread), "incorrect caller"); + + // Scavenge and allocate an instance. + oop result; + + assert(Klass::cast(array_type)->oop_is_typeArray(), "should be called only for type array"); + // The oopFactory likes to work with the element type. + BasicType elem_type = typeArrayKlass::cast(array_type)->element_type(); + result = oopFactory::new_typeArray_nozero(elem_type, len, THREAD); + + // Pass oops back through thread local storage. Our apparent type to Java + // is that we return an oop, but we can block on exit from this routine and + // a GC can trash the oop in C's return register. The generated stub will + // fetch the oop from TLS after any possible GC. + deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); + thread->set_vm_result(result); + JRT_BLOCK_END; + + if (GraphKit::use_ReduceInitialCardMarks()) { + // inform GC that we won't do card marks for initializing writes. + new_store_pre_barrier(thread); + } +JRT_END + // Note: multianewarray for one dimension is handled inline by GraphKit::new_array. // multianewarray for 2 dimensions @@ -965,10 +997,13 @@ force_unwind ? NULL : nm->handler_for_exception_and_pc(exception, pc); if (handler_address == NULL) { + Handle original_exception(thread, exception()); handler_address = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true); assert (handler_address != NULL, "must have compiled handler"); - // Update the exception cache only when the unwind was not forced. - if (!force_unwind) { + // Update the exception cache only when the unwind was not forced + // and there didn't happen another exception during the computation of the + // compiled exception handler. + if (!force_unwind && original_exception() == exception()) { nm->add_handler_for_exception_and_pc(exception,pc,handler_address); } } else {
--- a/src/share/vm/opto/runtime.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/opto/runtime.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -114,6 +114,7 @@ // References to generated stubs static address _new_instance_Java; static address _new_array_Java; + static address _new_array_nozero_Java; static address _multianewarray2_Java; static address _multianewarray3_Java; static address _multianewarray4_Java; @@ -143,6 +144,7 @@ // Allocate storage for a objArray or typeArray static void new_array_C(klassOopDesc* array_klass, int len, JavaThread *thread); + static void new_array_nozero_C(klassOopDesc* array_klass, int len, JavaThread *thread); // Post-slow-path-allocation, pre-initializing-stores step for // implementing ReduceInitialCardMarks @@ -208,6 +210,7 @@ // access to runtime stubs entry points for java code static address new_instance_Java() { return _new_instance_Java; } static address new_array_Java() { return _new_array_Java; } + static address new_array_nozero_Java() { return _new_array_nozero_Java; } static address multianewarray2_Java() { return _multianewarray2_Java; } static address multianewarray3_Java() { return _multianewarray3_Java; } static address multianewarray4_Java() { return _multianewarray4_Java; }
--- a/src/share/vm/prims/forte.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/prims/forte.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -621,6 +621,11 @@ // Method to let libcollector know about a dynamically loaded function. // Because it is weakly bound, the calls become NOP's when the library // isn't present. +#ifdef __APPLE__ +// XXXDARWIN: Link errors occur even when __attribute__((weak_import)) +// is added +#define collector_func_load(x0,x1,x2,x3,x4,x5,x6) (0) +#else void collector_func_load(char* name, void* null_argument_1, void* null_argument_2, @@ -631,6 +636,7 @@ #pragma weak collector_func_load #define collector_func_load(x0,x1,x2,x3,x4,x5,x6) \ ( collector_func_load ? collector_func_load(x0,x1,x2,x3,x4,x5,x6),0 : 0 ) +#endif // __APPLE__ #endif // !_WINDOWS } // end extern "C"
--- a/src/share/vm/prims/jni.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/prims/jni.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -82,6 +82,10 @@ # include "os_windows.inline.hpp" # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +# include "thread_bsd.inline.hpp" +#endif static jint CurrentVersion = JNI_VERSION_1_6; @@ -106,6 +110,7 @@ // return_value = 5; // return return_value; // JNI_END +#ifndef USDT2 #define DT_RETURN_MARK_DECL(name, type) \ HS_DTRACE_PROBE_DECL1(hotspot_jni, name##__return, type); \ DTRACE_ONLY( \ @@ -130,6 +135,30 @@ } \ ) +#else /* USDT2 */ + +#define DT_RETURN_MARK_DECL(name, type, probe) \ + DTRACE_ONLY( \ + class DTraceReturnProbeMark_##name { \ + public: \ + const type& _ret_ref; \ + DTraceReturnProbeMark_##name(const type& v) : _ret_ref(v) {} \ + ~DTraceReturnProbeMark_##name() { \ + probe; \ + } \ + } \ + ) +// Void functions are simpler since there's no return value +#define DT_VOID_RETURN_MARK_DECL(name, probe) \ + DTRACE_ONLY( \ + class DTraceReturnProbeMark_##name { \ + public: \ + ~DTraceReturnProbeMark_##name() { \ + probe; \ + } \ + } \ + ) +#endif /* USDT2 */ // Place these macros in the function to mark the return. Non-void // functions need the type and address of the return value. @@ -158,9 +187,15 @@ // Choose DT_RETURN_MARK macros based on the type: float/double -> void // (dtrace doesn't do FP yet) +#ifndef USDT2 #define DT_RETURN_MARK_DECL_FOR(TypeName, name, type) \ FP_SELECT(TypeName, \ DT_RETURN_MARK_DECL(name, type), DT_VOID_RETURN_MARK_DECL(name) ) +#else /* USDT2 */ +#define DT_RETURN_MARK_DECL_FOR(TypeName, name, type, probe) \ + FP_SELECT(TypeName, \ + DT_RETURN_MARK_DECL(name, type, probe), DT_VOID_RETURN_MARK_DECL(name, probe) ) +#endif /* USDT2 */ #define DT_RETURN_MARK_FOR(TypeName, name, type, ref) \ FP_SELECT(TypeName, \ DT_RETURN_MARK(name, type, ref), DT_VOID_RETURN_MARK(name) ) @@ -319,14 +354,24 @@ // Implementation of JNI entries +#ifndef USDT2 DT_RETURN_MARK_DECL(DefineClass, jclass); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(DefineClass, jclass + , HOTSPOT_JNI_DEFINECLASS_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderRef, const jbyte *buf, jsize bufLen)) JNIWrapper("DefineClass"); +#ifndef USDT2 DTRACE_PROBE5(hotspot_jni, DefineClass__entry, env, name, loaderRef, buf, bufLen); +#else /* USDT2 */ + HOTSPOT_JNI_DEFINECLASS_ENTRY( + env, (char*) name, loaderRef, (char*) buf, bufLen); +#endif /* USDT2 */ jclass cls = NULL; DT_RETURN_MARK(DefineClass, jclass, (const jclass&)cls); @@ -372,11 +417,21 @@ static bool first_time_FindClass = true; +#ifndef USDT2 DT_RETURN_MARK_DECL(FindClass, jclass); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(FindClass, jclass + , HOTSPOT_JNI_FINDCLASS_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jclass, jni_FindClass(JNIEnv *env, const char *name)) JNIWrapper("FindClass"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, FindClass__entry, env, name); +#else /* USDT2 */ + HOTSPOT_JNI_FINDCLASS_ENTRY( + env, (char *)name); +#endif /* USDT2 */ jclass result = NULL; DT_RETURN_MARK(FindClass, jclass, (const jclass&)result); @@ -440,11 +495,21 @@ return result; JNI_END +#ifndef USDT2 DT_RETURN_MARK_DECL(FromReflectedMethod, jmethodID); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(FromReflectedMethod, jmethodID + , HOTSPOT_JNI_FROMREFLECTEDMETHOD_RETURN((uintptr_t)_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jmethodID, jni_FromReflectedMethod(JNIEnv *env, jobject method)) JNIWrapper("FromReflectedMethod"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, FromReflectedMethod__entry, env, method); +#else /* USDT2 */ + HOTSPOT_JNI_FROMREFLECTEDMETHOD_ENTRY( + env, method); +#endif /* USDT2 */ jmethodID ret = NULL; DT_RETURN_MARK(FromReflectedMethod, jmethodID, (const jmethodID&)ret); @@ -471,11 +536,21 @@ return ret; JNI_END +#ifndef USDT2 DT_RETURN_MARK_DECL(FromReflectedField, jfieldID); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(FromReflectedField, jfieldID + , HOTSPOT_JNI_FROMREFLECTEDFIELD_RETURN((uintptr_t)_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jfieldID, jni_FromReflectedField(JNIEnv *env, jobject field)) JNIWrapper("FromReflectedField"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, FromReflectedField__entry, env, field); +#else /* USDT2 */ + HOTSPOT_JNI_FROMREFLECTEDFIELD_ENTRY( + env, field); +#endif /* USDT2 */ jfieldID ret = NULL; DT_RETURN_MARK(FromReflectedField, jfieldID, (const jfieldID&)ret); @@ -510,11 +585,21 @@ return ret; JNI_END +#ifndef USDT2 DT_RETURN_MARK_DECL(ToReflectedMethod, jobject); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(ToReflectedMethod, jobject + , HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic)) JNIWrapper("ToReflectedMethod"); +#ifndef USDT2 DTRACE_PROBE4(hotspot_jni, ToReflectedMethod__entry, env, cls, method_id, isStatic); +#else /* USDT2 */ + HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY( + env, cls, (uintptr_t) method_id, isStatic); +#endif /* USDT2 */ jobject ret = NULL; DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret); @@ -530,11 +615,21 @@ return ret; JNI_END +#ifndef USDT2 DT_RETURN_MARK_DECL(GetSuperclass, jclass); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(GetSuperclass, jclass + , HOTSPOT_JNI_GETSUPERCLASS_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub)) JNIWrapper("GetSuperclass"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, GetSuperclass__entry, env, sub); +#else /* USDT2 */ + HOTSPOT_JNI_GETSUPERCLASS_ENTRY( + env, sub); +#endif /* USDT2 */ jclass obj = NULL; DT_RETURN_MARK(GetSuperclass, jclass, (const jclass&)obj); @@ -563,13 +658,23 @@ JNI_QUICK_ENTRY(jboolean, jni_IsAssignableFrom(JNIEnv *env, jclass sub, jclass super)) JNIWrapper("IsSubclassOf"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, IsAssignableFrom__entry, env, sub, super); +#else /* USDT2 */ + HOTSPOT_JNI_ISASSIGNABLEFROM_ENTRY( + env, sub, super); +#endif /* USDT2 */ oop sub_mirror = JNIHandles::resolve_non_null(sub); oop super_mirror = JNIHandles::resolve_non_null(super); if (java_lang_Class::is_primitive(sub_mirror) || java_lang_Class::is_primitive(super_mirror)) { jboolean ret = (sub_mirror == super_mirror); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, IsAssignableFrom__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN( + ret); +#endif /* USDT2 */ return ret; } klassOop sub_klass = java_lang_Class::as_klassOop(sub_mirror); @@ -577,15 +682,30 @@ assert(sub_klass != NULL && super_klass != NULL, "invalid arguments to jni_IsAssignableFrom"); jboolean ret = Klass::cast(sub_klass)->is_subtype_of(super_klass) ? JNI_TRUE : JNI_FALSE; +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, IsAssignableFrom__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN( + ret); +#endif /* USDT2 */ return ret; JNI_END +#ifndef USDT2 DT_RETURN_MARK_DECL(Throw, jint); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(Throw, jint + , HOTSPOT_JNI_THROW_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jint, jni_Throw(JNIEnv *env, jthrowable obj)) JNIWrapper("Throw"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, Throw__entry, env, obj); +#else /* USDT2 */ + HOTSPOT_JNI_THROW_ENTRY( + env, obj); +#endif /* USDT2 */ jint ret = JNI_OK; DT_RETURN_MARK(Throw, jint, (const jint&)ret); @@ -593,11 +713,21 @@ ShouldNotReachHere(); JNI_END +#ifndef USDT2 DT_RETURN_MARK_DECL(ThrowNew, jint); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(ThrowNew, jint + , HOTSPOT_JNI_THROWNEW_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jint, jni_ThrowNew(JNIEnv *env, jclass clazz, const char *message)) JNIWrapper("ThrowNew"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, ThrowNew__entry, env, clazz, message); +#else /* USDT2 */ + HOTSPOT_JNI_THROWNEW_ENTRY( + env, clazz, (char *) message); +#endif /* USDT2 */ jint ret = JNI_OK; DT_RETURN_MARK(ThrowNew, jint, (const jint&)ret); @@ -626,18 +756,33 @@ JNI_ENTRY_NO_PRESERVE(jthrowable, jni_ExceptionOccurred(JNIEnv *env)) JNIWrapper("ExceptionOccurred"); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, ExceptionOccurred__entry, env); +#else /* USDT2 */ + HOTSPOT_JNI_EXCEPTIONOCCURRED_ENTRY( + env); +#endif /* USDT2 */ jni_check_async_exceptions(thread); oop exception = thread->pending_exception(); jthrowable ret = (jthrowable) JNIHandles::make_local(env, exception); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, ExceptionOccurred__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_EXCEPTIONOCCURRED_RETURN( + ret); +#endif /* USDT2 */ return ret; JNI_END JNI_ENTRY_NO_PRESERVE(void, jni_ExceptionDescribe(JNIEnv *env)) JNIWrapper("ExceptionDescribe"); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, ExceptionDescribe__entry, env); +#else /* USDT2 */ + HOTSPOT_JNI_EXCEPTIONDESCRIBE_ENTRY( + env); +#endif /* USDT2 */ if (thread->has_pending_exception()) { Handle ex(thread, thread->pending_exception()); thread->clear_pending_exception(); @@ -673,13 +818,23 @@ } } } +#ifndef USDT2 DTRACE_PROBE(hotspot_jni, ExceptionDescribe__return); +#else /* USDT2 */ + HOTSPOT_JNI_EXCEPTIONDESCRIBE_RETURN( + ); +#endif /* USDT2 */ JNI_END JNI_QUICK_ENTRY(void, jni_ExceptionClear(JNIEnv *env)) JNIWrapper("ExceptionClear"); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, ExceptionClear__entry, env); +#else /* USDT2 */ + HOTSPOT_JNI_EXCEPTIONCLEAR_ENTRY( + env); +#endif /* USDT2 */ // The jni code might be using this API to clear java thrown exception. // So just mark jvmti thread exception state as exception caught. @@ -688,13 +843,23 @@ state->set_exception_caught(); } thread->clear_pending_exception(); +#ifndef USDT2 DTRACE_PROBE(hotspot_jni, ExceptionClear__return); +#else /* USDT2 */ + HOTSPOT_JNI_EXCEPTIONCLEAR_RETURN( + ); +#endif /* USDT2 */ JNI_END JNI_ENTRY(void, jni_FatalError(JNIEnv *env, const char *msg)) JNIWrapper("FatalError"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, FatalError__entry, env, msg); +#else /* USDT2 */ + HOTSPOT_JNI_FATALERROR_ENTRY( + env, (char *) msg); +#endif /* USDT2 */ tty->print_cr("FATAL ERROR in native method: %s", msg); thread->print_stack(); os::abort(); // Dump core and abort @@ -703,10 +868,20 @@ JNI_ENTRY(jint, jni_PushLocalFrame(JNIEnv *env, jint capacity)) JNIWrapper("PushLocalFrame"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, PushLocalFrame__entry, env, capacity); +#else /* USDT2 */ + HOTSPOT_JNI_PUSHLOCALFRAME_ENTRY( + env, capacity); +#endif /* USDT2 */ //%note jni_11 if (capacity < 0 && capacity > MAX_REASONABLE_LOCAL_CAPACITY) { +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, PushLocalFrame__return, JNI_ERR); +#else /* USDT2 */ + HOTSPOT_JNI_PUSHLOCALFRAME_RETURN( + (uint32_t)JNI_ERR); +#endif /* USDT2 */ return JNI_ERR; } JNIHandleBlock* old_handles = thread->active_handles(); @@ -715,14 +890,24 @@ new_handles->set_pop_frame_link(old_handles); thread->set_active_handles(new_handles); jint ret = JNI_OK; +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, PushLocalFrame__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_PUSHLOCALFRAME_RETURN( + ret); +#endif /* USDT2 */ return ret; JNI_END JNI_ENTRY(jobject, jni_PopLocalFrame(JNIEnv *env, jobject result)) JNIWrapper("PopLocalFrame"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, PopLocalFrame__entry, env, result); +#else /* USDT2 */ + HOTSPOT_JNI_POPLOCALFRAME_ENTRY( + env, result); +#endif /* USDT2 */ //%note jni_11 Handle result_handle(thread, JNIHandles::resolve(result)); JNIHandleBlock* old_handles = thread->active_handles(); @@ -737,71 +922,141 @@ JNIHandleBlock::release_block(old_handles, thread); // may block result = JNIHandles::make_local(thread, result_handle()); } +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, PopLocalFrame__return, result); +#else /* USDT2 */ + HOTSPOT_JNI_POPLOCALFRAME_RETURN( + result); +#endif /* USDT2 */ return result; JNI_END JNI_ENTRY(jobject, jni_NewGlobalRef(JNIEnv *env, jobject ref)) JNIWrapper("NewGlobalRef"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, NewGlobalRef__entry, env, ref); +#else /* USDT2 */ + HOTSPOT_JNI_NEWGLOBALREF_ENTRY( + env, ref); +#endif /* USDT2 */ Handle ref_handle(thread, JNIHandles::resolve(ref)); jobject ret = JNIHandles::make_global(ref_handle); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, NewGlobalRef__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_NEWGLOBALREF_RETURN( + ret); +#endif /* USDT2 */ return ret; JNI_END // Must be JNI_ENTRY (with HandleMark) JNI_ENTRY_NO_PRESERVE(void, jni_DeleteGlobalRef(JNIEnv *env, jobject ref)) JNIWrapper("DeleteGlobalRef"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, DeleteGlobalRef__entry, env, ref); +#else /* USDT2 */ + HOTSPOT_JNI_DELETEGLOBALREF_ENTRY( + env, ref); +#endif /* USDT2 */ JNIHandles::destroy_global(ref); +#ifndef USDT2 DTRACE_PROBE(hotspot_jni, DeleteGlobalRef__return); +#else /* USDT2 */ + HOTSPOT_JNI_DELETEGLOBALREF_RETURN( + ); +#endif /* USDT2 */ JNI_END JNI_QUICK_ENTRY(void, jni_DeleteLocalRef(JNIEnv *env, jobject obj)) JNIWrapper("DeleteLocalRef"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, DeleteLocalRef__entry, env, obj); +#else /* USDT2 */ + HOTSPOT_JNI_DELETELOCALREF_ENTRY( + env, obj); +#endif /* USDT2 */ JNIHandles::destroy_local(obj); +#ifndef USDT2 DTRACE_PROBE(hotspot_jni, DeleteLocalRef__return); +#else /* USDT2 */ + HOTSPOT_JNI_DELETELOCALREF_RETURN( + ); +#endif /* USDT2 */ JNI_END JNI_QUICK_ENTRY(jboolean, jni_IsSameObject(JNIEnv *env, jobject r1, jobject r2)) JNIWrapper("IsSameObject"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, IsSameObject__entry, env, r1, r2); +#else /* USDT2 */ + HOTSPOT_JNI_ISSAMEOBJECT_ENTRY( + env, r1, r2); +#endif /* USDT2 */ oop a = JNIHandles::resolve(r1); oop b = JNIHandles::resolve(r2); jboolean ret = (a == b) ? JNI_TRUE : JNI_FALSE; +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, IsSameObject__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_ISSAMEOBJECT_RETURN( + ret); +#endif /* USDT2 */ return ret; JNI_END JNI_ENTRY(jobject, jni_NewLocalRef(JNIEnv *env, jobject ref)) JNIWrapper("NewLocalRef"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, NewLocalRef__entry, env, ref); +#else /* USDT2 */ + HOTSPOT_JNI_NEWLOCALREF_ENTRY( + env, ref); +#endif /* USDT2 */ jobject ret = JNIHandles::make_local(env, JNIHandles::resolve(ref)); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, NewLocalRef__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_NEWLOCALREF_RETURN( + ret); +#endif /* USDT2 */ return ret; JNI_END JNI_LEAF(jint, jni_EnsureLocalCapacity(JNIEnv *env, jint capacity)) JNIWrapper("EnsureLocalCapacity"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, EnsureLocalCapacity__entry, env, capacity); +#else /* USDT2 */ + HOTSPOT_JNI_ENSURELOCALCAPACITY_ENTRY( + env, capacity); +#endif /* USDT2 */ jint ret; if (capacity >= 0 && capacity <= MAX_REASONABLE_LOCAL_CAPACITY) { ret = JNI_OK; } else { ret = JNI_ERR; } +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, EnsureLocalCapacity__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_ENSURELOCALCAPACITY_RETURN( + ret); +#endif /* USDT2 */ return ret; JNI_END // Return the Handle Type JNI_LEAF(jobjectRefType, jni_GetObjectRefType(JNIEnv *env, jobject obj)) JNIWrapper("GetObjectRefType"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, GetObjectRefType__entry, env, obj); +#else /* USDT2 */ + HOTSPOT_JNI_GETOBJECTREFTYPE_ENTRY( + env, obj); +#endif /* USDT2 */ jobjectRefType ret; if (JNIHandles::is_local_handle(thread, obj) || JNIHandles::is_frame_handle(thread, obj)) @@ -812,7 +1067,12 @@ ret = JNIWeakGlobalRefType; else ret = JNIInvalidRefType; +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetObjectRefType__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_GETOBJECTREFTYPE_RETURN( + (void *) ret); +#endif /* USDT2 */ return ret; JNI_END @@ -1163,12 +1423,22 @@ return ih; } +#ifndef USDT2 DT_RETURN_MARK_DECL(AllocObject, jobject); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(AllocObject, jobject + , HOTSPOT_JNI_ALLOCOBJECT_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz)) JNIWrapper("AllocObject"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, AllocObject__entry, env, clazz); +#else /* USDT2 */ + HOTSPOT_JNI_ALLOCOBJECT_ENTRY( + env, clazz); +#endif /* USDT2 */ jobject ret = NULL; DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret); @@ -1177,11 +1447,21 @@ return ret; JNI_END +#ifndef USDT2 DT_RETURN_MARK_DECL(NewObjectA, jobject); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(NewObjectA, jobject + , HOTSPOT_JNI_NEWOBJECTA_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args)) JNIWrapper("NewObjectA"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, NewObjectA__entry, env, clazz, methodID); +#else /* USDT2 */ + HOTSPOT_JNI_NEWOBJECTA_ENTRY( + env, clazz, (uintptr_t) methodID); +#endif /* USDT2 */ jobject obj = NULL; DT_RETURN_MARK(NewObjectA, jobject, (const jobject)obj); @@ -1193,11 +1473,21 @@ return obj; JNI_END +#ifndef USDT2 DT_RETURN_MARK_DECL(NewObjectV, jobject); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(NewObjectV, jobject + , HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)) JNIWrapper("NewObjectV"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, NewObjectV__entry, env, clazz, methodID); +#else /* USDT2 */ + HOTSPOT_JNI_NEWOBJECTV_ENTRY( + env, clazz, (uintptr_t) methodID); +#endif /* USDT2 */ jobject obj = NULL; DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj); @@ -1209,11 +1499,21 @@ return obj; JNI_END +#ifndef USDT2 DT_RETURN_MARK_DECL(NewObject, jobject); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(NewObject, jobject + , HOTSPOT_JNI_NEWOBJECT_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jobject, jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)) JNIWrapper("NewObject"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, NewObject__entry, env, clazz, methodID); +#else /* USDT2 */ + HOTSPOT_JNI_NEWOBJECT_ENTRY( + env, clazz, (uintptr_t) methodID); +#endif /* USDT2 */ jobject obj = NULL; DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj); @@ -1231,17 +1531,32 @@ JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj)) JNIWrapper("GetObjectClass"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, GetObjectClass__entry, env, obj); +#else /* USDT2 */ + HOTSPOT_JNI_GETOBJECTCLASS_ENTRY( + env, obj); +#endif /* USDT2 */ klassOop k = JNIHandles::resolve_non_null(obj)->klass(); jclass ret = (jclass) JNIHandles::make_local(env, Klass::cast(k)->java_mirror()); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetObjectClass__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_GETOBJECTCLASS_RETURN( + ret); +#endif /* USDT2 */ return ret; JNI_END JNI_QUICK_ENTRY(jboolean, jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)) JNIWrapper("IsInstanceOf"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, IsInstanceOf__entry, env, obj, clazz); +#else /* USDT2 */ + HOTSPOT_JNI_ISINSTANCEOF_ENTRY( + env, obj, clazz); +#endif /* USDT2 */ jboolean ret = JNI_TRUE; if (obj != NULL) { ret = JNI_FALSE; @@ -1251,7 +1566,12 @@ ret = JNIHandles::resolve_non_null(obj)->is_a(k) ? JNI_TRUE : JNI_FALSE; } } +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, IsInstanceOf__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_ISINSTANCEOF_RETURN( + ret); +#endif /* USDT2 */ return ret; JNI_END @@ -1313,9 +1633,19 @@ JNI_ENTRY(jmethodID, jni_GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig)) JNIWrapper("GetMethodID"); +#ifndef USDT2 DTRACE_PROBE4(hotspot_jni, GetMethodID__entry, env, clazz, name, sig); +#else /* USDT2 */ + HOTSPOT_JNI_GETMETHODID_ENTRY( + env, clazz, (char *) name, (char *) sig); +#endif /* USDT2 */ jmethodID ret = get_method_id(env, clazz, name, sig, false, thread); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetMethodID__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_GETMETHODID_RETURN( + (uintptr_t) ret); +#endif /* USDT2 */ return ret; JNI_END @@ -1323,9 +1653,19 @@ JNI_ENTRY(jmethodID, jni_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig)) JNIWrapper("GetStaticMethodID"); +#ifndef USDT2 DTRACE_PROBE4(hotspot_jni, GetStaticMethodID__entry, env, clazz, name, sig); +#else /* USDT2 */ + HOTSPOT_JNI_GETSTATICMETHODID_ENTRY( + env, (char *) clazz, (char *) name, (char *)sig); +#endif /* USDT2 */ jmethodID ret = get_method_id(env, clazz, name, sig, true, thread); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetStaticMethodID__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_GETSTATICMETHODID_RETURN( + (uintptr_t) ret); +#endif /* USDT2 */ return ret; JNI_END @@ -1335,7 +1675,7 @@ // Calling Methods // - +#ifndef USDT2 #define DEFINE_CALLMETHOD(ResultType, Result, Tag) \ \ DT_RETURN_MARK_DECL_FOR(Result, Call##Result##Method, ResultType);\ @@ -1346,7 +1686,7 @@ jni_Call##Result##Method(JNIEnv *env, jobject obj, jmethodID methodID, ...)) \ JNIWrapper("Call" XSTR(Result) "Method"); \ \ - DTRACE_PROBE3(hotspot_jni, Call##Result##Method__entry, env, obj, methodID);\ + DTRACE_PROBE3(hotspot_jni, Call##Result##Method__entry, env, obj, methodID); \ ResultType ret = 0;\ DT_RETURN_MARK_FOR(Result, Call##Result##Method, ResultType, \ (const ResultType&)ret);\ @@ -1366,7 +1706,7 @@ jni_Call##Result##MethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)) \ JNIWrapper("Call" XSTR(Result) "MethodV"); \ \ - DTRACE_PROBE3(hotspot_jni, Call##Result##MethodV__entry, env, obj, methodID);\ + DTRACE_PROBE3(hotspot_jni, Call##Result##MethodV__entry, env, obj, methodID); \ ResultType ret = 0;\ DT_RETURN_MARK_FOR(Result, Call##Result##MethodV, ResultType, \ (const ResultType&)ret);\ @@ -1382,7 +1722,7 @@ JNI_ENTRY(ResultType, \ jni_Call##Result##MethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args)) \ JNIWrapper("Call" XSTR(Result) "MethodA"); \ - DTRACE_PROBE3(hotspot_jni, Call##Result##MethodA__entry, env, obj, methodID);\ + DTRACE_PROBE3(hotspot_jni, Call##Result##MethodA__entry, env, obj, methodID); \ ResultType ret = 0;\ DT_RETURN_MARK_FOR(Result, Call##Result##MethodA, ResultType, \ (const ResultType&)ret);\ @@ -1410,9 +1750,183 @@ DT_VOID_RETURN_MARK_DECL(CallVoidMethodV); DT_VOID_RETURN_MARK_DECL(CallVoidMethodA); +#else /* USDT2 */ + +#define DEFINE_CALLMETHOD(ResultType, Result, Tag \ + , EntryProbe, ReturnProbe) \ +\ + DT_RETURN_MARK_DECL_FOR(Result, Call##Result##Method, ResultType \ + , ReturnProbe); \ +\ +JNI_ENTRY(ResultType, \ + jni_Call##Result##Method(JNIEnv *env, jobject obj, jmethodID methodID, ...)) \ + JNIWrapper("Call" XSTR(Result) "Method"); \ +\ + EntryProbe; \ + ResultType ret = 0;\ + DT_RETURN_MARK_FOR(Result, Call##Result##Method, ResultType, \ + (const ResultType&)ret);\ +\ + va_list args; \ + va_start(args, methodID); \ + JavaValue jvalue(Tag); \ + JNI_ArgumentPusherVaArg ap(methodID, args); \ + jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \ + va_end(args); \ + ret = jvalue.get_##ResultType(); \ + return ret;\ +JNI_END + +// the runtime type of subword integral basic types is integer +DEFINE_CALLMETHOD(jboolean, Boolean, T_BOOLEAN + , HOTSPOT_JNI_CALLBOOLEANMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLBOOLEANMETHOD_RETURN(_ret_ref)) +DEFINE_CALLMETHOD(jbyte, Byte, T_BYTE + , HOTSPOT_JNI_CALLBYTEMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLBYTEMETHOD_RETURN(_ret_ref)) +DEFINE_CALLMETHOD(jchar, Char, T_CHAR + , HOTSPOT_JNI_CALLCHARMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLCHARMETHOD_RETURN(_ret_ref)) +DEFINE_CALLMETHOD(jshort, Short, T_SHORT + , HOTSPOT_JNI_CALLSHORTMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSHORTMETHOD_RETURN(_ret_ref)) + +DEFINE_CALLMETHOD(jobject, Object, T_OBJECT + , HOTSPOT_JNI_CALLOBJECTMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLOBJECTMETHOD_RETURN(_ret_ref)) +DEFINE_CALLMETHOD(jint, Int, T_INT, + HOTSPOT_JNI_CALLINTMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLINTMETHOD_RETURN(_ret_ref)) +DEFINE_CALLMETHOD(jlong, Long, T_LONG + , HOTSPOT_JNI_CALLLONGMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLLONGMETHOD_RETURN(_ret_ref)) +// Float and double probes don't return value because dtrace doesn't currently support it +DEFINE_CALLMETHOD(jfloat, Float, T_FLOAT + , HOTSPOT_JNI_CALLFLOATMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLFLOATMETHOD_RETURN()) +DEFINE_CALLMETHOD(jdouble, Double, T_DOUBLE + , HOTSPOT_JNI_CALLDOUBLEMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLDOUBLEMETHOD_RETURN()) + +#define DEFINE_CALLMETHODV(ResultType, Result, Tag \ + , EntryProbe, ReturnProbe) \ +\ + DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodV, ResultType \ + , ReturnProbe); \ +\ +JNI_ENTRY(ResultType, \ + jni_Call##Result##MethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)) \ + JNIWrapper("Call" XSTR(Result) "MethodV"); \ +\ + EntryProbe;\ + ResultType ret = 0;\ + DT_RETURN_MARK_FOR(Result, Call##Result##MethodV, ResultType, \ + (const ResultType&)ret);\ +\ + JavaValue jvalue(Tag); \ + JNI_ArgumentPusherVaArg ap(methodID, args); \ + jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \ + ret = jvalue.get_##ResultType(); \ + return ret;\ +JNI_END + +// the runtime type of subword integral basic types is integer +DEFINE_CALLMETHODV(jboolean, Boolean, T_BOOLEAN + , HOTSPOT_JNI_CALLBOOLEANMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLBOOLEANMETHOD_RETURN(_ret_ref)) +DEFINE_CALLMETHODV(jbyte, Byte, T_BYTE + , HOTSPOT_JNI_CALLBYTEMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLBYTEMETHOD_RETURN(_ret_ref)) +DEFINE_CALLMETHODV(jchar, Char, T_CHAR + , HOTSPOT_JNI_CALLCHARMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLCHARMETHOD_RETURN(_ret_ref)) +DEFINE_CALLMETHODV(jshort, Short, T_SHORT + , HOTSPOT_JNI_CALLSHORTMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSHORTMETHOD_RETURN(_ret_ref)) + +DEFINE_CALLMETHODV(jobject, Object, T_OBJECT + , HOTSPOT_JNI_CALLOBJECTMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLOBJECTMETHOD_RETURN(_ret_ref)) +DEFINE_CALLMETHODV(jint, Int, T_INT, + HOTSPOT_JNI_CALLINTMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLINTMETHOD_RETURN(_ret_ref)) +DEFINE_CALLMETHODV(jlong, Long, T_LONG + , HOTSPOT_JNI_CALLLONGMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLLONGMETHOD_RETURN(_ret_ref)) +// Float and double probes don't return value because dtrace doesn't currently support it +DEFINE_CALLMETHODV(jfloat, Float, T_FLOAT + , HOTSPOT_JNI_CALLFLOATMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLFLOATMETHOD_RETURN()) +DEFINE_CALLMETHODV(jdouble, Double, T_DOUBLE + , HOTSPOT_JNI_CALLDOUBLEMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLDOUBLEMETHOD_RETURN()) + +#define DEFINE_CALLMETHODA(ResultType, Result, Tag \ + , EntryProbe, ReturnProbe) \ +\ + DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodA, ResultType \ + , ReturnProbe); \ +\ +JNI_ENTRY(ResultType, \ + jni_Call##Result##MethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args)) \ + JNIWrapper("Call" XSTR(Result) "MethodA"); \ + EntryProbe; \ + ResultType ret = 0;\ + DT_RETURN_MARK_FOR(Result, Call##Result##MethodA, ResultType, \ + (const ResultType&)ret);\ +\ + JavaValue jvalue(Tag); \ + JNI_ArgumentPusherArray ap(methodID, args); \ + jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \ + ret = jvalue.get_##ResultType(); \ + return ret;\ +JNI_END + +// the runtime type of subword integral basic types is integer +DEFINE_CALLMETHODA(jboolean, Boolean, T_BOOLEAN + , HOTSPOT_JNI_CALLBOOLEANMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLBOOLEANMETHOD_RETURN(_ret_ref)) +DEFINE_CALLMETHODA(jbyte, Byte, T_BYTE + , HOTSPOT_JNI_CALLBYTEMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLBYTEMETHOD_RETURN(_ret_ref)) +DEFINE_CALLMETHODA(jchar, Char, T_CHAR + , HOTSPOT_JNI_CALLCHARMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLCHARMETHOD_RETURN(_ret_ref)) +DEFINE_CALLMETHODA(jshort, Short, T_SHORT + , HOTSPOT_JNI_CALLSHORTMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSHORTMETHOD_RETURN(_ret_ref)) + +DEFINE_CALLMETHODA(jobject, Object, T_OBJECT + , HOTSPOT_JNI_CALLOBJECTMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLOBJECTMETHOD_RETURN(_ret_ref)) +DEFINE_CALLMETHODA(jint, Int, T_INT, + HOTSPOT_JNI_CALLINTMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLINTMETHOD_RETURN(_ret_ref)) +DEFINE_CALLMETHODA(jlong, Long, T_LONG + , HOTSPOT_JNI_CALLLONGMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLLONGMETHOD_RETURN(_ret_ref)) +// Float and double probes don't return value because dtrace doesn't currently support it +DEFINE_CALLMETHODA(jfloat, Float, T_FLOAT + , HOTSPOT_JNI_CALLFLOATMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLFLOATMETHOD_RETURN()) +DEFINE_CALLMETHODA(jdouble, Double, T_DOUBLE + , HOTSPOT_JNI_CALLDOUBLEMETHOD_ENTRY(env, obj, (uintptr_t)methodID), + HOTSPOT_JNI_CALLDOUBLEMETHOD_RETURN()) + +DT_VOID_RETURN_MARK_DECL(CallVoidMethod, HOTSPOT_JNI_CALLVOIDMETHOD_RETURN()); +DT_VOID_RETURN_MARK_DECL(CallVoidMethodV, HOTSPOT_JNI_CALLVOIDMETHODV_RETURN()); +DT_VOID_RETURN_MARK_DECL(CallVoidMethodA, HOTSPOT_JNI_CALLVOIDMETHODA_RETURN()); + +#endif /* USDT2 */ + JNI_ENTRY(void, jni_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)) JNIWrapper("CallVoidMethod"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, CallVoidMethod__entry, env, obj, methodID); +#else /* USDT2 */ + HOTSPOT_JNI_CALLVOIDMETHOD_ENTRY( + env, obj, (uintptr_t) methodID); +#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallVoidMethod); va_list args; @@ -1426,7 +1940,12 @@ JNI_ENTRY(void, jni_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)) JNIWrapper("CallVoidMethodV"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, CallVoidMethodV__entry, env, obj, methodID); +#else /* USDT2 */ + HOTSPOT_JNI_CALLVOIDMETHODV_ENTRY( + env, obj, (uintptr_t) methodID); +#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallVoidMethodV); JavaValue jvalue(T_VOID); @@ -1437,7 +1956,12 @@ JNI_ENTRY(void, jni_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args)) JNIWrapper("CallVoidMethodA"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, CallVoidMethodA__entry, env, obj, methodID); +#else /* USDT2 */ + HOTSPOT_JNI_CALLVOIDMETHODA_ENTRY( + env, obj, (uintptr_t) methodID); +#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallVoidMethodA); JavaValue jvalue(T_VOID); @@ -1446,6 +1970,7 @@ JNI_END +#ifndef USDT2 #define DEFINE_CALLNONVIRTUALMETHOD(ResultType, Result, Tag) \ \ DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##Method, ResultType);\ @@ -1518,11 +2043,188 @@ DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodV); DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodA); +#else /* USDT2 */ + +#define DEFINE_CALLNONVIRTUALMETHOD(ResultType, Result, Tag \ + , EntryProbe, ReturnProbe) \ +\ + DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##Method, ResultType \ + , ReturnProbe);\ +\ +JNI_ENTRY(ResultType, \ + jni_CallNonvirtual##Result##Method(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...)) \ + JNIWrapper("CallNonvitual" XSTR(Result) "Method"); \ +\ + EntryProbe;\ + ResultType ret;\ + DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##Method, ResultType, \ + (const ResultType&)ret);\ +\ + va_list args; \ + va_start(args, methodID); \ + JavaValue jvalue(Tag); \ + JNI_ArgumentPusherVaArg ap(methodID, args); \ + jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \ + va_end(args); \ + ret = jvalue.get_##ResultType(); \ + return ret;\ +JNI_END + +// the runtime type of subword integral basic types is integer +DEFINE_CALLNONVIRTUALMETHOD(jboolean, Boolean, T_BOOLEAN + , HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHOD_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHOD(jbyte, Byte, T_BYTE + , HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHOD_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHOD(jchar, Char, T_CHAR + , HOTSPOT_JNI_CALLNONVIRTUALCHARMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALCHARMETHOD_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHOD(jshort, Short, T_SHORT + , HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHOD_RETURN(_ret_ref)) + +DEFINE_CALLNONVIRTUALMETHOD(jobject, Object, T_OBJECT + , HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHOD_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHOD(jint, Int, T_INT + , HOTSPOT_JNI_CALLNONVIRTUALINTMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALINTMETHOD_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHOD(jlong, Long, T_LONG + , HOTSPOT_JNI_CALLNONVIRTUALLONGMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), +// Float and double probes don't return value because dtrace doesn't currently support it + HOTSPOT_JNI_CALLNONVIRTUALLONGMETHOD_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHOD(jfloat, Float, T_FLOAT + , HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHOD_RETURN()) +DEFINE_CALLNONVIRTUALMETHOD(jdouble, Double, T_DOUBLE + , HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHOD_RETURN()) + +#define DEFINE_CALLNONVIRTUALMETHODV(ResultType, Result, Tag \ + , EntryProbe, ReturnProbe) \ +\ + DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodV, ResultType \ + , ReturnProbe);\ +\ +JNI_ENTRY(ResultType, \ + jni_CallNonvirtual##Result##MethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args)) \ + JNIWrapper("CallNonvitual" XSTR(Result) "MethodV"); \ +\ + EntryProbe;\ + ResultType ret;\ + DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodV, ResultType, \ + (const ResultType&)ret);\ +\ + JavaValue jvalue(Tag); \ + JNI_ArgumentPusherVaArg ap(methodID, args); \ + jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \ + ret = jvalue.get_##ResultType(); \ + return ret;\ +JNI_END + +// the runtime type of subword integral basic types is integer +DEFINE_CALLNONVIRTUALMETHODV(jboolean, Boolean, T_BOOLEAN + , HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODV_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHODV(jbyte, Byte, T_BYTE + , HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODV_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHODV(jchar, Char, T_CHAR + , HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODV_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHODV(jshort, Short, T_SHORT + , HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODV_RETURN(_ret_ref)) + +DEFINE_CALLNONVIRTUALMETHODV(jobject, Object, T_OBJECT + , HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODV_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHODV(jint, Int, T_INT + , HOTSPOT_JNI_CALLNONVIRTUALINTMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALINTMETHODV_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHODV(jlong, Long, T_LONG + , HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), +// Float and double probes don't return value because dtrace doesn't currently support it + HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODV_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHODV(jfloat, Float, T_FLOAT + , HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODV_RETURN()) +DEFINE_CALLNONVIRTUALMETHODV(jdouble, Double, T_DOUBLE + , HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODV_RETURN()) + +#define DEFINE_CALLNONVIRTUALMETHODA(ResultType, Result, Tag \ + , EntryProbe, ReturnProbe) \ +\ + DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodA, ResultType \ + , ReturnProbe);\ +\ +JNI_ENTRY(ResultType, \ + jni_CallNonvirtual##Result##MethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args)) \ + JNIWrapper("CallNonvitual" XSTR(Result) "MethodA"); \ +\ + EntryProbe;\ + ResultType ret;\ + DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodA, ResultType, \ + (const ResultType&)ret);\ +\ + JavaValue jvalue(Tag); \ + JNI_ArgumentPusherArray ap(methodID, args); \ + jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \ + ret = jvalue.get_##ResultType(); \ + return ret;\ +JNI_END + +// the runtime type of subword integral basic types is integer +DEFINE_CALLNONVIRTUALMETHODA(jboolean, Boolean, T_BOOLEAN + , HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODA_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHODA(jbyte, Byte, T_BYTE + , HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODA_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHODA(jchar, Char, T_CHAR + , HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODA_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHODA(jshort, Short, T_SHORT + , HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODA_RETURN(_ret_ref)) + +DEFINE_CALLNONVIRTUALMETHODA(jobject, Object, T_OBJECT + , HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODA_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHODA(jint, Int, T_INT + , HOTSPOT_JNI_CALLNONVIRTUALINTMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALINTMETHODA_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHODA(jlong, Long, T_LONG + , HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), +// Float and double probes don't return value because dtrace doesn't currently support it + HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODA_RETURN(_ret_ref)) +DEFINE_CALLNONVIRTUALMETHODA(jfloat, Float, T_FLOAT + , HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODA_RETURN()) +DEFINE_CALLNONVIRTUALMETHODA(jdouble, Double, T_DOUBLE + , HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODA_RETURN()) + +DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethod + , HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHOD_RETURN()); +DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodV + , HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODV_RETURN()); +DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodA + , HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODA_RETURN()); +#endif /* USDT2 */ + JNI_ENTRY(void, jni_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...)) JNIWrapper("CallNonvirtualVoidMethod"); +#ifndef USDT2 DTRACE_PROBE4(hotspot_jni, CallNonvirtualVoidMethod__entry, env, obj, cls, methodID); +#else /* USDT2 */ + HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHOD_ENTRY( + env, obj, cls, (uintptr_t) methodID); +#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallNonvirtualVoidMethod); va_list args; @@ -1537,8 +2239,13 @@ JNI_ENTRY(void, jni_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args)) JNIWrapper("CallNonvirtualVoidMethodV"); +#ifndef USDT2 DTRACE_PROBE4(hotspot_jni, CallNonvirtualVoidMethodV__entry, env, obj, cls, methodID); +#else /* USDT2 */ + HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODV_ENTRY( + env, obj, cls, (uintptr_t) methodID); +#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallNonvirtualVoidMethodV); JavaValue jvalue(T_VOID); @@ -1549,8 +2256,13 @@ JNI_ENTRY(void, jni_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args)) JNIWrapper("CallNonvirtualVoidMethodA"); +#ifndef USDT2 DTRACE_PROBE4(hotspot_jni, CallNonvirtualVoidMethodA__entry, env, obj, cls, methodID); +#else /* USDT2 */ + HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODA_ENTRY( + env, obj, cls, (uintptr_t) methodID); +#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallNonvirtualVoidMethodA); JavaValue jvalue(T_VOID); JNI_ArgumentPusherArray ap(methodID, args); @@ -1558,6 +2270,7 @@ JNI_END +#ifndef USDT2 #define DEFINE_CALLSTATICMETHOD(ResultType, Result, Tag) \ \ DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##Method, ResultType);\ @@ -1630,9 +2343,190 @@ DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodV); DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodA); +#else /* USDT2 */ + +#define DEFINE_CALLSTATICMETHOD(ResultType, Result, Tag \ + , EntryProbe, ResultProbe) \ +\ + DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##Method, ResultType \ + , ResultProbe); \ +\ +JNI_ENTRY(ResultType, \ + jni_CallStatic##Result##Method(JNIEnv *env, jclass cls, jmethodID methodID, ...)) \ + JNIWrapper("CallStatic" XSTR(Result) "Method"); \ +\ + EntryProbe; \ + ResultType ret = 0;\ + DT_RETURN_MARK_FOR(Result, CallStatic##Result##Method, ResultType, \ + (const ResultType&)ret);\ +\ + va_list args; \ + va_start(args, methodID); \ + JavaValue jvalue(Tag); \ + JNI_ArgumentPusherVaArg ap(methodID, args); \ + jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \ + va_end(args); \ + ret = jvalue.get_##ResultType(); \ + return ret;\ +JNI_END + +// the runtime type of subword integral basic types is integer +DEFINE_CALLSTATICMETHOD(jboolean, Boolean, T_BOOLEAN + , HOTSPOT_JNI_CALLSTATICBOOLEANMETHOD_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICBOOLEANMETHOD_RETURN(_ret_ref)); +DEFINE_CALLSTATICMETHOD(jbyte, Byte, T_BYTE + , HOTSPOT_JNI_CALLSTATICBYTEMETHOD_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICBYTEMETHOD_RETURN(_ret_ref)); +DEFINE_CALLSTATICMETHOD(jchar, Char, T_CHAR + , HOTSPOT_JNI_CALLSTATICCHARMETHOD_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICCHARMETHOD_RETURN(_ret_ref)); +DEFINE_CALLSTATICMETHOD(jshort, Short, T_SHORT + , HOTSPOT_JNI_CALLSTATICSHORTMETHOD_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICSHORTMETHOD_RETURN(_ret_ref)); + +DEFINE_CALLSTATICMETHOD(jobject, Object, T_OBJECT + , HOTSPOT_JNI_CALLSTATICOBJECTMETHOD_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICOBJECTMETHOD_RETURN(_ret_ref)); +DEFINE_CALLSTATICMETHOD(jint, Int, T_INT + , HOTSPOT_JNI_CALLSTATICINTMETHOD_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICINTMETHOD_RETURN(_ret_ref)); +DEFINE_CALLSTATICMETHOD(jlong, Long, T_LONG + , HOTSPOT_JNI_CALLSTATICLONGMETHOD_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICLONGMETHOD_RETURN(_ret_ref)); +// Float and double probes don't return value because dtrace doesn't currently support it +DEFINE_CALLSTATICMETHOD(jfloat, Float, T_FLOAT + , HOTSPOT_JNI_CALLSTATICFLOATMETHOD_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICFLOATMETHOD_RETURN()); +DEFINE_CALLSTATICMETHOD(jdouble, Double, T_DOUBLE + , HOTSPOT_JNI_CALLSTATICDOUBLEMETHOD_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICDOUBLEMETHOD_RETURN()); + +#define DEFINE_CALLSTATICMETHODV(ResultType, Result, Tag \ + , EntryProbe, ResultProbe) \ +\ + DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodV, ResultType \ + , ResultProbe); \ +\ +JNI_ENTRY(ResultType, \ + jni_CallStatic##Result##MethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args)) \ + JNIWrapper("CallStatic" XSTR(Result) "MethodV"); \ +\ + EntryProbe; \ + ResultType ret = 0;\ + DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodV, ResultType, \ + (const ResultType&)ret);\ +\ + JavaValue jvalue(Tag); \ + JNI_ArgumentPusherVaArg ap(methodID, args); \ + /* Make sure class is initialized before trying to invoke its method */ \ + KlassHandle k(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls))); \ + Klass::cast(k())->initialize(CHECK_0); \ + jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \ + va_end(args); \ + ret = jvalue.get_##ResultType(); \ + return ret;\ +JNI_END + +// the runtime type of subword integral basic types is integer +DEFINE_CALLSTATICMETHODV(jboolean, Boolean, T_BOOLEAN + , HOTSPOT_JNI_CALLSTATICBOOLEANMETHODV_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICBOOLEANMETHODV_RETURN(_ret_ref)); +DEFINE_CALLSTATICMETHODV(jbyte, Byte, T_BYTE + , HOTSPOT_JNI_CALLSTATICBYTEMETHODV_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICBYTEMETHODV_RETURN(_ret_ref)); +DEFINE_CALLSTATICMETHODV(jchar, Char, T_CHAR + , HOTSPOT_JNI_CALLSTATICCHARMETHODV_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICCHARMETHODV_RETURN(_ret_ref)); +DEFINE_CALLSTATICMETHODV(jshort, Short, T_SHORT + , HOTSPOT_JNI_CALLSTATICSHORTMETHODV_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICSHORTMETHODV_RETURN(_ret_ref)); + +DEFINE_CALLSTATICMETHODV(jobject, Object, T_OBJECT + , HOTSPOT_JNI_CALLSTATICOBJECTMETHODV_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICOBJECTMETHODV_RETURN(_ret_ref)); +DEFINE_CALLSTATICMETHODV(jint, Int, T_INT + , HOTSPOT_JNI_CALLSTATICINTMETHODV_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICINTMETHODV_RETURN(_ret_ref)); +DEFINE_CALLSTATICMETHODV(jlong, Long, T_LONG + , HOTSPOT_JNI_CALLSTATICLONGMETHODV_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICLONGMETHODV_RETURN(_ret_ref)); +// Float and double probes don't return value because dtrace doesn't currently support it +DEFINE_CALLSTATICMETHODV(jfloat, Float, T_FLOAT + , HOTSPOT_JNI_CALLSTATICFLOATMETHODV_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICFLOATMETHODV_RETURN()); +DEFINE_CALLSTATICMETHODV(jdouble, Double, T_DOUBLE + , HOTSPOT_JNI_CALLSTATICDOUBLEMETHODV_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICDOUBLEMETHODV_RETURN()); + +#define DEFINE_CALLSTATICMETHODA(ResultType, Result, Tag \ + , EntryProbe, ResultProbe) \ +\ + DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodA, ResultType \ + , ResultProbe); \ +\ +JNI_ENTRY(ResultType, \ + jni_CallStatic##Result##MethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args)) \ + JNIWrapper("CallStatic" XSTR(Result) "MethodA"); \ +\ + EntryProbe; \ + ResultType ret = 0;\ + DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodA, ResultType, \ + (const ResultType&)ret);\ +\ + JavaValue jvalue(Tag); \ + JNI_ArgumentPusherArray ap(methodID, args); \ + jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \ + ret = jvalue.get_##ResultType(); \ + return ret;\ +JNI_END + +// the runtime type of subword integral basic types is integer +DEFINE_CALLSTATICMETHODA(jboolean, Boolean, T_BOOLEAN + , HOTSPOT_JNI_CALLSTATICBOOLEANMETHODA_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICBOOLEANMETHODA_RETURN(_ret_ref)); +DEFINE_CALLSTATICMETHODA(jbyte, Byte, T_BYTE + , HOTSPOT_JNI_CALLSTATICBYTEMETHODA_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICBYTEMETHODA_RETURN(_ret_ref)); +DEFINE_CALLSTATICMETHODA(jchar, Char, T_CHAR + , HOTSPOT_JNI_CALLSTATICCHARMETHODA_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICCHARMETHODA_RETURN(_ret_ref)); +DEFINE_CALLSTATICMETHODA(jshort, Short, T_SHORT + , HOTSPOT_JNI_CALLSTATICSHORTMETHODA_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICSHORTMETHODA_RETURN(_ret_ref)); + +DEFINE_CALLSTATICMETHODA(jobject, Object, T_OBJECT + , HOTSPOT_JNI_CALLSTATICOBJECTMETHODA_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICOBJECTMETHODA_RETURN(_ret_ref)); +DEFINE_CALLSTATICMETHODA(jint, Int, T_INT + , HOTSPOT_JNI_CALLSTATICINTMETHODA_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICINTMETHODA_RETURN(_ret_ref)); +DEFINE_CALLSTATICMETHODA(jlong, Long, T_LONG + , HOTSPOT_JNI_CALLSTATICLONGMETHODA_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICLONGMETHODA_RETURN(_ret_ref)); +// Float and double probes don't return value because dtrace doesn't currently support it +DEFINE_CALLSTATICMETHODA(jfloat, Float, T_FLOAT + , HOTSPOT_JNI_CALLSTATICFLOATMETHODA_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICFLOATMETHODA_RETURN()); +DEFINE_CALLSTATICMETHODA(jdouble, Double, T_DOUBLE + , HOTSPOT_JNI_CALLSTATICDOUBLEMETHODA_ENTRY(env, cls, (uintptr_t)methodID), + HOTSPOT_JNI_CALLSTATICDOUBLEMETHODA_RETURN()); + +DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethod + , HOTSPOT_JNI_CALLSTATICVOIDMETHOD_RETURN()); +DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodV + , HOTSPOT_JNI_CALLSTATICVOIDMETHODV_RETURN()); +DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodA + , HOTSPOT_JNI_CALLSTATICVOIDMETHODA_RETURN()); +#endif /* USDT2 */ + JNI_ENTRY(void, jni_CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...)) JNIWrapper("CallStaticVoidMethod"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, CallStaticVoidMethod__entry, env, cls, methodID); +#else /* USDT2 */ + HOTSPOT_JNI_CALLSTATICVOIDMETHOD_ENTRY( + env, cls, (uintptr_t) methodID); +#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallStaticVoidMethod); va_list args; @@ -1646,7 +2540,12 @@ JNI_ENTRY(void, jni_CallStaticVoidMethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args)) JNIWrapper("CallStaticVoidMethodV"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, CallStaticVoidMethodV__entry, env, cls, methodID); +#else /* USDT2 */ + HOTSPOT_JNI_CALLSTATICVOIDMETHODV_ENTRY( + env, cls, (uintptr_t) methodID); +#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallStaticVoidMethodV); JavaValue jvalue(T_VOID); @@ -1657,7 +2556,12 @@ JNI_ENTRY(void, jni_CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args)) JNIWrapper("CallStaticVoidMethodA"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, CallStaticVoidMethodA__entry, env, cls, methodID); +#else /* USDT2 */ + HOTSPOT_JNI_CALLSTATICVOIDMETHODA_ENTRY( + env, cls, (uintptr_t) methodID); +#endif /* USDT2 */ DT_VOID_RETURN_MARK(CallStaticVoidMethodA); JavaValue jvalue(T_VOID); @@ -1671,12 +2575,22 @@ // +#ifndef USDT2 DT_RETURN_MARK_DECL(GetFieldID, jfieldID); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(GetFieldID, jfieldID + , HOTSPOT_JNI_GETFIELDID_RETURN((uintptr_t)_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jfieldID, jni_GetFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig)) JNIWrapper("GetFieldID"); +#ifndef USDT2 DTRACE_PROBE4(hotspot_jni, GetFieldID__entry, env, clazz, name, sig); +#else /* USDT2 */ + HOTSPOT_JNI_GETFIELDID_ENTRY( + env, clazz, (char *) name, (char *) sig); +#endif /* USDT2 */ jfieldID ret = 0; DT_RETURN_MARK(GetFieldID, jfieldID, (const jfieldID&)ret); @@ -1708,7 +2622,12 @@ JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)) JNIWrapper("GetObjectField"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, GetObjectField__entry, env, obj, fieldID); +#else /* USDT2 */ + HOTSPOT_JNI_GETOBJECTFIELD_ENTRY( + env, obj, (uintptr_t) fieldID); +#endif /* USDT2 */ oop o = JNIHandles::resolve_non_null(obj); klassOop k = o->klass(); int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); @@ -1738,11 +2657,17 @@ } } #endif // SERIALGC +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetObjectField__return, ret); +#else /* USDT2 */ +HOTSPOT_JNI_GETOBJECTFIELD_RETURN( + ret); +#endif /* USDT2 */ return ret; JNI_END +#ifndef USDT2 #define DEFINE_GETFIELD(Return,Fieldname,Result) \ \ DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return);\ @@ -1776,6 +2701,61 @@ DEFINE_GETFIELD(jfloat, float, Float) DEFINE_GETFIELD(jdouble, double, Double) +#else /* USDT2 */ + +#define DEFINE_GETFIELD(Return,Fieldname,Result \ + , EntryProbe, ReturnProbe) \ +\ + DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \ + , ReturnProbe); \ +\ +JNI_QUICK_ENTRY(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \ + JNIWrapper("Get" XSTR(Result) "Field"); \ +\ + EntryProbe; \ + Return ret = 0;\ + DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\ +\ + oop o = JNIHandles::resolve_non_null(obj); \ + klassOop k = o->klass(); \ + int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \ + /* Keep JVMTI addition small and only check enabled flag here. */ \ + /* jni_GetField_probe_nh() assumes that is not okay to create handles */ \ + /* and creates a ResetNoHandleMark. */ \ + if (JvmtiExport::should_post_field_access()) { \ + o = JvmtiExport::jni_GetField_probe_nh(thread, obj, o, k, fieldID, false); \ + } \ + ret = o->Fieldname##_field(offset); \ + return ret; \ +JNI_END + +DEFINE_GETFIELD(jboolean, bool, Boolean + , HOTSPOT_JNI_GETBOOLEANFIELD_ENTRY(env, obj, (uintptr_t)fieldID), + HOTSPOT_JNI_GETBOOLEANFIELD_RETURN(_ret_ref)) +DEFINE_GETFIELD(jbyte, byte, Byte + , HOTSPOT_JNI_GETBYTEFIELD_ENTRY(env, obj, (uintptr_t)fieldID), + HOTSPOT_JNI_GETBYTEFIELD_RETURN(_ret_ref)) +DEFINE_GETFIELD(jchar, char, Char + , HOTSPOT_JNI_GETCHARFIELD_ENTRY(env, obj, (uintptr_t)fieldID), + HOTSPOT_JNI_GETCHARFIELD_RETURN(_ret_ref)) +DEFINE_GETFIELD(jshort, short, Short + , HOTSPOT_JNI_GETSHORTFIELD_ENTRY(env, obj, (uintptr_t)fieldID), + HOTSPOT_JNI_GETSHORTFIELD_RETURN(_ret_ref)) +DEFINE_GETFIELD(jint, int, Int + , HOTSPOT_JNI_GETINTFIELD_ENTRY(env, obj, (uintptr_t)fieldID), + HOTSPOT_JNI_GETINTFIELD_RETURN(_ret_ref)) +DEFINE_GETFIELD(jlong, long, Long + , HOTSPOT_JNI_GETLONGFIELD_ENTRY(env, obj, (uintptr_t)fieldID), + HOTSPOT_JNI_GETLONGFIELD_RETURN(_ret_ref)) +// Float and double probes don't return value because dtrace doesn't currently support it +DEFINE_GETFIELD(jfloat, float, Float + , HOTSPOT_JNI_GETFLOATFIELD_ENTRY(env, obj, (uintptr_t)fieldID), + HOTSPOT_JNI_GETFLOATFIELD_RETURN()) +DEFINE_GETFIELD(jdouble, double, Double + , HOTSPOT_JNI_GETDOUBLEFIELD_ENTRY(env, obj, (uintptr_t)fieldID), + HOTSPOT_JNI_GETDOUBLEFIELD_RETURN()) +#endif /* USDT2 */ + address jni_GetBooleanField_addr() { return (address)jni_GetBooleanField; } @@ -1803,7 +2783,12 @@ JNI_QUICK_ENTRY(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value)) JNIWrapper("SetObjectField"); +#ifndef USDT2 DTRACE_PROBE4(hotspot_jni, SetObjectField__entry, env, obj, fieldID, value); +#else /* USDT2 */ + HOTSPOT_JNI_SETOBJECTFIELD_ENTRY( + env, obj, (uintptr_t) fieldID, value); +#endif /* USDT2 */ oop o = JNIHandles::resolve_non_null(obj); klassOop k = o->klass(); int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); @@ -1816,9 +2801,15 @@ o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, 'L', (jvalue *)&field_value); } o->obj_field_put(offset, JNIHandles::resolve(value)); +#ifndef USDT2 DTRACE_PROBE(hotspot_jni, SetObjectField__return); +#else /* USDT2 */ + HOTSPOT_JNI_SETOBJECTFIELD_RETURN( +); +#endif /* USDT2 */ JNI_END +#ifndef USDT2 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType) \ \ JNI_QUICK_ENTRY(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \ @@ -1853,12 +2844,74 @@ DEFINE_SETFIELD(jfloat, float, Float, 'F', f) DEFINE_SETFIELD(jdouble, double, Double, 'D', d) +#else /* USDT2 */ + +#define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \ + , EntryProbe, ReturnProbe) \ +\ +JNI_QUICK_ENTRY(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \ + JNIWrapper("Set" XSTR(Result) "Field"); \ +\ + EntryProbe; \ +\ + oop o = JNIHandles::resolve_non_null(obj); \ + klassOop k = o->klass(); \ + int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \ + /* Keep JVMTI addition small and only check enabled flag here. */ \ + /* jni_SetField_probe_nh() assumes that is not okay to create handles */ \ + /* and creates a ResetNoHandleMark. */ \ + if (JvmtiExport::should_post_field_modification()) { \ + jvalue field_value; \ + field_value.unionType = value; \ + o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \ + } \ + o->Fieldname##_field_put(offset, value); \ + ReturnProbe; \ +JNI_END + +DEFINE_SETFIELD(jboolean, bool, Boolean, 'Z', z + , HOTSPOT_JNI_SETBOOLEANFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value), + HOTSPOT_JNI_SETBOOLEANFIELD_RETURN()) +DEFINE_SETFIELD(jbyte, byte, Byte, 'B', b + , HOTSPOT_JNI_SETBYTEFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value), + HOTSPOT_JNI_SETBYTEFIELD_RETURN()) +DEFINE_SETFIELD(jchar, char, Char, 'C', c + , HOTSPOT_JNI_SETCHARFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value), + HOTSPOT_JNI_SETCHARFIELD_RETURN()) +DEFINE_SETFIELD(jshort, short, Short, 'S', s + , HOTSPOT_JNI_SETSHORTFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value), + HOTSPOT_JNI_SETSHORTFIELD_RETURN()) +DEFINE_SETFIELD(jint, int, Int, 'I', i + , HOTSPOT_JNI_SETINTFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value), + HOTSPOT_JNI_SETINTFIELD_RETURN()) +DEFINE_SETFIELD(jlong, long, Long, 'J', j + , HOTSPOT_JNI_SETLONGFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value), + HOTSPOT_JNI_SETLONGFIELD_RETURN()) +// Float and double probes don't return value because dtrace doesn't currently support it +DEFINE_SETFIELD(jfloat, float, Float, 'F', f + , HOTSPOT_JNI_SETFLOATFIELD_ENTRY(env, obj, (uintptr_t)fieldID), + HOTSPOT_JNI_SETFLOATFIELD_RETURN()) +DEFINE_SETFIELD(jdouble, double, Double, 'D', d + , HOTSPOT_JNI_SETDOUBLEFIELD_ENTRY(env, obj, (uintptr_t)fieldID), + HOTSPOT_JNI_SETDOUBLEFIELD_RETURN()) +#endif /* USDT2 */ + +#ifndef USDT2 DT_RETURN_MARK_DECL(ToReflectedField, jobject); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(ToReflectedField, jobject + , HOTSPOT_JNI_TOREFLECTEDFIELD_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jobject, jni_ToReflectedField(JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic)) JNIWrapper("ToReflectedField"); +#ifndef USDT2 DTRACE_PROBE4(hotspot_jni, ToReflectedField__entry, env, cls, fieldID, isStatic); +#else /* USDT2 */ + HOTSPOT_JNI_TOREFLECTEDFIELD_ENTRY( + env, cls, (uintptr_t) fieldID, isStatic); +#endif /* USDT2 */ jobject ret = NULL; DT_RETURN_MARK(ToReflectedField, jobject, (const jobject&)ret); @@ -1888,12 +2941,22 @@ // // Accessing Static Fields // +#ifndef USDT2 DT_RETURN_MARK_DECL(GetStaticFieldID, jfieldID); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(GetStaticFieldID, jfieldID + , HOTSPOT_JNI_GETSTATICFIELDID_RETURN((uintptr_t)_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jfieldID, jni_GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig)) JNIWrapper("GetStaticFieldID"); +#ifndef USDT2 DTRACE_PROBE4(hotspot_jni, GetStaticFieldID__entry, env, clazz, name, sig); +#else /* USDT2 */ + HOTSPOT_JNI_GETSTATICFIELDID_ENTRY( + env, clazz, (char *) name, (char *) sig); +#endif /* USDT2 */ jfieldID ret = NULL; DT_RETURN_MARK(GetStaticFieldID, jfieldID, (const jfieldID&)ret); @@ -1929,7 +2992,12 @@ JNI_ENTRY(jobject, jni_GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID)) JNIWrapper("GetStaticObjectField"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, GetStaticObjectField__entry, env, clazz, fieldID); +#else /* USDT2 */ + HOTSPOT_JNI_GETSTATICOBJECTFIELD_ENTRY( + env, clazz, (uintptr_t) fieldID); +#endif /* USDT2 */ #ifndef JNICHECK_KERNEL DEBUG_ONLY(klassOop param_k = jniCheck::validate_class(thread, clazz);) #endif // JNICHECK_KERNEL @@ -1941,10 +3009,16 @@ JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true); } jobject ret = JNIHandles::make_local(id->holder()->java_mirror()->obj_field(id->offset())); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetStaticObjectField__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_GETSTATICOBJECTFIELD_RETURN( + ret); +#endif /* USDT2 */ return ret; JNI_END +#ifndef USDT2 #define DEFINE_GETSTATICFIELD(Return,Fieldname,Result) \ \ DT_RETURN_MARK_DECL_FOR(Result, GetStatic##Result##Field, Return);\ @@ -1975,10 +3049,58 @@ DEFINE_GETSTATICFIELD(jfloat, float, Float) DEFINE_GETSTATICFIELD(jdouble, double, Double) +#else /* USDT2 */ + +#define DEFINE_GETSTATICFIELD(Return,Fieldname,Result \ + , EntryProbe, ReturnProbe) \ +\ + DT_RETURN_MARK_DECL_FOR(Result, GetStatic##Result##Field, Return \ + , ReturnProbe); \ +\ +JNI_ENTRY(Return, jni_GetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID)) \ + JNIWrapper("GetStatic" XSTR(Result) "Field"); \ + EntryProbe; \ + Return ret = 0;\ + DT_RETURN_MARK_FOR(Result, GetStatic##Result##Field, Return, \ + (const Return&)ret);\ + JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \ + assert(id->is_static_field_id(), "invalid static field id"); \ + /* Keep JVMTI addition small and only check enabled flag here. */ \ + /* jni_GetField_probe() assumes that is okay to create handles. */ \ + if (JvmtiExport::should_post_field_access()) { \ + JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true); \ + } \ + ret = id->holder()->java_mirror()-> Fieldname##_field (id->offset()); \ + return ret;\ +JNI_END + +DEFINE_GETSTATICFIELD(jboolean, bool, Boolean + , HOTSPOT_JNI_GETSTATICBOOLEANFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICBOOLEANFIELD_RETURN(_ret_ref)) +DEFINE_GETSTATICFIELD(jbyte, byte, Byte + , HOTSPOT_JNI_GETSTATICBYTEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICBYTEFIELD_RETURN(_ret_ref) ) +DEFINE_GETSTATICFIELD(jchar, char, Char + , HOTSPOT_JNI_GETSTATICCHARFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICCHARFIELD_RETURN(_ret_ref) ) +DEFINE_GETSTATICFIELD(jshort, short, Short + , HOTSPOT_JNI_GETSTATICSHORTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICSHORTFIELD_RETURN(_ret_ref) ) +DEFINE_GETSTATICFIELD(jint, int, Int + , HOTSPOT_JNI_GETSTATICINTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICINTFIELD_RETURN(_ret_ref) ) +DEFINE_GETSTATICFIELD(jlong, long, Long + , HOTSPOT_JNI_GETSTATICLONGFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICLONGFIELD_RETURN(_ret_ref) ) +// Float and double probes don't return value because dtrace doesn't currently support it +DEFINE_GETSTATICFIELD(jfloat, float, Float + , HOTSPOT_JNI_GETSTATICFLOATFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICFLOATFIELD_RETURN() ) +DEFINE_GETSTATICFIELD(jdouble, double, Double + , HOTSPOT_JNI_GETSTATICDOUBLEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICDOUBLEFIELD_RETURN() ) +#endif /* USDT2 */ JNI_ENTRY(void, jni_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value)) JNIWrapper("SetStaticObjectField"); +#ifndef USDT2 DTRACE_PROBE4(hotspot_jni, SetStaticObjectField__entry, env, clazz, fieldID, value); +#else /* USDT2 */ + HOTSPOT_JNI_SETSTATICOBJECTFIELD_ENTRY( + env, clazz, (uintptr_t) fieldID, value); +#endif /* USDT2 */ JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); assert(id->is_static_field_id(), "invalid static field id"); // Keep JVMTI addition small and only check enabled flag here. @@ -1989,10 +3111,16 @@ JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, 'L', (jvalue *)&field_value); } id->holder()->java_mirror()->obj_field_put(id->offset(), JNIHandles::resolve(value)); +#ifndef USDT2 DTRACE_PROBE(hotspot_jni, SetStaticObjectField__return); +#else /* USDT2 */ + HOTSPOT_JNI_SETSTATICOBJECTFIELD_RETURN( + ); +#endif /* USDT2 */ JNI_END +#ifndef USDT2 #define DEFINE_SETSTATICFIELD(Argument,Fieldname,Result,SigType,unionType) \ \ JNI_ENTRY(void, jni_SetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID, Argument value)) \ @@ -2024,6 +3152,54 @@ DEFINE_SETSTATICFIELD(jfloat, float, Float, 'F', f) DEFINE_SETSTATICFIELD(jdouble, double, Double, 'D', d) +#else /* USDT2 */ + +#define DEFINE_SETSTATICFIELD(Argument,Fieldname,Result,SigType,unionType \ + , EntryProbe, ReturnProbe) \ +\ +JNI_ENTRY(void, jni_SetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID, Argument value)) \ + JNIWrapper("SetStatic" XSTR(Result) "Field"); \ + EntryProbe; \ +\ + JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \ + assert(id->is_static_field_id(), "invalid static field id"); \ + /* Keep JVMTI addition small and only check enabled flag here. */ \ + /* jni_SetField_probe() assumes that is okay to create handles. */ \ + if (JvmtiExport::should_post_field_modification()) { \ + jvalue field_value; \ + field_value.unionType = value; \ + JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \ + } \ + id->holder()->java_mirror()-> Fieldname##_field_put (id->offset(), value); \ + ReturnProbe;\ +JNI_END + +DEFINE_SETSTATICFIELD(jboolean, bool, Boolean, 'Z', z + , HOTSPOT_JNI_SETBOOLEANFIELD_ENTRY(env, clazz, (uintptr_t)fieldID, value), + HOTSPOT_JNI_SETBOOLEANFIELD_RETURN()) +DEFINE_SETSTATICFIELD(jbyte, byte, Byte, 'B', b + , HOTSPOT_JNI_SETSTATICBYTEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value), + HOTSPOT_JNI_SETSTATICBYTEFIELD_RETURN()) +DEFINE_SETSTATICFIELD(jchar, char, Char, 'C', c + , HOTSPOT_JNI_SETSTATICCHARFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value), + HOTSPOT_JNI_SETSTATICCHARFIELD_RETURN()) +DEFINE_SETSTATICFIELD(jshort, short, Short, 'S', s + , HOTSPOT_JNI_SETSTATICSHORTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value), + HOTSPOT_JNI_SETSTATICSHORTFIELD_RETURN()) +DEFINE_SETSTATICFIELD(jint, int, Int, 'I', i + , HOTSPOT_JNI_SETSTATICINTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value), + HOTSPOT_JNI_SETSTATICINTFIELD_RETURN()) +DEFINE_SETSTATICFIELD(jlong, long, Long, 'J', j + , HOTSPOT_JNI_SETSTATICLONGFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value), + HOTSPOT_JNI_SETSTATICLONGFIELD_RETURN()) +// Float and double probes don't return value because dtrace doesn't currently support it +DEFINE_SETSTATICFIELD(jfloat, float, Float, 'F', f + , HOTSPOT_JNI_SETSTATICFLOATFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), + HOTSPOT_JNI_SETSTATICFLOATFIELD_RETURN()) +DEFINE_SETSTATICFIELD(jdouble, double, Double, 'D', d + , HOTSPOT_JNI_SETSTATICDOUBLEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), + HOTSPOT_JNI_SETSTATICDOUBLEFIELD_RETURN()) +#endif /* USDT2 */ // // String Operations @@ -2031,11 +3207,21 @@ // Unicode Interface +#ifndef USDT2 DT_RETURN_MARK_DECL(NewString, jstring); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(NewString, jstring + , HOTSPOT_JNI_NEWSTRING_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jstring, jni_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len)) JNIWrapper("NewString"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, NewString__entry, env, unicodeChars, len); +#else /* USDT2 */ + HOTSPOT_JNI_NEWSTRING_ENTRY( + env, (uint16_t *) unicodeChars, len); +#endif /* USDT2 */ jstring ret = NULL; DT_RETURN_MARK(NewString, jstring, (const jstring&)ret); oop string=java_lang_String::create_oop_from_unicode((jchar*) unicodeChars, len, CHECK_NULL); @@ -2046,9 +3232,19 @@ JNI_QUICK_ENTRY(jsize, jni_GetStringLength(JNIEnv *env, jstring string)) JNIWrapper("GetStringLength"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, GetStringLength__entry, env, string); +#else /* USDT2 */ + HOTSPOT_JNI_GETSTRINGLENGTH_ENTRY( + env, string); +#endif /* USDT2 */ jsize ret = java_lang_String::length(JNIHandles::resolve_non_null(string)); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetStringLength__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_GETSTRINGLENGTH_RETURN( + ret); +#endif /* USDT2 */ return ret; JNI_END @@ -2056,7 +3252,12 @@ JNI_QUICK_ENTRY(const jchar*, jni_GetStringChars( JNIEnv *env, jstring string, jboolean *isCopy)) JNIWrapper("GetStringChars"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, GetStringChars__entry, env, string, isCopy); +#else /* USDT2 */ + HOTSPOT_JNI_GETSTRINGCHARS_ENTRY( + env, string, (uintptr_t *) isCopy); +#endif /* USDT2 */ //%note jni_5 if (isCopy != NULL) { *isCopy = JNI_TRUE; @@ -2070,31 +3271,56 @@ memcpy(buf, s_value->char_at_addr(s_offset), sizeof(jchar)*s_len); } buf[s_len] = 0; +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetStringChars__return, buf); +#else /* USDT2 */ + HOTSPOT_JNI_GETSTRINGCHARS_RETURN( + buf); +#endif /* USDT2 */ return buf; JNI_END JNI_QUICK_ENTRY(void, jni_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)) JNIWrapper("ReleaseStringChars"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, ReleaseStringChars__entry, env, str, chars); +#else /* USDT2 */ + HOTSPOT_JNI_RELEASESTRINGCHARS_ENTRY( + env, str, (uint16_t *) chars); +#endif /* USDT2 */ //%note jni_6 if (chars != NULL) { // Since String objects are supposed to be immutable, don't copy any // new data back. A bad user will have to go after the char array. FreeHeap((void*) chars); } +#ifndef USDT2 DTRACE_PROBE(hotspot_jni, ReleaseStringChars__return); +#else /* USDT2 */ + HOTSPOT_JNI_RELEASESTRINGCHARS_RETURN( +); +#endif /* USDT2 */ JNI_END // UTF Interface +#ifndef USDT2 DT_RETURN_MARK_DECL(NewStringUTF, jstring); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(NewStringUTF, jstring + , HOTSPOT_JNI_NEWSTRINGUTF_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jstring, jni_NewStringUTF(JNIEnv *env, const char *bytes)) JNIWrapper("NewStringUTF"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, NewStringUTF__entry, env, bytes); +#else /* USDT2 */ + HOTSPOT_JNI_NEWSTRINGUTF_ENTRY( + env, (char *) bytes); +#endif /* USDT2 */ jstring ret; DT_RETURN_MARK(NewStringUTF, jstring, (const jstring&)ret); @@ -2106,43 +3332,83 @@ JNI_ENTRY(jsize, jni_GetStringUTFLength(JNIEnv *env, jstring string)) JNIWrapper("GetStringUTFLength"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, GetStringUTFLength__entry, env, string); +#else /* USDT2 */ + HOTSPOT_JNI_GETSTRINGUTFLENGTH_ENTRY( + env, string); +#endif /* USDT2 */ jsize ret = java_lang_String::utf8_length(JNIHandles::resolve_non_null(string)); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetStringUTFLength__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_GETSTRINGUTFLENGTH_RETURN( + ret); +#endif /* USDT2 */ return ret; JNI_END JNI_ENTRY(const char*, jni_GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy)) JNIWrapper("GetStringUTFChars"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, GetStringUTFChars__entry, env, string, isCopy); +#else /* USDT2 */ + HOTSPOT_JNI_GETSTRINGUTFCHARS_ENTRY( + env, string, (uintptr_t *) isCopy); +#endif /* USDT2 */ oop java_string = JNIHandles::resolve_non_null(string); size_t length = java_lang_String::utf8_length(java_string); char* result = AllocateHeap(length + 1, "GetStringUTFChars"); java_lang_String::as_utf8_string(java_string, result, (int) length + 1); if (isCopy != NULL) *isCopy = JNI_TRUE; +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetStringUTFChars__return, result); +#else /* USDT2 */ + HOTSPOT_JNI_GETSTRINGUTFCHARS_RETURN( + result); +#endif /* USDT2 */ return result; JNI_END JNI_LEAF(void, jni_ReleaseStringUTFChars(JNIEnv *env, jstring str, const char *chars)) JNIWrapper("ReleaseStringUTFChars"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, ReleaseStringUTFChars__entry, env, str, chars); +#else /* USDT2 */ + HOTSPOT_JNI_RELEASESTRINGUTFCHARS_ENTRY( + env, str, (char *) chars); +#endif /* USDT2 */ if (chars != NULL) { FreeHeap((char*) chars); } +#ifndef USDT2 DTRACE_PROBE(hotspot_jni, ReleaseStringUTFChars__return); +#else /* USDT2 */ +HOTSPOT_JNI_RELEASESTRINGUTFCHARS_RETURN( +); +#endif /* USDT2 */ JNI_END JNI_QUICK_ENTRY(jsize, jni_GetArrayLength(JNIEnv *env, jarray array)) JNIWrapper("GetArrayLength"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, GetArrayLength__entry, env, array); +#else /* USDT2 */ + HOTSPOT_JNI_GETARRAYLENGTH_ENTRY( + env, array); +#endif /* USDT2 */ arrayOop a = arrayOop(JNIHandles::resolve_non_null(array)); assert(a->is_array(), "must be array"); jsize ret = a->length(); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetArrayLength__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_GETARRAYLENGTH_RETURN( + ret); +#endif /* USDT2 */ return ret; JNI_END @@ -2151,11 +3417,21 @@ // Object Array Operations // +#ifndef USDT2 DT_RETURN_MARK_DECL(NewObjectArray, jobjectArray); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(NewObjectArray, jobjectArray + , HOTSPOT_JNI_NEWOBJECTARRAY_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jobjectArray, jni_NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement)) JNIWrapper("NewObjectArray"); +#ifndef USDT2 DTRACE_PROBE4(hotspot_jni, NewObjectArray__entry, env, length, elementClass, initialElement); +#else /* USDT2 */ + HOTSPOT_JNI_NEWOBJECTARRAY_ENTRY( + env, length, elementClass, initialElement); +#endif /* USDT2 */ jobjectArray ret = NULL; DT_RETURN_MARK(NewObjectArray, jobjectArray, (const jobjectArray&)ret); KlassHandle ek(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(elementClass))); @@ -2173,11 +3449,21 @@ return ret; JNI_END +#ifndef USDT2 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject + , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index)) JNIWrapper("GetObjectArrayElement"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, GetObjectArrayElement__entry, env, array, index); +#else /* USDT2 */ + HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY( + env, array, index); +#endif /* USDT2 */ jobject ret = NULL; DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret); objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array)); @@ -2191,11 +3477,21 @@ } JNI_END +#ifndef USDT2 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement); +#else /* USDT2 */ +DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement + , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN()); +#endif /* USDT2 */ JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value)) JNIWrapper("SetObjectArrayElement"); +#ifndef USDT2 DTRACE_PROBE4(hotspot_jni, SetObjectArrayElement__entry, env, array, index, value); +#else /* USDT2 */ + HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY( + env, array, index, value); +#endif /* USDT2 */ DT_VOID_RETURN_MARK(SetObjectArrayElement); objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array)); @@ -2214,9 +3510,10 @@ JNI_END +#ifndef USDT2 #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result) \ \ - DT_RETURN_MARK_DECL(New##Result##Array, Return);\ + DT_RETURN_MARK_DECL(New##Result##Array, Return); \ \ JNI_ENTRY(Return, \ jni_New##Result##Array(JNIEnv *env, jsize len)) \ @@ -2239,6 +3536,51 @@ DEFINE_NEWSCALARARRAY(jfloatArray, new_singleArray, Float) DEFINE_NEWSCALARARRAY(jdoubleArray, new_doubleArray, Double) +#else /* USDT2 */ + +#define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \ + ,EntryProbe,ReturnProbe) \ +\ + DT_RETURN_MARK_DECL(New##Result##Array, Return \ + , ReturnProbe); \ +\ +JNI_ENTRY(Return, \ + jni_New##Result##Array(JNIEnv *env, jsize len)) \ + JNIWrapper("New" XSTR(Result) "Array"); \ + EntryProbe; \ + Return ret = NULL;\ + DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\ +\ + oop obj= oopFactory::Allocator(len, CHECK_0); \ + ret = (Return) JNIHandles::make_local(env, obj); \ + return ret;\ +JNI_END + +DEFINE_NEWSCALARARRAY(jbooleanArray, new_boolArray, Boolean, + HOTSPOT_JNI_NEWBOOLEANARRAY_ENTRY(env, len), + HOTSPOT_JNI_NEWBOOLEANARRAY_RETURN(_ret_ref)) +DEFINE_NEWSCALARARRAY(jbyteArray, new_byteArray, Byte, + HOTSPOT_JNI_NEWBYTEARRAY_ENTRY(env, len), + HOTSPOT_JNI_NEWBYTEARRAY_RETURN(_ret_ref)) +DEFINE_NEWSCALARARRAY(jshortArray, new_shortArray, Short, + HOTSPOT_JNI_NEWSHORTARRAY_ENTRY(env, len), + HOTSPOT_JNI_NEWSHORTARRAY_RETURN(_ret_ref)) +DEFINE_NEWSCALARARRAY(jcharArray, new_charArray, Char, + HOTSPOT_JNI_NEWCHARARRAY_ENTRY(env, len), + HOTSPOT_JNI_NEWCHARARRAY_RETURN(_ret_ref)) +DEFINE_NEWSCALARARRAY(jintArray, new_intArray, Int, + HOTSPOT_JNI_NEWINTARRAY_ENTRY(env, len), + HOTSPOT_JNI_NEWINTARRAY_RETURN(_ret_ref)) +DEFINE_NEWSCALARARRAY(jlongArray, new_longArray, Long, + HOTSPOT_JNI_NEWLONGARRAY_ENTRY(env, len), + HOTSPOT_JNI_NEWLONGARRAY_RETURN(_ret_ref)) +DEFINE_NEWSCALARARRAY(jfloatArray, new_singleArray, Float, + HOTSPOT_JNI_NEWFLOATARRAY_ENTRY(env, len), + HOTSPOT_JNI_NEWFLOATARRAY_RETURN(_ret_ref)) +DEFINE_NEWSCALARARRAY(jdoubleArray, new_doubleArray, Double, + HOTSPOT_JNI_NEWDOUBLEARRAY_ENTRY(env, len), + HOTSPOT_JNI_NEWDOUBLEARRAY_RETURN(_ret_ref)) +#endif /* USDT2 */ // Return an address which will fault if the caller writes to it. @@ -2256,6 +3598,7 @@ } +#ifndef USDT2 #define DEFINE_GETSCALARARRAYELEMENTS(ElementTag,ElementType,Result, Tag) \ \ JNI_QUICK_ENTRY(ElementType*, \ @@ -2290,7 +3633,62 @@ DEFINE_GETSCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float) DEFINE_GETSCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double) - +#else /* USDT2 */ + +#define DEFINE_GETSCALARARRAYELEMENTS(ElementTag,ElementType,Result, Tag \ + , EntryProbe, ReturnProbe) \ +\ +JNI_QUICK_ENTRY(ElementType*, \ + jni_Get##Result##ArrayElements(JNIEnv *env, ElementType##Array array, jboolean *isCopy)) \ + JNIWrapper("Get" XSTR(Result) "ArrayElements"); \ + EntryProbe; \ + /* allocate an chunk of memory in c land */ \ + typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \ + ElementType* result; \ + int len = a->length(); \ + if (len == 0) { \ + /* Empty array: legal but useless, can't return NULL. \ + * Return a pointer to something useless. \ + * Avoid asserts in typeArrayOop. */ \ + result = (ElementType*)get_bad_address(); \ + } else { \ + result = NEW_C_HEAP_ARRAY(ElementType, len); \ + /* copy the array to the c chunk */ \ + memcpy(result, a->Tag##_at_addr(0), sizeof(ElementType)*len); \ + } \ + if (isCopy) *isCopy = JNI_TRUE; \ + ReturnProbe; \ + return result; \ +JNI_END + +DEFINE_GETSCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool + , HOTSPOT_JNI_GETBOOLEANARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy), + HOTSPOT_JNI_GETBOOLEANARRAYELEMENTS_RETURN((uintptr_t*)result)) +DEFINE_GETSCALARARRAYELEMENTS(T_BYTE, jbyte, Byte, byte + , HOTSPOT_JNI_GETBYTEARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy), + HOTSPOT_JNI_GETBYTEARRAYELEMENTS_RETURN((char*)result)) +DEFINE_GETSCALARARRAYELEMENTS(T_SHORT, jshort, Short, short + , HOTSPOT_JNI_GETSHORTARRAYELEMENTS_ENTRY(env, (uint16_t*) array, (uintptr_t *) isCopy), + HOTSPOT_JNI_GETSHORTARRAYELEMENTS_RETURN((uint16_t*)result)) +DEFINE_GETSCALARARRAYELEMENTS(T_CHAR, jchar, Char, char + , HOTSPOT_JNI_GETCHARARRAYELEMENTS_ENTRY(env, (uint16_t*) array, (uintptr_t *) isCopy), + HOTSPOT_JNI_GETCHARARRAYELEMENTS_RETURN(result)) +DEFINE_GETSCALARARRAYELEMENTS(T_INT, jint, Int, int + , HOTSPOT_JNI_GETINTARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy), + HOTSPOT_JNI_GETINTARRAYELEMENTS_RETURN((uint32_t*)result)) +DEFINE_GETSCALARARRAYELEMENTS(T_LONG, jlong, Long, long + , HOTSPOT_JNI_GETLONGARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy), + HOTSPOT_JNI_GETLONGARRAYELEMENTS_RETURN(((uintptr_t*)result))) +// Float and double probes don't return value because dtrace doesn't currently support it +DEFINE_GETSCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float + , HOTSPOT_JNI_GETFLOATARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy), + HOTSPOT_JNI_GETFLOATARRAYELEMENTS_RETURN(result)) +DEFINE_GETSCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double + , HOTSPOT_JNI_GETDOUBLEARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy), + HOTSPOT_JNI_GETDOUBLEARRAYELEMENTS_RETURN(result)) +#endif /* USDT2 */ + +#ifndef USDT2 #define DEFINE_RELEASESCALARARRAYELEMENTS(ElementTag,ElementType,Result,Tag) \ \ JNI_QUICK_ENTRY(void, \ @@ -2320,6 +3718,56 @@ DEFINE_RELEASESCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float) DEFINE_RELEASESCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double) +#else /* USDT2 */ + +#define DEFINE_RELEASESCALARARRAYELEMENTS(ElementTag,ElementType,Result,Tag \ + , EntryProbe, ReturnProbe);\ +\ +JNI_QUICK_ENTRY(void, \ + jni_Release##Result##ArrayElements(JNIEnv *env, ElementType##Array array, \ + ElementType *buf, jint mode)) \ + JNIWrapper("Release" XSTR(Result) "ArrayElements"); \ + EntryProbe; \ + typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \ + int len = a->length(); \ + if (len != 0) { /* Empty array: nothing to free or copy. */ \ + if ((mode == 0) || (mode == JNI_COMMIT)) { \ + memcpy(a->Tag##_at_addr(0), buf, sizeof(ElementType)*len); \ + } \ + if ((mode == 0) || (mode == JNI_ABORT)) { \ + FreeHeap(buf); \ + } \ + } \ + ReturnProbe; \ +JNI_END + +DEFINE_RELEASESCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool + , HOTSPOT_JNI_RELEASEBOOLEANARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) buf, mode), + HOTSPOT_JNI_RELEASEBOOLEANARRAYELEMENTS_RETURN()) +DEFINE_RELEASESCALARARRAYELEMENTS(T_BYTE, jbyte, Byte, byte + , HOTSPOT_JNI_RELEASEBYTEARRAYELEMENTS_ENTRY(env, array, (char *) buf, mode), + HOTSPOT_JNI_RELEASEBYTEARRAYELEMENTS_RETURN()) +DEFINE_RELEASESCALARARRAYELEMENTS(T_SHORT, jshort, Short, short + , HOTSPOT_JNI_RELEASESHORTARRAYELEMENTS_ENTRY(env, array, (uint16_t *) buf, mode), + HOTSPOT_JNI_RELEASESHORTARRAYELEMENTS_RETURN()) +DEFINE_RELEASESCALARARRAYELEMENTS(T_CHAR, jchar, Char, char + , HOTSPOT_JNI_RELEASECHARARRAYELEMENTS_ENTRY(env, array, (uint16_t *) buf, mode), + HOTSPOT_JNI_RELEASECHARARRAYELEMENTS_RETURN()) +DEFINE_RELEASESCALARARRAYELEMENTS(T_INT, jint, Int, int + , HOTSPOT_JNI_RELEASEINTARRAYELEMENTS_ENTRY(env, array, (uint32_t *) buf, mode), + HOTSPOT_JNI_RELEASEINTARRAYELEMENTS_RETURN()) +DEFINE_RELEASESCALARARRAYELEMENTS(T_LONG, jlong, Long, long + , HOTSPOT_JNI_RELEASELONGARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) buf, mode), + HOTSPOT_JNI_RELEASELONGARRAYELEMENTS_RETURN()) +DEFINE_RELEASESCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float + , HOTSPOT_JNI_RELEASEFLOATARRAYELEMENTS_ENTRY(env, array, (float *) buf, mode), + HOTSPOT_JNI_RELEASEFLOATARRAYELEMENTS_RETURN()) +DEFINE_RELEASESCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double + , HOTSPOT_JNI_RELEASEDOUBLEARRAYELEMENTS_ENTRY(env, array, (double *) buf, mode), + HOTSPOT_JNI_RELEASEDOUBLEARRAYELEMENTS_RETURN()) +#endif /* USDT2 */ + +#ifndef USDT2 #define DEFINE_GETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag) \ DT_VOID_RETURN_MARK_DECL(Get##Result##ArrayRegion);\ \ @@ -2351,6 +3799,59 @@ DEFINE_GETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float) DEFINE_GETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double) +#else /* USDT2 */ + +#define DEFINE_GETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag \ + , EntryProbe, ReturnProbe); \ + DT_VOID_RETURN_MARK_DECL(Get##Result##ArrayRegion \ + , ReturnProbe); \ +\ +JNI_ENTRY(void, \ +jni_Get##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \ + jsize len, ElementType *buf)) \ + JNIWrapper("Get" XSTR(Result) "ArrayRegion"); \ + EntryProbe; \ + DT_VOID_RETURN_MARK(Get##Result##ArrayRegion); \ + typeArrayOop src = typeArrayOop(JNIHandles::resolve_non_null(array)); \ + if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)src->length())) { \ + THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \ + } else { \ + if (len > 0) { \ + int sc = typeArrayKlass::cast(src->klass())->log2_element_size(); \ + memcpy((u_char*) buf, \ + (u_char*) src->Tag##_at_addr(start), \ + len << sc); \ + } \ + } \ +JNI_END + +DEFINE_GETSCALARARRAYREGION(T_BOOLEAN, jboolean,Boolean, bool + , HOTSPOT_JNI_GETBOOLEANARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *) buf), + HOTSPOT_JNI_GETBOOLEANARRAYREGION_RETURN()); +DEFINE_GETSCALARARRAYREGION(T_BYTE, jbyte, Byte, byte + , HOTSPOT_JNI_GETBYTEARRAYREGION_ENTRY(env, array, start, len, (char *) buf), + HOTSPOT_JNI_GETBYTEARRAYREGION_RETURN()); +DEFINE_GETSCALARARRAYREGION(T_SHORT, jshort, Short, short + , HOTSPOT_JNI_GETSHORTARRAYREGION_ENTRY(env, array, start, len, (uint16_t *) buf), + HOTSPOT_JNI_GETSHORTARRAYREGION_RETURN()); +DEFINE_GETSCALARARRAYREGION(T_CHAR, jchar, Char, char + , HOTSPOT_JNI_GETCHARARRAYREGION_ENTRY(env, array, start, len, (uint16_t*) buf), + HOTSPOT_JNI_GETCHARARRAYREGION_RETURN()); +DEFINE_GETSCALARARRAYREGION(T_INT, jint, Int, int + , HOTSPOT_JNI_GETINTARRAYREGION_ENTRY(env, array, start, len, (uint32_t*) buf), + HOTSPOT_JNI_GETINTARRAYREGION_RETURN()); +DEFINE_GETSCALARARRAYREGION(T_LONG, jlong, Long, long + , HOTSPOT_JNI_GETLONGARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *) buf), + HOTSPOT_JNI_GETLONGARRAYREGION_RETURN()); +DEFINE_GETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float + , HOTSPOT_JNI_GETFLOATARRAYREGION_ENTRY(env, array, start, len, (float *) buf), + HOTSPOT_JNI_GETFLOATARRAYREGION_RETURN()); +DEFINE_GETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double + , HOTSPOT_JNI_GETDOUBLEARRAYREGION_ENTRY(env, array, start, len, (double *) buf), + HOTSPOT_JNI_GETDOUBLEARRAYREGION_RETURN()); +#endif /* USDT2 */ + +#ifndef USDT2 #define DEFINE_SETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag) \ DT_VOID_RETURN_MARK_DECL(Set##Result##ArrayRegion);\ \ @@ -2382,6 +3883,58 @@ DEFINE_SETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float) DEFINE_SETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double) +#else /* USDT2 */ + +#define DEFINE_SETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag \ + , EntryProbe, ReturnProbe); \ + DT_VOID_RETURN_MARK_DECL(Set##Result##ArrayRegion \ + ,ReturnProbe); \ +\ +JNI_ENTRY(void, \ +jni_Set##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \ + jsize len, const ElementType *buf)) \ + JNIWrapper("Set" XSTR(Result) "ArrayRegion"); \ + EntryProbe; \ + DT_VOID_RETURN_MARK(Set##Result##ArrayRegion); \ + typeArrayOop dst = typeArrayOop(JNIHandles::resolve_non_null(array)); \ + if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)dst->length())) { \ + THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \ + } else { \ + if (len > 0) { \ + int sc = typeArrayKlass::cast(dst->klass())->log2_element_size(); \ + memcpy((u_char*) dst->Tag##_at_addr(start), \ + (u_char*) buf, \ + len << sc); \ + } \ + } \ +JNI_END + +DEFINE_SETSCALARARRAYREGION(T_BOOLEAN, jboolean, Boolean, bool + , HOTSPOT_JNI_SETBOOLEANARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *)buf), + HOTSPOT_JNI_SETBOOLEANARRAYREGION_RETURN()) +DEFINE_SETSCALARARRAYREGION(T_BYTE, jbyte, Byte, byte + , HOTSPOT_JNI_SETBYTEARRAYREGION_ENTRY(env, array, start, len, (char *) buf), + HOTSPOT_JNI_SETBYTEARRAYREGION_RETURN()) +DEFINE_SETSCALARARRAYREGION(T_SHORT, jshort, Short, short + , HOTSPOT_JNI_SETSHORTARRAYREGION_ENTRY(env, array, start, len, (uint16_t *) buf), + HOTSPOT_JNI_SETSHORTARRAYREGION_RETURN()) +DEFINE_SETSCALARARRAYREGION(T_CHAR, jchar, Char, char + , HOTSPOT_JNI_SETCHARARRAYREGION_ENTRY(env, array, start, len, (uint16_t *) buf), + HOTSPOT_JNI_SETCHARARRAYREGION_RETURN()) +DEFINE_SETSCALARARRAYREGION(T_INT, jint, Int, int + , HOTSPOT_JNI_SETINTARRAYREGION_ENTRY(env, array, start, len, (uint32_t *) buf), + HOTSPOT_JNI_SETINTARRAYREGION_RETURN()) +DEFINE_SETSCALARARRAYREGION(T_LONG, jlong, Long, long + , HOTSPOT_JNI_SETLONGARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *) buf), + HOTSPOT_JNI_SETLONGARRAYREGION_RETURN()) +DEFINE_SETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float + , HOTSPOT_JNI_SETFLOATARRAYREGION_ENTRY(env, array, start, len, (float *) buf), + HOTSPOT_JNI_SETFLOATARRAYREGION_RETURN()) +DEFINE_SETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double + , HOTSPOT_JNI_SETDOUBLEARRAYREGION_ENTRY(env, array, start, len, (double *) buf), + HOTSPOT_JNI_SETDOUBLEARRAYREGION_RETURN()) +#endif /* USDT2 */ + // // Interception of natives @@ -2463,13 +4016,23 @@ return true; } +#ifndef USDT2 DT_RETURN_MARK_DECL(RegisterNatives, jint); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(RegisterNatives, jint + , HOTSPOT_JNI_REGISTERNATIVES_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jint, jni_RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint nMethods)) JNIWrapper("RegisterNatives"); +#ifndef USDT2 DTRACE_PROBE4(hotspot_jni, RegisterNatives__entry, env, clazz, methods, nMethods); +#else /* USDT2 */ + HOTSPOT_JNI_REGISTERNATIVES_ENTRY( + env, clazz, (void *) methods, nMethods); +#endif /* USDT2 */ jint ret = 0; DT_RETURN_MARK(RegisterNatives, jint, (const jint&)ret); @@ -2507,7 +4070,12 @@ JNI_ENTRY(jint, jni_UnregisterNatives(JNIEnv *env, jclass clazz)) JNIWrapper("UnregisterNatives"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, UnregisterNatives__entry, env, clazz); +#else /* USDT2 */ + HOTSPOT_JNI_UNREGISTERNATIVES_ENTRY( + env, clazz); +#endif /* USDT2 */ klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz)); //%note jni_2 if (Klass::cast(k)->oop_is_instance()) { @@ -2519,7 +4087,12 @@ } } } +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, UnregisterNatives__return, 0); +#else /* USDT2 */ + HOTSPOT_JNI_UNREGISTERNATIVES_RETURN( + 0); +#endif /* USDT2 */ return 0; JNI_END @@ -2527,10 +4100,20 @@ // Monitor functions // +#ifndef USDT2 DT_RETURN_MARK_DECL(MonitorEnter, jint); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(MonitorEnter, jint + , HOTSPOT_JNI_MONITORENTER_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jint, jni_MonitorEnter(JNIEnv *env, jobject jobj)) +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, MonitorEnter__entry, env, jobj); +#else /* USDT2 */ + HOTSPOT_JNI_MONITORENTER_ENTRY( + env, jobj); +#endif /* USDT2 */ jint ret = JNI_ERR; DT_RETURN_MARK(MonitorEnter, jint, (const jint&)ret); @@ -2545,10 +4128,20 @@ return ret; JNI_END +#ifndef USDT2 DT_RETURN_MARK_DECL(MonitorExit, jint); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(MonitorExit, jint + , HOTSPOT_JNI_MONITOREXIT_RETURN(_ret_ref)); +#endif /* USDT2 */ JNI_ENTRY(jint, jni_MonitorExit(JNIEnv *env, jobject jobj)) +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, MonitorExit__entry, env, jobj); +#else /* USDT2 */ + HOTSPOT_JNI_MONITOREXIT_ENTRY( + env, jobj); +#endif /* USDT2 */ jint ret = JNI_ERR; DT_RETURN_MARK(MonitorExit, jint, (const jint&)ret); @@ -2568,11 +4161,21 @@ // Extensions // +#ifndef USDT2 DT_VOID_RETURN_MARK_DECL(GetStringRegion); +#else /* USDT2 */ +DT_VOID_RETURN_MARK_DECL(GetStringRegion + , HOTSPOT_JNI_GETSTRINGREGION_RETURN()); +#endif /* USDT2 */ JNI_ENTRY(void, jni_GetStringRegion(JNIEnv *env, jstring string, jsize start, jsize len, jchar *buf)) JNIWrapper("GetStringRegion"); +#ifndef USDT2 DTRACE_PROBE5(hotspot_jni, GetStringRegion__entry, env, string, start, len, buf); +#else /* USDT2 */ + HOTSPOT_JNI_GETSTRINGREGION_ENTRY( + env, string, start, len, buf); +#endif /* USDT2 */ DT_VOID_RETURN_MARK(GetStringRegion); oop s = JNIHandles::resolve_non_null(string); int s_len = java_lang_String::length(s); @@ -2587,11 +4190,21 @@ } JNI_END +#ifndef USDT2 DT_VOID_RETURN_MARK_DECL(GetStringUTFRegion); +#else /* USDT2 */ +DT_VOID_RETURN_MARK_DECL(GetStringUTFRegion + , HOTSPOT_JNI_GETSTRINGUTFREGION_RETURN()); +#endif /* USDT2 */ JNI_ENTRY(void, jni_GetStringUTFRegion(JNIEnv *env, jstring string, jsize start, jsize len, char *buf)) JNIWrapper("GetStringUTFRegion"); +#ifndef USDT2 DTRACE_PROBE5(hotspot_jni, GetStringUTFRegion__entry, env, string, start, len, buf); +#else /* USDT2 */ + HOTSPOT_JNI_GETSTRINGUTFREGION_ENTRY( + env, string, start, len, buf); +#endif /* USDT2 */ DT_VOID_RETURN_MARK(GetStringUTFRegion); oop s = JNIHandles::resolve_non_null(string); int s_len = java_lang_String::length(s); @@ -2617,7 +4230,12 @@ JNI_ENTRY(void*, jni_GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy)) JNIWrapper("GetPrimitiveArrayCritical"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, GetPrimitiveArrayCritical__entry, env, array, isCopy); +#else /* USDT2 */ + HOTSPOT_JNI_GETPRIMITIVEARRAYCRITICAL_ENTRY( + env, array, (uintptr_t *) isCopy); +#endif /* USDT2 */ GC_locker::lock_critical(thread); if (isCopy != NULL) { *isCopy = JNI_FALSE; @@ -2631,23 +4249,43 @@ type = typeArrayKlass::cast(a->klass())->element_type(); } void* ret = arrayOop(a)->base(type); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetPrimitiveArrayCritical__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_GETPRIMITIVEARRAYCRITICAL_RETURN( + ret); +#endif /* USDT2 */ return ret; JNI_END JNI_ENTRY(void, jni_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode)) JNIWrapper("ReleasePrimitiveArrayCritical"); +#ifndef USDT2 DTRACE_PROBE4(hotspot_jni, ReleasePrimitiveArrayCritical__entry, env, array, carray, mode); +#else /* USDT2 */ + HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_ENTRY( + env, array, carray, mode); +#endif /* USDT2 */ // The array, carray and mode arguments are ignored GC_locker::unlock_critical(thread); +#ifndef USDT2 DTRACE_PROBE(hotspot_jni, ReleasePrimitiveArrayCritical__return); +#else /* USDT2 */ +HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_RETURN( +); +#endif /* USDT2 */ JNI_END JNI_ENTRY(const jchar*, jni_GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy)) JNIWrapper("GetStringCritical"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, GetStringCritical__entry, env, string, isCopy); +#else /* USDT2 */ + HOTSPOT_JNI_GETSTRINGCRITICAL_ENTRY( + env, string, (uintptr_t *) isCopy); +#endif /* USDT2 */ GC_locker::lock_critical(thread); if (isCopy != NULL) { *isCopy = JNI_FALSE; @@ -2662,44 +4300,89 @@ } else { ret = (jchar*) s_value->base(T_CHAR); } +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetStringCritical__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_GETSTRINGCRITICAL_RETURN( + (uint16_t *) ret); +#endif /* USDT2 */ return ret; JNI_END JNI_ENTRY(void, jni_ReleaseStringCritical(JNIEnv *env, jstring str, const jchar *chars)) JNIWrapper("ReleaseStringCritical"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, ReleaseStringCritical__entry, env, str, chars); +#else /* USDT2 */ + HOTSPOT_JNI_RELEASESTRINGCRITICAL_ENTRY( + env, str, (uint16_t *) chars); +#endif /* USDT2 */ // The str and chars arguments are ignored GC_locker::unlock_critical(thread); +#ifndef USDT2 DTRACE_PROBE(hotspot_jni, ReleaseStringCritical__return); +#else /* USDT2 */ +HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN( +); +#endif /* USDT2 */ JNI_END JNI_ENTRY(jweak, jni_NewWeakGlobalRef(JNIEnv *env, jobject ref)) JNIWrapper("jni_NewWeakGlobalRef"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, NewWeakGlobalRef__entry, env, ref); +#else /* USDT2 */ + HOTSPOT_JNI_NEWWEAKGLOBALREF_ENTRY( + env, ref); +#endif /* USDT2 */ Handle ref_handle(thread, JNIHandles::resolve(ref)); jweak ret = JNIHandles::make_weak_global(ref_handle); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, NewWeakGlobalRef__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_NEWWEAKGLOBALREF_RETURN( + ret); +#endif /* USDT2 */ return ret; JNI_END // Must be JNI_ENTRY (with HandleMark) JNI_ENTRY(void, jni_DeleteWeakGlobalRef(JNIEnv *env, jweak ref)) JNIWrapper("jni_DeleteWeakGlobalRef"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, DeleteWeakGlobalRef__entry, env, ref); +#else /* USDT2 */ + HOTSPOT_JNI_DELETEWEAKGLOBALREF_ENTRY( + env, ref); +#endif /* USDT2 */ JNIHandles::destroy_weak_global(ref); +#ifndef USDT2 DTRACE_PROBE(hotspot_jni, DeleteWeakGlobalRef__return); +#else /* USDT2 */ + HOTSPOT_JNI_DELETEWEAKGLOBALREF_RETURN( + ); +#endif /* USDT2 */ JNI_END JNI_QUICK_ENTRY(jboolean, jni_ExceptionCheck(JNIEnv *env)) JNIWrapper("jni_ExceptionCheck"); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, ExceptionCheck__entry, env); +#else /* USDT2 */ + HOTSPOT_JNI_EXCEPTIONCHECK_ENTRY( + env); +#endif /* USDT2 */ jni_check_async_exceptions(thread); jboolean ret = (thread->has_pending_exception()) ? JNI_TRUE : JNI_FALSE; +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, ExceptionCheck__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_EXCEPTIONCHECK_RETURN( + ret); +#endif /* USDT2 */ return ret; JNI_END @@ -2791,11 +4474,21 @@ JavaThread* thread = JavaThread::thread_from_jni_environment(env); JNIWrapper("jni_NewDirectByteBuffer"); +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, NewDirectByteBuffer__entry, env, address, capacity); +#else /* USDT2 */ + HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_ENTRY( + env, address, capacity); +#endif /* USDT2 */ if (!directBufferSupportInitializeEnded) { if (!initializeDirectBufferSupport(env, thread)) { +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, NewDirectByteBuffer__return, NULL); +#else /* USDT2 */ + HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_RETURN( + NULL); +#endif /* USDT2 */ return NULL; } } @@ -2806,11 +4499,21 @@ // takes int capacity jint cap = (jint) capacity; jobject ret = env->NewObject(directByteBufferClass, directByteBufferConstructor, addr, cap); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, NewDirectByteBuffer__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_RETURN( + ret); +#endif /* USDT2 */ return ret; } +#ifndef USDT2 DT_RETURN_MARK_DECL(GetDirectBufferAddress, void*); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(GetDirectBufferAddress, void* + , HOTSPOT_JNI_GETDIRECTBUFFERADDRESS_RETURN((void*) _ret_ref)); +#endif /* USDT2 */ extern "C" void* JNICALL jni_GetDirectBufferAddress(JNIEnv *env, jobject buf) { @@ -2818,7 +4521,12 @@ JavaThread* thread = JavaThread::thread_from_jni_environment(env); JNIWrapper("jni_GetDirectBufferAddress"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, GetDirectBufferAddress__entry, env, buf); +#else /* USDT2 */ + HOTSPOT_JNI_GETDIRECTBUFFERADDRESS_ENTRY( + env, buf); +#endif /* USDT2 */ void* ret = NULL; DT_RETURN_MARK(GetDirectBufferAddress, void*, (const void*&)ret); @@ -2836,7 +4544,12 @@ return ret; } +#ifndef USDT2 DT_RETURN_MARK_DECL(GetDirectBufferCapacity, jlong); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(GetDirectBufferCapacity, jlong + , HOTSPOT_JNI_GETDIRECTBUFFERCAPACITY_RETURN(_ret_ref)); +#endif /* USDT2 */ extern "C" jlong JNICALL jni_GetDirectBufferCapacity(JNIEnv *env, jobject buf) { @@ -2844,7 +4557,12 @@ JavaThread* thread = JavaThread::thread_from_jni_environment(env); JNIWrapper("jni_GetDirectBufferCapacity"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, GetDirectBufferCapacity__entry, env, buf); +#else /* USDT2 */ + HOTSPOT_JNI_GETDIRECTBUFFERCAPACITY_ENTRY( + env, buf); +#endif /* USDT2 */ jlong ret = -1; DT_RETURN_MARK(GetDirectBufferCapacity, jlong, (const jlong&)ret); @@ -2871,8 +4589,18 @@ JNI_LEAF(jint, jni_GetVersion(JNIEnv *env)) JNIWrapper("GetVersion"); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetVersion__entry, env); +#else /* USDT2 */ + HOTSPOT_JNI_GETVERSION_ENTRY( + env); +#endif /* USDT2 */ +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetVersion__return, CurrentVersion); +#else /* USDT2 */ + HOTSPOT_JNI_GETVERSION_RETURN( + CurrentVersion); +#endif /* USDT2 */ return CurrentVersion; JNI_END @@ -2880,9 +4608,19 @@ JNI_LEAF(jint, jni_GetJavaVM(JNIEnv *env, JavaVM **vm)) JNIWrapper("jni_GetJavaVM"); +#ifndef USDT2 DTRACE_PROBE2(hotspot_jni, GetJavaVM__entry, env, vm); +#else /* USDT2 */ + HOTSPOT_JNI_GETJAVAVM_ENTRY( + env, (void **) vm); +#endif /* USDT2 */ *vm = (JavaVM *)(&main_vm); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetJavaVM__return, JNI_OK); +#else /* USDT2 */ + HOTSPOT_JNI_GETJAVAVM_RETURN( + JNI_OK); +#endif /* USDT2 */ return JNI_OK; JNI_END @@ -3262,11 +5000,21 @@ #define JAVASTACKSIZE (400 * 1024) /* Default size of a thread java stack */ enum { VERIFY_NONE, VERIFY_REMOTE, VERIFY_ALL }; +#ifndef USDT2 HS_DTRACE_PROBE_DECL1(hotspot_jni, GetDefaultJavaVMInitArgs__entry, void*); DT_RETURN_MARK_DECL(GetDefaultJavaVMInitArgs, jint); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(GetDefaultJavaVMInitArgs, jint + , HOTSPOT_JNI_GETDEFAULTJAVAVMINITARGS_RETURN(_ret_ref)); +#endif /* USDT2 */ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) { +#ifndef USDT2 HS_DTRACE_PROBE1(hotspot_jni, GetDefaultJavaVMInitArgs__entry, args_); +#else /* USDT2 */ + HOTSPOT_JNI_GETDEFAULTJAVAVMINITARGS_ENTRY( + args_); +#endif /* USDT2 */ JDK1_1InitArgs *args = (JDK1_1InitArgs *)args_; jint ret = JNI_ERR; DT_RETURN_MARK(GetDefaultJavaVMInitArgs, jint, (const jint&)ret); @@ -3300,11 +5048,21 @@ #endif +#ifndef USDT2 HS_DTRACE_PROBE_DECL3(hotspot_jni, CreateJavaVM__entry, vm, penv, args); DT_RETURN_MARK_DECL(CreateJavaVM, jint); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(CreateJavaVM, jint + , HOTSPOT_JNI_CREATEJAVAVM_RETURN(_ret_ref)); +#endif /* USDT2 */ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args) { +#ifndef USDT2 HS_DTRACE_PROBE3(hotspot_jni, CreateJavaVM__entry, vm, penv, args); +#else /* USDT2 */ + HOTSPOT_JNI_CREATEJAVAVM_ENTRY( + (void **) vm, penv, args); +#endif /* USDT2 */ jint result = JNI_ERR; DT_RETURN_MARK(CreateJavaVM, jint, (const jint&)result); @@ -3394,31 +5152,53 @@ return result; } +#ifndef USDT2 HS_DTRACE_PROBE_DECL3(hotspot_jni, GetCreatedJavaVMs__entry, \ JavaVM**, jsize, jsize*); HS_DTRACE_PROBE_DECL1(hotspot_jni, GetCreatedJavaVMs__return, jint); +#endif /* !USDT2 */ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetCreatedJavaVMs(JavaVM **vm_buf, jsize bufLen, jsize *numVMs) { // See bug 4367188, the wrapper can sometimes cause VM crashes // JNIWrapper("GetCreatedJavaVMs"); +#ifndef USDT2 HS_DTRACE_PROBE3(hotspot_jni, GetCreatedJavaVMs__entry, \ vm_buf, bufLen, numVMs); +#else /* USDT2 */ + HOTSPOT_JNI_GETCREATEDJAVAVMS_ENTRY( + (void **) vm_buf, bufLen, (uintptr_t *) numVMs); +#endif /* USDT2 */ if (vm_created) { if (numVMs != NULL) *numVMs = 1; if (bufLen > 0) *vm_buf = (JavaVM *)(&main_vm); } else { if (numVMs != NULL) *numVMs = 0; } +#ifndef USDT2 HS_DTRACE_PROBE1(hotspot_jni, GetCreatedJavaVMs__return, JNI_OK); +#else /* USDT2 */ + HOTSPOT_JNI_GETCREATEDJAVAVMS_RETURN( + JNI_OK); +#endif /* USDT2 */ return JNI_OK; } extern "C" { +#ifndef USDT2 DT_RETURN_MARK_DECL(DestroyJavaVM, jint); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(DestroyJavaVM, jint + , HOTSPOT_JNI_DESTROYJAVAVM_RETURN(_ret_ref)); +#endif /* USDT2 */ jint JNICALL jni_DestroyJavaVM(JavaVM *vm) { +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, DestroyJavaVM__entry, vm); +#else /* USDT2 */ + HOTSPOT_JNI_DESTROYJAVAVM_ENTRY( + vm); +#endif /* USDT2 */ jint res = JNI_ERR; DT_RETURN_MARK(DestroyJavaVM, jint, (const jint&)res); @@ -3536,7 +5316,7 @@ // mark the thread as no longer attaching // this uses a fence to push the change through so we don't have // to regrab the threads_lock - thread->set_attached(); + thread->set_done_attaching_via_jni(); // Set java thread status. java_lang_Thread::set_thread_status(thread->threadObj(), @@ -3564,34 +5344,64 @@ jint JNICALL jni_AttachCurrentThread(JavaVM *vm, void **penv, void *_args) { +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, AttachCurrentThread__entry, vm, penv, _args); +#else /* USDT2 */ + HOTSPOT_JNI_ATTACHCURRENTTHREAD_ENTRY( + vm, penv, _args); +#endif /* USDT2 */ if (!vm_created) { +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, AttachCurrentThread__return, JNI_ERR); +#else /* USDT2 */ + HOTSPOT_JNI_ATTACHCURRENTTHREAD_RETURN( + (uint32_t) JNI_ERR); +#endif /* USDT2 */ return JNI_ERR; } JNIWrapper("AttachCurrentThread"); jint ret = attach_current_thread(vm, penv, _args, false); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, AttachCurrentThread__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_ATTACHCURRENTTHREAD_RETURN( + ret); +#endif /* USDT2 */ return ret; } jint JNICALL jni_DetachCurrentThread(JavaVM *vm) { +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__entry, vm); +#else /* USDT2 */ + HOTSPOT_JNI_DETACHCURRENTTHREAD_ENTRY( + vm); +#endif /* USDT2 */ VM_Exit::block_if_vm_exited(); JNIWrapper("DetachCurrentThread"); // If the thread has been deattacted the operations is a no-op if (ThreadLocalStorage::thread() == NULL) { +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__return, JNI_OK); +#else /* USDT2 */ + HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN( + JNI_OK); +#endif /* USDT2 */ return JNI_OK; } JavaThread* thread = JavaThread::current(); if (thread->has_last_Java_frame()) { +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__return, JNI_ERR); +#else /* USDT2 */ + HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN( + (uint32_t) JNI_ERR); +#endif /* USDT2 */ // Can't detach a thread that's running java, that can't work. return JNI_ERR; } @@ -3612,14 +5422,29 @@ thread->exit(false, JavaThread::jni_detach); delete thread; +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__return, JNI_OK); +#else /* USDT2 */ + HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN( + JNI_OK); +#endif /* USDT2 */ return JNI_OK; } +#ifndef USDT2 DT_RETURN_MARK_DECL(GetEnv, jint); +#else /* USDT2 */ +DT_RETURN_MARK_DECL(GetEnv, jint + , HOTSPOT_JNI_GETENV_RETURN(_ret_ref)); +#endif /* USDT2 */ jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) { +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, GetEnv__entry, vm, penv, version); +#else /* USDT2 */ + HOTSPOT_JNI_GETENV_ENTRY( + vm, penv, version); +#endif /* USDT2 */ jint ret = JNI_ERR; DT_RETURN_MARK(GetEnv, jint, (const jint&)ret); @@ -3674,15 +5499,30 @@ jint JNICALL jni_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *_args) { +#ifndef USDT2 DTRACE_PROBE3(hotspot_jni, AttachCurrentThreadAsDaemon__entry, vm, penv, _args); +#else /* USDT2 */ + HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_ENTRY( + vm, penv, _args); +#endif /* USDT2 */ if (!vm_created) { +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, AttachCurrentThreadAsDaemon__return, JNI_ERR); +#else /* USDT2 */ + HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN( + (uint32_t) JNI_ERR); +#endif /* USDT2 */ return JNI_ERR; } JNIWrapper("AttachCurrentThreadAsDaemon"); jint ret = attach_current_thread(vm, penv, _args, true); +#ifndef USDT2 DTRACE_PROBE1(hotspot_jni, AttachCurrentThreadAsDaemon__return, ret); +#else /* USDT2 */ + HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN( + ret); +#endif /* USDT2 */ return ret; }
--- a/src/share/vm/prims/jvm.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/prims/jvm.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -73,12 +73,17 @@ #ifdef TARGET_OS_FAMILY_windows # include "jvm_windows.h" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "jvm_bsd.h" +#endif #include <errno.h> +#ifndef USDT2 HS_DTRACE_PROBE_DECL1(hotspot, thread__sleep__begin, long long); HS_DTRACE_PROBE_DECL1(hotspot, thread__sleep__end, int); HS_DTRACE_PROBE_DECL0(hotspot, thread__yield); +#endif /* !USDT2 */ /* NOTE about use of any ctor or function call that can trigger a safepoint/GC: @@ -2813,7 +2818,11 @@ JVM_ENTRY(void, JVM_Yield(JNIEnv *env, jclass threadClass)) JVMWrapper("JVM_Yield"); if (os::dont_yield()) return; +#ifndef USDT2 HS_DTRACE_PROBE0(hotspot, thread__yield); +#else /* USDT2 */ + HOTSPOT_THREAD_YIELD(); +#endif /* USDT2 */ // When ConvertYieldToSleep is off (default), this matches the classic VM use of yield. // Critical for similar threading behaviour if (ConvertYieldToSleep) { @@ -2839,7 +2848,12 @@ // And set new thread state to SLEEPING. JavaThreadSleepState jtss(thread); +#ifndef USDT2 HS_DTRACE_PROBE1(hotspot, thread__sleep__begin, millis); +#else /* USDT2 */ + HOTSPOT_THREAD_SLEEP_BEGIN( + millis); +#endif /* USDT2 */ if (millis == 0) { // When ConvertSleepToYield is on, this matches the classic VM implementation of @@ -2861,7 +2875,12 @@ // An asynchronous exception (e.g., ThreadDeathException) could have been thrown on // us while we were sleeping. We do not overwrite those. if (!HAS_PENDING_EXCEPTION) { +#ifndef USDT2 HS_DTRACE_PROBE1(hotspot, thread__sleep__end,1); +#else /* USDT2 */ + HOTSPOT_THREAD_SLEEP_END( + 1); +#endif /* USDT2 */ // TODO-FIXME: THROW_MSG returns which means we will not call set_state() // to properly restore the thread state. That's likely wrong. THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted"); @@ -2869,7 +2888,12 @@ } thread->osthread()->set_state(old_state); } +#ifndef USDT2 HS_DTRACE_PROBE1(hotspot, thread__sleep__end,0); +#else /* USDT2 */ + HOTSPOT_THREAD_SLEEP_END( + 0); +#endif /* USDT2 */ JVM_END JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass)) @@ -2987,6 +3011,20 @@ } JVM_END +JVM_ENTRY(void, JVM_SetNativeThreadName(JNIEnv* env, jobject jthread, jstring name)) + JVMWrapper("JVM_SetNativeThreadName"); + ResourceMark rm(THREAD); + oop java_thread = JNIHandles::resolve_non_null(jthread); + JavaThread* thr = java_lang_Thread::thread(java_thread); + // Thread naming only supported for the current thread, doesn't work for + // target threads. + if (Thread::current() == thr && !thr->has_attached_via_jni()) { + // we don't set the name of an attached thread to avoid stepping + // on other programs + const char *thread_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(name)); + os::set_native_thread_name(thread_name); + } +JVM_END // java.lang.SecurityManager ///////////////////////////////////////////////////////////////////////
--- a/src/share/vm/prims/jvm.h Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/prims/jvm.h Thu Oct 27 12:21:43 2011 -0700 @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "jvm_windows.h" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "jvm_bsd.h" +#endif #ifndef _JAVASOFT_JVM_H_ #define _JAVASOFT_JVM_H_ @@ -288,6 +291,9 @@ JNIEXPORT jobjectArray JNICALL JVM_GetAllThreads(JNIEnv *env, jclass dummy); +JNIEXPORT void JNICALL +JVM_SetNativeThreadName(JNIEnv *env, jobject jthread, jstring name); + /* getStackTrace() and getAllStackTraces() method */ JNIEXPORT jobjectArray JNICALL JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads);
--- a/src/share/vm/prims/jvmtiEnv.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/prims/jvmtiEnv.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -68,6 +68,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif
--- a/src/share/vm/prims/jvmtiImpl.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/prims/jvmtiImpl.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -54,6 +54,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // // class JvmtiAgentThread
--- a/src/share/vm/prims/methodHandleWalk.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/prims/methodHandleWalk.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -1387,10 +1387,8 @@ int total = count1 + count2; if (count1 != -1 && count2 != -1 && total != 0) { // Normalize the collect counts to the invoke_count - tty->print("counts %d %d scaled by %d = ", count2, count1, _invoke_count); if (count1 != 0) _not_taken_count = (int)(_invoke_count * count1 / (double)total); if (count2 != 0) _taken_count = (int)(_invoke_count * count2 / (double)total); - tty->print_cr("%d %d", _taken_count, _not_taken_count); return true; } return false;
--- a/src/share/vm/prims/nativeLookup.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/prims/nativeLookup.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -49,6 +49,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif static void mangle_name_on(outputStream* st, Symbol* name, int begin, int end) {
--- a/src/share/vm/prims/unsafe.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/prims/unsafe.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -42,9 +42,11 @@ * Implementation of class sun.misc.Unsafe */ +#ifndef USDT2 HS_DTRACE_PROBE_DECL3(hotspot, thread__park__begin, uintptr_t, int, long long); HS_DTRACE_PROBE_DECL1(hotspot, thread__park__end, uintptr_t); HS_DTRACE_PROBE_DECL1(hotspot, thread__unpark, uintptr_t); +#endif /* !USDT2 */ #define MAX_OBJECT_SIZE \ ( arrayOopDesc::header_size(T_DOUBLE) * HeapWordSize \ @@ -1187,10 +1189,20 @@ UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) UnsafeWrapper("Unsafe_Park"); +#ifndef USDT2 HS_DTRACE_PROBE3(hotspot, thread__park__begin, thread->parker(), (int) isAbsolute, time); +#else /* USDT2 */ + HOTSPOT_THREAD_PARK_BEGIN( + (uintptr_t) thread->parker(), (int) isAbsolute, time); +#endif /* USDT2 */ JavaThreadParkedState jtps(thread, time != 0); thread->parker()->park(isAbsolute != 0, time); +#ifndef USDT2 HS_DTRACE_PROBE1(hotspot, thread__park__end, thread->parker()); +#else /* USDT2 */ + HOTSPOT_THREAD_PARK_END( + (uintptr_t) thread->parker()); +#endif /* USDT2 */ UNSAFE_END UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) @@ -1222,7 +1234,12 @@ } } if (p != NULL) { +#ifndef USDT2 HS_DTRACE_PROBE1(hotspot, thread__unpark, p); +#else /* USDT2 */ + HOTSPOT_THREAD_UNPARK( + (uintptr_t) p); +#endif /* USDT2 */ p->unpark(); } UNSAFE_END
--- a/src/share/vm/runtime/arguments.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/arguments.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -46,6 +46,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif #ifndef SERIALGC #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" #endif @@ -2599,16 +2602,16 @@ FLAG_SET_CMDLINE(bool, DisplayVMOutputToStderr, false); FLAG_SET_CMDLINE(bool, DisplayVMOutputToStdout, true); } else if (match_option(option, "-XX:+ExtendedDTraceProbes", &tail)) { -#ifdef SOLARIS +#if defined(DTRACE_ENABLED) FLAG_SET_CMDLINE(bool, ExtendedDTraceProbes, true); FLAG_SET_CMDLINE(bool, DTraceMethodProbes, true); FLAG_SET_CMDLINE(bool, DTraceAllocProbes, true); FLAG_SET_CMDLINE(bool, DTraceMonitorProbes, true); -#else // ndef SOLARIS +#else // defined(DTRACE_ENABLED) jio_fprintf(defaultStream::error_stream(), - "ExtendedDTraceProbes flag is only applicable on Solaris\n"); + "ExtendedDTraceProbes flag is not applicable for this configuration\n"); return JNI_EINVAL; -#endif // ndef SOLARIS +#endif // defined(DTRACE_ENABLED) #ifdef ASSERT } else if (match_option(option, "-XX:+FullGCALot", &tail)) { FLAG_SET_CMDLINE(bool, FullGCALot, true);
--- a/src/share/vm/runtime/atomic.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/atomic.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -33,6 +33,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif #ifdef TARGET_OS_ARCH_linux_x86 # include "atomic_linux_x86.inline.hpp" #endif @@ -57,6 +60,12 @@ #ifdef TARGET_OS_ARCH_linux_ppc # include "atomic_linux_ppc.inline.hpp" #endif +#ifdef TARGET_OS_ARCH_bsd_x86 +# include "atomic_bsd_x86.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_bsd_zero +# include "atomic_bsd_zero.inline.hpp" +#endif jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) { assert(sizeof(jbyte) == 1, "assumption.");
--- a/src/share/vm/runtime/fprofiler.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/fprofiler.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // a simple flat profiler for Java
--- a/src/share/vm/runtime/globals.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/globals.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -50,6 +50,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "globals_windows.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "globals_bsd.hpp" +#endif #ifdef TARGET_OS_ARCH_linux_x86 # include "globals_linux_x86.hpp" #endif @@ -74,6 +77,12 @@ #ifdef TARGET_OS_ARCH_linux_ppc # include "globals_linux_ppc.hpp" #endif +#ifdef TARGET_OS_ARCH_bsd_x86 +# include "globals_bsd_x86.hpp" +#endif +#ifdef TARGET_OS_ARCH_bsd_zero +# include "globals_bsd_zero.hpp" +#endif #ifdef COMPILER1 #ifdef TARGET_ARCH_x86 # include "c1_globals_x86.hpp" @@ -96,6 +105,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "c1_globals_windows.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "c1_globals_bsd.hpp" +#endif #endif #ifdef COMPILER2 #ifdef TARGET_ARCH_x86 @@ -116,6 +128,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "c2_globals_windows.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "c2_globals_bsd.hpp" +#endif #endif #ifdef SHARK #ifdef TARGET_ARCH_zero @@ -662,7 +677,7 @@ notproduct(bool, WalkStackALot, false, \ "trace stack (no print) at every exit from the runtime system") \ \ - develop(bool, Debugging, false, \ + product(bool, Debugging, false, \ "set when executing debug methods in debug.ccp " \ "(to prevent triggering assertions)") \ \ @@ -3506,6 +3521,9 @@ "C1 with MDO profiling (tier 3) invocation notification " \ "frequency.") \ \ + product(intx, Tier23InlineeNotifyFreqLog, 20, \ + "Inlinee invocation (tiers 2 and 3) notification frequency") \ + \ product(intx, Tier0BackedgeNotifyFreqLog, 10, \ "Interpreter (tier 0) invocation notification frequency.") \ \
--- a/src/share/vm/runtime/handles.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/handles.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -38,6 +38,10 @@ # include "os_windows.inline.hpp" # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +# include "thread_bsd.inline.hpp" +#endif #ifdef ASSERT oop* HandleArea::allocate_handle(oop obj) {
--- a/src/share/vm/runtime/handles.inline.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/handles.inline.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // these inline functions are in a separate file to break an include cycle // between Thread and Handle
--- a/src/share/vm/runtime/interfaceSupport.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/interfaceSupport.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -44,6 +44,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // Wrapper for all entry points to the virtual machine. // The HandleMarkCleaner is a faster version of HandleMark. @@ -115,6 +118,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "interfaceSupport_windows.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "interfaceSupport_bsd.hpp" +#endif };
--- a/src/share/vm/runtime/java.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/java.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -85,6 +85,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifndef SERIALGC #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" @@ -102,7 +105,9 @@ #include "opto/runtime.hpp" #endif +#ifndef USDT2 HS_DTRACE_PROBE_DECL(hotspot, vm__shutdown); +#endif /* !USDT2 */ #ifndef PRODUCT @@ -544,8 +549,12 @@ void notify_vm_shutdown() { // For now, just a dtrace probe. +#ifndef USDT2 HS_DTRACE_PROBE(hotspot, vm__shutdown); HS_DTRACE_WORKAROUND_TAIL_CALL_BUG(); +#else /* USDT2 */ + HOTSPOT_VM_SHUTDOWN(); +#endif /* USDT2 */ } void vm_direct_exit(int code) {
--- a/src/share/vm/runtime/javaCalls.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/javaCalls.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -48,6 +48,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // ----------------------------------------------------- // Implementation of JavaCallWrapper @@ -557,4 +560,3 @@ sc.check_doing_return(true); sc.iterate_returntype(); } -
--- a/src/share/vm/runtime/javaCalls.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/javaCalls.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -54,6 +54,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // A JavaCallWrapper is constructed before each JavaCall and destructed after the call. // Its purpose is to allocate/deallocate a new handle block and to save/restore the last
--- a/src/share/vm/runtime/javaFrameAnchor.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/javaFrameAnchor.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -50,6 +50,13 @@ #ifdef TARGET_OS_ARCH_linux_ppc # include "orderAccess_linux_ppc.inline.hpp" #endif +#ifdef TARGET_OS_ARCH_bsd_x86 +# include "orderAccess_bsd_x86.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_bsd_zero +# include "orderAccess_bsd_zero.inline.hpp" +#endif + // // An object for encapsulating the machine/os dependent part of a JavaThread frame state //
--- a/src/share/vm/runtime/jniHandles.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/jniHandles.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -37,6 +37,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif JNIHandleBlock* JNIHandles::_global_handles = NULL;
--- a/src/share/vm/runtime/memprofiler.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/memprofiler.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -46,6 +46,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifndef PRODUCT
--- a/src/share/vm/runtime/mutex.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/mutex.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -39,6 +39,10 @@ # include "mutex_windows.inline.hpp" # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "mutex_bsd.inline.hpp" +# include "thread_bsd.inline.hpp" +#endif // o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o //
--- a/src/share/vm/runtime/mutexLocker.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/mutexLocker.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -36,6 +36,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // Mutexes used in the VM (see comment in mutexLocker.hpp): //
--- a/src/share/vm/runtime/mutexLocker.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/mutexLocker.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -36,6 +36,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif // Mutexes used in the VM.
--- a/src/share/vm/runtime/objectMonitor.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/objectMonitor.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -50,6 +50,10 @@ # include "os_windows.inline.hpp" # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +# include "thread_bsd.inline.hpp" +#endif #if defined(__GNUC__) && !defined(IA64) // Need to inhibit inlining for older versions of GCC to avoid build-time failures @@ -64,6 +68,19 @@ // Only bother with this argument setup if dtrace is available // TODO-FIXME: probes should not fire when caller is _blocked. assert() accordingly. + +#define DTRACE_MONITOR_PROBE_COMMON(klassOop, thread) \ + char* bytes = NULL; \ + int len = 0; \ + jlong jtid = SharedRuntime::get_java_tid(thread); \ + Symbol* klassname = ((oop)(klassOop))->klass()->klass_part()->name(); \ + if (klassname != NULL) { \ + bytes = (char*)klassname->bytes(); \ + len = klassname->utf8_length(); \ + } + +#ifndef USDT2 + HS_DTRACE_PROBE_DECL4(hotspot, monitor__notify, jlong, uintptr_t, char*, int); HS_DTRACE_PROBE_DECL4(hotspot, monitor__notifyAll, @@ -75,16 +92,6 @@ HS_DTRACE_PROBE_DECL4(hotspot, monitor__contended__exit, jlong, uintptr_t, char*, int); -#define DTRACE_MONITOR_PROBE_COMMON(klassOop, thread) \ - char* bytes = NULL; \ - int len = 0; \ - jlong jtid = SharedRuntime::get_java_tid(thread); \ - Symbol* klassname = ((oop)(klassOop))->klass()->klass_part()->name(); \ - if (klassname != NULL) { \ - bytes = (char*)klassname->bytes(); \ - len = klassname->utf8_length(); \ - } - #define DTRACE_MONITOR_WAIT_PROBE(monitor, klassOop, thread, millis) \ { \ if (DTraceMonitorProbes) { \ @@ -103,6 +110,33 @@ } \ } +#else /* USDT2 */ + +#define DTRACE_MONITOR_WAIT_PROBE(monitor, klassOop, thread, millis) \ + { \ + if (DTraceMonitorProbes) { \ + DTRACE_MONITOR_PROBE_COMMON(klassOop, thread); \ + HOTSPOT_MONITOR_WAIT(jtid, \ + (monitor), bytes, len, (millis)); \ + } \ + } + +#define HOTSPOT_MONITOR_contended__enter HOTSPOT_MONITOR_CONTENDED_ENTER +#define HOTSPOT_MONITOR_contended__entered HOTSPOT_MONITOR_CONTENDED_ENTERED +#define HOTSPOT_MONITOR_contended__exit HOTSPOT_MONITOR_CONTENDED_EXIT +#define HOTSPOT_MONITOR_notify HOTSPOT_MONITOR_NOTIFY +#define HOTSPOT_MONITOR_notifyAll HOTSPOT_MONITOR_NOTIFYALL + +#define DTRACE_MONITOR_PROBE(probe, monitor, klassOop, thread) \ + { \ + if (DTraceMonitorProbes) { \ + DTRACE_MONITOR_PROBE_COMMON(klassOop, thread); \ + HOTSPOT_MONITOR_##probe(jtid, \ + (uintptr_t)(monitor), bytes, len); \ + } \ + } + +#endif /* USDT2 */ #else // ndef DTRACE_ENABLED #define DTRACE_MONITOR_WAIT_PROBE(klassOop, thread, millis, mon) {;}
--- a/src/share/vm/runtime/os.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/os.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -60,6 +60,10 @@ # include "os_windows.inline.hpp" # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +# include "thread_bsd.inline.hpp" +#endif # include <signal.h> @@ -116,7 +120,11 @@ assert(false, "Failed localtime_pd"); return NULL; } +#if defined(_ALLBSD_SOURCE) + const time_t zone = (time_t) time_struct.tm_gmtoff; +#else const time_t zone = timezone; +#endif // If daylight savings time is in effect, // we are 1 hour East of our time zone @@ -384,6 +392,13 @@ if (_native_java_library == NULL) { vm_exit_during_initialization("Unable to load native library", ebuf); } + +#if defined(__OpenBSD__) + // Work-around OpenBSD's lack of $ORIGIN support by pre-loading libnet.so + // ignore errors + dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), "net"); + dll_load(buffer, ebuf, sizeof(ebuf)); +#endif } static jboolean onLoaded = JNI_FALSE; if (onLoaded) { @@ -1080,6 +1095,9 @@ "%/lib/jsse.jar:" "%/lib/jce.jar:" "%/lib/charsets.jar:" +#ifdef __APPLE__ + "%/lib/JObjC.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 Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/os.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -39,6 +39,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "jvm_windows.h" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "jvm_bsd.h" +#endif // os defines the interface to operating system; this includes traditional // OS services (time, I/O) as well as other functionality with system- @@ -181,6 +184,9 @@ // Returns true if it worked, false if it didn't. static bool bind_to_processor(uint processor_id); + // Give a name to the current thread. + static void set_native_thread_name(const char *name); + // Interface for stack banging (predetect possible stack overflow for // exception processing) There are guard pages, and above that shadow // pages for stack overflow checking. @@ -675,6 +681,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.hpp" +#endif #ifdef TARGET_OS_ARCH_linux_x86 # include "os_linux_x86.hpp" #endif @@ -699,6 +708,12 @@ #ifdef TARGET_OS_ARCH_linux_ppc # include "os_linux_ppc.hpp" #endif +#ifdef TARGET_OS_ARCH_bsd_x86 +# include "os_bsd_x86.hpp" +#endif +#ifdef TARGET_OS_ARCH_bsd_zero +# include "os_bsd_zero.hpp" +#endif // debugging support (mostly used by debug.cpp but also fatal error handler)
--- a/src/share/vm/runtime/osThread.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/osThread.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -109,6 +109,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "osThread_windows.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "osThread_bsd.hpp" +#endif };
--- a/src/share/vm/runtime/safepoint.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/safepoint.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -78,6 +78,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifndef SERIALGC #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/shared/concurrentGCThread.hpp"
--- a/src/share/vm/runtime/sharedRuntime.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/sharedRuntime.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -148,11 +148,13 @@ #include <math.h> +#ifndef USDT2 HS_DTRACE_PROBE_DECL4(hotspot, object__alloc, Thread*, char*, int, size_t); HS_DTRACE_PROBE_DECL7(hotspot, method__entry, int, char*, int, char*, int, char*, int); HS_DTRACE_PROBE_DECL7(hotspot, method__return, int, char*, int, char*, int, char*, int); +#endif /* !USDT2 */ // Implementation of SharedRuntime @@ -659,12 +661,14 @@ int scope_depth = 0; if (!force_unwind) { int bci = sd->bci(); + bool recursive_exception = false; do { bool skip_scope_increment = false; // exception handler lookup KlassHandle ek (THREAD, exception->klass()); handler_bci = sd->method()->fast_exception_handler_bci_for(ek, bci, THREAD); if (HAS_PENDING_EXCEPTION) { + recursive_exception = true; // We threw an exception while trying to find the exception handler. // Transfer the new exception to the exception handle which will // be set into thread local storage, and do another lookup for an @@ -680,6 +684,9 @@ skip_scope_increment = true; } } + else { + recursive_exception = false; + } if (!top_frame_only && handler_bci < 0 && !skip_scope_increment) { sd = sd->sender(); if (sd != NULL) { @@ -687,7 +694,7 @@ } ++scope_depth; } - } while (!top_frame_only && handler_bci < 0 && sd != NULL); + } while (recursive_exception || (!top_frame_only && handler_bci < 0 && sd != NULL)); } // found handling method => lookup exception handler @@ -954,8 +961,14 @@ Klass* klass = o->blueprint(); int size = o->size(); Symbol* name = klass->name(); +#ifndef USDT2 HS_DTRACE_PROBE4(hotspot, object__alloc, get_java_tid(thread), name->bytes(), name->utf8_length(), size * HeapWordSize); +#else /* USDT2 */ + HOTSPOT_OBJECT_ALLOC( + get_java_tid(thread), + (char *) name->bytes(), name->utf8_length(), size * HeapWordSize); +#endif /* USDT2 */ return 0; } @@ -965,10 +978,18 @@ Symbol* kname = method->klass_name(); Symbol* name = method->name(); Symbol* sig = method->signature(); +#ifndef USDT2 HS_DTRACE_PROBE7(hotspot, method__entry, get_java_tid(thread), kname->bytes(), kname->utf8_length(), name->bytes(), name->utf8_length(), sig->bytes(), sig->utf8_length()); +#else /* USDT2 */ + HOTSPOT_METHOD_ENTRY( + get_java_tid(thread), + (char *) kname->bytes(), kname->utf8_length(), + (char *) name->bytes(), name->utf8_length(), + (char *) sig->bytes(), sig->utf8_length()); +#endif /* USDT2 */ return 0; JRT_END @@ -978,10 +999,18 @@ Symbol* kname = method->klass_name(); Symbol* name = method->name(); Symbol* sig = method->signature(); +#ifndef USDT2 HS_DTRACE_PROBE7(hotspot, method__return, get_java_tid(thread), kname->bytes(), kname->utf8_length(), name->bytes(), name->utf8_length(), sig->bytes(), sig->utf8_length()); +#else /* USDT2 */ + HOTSPOT_METHOD_RETURN( + get_java_tid(thread), + (char *) kname->bytes(), kname->utf8_length(), + (char *) name->bytes(), name->utf8_length(), + (char *) sig->bytes(), sig->utf8_length()); +#endif /* USDT2 */ return 0; JRT_END
--- a/src/share/vm/runtime/synchronizer.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/synchronizer.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -51,6 +51,10 @@ # include "os_windows.inline.hpp" # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +# include "thread_bsd.inline.hpp" +#endif #if defined(__GNUC__) && !defined(IA64) // Need to inhibit inlining for older versions of GCC to avoid build-time failures @@ -73,11 +77,6 @@ // Only bother with this argument setup if dtrace is available // TODO-FIXME: probes should not fire when caller is _blocked. assert() accordingly. -HS_DTRACE_PROBE_DECL5(hotspot, monitor__wait, - jlong, uintptr_t, char*, int, long); -HS_DTRACE_PROBE_DECL4(hotspot, monitor__waited, - jlong, uintptr_t, char*, int); - #define DTRACE_MONITOR_PROBE_COMMON(klassOop, thread) \ char* bytes = NULL; \ int len = 0; \ @@ -88,6 +87,12 @@ len = klassname->utf8_length(); \ } +#ifndef USDT2 +HS_DTRACE_PROBE_DECL5(hotspot, monitor__wait, + jlong, uintptr_t, char*, int, long); +HS_DTRACE_PROBE_DECL4(hotspot, monitor__waited, + jlong, uintptr_t, char*, int); + #define DTRACE_MONITOR_WAIT_PROBE(monitor, klassOop, thread, millis) \ { \ if (DTraceMonitorProbes) { \ @@ -106,6 +111,29 @@ } \ } +#else /* USDT2 */ + +#define DTRACE_MONITOR_WAIT_PROBE(monitor, klassOop, thread, millis) \ + { \ + if (DTraceMonitorProbes) { \ + DTRACE_MONITOR_PROBE_COMMON(klassOop, thread); \ + HOTSPOT_MONITOR_WAIT(jtid, \ + (uintptr_t)(monitor), bytes, len, (millis)); \ + } \ + } + +#define HOTSPOT_MONITOR_PROBE_waited HOTSPOT_MONITOR_PROBE_WAITED + +#define DTRACE_MONITOR_PROBE(probe, monitor, klassOop, thread) \ + { \ + if (DTraceMonitorProbes) { \ + DTRACE_MONITOR_PROBE_COMMON(klassOop, thread); \ + HOTSPOT_MONITOR_PROBE_##probe(jtid, /* probe = waited */ \ + (uintptr_t)(monitor), bytes, len); \ + } \ + } + +#endif /* USDT2 */ #else // ndef DTRACE_ENABLED #define DTRACE_MONITOR_WAIT_PROBE(klassOop, thread, millis, mon) {;}
--- a/src/share/vm/runtime/task.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/task.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -39,6 +39,10 @@ # include "os_windows.inline.hpp" # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +# include "thread_bsd.inline.hpp" +#endif int PeriodicTask::_num_tasks = 0; PeriodicTask* PeriodicTask::_tasks[PeriodicTask::max_tasks];
--- a/src/share/vm/runtime/thread.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/thread.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -89,6 +89,10 @@ # include "os_windows.inline.hpp" # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +# include "thread_bsd.inline.hpp" +#endif #ifndef SERIALGC #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/g1/concurrentMarkThread.inline.hpp" @@ -106,6 +110,7 @@ // Only bother with this argument setup if dtrace is available +#ifndef USDT2 HS_DTRACE_PROBE_DECL(hotspot, vm__init__begin); HS_DTRACE_PROBE_DECL(hotspot, vm__init__end); HS_DTRACE_PROBE_DECL5(hotspot, thread__start, char*, intptr_t, @@ -126,6 +131,26 @@ java_lang_Thread::is_daemon((javathread)->threadObj())); \ } +#else /* USDT2 */ + +#define HOTSPOT_THREAD_PROBE_start HOTSPOT_THREAD_PROBE_START +#define HOTSPOT_THREAD_PROBE_stop HOTSPOT_THREAD_PROBE_STOP + +#define DTRACE_THREAD_PROBE(probe, javathread) \ + { \ + ResourceMark rm(this); \ + int len = 0; \ + const char* name = (javathread)->get_thread_name(); \ + len = strlen(name); \ + HOTSPOT_THREAD_PROBE_##probe( /* probe = start, stop */ \ + (char *) name, len, \ + java_lang_Thread::thread_id((javathread)->threadObj()), \ + (uintptr_t) (javathread)->osthread()->thread_id(), \ + java_lang_Thread::is_daemon((javathread)->threadObj())); \ + } + +#endif /* USDT2 */ + #else // ndef DTRACE_ENABLED #define DTRACE_THREAD_PROBE(probe, javathread) @@ -749,8 +774,9 @@ jint thread_parity = _oops_do_parity; if (thread_parity != strong_roots_parity) { jint res = Atomic::cmpxchg(strong_roots_parity, &_oops_do_parity, thread_parity); - if (res == thread_parity) return true; - else { + if (res == thread_parity) { + return true; + } else { guarantee(res == strong_roots_parity, "Or else what?"); assert(SharedHeap::heap()->n_par_threads() > 0, "Should only fail when parallel."); @@ -1323,7 +1349,7 @@ DirtyCardQueueSet JavaThread::_dirty_card_queue_set; #endif // !SERIALGC -JavaThread::JavaThread(bool is_attaching) : +JavaThread::JavaThread(bool is_attaching_via_jni) : Thread() #ifndef SERIALGC , _satb_mark_queue(&_satb_mark_queue_set), @@ -1331,7 +1357,11 @@ #endif // !SERIALGC { initialize(); - _is_attaching = is_attaching; + if (is_attaching_via_jni) { + _jni_attach_state = _attaching_via_jni; + } else { + _jni_attach_state = _not_attaching_via_jni; + } assert(_deferred_card_mark.is_empty(), "Default MemRegion ctor"); } @@ -1387,7 +1417,7 @@ tty->print_cr("creating thread %p", this); } initialize(); - _is_attaching = false; + _jni_attach_state = _not_attaching_via_jni; set_entry_point(entry_point); // Create the native thread itself. // %note runtime_23 @@ -1499,6 +1529,10 @@ // Note: Due to JVM_StopThread we can have pending exceptions already! if (!this->has_pending_exception() && !java_lang_Thread::is_stillborn(this->threadObj())) { + { + ResourceMark rm(this); + this->set_native_thread_name(this->get_thread_name()); + } HandleMark hm(this); this->entry_point()(this, this); } @@ -2678,7 +2712,7 @@ name_str = UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length(), buf, buflen); } } - else if (is_attaching()) { // workaround for 6412693 - see 6404306 + else if (is_attaching_via_jni()) { // workaround for 6412693 - see 6404306 name_str = "<no-name - thread is attaching>"; } else { @@ -3074,7 +3108,11 @@ os::pause(); } +#ifndef USDT2 HS_DTRACE_PROBE(hotspot, vm__init__begin); +#else /* USDT2 */ + HOTSPOT_VM_INIT_BEGIN(); +#endif /* USDT2 */ // Record VM creation timing statistics TraceVmCreationTime create_vm_timer; @@ -3329,7 +3367,11 @@ // debug stuff, that does not work until all basic classes have been initialized. set_init_completed(); +#ifndef USDT2 HS_DTRACE_PROBE(hotspot, vm__init__end); +#else /* USDT2 */ + HOTSPOT_VM_INIT_END(); +#endif /* USDT2 */ // record VM initialization completion time Management::record_vm_init_completed(); @@ -3905,8 +3947,9 @@ } } VMThread* vmt = VMThread::vm_thread(); - if (vmt->claim_oops_do(is_par, cp)) + if (vmt->claim_oops_do(is_par, cp)) { vmt->oops_do(f, cf); + } } #ifndef SERIALGC
--- a/src/share/vm/runtime/thread.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/thread.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -309,6 +309,11 @@ static void interrupt(Thread* thr); static bool is_interrupted(Thread* thr, bool clear_interrupted); + void set_native_thread_name(const char *name) { + assert(Thread::current() == this, "set_native_thread_name can only be called on the current thread"); + os::set_native_thread_name(name); + } + ObjectMonitor** omInUseList_addr() { return (ObjectMonitor **)&omInUseList; } Monitor* SR_lock() const { return _SR_lock; } @@ -818,10 +823,17 @@ bool _do_not_unlock_if_synchronized; // Do not unlock the receiver of a synchronized method (since it was // never locked) when throwing an exception. Used by interpreter only. - // Flag to mark a JNI thread in the process of attaching - See CR 6404306 - // This flag is never set true other than at construction, and in that case - // is shortly thereafter set false - volatile bool _is_attaching; + // JNI attach states: + enum JNIAttachStates { + _not_attaching_via_jni = 1, // thread is not attaching via JNI + _attaching_via_jni, // thread is attaching via JNI + _attached_via_jni // thread has attached via JNI + }; + + // A regular JavaThread's _jni_attach_state is _not_attaching_via_jni. + // A native thread that is attaching via JNI starts with a value + // of _attaching_via_jni and transitions to _attached_via_jni. + volatile JNIAttachStates _jni_attach_state; public: // State of the stack guard pages for this thread. @@ -889,7 +901,7 @@ public: // Constructor - JavaThread(bool is_attaching = false); // for main thread and JNI attached threads + JavaThread(bool is_attaching_via_jni = false); // for main thread and JNI attached threads JavaThread(ThreadFunction entry_point, size_t stack_size = 0); ~JavaThread(); @@ -1607,6 +1619,12 @@ #ifdef TARGET_OS_ARCH_linux_ppc # include "thread_linux_ppc.hpp" #endif +#ifdef TARGET_OS_ARCH_bsd_x86 +# include "thread_bsd_x86.hpp" +#endif +#ifdef TARGET_OS_ARCH_bsd_zero +# include "thread_bsd_zero.hpp" +#endif public: @@ -1635,8 +1653,9 @@ void set_cached_monitor_info(GrowableArray<MonitorInfo*>* info) { _cached_monitor_info = info; } // clearing/querying jni attach status - bool is_attaching() const { return _is_attaching; } - void set_attached() { _is_attaching = false; OrderAccess::fence(); } + bool is_attaching_via_jni() const { return _jni_attach_state == _attaching_via_jni; } + bool has_attached_via_jni() const { return is_attaching_via_jni() || _jni_attach_state == _attached_via_jni; } + void set_done_attaching_via_jni() { _jni_attach_state = _attached_via_jni; OrderAccess::fence(); } private: // This field is used to determine if a thread has claimed // a par_id: it is -1 if the thread has not claimed a par_id;
--- a/src/share/vm/runtime/threadLocalStorage.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/threadLocalStorage.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -36,6 +36,10 @@ # include "os_windows.inline.hpp" # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +# include "thread_bsd.inline.hpp" +#endif // static member initialization int ThreadLocalStorage::_thread_index = -1;
--- a/src/share/vm/runtime/threadLocalStorage.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/threadLocalStorage.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -68,6 +68,12 @@ #ifdef TARGET_OS_ARCH_linux_ppc # include "threadLS_linux_ppc.hpp" #endif +#ifdef TARGET_OS_ARCH_bsd_x86 +# include "threadLS_bsd_x86.hpp" +#endif +#ifdef TARGET_OS_ARCH_bsd_zero +# include "threadLS_bsd_zero.hpp" +#endif public:
--- a/src/share/vm/runtime/timer.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/timer.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif void elapsedTimer::add(elapsedTimer t) {
--- a/src/share/vm/runtime/virtualspace.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/virtualspace.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif // ReservedSpace
--- a/src/share/vm/runtime/vmStructs.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/vmStructs.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -133,6 +133,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifdef TARGET_OS_ARCH_linux_x86 # include "vmStructs_linux_x86.hpp" #endif @@ -157,6 +160,12 @@ #ifdef TARGET_OS_ARCH_linux_ppc # include "vmStructs_linux_ppc.hpp" #endif +#ifdef TARGET_OS_ARCH_bsd_x86 +# include "vmStructs_bsd_x86.hpp" +#endif +#ifdef TARGET_OS_ARCH_bsd_zero +# include "vmStructs_bsd_zero.hpp" +#endif #ifndef SERIALGC #include "gc_implementation/concurrentMarkSweep/cmsPermGen.hpp" #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" @@ -173,6 +182,7 @@ #include "gc_implementation/parallelScavenge/psVirtualspace.hpp" #include "gc_implementation/parallelScavenge/psYoungGen.hpp" #include "gc_implementation/parallelScavenge/vmStructs_parallelgc.hpp" +#include "gc_implementation/g1/vmStructs_g1.hpp" #endif #ifdef COMPILER2 #include "opto/addnode.hpp" @@ -694,6 +704,12 @@ static_field(SystemDictionary, _box_klasses[0], klassOop) \ static_field(SystemDictionary, _java_system_loader, oop) \ \ + /*************/ \ + /* vmSymbols */ \ + /*************/ \ + \ + static_field(vmSymbols, _symbols[0], Symbol*) \ + \ /*******************/ \ /* HashtableBucket */ \ /*******************/ \ @@ -1539,6 +1555,7 @@ declare_type(LoaderConstraintEntry, HashtableEntry<klassOop>) \ declare_toplevel_type(HashtableBucket) \ declare_toplevel_type(SystemDictionary) \ + declare_toplevel_type(vmSymbols) \ declare_toplevel_type(ProtectionDomainEntry) \ \ declare_toplevel_type(GenericGrowableArray) \ @@ -2521,6 +2538,13 @@ X86_ONLY(declare_constant(frame::entry_frame_call_wrapper_offset)) \ declare_constant(frame::pc_return_offset) \ \ + /*************/ \ + /* vmSymbols */ \ + /*************/ \ + \ + declare_constant(vmSymbols::FIRST_SID) \ + declare_constant(vmSymbols::SID_LIMIT) \ + \ /********************************/ \ /* Calling convention constants */ \ /********************************/ \ @@ -2855,6 +2879,9 @@ VM_STRUCTS_CMS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ GENERATE_STATIC_VM_STRUCT_ENTRY) + + VM_STRUCTS_G1(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ + GENERATE_STATIC_VM_STRUCT_ENTRY) #endif // SERIALGC VM_STRUCTS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ @@ -2898,6 +2925,9 @@ GENERATE_TOPLEVEL_VM_TYPE_ENTRY) VM_TYPES_PARNEW(GENERATE_VM_TYPE_ENTRY) + + VM_TYPES_G1(GENERATE_VM_TYPE_ENTRY, + GENERATE_TOPLEVEL_VM_TYPE_ENTRY) #endif // SERIALGC VM_TYPES_CPU(GENERATE_VM_TYPE_ENTRY, @@ -2997,6 +3027,9 @@ VM_STRUCTS_CMS(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY); + + VM_STRUCTS_G1(CHECK_NONSTATIC_VM_STRUCT_ENTRY, + CHECK_STATIC_VM_STRUCT_ENTRY); #endif // SERIALGC VM_STRUCTS_CPU(CHECK_NONSTATIC_VM_STRUCT_ENTRY, @@ -3037,6 +3070,9 @@ CHECK_SINGLE_ARG_VM_TYPE_NO_OP); VM_TYPES_PARNEW(CHECK_VM_TYPE_ENTRY) + + VM_TYPES_G1(CHECK_VM_TYPE_ENTRY, + CHECK_SINGLE_ARG_VM_TYPE_NO_OP); #endif // SERIALGC VM_TYPES_CPU(CHECK_VM_TYPE_ENTRY, @@ -3102,6 +3138,8 @@ debug_only(VM_STRUCTS_CMS(ENSURE_FIELD_TYPE_PRESENT, \ ENSURE_FIELD_TYPE_PRESENT, \ ENSURE_FIELD_TYPE_PRESENT)); + debug_only(VM_STRUCTS_G1(ENSURE_FIELD_TYPE_PRESENT, \ + ENSURE_FIELD_TYPE_PRESENT)); #endif // SERIALGC debug_only(VM_STRUCTS_CPU(ENSURE_FIELD_TYPE_PRESENT, \ ENSURE_FIELD_TYPE_PRESENT, \
--- a/src/share/vm/runtime/vmThread.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/vmThread.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -46,10 +46,15 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif +#ifndef USDT2 HS_DTRACE_PROBE_DECL3(hotspot, vmops__request, char *, uintptr_t, int); HS_DTRACE_PROBE_DECL3(hotspot, vmops__begin, char *, uintptr_t, int); HS_DTRACE_PROBE_DECL3(hotspot, vmops__end, char *, uintptr_t, int); +#endif /* !USDT2 */ // Dummy VM operation to act as first element in our circular double-linked list class VM_Dummy: public VM_Operation { @@ -159,8 +164,14 @@ // High-level interface bool VMOperationQueue::add(VM_Operation *op) { +#ifndef USDT2 HS_DTRACE_PROBE3(hotspot, vmops__request, op->name(), strlen(op->name()), op->evaluation_mode()); +#else /* USDT2 */ + HOTSPOT_VMOPS_REQUEST( + (char *) op->name(), strlen(op->name()), + op->evaluation_mode()); +#endif /* USDT2 */ // Encapsulates VM queue policy. Currently, that // only involves putting them on the right list @@ -357,11 +368,23 @@ { PerfTraceTime vm_op_timer(perf_accumulated_vm_operation_time()); +#ifndef USDT2 HS_DTRACE_PROBE3(hotspot, vmops__begin, op->name(), strlen(op->name()), op->evaluation_mode()); +#else /* USDT2 */ + HOTSPOT_VMOPS_BEGIN( + (char *) op->name(), strlen(op->name()), + op->evaluation_mode()); +#endif /* USDT2 */ op->evaluate(); +#ifndef USDT2 HS_DTRACE_PROBE3(hotspot, vmops__end, op->name(), strlen(op->name()), op->evaluation_mode()); +#else /* USDT2 */ + HOTSPOT_VMOPS_END( + (char *) op->name(), strlen(op->name()), + op->evaluation_mode()); +#endif /* USDT2 */ } // Last access of info in _cur_vm_operation!
--- a/src/share/vm/runtime/vmThread.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/vmThread.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -36,6 +36,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // // Prioritized queue of VM operations.
--- a/src/share/vm/runtime/vm_operations.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/vm_operations.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -45,6 +45,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #define VM_OP_NAME_INITIALIZE(name) #name,
--- a/src/share/vm/runtime/vm_version.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/runtime/vm_version.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -128,7 +128,7 @@ #ifndef HOTSPOT_VM_DISTRO #error HOTSPOT_VM_DISTRO must be defined #endif -#define VMNAME HOTSPOT_VM_DISTRO " " VMLP VMTYPE " VM" +#define VMNAME HOTSPOT_VM_DISTRO " " VMLP EMBEDDED_ONLY("Embedded ") VMTYPE " VM" const char* Abstract_VM_Version::vm_name() { return VMNAME; @@ -167,7 +167,8 @@ #define OS LINUX_ONLY("linux") \ WINDOWS_ONLY("windows") \ - SOLARIS_ONLY("solaris") + SOLARIS_ONLY("solaris") \ + BSD_ONLY("bsd") #ifdef ZERO #define CPU ZERO_LIBARCH
--- a/src/share/vm/services/classLoadingService.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/services/classLoadingService.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -36,6 +36,8 @@ // Only bother with this argument setup if dtrace is available +#ifndef USDT2 + HS_DTRACE_PROBE_DECL4(hotspot, class__loaded, char*, int, oop, bool); HS_DTRACE_PROBE_DECL4(hotspot, class__unloaded, char*, int, oop, bool); @@ -52,6 +54,24 @@ data, len, (clss)->class_loader(), (shared)); \ } +#else /* USDT2 */ + +#define HOTSPOT_CLASS_unloaded HOTSPOT_CLASS_UNLOADED +#define HOTSPOT_CLASS_loaded HOTSPOT_CLASS_LOADED +#define DTRACE_CLASSLOAD_PROBE(type, clss, shared) \ + { \ + char* data = NULL; \ + int len = 0; \ + Symbol* name = (clss)->name(); \ + if (name != NULL) { \ + data = (char*)name->bytes(); \ + len = name->utf8_length(); \ + } \ + HOTSPOT_CLASS_##type( /* type = unloaded, loaded */ \ + data, len, (clss)->class_loader(), (shared)); \ + } + +#endif /* USDT2 */ #else // ndef DTRACE_ENABLED #define DTRACE_CLASSLOAD_PROBE(type, clss, shared)
--- a/src/share/vm/services/g1MemoryPool.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/services/g1MemoryPool.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -32,71 +32,44 @@ G1MemoryPoolSuper::G1MemoryPoolSuper(G1CollectedHeap* g1h, const char* name, size_t init_size, + size_t max_size, bool support_usage_threshold) : - _g1h(g1h), CollectedMemoryPool(name, - MemoryPool::Heap, - init_size, - undefined_max(), - support_usage_threshold) { + _g1mm(g1h->g1mm()), CollectedMemoryPool(name, + MemoryPool::Heap, + init_size, + max_size, + support_usage_threshold) { assert(UseG1GC, "sanity"); } -// See the comment at the top of g1MemoryPool.hpp -size_t G1MemoryPoolSuper::eden_space_committed(G1CollectedHeap* g1h) { - return MAX2(eden_space_used(g1h), (size_t) HeapRegion::GrainBytes); -} - -// See the comment at the top of g1MemoryPool.hpp -size_t G1MemoryPoolSuper::eden_space_used(G1CollectedHeap* g1h) { - return g1h->g1mm()->eden_space_used(); -} - -// See the comment at the top of g1MemoryPool.hpp -size_t G1MemoryPoolSuper::survivor_space_committed(G1CollectedHeap* g1h) { - return g1h->g1mm()->survivor_space_committed(); -} - -// See the comment at the top of g1MemoryPool.hpp -size_t G1MemoryPoolSuper::survivor_space_used(G1CollectedHeap* g1h) { - return g1h->g1mm()->survivor_space_used(); -} - -// See the comment at the top of g1MemoryPool.hpp -size_t G1MemoryPoolSuper::old_space_committed(G1CollectedHeap* g1h) { - return g1h->g1mm()->old_space_committed(); -} - -// See the comment at the top of g1MemoryPool.hpp -size_t G1MemoryPoolSuper::old_space_used(G1CollectedHeap* g1h) { - return g1h->g1mm()->old_space_used(); -} - G1EdenPool::G1EdenPool(G1CollectedHeap* g1h) : G1MemoryPoolSuper(g1h, - "G1 Eden", - eden_space_committed(g1h), /* init_size */ + "G1 Eden Space", + g1h->g1mm()->eden_space_committed(), /* init_size */ + _undefined_max, false /* support_usage_threshold */) { } MemoryUsage G1EdenPool::get_memory_usage() { size_t initial_sz = initial_size(); size_t max_sz = max_size(); size_t used = used_in_bytes(); - size_t committed = eden_space_committed(_g1h); + size_t committed = _g1mm->eden_space_committed(); return MemoryUsage(initial_sz, used, committed, max_sz); } G1SurvivorPool::G1SurvivorPool(G1CollectedHeap* g1h) : G1MemoryPoolSuper(g1h, - "G1 Survivor", - survivor_space_committed(g1h), /* init_size */ + "G1 Survivor Space", + g1h->g1mm()->survivor_space_committed(), /* init_size */ + _undefined_max, false /* support_usage_threshold */) { } MemoryUsage G1SurvivorPool::get_memory_usage() { size_t initial_sz = initial_size(); size_t max_sz = max_size(); size_t used = used_in_bytes(); - size_t committed = survivor_space_committed(_g1h); + size_t committed = _g1mm->survivor_space_committed(); return MemoryUsage(initial_sz, used, committed, max_sz); } @@ -104,14 +77,15 @@ G1OldGenPool::G1OldGenPool(G1CollectedHeap* g1h) : G1MemoryPoolSuper(g1h, "G1 Old Gen", - old_space_committed(g1h), /* init_size */ + g1h->g1mm()->old_space_committed(), /* init_size */ + _undefined_max, true /* support_usage_threshold */) { } MemoryUsage G1OldGenPool::get_memory_usage() { size_t initial_sz = initial_size(); size_t max_sz = max_size(); size_t used = used_in_bytes(); - size_t committed = old_space_committed(_g1h); + size_t committed = _g1mm->old_space_committed(); return MemoryUsage(initial_sz, used, committed, max_sz); }
--- a/src/share/vm/services/g1MemoryPool.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/services/g1MemoryPool.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -26,12 +26,11 @@ #define SHARE_VM_SERVICES_G1MEMORYPOOL_HPP #ifndef SERIALGC +#include "gc_implementation/g1/g1MonitoringSupport.hpp" #include "services/memoryPool.hpp" #include "services/memoryUsage.hpp" #endif -class G1CollectedHeap; - // This file contains the three classes that represent the memory // pools of the G1 spaces: G1EdenPool, G1SurvivorPool, and // G1OldGenPool. In G1, unlike our other GCs, we do not have a @@ -50,37 +49,19 @@ // on this model. // - // This class is shared by the three G1 memory pool classes -// (G1EdenPool, G1SurvivorPool, G1OldGenPool). Given that the way we -// calculate used / committed bytes for these three pools is related -// (see comment above), we put the calculations in this class so that -// we can easily share them among the subclasses. +// (G1EdenPool, G1SurvivorPool, G1OldGenPool). class G1MemoryPoolSuper : public CollectedMemoryPool { protected: - G1CollectedHeap* _g1h; + const static size_t _undefined_max = (size_t) -1; + G1MonitoringSupport* _g1mm; // Would only be called from subclasses. G1MemoryPoolSuper(G1CollectedHeap* g1h, const char* name, size_t init_size, + size_t max_size, bool support_usage_threshold); - - // The reason why all the code is in static methods is so that it - // can be safely called from the constructors of the subclasses. - - static size_t undefined_max() { - return (size_t) -1; - } - - static size_t eden_space_committed(G1CollectedHeap* g1h); - static size_t eden_space_used(G1CollectedHeap* g1h); - - static size_t survivor_space_committed(G1CollectedHeap* g1h); - static size_t survivor_space_used(G1CollectedHeap* g1h); - - static size_t old_space_committed(G1CollectedHeap* g1h); - static size_t old_space_used(G1CollectedHeap* g1h); }; // Memory pool that represents the G1 eden. @@ -89,10 +70,10 @@ G1EdenPool(G1CollectedHeap* g1h); size_t used_in_bytes() { - return eden_space_used(_g1h); + return _g1mm->eden_space_used(); } size_t max_size() const { - return undefined_max(); + return _undefined_max; } MemoryUsage get_memory_usage(); }; @@ -103,10 +84,10 @@ G1SurvivorPool(G1CollectedHeap* g1h); size_t used_in_bytes() { - return survivor_space_used(_g1h); + return _g1mm->survivor_space_used(); } size_t max_size() const { - return undefined_max(); + return _undefined_max; } MemoryUsage get_memory_usage(); }; @@ -117,10 +98,10 @@ G1OldGenPool(G1CollectedHeap* g1h); size_t used_in_bytes() { - return old_space_used(_g1h); + return _g1mm->old_space_used(); } size_t max_size() const { - return undefined_max(); + return _undefined_max; } MemoryUsage get_memory_usage(); };
--- a/src/share/vm/services/memoryManager.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/services/memoryManager.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -36,10 +36,12 @@ #include "services/gcNotifier.hpp" #include "utilities/dtrace.hpp" +#ifndef USDT2 HS_DTRACE_PROBE_DECL8(hotspot, mem__pool__gc__begin, char*, int, char*, int, size_t, size_t, size_t, size_t); HS_DTRACE_PROBE_DECL8(hotspot, mem__pool__gc__end, char*, int, char*, int, size_t, size_t, size_t, size_t); +#endif /* !USDT2 */ MemoryManager::MemoryManager() { _num_pools = 0; @@ -238,11 +240,19 @@ MemoryPool* pool = MemoryService::get_memory_pool(i); MemoryUsage usage = pool->get_memory_usage(); _current_gc_stat->set_before_gc_usage(i, usage); +#ifndef USDT2 HS_DTRACE_PROBE8(hotspot, mem__pool__gc__begin, name(), strlen(name()), pool->name(), strlen(pool->name()), usage.init_size(), usage.used(), usage.committed(), usage.max_size()); +#else /* USDT2 */ + HOTSPOT_MEM_POOL_GC_BEGIN( + (char *) name(), strlen(name()), + (char *) pool->name(), strlen(pool->name()), + usage.init_size(), usage.used(), + usage.committed(), usage.max_size()); +#endif /* USDT2 */ } } } @@ -268,11 +278,19 @@ MemoryPool* pool = MemoryService::get_memory_pool(i); MemoryUsage usage = pool->get_memory_usage(); +#ifndef USDT2 HS_DTRACE_PROBE8(hotspot, mem__pool__gc__end, name(), strlen(name()), pool->name(), strlen(pool->name()), usage.init_size(), usage.used(), usage.committed(), usage.max_size()); +#else /* USDT2 */ + HOTSPOT_MEM_POOL_GC_END( + (char *) name(), strlen(name()), + (char *) pool->name(), strlen(pool->name()), + usage.init_size(), usage.used(), + usage.committed(), usage.max_size()); +#endif /* USDT2 */ _current_gc_stat->set_after_gc_usage(i, usage); }
--- a/src/share/vm/services/runtimeService.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/services/runtimeService.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -30,8 +30,10 @@ #include "utilities/dtrace.hpp" #include "utilities/exceptions.hpp" +#ifndef USDT2 HS_DTRACE_PROBE_DECL(hs_private, safepoint__begin); HS_DTRACE_PROBE_DECL(hs_private, safepoint__end); +#endif /* !USDT2 */ TimeStamp RuntimeService::_app_timer; TimeStamp RuntimeService::_safepoint_timer; @@ -108,7 +110,11 @@ } void RuntimeService::record_safepoint_begin() { +#ifndef USDT2 HS_DTRACE_PROBE(hs_private, safepoint__begin); +#else /* USDT2 */ + HS_PRIVATE_SAFEPOINT_BEGIN(); +#endif /* USDT2 */ // Print the time interval in which the app was executing if (PrintGCApplicationConcurrentTime) { @@ -133,7 +139,11 @@ } void RuntimeService::record_safepoint_end() { +#ifndef USDT2 HS_DTRACE_PROBE(hs_private, safepoint__end); +#else /* USDT2 */ + HS_PRIVATE_SAFEPOINT_END(); +#endif /* USDT2 */ // Print the time interval for which the app was stopped // during the current safepoint operation.
--- a/src/share/vm/services/threadService.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/services/threadService.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -751,7 +751,7 @@ _blocker_object = obj(); JavaThread* owner = ObjectSynchronizer::get_lock_owner(obj, false); if ((owner == NULL && _thread_status == java_lang_Thread::BLOCKED_ON_MONITOR_ENTER) - || (owner != NULL && owner->is_attaching())) { + || (owner != NULL && owner->is_attaching_via_jni())) { // ownership information of the monitor is not available // (may no longer be owned or releasing to some other thread) // make this thread in RUNNABLE state. @@ -899,7 +899,7 @@ } // skip jni threads in the process of attaching - if (!include_jni_attaching_threads && jt->is_attaching()) { + if (!include_jni_attaching_threads && jt->is_attaching_via_jni()) { continue; }
--- a/src/share/vm/utilities/accessFlags.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/accessFlags.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -34,6 +34,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif void AccessFlags::atomic_set_bits(jint bits) {
--- a/src/share/vm/utilities/array.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/array.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -34,6 +34,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifdef ASSERT
--- a/src/share/vm/utilities/bitMap.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/bitMap.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif BitMap::BitMap(bm_word_t* map, idx_t size_in_bits) :
--- a/src/share/vm/utilities/debug.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/debug.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -62,6 +62,10 @@ # include "os_windows.inline.hpp" # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +# include "thread_bsd.inline.hpp" +#endif #ifndef ASSERT # ifdef _DEBUG @@ -205,7 +209,7 @@ // Place-holder for non-existent suppression check: #define error_is_suppressed(file_name, line_no) (false) -#endif //PRODUCT +#endif // !PRODUCT void report_vm_error(const char* file, int line, const char* error_msg, const char* detail_msg) @@ -260,7 +264,7 @@ void report_untested(const char* file, int line, const char* message) { #ifndef PRODUCT warning("Untested: %s in %s: %d\n", message, file, line); -#endif // PRODUCT +#endif // !PRODUCT } void report_out_of_shared_space(SharedSpaceType shared_space) { @@ -305,9 +309,6 @@ } } - -extern "C" void ps(); - static bool error_reported = false; // call this when the VM is dying--it might loosen some asserts @@ -362,11 +363,10 @@ default: ShouldNotReachHere(); } } -#endif // #ifndef PRODUCT +#endif // !PRODUCT // ------ helper functions for debugging go here ------------ -#ifndef PRODUCT // All debug entries should be wrapped with a stack allocated // Command object. It makes sure a resource mark is set and // flushes the logfile to prevent file sharing problems. @@ -387,11 +387,17 @@ tty->print_cr("\"Executing %s\"", str); } - ~Command() { tty->flush(); Debugging = debug_save; level--; } + ~Command() { + tty->flush(); + Debugging = debug_save; + level--; + } }; int Command::level = 0; +#ifndef PRODUCT + extern "C" void blob(CodeBlob* cb) { Command c("blob"); cb->print(); @@ -474,7 +480,7 @@ oop obj = oop(p); obj->print(); } else { - tty->print("%#p", p); + tty->print(PTR_FORMAT, p); } } @@ -483,7 +489,10 @@ extern "C" void pa(intptr_t p) { ((AllocatedObj*) p)->print(); } extern "C" void findpc(intptr_t x); +#endif // !PRODUCT + extern "C" void ps() { // print stack + if (Thread::current() == NULL) return; Command c("ps"); @@ -496,6 +505,11 @@ if (p->has_last_Java_frame()) { // If the last_Java_fp is set we are in C land and // can call the standard stack_trace function. +#ifdef PRODUCT + p->print_stack(); + } else { + tty->print_cr("Cannot find the last Java frame, printing stack disabled."); +#else // !PRODUCT p->trace_stack(); } else { frame f = os::current_frame(); @@ -504,6 +518,7 @@ tty->print("(guessing starting frame id=%#p based on current fp)\n", f.id()); p->trace_stack_from(vframe::new_vframe(&f, ®_map, p)); pd_ps(f); +#endif // PRODUCT } } @@ -520,6 +535,8 @@ } } +#ifndef PRODUCT + extern "C" void psf() { // print stack frames { Command c("psf"); @@ -551,12 +568,15 @@ SafepointSynchronize::print_state(); } +#endif // !PRODUCT extern "C" void pss() { // print all stacks + if (Thread::current() == NULL) return; Command c("pss"); - Threads::print(true, true); + Threads::print(true, PRODUCT_ONLY(false) NOT_PRODUCT(true)); } +#ifndef PRODUCT extern "C" void debug() { // to set things up for compiler debugging Command c("debug"); @@ -907,4 +927,4 @@ } #endif -#endif // PRODUCT +#endif // !PRODUCT
--- a/src/share/vm/utilities/decoder.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/decoder.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -29,7 +29,7 @@ Decoder::decoder_status Decoder::_decoder_status = Decoder::no_error; bool Decoder::_initialized = false; -#ifndef _WINDOWS +#if !defined(_WINDOWS) && !defined(__APPLE__) // Implementation of common functionalities among Solaris and Linux #include "utilities/elfFile.hpp" @@ -101,4 +101,3 @@ } #endif -
--- a/src/share/vm/utilities/decoder.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/decoder.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -38,6 +38,8 @@ typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64); typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWORD); +#elif defined(__APPLE__) + #else class ElfFile; @@ -79,7 +81,7 @@ static decoder_status get_status() { return _decoder_status; }; -#ifndef _WINDOWS +#if !defined(_WINDOWS) && !defined(__APPLE__) private: static ElfFile* get_elf_file(const char* filepath); #endif // _WINDOWS @@ -94,6 +96,7 @@ static bool _can_decode_in_vm; static pfn_SymGetSymFromAddr64 _pfnSymGetSymFromAddr64; static pfn_UndecorateSymbolName _pfnUndecorateSymbolName; +#elif __APPLE__ #else static ElfFile* _opened_elf_files; #endif // _WINDOWS
--- a/src/share/vm/utilities/dtrace.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/dtrace.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -25,7 +25,7 @@ #ifndef SHARE_VM_UTILITIES_DTRACE_HPP #define SHARE_VM_UTILITIES_DTRACE_HPP -#if defined(SOLARIS) && defined(DTRACE_ENABLED) +#if defined(DTRACE_ENABLED) #include <sys/sdt.h> @@ -36,11 +36,27 @@ #define HS_DTRACE_WORKAROUND_TAIL_CALL_BUG() \ do { volatile size_t dtrace_workaround_tail_call_bug = 1; } while (0) -#else // ndef SOLARIS || ndef DTRACE_ENABLED +#if defined(SOLARIS) +#define USDT1 1 +#elif defined(__APPLE__) +#define USDT2 1 +#include <sys/types.h> +#include "dtracefiles/hotspot.h" +#include "dtracefiles/hotspot_jni.h" +#include "dtracefiles/hs_private.h" +#else +#error "dtrace enabled for unknown os" +#endif /* defined(SOLARIS) */ + +#else /* defined(DTRACE_ENABLED) */ #define DTRACE_ONLY(x) #define NOT_DTRACE(x) x +#define HS_DTRACE_WORKAROUND_TAIL_CALL_BUG() + +#ifndef USDT2 + #define DTRACE_PROBE(a,b) {;} #define DTRACE_PROBE1(a,b,c) {;} #define DTRACE_PROBE2(a,b,c,d) {;} @@ -48,9 +64,14 @@ #define DTRACE_PROBE4(a,b,c,d,e,f) {;} #define DTRACE_PROBE5(a,b,c,d,e,f,g) {;} -#define HS_DTRACE_WORKAROUND_TAIL_CALL_BUG() +#else /* USDT2 */ -#endif +#include "dtrace_usdt2_disabled.hpp" +#endif /* USDT2 */ + +#endif /* defined(DTRACE_ENABLED) */ + +#ifndef USDT2 #define HS_DTRACE_PROBE_FN(provider,name)\ __dtrace_##provider##___##name @@ -133,4 +154,6 @@ (uintptr_t)a3,(uintptr_t)a4,(uintptr_t)a5,(uintptr_t)a6,(uintptr_t)a7,\ (uintptr_t)a8,(uintptr_t)a9)) +#endif /* !USDT2 */ + #endif // SHARE_VM_UTILITIES_DTRACE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/utilities/dtrace_usdt2_disabled.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,1097 @@ +/* + * 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. + * + */ + +#ifndef SHARE_VM_UTILITIES_DTRACE_USDT2_DISABLED_HPP +#define SHARE_VM_UTILITIES_DTRACE_USDT2_DISABLED_HPP + +/* This file contains dummy provider probes needed when compiling a hotspot + * that does not support dtrace probes. This could be because we're building + * on a system that doesn't suuport dtrace or because we're bulding a variant + * of hotspot (like core) where we do not support dtrace + */ +#if !defined(DTRACE_ENABLED) + +#ifdef USDT2 + +/* hotspot provider probes */ +#define HOTSPOT_CLASS_LOADED(arg0, arg1, arg2, arg3) +#define HOTSPOT_CLASS_LOADED_ENABLED() 0 +#define HOTSPOT_CLASS_UNLOADED(arg0, arg1, arg2, arg3) +#define HOTSPOT_CLASS_UNLOADED_ENABLED() 0 +#define HOTSPOT_CLASS_INITIALIZATION_REQUIRED(arg0, arg1, arg2, arg3) +#define HOTSPOT_CLASS_INITIALIZATION_REQUIRED_ENABLED() 0 +#define HOTSPOT_CLASS_INITIALIZATION_RECURSIVE(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_CLASS_INITIALIZATION_RECURSIVE_ENABLED() 0 +#define HOTSPOT_CLASS_INITIALIZATION_CONCURRENT(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_CLASS_INITIALIZATION_CONCURRENT_ENABLED() 0 +#define HOTSPOT_CLASS_INITIALIZATION_ERRONEOUS(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_CLASS_INITIALIZATION_ERRONEOUS_ENABLED() 0 +#define HOTSPOT_CLASS_INITIALIZATION_SUPER_FAILED(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_CLASS_INITIALIZATION_SUPER_FAILED_ENABLED() 0 +#define HOTSPOT_CLASS_INITIALIZATION_CLINIT(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_CLASS_INITIALIZATION_CLINIT_ENABLED() 0 +#define HOTSPOT_CLASS_INITIALIZATION_ERROR(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_CLASS_INITIALIZATION_ERROR_ENABLED() 0 +#define HOTSPOT_CLASS_INITIALIZATION_END(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_CLASS_INITIALIZATION_END_ENABLED() 0 +#define HOTSPOT_COMPILED_METHOD_LOAD(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) +#define HOTSPOT_COMPILED_METHOD_LOAD_ENABLED() 0 +#define HOTSPOT_COMPILED_METHOD_UNLOAD(arg0, arg1, arg2, arg3, arg4, arg5) +#define HOTSPOT_COMPILED_METHOD_UNLOAD_ENABLED() 0 +#define HOTSPOT_GC_BEGIN(arg0) +#define HOTSPOT_GC_BEGIN_ENABLED() 0 +#define HOTSPOT_GC_END() +#define HOTSPOT_GC_END_ENABLED() 0 +#define HOTSPOT_MEM_POOL_GC_BEGIN(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) +#define HOTSPOT_MEM_POOL_GC_BEGIN_ENABLED() 0 +#define HOTSPOT_MEM_POOL_GC_END(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) +#define HOTSPOT_MEM_POOL_GC_END_ENABLED() 0 +#define HOTSPOT_METHOD_COMPILE_BEGIN(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) +#define HOTSPOT_METHOD_COMPILE_BEGIN_ENABLED() 0 +#define HOTSPOT_METHOD_COMPILE_END(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) +#define HOTSPOT_METHOD_COMPILE_END_ENABLED() 0 +#define HOTSPOT_METHOD_ENTRY(arg0, arg1, arg2, arg3, arg4, arg5, arg6) +#define HOTSPOT_METHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_METHOD_RETURN(arg0, arg1, arg2, arg3, arg4, arg5, arg6) +#define HOTSPOT_METHOD_RETURN_ENABLED() 0 +#define HOTSPOT_MONITOR_CONTENDED_ENTER(arg0, arg1, arg2, arg3) +#define HOTSPOT_MONITOR_CONTENDED_ENTER_ENABLED() 0 +#define HOTSPOT_MONITOR_CONTENDED_ENTERED(arg0, arg1, arg2, arg3) +#define HOTSPOT_MONITOR_CONTENDED_ENTERED_ENABLED() 0 +#define HOTSPOT_MONITOR_CONTENDED_EXIT(arg0, arg1, arg2, arg3) +#define HOTSPOT_MONITOR_CONTENDED_EXIT_ENABLED() 0 +#define HOTSPOT_MONITOR_NOTIFY(arg0, arg1, arg2, arg3) +#define HOTSPOT_MONITOR_NOTIFY_ENABLED() 0 +#define HOTSPOT_MONITOR_NOTIFYALL(arg0, arg1, arg2, arg3) +#define HOTSPOT_MONITOR_NOTIFYALL_ENABLED() 0 +#define HOTSPOT_MONITOR_WAIT(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_MONITOR_WAIT_ENABLED() 0 +#define HOTSPOT_MONITOR_WAIT_PROBE(arg0, arg1, arg2, arg3) +#define HOTSPOT_MONITOR_WAIT_PROBE_ENABLED() 0 +#define HOTSPOT_MONITOR_WAITED(arg0, arg1, arg2, arg3) +#define HOTSPOT_MONITOR_WAITED_ENABLED() 0 +#define HOTSPOT_OBJECT_ALLOC(arg0, arg1, arg2, arg3) +#define HOTSPOT_OBJECT_ALLOC_ENABLED() 0 +#define HOTSPOT_THREAD_START(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_THREAD_START_ENABLED() 0 +#define HOTSPOT_THREAD_STOP(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_THREAD_STOP_ENABLED() 0 +#define HOTSPOT_THREAD_SLEEP_BEGIN(arg0) +#define HOTSPOT_THREAD_SLEEP_BEGIN_ENABLED() 0 +#define HOTSPOT_THREAD_SLEEP_END(arg0) +#define HOTSPOT_THREAD_SLEEP_END_ENABLED() 0 +#define HOTSPOT_THREAD_YIELD() +#define HOTSPOT_THREAD_YIELD_ENABLED() 0 +#define HOTSPOT_THREAD_PARK_BEGIN(arg0, arg1, arg2) +#define HOTSPOT_THREAD_PARK_BEGIN_ENABLED() 0 +#define HOTSPOT_THREAD_PARK_END(arg0) +#define HOTSPOT_THREAD_PARK_END_ENABLED() 0 +#define HOTSPOT_THREAD_UNPARK() +#define HOTSPOT_THREAD_UNPARK_ENABLED() 0 +#define HOTSPOT_VM_INIT_BEGIN() +#define HOTSPOT_VM_INIT_BEGIN_ENABLED() 0 +#define HOTSPOT_VM_INIT_END() +#define HOTSPOT_VM_INIT_END_ENABLED() 0 +#define HOTSPOT_VM_SHUTDOWN() +#define HOTSPOT_VM_SHUTDOWN_ENABLED() 0 +#define HOTSPOT_VMOPS_REQUEST(arg0, arg1, arg2) +#define HOTSPOT_VMOPS_REQUEST_ENABLED() 0 +#define HOTSPOT_VMOPS_BEGIN(arg0, arg1, arg2) +#define HOTSPOT_VMOPS_BEGIN_ENABLED() 0 +#define HOTSPOT_VMOPS_END(arg0, arg1, arg2) +#define HOTSPOT_VMOPS_END_ENABLED() 0 + +/* hs_private provider probes */ +#define HS_PRIVATE_CMS_INITMARK_BEGIN() +#define HS_PRIVATE_CMS_INITMARK_BEGIN_ENABLED() 0 +#define HS_PRIVATE_CMS_INITMARK_END() +#define HS_PRIVATE_CMS_INITMARK_END_ENABLED() 0 +#define HS_PRIVATE_CMS_REMARK_BEGIN() +#define HS_PRIVATE_CMS_REMARK_BEGIN_ENABLED() 0 +#define HS_PRIVATE_CMS_REMARK_END() +#define HS_PRIVATE_CMS_REMARK_END_ENABLED() 0 +#define HS_PRIVATE_HASHTABLE_NEW_ENTRY(arg0, arg1, arg2, arg3) +#define HS_PRIVATE_HASHTABLE_NEW_ENTRY_ENABLED() 0 +#define HS_PRIVATE_SAFEPOINT_BEGIN() +#define HS_PRIVATE_SAFEPOINT_BEGIN_ENABLED() 0 +#define HS_PRIVATE_SAFEPOINT_END() +#define HS_PRIVATE_SAFEPOINT_END_ENABLED() 0 + +/* hotspot_jni provider probes */ +#define HOTSPOT_JNI_ALLOCOBJECT_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_ALLOCOBJECT_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_ALLOCOBJECT_RETURN(arg0) +#define HOTSPOT_JNI_ALLOCOBJECT_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_ATTACHCURRENTTHREAD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_ATTACHCURRENTTHREAD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_ATTACHCURRENTTHREAD_RETURN(arg0) +#define HOTSPOT_JNI_ATTACHCURRENTTHREAD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN(arg0) +#define HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLBOOLEANMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLBOOLEANMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLBOOLEANMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLBOOLEANMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLBOOLEANMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLBOOLEANMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLBOOLEANMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLBOOLEANMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLBOOLEANMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLBOOLEANMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLBOOLEANMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLBOOLEANMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLBYTEMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLBYTEMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLBYTEMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLBYTEMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLBYTEMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLBYTEMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLBYTEMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLBYTEMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLBYTEMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLBYTEMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLBYTEMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLBYTEMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLCHARMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLCHARMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLCHARMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLCHARMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLCHARMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLCHARMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLCHARMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLCHARMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLCHARMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLCHARMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLCHARMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLCHARMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLDOUBLEMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLDOUBLEMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLDOUBLEMETHOD_RETURN() +#define HOTSPOT_JNI_CALLDOUBLEMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLDOUBLEMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLDOUBLEMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLDOUBLEMETHODA_RETURN() +#define HOTSPOT_JNI_CALLDOUBLEMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLDOUBLEMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLDOUBLEMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLDOUBLEMETHODV_RETURN() +#define HOTSPOT_JNI_CALLDOUBLEMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLFLOATMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLFLOATMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLFLOATMETHOD_RETURN() +#define HOTSPOT_JNI_CALLFLOATMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLFLOATMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLFLOATMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLFLOATMETHODA_RETURN() +#define HOTSPOT_JNI_CALLFLOATMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLFLOATMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLFLOATMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLFLOATMETHODV_RETURN() +#define HOTSPOT_JNI_CALLFLOATMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLINTMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLINTMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLINTMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLINTMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLINTMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLINTMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLINTMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLINTMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLINTMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLINTMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLINTMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLINTMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLLONGMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLLONGMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLLONGMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLLONGMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLLONGMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLLONGMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLLONGMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLLONGMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLLONGMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLLONGMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLLONGMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLLONGMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHOD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODA_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODV_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHOD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODA_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODV_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALCHARMETHOD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALCHARMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALCHARMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALCHARMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODA_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODV_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHOD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHOD_RETURN() +#define HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODA_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODA_RETURN() +#define HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODV_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODV_RETURN() +#define HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHOD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHOD_RETURN() +#define HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODA_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODA_RETURN() +#define HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODV_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODV_RETURN() +#define HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALINTMETHOD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALINTMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALINTMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALINTMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALINTMETHODA_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALINTMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALINTMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALINTMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALINTMETHODV_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALINTMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALINTMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALINTMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALLONGMETHOD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALLONGMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALLONGMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALLONGMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODA_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODV_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHOD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODA_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODV_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHOD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODA_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODV_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHOD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHOD_RETURN() +#define HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODA_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODA_RETURN() +#define HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODV_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODV_RETURN() +#define HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLOBJECTMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLOBJECTMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLOBJECTMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLOBJECTMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLOBJECTMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLOBJECTMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLOBJECTMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLOBJECTMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLOBJECTMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLOBJECTMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLOBJECTMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLOBJECTMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSHORTMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSHORTMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSHORTMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLSHORTMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSHORTMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSHORTMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSHORTMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLSHORTMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSHORTMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSHORTMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSHORTMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLSHORTMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICBOOLEANMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICBOOLEANMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICBOOLEANMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICBOOLEANMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICBOOLEANMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICBOOLEANMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICBOOLEANMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICBOOLEANMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICBOOLEANMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICBOOLEANMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICBOOLEANMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICBOOLEANMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICBYTEMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICBYTEMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICBYTEMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICBYTEMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICBYTEMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICBYTEMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICBYTEMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICBYTEMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICBYTEMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICBYTEMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICBYTEMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICBYTEMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICCHARMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICCHARMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICCHARMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICCHARMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICCHARMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICCHARMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICCHARMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICCHARMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICCHARMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICCHARMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICCHARMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICCHARMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICDOUBLEMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICDOUBLEMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICDOUBLEMETHOD_RETURN() +#define HOTSPOT_JNI_CALLSTATICDOUBLEMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICDOUBLEMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICDOUBLEMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICDOUBLEMETHODA_RETURN() +#define HOTSPOT_JNI_CALLSTATICDOUBLEMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICDOUBLEMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICDOUBLEMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICDOUBLEMETHODV_RETURN() +#define HOTSPOT_JNI_CALLSTATICDOUBLEMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICFLOATMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICFLOATMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICFLOATMETHOD_RETURN() +#define HOTSPOT_JNI_CALLSTATICFLOATMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICFLOATMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICFLOATMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICFLOATMETHODA_RETURN() +#define HOTSPOT_JNI_CALLSTATICFLOATMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICFLOATMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICFLOATMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICFLOATMETHODV_RETURN() +#define HOTSPOT_JNI_CALLSTATICFLOATMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICINTMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICINTMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICINTMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICINTMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICINTMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICINTMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICINTMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICINTMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICINTMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICINTMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICINTMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICINTMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICLONGMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICLONGMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICLONGMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICLONGMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICLONGMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICLONGMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICLONGMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICLONGMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICLONGMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICLONGMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICLONGMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICLONGMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICOBJECTMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICOBJECTMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICOBJECTMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICOBJECTMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICOBJECTMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICOBJECTMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICOBJECTMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICOBJECTMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICOBJECTMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICOBJECTMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICOBJECTMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICOBJECTMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICSHORTMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICSHORTMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICSHORTMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICSHORTMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICSHORTMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICSHORTMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICSHORTMETHODA_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICSHORTMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICSHORTMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICSHORTMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICSHORTMETHODV_RETURN(arg0) +#define HOTSPOT_JNI_CALLSTATICSHORTMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICVOIDMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICVOIDMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICVOIDMETHOD_RETURN() +#define HOTSPOT_JNI_CALLSTATICVOIDMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICVOIDMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICVOIDMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICVOIDMETHODA_RETURN() +#define HOTSPOT_JNI_CALLSTATICVOIDMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICVOIDMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLSTATICVOIDMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLSTATICVOIDMETHODV_RETURN() +#define HOTSPOT_JNI_CALLSTATICVOIDMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLVOIDMETHOD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLVOIDMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLVOIDMETHOD_RETURN() +#define HOTSPOT_JNI_CALLVOIDMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLVOIDMETHODA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLVOIDMETHODA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLVOIDMETHODA_RETURN() +#define HOTSPOT_JNI_CALLVOIDMETHODA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CALLVOIDMETHODV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CALLVOIDMETHODV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CALLVOIDMETHODV_RETURN() +#define HOTSPOT_JNI_CALLVOIDMETHODV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_CREATEJAVAVM_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_CREATEJAVAVM_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_CREATEJAVAVM_RETURN(arg0) +#define HOTSPOT_JNI_CREATEJAVAVM_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_DEFINECLASS_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_DEFINECLASS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_DEFINECLASS_RETURN(arg0) +#define HOTSPOT_JNI_DEFINECLASS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_DELETEGLOBALREF_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_DELETEGLOBALREF_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_DELETEGLOBALREF_RETURN() +#define HOTSPOT_JNI_DELETEGLOBALREF_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_DELETELOCALREF_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_DELETELOCALREF_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_DELETELOCALREF_RETURN() +#define HOTSPOT_JNI_DELETELOCALREF_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_DELETEWEAKGLOBALREF_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_DELETEWEAKGLOBALREF_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_DELETEWEAKGLOBALREF_RETURN() +#define HOTSPOT_JNI_DELETEWEAKGLOBALREF_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_DESTROYJAVAVM_ENTRY(arg0) +#define HOTSPOT_JNI_DESTROYJAVAVM_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_DESTROYJAVAVM_RETURN(arg0) +#define HOTSPOT_JNI_DESTROYJAVAVM_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_DETACHCURRENTTHREAD_ENTRY(arg0) +#define HOTSPOT_JNI_DETACHCURRENTTHREAD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN(arg0) +#define HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_ENSURELOCALCAPACITY_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_ENSURELOCALCAPACITY_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_ENSURELOCALCAPACITY_RETURN(arg0) +#define HOTSPOT_JNI_ENSURELOCALCAPACITY_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_EXCEPTIONCHECK_ENTRY(arg0) +#define HOTSPOT_JNI_EXCEPTIONCHECK_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_EXCEPTIONCHECK_RETURN(arg0) +#define HOTSPOT_JNI_EXCEPTIONCHECK_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_EXCEPTIONCLEAR_ENTRY(arg0) +#define HOTSPOT_JNI_EXCEPTIONCLEAR_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_EXCEPTIONCLEAR_RETURN() +#define HOTSPOT_JNI_EXCEPTIONCLEAR_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_EXCEPTIONDESCRIBE_ENTRY(arg0) +#define HOTSPOT_JNI_EXCEPTIONDESCRIBE_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_EXCEPTIONDESCRIBE_RETURN() +#define HOTSPOT_JNI_EXCEPTIONDESCRIBE_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_EXCEPTIONOCCURRED_ENTRY(arg0) +#define HOTSPOT_JNI_EXCEPTIONOCCURRED_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_EXCEPTIONOCCURRED_RETURN(arg0) +#define HOTSPOT_JNI_EXCEPTIONOCCURRED_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_FATALERROR_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_FATALERROR_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_FINDCLASS_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_FINDCLASS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_FINDCLASS_RETURN(arg0) +#define HOTSPOT_JNI_FINDCLASS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_FROMREFLECTEDFIELD_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_FROMREFLECTEDFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_FROMREFLECTEDFIELD_RETURN(arg0) +#define HOTSPOT_JNI_FROMREFLECTEDFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_FROMREFLECTEDMETHOD_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_FROMREFLECTEDMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_FROMREFLECTEDMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_FROMREFLECTEDMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETARRAYLENGTH_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_GETARRAYLENGTH_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETARRAYLENGTH_RETURN(arg0) +#define HOTSPOT_JNI_GETARRAYLENGTH_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETBOOLEANARRAYELEMENTS_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETBOOLEANARRAYELEMENTS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETBOOLEANARRAYELEMENTS_RETURN(arg0) +#define HOTSPOT_JNI_GETBOOLEANARRAYELEMENTS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETBOOLEANARRAYREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_GETBOOLEANARRAYREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETBOOLEANARRAYREGION_RETURN() +#define HOTSPOT_JNI_GETBOOLEANARRAYREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETBOOLEANFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETBOOLEANFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETBOOLEANFIELD_RETURN(arg0) +#define HOTSPOT_JNI_GETBOOLEANFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETBYTEARRAYELEMENTS_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETBYTEARRAYELEMENTS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETBYTEARRAYELEMENTS_RETURN(arg0) +#define HOTSPOT_JNI_GETBYTEARRAYELEMENTS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETBYTEARRAYREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_GETBYTEARRAYREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETBYTEARRAYREGION_RETURN() +#define HOTSPOT_JNI_GETBYTEARRAYREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETBYTEFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETBYTEFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETBYTEFIELD_RETURN(arg0) +#define HOTSPOT_JNI_GETBYTEFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETCHARARRAYELEMENTS_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETCHARARRAYELEMENTS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETCHARARRAYELEMENTS_RETURN(arg0) +#define HOTSPOT_JNI_GETCHARARRAYELEMENTS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETCHARARRAYREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_GETCHARARRAYREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETCHARARRAYREGION_RETURN() +#define HOTSPOT_JNI_GETCHARARRAYREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETCHARFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETCHARFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETCHARFIELD_RETURN(arg0) +#define HOTSPOT_JNI_GETCHARFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETCREATEDJAVAVMS_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETCREATEDJAVAVMS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETCREATEDJAVAVMS_RETURN(arg0) +#define HOTSPOT_JNI_GETCREATEDJAVAVMS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETDEFAULTJAVAVMINITARGS_ENTRY(arg0) +#define HOTSPOT_JNI_GETDEFAULTJAVAVMINITARGS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETDEFAULTJAVAVMINITARGS_RETURN(arg0) +#define HOTSPOT_JNI_GETDEFAULTJAVAVMINITARGS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETDIRECTBUFFERADDRESS_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_GETDIRECTBUFFERADDRESS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETDIRECTBUFFERADDRESS_RETURN(arg0) +#define HOTSPOT_JNI_GETDIRECTBUFFERADDRESS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETDIRECTBUFFERCAPACITY_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_GETDIRECTBUFFERCAPACITY_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETDIRECTBUFFERCAPACITY_RETURN(arg0) +#define HOTSPOT_JNI_GETDIRECTBUFFERCAPACITY_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETDOUBLEARRAYELEMENTS_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETDOUBLEARRAYELEMENTS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETDOUBLEARRAYELEMENTS_RETURN(arg0) +#define HOTSPOT_JNI_GETDOUBLEARRAYELEMENTS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETDOUBLEARRAYREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_GETDOUBLEARRAYREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETDOUBLEARRAYREGION_RETURN() +#define HOTSPOT_JNI_GETDOUBLEARRAYREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETDOUBLEFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETDOUBLEFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETDOUBLEFIELD_RETURN() +#define HOTSPOT_JNI_GETDOUBLEFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETENV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETENV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETENV_RETURN(arg0) +#define HOTSPOT_JNI_GETENV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETFIELDID_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_GETFIELDID_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETFIELDID_RETURN(arg0) +#define HOTSPOT_JNI_GETFIELDID_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETFLOATARRAYELEMENTS_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETFLOATARRAYELEMENTS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETFLOATARRAYELEMENTS_RETURN(arg0) +#define HOTSPOT_JNI_GETFLOATARRAYELEMENTS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETFLOATARRAYREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_GETFLOATARRAYREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETFLOATARRAYREGION_RETURN() +#define HOTSPOT_JNI_GETFLOATARRAYREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETFLOATFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETFLOATFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETFLOATFIELD_RETURN() +#define HOTSPOT_JNI_GETFLOATFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETINTARRAYELEMENTS_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETINTARRAYELEMENTS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETINTARRAYELEMENTS_RETURN(arg0) +#define HOTSPOT_JNI_GETINTARRAYELEMENTS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETINTARRAYREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_GETINTARRAYREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETINTARRAYREGION_RETURN() +#define HOTSPOT_JNI_GETINTARRAYREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETINTFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETINTFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETINTFIELD_RETURN(arg0) +#define HOTSPOT_JNI_GETINTFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETJAVAVM_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_GETJAVAVM_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETJAVAVM_RETURN(arg0) +#define HOTSPOT_JNI_GETJAVAVM_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETLONGARRAYELEMENTS_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETLONGARRAYELEMENTS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETLONGARRAYELEMENTS_RETURN(arg0) +#define HOTSPOT_JNI_GETLONGARRAYELEMENTS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETLONGARRAYREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_GETLONGARRAYREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETLONGARRAYREGION_RETURN() +#define HOTSPOT_JNI_GETLONGARRAYREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETLONGFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETLONGFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETLONGFIELD_RETURN(arg0) +#define HOTSPOT_JNI_GETLONGFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETMETHODID_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_GETMETHODID_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETMETHODID_RETURN(arg0) +#define HOTSPOT_JNI_GETMETHODID_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(arg0) +#define HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETOBJECTCLASS_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_GETOBJECTCLASS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETOBJECTCLASS_RETURN(arg0) +#define HOTSPOT_JNI_GETOBJECTCLASS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETOBJECTFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETOBJECTFIELD_RETURN(arg0) +#define HOTSPOT_JNI_GETOBJECTFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETOBJECTREFTYPE_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_GETOBJECTREFTYPE_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETOBJECTREFTYPE_RETURN(arg0) +#define HOTSPOT_JNI_GETOBJECTREFTYPE_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETPRIMITIVEARRAYCRITICAL_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETPRIMITIVEARRAYCRITICAL_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETPRIMITIVEARRAYCRITICAL_RETURN(arg0) +#define HOTSPOT_JNI_GETPRIMITIVEARRAYCRITICAL_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSHORTARRAYELEMENTS_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETSHORTARRAYELEMENTS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSHORTARRAYELEMENTS_RETURN(arg0) +#define HOTSPOT_JNI_GETSHORTARRAYELEMENTS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSHORTARRAYREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_GETSHORTARRAYREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSHORTARRAYREGION_RETURN() +#define HOTSPOT_JNI_GETSHORTARRAYREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSHORTFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETSHORTFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSHORTFIELD_RETURN(arg0) +#define HOTSPOT_JNI_GETSHORTFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICBOOLEANFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETSTATICBOOLEANFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICBOOLEANFIELD_RETURN(arg0) +#define HOTSPOT_JNI_GETSTATICBOOLEANFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICBYTEFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETSTATICBYTEFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICBYTEFIELD_RETURN(arg0) +#define HOTSPOT_JNI_GETSTATICBYTEFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICCHARFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETSTATICCHARFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICCHARFIELD_RETURN(arg0) +#define HOTSPOT_JNI_GETSTATICCHARFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICDOUBLEFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETSTATICDOUBLEFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICDOUBLEFIELD_RETURN() +#define HOTSPOT_JNI_GETSTATICDOUBLEFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICFIELDID_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_GETSTATICFIELDID_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICFIELDID_RETURN(arg0) +#define HOTSPOT_JNI_GETSTATICFIELDID_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICFLOATFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETSTATICFLOATFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICFLOATFIELD_RETURN() +#define HOTSPOT_JNI_GETSTATICFLOATFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICINTFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETSTATICINTFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICINTFIELD_RETURN(arg0) +#define HOTSPOT_JNI_GETSTATICINTFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICLONGFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETSTATICLONGFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICLONGFIELD_RETURN(arg0) +#define HOTSPOT_JNI_GETSTATICLONGFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICMETHODID_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_GETSTATICMETHODID_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICMETHODID_RETURN(arg0) +#define HOTSPOT_JNI_GETSTATICMETHODID_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICOBJECTFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETSTATICOBJECTFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICOBJECTFIELD_RETURN(arg0) +#define HOTSPOT_JNI_GETSTATICOBJECTFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICSHORTFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETSTATICSHORTFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTATICSHORTFIELD_RETURN(arg0) +#define HOTSPOT_JNI_GETSTATICSHORTFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTRINGCHARS_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETSTRINGCHARS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTRINGCHARS_RETURN(arg0) +#define HOTSPOT_JNI_GETSTRINGCHARS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTRINGCRITICAL_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETSTRINGCRITICAL_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTRINGCRITICAL_RETURN(arg0) +#define HOTSPOT_JNI_GETSTRINGCRITICAL_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTRINGLENGTH_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_GETSTRINGLENGTH_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTRINGLENGTH_RETURN(arg0) +#define HOTSPOT_JNI_GETSTRINGLENGTH_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTRINGREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_GETSTRINGREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTRINGREGION_RETURN() +#define HOTSPOT_JNI_GETSTRINGREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTRINGUTFCHARS_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_GETSTRINGUTFCHARS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTRINGUTFCHARS_RETURN(arg0) +#define HOTSPOT_JNI_GETSTRINGUTFCHARS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTRINGUTFLENGTH_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_GETSTRINGUTFLENGTH_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTRINGUTFLENGTH_RETURN(arg0) +#define HOTSPOT_JNI_GETSTRINGUTFLENGTH_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSTRINGUTFREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_GETSTRINGUTFREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSTRINGUTFREGION_RETURN() +#define HOTSPOT_JNI_GETSTRINGUTFREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETSUPERCLASS_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_GETSUPERCLASS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETSUPERCLASS_RETURN(arg0) +#define HOTSPOT_JNI_GETSUPERCLASS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_GETVERSION_ENTRY(arg0) +#define HOTSPOT_JNI_GETVERSION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_GETVERSION_RETURN(arg0) +#define HOTSPOT_JNI_GETVERSION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_ISASSIGNABLEFROM_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_ISASSIGNABLEFROM_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(arg0) +#define HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_ISINSTANCEOF_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_ISINSTANCEOF_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_ISINSTANCEOF_RETURN(arg0) +#define HOTSPOT_JNI_ISINSTANCEOF_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_ISSAMEOBJECT_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_ISSAMEOBJECT_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_ISSAMEOBJECT_RETURN(arg0) +#define HOTSPOT_JNI_ISSAMEOBJECT_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_MONITORENTER_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_MONITORENTER_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_MONITORENTER_RETURN(arg0) +#define HOTSPOT_JNI_MONITORENTER_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_MONITOREXIT_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_MONITOREXIT_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_MONITOREXIT_RETURN(arg0) +#define HOTSPOT_JNI_MONITOREXIT_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWBOOLEANARRAY_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_NEWBOOLEANARRAY_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWBOOLEANARRAY_RETURN(arg0) +#define HOTSPOT_JNI_NEWBOOLEANARRAY_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWBYTEARRAY_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_NEWBYTEARRAY_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWBYTEARRAY_RETURN(arg0) +#define HOTSPOT_JNI_NEWBYTEARRAY_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWCHARARRAY_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_NEWCHARARRAY_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWCHARARRAY_RETURN(arg0) +#define HOTSPOT_JNI_NEWCHARARRAY_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_RETURN(arg0) +#define HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWDOUBLEARRAY_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_NEWDOUBLEARRAY_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWDOUBLEARRAY_RETURN(arg0) +#define HOTSPOT_JNI_NEWDOUBLEARRAY_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWFLOATARRAY_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_NEWFLOATARRAY_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWFLOATARRAY_RETURN(arg0) +#define HOTSPOT_JNI_NEWFLOATARRAY_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWGLOBALREF_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_NEWGLOBALREF_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWGLOBALREF_RETURN(arg0) +#define HOTSPOT_JNI_NEWGLOBALREF_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWINTARRAY_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_NEWINTARRAY_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWINTARRAY_RETURN(arg0) +#define HOTSPOT_JNI_NEWINTARRAY_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWLOCALREF_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_NEWLOCALREF_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWLOCALREF_RETURN(arg0) +#define HOTSPOT_JNI_NEWLOCALREF_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWLONGARRAY_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_NEWLONGARRAY_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWLONGARRAY_RETURN(arg0) +#define HOTSPOT_JNI_NEWLONGARRAY_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWOBJECT_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_NEWOBJECT_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWOBJECT_RETURN(arg0) +#define HOTSPOT_JNI_NEWOBJECT_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWOBJECTA_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_NEWOBJECTA_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWOBJECTA_RETURN(arg0) +#define HOTSPOT_JNI_NEWOBJECTA_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWOBJECTARRAY_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_NEWOBJECTARRAY_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWOBJECTARRAY_RETURN(arg0) +#define HOTSPOT_JNI_NEWOBJECTARRAY_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWOBJECTV_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_NEWOBJECTV_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWOBJECTV_RETURN(arg0) +#define HOTSPOT_JNI_NEWOBJECTV_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWSHORTARRAY_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_NEWSHORTARRAY_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWSHORTARRAY_RETURN(arg0) +#define HOTSPOT_JNI_NEWSHORTARRAY_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWSTRING_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_NEWSTRING_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWSTRING_RETURN(arg0) +#define HOTSPOT_JNI_NEWSTRING_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWSTRINGUTF_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_NEWSTRINGUTF_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWSTRINGUTF_RETURN(arg0) +#define HOTSPOT_JNI_NEWSTRINGUTF_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_NEWWEAKGLOBALREF_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_NEWWEAKGLOBALREF_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_NEWWEAKGLOBALREF_RETURN(arg0) +#define HOTSPOT_JNI_NEWWEAKGLOBALREF_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_POPLOCALFRAME_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_POPLOCALFRAME_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_POPLOCALFRAME_RETURN(arg0) +#define HOTSPOT_JNI_POPLOCALFRAME_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_PUSHLOCALFRAME_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_PUSHLOCALFRAME_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_PUSHLOCALFRAME_RETURN(arg0) +#define HOTSPOT_JNI_PUSHLOCALFRAME_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_REGISTERNATIVES_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_REGISTERNATIVES_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_REGISTERNATIVES_RETURN(arg0) +#define HOTSPOT_JNI_REGISTERNATIVES_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_RELEASEBOOLEANARRAYELEMENTS_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_RELEASEBOOLEANARRAYELEMENTS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_RELEASEBOOLEANARRAYELEMENTS_RETURN() +#define HOTSPOT_JNI_RELEASEBOOLEANARRAYELEMENTS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_RELEASEBYTEARRAYELEMENTS_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_RELEASEBYTEARRAYELEMENTS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_RELEASEBYTEARRAYELEMENTS_RETURN() +#define HOTSPOT_JNI_RELEASEBYTEARRAYELEMENTS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_RELEASECHARARRAYELEMENTS_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_RELEASECHARARRAYELEMENTS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_RELEASECHARARRAYELEMENTS_RETURN() +#define HOTSPOT_JNI_RELEASECHARARRAYELEMENTS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_RELEASEDOUBLEARRAYELEMENTS_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_RELEASEDOUBLEARRAYELEMENTS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_RELEASEDOUBLEARRAYELEMENTS_RETURN() +#define HOTSPOT_JNI_RELEASEDOUBLEARRAYELEMENTS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_RELEASEFLOATARRAYELEMENTS_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_RELEASEFLOATARRAYELEMENTS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_RELEASEFLOATARRAYELEMENTS_RETURN() +#define HOTSPOT_JNI_RELEASEFLOATARRAYELEMENTS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_RELEASEINTARRAYELEMENTS_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_RELEASEINTARRAYELEMENTS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_RELEASEINTARRAYELEMENTS_RETURN() +#define HOTSPOT_JNI_RELEASEINTARRAYELEMENTS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_RELEASELONGARRAYELEMENTS_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_RELEASELONGARRAYELEMENTS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_RELEASELONGARRAYELEMENTS_RETURN() +#define HOTSPOT_JNI_RELEASELONGARRAYELEMENTS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_RETURN() +#define HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_RELEASESHORTARRAYELEMENTS_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_RELEASESHORTARRAYELEMENTS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_RELEASESHORTARRAYELEMENTS_RETURN() +#define HOTSPOT_JNI_RELEASESHORTARRAYELEMENTS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_RELEASESTRINGCHARS_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_RELEASESTRINGCHARS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_RELEASESTRINGCHARS_RETURN() +#define HOTSPOT_JNI_RELEASESTRINGCHARS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_RELEASESTRINGCRITICAL_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_RELEASESTRINGCRITICAL_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN() +#define HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_RELEASESTRINGUTFCHARS_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_RELEASESTRINGUTFCHARS_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_RELEASESTRINGUTFCHARS_RETURN() +#define HOTSPOT_JNI_RELEASESTRINGUTFCHARS_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETBOOLEANARRAYREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_SETBOOLEANARRAYREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETBOOLEANARRAYREGION_RETURN() +#define HOTSPOT_JNI_SETBOOLEANARRAYREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETBOOLEANFIELD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_SETBOOLEANFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETBOOLEANFIELD_RETURN() +#define HOTSPOT_JNI_SETBOOLEANFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETBYTEARRAYREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_SETBYTEARRAYREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETBYTEARRAYREGION_RETURN() +#define HOTSPOT_JNI_SETBYTEARRAYREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETBYTEFIELD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_SETBYTEFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETBYTEFIELD_RETURN() +#define HOTSPOT_JNI_SETBYTEFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETCHARARRAYREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_SETCHARARRAYREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETCHARARRAYREGION_RETURN() +#define HOTSPOT_JNI_SETCHARARRAYREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETCHARFIELD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_SETCHARFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETCHARFIELD_RETURN() +#define HOTSPOT_JNI_SETCHARFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETDOUBLEARRAYREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_SETDOUBLEARRAYREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETDOUBLEARRAYREGION_RETURN() +#define HOTSPOT_JNI_SETDOUBLEARRAYREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETDOUBLEFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_SETDOUBLEFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETDOUBLEFIELD_RETURN() +#define HOTSPOT_JNI_SETDOUBLEFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETFLOATARRAYREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_SETFLOATARRAYREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETFLOATARRAYREGION_RETURN() +#define HOTSPOT_JNI_SETFLOATARRAYREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETFLOATFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_SETFLOATFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETFLOATFIELD_RETURN() +#define HOTSPOT_JNI_SETFLOATFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETINTARRAYREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_SETINTARRAYREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETINTARRAYREGION_RETURN() +#define HOTSPOT_JNI_SETINTARRAYREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETINTFIELD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_SETINTFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETINTFIELD_RETURN() +#define HOTSPOT_JNI_SETINTFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETLONGARRAYREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_SETLONGARRAYREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETLONGARRAYREGION_RETURN() +#define HOTSPOT_JNI_SETLONGARRAYREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETLONGFIELD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_SETLONGFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETLONGFIELD_RETURN() +#define HOTSPOT_JNI_SETLONGFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN() +#define HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_SETOBJECTFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETOBJECTFIELD_RETURN() +#define HOTSPOT_JNI_SETOBJECTFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETSHORTARRAYREGION_ENTRY(arg0, arg1, arg2, arg3, arg4) +#define HOTSPOT_JNI_SETSHORTARRAYREGION_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETSHORTARRAYREGION_RETURN() +#define HOTSPOT_JNI_SETSHORTARRAYREGION_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETSHORTFIELD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_SETSHORTFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETSHORTFIELD_RETURN() +#define HOTSPOT_JNI_SETSHORTFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICBOOLEANFIELD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_SETSTATICBOOLEANFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICBOOLEANFIELD_RETURN() +#define HOTSPOT_JNI_SETSTATICBOOLEANFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICBYTEFIELD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_SETSTATICBYTEFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICBYTEFIELD_RETURN() +#define HOTSPOT_JNI_SETSTATICBYTEFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICCHARFIELD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_SETSTATICCHARFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICCHARFIELD_RETURN() +#define HOTSPOT_JNI_SETSTATICCHARFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICDOUBLEFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_SETSTATICDOUBLEFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICDOUBLEFIELD_RETURN() +#define HOTSPOT_JNI_SETSTATICDOUBLEFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICFLOATFIELD_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_SETSTATICFLOATFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICFLOATFIELD_RETURN() +#define HOTSPOT_JNI_SETSTATICFLOATFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICINTFIELD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_SETSTATICINTFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICINTFIELD_RETURN() +#define HOTSPOT_JNI_SETSTATICINTFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICLONGFIELD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_SETSTATICLONGFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICLONGFIELD_RETURN() +#define HOTSPOT_JNI_SETSTATICLONGFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICOBJECTFIELD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_SETSTATICOBJECTFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICOBJECTFIELD_RETURN() +#define HOTSPOT_JNI_SETSTATICOBJECTFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICSHORTFIELD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_SETSTATICSHORTFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_SETSTATICSHORTFIELD_RETURN() +#define HOTSPOT_JNI_SETSTATICSHORTFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_THROW_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_THROW_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_THROW_RETURN(arg0) +#define HOTSPOT_JNI_THROW_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_THROWNEW_ENTRY(arg0, arg1, arg2) +#define HOTSPOT_JNI_THROWNEW_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_THROWNEW_RETURN(arg0) +#define HOTSPOT_JNI_THROWNEW_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_TOREFLECTEDFIELD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_TOREFLECTEDFIELD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_TOREFLECTEDFIELD_RETURN(arg0) +#define HOTSPOT_JNI_TOREFLECTEDFIELD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY(arg0, arg1, arg2, arg3) +#define HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN(arg0) +#define HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN_ENABLED() 0 +#define HOTSPOT_JNI_UNREGISTERNATIVES_ENTRY(arg0, arg1) +#define HOTSPOT_JNI_UNREGISTERNATIVES_ENTRY_ENABLED() 0 +#define HOTSPOT_JNI_UNREGISTERNATIVES_RETURN(arg0) +#define HOTSPOT_JNI_UNREGISTERNATIVES_RETURN_ENABLED() 0 + +#else /* USDT2 */ +#error This file should only be included for USDT2 +#endif /* USDT2 */ + +#else /* !defined(DTRACE_ENABLED) */ +#error This file should only be included when dtrace is not enabled +#end /* !defined(DTRACE_ENABLED) */ + +#endif // SHARE_VM_UTILITIES_DTRACE_USDT2_DISABLED_HPP
--- a/src/share/vm/utilities/elfFile.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/elfFile.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -24,7 +24,7 @@ #include "precompiled.hpp" -#ifndef _WINDOWS +#if !defined(_WINDOWS) && !defined(__APPLE__) #include <string.h> #include <stdio.h>
--- a/src/share/vm/utilities/elfFile.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/elfFile.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -25,9 +25,13 @@ #ifndef __ELF_FILE_HPP #define __ELF_FILE_HPP -#ifndef _WINDOWS +#if !defined(_WINDOWS) && !defined(__APPLE__) +#if defined(__OpenBSD__) +#include <sys/exec_elf.h> +#else #include <elf.h> +#endif #include <stdio.h> #ifdef _LP64 @@ -41,7 +45,9 @@ typedef Elf64_Shdr Elf_Shdr; typedef Elf64_Sym Elf_Sym; +#if !defined(_ALLBSD_SOURCE) || defined(__APPLE__) #define ELF_ST_TYPE ELF64_ST_TYPE +#endif #else @@ -55,8 +61,10 @@ typedef Elf32_Shdr Elf_Shdr; typedef Elf32_Sym Elf_Sym; +#if !defined(_ALLBSD_SOURCE) || defined(__APPLE__) #define ELF_ST_TYPE ELF32_ST_TYPE #endif +#endif #include "globalDefinitions.hpp" #include "memory/allocation.hpp" @@ -137,4 +145,3 @@ #endif // _WINDOWS #endif // __ELF_FILE_HPP -
--- a/src/share/vm/utilities/elfStringTable.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/elfStringTable.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -24,7 +24,7 @@ #include "precompiled.hpp" -#ifndef _WINDOWS +#if !defined(_WINDOWS) && !defined(__APPLE__) #include "memory/allocation.inline.hpp" #include "runtime/os.hpp" @@ -87,4 +87,3 @@ } #endif // _WINDOWS -
--- a/src/share/vm/utilities/elfStringTable.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/elfStringTable.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -25,7 +25,7 @@ #ifndef __ELF_STRING_TABLE_HPP #define __ELF_STRING_TABLE_HPP -#ifndef _WINDOWS +#if !defined(_WINDOWS) && !defined(__APPLE__) #include "memory/allocation.hpp" #include "utilities/decoder.hpp" @@ -79,4 +79,3 @@ #endif // _WINDOWS #endif // __ELF_STRING_TABLE_HPP -
--- a/src/share/vm/utilities/elfSymbolTable.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/elfSymbolTable.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -24,7 +24,7 @@ #include "precompiled.hpp" -#ifndef _WINDOWS +#if !defined(_WINDOWS) && !defined(__APPLE__) #include "memory/allocation.inline.hpp" #include "utilities/elfSymbolTable.hpp"
--- a/src/share/vm/utilities/elfSymbolTable.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/elfSymbolTable.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -25,7 +25,7 @@ #ifndef __ELF_SYMBOL_TABLE_HPP #define __ELF_SYMBOL_TABLE_HPP -#ifndef _WINDOWS +#if !defined(_WINDOWS) && !defined(__APPLE__) #include "memory/allocation.hpp" @@ -68,6 +68,3 @@ #endif // _WINDOWS #endif // __ELF_SYMBOL_TABLE_HPP - - -
--- a/src/share/vm/utilities/events.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/events.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -38,6 +38,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifndef PRODUCT
--- a/src/share/vm/utilities/exceptions.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/exceptions.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -42,6 +42,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // Implementation of ThreadShadow
--- a/src/share/vm/utilities/globalDefinitions.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/globalDefinitions.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -25,6 +25,10 @@ #ifndef SHARE_VM_UTILITIES_GLOBALDEFINITIONS_HPP #define SHARE_VM_UTILITIES_GLOBALDEFINITIONS_HPP +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif + #ifdef TARGET_COMPILER_gcc # include "utilities/globalDefinitions_gcc.hpp" #endif @@ -1178,67 +1182,47 @@ } // Printf-style formatters for fixed- and variable-width types as pointers and -// integers. -// -// Each compiler-specific definitions file (e.g., globalDefinitions_gcc.hpp) -// must define the macro FORMAT64_MODIFIER, which is the modifier for '%x' or -// '%d' formats to indicate a 64-bit quantity; commonly "l" (in LP64) or "ll" -// (in ILP32). +// integers. These are derived from the definitions in inttypes.h. If the platform +// doesn't provide appropriate definitions, they should be provided in +// the compiler-specific definitions file (e.g., globalDefinitions_gcc.hpp) #define BOOL_TO_STR(_b_) ((_b_) ? "true" : "false") // Format 32-bit quantities. -#define INT32_FORMAT "%d" -#define UINT32_FORMAT "%u" -#define INT32_FORMAT_W(width) "%" #width "d" -#define UINT32_FORMAT_W(width) "%" #width "u" +#define INT32_FORMAT "%" PRId32 +#define UINT32_FORMAT "%" PRIu32 +#define INT32_FORMAT_W(width) "%" #width PRId32 +#define UINT32_FORMAT_W(width) "%" #width PRIu32 -#define PTR32_FORMAT "0x%08x" +#define PTR32_FORMAT "0x%08" PRIx32 // Format 64-bit quantities. -#define INT64_FORMAT "%" FORMAT64_MODIFIER "d" -#define UINT64_FORMAT "%" FORMAT64_MODIFIER "u" -#define PTR64_FORMAT "0x%016" FORMAT64_MODIFIER "x" - -#define INT64_FORMAT_W(width) "%" #width FORMAT64_MODIFIER "d" -#define UINT64_FORMAT_W(width) "%" #width FORMAT64_MODIFIER "u" +#define INT64_FORMAT "%" PRId64 +#define UINT64_FORMAT "%" PRIu64 +#define INT64_FORMAT_W(width) "%" #width PRId64 +#define UINT64_FORMAT_W(width) "%" #width PRIu64 -// Format macros that allow the field width to be specified. The width must be -// a string literal (e.g., "8") or a macro that evaluates to one. -#ifdef _LP64 -#define UINTX_FORMAT_W(width) UINT64_FORMAT_W(width) -#define SSIZE_FORMAT_W(width) INT64_FORMAT_W(width) -#define SIZE_FORMAT_W(width) UINT64_FORMAT_W(width) -#else -#define UINTX_FORMAT_W(width) UINT32_FORMAT_W(width) -#define SSIZE_FORMAT_W(width) INT32_FORMAT_W(width) -#define SIZE_FORMAT_W(width) UINT32_FORMAT_W(width) -#endif // _LP64 +#define PTR64_FORMAT "0x%016" PRIx64 -// Format pointers and size_t (or size_t-like integer types) which change size -// between 32- and 64-bit. The pointer format theoretically should be "%p", -// however, it has different output on different platforms. On Windows, the data -// will be padded with zeros automatically. On Solaris, we can use "%016p" & -// "%08p" on 64 bit & 32 bit platforms to make the data padded with extra zeros. -// On Linux, "%016p" or "%08p" is not be allowed, at least on the latest GCC -// 4.3.2. So we have to use "%016x" or "%08x" to simulate the printing format. -// GCC 4.3.2, however requires the data to be converted to "intptr_t" when -// using "%x". +// Format pointers which change size between 32- and 64-bit. #ifdef _LP64 -#define PTR_FORMAT PTR64_FORMAT -#define UINTX_FORMAT UINT64_FORMAT -#define INTX_FORMAT INT64_FORMAT -#define SIZE_FORMAT UINT64_FORMAT -#define SSIZE_FORMAT INT64_FORMAT +#define INTPTR_FORMAT "0x%016" PRIxPTR +#define PTR_FORMAT "0x%016" PRIxPTR #else // !_LP64 -#define PTR_FORMAT PTR32_FORMAT -#define UINTX_FORMAT UINT32_FORMAT -#define INTX_FORMAT INT32_FORMAT -#define SIZE_FORMAT UINT32_FORMAT -#define SSIZE_FORMAT INT32_FORMAT +#define INTPTR_FORMAT "0x%08" PRIxPTR +#define PTR_FORMAT "0x%08" PRIxPTR #endif // _LP64 -#define INTPTR_FORMAT PTR_FORMAT +#define SSIZE_FORMAT "%" PRIdPTR +#define SIZE_FORMAT "%" PRIuPTR +#define SSIZE_FORMAT_W(width) "%" #width PRIdPTR +#define SIZE_FORMAT_W(width) "%" #width PRIuPTR + +#define INTX_FORMAT "%" PRIdPTR +#define UINTX_FORMAT "%" PRIuPTR +#define INTX_FORMAT_W(width) "%" #width PRIdPTR +#define UINTX_FORMAT_W(width) "%" #width PRIuPTR + // Enable zap-a-lot if in debug version.
--- a/src/share/vm/utilities/globalDefinitions_gcc.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/globalDefinitions_gcc.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -76,15 +76,28 @@ # include <sys/procfs.h> # endif -#ifdef LINUX +#if defined(LINUX) || defined(_ALLBSD_SOURCE) #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS #endif // __STDC_LIMIT_MACROS #include <inttypes.h> #include <signal.h> +#ifndef __OpenBSD__ #include <ucontext.h> +#endif +#ifdef __APPLE__ + #include <AvailabilityMacros.h> + #if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4) + // Mac OS X 10.4 defines EFL_AC and EFL_ID, + // which conflict with hotspot variable names. + // + // This has been fixed in Mac OS X 10.5. + #undef EFL_AC + #undef EFL_ID + #endif +#endif #include <sys/time.h> -#endif // LINUX +#endif // LINUX || _ALLBSD_SOURCE // 4810578: varargs unsafe on 32-bit integer/64-bit pointer architectures // When __cplusplus is defined, NULL is defined as 0 (32-bit constant) in @@ -120,7 +133,7 @@ // pointer is stored as integer value. On some platforms, sizeof(intptr_t) > // sizeof(void*), so here we want something which is integer type, but has the // same size as a pointer. -#ifdef LINUX +#ifdef __GNUC__ #ifdef _LP64 #define NULL_WORD 0L #else @@ -132,7 +145,7 @@ #define NULL_WORD NULL #endif -#ifndef LINUX +#if !defined(LINUX) && !defined(_ALLBSD_SOURCE) // Compiler-specific primitive types typedef unsigned short uint16_t; #ifndef _UINT32_T @@ -152,7 +165,7 @@ // prior definition of intptr_t, and add "&& !defined(XXX)" above. #endif // _SYS_INT_TYPES_H -#endif // !LINUX +#endif // !LINUX && !_ALLBSD_SOURCE // Additional Java basic types @@ -244,7 +257,9 @@ inline int g_isnan(float f) { return isnand(f); } #endif inline int g_isnan(double f) { return isnand(f); } -#elif LINUX +#elif defined(__APPLE__) +inline int g_isnan(double f) { return isnan(f); } +#elif defined(LINUX) || defined(_ALLBSD_SOURCE) inline int g_isnan(float f) { return isnanf(f); } inline int g_isnan(double f) { return isnan(f); } #else
--- a/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -74,8 +74,25 @@ # ifdef SOLARIS_MUTATOR_LIBTHREAD # include <sys/procfs.h> # endif + +#include <inttypes.h> + +// Solaris 8 doesn't provide definitions of these +#ifdef SOLARIS +#ifndef PRIdPTR +#if defined(_LP64) +#define PRIdPTR "ld" +#define PRIuPTR "lu" +#define PRIxPTR "lx" +#else +#define PRIdPTR "d" +#define PRIuPTR "u" +#define PRIxPTR "x" +#endif +#endif +#endif + #ifdef LINUX -# include <inttypes.h> # include <signal.h> # include <ucontext.h> # include <sys/time.h>
--- a/src/share/vm/utilities/globalDefinitions_visCPP.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/globalDefinitions_visCPP.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -207,6 +207,20 @@ // Formatting. #define FORMAT64_MODIFIER "I64" +// Visual Studio doesn't provide inttypes.h so provide appropriate definitions here. +// The 32 bits ones might need I32 but seem to work ok without it. +#define PRId32 "d" +#define PRIu32 "u" +#define PRIx32 "x" + +#define PRId64 "I64d" +#define PRIu64 "I64u" +#define PRIx64 "I64x" + +#define PRIdPTR "d" +#define PRIuPTR "u" +#define PRIxPTR "x" + #define offset_of(klass,field) offsetof(klass,field) #endif // SHARE_VM_UTILITIES_GLOBALDEFINITIONS_VISCPP_HPP
--- a/src/share/vm/utilities/growableArray.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/growableArray.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -34,6 +34,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifdef ASSERT void GenericGrowableArray::set_nesting() { if (on_stack()) {
--- a/src/share/vm/utilities/hashtable.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/hashtable.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -32,8 +32,10 @@ #include "utilities/hashtable.inline.hpp" +#ifndef USDT2 HS_DTRACE_PROBE_DECL4(hs_private, hashtable__new_entry, void*, unsigned int, void*, void*); +#endif /* !USDT2 */ // This is a generic hashtable, designed to be used for the symbol // and string tables. @@ -73,8 +75,13 @@ entry = (HashtableEntry<T>*)BasicHashtable::new_entry(hashValue); entry->set_literal(obj); +#ifndef USDT2 HS_DTRACE_PROBE4(hs_private, hashtable__new_entry, this, hashValue, obj, entry); +#else /* USDT2 */ + HS_PRIVATE_HASHTABLE_NEW_ENTRY( + this, hashValue, (uintptr_t) obj, entry); +#endif /* USDT2 */ return entry; }
--- a/src/share/vm/utilities/histogram.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/histogram.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -37,6 +37,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif // This class provides a framework for collecting various statistics. // The current implementation is oriented towards counting invocations
--- a/src/share/vm/utilities/macros.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/macros.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -161,6 +161,14 @@ #define NOT_WINDOWS(code) code #endif +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) +#define BSD_ONLY(code) code +#define NOT_BSD(code) +#else +#define BSD_ONLY(code) +#define NOT_BSD(code) code +#endif + #ifdef _WIN64 #define WIN64_ONLY(code) code #define NOT_WIN64(code)
--- a/src/share/vm/utilities/ostream.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/ostream.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -39,6 +39,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "os_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif extern "C" void jio_print(const char* s); // Declarationtion of jvm method @@ -992,7 +995,7 @@ #ifndef PRODUCT -#if defined(SOLARIS) || defined(LINUX) +#if defined(SOLARIS) || defined(LINUX) || defined(_ALLBSD_SOURCE) #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h>
--- a/src/share/vm/utilities/preserveException.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/preserveException.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // This file provides more support for exception handling; see also exceptions.hpp class PreserveExceptionMark {
--- a/src/share/vm/utilities/quickSort.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/quickSort.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -54,16 +54,18 @@ return 1; } -static int test_stdlib_comparator(const void* a, const void* b) { - int ai = *(int*)a; - int bi = *(int*)b; - if (ai == bi) { - return 0; +extern "C" { + static int test_stdlib_comparator(const void* a, const void* b) { + int ai = *(int*)a; + int bi = *(int*)b; + if (ai == bi) { + return 0; + } + if (ai < bi) { + return -1; + } + return 1; } - if (ai < bi) { - return -1; - } - return 1; } void QuickSort::print_array(const char* prefix, int* array, int length) { @@ -92,7 +94,6 @@ } bool QuickSort::test_quick_sort() { -#if 0 tty->print_cr("test_quick_sort\n"); { int* test_array = NULL; @@ -213,7 +214,6 @@ delete[] test_array; delete[] expected_array; } -#endif return true; }
--- a/src/share/vm/utilities/taskqueue.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/taskqueue.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -37,6 +37,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif #ifdef TRACESPINNING uint ParallelTaskTerminator::_total_yields = 0; @@ -274,4 +277,3 @@ reset_for_reuse(); _n_threads = n_threads; } -
--- a/src/share/vm/utilities/taskqueue.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/taskqueue.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -53,6 +53,12 @@ #ifdef TARGET_OS_ARCH_linux_ppc # include "orderAccess_linux_ppc.inline.hpp" #endif +#ifdef TARGET_OS_ARCH_bsd_x86 +# include "orderAccess_bsd_x86.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_bsd_zero +# include "orderAccess_bsd_zero.inline.hpp" +#endif // Simple TaskQueue stats that are collected by default in debug builds.
--- a/src/share/vm/utilities/vmError.cpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/vmError.cpp Thu Oct 27 12:21:43 2011 -0700 @@ -45,13 +45,18 @@ "JAVA_HOME", "JRE_HOME", "JAVA_TOOL_OPTIONS", "_JAVA_OPTIONS", "CLASSPATH", "JAVA_COMPILER", "PATH", "USERNAME", - // Env variables that are defined on Solaris/Linux + // Env variables that are defined on Solaris/Linux/BSD "LD_LIBRARY_PATH", "LD_PRELOAD", "SHELL", "DISPLAY", "HOSTTYPE", "OSTYPE", "ARCH", "MACHTYPE", // defined on Linux "LD_ASSUME_KERNEL", "_JAVA_SR_SIGNUM", + // defined on Darwin + "DYLD_LIBRARY_PATH", "DYLD_FALLBACK_LIBRARY_PATH", + "DYLD_FRAMEWORK_PATH", "DYLD_FALLBACK_FRAMEWORK_PATH", + "DYLD_INSERT_LIBRARIES", + // defined on Windows "OS", "PROCESSOR_IDENTIFIER", "_ALT_JAVA_HOME_DIR", @@ -958,7 +963,7 @@ const char* ptr = OnError; while ((cmd = next_OnError_command(buffer, sizeof(buffer), &ptr)) != NULL){ out.print_raw ("# Executing "); -#if defined(LINUX) +#if defined(LINUX) || defined(_ALLBSD_SOURCE) out.print_raw ("/bin/sh -c "); #elif defined(SOLARIS) out.print_raw ("/usr/bin/sh -c ");
--- a/src/share/vm/utilities/workgroup.hpp Wed Oct 26 12:43:05 2011 -0700 +++ b/src/share/vm/utilities/workgroup.hpp Thu Oct 27 12:21:43 2011 -0700 @@ -35,6 +35,9 @@ #ifdef TARGET_OS_FAMILY_windows # include "thread_windows.inline.hpp" #endif +#ifdef TARGET_OS_FAMILY_bsd +# include "thread_bsd.inline.hpp" +#endif // Task class hierarchy: // AbstractGangTask
--- a/test/Makefile Wed Oct 26 12:43:05 2011 -0700 +++ b/test/Makefile Thu Oct 27 12:21:43 2011 -0700 @@ -44,6 +44,22 @@ ARCH = i586 endif endif +ifeq ($(OSNAME), Darwin) + PLATFORM = bsd + SLASH_JAVA = /java + ARCH = $(shell uname -m) + ifeq ($(ARCH), i386) + ARCH = i586 + endif +endif +ifeq ($(findstring BSD,$(OSNAME)), BSD) + PLATFORM = bsd + SLASH_JAVA = /java + ARCH = $(shell uname -m) + ifeq ($(ARCH), i386) + ARCH = i586 + endif +endif ifeq ($(OSNAME), Windows_NT) PLATFORM = windows SLASH_JAVA = J:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6865265/StackOverflowBug.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,89 @@ +/* + * 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. + * + */ + +/** + * @test + * @bug 6865265 + * @summary JVM crashes with "missing exception handler" error + * @author volker.simonis@sap.com + * + * @run main/othervm -XX:CompileThreshold=100 -Xbatch -Xss128k StackOverflowBug + */ + + +public class StackOverflowBug { + + public static int run() { + try { + try { + return run(); + } catch (Throwable e) { + // Notice that the class 'Throwable' is NOT resolved by the verifier, + // because the verifier only checks if 'Throwable' is assignable to + // 'java.lang.Throwable' and this check succeeds immediately if the two + // types have equal names (see 'VerificationType::is_assignable_from' which + // is called from 'ClassVerifier::verify_exception_handler_table'). + // This is strange, because if the two classes have different names, + // 'is_assignable_from()' calls 'is_reference_assignable_from()' which resolves + // both classes by calling 'SystemDictionary::resolve_or_fail()'. This call + // also takes into account the current class loader (i.e. the one which was used + // to load this class) and would place a corresponding + // "java.lang.Throwable / current-Classloader" entry into the system dictionary. + // This would in turn allow C2 to see 'java.lang.Throwable' as "loaded" + // (see 'Parse::catch_inline_exceptions()') when this method is compiled. + return 42; + } + } + finally { + } + } + + public static void main(String argv[]) { + run(); + } +} + +/* + public static int run(); + Code: + 0: invokestatic #2 // Method run:()I + 3: istore_0 + 4: iload_0 + 5: ireturn + 6: astore_0 + 7: bipush 42 + 9: istore_1 + 10: iload_1 + 11: ireturn + 12: astore_2 + 13: aload_2 + 14: athrow + Exception table: + from to target type + 0 4 6 Class java/lang/Throwable + 0 4 12 any + 6 10 12 any + 12 13 12 any + + */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/7100757/Test7100757.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,98 @@ +/* + * 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. + * + */ + +/** + * @test + * @bug 7100757 + * @summary The BitSet.nextSetBit() produces incorrect result in 32bit VM on Sparc + * + * @run main/timeout=300 Test7100757 + */ + +import java.util.*; + +public class Test7100757 { + + public static final int NBITS = 256; + + public static void main(String[] args) { + + BitSet bs = new BitSet(NBITS); + Random rnd = new Random(); + long[] ra = new long[(NBITS+63)/64]; + + for(int l=0; l < 5000000; l++) { + + for(int r = 0; r < ra.length; r++) { + ra[r] = rnd.nextLong(); + } + test(ra, bs); + } + } + + static void test(long[] ra, BitSet bs) { + bs.clear(); + int bits_set = 0; + for(int i = 0, t = 0, b = 0; i < NBITS; i++) { + long bit = 1L << b++; + if((ra[t]&bit) != 0) { + bs.set(i); + bits_set++; + } + if(b == 64) { + t++; + b = 0; + } + } + // Test Long.bitCount() + int check_bits = bs.cardinality(); + if (check_bits != bits_set) { + String bs_str = bs.toString(); + System.err.printf("cardinality bits: %d != %d bs: %s\n", check_bits, bits_set, bs_str); + System.exit(97); + } + // Test Long.numberOfTrailingZeros() + check_bits = 0; + for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) { + check_bits++; + } + if (check_bits != bits_set) { + String bs_str = bs.toString(); + System.err.printf("nextSetBit bits: %d != %d bs: %s\n", check_bits, bits_set, bs_str); + System.exit(97); + } + // Test Long.numberOfLeadingZeros() + for(int i = bs.length(); i > 0; i = bs.length()) { + bs.clear(i-1); + } + // Test Long.bitCount() + check_bits = bs.cardinality(); + if (check_bits != 0) { + String bs_str = bs.toString(); + System.err.printf("after clear bits: %d != 0 bs: %s\n", check_bits, bs_str); + System.exit(97); + } + } + +};
--- a/test/jprt.config Wed Oct 26 12:43:05 2011 -0700 +++ b/test/jprt.config Thu Oct 27 12:21:43 2011 -0700 @@ -75,8 +75,8 @@ # Uses 'uname -s', but only expect SunOS or Linux, assume Windows otherwise. osname=`uname -s` -if [ "${osname}" = SunOS ] ; then - +case "${osname}" in + SunOS ) # SOLARIS: Sparc or X86 osarch=`uname -p` if [ "${osarch}" = sparc ] ; then @@ -100,9 +100,9 @@ # File creation mask umask 002 + ;; -elif [ "${osname}" = Linux ] ; then - + Linux | Darwin ) # Add basic paths path4sdk=/usr/bin:/bin:/usr/sbin:/sbin @@ -111,9 +111,31 @@ fileMustExist "${make}" make umask 002 + ;; -else + FreeBSD | OpenBSD ) + # Add basic paths + path4sdk=/usr/bin:/bin:/usr/sbin:/sbin + + # Find GNU make + make=/usr/local/bin/gmake + fileMustExist "${make}" make + + umask 002 + ;; + NetBSD ) + # Add basic paths + path4sdk=/usr/bin:/bin:/usr/sbin:/sbin + + # Find GNU make + make=/usr/pkg/bin/gmake + fileMustExist "${make}" make + + umask 002 + ;; + + * ) # Windows: Differs on CYGWIN vs. MKS. # We need to determine if we are running a CYGWIN shell or an MKS shell @@ -154,8 +176,8 @@ if [ "${unix_toolset}" = CYGWIN ] ; then path4sdk="`/usr/bin/cygpath -p ${path4sdk}`" fi - -fi + ;; +esac # Export PATH setting PATH="${path4sdk}"
--- a/test/runtime/6929067/Test6929067.sh Wed Oct 26 12:43:05 2011 -0700 +++ b/test/runtime/6929067/Test6929067.sh Thu Oct 27 12:21:43 2011 -0700 @@ -29,7 +29,7 @@ PS=":" FS="/" ;; - SunOS | Windows_* ) + SunOS | Windows_* | *BSD) NULL=NUL PS=";" FS="\\"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/7051189/Xchecksig.sh Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,151 @@ +# +# 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. +# + + +# @test Xchecksig.sh +# @bug 7051189 +# @summary Need to suppress info message if -xcheck:jni used with libjsig.so +# @run shell Xchecksig.sh +# + +if [ "${TESTSRC}" = "" ] + then TESTSRC=. +fi + +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 + + +BIT_FLAG="" + +OS=`uname -s` +case "$OS" in + SunOS | Linux ) + FS="/" + ## for solaris, linux it's HOME + FILE_LOCATION=$HOME + if [ -f ${FILE_LOCATION}${FS}JDK64BIT -a ${OS} = "SunOS" ] + then + BIT_FLAG=`cat ${FILE_LOCATION}${FS}JDK64BIT` + fi + ;; + Windows_* ) + printf "Not testing libjsig.so on Windows. PASSED.\n " + exit 0 + ;; + * ) + printf "Not testing libjsig.so on unrecognised system. PASSED.\n " + exit 0 + ;; +esac + + +JAVA=${TESTJAVA}${FS}bin${FS}java + +# LD_PRELOAD arch needs to match the binary we run, so run the java +# 64-bit binary directly if we are testing 64-bit (bin/ARCH/java). + +# However JPRT runs: .../solaris_x64_5.10-debug/bin/java +# ..which is 32-bit, when it has built the 64-bit version to test. +# +# How does this script know we are meant to run the 64-bit version? +# Can check for the path of the binary containing "x64" on Solaris. + +if [ ${OS} -eq "SunOS" ] +then + printf "SunOS test JAVA=${JAVA}" + printf ${JAVA} | grep x64 > /dev/null + if [ $? -eq 0 ] + then + printf "SunOS x64 test, forcing -d64\n" + BIT_FLAG=-d64 + fi +fi + +ARCH=`uname -p` +case $ARCH in + i386) + if [ X${BIT_FLAG} != "X" ] + then + ARCH=amd64 + JAVA=${TESTJAVA}${FS}bin${FS}${ARCH}${FS}java + fi + ;; + sparc) + if [ X${BIT_FLAG} != "X" ] + then + ARCH=sparcv9 + JAVA=${TESTJAVA}${FS}bin${FS}${ARCH}${FS}java + fi + ;; + * ) + printf "Not testing architecture $ARCH, skipping test.\n" + exit 0 + ;; +esac + +LIBJSIG=${TESTJAVA}${FS}jre${FS}lib${FS}${ARCH}${FS}libjsig.so + +# If libjsig and binary do not match, skip test. + +A=`file ${LIBJSIG} | awk '{ print $3 }'` +B=`file ${JAVA} | awk '{ print $3 }'` + +if [ $A -ne $B ] +then + printf "Mismatching binary and library to preload, skipping test.\n" + exit 0 +fi + +if [ ! -f ${LIBJSIG} ] +then + printf "Skipping test: libjsig missing for given architecture: ${LIBJSIG}\n" + exit 0 +fi +# Use java -version to test, java version info appeas on stderr, +# the libjsig message we are removing appears on stdout. + +# grep returns zero meaning found, non-zero means not found: + +LD_PRELOAD=${LIBJSIG} ${JAVA} ${BIT_FLAG} -Xcheck:jni -version 2>&1 | grep "libjsig is activated" + +if [ $? -eq 0 ]; then + printf "Failed: -Xcheck:jni prints message when libjsig.so is loaded.\n" + exit 1 +fi + + +LD_PRELOAD=${LIBJSIG} ${JAVA} ${BIT_FLAG} -Xcheck:jni -verbose:jni -version 2>&1 | grep "libjsig is activated" +if [ $? != 0 ]; then + printf "Failed: -Xcheck:jni does not print message when libjsig.so is loaded and -verbose:jni is set.\n" + exit 1 +fi + +printf "PASSED\n" +exit 0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/7100935/TestConjointAtomicArraycopy.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright 2011 SAP AG. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 TestConjointAtomicArraycopy + * @bug 7100935 + * @summary verify that oops are copied element-wise atomic + * @run main/othervm -Xint TestConjointAtomicArraycopy + * @run main/othervm -Xcomp -Xbatch TestConjointAtomicArraycopy + * @author axel.siebenborn@sap.com + */ + +public class TestConjointAtomicArraycopy { + + static volatile Object [] testArray = new Object [4]; + + static short[] a1 = new short[8]; + static short[] a2 = new short[8]; + static short[] a3 = new short[8]; + + static volatile boolean keepRunning = true; + + static void testOopsCopy() throws InterruptedException{ + + } + + public static void main(String[] args ) throws InterruptedException{ + for (int i = 0; i < testArray.length; i++){ + testArray[i] = new String("A"); + } + + Thread writer = new Thread (new Runnable(){ + public void run(){ + for (int i = 0 ; i < 1000000; i++) { + System.arraycopy(testArray, 1, testArray, 0, 3); + testArray[2] = new String("a"); + } + } + }); + + Thread reader = new Thread( new Runnable(){ + public void run(){ + while (keepRunning){ + String name = testArray[2].getClass().getName(); + if(!(name.endsWith("String"))){ + throw new RuntimeException("got wrong class name"); + } + } + } + }); + keepRunning = true; + reader.start(); + writer.start(); + writer.join(); + keepRunning = false; + reader.join(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/7100935/TestShortArraycopy.java Thu Oct 27 12:21:43 2011 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright 2011 SAP AG. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 TestShortArraycopy + * @bug 7100935 + * @summary verify that shorts are copied element-wise atomic. + * @run main/othervm -Xint TestShortArraycopy + * @run main/othervm -Xcomp -Xbatch TestShortArraycopy + * @author volker.simonis@gmail.com + */ + +public class TestShortArraycopy { + + static short[] a1 = new short[8]; + static short[] a2 = new short[8]; + static short[] a3 = new short[8]; + + static volatile boolean keepRunning = true; + + public static void main(String[] args) throws InterruptedException { + + for (int i = 0; i < a1.length ; i++) { + a1[i] = (short)0xffff; + a2[i] = (short)0xffff; + a3[i] = (short)0x0000; + } + Thread reader = new Thread() { + public void run() { + while (keepRunning) { + for (int j = 0; j < a1.length; j++) { + short s = a1[j]; + if (s != (short)0xffff && s != (short)0x0000) { + System.out.println("Error: s = " + s); + throw new RuntimeException("wrong result"); + + } + } + } + } + }; + Thread writer = new Thread() { + public void run() { + for (int i = 0; i < 1000000; i++) { + System.arraycopy(a2, 5, a1, 3, 3); + System.arraycopy(a3, 5, a1, 3, 3); + } + } + }; + keepRunning = true; + reader.start(); + writer.start(); + writer.join(); + keepRunning = false; + reader.join(); + } +}