提交 fbed1f27 编写于 作者: S sspitsyn

Merge

...@@ -97,7 +97,8 @@ static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) { ...@@ -97,7 +97,8 @@ static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
* Method: init0 * Method: init0
* Signature: ()V * Signature: ()V
*/ */
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) { JNIEXPORT void JNICALL
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) {
symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J"); symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J");
taskID = (*env)->GetFieldID(env, cls, "task", "J"); taskID = (*env)->GetFieldID(env, cls, "task", "J");
CHECK_EXCEPTION; CHECK_EXCEPTION;
...@@ -108,7 +109,11 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0( ...@@ -108,7 +109,11 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(
* Method: lookupByName0 * Method: lookupByName0
* Signature: (Ljava/lang/String;Ljava/lang/String;)J * Signature: (Ljava/lang/String;Ljava/lang/String;)J
*/ */
JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0(JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) { JNIEXPORT jlong JNICALL
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0(
JNIEnv *env, jobject this_obj,
jstring objectName, jstring symbolName)
{
jlong address = 0; jlong address = 0;
JNF_COCOA_ENTER(env); JNF_COCOA_ENTER(env);
...@@ -137,7 +142,11 @@ JNF_COCOA_EXIT(env); ...@@ -137,7 +142,11 @@ JNF_COCOA_EXIT(env);
* Method: readBytesFromProcess0 * Method: readBytesFromProcess0
* Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult; * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
*/ */
JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0(JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) { JNIEXPORT jbyteArray JNICALL
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0(
JNIEnv *env, jobject this_obj,
jlong addr, jlong numBytes)
{
if (debug) printf("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes); if (debug) printf("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes);
// must allocate storage instead of using former parameter buf // must allocate storage instead of using former parameter buf
...@@ -209,12 +218,74 @@ JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_ ...@@ -209,12 +218,74 @@ JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_
return array; return array;
} }
/*
* Lookup the thread_t that corresponds to the given thread_id.
* The thread_id should be the result from calling thread_info() with THREAD_IDENTIFIER_INFO
* and reading the m_ident_info.thread_id returned.
* The returned thread_t is the mach send right to the kernel port for the corresponding thread.
*
* We cannot simply use the OSThread._thread_id field in the JVM. This is set to ::mach_thread_self()
* in the VM, but that thread port is not valid for a remote debugger to access the thread.
*/
thread_t
lookupThreadFromThreadId(task_t task, jlong thread_id) {
if (debug) {
printf("lookupThreadFromThreadId thread_id=0x%llx\n", thread_id);
}
thread_array_t thread_list = NULL;
mach_msg_type_number_t thread_list_count = 0;
thread_t result_thread = 0;
int i;
// get the list of all the send rights
kern_return_t result = task_threads(task, &thread_list, &thread_list_count);
if (result != KERN_SUCCESS) {
if (debug) {
printf("task_threads returned 0x%x\n", result);
}
return 0;
}
for(i = 0 ; i < thread_list_count; i++) {
thread_identifier_info_data_t m_ident_info;
mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
// get the THREAD_IDENTIFIER_INFO for the send right
result = thread_info(thread_list[i], THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count);
if (result != KERN_SUCCESS) {
if (debug) {
printf("thread_info returned 0x%x\n", result);
}
break;
}
// if this is the one we're looking for, return the send right
if (thread_id == m_ident_info.thread_id)
{
result_thread = thread_list[i];
break;
}
}
vm_size_t thread_list_size = (vm_size_t) (thread_list_count * sizeof (thread_t));
vm_deallocate(mach_task_self(), (vm_address_t) thread_list, thread_list_count);
return result_thread;
}
/* /*
* Class: sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
* Method: getThreadIntegerRegisterSet0 * Method: getThreadIntegerRegisterSet0
* Signature: (I)[J * Signature: (J)[J
*/ */
JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0(JNIEnv *env, jobject this_obj, jint lwp_id) { JNIEXPORT jlongArray JNICALL
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0(
JNIEnv *env, jobject this_obj,
jlong thread_id)
{
if (debug) if (debug)
printf("getThreadRegisterSet0 called\n"); printf("getThreadRegisterSet0 called\n");
...@@ -226,8 +297,9 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_ ...@@ -226,8 +297,9 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_
int i; int i;
jlongArray registerArray; jlongArray registerArray;
jlong *primitiveArray; jlong *primitiveArray;
task_t gTask = getTask(env, this_obj);
tid = lwp_id; tid = lookupThreadFromThreadId(gTask, thread_id);
result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count); result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count);
...@@ -328,12 +400,14 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_ ...@@ -328,12 +400,14 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_
} }
/* /*
* Class: sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
* Method: translateTID0 * Method: translateTID0
* Signature: (I)I * Signature: (I)I
*/ */
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(JNIEnv *env, jobject this_obj, jint tid) { Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(
JNIEnv *env, jobject this_obj, jint tid)
{
if (debug) if (debug)
printf("translateTID0 called on tid = 0x%x\n", (int)tid); printf("translateTID0 called on tid = 0x%x\n", (int)tid);
...@@ -361,7 +435,10 @@ Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(JNIEnv *e ...@@ -361,7 +435,10 @@ Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(JNIEnv *e
* Method: attach0 * Method: attach0
* Signature: (I)V * Signature: (I)V
*/ */
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(JNIEnv *env, jobject this_obj, jint jpid) { JNIEXPORT void JNICALL
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(
JNIEnv *env, jobject this_obj, jint jpid)
{
JNF_COCOA_ENTER(env); JNF_COCOA_ENTER(env);
if (getenv("JAVA_SAPROC_DEBUG") != NULL) if (getenv("JAVA_SAPROC_DEBUG") != NULL)
debug = JNI_TRUE; debug = JNI_TRUE;
...@@ -401,7 +478,10 @@ JNF_COCOA_EXIT(env); ...@@ -401,7 +478,10 @@ JNF_COCOA_EXIT(env);
* Method: detach0 * Method: detach0
* Signature: ()V * Signature: ()V
*/ */
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(JNIEnv *env, jobject this_obj) { JNIEXPORT void JNICALL
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(
JNIEnv *env, jobject this_obj)
{
JNF_COCOA_ENTER(env); JNF_COCOA_ENTER(env);
if (debug) printf("detach0 called\n"); if (debug) printf("detach0 called\n");
...@@ -419,10 +499,13 @@ JNF_COCOA_EXIT(env); ...@@ -419,10 +499,13 @@ JNF_COCOA_EXIT(env);
* Method: load_library * Method: load_library
* Signature: (Ljava/lang/String;)L * Signature: (Ljava/lang/String;)L
*/ */
JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_asm_Disassembler_load_1library(JNIEnv * env, JNIEXPORT jlong JNICALL
Java_sun_jvm_hotspot_asm_Disassembler_load_1library(
JNIEnv * env,
jclass disclass, jclass disclass,
jstring jrepath_s, jstring jrepath_s,
jstring libname_s) { jstring libname_s)
{
uintptr_t func = 0; uintptr_t func = 0;
const char* error_message = NULL; const char* error_message = NULL;
const char* java_home; const char* java_home;
...@@ -533,13 +616,16 @@ static int printf_to_env(void* env_pv, const char* format, ...) { ...@@ -533,13 +616,16 @@ static int printf_to_env(void* env_pv, const char* format, ...) {
* Method: decode * Method: decode
* Signature: (Lsun/jvm/hotspot/asm/InstructionVisitor;J[BLjava/lang/String;J)V * Signature: (Lsun/jvm/hotspot/asm/InstructionVisitor;J[BLjava/lang/String;J)V
*/ */
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_asm_Disassembler_decode(JNIEnv * env, JNIEXPORT void JNICALL
Java_sun_jvm_hotspot_asm_Disassembler_decode(
JNIEnv * env,
jobject dis, jobject dis,
jobject visitor, jobject visitor,
jlong startPc, jlong startPc,
jbyteArray code, jbyteArray code,
jstring options_s, jstring options_s,
jlong decode_instructions_virtual) { jlong decode_instructions_virtual)
{
jboolean isCopy; jboolean isCopy;
jbyte* start = (*env)->GetByteArrayElements(env, code, &isCopy); jbyte* start = (*env)->GetByteArrayElements(env, code, &isCopy);
jbyte* end = start + (*env)->GetArrayLength(env, code); jbyte* end = start + (*env)->GetArrayLength(env, code);
......
...@@ -49,7 +49,7 @@ public interface BsdDebugger extends JVMDebugger { ...@@ -49,7 +49,7 @@ public interface BsdDebugger extends JVMDebugger {
public BsdAddress readCompKlassAddress(long address) throws DebuggerException; public BsdAddress readCompKlassAddress(long address) throws DebuggerException;
public BsdOopHandle readOopHandle(long address) throws DebuggerException; public BsdOopHandle readOopHandle(long address) throws DebuggerException;
public BsdOopHandle readCompOopHandle(long address) throws DebuggerException; public BsdOopHandle readCompOopHandle(long address) throws DebuggerException;
public long[] getThreadIntegerRegisterSet(int lwp_id) throws DebuggerException; public long[] getThreadIntegerRegisterSet(long unique_thread_id) throws DebuggerException;
public long getAddressValue(Address addr) throws DebuggerException; public long getAddressValue(Address addr) throws DebuggerException;
public Address newAddress(long value) throws DebuggerException; public Address newAddress(long value) throws DebuggerException;
......
...@@ -90,7 +90,7 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger { ...@@ -90,7 +90,7 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
throws DebuggerException; throws DebuggerException;
private native ClosestSymbol lookupByAddress0(long address) private native ClosestSymbol lookupByAddress0(long address)
throws DebuggerException; throws DebuggerException;
private native long[] getThreadIntegerRegisterSet0(int lwp_id) private native long[] getThreadIntegerRegisterSet0(long unique_thread_id)
throws DebuggerException; throws DebuggerException;
private native byte[] readBytesFromProcess0(long address, long numBytes) private native byte[] readBytesFromProcess0(long address, long numBytes)
throws DebuggerException; throws DebuggerException;
...@@ -400,10 +400,15 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger { ...@@ -400,10 +400,15 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
// //
/** From the ThreadAccess interface via Debugger and JVMDebugger */ /** From the ThreadAccess interface via Debugger and JVMDebugger */
public ThreadProxy getThreadForIdentifierAddress(Address threadIdAddr, Address uniqueThreadIdAddr) {
return new BsdThread(this, threadIdAddr, uniqueThreadIdAddr);
}
@Override
public ThreadProxy getThreadForIdentifierAddress(Address addr) { public ThreadProxy getThreadForIdentifierAddress(Address addr) {
return new BsdThread(this, addr); throw new RuntimeException("unimplemented");
} }
/** From the ThreadAccess interface via Debugger and JVMDebugger */ /** From the ThreadAccess interface via Debugger and JVMDebugger */
public ThreadProxy getThreadForThreadId(long id) { public ThreadProxy getThreadForThreadId(long id) {
return new BsdThread(this, id); return new BsdThread(this, id);
...@@ -455,22 +460,22 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger { ...@@ -455,22 +460,22 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
// Thread context access // Thread context access
// //
public synchronized long[] getThreadIntegerRegisterSet(int lwp_id) public synchronized long[] getThreadIntegerRegisterSet(long unique_thread_id)
throws DebuggerException { throws DebuggerException {
requireAttach(); requireAttach();
if (isCore) { if (isCore) {
return getThreadIntegerRegisterSet0(lwp_id); return getThreadIntegerRegisterSet0(unique_thread_id);
} else { } else {
class GetThreadIntegerRegisterSetTask implements WorkerThreadTask { class GetThreadIntegerRegisterSetTask implements WorkerThreadTask {
int lwp_id; long unique_thread_id;
long[] result; long[] result;
public void doit(BsdDebuggerLocal debugger) { public void doit(BsdDebuggerLocal debugger) {
result = debugger.getThreadIntegerRegisterSet0(lwp_id); result = debugger.getThreadIntegerRegisterSet0(unique_thread_id);
} }
} }
GetThreadIntegerRegisterSetTask task = new GetThreadIntegerRegisterSetTask(); GetThreadIntegerRegisterSetTask task = new GetThreadIntegerRegisterSetTask();
task.lwp_id = lwp_id; task.unique_thread_id = unique_thread_id;
workerThread.execute(task); workerThread.execute(task);
return task.result; return task.result;
} }
......
...@@ -28,21 +28,23 @@ import sun.jvm.hotspot.debugger.*; ...@@ -28,21 +28,23 @@ import sun.jvm.hotspot.debugger.*;
class BsdThread implements ThreadProxy { class BsdThread implements ThreadProxy {
private BsdDebugger debugger; private BsdDebugger debugger;
private int lwp_id; private int thread_id;
private long unique_thread_id;
/** The address argument must be the address of the _thread_id in the /** The address argument must be the address of the _thread_id in the
OSThread. It's value is result ::gettid() call. */ OSThread. It's value is result ::gettid() call. */
BsdThread(BsdDebugger debugger, Address addr) { BsdThread(BsdDebugger debugger, Address threadIdAddr, Address uniqueThreadIdAddr) {
this.debugger = debugger; this.debugger = debugger;
// FIXME: size of data fetched here should be configurable. // FIXME: size of data fetched here should be configurable.
// However, making it so would produce a dependency on the "types" // However, making it so would produce a dependency on the "types"
// package from the debugger package, which is not desired. // package from the debugger package, which is not desired.
this.lwp_id = (int) addr.getCIntegerAt(0, 4, true); this.thread_id = (int) threadIdAddr.getCIntegerAt(0, 4, true);
this.unique_thread_id = uniqueThreadIdAddr.getCIntegerAt(0, 8, true);
} }
BsdThread(BsdDebugger debugger, long id) { BsdThread(BsdDebugger debugger, long id) {
this.debugger = debugger; this.debugger = debugger;
this.lwp_id = (int) id; this.thread_id = (int) id;
} }
public boolean equals(Object obj) { public boolean equals(Object obj) {
...@@ -50,19 +52,19 @@ class BsdThread implements ThreadProxy { ...@@ -50,19 +52,19 @@ class BsdThread implements ThreadProxy {
return false; return false;
} }
return (((BsdThread) obj).lwp_id == lwp_id); return (((BsdThread) obj).thread_id == thread_id);
} }
public int hashCode() { public int hashCode() {
return lwp_id; return thread_id;
} }
public String toString() { public String toString() {
return Integer.toString(lwp_id); return Integer.toString(thread_id);
} }
public ThreadContext getContext() throws IllegalThreadStateException { public ThreadContext getContext() throws IllegalThreadStateException {
long[] data = debugger.getThreadIntegerRegisterSet(lwp_id); long[] data = debugger.getThreadIntegerRegisterSet(unique_thread_id);
ThreadContext context = BsdThreadContextFactory.createThreadContext(debugger); ThreadContext context = BsdThreadContextFactory.createThreadContext(debugger);
for (int i = 0; i < data.length; i++) { for (int i = 0; i < data.length; i++) {
context.setRegister(i, data[i]); context.setRegister(i, data[i]);
......
...@@ -28,6 +28,8 @@ import java.io.*; ...@@ -28,6 +28,8 @@ import java.io.*;
import java.util.*; import java.util.*;
import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.amd64.*; import sun.jvm.hotspot.debugger.amd64.*;
import sun.jvm.hotspot.debugger.bsd.BsdDebugger;
import sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal;
import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.runtime.amd64.*; import sun.jvm.hotspot.runtime.amd64.*;
import sun.jvm.hotspot.runtime.x86.*; import sun.jvm.hotspot.runtime.x86.*;
...@@ -38,8 +40,9 @@ public class BsdAMD64JavaThreadPDAccess implements JavaThreadPDAccess { ...@@ -38,8 +40,9 @@ public class BsdAMD64JavaThreadPDAccess implements JavaThreadPDAccess {
private static AddressField lastJavaFPField; private static AddressField lastJavaFPField;
private static AddressField osThreadField; private static AddressField osThreadField;
// Field from OSThread // Fields from OSThread
private static CIntegerField osThreadThreadIDField; private static CIntegerField osThreadThreadIDField;
private static CIntegerField osThreadUniqueThreadIDField;
// This is currently unneeded but is being kept in case we change // This is currently unneeded but is being kept in case we change
// the currentFrameGuess algorithm // the currentFrameGuess algorithm
...@@ -62,6 +65,7 @@ public class BsdAMD64JavaThreadPDAccess implements JavaThreadPDAccess { ...@@ -62,6 +65,7 @@ public class BsdAMD64JavaThreadPDAccess implements JavaThreadPDAccess {
Type osThreadType = db.lookupType("OSThread"); Type osThreadType = db.lookupType("OSThread");
osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id"); osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id");
osThreadUniqueThreadIDField = osThreadType.getCIntegerField("_unique_thread_id");
} }
public Address getLastJavaFP(Address addr) { public Address getLastJavaFP(Address addr) {
...@@ -125,8 +129,9 @@ public class BsdAMD64JavaThreadPDAccess implements JavaThreadPDAccess { ...@@ -125,8 +129,9 @@ public class BsdAMD64JavaThreadPDAccess implements JavaThreadPDAccess {
Address osThreadAddr = osThreadField.getValue(addr); Address osThreadAddr = osThreadField.getValue(addr);
// Get the address of the _thread_id from the OSThread // Get the address of the _thread_id from the OSThread
Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset()); Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
Address uniqueThreadIdAddr = osThreadAddr.addOffsetTo(osThreadUniqueThreadIDField.getOffset());
JVMDebugger debugger = VM.getVM().getDebugger(); BsdDebuggerLocal debugger = (BsdDebuggerLocal) VM.getVM().getDebugger();
return debugger.getThreadForIdentifierAddress(threadIdAddr); return debugger.getThreadForIdentifierAddress(threadIdAddr, uniqueThreadIdAddr);
} }
} }
...@@ -49,6 +49,11 @@ ...@@ -49,6 +49,11 @@
// (e.g. pthread_kill). // (e.g. pthread_kill).
pthread_t _pthread_id; pthread_t _pthread_id;
// This is the "thread_id" from struct thread_identifier_info. According to a
// comment in thread_info.h, this is a "system-wide unique 64-bit thread id".
// The value is used by SA to correlate threads.
uint64_t _unique_thread_id;
sigset_t _caller_sigmask; // Caller's signal mask sigset_t _caller_sigmask; // Caller's signal mask
public: public:
...@@ -77,6 +82,10 @@ ...@@ -77,6 +82,10 @@
_pthread_id = tid; _pthread_id = tid;
} }
void set_unique_thread_id(uint64_t id) {
_unique_thread_id = id;
}
// *************************************************************** // ***************************************************************
// suspension support. // suspension support.
// *************************************************************** // ***************************************************************
......
...@@ -657,6 +657,18 @@ extern "C" objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFu ...@@ -657,6 +657,18 @@ extern "C" objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFu
objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFunction = NULL; objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFunction = NULL;
#endif #endif
#ifdef __APPLE__
static uint64_t locate_unique_thread_id() {
// Additional thread_id used to correlate threads in SA
thread_identifier_info_data_t m_ident_info;
mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
thread_info(::mach_thread_self(), THREAD_IDENTIFIER_INFO,
(thread_info_t) &m_ident_info, &count);
return m_ident_info.thread_id;
}
#endif
// Thread start routine for all newly created threads // Thread start routine for all newly created threads
static void *java_start(Thread *thread) { static void *java_start(Thread *thread) {
// Try to randomize the cache line index of hot stack frames. // Try to randomize the cache line index of hot stack frames.
...@@ -685,6 +697,7 @@ static void *java_start(Thread *thread) { ...@@ -685,6 +697,7 @@ static void *java_start(Thread *thread) {
#ifdef __APPLE__ #ifdef __APPLE__
// thread_id is mach thread on macos // thread_id is mach thread on macos
osthread->set_thread_id(::mach_thread_self()); osthread->set_thread_id(::mach_thread_self());
osthread->set_unique_thread_id(locate_unique_thread_id());
#else #else
// thread_id is pthread_id on BSD // thread_id is pthread_id on BSD
osthread->set_thread_id(::pthread_self()); osthread->set_thread_id(::pthread_self());
...@@ -847,6 +860,7 @@ bool os::create_attached_thread(JavaThread* thread) { ...@@ -847,6 +860,7 @@ bool os::create_attached_thread(JavaThread* thread) {
// Store pthread info into the OSThread // Store pthread info into the OSThread
#ifdef __APPLE__ #ifdef __APPLE__
osthread->set_thread_id(::mach_thread_self()); osthread->set_thread_id(::mach_thread_self());
osthread->set_unique_thread_id(locate_unique_thread_id());
#else #else
osthread->set_thread_id(::pthread_self()); osthread->set_thread_id(::pthread_self());
#endif #endif
......
...@@ -35,17 +35,16 @@ ...@@ -35,17 +35,16 @@
/* Threads (NOTE: incomplete) */ \ /* Threads (NOTE: incomplete) */ \
/******************************/ \ /******************************/ \
nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \
nonstatic_field(OSThread, _pthread_id, pthread_t) nonstatic_field(OSThread, _unique_thread_id, uint64_t)
#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ #define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \
\ \
/**********************/ \ /**********************/ \
/* Posix Thread IDs */ \ /* Thread IDs */ \
/**********************/ \ /**********************/ \
\ \
declare_unsigned_integer_type(OSThread::thread_id_t) \ declare_unsigned_integer_type(OSThread::thread_id_t)
declare_unsigned_integer_type(pthread_t)
#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) #define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
......
/* /*
* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -402,8 +402,9 @@ oop ConstantPoolCacheEntry::method_type_if_resolved(constantPoolHandle cpool) { ...@@ -402,8 +402,9 @@ oop ConstantPoolCacheEntry::method_type_if_resolved(constantPoolHandle cpool) {
} }
#if INCLUDE_JVMTI
// RedefineClasses() API support: // RedefineClasses() API support:
// If this constantPoolCacheEntry refers to old_method then update it // If this ConstantPoolCacheEntry refers to old_method then update it
// to refer to new_method. // to refer to new_method.
bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method, bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
Method* new_method, bool * trace_name_printed) { Method* new_method, bool * trace_name_printed) {
...@@ -461,16 +462,24 @@ bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method, ...@@ -461,16 +462,24 @@ bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
return false; return false;
} }
#ifndef PRODUCT // a constant pool cache entry should never contain old or obsolete methods
bool ConstantPoolCacheEntry::check_no_old_entries() { bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() {
if (is_vfinal()) { if (is_vfinal()) {
// virtual and final so _f2 contains method ptr instead of vtable index
Metadata* f2 = (Metadata*)_f2; Metadata* f2 = (Metadata*)_f2;
return (f2->is_valid() && f2->is_method() && !((Method*)f2)->is_old()); // Return false if _f2 refers to an old or an obsolete method.
} else { // _f2 == NULL || !_f2->is_method() are just as unexpected here.
return (_f1 == NULL || (_f1->is_valid() && _f1->is_method() && !((Method*)_f1)->is_old())); return (f2 != NULL NOT_PRODUCT(&& f2->is_valid()) && f2->is_method() &&
!((Method*)f2)->is_old() && !((Method*)f2)->is_obsolete());
} else if (_f1 == NULL ||
(NOT_PRODUCT(_f1->is_valid() &&) !_f1->is_method())) {
// _f1 == NULL || !_f1->is_method() are OK here
return true;
} }
// return false if _f1 refers to an old or an obsolete method
return (NOT_PRODUCT(_f1->is_valid() &&) _f1->is_method() &&
!((Method*)_f1)->is_old() && !((Method*)_f1)->is_obsolete());
} }
#endif
bool ConstantPoolCacheEntry::is_interesting_method_entry(Klass* k) { bool ConstantPoolCacheEntry::is_interesting_method_entry(Klass* k) {
if (!is_method_entry()) { if (!is_method_entry()) {
...@@ -503,13 +512,15 @@ bool ConstantPoolCacheEntry::is_interesting_method_entry(Klass* k) { ...@@ -503,13 +512,15 @@ bool ConstantPoolCacheEntry::is_interesting_method_entry(Klass* k) {
// the method is in the interesting class so the entry is interesting // the method is in the interesting class so the entry is interesting
return true; return true;
} }
#endif // INCLUDE_JVMTI
void ConstantPoolCacheEntry::print(outputStream* st, int index) const { void ConstantPoolCacheEntry::print(outputStream* st, int index) const {
// print separator // print separator
if (index == 0) st->print_cr(" -------------"); if (index == 0) st->print_cr(" -------------");
// print entry // print entry
st->print("%3d ("PTR_FORMAT") ", index, (intptr_t)this); st->print("%3d ("PTR_FORMAT") ", index, (intptr_t)this);
st->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(), constant_pool_index()); st->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(),
constant_pool_index());
st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_f1); st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_f1);
st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_f2); st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_f2);
st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_flags); st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_flags);
...@@ -553,8 +564,9 @@ void ConstantPoolCache::initialize(intArray& inverse_index_map, intArray& invoke ...@@ -553,8 +564,9 @@ void ConstantPoolCache::initialize(intArray& inverse_index_map, intArray& invoke
} }
} }
#if INCLUDE_JVMTI
// RedefineClasses() API support: // RedefineClasses() API support:
// If any entry of this constantPoolCache points to any of // If any entry of this ConstantPoolCache points to any of
// old_methods, replace it with the corresponding new_method. // old_methods, replace it with the corresponding new_method.
void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new_methods, void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new_methods,
int methods_length, bool * trace_name_printed) { int methods_length, bool * trace_name_printed) {
...@@ -573,7 +585,7 @@ void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new ...@@ -573,7 +585,7 @@ void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new
continue; continue;
} }
// The constantPoolCache contains entries for several different // The ConstantPoolCache contains entries for several different
// things, but we only care about methods. In fact, we only care // things, but we only care about methods. In fact, we only care
// about methods in the same class as the one that contains the // about methods in the same class as the one that contains the
// old_methods. At this point, we have an interesting entry. // old_methods. At this point, we have an interesting entry.
...@@ -592,17 +604,25 @@ void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new ...@@ -592,17 +604,25 @@ void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new
} }
} }
#ifndef PRODUCT // the constant pool cache should never contain old or obsolete methods
bool ConstantPoolCache::check_no_old_entries() { bool ConstantPoolCache::check_no_old_or_obsolete_entries() {
for (int i = 1; i < length(); i++) { for (int i = 1; i < length(); i++) {
if (entry_at(i)->is_interesting_method_entry(NULL) && if (entry_at(i)->is_interesting_method_entry(NULL) &&
!entry_at(i)->check_no_old_entries()) { !entry_at(i)->check_no_old_or_obsolete_entries()) {
return false; return false;
} }
} }
return true; return true;
} }
#endif // PRODUCT
void ConstantPoolCache::dump_cache() {
for (int i = 1; i < length(); i++) {
if (entry_at(i)->is_interesting_method_entry(NULL)) {
entry_at(i)->print(tty, i);
}
}
}
#endif // INCLUDE_JVMTI
// Printing // Printing
......
/* /*
* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -337,16 +337,18 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { ...@@ -337,16 +337,18 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
static ByteSize f2_offset() { return byte_offset_of(ConstantPoolCacheEntry, _f2); } static ByteSize f2_offset() { return byte_offset_of(ConstantPoolCacheEntry, _f2); }
static ByteSize flags_offset() { return byte_offset_of(ConstantPoolCacheEntry, _flags); } static ByteSize flags_offset() { return byte_offset_of(ConstantPoolCacheEntry, _flags); }
#if INCLUDE_JVMTI
// RedefineClasses() API support: // RedefineClasses() API support:
// If this constantPoolCacheEntry refers to old_method then update it // If this ConstantPoolCacheEntry refers to old_method then update it
// to refer to new_method. // to refer to new_method.
// trace_name_printed is set to true if the current call has // trace_name_printed is set to true if the current call has
// printed the klass name so that other routines in the adjust_* // printed the klass name so that other routines in the adjust_*
// group don't print the klass name. // group don't print the klass name.
bool adjust_method_entry(Method* old_method, Method* new_method, bool adjust_method_entry(Method* old_method, Method* new_method,
bool * trace_name_printed); bool * trace_name_printed);
NOT_PRODUCT(bool check_no_old_entries();) bool check_no_old_or_obsolete_entries();
bool is_interesting_method_entry(Klass* k); bool is_interesting_method_entry(Klass* k);
#endif // INCLUDE_JVMTI
// Debugging & Printing // Debugging & Printing
void print (outputStream* st, int index) const; void print (outputStream* st, int index) const;
...@@ -423,15 +425,18 @@ class ConstantPoolCache: public MetaspaceObj { ...@@ -423,15 +425,18 @@ class ConstantPoolCache: public MetaspaceObj {
return (base_offset() + ConstantPoolCacheEntry::size_in_bytes() * index); return (base_offset() + ConstantPoolCacheEntry::size_in_bytes() * index);
} }
#if INCLUDE_JVMTI
// RedefineClasses() API support: // RedefineClasses() API support:
// If any entry of this constantPoolCache points to any of // If any entry of this ConstantPoolCache points to any of
// old_methods, replace it with the corresponding new_method. // old_methods, replace it with the corresponding new_method.
// trace_name_printed is set to true if the current call has // trace_name_printed is set to true if the current call has
// printed the klass name so that other routines in the adjust_* // printed the klass name so that other routines in the adjust_*
// group don't print the klass name. // group don't print the klass name.
void adjust_method_entries(Method** old_methods, Method** new_methods, void adjust_method_entries(Method** old_methods, Method** new_methods,
int methods_length, bool * trace_name_printed); int methods_length, bool * trace_name_printed);
NOT_PRODUCT(bool check_no_old_entries();) bool check_no_old_or_obsolete_entries();
void dump_cache();
#endif // INCLUDE_JVMTI
// Deallocate - no fields to deallocate // Deallocate - no fields to deallocate
DEBUG_ONLY(bool on_stack() { return false; }) DEBUG_ONLY(bool on_stack() { return false; })
......
/* /*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -610,6 +610,7 @@ void klassVtable::copy_vtable_to(vtableEntry* start) { ...@@ -610,6 +610,7 @@ void klassVtable::copy_vtable_to(vtableEntry* start) {
Copy::disjoint_words((HeapWord*)table(), (HeapWord*)start, _length * vtableEntry::size()); Copy::disjoint_words((HeapWord*)table(), (HeapWord*)start, _length * vtableEntry::size());
} }
#if INCLUDE_JVMTI
void klassVtable::adjust_method_entries(Method** old_methods, Method** new_methods, void klassVtable::adjust_method_entries(Method** old_methods, Method** new_methods,
int methods_length, bool * trace_name_printed) { int methods_length, bool * trace_name_printed) {
// search the vtable for uses of either obsolete or EMCP methods // search the vtable for uses of either obsolete or EMCP methods
...@@ -638,11 +639,39 @@ void klassVtable::adjust_method_entries(Method** old_methods, Method** new_metho ...@@ -638,11 +639,39 @@ void klassVtable::adjust_method_entries(Method** old_methods, Method** new_metho
new_method->name()->as_C_string(), new_method->name()->as_C_string(),
new_method->signature()->as_C_string())); new_method->signature()->as_C_string()));
} }
// cannot 'break' here; see for-loop comment above.
} }
} }
} }
} }
// a vtable should never contain old or obsolete methods
bool klassVtable::check_no_old_or_obsolete_entries() {
for (int i = 0; i < length(); i++) {
Method* m = unchecked_method_at(i);
if (m != NULL &&
(NOT_PRODUCT(!m->is_valid() ||) m->is_old() || m->is_obsolete())) {
return false;
}
}
return true;
}
void klassVtable::dump_vtable() {
tty->print_cr("vtable dump --");
for (int i = 0; i < length(); i++) {
Method* m = unchecked_method_at(i);
if (m != NULL) {
tty->print(" (%5d) ", i);
m->access_flags().print_on(tty);
tty->print(" -- ");
m->print_name(tty);
tty->cr();
}
}
}
#endif // INCLUDE_JVMTI
// CDS/RedefineClasses support - clear vtables so they can be reinitialized // CDS/RedefineClasses support - clear vtables so they can be reinitialized
void klassVtable::clear_vtable() { void klassVtable::clear_vtable() {
for (int i = 0; i < _length; i++) table()[i].clear(); for (int i = 0; i < _length; i++) table()[i].clear();
...@@ -805,6 +834,7 @@ void klassItable::initialize_with_method(Method* m) { ...@@ -805,6 +834,7 @@ void klassItable::initialize_with_method(Method* m) {
} }
} }
#if INCLUDE_JVMTI
void klassItable::adjust_method_entries(Method** old_methods, Method** new_methods, void klassItable::adjust_method_entries(Method** old_methods, Method** new_methods,
int methods_length, bool * trace_name_printed) { int methods_length, bool * trace_name_printed) {
// search the itable for uses of either obsolete or EMCP methods // search the itable for uses of either obsolete or EMCP methods
...@@ -833,13 +863,44 @@ void klassItable::adjust_method_entries(Method** old_methods, Method** new_metho ...@@ -833,13 +863,44 @@ void klassItable::adjust_method_entries(Method** old_methods, Method** new_metho
new_method->name()->as_C_string(), new_method->name()->as_C_string(),
new_method->signature()->as_C_string())); new_method->signature()->as_C_string()));
} }
// Cannot break because there might be another entry for this method // cannot 'break' here; see for-loop comment above.
} }
ime++; ime++;
} }
} }
} }
// an itable should never contain old or obsolete methods
bool klassItable::check_no_old_or_obsolete_entries() {
itableMethodEntry* ime = method_entry(0);
for (int i = 0; i < _size_method_table; i++) {
Method* m = ime->method();
if (m != NULL &&
(NOT_PRODUCT(!m->is_valid() ||) m->is_old() || m->is_obsolete())) {
return false;
}
ime++;
}
return true;
}
void klassItable::dump_itable() {
itableMethodEntry* ime = method_entry(0);
tty->print_cr("itable dump --");
for (int i = 0; i < _size_method_table; i++) {
Method* m = ime->method();
if (m != NULL) {
tty->print(" (%5d) ", i);
m->access_flags().print_on(tty);
tty->print(" -- ");
m->print_name(tty);
tty->cr();
}
ime++;
}
}
#endif // INCLUDE_JVMTI
// Setup // Setup
class InterfaceVisiterClosure : public StackObj { class InterfaceVisiterClosure : public StackObj {
...@@ -1126,43 +1187,6 @@ void klassVtable::print_statistics() { ...@@ -1126,43 +1187,6 @@ void klassVtable::print_statistics() {
tty->print_cr("%6d bytes total", total); tty->print_cr("%6d bytes total", total);
} }
bool klassVtable::check_no_old_entries() {
// Check that there really is no entry
for (int i = 0; i < length(); i++) {
Method* m = unchecked_method_at(i);
if (m != NULL) {
if (!m->is_valid() || m->is_old()) {
return false;
}
}
}
return true;
}
void klassVtable::dump_vtable() {
tty->print_cr("vtable dump --");
for (int i = 0; i < length(); i++) {
Method* m = unchecked_method_at(i);
if (m != NULL) {
tty->print(" (%5d) ", i);
m->access_flags().print_on(tty);
tty->print(" -- ");
m->print_name(tty);
tty->cr();
}
}
}
bool klassItable::check_no_old_entries() {
itableMethodEntry* ime = method_entry(0);
for(int i = 0; i < _size_method_table; i++) {
Method* m = ime->method();
if (m != NULL && (!m->is_valid() || m->is_old())) return false;
ime++;
}
return true;
}
int klassItable::_total_classes; // Total no. of classes with itables int klassItable::_total_classes; // Total no. of classes with itables
long klassItable::_total_size; // Total no. of bytes used for itables long klassItable::_total_size; // Total no. of bytes used for itables
......
/* /*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -90,6 +90,7 @@ class klassVtable : public ResourceObj { ...@@ -90,6 +90,7 @@ class klassVtable : public ResourceObj {
Array<Method*>* methods, AccessFlags class_flags, Handle classloader, Array<Method*>* methods, AccessFlags class_flags, Handle classloader,
Symbol* classname, Array<Klass*>* local_interfaces, TRAPS); Symbol* classname, Array<Klass*>* local_interfaces, TRAPS);
#if INCLUDE_JVMTI
// RedefineClasses() API support: // RedefineClasses() API support:
// If any entry of this vtable points to any of old_methods, // If any entry of this vtable points to any of old_methods,
// replace it with the corresponding new_method. // replace it with the corresponding new_method.
...@@ -98,17 +99,15 @@ class klassVtable : public ResourceObj { ...@@ -98,17 +99,15 @@ class klassVtable : public ResourceObj {
// group don't print the klass name. // group don't print the klass name.
void adjust_method_entries(Method** old_methods, Method** new_methods, void adjust_method_entries(Method** old_methods, Method** new_methods,
int methods_length, bool * trace_name_printed); int methods_length, bool * trace_name_printed);
bool check_no_old_or_obsolete_entries();
void dump_vtable();
#endif // INCLUDE_JVMTI
// Debugging code // Debugging code
void print() PRODUCT_RETURN; void print() PRODUCT_RETURN;
void verify(outputStream* st, bool force = false); void verify(outputStream* st, bool force = false);
static void print_statistics() PRODUCT_RETURN; static void print_statistics() PRODUCT_RETURN;
#ifndef PRODUCT
bool check_no_old_entries();
void dump_vtable();
#endif
protected: protected:
friend class vtableEntry; friend class vtableEntry;
private: private:
...@@ -275,6 +274,7 @@ class klassItable : public ResourceObj { ...@@ -275,6 +274,7 @@ class klassItable : public ResourceObj {
// Updates // Updates
void initialize_with_method(Method* m); void initialize_with_method(Method* m);
#if INCLUDE_JVMTI
// RedefineClasses() API support: // RedefineClasses() API support:
// if any entry of this itable points to any of old_methods, // if any entry of this itable points to any of old_methods,
// replace it with the corresponding new_method. // replace it with the corresponding new_method.
...@@ -283,6 +283,9 @@ class klassItable : public ResourceObj { ...@@ -283,6 +283,9 @@ class klassItable : public ResourceObj {
// group don't print the klass name. // group don't print the klass name.
void adjust_method_entries(Method** old_methods, Method** new_methods, void adjust_method_entries(Method** old_methods, Method** new_methods,
int methods_length, bool * trace_name_printed); int methods_length, bool * trace_name_printed);
bool check_no_old_or_obsolete_entries();
void dump_itable();
#endif // INCLUDE_JVMTI
// Setup of itable // Setup of itable
static int compute_itable_size(Array<Klass*>* transitive_interfaces); static int compute_itable_size(Array<Klass*>* transitive_interfaces);
...@@ -307,11 +310,6 @@ class klassItable : public ResourceObj { ...@@ -307,11 +310,6 @@ class klassItable : public ResourceObj {
NOT_PRODUCT(static long _total_size;) // Total no. of bytes used for itables NOT_PRODUCT(static long _total_size;) // Total no. of bytes used for itables
static void update_stats(int size) PRODUCT_RETURN NOT_PRODUCT({ _total_classes++; _total_size += size; }) static void update_stats(int size) PRODUCT_RETURN NOT_PRODUCT({ _total_classes++; _total_size += size; })
public:
#ifndef PRODUCT
bool check_no_old_entries();
#endif
}; };
#endif // SHARE_VM_OOPS_KLASSVTABLE_HPP #endif // SHARE_VM_OOPS_KLASSVTABLE_HPP
...@@ -1393,9 +1393,9 @@ void Method::sort_methods(Array<Method*>* methods, ...@@ -1393,9 +1393,9 @@ void Method::sort_methods(Array<Method*>* methods,
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
// Non-product code // Non-product code unless JVM/TI needs it
#ifndef PRODUCT #if !defined(PRODUCT) || INCLUDE_JVMTI
class SignatureTypePrinter : public SignatureTypeNames { class SignatureTypePrinter : public SignatureTypeNames {
private: private:
outputStream* _st; outputStream* _st;
...@@ -1430,8 +1430,13 @@ void Method::print_name(outputStream* st) { ...@@ -1430,8 +1430,13 @@ void Method::print_name(outputStream* st) {
sig.print_parameters(); sig.print_parameters();
st->print(")"); st->print(")");
} }
#endif // !PRODUCT || INCLUDE_JVMTI
//-----------------------------------------------------------------------------------
// Non-product code
#ifndef PRODUCT
void Method::print_codes_on(outputStream* st) const { void Method::print_codes_on(outputStream* st) const {
print_codes_on(0, code_size(), st); print_codes_on(0, code_size(), st);
} }
......
...@@ -800,8 +800,12 @@ class Method : public Metadata { ...@@ -800,8 +800,12 @@ class Method : public Metadata {
static bool has_unloaded_classes_in_signature(methodHandle m, TRAPS); static bool has_unloaded_classes_in_signature(methodHandle m, TRAPS);
// Printing // Printing
void print_short_name(outputStream* st = tty) /*PRODUCT_RETURN*/; // prints as klassname::methodname; Exposed so field engineers can debug VM void print_short_name(outputStream* st = tty); // prints as klassname::methodname; Exposed so field engineers can debug VM
#if INCLUDE_JVMTI
void print_name(outputStream* st = tty); // prints as "virtual void foo(int)"; exposed for TraceRedefineClasses
#else
void print_name(outputStream* st = tty) PRODUCT_RETURN; // prints as "virtual void foo(int)" void print_name(outputStream* st = tty) PRODUCT_RETURN; // prints as "virtual void foo(int)"
#endif
// Helper routine used for method sorting // Helper routine used for method sorting
static void sort_methods(Array<Method*>* methods, static void sort_methods(Array<Method*>* methods,
......
...@@ -154,8 +154,15 @@ void VM_RedefineClasses::doit() { ...@@ -154,8 +154,15 @@ void VM_RedefineClasses::doit() {
// See jvmtiExport.hpp for detailed explanation. // See jvmtiExport.hpp for detailed explanation.
JvmtiExport::set_has_redefined_a_class(); JvmtiExport::set_has_redefined_a_class();
#ifdef ASSERT // check_class() is optionally called for product bits, but is
// always called for non-product bits.
#ifdef PRODUCT
if (RC_TRACE_ENABLED(0x00004000)) {
#endif
RC_TRACE_WITH_THREAD(0x00004000, thread, ("calling check_class"));
SystemDictionary::classes_do(check_class, thread); SystemDictionary::classes_do(check_class, thread);
#ifdef PRODUCT
}
#endif #endif
} }
...@@ -1564,9 +1571,9 @@ void VM_RedefineClasses::rewrite_cp_refs_in_method(methodHandle method, ...@@ -1564,9 +1571,9 @@ void VM_RedefineClasses::rewrite_cp_refs_in_method(methodHandle method,
bcp, cp_index, new_index)); bcp, cp_index, new_index));
// Rewriter::rewrite_method() uses put_native_u2() in this // Rewriter::rewrite_method() uses put_native_u2() in this
// situation because it is reusing the constant pool index // situation because it is reusing the constant pool index
// location for a native index into the constantPoolCache. // location for a native index into the ConstantPoolCache.
// Since we are updating the constant pool index prior to // Since we are updating the constant pool index prior to
// verification and constantPoolCache initialization, we // verification and ConstantPoolCache initialization, we
// need to keep the new index in Java byte order. // need to keep the new index in Java byte order.
Bytes::put_Java_u2(p, new_index); Bytes::put_Java_u2(p, new_index);
} }
...@@ -3371,7 +3378,6 @@ void VM_RedefineClasses::increment_class_counter(InstanceKlass *ik, TRAPS) { ...@@ -3371,7 +3378,6 @@ void VM_RedefineClasses::increment_class_counter(InstanceKlass *ik, TRAPS) {
} }
} }
#ifndef PRODUCT
void VM_RedefineClasses::check_class(Klass* k_oop, void VM_RedefineClasses::check_class(Klass* k_oop,
ClassLoaderData* initiating_loader, ClassLoaderData* initiating_loader,
TRAPS) { TRAPS) {
...@@ -3379,82 +3385,110 @@ void VM_RedefineClasses::check_class(Klass* k_oop, ...@@ -3379,82 +3385,110 @@ void VM_RedefineClasses::check_class(Klass* k_oop,
if (k->oop_is_instance()) { if (k->oop_is_instance()) {
HandleMark hm(THREAD); HandleMark hm(THREAD);
InstanceKlass *ik = (InstanceKlass *) k; InstanceKlass *ik = (InstanceKlass *) k;
bool no_old_methods = true; // be optimistic
if (ik->vtable_length() > 0) {
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
if (!ik->vtable()->check_no_old_entries()) {
tty->print_cr("klassVtable::check_no_old_entries failure -- OLD method found -- class: %s", ik->signature_name()); // a vtable should never contain old or obsolete methods
if (ik->vtable_length() > 0 &&
!ik->vtable()->check_no_old_or_obsolete_entries()) {
if (RC_TRACE_ENABLED(0x00004000)) {
RC_TRACE_WITH_THREAD(0x00004000, THREAD,
("klassVtable::check_no_old_or_obsolete_entries failure"
" -- OLD or OBSOLETE method found -- class: %s",
ik->signature_name()));
ik->vtable()->dump_vtable(); ik->vtable()->dump_vtable();
assert(false, "OLD method found");
} }
no_old_methods = false;
} }
if (ik->itable_length() > 0) {
ResourceMark rm(THREAD); // an itable should never contain old or obsolete methods
if (!ik->itable()->check_no_old_entries()) { if (ik->itable_length() > 0 &&
tty->print_cr("klassItable::check_no_old_entries failure -- OLD method found -- class: %s", ik->signature_name()); !ik->itable()->check_no_old_or_obsolete_entries()) {
assert(false, "OLD method found"); if (RC_TRACE_ENABLED(0x00004000)) {
RC_TRACE_WITH_THREAD(0x00004000, THREAD,
("klassItable::check_no_old_or_obsolete_entries failure"
" -- OLD or OBSOLETE method found -- class: %s",
ik->signature_name()));
ik->itable()->dump_itable();
} }
no_old_methods = false;
} }
// Check that the constant pool cache has no deleted entries.
// the constant pool cache should never contain old or obsolete methods
if (ik->constants() != NULL && if (ik->constants() != NULL &&
ik->constants()->cache() != NULL && ik->constants()->cache() != NULL &&
!ik->constants()->cache()->check_no_old_entries()) { !ik->constants()->cache()->check_no_old_or_obsolete_entries()) {
tty->print_cr("klassVtable::check_no_old_entries failure -- OLD method found -- class: %s", ik->signature_name()); if (RC_TRACE_ENABLED(0x00004000)) {
assert(false, "OLD method found"); RC_TRACE_WITH_THREAD(0x00004000, THREAD,
("cp-cache::check_no_old_or_obsolete_entries failure"
" -- OLD or OBSOLETE method found -- class: %s",
ik->signature_name()));
ik->constants()->cache()->dump_cache();
}
no_old_methods = false;
}
if (!no_old_methods) {
if (RC_TRACE_ENABLED(0x00004000)) {
dump_methods();
} else {
tty->print_cr("INFO: use the '-XX:TraceRedefineClasses=16384' option "
"to see more info about the following guarantee() failure.");
}
guarantee(false, "OLD and/or OBSOLETE method(s) found");
} }
} }
} }
void VM_RedefineClasses::dump_methods() { void VM_RedefineClasses::dump_methods() {
int j; int j;
tty->print_cr("_old_methods --"); RC_TRACE(0x00004000, ("_old_methods --"));
for (j = 0; j < _old_methods->length(); ++j) { for (j = 0; j < _old_methods->length(); ++j) {
Method* m = _old_methods->at(j); Method* m = _old_methods->at(j);
tty->print("%4d (%5d) ", j, m->vtable_index()); RC_TRACE_NO_CR(0x00004000, ("%4d (%5d) ", j, m->vtable_index()));
m->access_flags().print_on(tty); m->access_flags().print_on(tty);
tty->print(" -- "); tty->print(" -- ");
m->print_name(tty); m->print_name(tty);
tty->cr(); tty->cr();
} }
tty->print_cr("_new_methods --"); RC_TRACE(0x00004000, ("_new_methods --"));
for (j = 0; j < _new_methods->length(); ++j) { for (j = 0; j < _new_methods->length(); ++j) {
Method* m = _new_methods->at(j); Method* m = _new_methods->at(j);
tty->print("%4d (%5d) ", j, m->vtable_index()); RC_TRACE_NO_CR(0x00004000, ("%4d (%5d) ", j, m->vtable_index()));
m->access_flags().print_on(tty); m->access_flags().print_on(tty);
tty->print(" -- "); tty->print(" -- ");
m->print_name(tty); m->print_name(tty);
tty->cr(); tty->cr();
} }
tty->print_cr("_matching_(old/new)_methods --"); RC_TRACE(0x00004000, ("_matching_(old/new)_methods --"));
for (j = 0; j < _matching_methods_length; ++j) { for (j = 0; j < _matching_methods_length; ++j) {
Method* m = _matching_old_methods[j]; Method* m = _matching_old_methods[j];
tty->print("%4d (%5d) ", j, m->vtable_index()); RC_TRACE_NO_CR(0x00004000, ("%4d (%5d) ", j, m->vtable_index()));
m->access_flags().print_on(tty); m->access_flags().print_on(tty);
tty->print(" -- "); tty->print(" -- ");
m->print_name(tty); m->print_name(tty);
tty->cr(); tty->cr();
m = _matching_new_methods[j]; m = _matching_new_methods[j];
tty->print(" (%5d) ", m->vtable_index()); RC_TRACE_NO_CR(0x00004000, (" (%5d) ", m->vtable_index()));
m->access_flags().print_on(tty); m->access_flags().print_on(tty);
tty->cr(); tty->cr();
} }
tty->print_cr("_deleted_methods --"); RC_TRACE(0x00004000, ("_deleted_methods --"));
for (j = 0; j < _deleted_methods_length; ++j) { for (j = 0; j < _deleted_methods_length; ++j) {
Method* m = _deleted_methods[j]; Method* m = _deleted_methods[j];
tty->print("%4d (%5d) ", j, m->vtable_index()); RC_TRACE_NO_CR(0x00004000, ("%4d (%5d) ", j, m->vtable_index()));
m->access_flags().print_on(tty); m->access_flags().print_on(tty);
tty->print(" -- "); tty->print(" -- ");
m->print_name(tty); m->print_name(tty);
tty->cr(); tty->cr();
} }
tty->print_cr("_added_methods --"); RC_TRACE(0x00004000, ("_added_methods --"));
for (j = 0; j < _added_methods_length; ++j) { for (j = 0; j < _added_methods_length; ++j) {
Method* m = _added_methods[j]; Method* m = _added_methods[j];
tty->print("%4d (%5d) ", j, m->vtable_index()); RC_TRACE_NO_CR(0x00004000, ("%4d (%5d) ", j, m->vtable_index()));
m->access_flags().print_on(tty); m->access_flags().print_on(tty);
tty->print(" -- "); tty->print(" -- ");
m->print_name(tty); m->print_name(tty);
tty->cr(); tty->cr();
} }
} }
#endif
...@@ -468,9 +468,9 @@ class VM_RedefineClasses: public VM_Operation { ...@@ -468,9 +468,9 @@ class VM_RedefineClasses: public VM_Operation {
void flush_dependent_code(instanceKlassHandle k_h, TRAPS); void flush_dependent_code(instanceKlassHandle k_h, TRAPS);
static void check_class(Klass* k_oop, ClassLoaderData* initiating_loader, TRAPS) PRODUCT_RETURN; static void check_class(Klass* k_oop, ClassLoaderData* initiating_loader,
TRAPS);
static void dump_methods() PRODUCT_RETURN; static void dump_methods();
public: public:
VM_RedefineClasses(jint class_count, VM_RedefineClasses(jint class_count,
......
/* /*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
// 0x00000800 | 2048 - previous class breakpoint mgmt // 0x00000800 | 2048 - previous class breakpoint mgmt
// 0x00001000 | 4096 - detect calls to obsolete methods // 0x00001000 | 4096 - detect calls to obsolete methods
// 0x00002000 | 8192 - fail a guarantee() in addition to detection // 0x00002000 | 8192 - fail a guarantee() in addition to detection
// 0x00004000 | 16384 - unused // 0x00004000 | 16384 - detect old/obsolete methods in metadata
// 0x00008000 | 32768 - old/new method matching/add/delete // 0x00008000 | 32768 - old/new method matching/add/delete
// 0x00010000 | 65536 - impl details: CP size info // 0x00010000 | 65536 - impl details: CP size info
// 0x00020000 | 131072 - impl details: CP merge pass info // 0x00020000 | 131072 - impl details: CP merge pass info
...@@ -82,6 +82,13 @@ ...@@ -82,6 +82,13 @@
tty->print_cr args; \ tty->print_cr args; \
} while (0) } while (0)
#define RC_TRACE_NO_CR(level, args) \
if ((TraceRedefineClasses & level) != 0) { \
ResourceMark rm; \
tty->print("RedefineClasses-0x%x: ", level); \
tty->print args; \
} while (0)
#define RC_TRACE_WITH_THREAD(level, thread, args) \ #define RC_TRACE_WITH_THREAD(level, thread, args) \
if ((TraceRedefineClasses & level) != 0) { \ if ((TraceRedefineClasses & level) != 0) { \
ResourceMark rm(thread); \ ResourceMark rm(thread); \
......
/* /*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -59,7 +59,7 @@ void AccessFlags::atomic_clear_bits(jint bits) { ...@@ -59,7 +59,7 @@ void AccessFlags::atomic_clear_bits(jint bits) {
} while(f != old_flags); } while(f != old_flags);
} }
#ifndef PRODUCT #if !defined(PRODUCT) || INCLUDE_JVMTI
void AccessFlags::print_on(outputStream* st) const { void AccessFlags::print_on(outputStream* st) const {
if (is_public ()) st->print("public " ); if (is_public ()) st->print("public " );
...@@ -80,7 +80,7 @@ void AccessFlags::print_on(outputStream* st) const { ...@@ -80,7 +80,7 @@ void AccessFlags::print_on(outputStream* st) const {
if (on_stack ()) st->print("{on_stack} " ); if (on_stack ()) st->print("{on_stack} " );
} }
#endif #endif // !PRODUCT || INCLUDE_JVMTI
void accessFlags_init() { void accessFlags_init() {
assert(sizeof(AccessFlags) == sizeof(jint), "just checking size of flags"); assert(sizeof(AccessFlags) == sizeof(jint), "just checking size of flags");
......
/* /*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -239,7 +239,11 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC { ...@@ -239,7 +239,11 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC {
inline friend AccessFlags accessFlags_from(jint flags); inline friend AccessFlags accessFlags_from(jint flags);
// Printing/debugging // Printing/debugging
#if INCLUDE_JVMTI
void print_on(outputStream* st) const;
#else
void print_on(outputStream* st) const PRODUCT_RETURN; void print_on(outputStream* st) const PRODUCT_RETURN;
#endif
}; };
inline AccessFlags accessFlags_from(jint flags) { inline AccessFlags accessFlags_from(jint flags) {
......
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006298
* @summary Setting an invalid value for a bool argument should result in a useful error message
* @library /testlibrary
*/
import com.oracle.java.testlibrary.*;
public class BooleanFlagWithInvalidValue {
public static void main(String[] args) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:+UseLargePages=8", "-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("Improperly specified VM option 'UseLargePages=8'");
output.shouldHaveExitValue(1);
pb = ProcessTools.createJavaProcessBuilder(
"-XX:-UseLargePages=8", "-version");
output = new OutputAnalyzer(pb.start());
output.shouldContain("Improperly specified VM option 'UseLargePages=8'");
output.shouldHaveExitValue(1);
}
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006298
* @summary Setting a flag to an invalid value should print a useful error message
* @library /testlibrary
*/
import com.oracle.java.testlibrary.*;
public class FlagWithInvalidValue {
public static void main(String[] args) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:ObjectAlignmentInBytes=v", "-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("Improperly specified VM option 'ObjectAlignmentInBytes=v'");
output.shouldHaveExitValue(1);
}
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006298
* @summary Using a bool (+/-) prefix on non-bool flag should result in a useful error message
* @library /testlibrary
*/
import com.oracle.java.testlibrary.*;
public class NonBooleanFlagWithInvalidBooleanPrefix {
public static void main(String[] args) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:-ObjectAlignmentInBytes=16", "-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("Unexpected +/- setting in VM option 'ObjectAlignmentInBytes=16'");
output.shouldHaveExitValue(1);
pb = ProcessTools.createJavaProcessBuilder(
"-XX:+ObjectAlignmentInBytes=16", "-version");
output = new OutputAnalyzer(pb.start());
output.shouldContain("Unexpected +/- setting in VM option 'ObjectAlignmentInBytes=16'");
output.shouldHaveExitValue(1);
}
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8006298
* @summary Using an unrecognized VM option should print the name of the option
* @library /testlibrary
*/
import com.oracle.java.testlibrary.*;
public class UnrecognizedVMOption {
public static void main(String[] args) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:bogus_option", "-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("Unrecognized VM option 'bogus_option'");
output.shouldHaveExitValue(1);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册