6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
Summary: Remove incorrect optimization in klassItable::adjust_method_entries(). Add RedefineClasses() tracing support for obsolete method entry.
Reviewed-by: acorn, swamyv
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Mon Mar 02 14:00:23 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Mon Mar 02 14:03:03 2009 -0700
@@ -2465,7 +2465,10 @@
// InterpreterRuntime::post_method_entry();
// }
// if (DTraceMethodProbes) {
-// SharedRuntime::dtrace_method_entry(method, reciever);
+// SharedRuntime::dtrace_method_entry(method, receiver);
+// }
+// if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
+// SharedRuntime::rc_trace_method_entry(method, receiver);
// }
void InterpreterMacroAssembler::notify_method_entry() {
@@ -2497,6 +2500,13 @@
CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry),
G2_thread, Lmethod);
}
+
+ // RedefineClasses() tracing support for obsolete method entry
+ if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
+ call_VM_leaf(noreg,
+ CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
+ G2_thread, Lmethod);
+ }
}
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Mon Mar 02 14:00:23 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Mon Mar 02 14:03:03 2009 -0700
@@ -2161,6 +2161,18 @@
__ restore();
}
+ // RedefineClasses() tracing support for obsolete method entry
+ if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
+ // create inner frame
+ __ save_frame(0);
+ __ mov(G2_thread, L7_thread_cache);
+ __ set_oop_constant(JNIHandles::make_local(method()), O1);
+ __ call_VM_leaf(L7_thread_cache,
+ CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
+ G2_thread, O1);
+ __ restore();
+ }
+
// We are in the jni frame unless saved_frame is true in which case
// we are in one frame deeper (the "inner" frame). If we are in the
// "inner" frames the args are in the Iregs and if the jni frame then
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp Mon Mar 02 14:00:23 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp Mon Mar 02 14:03:03 2009 -0700
@@ -1512,6 +1512,15 @@
call_VM_leaf(
CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), rcx, rbx);
}
+
+ // RedefineClasses() tracing support for obsolete method entry
+ if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
+ get_thread(rcx);
+ get_method(rbx);
+ call_VM_leaf(
+ CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
+ rcx, rbx);
+ }
}
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp Mon Mar 02 14:00:23 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp Mon Mar 02 14:03:03 2009 -0700
@@ -1593,6 +1593,14 @@
call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry),
r15_thread, c_rarg1);
}
+
+ // RedefineClasses() tracing support for obsolete method entry
+ if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
+ get_method(c_rarg1);
+ call_VM_leaf(
+ CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
+ r15_thread, c_rarg1);
+ }
}
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Mon Mar 02 14:00:23 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Mon Mar 02 14:03:03 2009 -0700
@@ -1532,6 +1532,14 @@
thread, rax);
}
+ // RedefineClasses() tracing support for obsolete method entry
+ if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
+ __ movoop(rax, JNIHandles::make_local(method()));
+ __ call_VM_leaf(
+ CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
+ thread, rax);
+ }
+
// These are register definitions we need for locking/unlocking
const Register swap_reg = rax; // Must use rax, for cmpxchg instruction
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Mon Mar 02 14:00:23 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Mon Mar 02 14:03:03 2009 -0700
@@ -1506,6 +1506,17 @@
restore_args(masm, total_c_args, c_arg, out_regs);
}
+ // RedefineClasses() tracing support for obsolete method entry
+ if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
+ // protect the args we've loaded
+ save_args(masm, total_c_args, c_arg, out_regs);
+ __ movoop(c_rarg1, JNIHandles::make_local(method()));
+ __ call_VM_leaf(
+ CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
+ r15_thread, c_rarg1);
+ restore_args(masm, total_c_args, c_arg, out_regs);
+ }
+
// Lock a synchronized method
// Register definitions used by locking and unlocking
--- a/hotspot/src/share/vm/includeDB_core Mon Mar 02 14:00:23 2009 -0700
+++ b/hotspot/src/share/vm/includeDB_core Mon Mar 02 14:03:03 2009 -0700
@@ -2093,6 +2093,7 @@
interp_masm_<arch_model>.cpp interpreterRuntime.hpp
interp_masm_<arch_model>.cpp interpreter.hpp
interp_masm_<arch_model>.cpp jvmtiExport.hpp
+interp_masm_<arch_model>.cpp jvmtiRedefineClassesTrace.hpp
interp_masm_<arch_model>.cpp jvmtiThreadState.hpp
interp_masm_<arch_model>.cpp markOop.hpp
interp_masm_<arch_model>.cpp methodDataOop.hpp
@@ -3669,6 +3670,7 @@
sharedRuntime.cpp interpreter.hpp
sharedRuntime.cpp javaCalls.hpp
sharedRuntime.cpp jvmtiExport.hpp
+sharedRuntime.cpp jvmtiRedefineClassesTrace.hpp
sharedRuntime.cpp nativeInst_<arch>.hpp
sharedRuntime.cpp nativeLookup.hpp
sharedRuntime.cpp oop.inline.hpp
@@ -3698,6 +3700,7 @@
sharedRuntime_<arch_model>.cpp debugInfoRec.hpp
sharedRuntime_<arch_model>.cpp icBuffer.hpp
sharedRuntime_<arch_model>.cpp interpreter.hpp
+sharedRuntime_<arch_model>.cpp jvmtiRedefineClassesTrace.hpp
sharedRuntime_<arch_model>.cpp sharedRuntime.hpp
sharedRuntime_<arch_model>.cpp vframeArray.hpp
sharedRuntime_<arch_model>.cpp vmreg_<arch>.inline.hpp
--- a/hotspot/src/share/vm/oops/klassVtable.cpp Mon Mar 02 14:00:23 2009 -0700
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp Mon Mar 02 14:03:03 2009 -0700
@@ -992,6 +992,10 @@
methodOop new_method = new_methods[j];
itableMethodEntry* ime = method_entry(0);
+ // The itable can describe more than one interface and the same
+ // method signature can be specified by more than one interface.
+ // This means we have to do an exhaustive search to find all the
+ // old_method references.
for (int i = 0; i < _size_method_table; i++) {
if (ime->method() == old_method) {
ime->initialize(new_method);
@@ -1008,7 +1012,6 @@
new_method->name()->as_C_string(),
new_method->signature()->as_C_string()));
}
- break;
}
ime++;
}
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp Mon Mar 02 14:00:23 2009 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp Mon Mar 02 14:03:03 2009 -0700
@@ -49,8 +49,8 @@
// 0x00000400 | 1024 - previous class weak reference mgmt during
// add previous ops (GC)
// 0x00000800 | 2048 - previous class breakpoint mgmt
-// 0x00001000 | 4096 - unused
-// 0x00002000 | 8192 - unused
+// 0x00001000 | 4096 - detect calls to obsolete methods
+// 0x00002000 | 8192 - fail a guarantee() in addition to detection
// 0x00004000 | 16384 - unused
// 0x00008000 | 32768 - old/new method matching/add/delete
// 0x00010000 | 65536 - impl details: CP size info
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Mon Mar 02 14:00:23 2009 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Mon Mar 02 14:03:03 2009 -0700
@@ -395,6 +395,32 @@
throw_and_post_jvmti_exception(thread, h_exception);
}
+// The interpreter code to call this tracing function is only
+// called/generated when TraceRedefineClasses has the right bits
+// set. Since obsolete methods are never compiled, we don't have
+// to modify the compilers to generate calls to this function.
+//
+JRT_LEAF(int, SharedRuntime::rc_trace_method_entry(
+ JavaThread* thread, methodOopDesc* method))
+ assert(RC_TRACE_IN_RANGE(0x00001000, 0x00002000), "wrong call");
+
+ if (method->is_obsolete()) {
+ // We are calling an obsolete method, but this is not necessarily
+ // an error. Our method could have been redefined just after we
+ // fetched the methodOop from the constant pool.
+
+ // RC_TRACE macro has an embedded ResourceMark
+ RC_TRACE_WITH_THREAD(0x00001000, thread,
+ ("calling obsolete method '%s'",
+ method->name_and_sig_as_C_string()));
+ if (RC_TRACE_ENABLED(0x00002000)) {
+ // this option is provided to debug calls to obsolete methods
+ guarantee(false, "faulting at call to an obsolete method.");
+ }
+ }
+ return 0;
+JRT_END
+
// ret_pc points into caller; we are returning caller's exception handler
// for given exception
address SharedRuntime::compute_compiled_exc_handler(nmethod* nm, address ret_pc, Handle& exception,
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp Mon Mar 02 14:00:23 2009 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp Mon Mar 02 14:03:03 2009 -0700
@@ -166,6 +166,9 @@
static void throw_and_post_jvmti_exception(JavaThread *thread, Handle h_exception);
static void throw_and_post_jvmti_exception(JavaThread *thread, symbolOop name, const char *message = NULL);
+ // RedefineClasses() tracing support for obsolete method entry
+ static int rc_trace_method_entry(JavaThread* thread, methodOopDesc* m);
+
// To be used as the entry point for unresolved native methods.
static address native_method_throw_unsatisfied_link_error_entry();