7055355: JSR 292: crash while throwing WrongMethodTypeException
Reviewed-by: jrose, twisti, bdelsart
--- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Thu Jun 16 13:46:55 2011 -0700
@@ -307,11 +307,12 @@
__ stop("damaged ricochet frame: L4 < FP");
__ BIND(L_ok_2);
- __ sub(L4_saved_args_base, UNREASONABLE_STACK_MOVE * Interpreter::stackElementSize, O7_temp);
- __ cmp(O7_temp, FP_temp);
- __ br(Assembler::lessEqualUnsigned, false, Assembler::pt, L_ok_3);
- __ delayed()->nop();
- __ stop("damaged ricochet frame: (L4 - UNREASONABLE_STACK_MOVE) > FP");
+ // Disable until we decide on it's fate
+ // __ sub(L4_saved_args_base, UNREASONABLE_STACK_MOVE * Interpreter::stackElementSize, O7_temp);
+ // __ cmp(O7_temp, FP_temp);
+ // __ br(Assembler::lessEqualUnsigned, false, Assembler::pt, L_ok_3);
+ // __ delayed()->nop();
+ // __ stop("damaged ricochet frame: (L4 - UNREASONABLE_STACK_MOVE) > FP");
__ BIND(L_ok_3);
extract_conversion_dest_type(_masm, L5_conversion, O7_temp);
@@ -547,8 +548,9 @@
__ brx(Assembler::notEqual, false, Assembler::pt, invoke_generic_slow_path);
__ delayed()->nop();
__ mov(O0_mtype, G5_method_type); // required by throw_WrongMethodType
- // mov(G3_method_handle, G3_method_handle); // already in this register
- __ jump_to(AddressLiteral(Interpreter::throw_WrongMethodType_entry()), O1_scratch);
+ __ mov(G3_method_handle, G3_method_handle); // already in this register
+ // O0 will be filled in with JavaThread in stub
+ __ jump_to(AddressLiteral(StubRoutines::throw_WrongMethodTypeException_entry()), O3_scratch);
__ delayed()->nop();
// here's where control starts out:
@@ -1145,23 +1147,13 @@
// FIXME: fill in _raise_exception_method with a suitable java.lang.invoke method
__ set(AddressLiteral((address) &_raise_exception_method), G5_method);
__ ld_ptr(Address(G5_method, 0), G5_method);
- __ tst(G5_method);
- __ brx(Assembler::zero, false, Assembler::pn, L_no_method);
- __ delayed()->nop();
const int jobject_oop_offset = 0;
__ ld_ptr(Address(G5_method, jobject_oop_offset), G5_method);
- __ tst(G5_method);
- __ brx(Assembler::zero, false, Assembler::pn, L_no_method);
- __ delayed()->nop();
__ verify_oop(G5_method);
__ jump_indirect_to(G5_method_fce, O3_scratch); // jump to compiled entry
__ delayed()->nop();
-
- // Do something that is at least causes a valid throw from the interpreter.
- __ bind(L_no_method);
- __ unimplemented("call throw_WrongMethodType_entry");
}
break;
--- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Thu Jun 16 13:46:55 2011 -0700
@@ -440,7 +440,8 @@
#undef __
#define __ masm->
- address generate_throw_exception(const char* name, address runtime_entry, bool restore_saved_exception_pc) {
+ address generate_throw_exception(const char* name, address runtime_entry, bool restore_saved_exception_pc,
+ Register arg1 = noreg, Register arg2 = noreg) {
#ifdef ASSERT
int insts_size = VerifyThread ? 1 * K : 600;
#else
@@ -476,6 +477,13 @@
__ set_last_Java_frame(last_java_sp, G0);
if (VerifyThread) __ mov(G2_thread, O0); // about to be smashed; pass early
__ save_thread(noreg);
+ if (arg1 != noreg) {
+ assert(arg2 != O1, "clobbered");
+ __ mov(arg1, O1);
+ }
+ if (arg2 != noreg) {
+ __ mov(arg2, O2);
+ }
// do the call
BLOCK_COMMENT("call runtime_entry");
__ call(runtime_entry, relocInfo::runtime_call_type);
@@ -3240,6 +3248,14 @@
StubRoutines::_atomic_cmpxchg_long_entry = generate_atomic_cmpxchg_long();
StubRoutines::_atomic_add_ptr_entry = StubRoutines::_atomic_add_entry;
#endif // COMPILER2 !=> _LP64
+
+ // Build this early so it's available for the interpreter. The
+ // stub expects the required and actual type to already be in O1
+ // and O2 respectively.
+ StubRoutines::_throw_WrongMethodTypeException_entry =
+ generate_throw_exception("WrongMethodTypeException throw_exception",
+ CAST_FROM_FN_PTR(address, SharedRuntime::throw_WrongMethodTypeException),
+ false, G5_method_type, G3_method_handle);
}
--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Thu Jun 16 13:46:55 2011 -0700
@@ -128,24 +128,6 @@
}
-// Arguments are: required type in G5_method_type, and
-// failing object (or NULL) in G3_method_handle.
-address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
- address entry = __ pc();
- // expression stack must be empty before entering the VM if an exception
- // happened
- __ empty_expression_stack();
- // load exception object
- __ call_VM(Oexception,
- CAST_FROM_FN_PTR(address,
- InterpreterRuntime::throw_WrongMethodTypeException),
- G5_method_type, // required
- G3_method_handle); // actual
- __ should_not_reach_here();
- return entry;
-}
-
-
address TemplateInterpreterGenerator::generate_ArrayIndexOutOfBounds_handler(const char* name) {
address entry = __ pc();
// expression stack must be empty before entering the VM if an exception happened
--- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Thu Jun 16 13:46:55 2011 -0700
@@ -602,15 +602,8 @@
// error path for invokeExact (only)
__ bind(invoke_exact_error_path);
- // jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
- Register rdx_last_Java_sp = rdx_temp;
- __ lea(rdx_last_Java_sp, __ argument_address(constant(0)));
- __ super_call_VM(noreg,
- rdx_last_Java_sp,
- CAST_FROM_FN_PTR(address,
- InterpreterRuntime::throw_WrongMethodTypeException),
- // pass required type, then failing mh object
- rax_mtype, rcx_recv);
+ // Stub wants expected type in rax and the actual type in rcx
+ __ jump(ExternalAddress(StubRoutines::throw_WrongMethodTypeException_entry()));
// for invokeGeneric (only), apply argument and result conversions on the fly
__ bind(invoke_generic_slow_path);
@@ -1175,27 +1168,15 @@
__ mov(rsp, saved_last_sp); // cut the stack back to where the caller started
Register rbx_method = rbx_temp;
- Label L_no_method;
- // FIXME: fill in _raise_exception_method with a suitable java.lang.invoke method
__ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method));
- __ testptr(rbx_method, rbx_method);
- __ jccb(Assembler::zero, L_no_method);
const int jobject_oop_offset = 0;
__ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject
- __ testptr(rbx_method, rbx_method);
- __ jccb(Assembler::zero, L_no_method);
__ verify_oop(rbx_method);
NOT_LP64(__ push(rarg2_required));
__ push(rdi_pc); // restore caller PC
__ jmp(rbx_method_fce); // jump to compiled entry
-
- // Do something that is at least causes a valid throw from the interpreter.
- __ bind(L_no_method);
- __ push(rarg2_required);
- __ push(rarg1_actual);
- __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
}
break;
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Thu Jun 16 13:46:55 2011 -0700
@@ -2151,6 +2151,8 @@
// if they expect all registers to be preserved.
enum layout {
thread_off, // last_java_sp
+ arg1_off,
+ arg2_off,
rbp_off, // callee saved register
ret_pc,
framesize
@@ -2185,7 +2187,7 @@
// either at call sites or otherwise assume that stack unwinding will be initiated,
// so caller saved registers were assumed volatile in the compiler.
address generate_throw_exception(const char* name, address runtime_entry,
- bool restore_saved_exception_pc) {
+ bool restore_saved_exception_pc, Register arg1 = noreg, Register arg2 = noreg) {
int insts_size = 256;
int locs_size = 32;
@@ -2218,6 +2220,13 @@
// push java thread (becomes first argument of C function)
__ movptr(Address(rsp, thread_off * wordSize), java_thread);
+ if (arg1 != noreg) {
+ __ movptr(Address(rsp, arg1_off * wordSize), arg1);
+ }
+ if (arg2 != noreg) {
+ assert(arg1 != noreg, "missing reg arg");
+ __ movptr(Address(rsp, arg2_off * wordSize), arg2);
+ }
// Set up last_Java_sp and last_Java_fp
__ set_last_Java_frame(java_thread, rsp, rbp, NULL);
@@ -2309,6 +2318,12 @@
CAST_FROM_FN_PTR(address, SharedRuntime::d2i));
StubRoutines::_d2l_wrapper = generate_d2i_wrapper(T_LONG,
CAST_FROM_FN_PTR(address, SharedRuntime::d2l));
+
+ // Build this early so it's available for the interpreter
+ StubRoutines::_throw_WrongMethodTypeException_entry =
+ generate_throw_exception("WrongMethodTypeException throw_exception",
+ CAST_FROM_FN_PTR(address, SharedRuntime::throw_WrongMethodTypeException),
+ false, rax, rcx);
}
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Thu Jun 16 13:46:55 2011 -0700
@@ -2934,7 +2934,9 @@
// caller saved registers were assumed volatile in the compiler.
address generate_throw_exception(const char* name,
address runtime_entry,
- bool restore_saved_exception_pc) {
+ bool restore_saved_exception_pc,
+ Register arg1 = noreg,
+ Register arg2 = noreg) {
// Information about frame layout at time of blocking runtime call.
// Note that we only have to preserve callee-saved registers since
// the compilers are responsible for supplying a continuation point
@@ -2980,6 +2982,13 @@
__ set_last_Java_frame(rsp, rbp, NULL);
// Call runtime
+ if (arg1 != noreg) {
+ assert(arg2 != c_rarg1, "clobbered");
+ __ movptr(c_rarg1, arg1);
+ }
+ if (arg2 != noreg) {
+ __ movptr(c_rarg2, arg2);
+ }
__ movptr(c_rarg0, r15_thread);
BLOCK_COMMENT("call runtime_entry");
__ call(RuntimeAddress(runtime_entry));
@@ -3052,6 +3061,14 @@
StubRoutines::x86::_get_previous_fp_entry = generate_get_previous_fp();
StubRoutines::x86::_verify_mxcsr_entry = generate_verify_mxcsr();
+
+ // Build this early so it's available for the interpreter. Stub
+ // expects the required and actual types as register arguments in
+ // j_rarg0 and j_rarg1 respectively.
+ StubRoutines::_throw_WrongMethodTypeException_entry =
+ generate_throw_exception("WrongMethodTypeException throw_exception",
+ CAST_FROM_FN_PTR(address, SharedRuntime::throw_WrongMethodTypeException),
+ false, rax, rcx);
}
void generate_all() {
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Thu Jun 16 13:46:55 2011 -0700
@@ -112,32 +112,6 @@
return entry;
}
-// Arguments are: required type at TOS+4, failing object (or NULL) at TOS.
-address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
- address entry = __ pc();
-
- __ pop(rbx); // actual failing object is at TOS
- __ pop(rax); // required type is at TOS+4
-
- __ verify_oop(rbx);
- __ verify_oop(rax);
-
- // Various method handle types use interpreter registers as temps.
- __ restore_bcp();
- __ restore_locals();
-
- // Expression stack must be empty before entering the VM for an exception.
- __ empty_expression_stack();
- __ empty_FPU_stack();
- __ call_VM(noreg,
- CAST_FROM_FN_PTR(address,
- InterpreterRuntime::throw_WrongMethodTypeException),
- // pass required type, failing object (or NULL)
- rax, rbx);
- return entry;
-}
-
-
address TemplateInterpreterGenerator::generate_exception_handler_common(const char* name, const char* message, bool pass_oop) {
assert(!pass_oop || message == NULL, "either oop or message but not both");
address entry = __ pc();
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Thu Jun 16 13:46:55 2011 -0700
@@ -120,31 +120,6 @@
return entry;
}
-// Arguments are: required type at TOS+8, failing object (or NULL) at TOS+4.
-address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
- address entry = __ pc();
-
- __ pop(c_rarg2); // failing object is at TOS
- __ pop(c_rarg1); // required type is at TOS+8
-
- __ verify_oop(c_rarg1);
- __ verify_oop(c_rarg2);
-
- // Various method handle types use interpreter registers as temps.
- __ restore_bcp();
- __ restore_locals();
-
- // Expression stack must be empty before entering the VM for an exception.
- __ empty_expression_stack();
-
- __ call_VM(noreg,
- CAST_FROM_FN_PTR(address,
- InterpreterRuntime::throw_WrongMethodTypeException),
- // pass required type, failing object (or NULL)
- c_rarg1, c_rarg2);
- return entry;
-}
-
address TemplateInterpreterGenerator::generate_exception_handler_common(
const char* name, const char* message, bool pass_oop) {
assert(!pass_oop || message == NULL, "either oop or message but not both");
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Thu Jun 16 13:46:55 2011 -0700
@@ -657,7 +657,7 @@
if (!is_exact) {
if (method->intrinsic_id() == vmIntrinsics::_invokeExact) {
CALL_VM_NOCHECK_NOFIX(
- InterpreterRuntime::throw_WrongMethodTypeException(
+ SharedRuntime::throw_WrongMethodTypeException(
thread, method_type, mhtype));
// NB all oops trashed!
assert(HAS_PENDING_EXCEPTION, "should do");
@@ -673,7 +673,7 @@
oop adapter = java_lang_invoke_MethodTypeForm::genericInvoker(form);
if (adapter == NULL) {
CALL_VM_NOCHECK_NOFIX(
- InterpreterRuntime::throw_WrongMethodTypeException(
+ SharedRuntime::throw_WrongMethodTypeException(
thread, method_type, mhtype));
// NB all oops trashed!
assert(HAS_PENDING_EXCEPTION, "should do");
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Thu Jun 16 13:46:55 2011 -0700
@@ -362,25 +362,6 @@
THROW_MSG(vmSymbols::java_lang_ClassCastException(), message);
IRT_END
-// required can be either a MethodType, or a Class (for a single argument)
-// actual (if not null) can be either a MethodHandle, or an arbitrary value (for a single argument)
-IRT_ENTRY(void, InterpreterRuntime::throw_WrongMethodTypeException(JavaThread* thread,
- oopDesc* required,
- oopDesc* actual)) {
- ResourceMark rm(thread);
- char* message = SharedRuntime::generate_wrong_method_type_message(thread, required, actual);
-
- if (ProfileTraps) {
- note_trap(thread, Deoptimization::Reason_constraint, CHECK);
- }
-
- // create exception
- THROW_MSG(vmSymbols::java_lang_invoke_WrongMethodTypeException(), message);
-}
-IRT_END
-
-
-
// exception_handler_for_exception(...) returns the continuation address,
// the exception oop (via TLS) and sets the bci/bcp for the continuation.
// The exception oop is returned to make sure it is preserved over GC (it
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Thu Jun 16 13:46:55 2011 -0700
@@ -98,7 +98,6 @@
static void throw_StackOverflowError(JavaThread* thread);
static void throw_ArrayIndexOutOfBoundsException(JavaThread* thread, char* name, jint index);
static void throw_ClassCastException(JavaThread* thread, oopDesc* obj);
- static void throw_WrongMethodTypeException(JavaThread* thread, oopDesc* mtype = NULL, oopDesc* mhandle = NULL);
static void create_exception(JavaThread* thread, char* name, char* message);
static void create_klass_exception(JavaThread* thread, char* name, oopDesc* obj);
static address exception_handler_for_exception(JavaThread* thread, oopDesc* exception);
--- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp Thu Jun 16 13:46:55 2011 -0700
@@ -171,7 +171,6 @@
address TemplateInterpreter::_throw_ArrayStoreException_entry = NULL;
address TemplateInterpreter::_throw_ArithmeticException_entry = NULL;
address TemplateInterpreter::_throw_ClassCastException_entry = NULL;
-address TemplateInterpreter::_throw_WrongMethodType_entry = NULL;
address TemplateInterpreter::_throw_NullPointerException_entry = NULL;
address TemplateInterpreter::_throw_StackOverflowError_entry = NULL;
address TemplateInterpreter::_throw_exception_entry = NULL;
@@ -346,7 +345,6 @@
Interpreter::_throw_ArrayStoreException_entry = generate_klass_exception_handler("java/lang/ArrayStoreException" );
Interpreter::_throw_ArithmeticException_entry = generate_exception_handler("java/lang/ArithmeticException" , "/ by zero");
Interpreter::_throw_ClassCastException_entry = generate_ClassCastException_handler();
- Interpreter::_throw_WrongMethodType_entry = generate_WrongMethodType_handler();
Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException" , NULL );
Interpreter::_throw_StackOverflowError_entry = generate_StackOverflowError_handler();
}
--- a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp Thu Jun 16 13:46:55 2011 -0700
@@ -51,7 +51,6 @@
}
address generate_exception_handler_common(const char* name, const char* message, bool pass_oop);
address generate_ClassCastException_handler();
- address generate_WrongMethodType_handler();
address generate_ArrayIndexOutOfBounds_handler(const char* name);
address generate_continuation_for(TosState state);
address generate_return_entry_for(TosState state, int step);
--- a/hotspot/src/share/vm/prims/methodHandles.cpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp Thu Jun 16 13:46:55 2011 -0700
@@ -629,6 +629,8 @@
// convert the external string name to an internal symbol
TempNewSymbol name = java_lang_String::as_symbol_or_null(name_str());
if (name == NULL) return; // no such name
+ if (name == vmSymbols::class_initializer_name())
+ return; // illegal name
Handle polymorphic_method_type;
bool polymorphic_signature = false;
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Jun 16 13:46:55 2011 -0700
@@ -763,6 +763,13 @@
throw_and_post_jvmti_exception(thread, exception);
JRT_END
+JRT_ENTRY(void, SharedRuntime::throw_WrongMethodTypeException(JavaThread* thread, oopDesc* required, oopDesc* actual))
+ assert(thread == JavaThread::current() && required->is_oop() && actual->is_oop(), "bad args");
+ ResourceMark rm;
+ char* message = SharedRuntime::generate_wrong_method_type_message(thread, required, actual);
+ throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_invoke_WrongMethodTypeException(), message);
+JRT_END
+
address SharedRuntime::continuation_for_implicit_exception(JavaThread* thread,
address pc,
SharedRuntime::ImplicitExceptionKind exception_kind)
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp Thu Jun 16 13:46:55 2011 -0700
@@ -185,6 +185,7 @@
static void throw_NullPointerException(JavaThread* thread);
static void throw_NullPointerException_at_call(JavaThread* thread);
static void throw_StackOverflowError(JavaThread* thread);
+ static void throw_WrongMethodTypeException(JavaThread* thread, oopDesc* required, oopDesc* actual);
static address continuation_for_implicit_exception(JavaThread* thread,
address faulting_pc,
ImplicitExceptionKind exception_kind);
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp Thu Jun 16 13:46:55 2011 -0700
@@ -55,6 +55,7 @@
address StubRoutines::_throw_NullPointerException_entry = NULL;
address StubRoutines::_throw_NullPointerException_at_call_entry = NULL;
address StubRoutines::_throw_StackOverflowError_entry = NULL;
+address StubRoutines::_throw_WrongMethodTypeException_entry = NULL;
address StubRoutines::_handler_for_unsafe_access_entry = NULL;
jint StubRoutines::_verify_oop_count = 0;
address StubRoutines::_verify_oop_subroutine_entry = NULL;
--- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Wed Jun 15 10:20:03 2011 -0700
+++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Thu Jun 16 13:46:55 2011 -0700
@@ -132,6 +132,7 @@
static address _throw_NullPointerException_entry;
static address _throw_NullPointerException_at_call_entry;
static address _throw_StackOverflowError_entry;
+ static address _throw_WrongMethodTypeException_entry;
static address _handler_for_unsafe_access_entry;
static address _atomic_xchg_entry;
@@ -254,6 +255,7 @@
static address throw_NullPointerException_entry() { return _throw_NullPointerException_entry; }
static address throw_NullPointerException_at_call_entry(){ return _throw_NullPointerException_at_call_entry; }
static address throw_StackOverflowError_entry() { return _throw_StackOverflowError_entry; }
+ static address throw_WrongMethodTypeException_entry() { return _throw_WrongMethodTypeException_entry; }
// Exceptions during unsafe access - should throw Java exception rather
// than crash.