From acff0e3be5907c684c77ebf684ec254c5e96b97a Mon Sep 17 00:00:00 2001 From: jrose Date: Wed, 8 Jun 2011 17:04:06 -0700 Subject: [PATCH] 7047697: MethodHandle.invokeExact call for wrong method causes VM failure if run with -Xcomp Reviewed-by: never, twisti --- src/cpu/x86/vm/assembler_x86.cpp | 47 ++++++++++++++++++++++++++++ src/cpu/x86/vm/assembler_x86.hpp | 8 +++++ src/cpu/x86/vm/frame_x86.inline.hpp | 2 ++ src/cpu/x86/vm/methodHandles_x86.cpp | 29 +++++++++++------ src/share/vm/code/pcDesc.cpp | 2 +- 5 files changed, 78 insertions(+), 10 deletions(-) diff --git a/src/cpu/x86/vm/assembler_x86.cpp b/src/cpu/x86/vm/assembler_x86.cpp index 3fb778808..ec7f42a7f 100644 --- a/src/cpu/x86/vm/assembler_x86.cpp +++ b/src/cpu/x86/vm/assembler_x86.cpp @@ -5891,6 +5891,53 @@ void MacroAssembler::call_VM(Register oop_result, call_VM(oop_result, last_java_sp, entry_point, 3, check_exceptions); } +void MacroAssembler::super_call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + int number_of_arguments, + bool check_exceptions) { + Register thread = LP64_ONLY(r15_thread) NOT_LP64(noreg); + MacroAssembler::call_VM_base(oop_result, thread, last_java_sp, entry_point, number_of_arguments, check_exceptions); +} + +void MacroAssembler::super_call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, + bool check_exceptions) { + pass_arg1(this, arg_1); + super_call_VM(oop_result, last_java_sp, entry_point, 1, check_exceptions); +} + +void MacroAssembler::super_call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, + Register arg_2, + bool check_exceptions) { + + LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); + pass_arg2(this, arg_2); + pass_arg1(this, arg_1); + super_call_VM(oop_result, last_java_sp, entry_point, 2, check_exceptions); +} + +void MacroAssembler::super_call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, + Register arg_2, + Register arg_3, + bool check_exceptions) { + LP64_ONLY(assert(arg_1 != c_rarg3, "smashed arg")); + LP64_ONLY(assert(arg_2 != c_rarg3, "smashed arg")); + pass_arg3(this, arg_3); + LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); + pass_arg2(this, arg_2); + pass_arg1(this, arg_1); + super_call_VM(oop_result, last_java_sp, entry_point, 3, check_exceptions); +} + void MacroAssembler::call_VM_base(Register oop_result, Register java_thread, Register last_java_sp, diff --git a/src/cpu/x86/vm/assembler_x86.hpp b/src/cpu/x86/vm/assembler_x86.hpp index c36709a33..2cd4b5c34 100644 --- a/src/cpu/x86/vm/assembler_x86.hpp +++ b/src/cpu/x86/vm/assembler_x86.hpp @@ -1660,6 +1660,14 @@ class MacroAssembler: public Assembler { Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true); + // These always tightly bind to MacroAssembler::call_VM_base + // bypassing the virtual implementation + void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, int number_of_arguments = 0, bool check_exceptions = true); + void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, bool check_exceptions = true); + void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, bool check_exceptions = true); + void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true); + void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, Register arg_3, Register arg_4, bool check_exceptions = true); + void call_VM_leaf(address entry_point, int number_of_arguments = 0); void call_VM_leaf(address entry_point, diff --git a/src/cpu/x86/vm/frame_x86.inline.hpp b/src/cpu/x86/vm/frame_x86.inline.hpp index d093facdc..2d542eae4 100644 --- a/src/cpu/x86/vm/frame_x86.inline.hpp +++ b/src/cpu/x86/vm/frame_x86.inline.hpp @@ -45,6 +45,7 @@ inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) { _pc = pc; assert(pc != NULL, "no pc?"); _cb = CodeCache::find_blob(pc); + adjust_unextended_sp(); address original_pc = nmethod::get_deopt_original_pc(this); if (original_pc != NULL) { @@ -92,6 +93,7 @@ inline frame::frame(intptr_t* sp, intptr_t* fp) { // assert(_pc != NULL, "no pc?"); _cb = CodeCache::find_blob(_pc); + adjust_unextended_sp(); address original_pc = nmethod::get_deopt_original_pc(this); if (original_pc != NULL) { diff --git a/src/cpu/x86/vm/methodHandles_x86.cpp b/src/cpu/x86/vm/methodHandles_x86.cpp index 761112afb..dece04107 100644 --- a/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/src/cpu/x86/vm/methodHandles_x86.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "interpreter/interpreter.hpp" +#include "interpreter/interpreterRuntime.hpp" #include "memory/allocation.inline.hpp" #include "prims/methodHandles.hpp" @@ -37,6 +38,11 @@ #define BIND(label) bind(label); BLOCK_COMMENT(#label ":") +// Workaround for C++ overloading nastiness on '0' for RegisterOrConstant. +static RegisterOrConstant constant(int value) { + return RegisterOrConstant(value); +} + address MethodHandleEntry::start_compiled_entry(MacroAssembler* _masm, address interpreted_entry) { // Just before the actual machine code entry point, allocate space @@ -556,13 +562,11 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* // emit WrongMethodType path first, to enable jccb back-branch from main path Label wrong_method_type; __ bind(wrong_method_type); - Label invoke_generic_slow_path; + Label invoke_generic_slow_path, invoke_exact_error_path; assert(methodOopDesc::intrinsic_id_size_in_bytes() == sizeof(u1), "");; __ cmpb(Address(rbx_method, methodOopDesc::intrinsic_id_offset_in_bytes()), (int) vmIntrinsics::_invokeExact); __ jcc(Assembler::notEqual, invoke_generic_slow_path); - __ push(rax_mtype); // required mtype - __ push(rcx_recv); // bad mh (1st stacked argument) - __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry())); + __ jmp(invoke_exact_error_path); // here's where control starts out: __ align(CodeEntryAlignment); @@ -596,6 +600,18 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* __ jump_to_method_handle_entry(rcx_recv, rdi_temp); + // 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); + // for invokeGeneric (only), apply argument and result conversions on the fly __ bind(invoke_generic_slow_path); #ifdef ASSERT @@ -633,11 +649,6 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* return entry_point; } -// Workaround for C++ overloading nastiness on '0' for RegisterOrConstant. -static RegisterOrConstant constant(int value) { - return RegisterOrConstant(value); -} - // Helper to insert argument slots into the stack. // arg_slots must be a multiple of stack_move_unit() and < 0 // rax_argslot is decremented to point to the new (shifted) location of the argslot diff --git a/src/share/vm/code/pcDesc.cpp b/src/share/vm/code/pcDesc.cpp index 7e217998d..d6c375163 100644 --- a/src/share/vm/code/pcDesc.cpp +++ b/src/share/vm/code/pcDesc.cpp @@ -44,7 +44,7 @@ address PcDesc::real_pc(const nmethod* code) const { void PcDesc::print(nmethod* code) { #ifndef PRODUCT ResourceMark rm; - tty->print_cr("PcDesc(pc=0x%lx offset=%x):", real_pc(code), pc_offset()); + tty->print_cr("PcDesc(pc=0x%lx offset=%x bits=%x):", real_pc(code), pc_offset(), _flags.bits); if (scope_decode_offset() == DebugInformationRecorder::serialized_null) { return; -- GitLab