提交 5dd86652 编写于 作者: N never

7055355: JSR 292: crash while throwing WrongMethodTypeException

Reviewed-by: jrose, twisti, bdelsart
上级 4f7abda8
......@@ -307,11 +307,12 @@ void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) {
__ 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 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
__ 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 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
// 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;
......
......@@ -440,7 +440,8 @@ class StubGenerator: public StubCodeGenerator {
#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 @@ class StubGenerator: public StubCodeGenerator {
__ 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 @@ class StubGenerator: public StubCodeGenerator {
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);
}
......
......@@ -128,24 +128,6 @@ address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
}
// 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
......
......@@ -602,15 +602,8 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
// 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 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
__ 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;
......
......@@ -2151,6 +2151,8 @@ class StubGenerator: public StubCodeGenerator {
// 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 @@ class StubGenerator: public StubCodeGenerator {
// 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 @@ class StubGenerator: public StubCodeGenerator {
// 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 @@ class StubGenerator: public StubCodeGenerator {
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);
}
......
......@@ -2934,7 +2934,9 @@ class StubGenerator: public StubCodeGenerator {
// 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 @@ class StubGenerator: public StubCodeGenerator {
__ 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 @@ class StubGenerator: public StubCodeGenerator {
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() {
......
......@@ -112,32 +112,6 @@ address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
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();
......
......@@ -120,31 +120,6 @@ address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
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");
......
......@@ -657,7 +657,7 @@ int CppInterpreter::method_handle_entry(methodOop method,
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 @@ int CppInterpreter::method_handle_entry(methodOop method,
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");
......
......@@ -362,25 +362,6 @@ IRT_ENTRY(void, InterpreterRuntime::throw_ClassCastException(
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
......
......@@ -98,7 +98,6 @@ class InterpreterRuntime: AllStatic {
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);
......
......@@ -171,7 +171,6 @@ address TemplateInterpreter::_throw_ArrayIndexOutOfBoundsException_entry = NU
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 @@ void TemplateInterpreterGenerator::generate_all() {
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();
}
......
......@@ -51,7 +51,6 @@ class TemplateInterpreterGenerator: public AbstractInterpreterGenerator {
}
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);
......
......@@ -629,6 +629,8 @@ void MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
// 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;
......
......@@ -763,6 +763,13 @@ JRT_ENTRY(void, SharedRuntime::throw_StackOverflowError(JavaThread* thread))
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)
......
......@@ -185,6 +185,7 @@ class SharedRuntime: AllStatic {
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);
......
......@@ -55,6 +55,7 @@ address StubRoutines::_throw_ArithmeticException_entry = NULL;
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;
......
......@@ -132,6 +132,7 @@ class StubRoutines: AllStatic {
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 @@ class StubRoutines: AllStatic {
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.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册