Wed, 08 Jun 2011 17:04:06 -0700
7047697: MethodHandle.invokeExact call for wrong method causes VM failure if run with -Xcomp
Reviewed-by: never, twisti
1.1 --- a/src/cpu/x86/vm/assembler_x86.cpp Sat Jun 04 10:36:22 2011 -0700 1.2 +++ b/src/cpu/x86/vm/assembler_x86.cpp Wed Jun 08 17:04:06 2011 -0700 1.3 @@ -5891,6 +5891,53 @@ 1.4 call_VM(oop_result, last_java_sp, entry_point, 3, check_exceptions); 1.5 } 1.6 1.7 +void MacroAssembler::super_call_VM(Register oop_result, 1.8 + Register last_java_sp, 1.9 + address entry_point, 1.10 + int number_of_arguments, 1.11 + bool check_exceptions) { 1.12 + Register thread = LP64_ONLY(r15_thread) NOT_LP64(noreg); 1.13 + MacroAssembler::call_VM_base(oop_result, thread, last_java_sp, entry_point, number_of_arguments, check_exceptions); 1.14 +} 1.15 + 1.16 +void MacroAssembler::super_call_VM(Register oop_result, 1.17 + Register last_java_sp, 1.18 + address entry_point, 1.19 + Register arg_1, 1.20 + bool check_exceptions) { 1.21 + pass_arg1(this, arg_1); 1.22 + super_call_VM(oop_result, last_java_sp, entry_point, 1, check_exceptions); 1.23 +} 1.24 + 1.25 +void MacroAssembler::super_call_VM(Register oop_result, 1.26 + Register last_java_sp, 1.27 + address entry_point, 1.28 + Register arg_1, 1.29 + Register arg_2, 1.30 + bool check_exceptions) { 1.31 + 1.32 + LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); 1.33 + pass_arg2(this, arg_2); 1.34 + pass_arg1(this, arg_1); 1.35 + super_call_VM(oop_result, last_java_sp, entry_point, 2, check_exceptions); 1.36 +} 1.37 + 1.38 +void MacroAssembler::super_call_VM(Register oop_result, 1.39 + Register last_java_sp, 1.40 + address entry_point, 1.41 + Register arg_1, 1.42 + Register arg_2, 1.43 + Register arg_3, 1.44 + bool check_exceptions) { 1.45 + LP64_ONLY(assert(arg_1 != c_rarg3, "smashed arg")); 1.46 + LP64_ONLY(assert(arg_2 != c_rarg3, "smashed arg")); 1.47 + pass_arg3(this, arg_3); 1.48 + LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); 1.49 + pass_arg2(this, arg_2); 1.50 + pass_arg1(this, arg_1); 1.51 + super_call_VM(oop_result, last_java_sp, entry_point, 3, check_exceptions); 1.52 +} 1.53 + 1.54 void MacroAssembler::call_VM_base(Register oop_result, 1.55 Register java_thread, 1.56 Register last_java_sp,
2.1 --- a/src/cpu/x86/vm/assembler_x86.hpp Sat Jun 04 10:36:22 2011 -0700 2.2 +++ b/src/cpu/x86/vm/assembler_x86.hpp Wed Jun 08 17:04:06 2011 -0700 2.3 @@ -1660,6 +1660,14 @@ 2.4 Register arg_1, Register arg_2, Register arg_3, 2.5 bool check_exceptions = true); 2.6 2.7 + // These always tightly bind to MacroAssembler::call_VM_base 2.8 + // bypassing the virtual implementation 2.9 + void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, int number_of_arguments = 0, bool check_exceptions = true); 2.10 + void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, bool check_exceptions = true); 2.11 + void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, bool check_exceptions = true); 2.12 + 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); 2.13 + 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); 2.14 + 2.15 void call_VM_leaf(address entry_point, 2.16 int number_of_arguments = 0); 2.17 void call_VM_leaf(address entry_point,
3.1 --- a/src/cpu/x86/vm/frame_x86.inline.hpp Sat Jun 04 10:36:22 2011 -0700 3.2 +++ b/src/cpu/x86/vm/frame_x86.inline.hpp Wed Jun 08 17:04:06 2011 -0700 3.3 @@ -45,6 +45,7 @@ 3.4 _pc = pc; 3.5 assert(pc != NULL, "no pc?"); 3.6 _cb = CodeCache::find_blob(pc); 3.7 + adjust_unextended_sp(); 3.8 3.9 address original_pc = nmethod::get_deopt_original_pc(this); 3.10 if (original_pc != NULL) { 3.11 @@ -92,6 +93,7 @@ 3.12 // assert(_pc != NULL, "no pc?"); 3.13 3.14 _cb = CodeCache::find_blob(_pc); 3.15 + adjust_unextended_sp(); 3.16 3.17 address original_pc = nmethod::get_deopt_original_pc(this); 3.18 if (original_pc != NULL) {
4.1 --- a/src/cpu/x86/vm/methodHandles_x86.cpp Sat Jun 04 10:36:22 2011 -0700 4.2 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp Wed Jun 08 17:04:06 2011 -0700 4.3 @@ -24,6 +24,7 @@ 4.4 4.5 #include "precompiled.hpp" 4.6 #include "interpreter/interpreter.hpp" 4.7 +#include "interpreter/interpreterRuntime.hpp" 4.8 #include "memory/allocation.inline.hpp" 4.9 #include "prims/methodHandles.hpp" 4.10 4.11 @@ -37,6 +38,11 @@ 4.12 4.13 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":") 4.14 4.15 +// Workaround for C++ overloading nastiness on '0' for RegisterOrConstant. 4.16 +static RegisterOrConstant constant(int value) { 4.17 + return RegisterOrConstant(value); 4.18 +} 4.19 + 4.20 address MethodHandleEntry::start_compiled_entry(MacroAssembler* _masm, 4.21 address interpreted_entry) { 4.22 // Just before the actual machine code entry point, allocate space 4.23 @@ -556,13 +562,11 @@ 4.24 // emit WrongMethodType path first, to enable jccb back-branch from main path 4.25 Label wrong_method_type; 4.26 __ bind(wrong_method_type); 4.27 - Label invoke_generic_slow_path; 4.28 + Label invoke_generic_slow_path, invoke_exact_error_path; 4.29 assert(methodOopDesc::intrinsic_id_size_in_bytes() == sizeof(u1), "");; 4.30 __ cmpb(Address(rbx_method, methodOopDesc::intrinsic_id_offset_in_bytes()), (int) vmIntrinsics::_invokeExact); 4.31 __ jcc(Assembler::notEqual, invoke_generic_slow_path); 4.32 - __ push(rax_mtype); // required mtype 4.33 - __ push(rcx_recv); // bad mh (1st stacked argument) 4.34 - __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry())); 4.35 + __ jmp(invoke_exact_error_path); 4.36 4.37 // here's where control starts out: 4.38 __ align(CodeEntryAlignment); 4.39 @@ -596,6 +600,18 @@ 4.40 4.41 __ jump_to_method_handle_entry(rcx_recv, rdi_temp); 4.42 4.43 + // error path for invokeExact (only) 4.44 + __ bind(invoke_exact_error_path); 4.45 + // jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry())); 4.46 + Register rdx_last_Java_sp = rdx_temp; 4.47 + __ lea(rdx_last_Java_sp, __ argument_address(constant(0))); 4.48 + __ super_call_VM(noreg, 4.49 + rdx_last_Java_sp, 4.50 + CAST_FROM_FN_PTR(address, 4.51 + InterpreterRuntime::throw_WrongMethodTypeException), 4.52 + // pass required type, then failing mh object 4.53 + rax_mtype, rcx_recv); 4.54 + 4.55 // for invokeGeneric (only), apply argument and result conversions on the fly 4.56 __ bind(invoke_generic_slow_path); 4.57 #ifdef ASSERT 4.58 @@ -633,11 +649,6 @@ 4.59 return entry_point; 4.60 } 4.61 4.62 -// Workaround for C++ overloading nastiness on '0' for RegisterOrConstant. 4.63 -static RegisterOrConstant constant(int value) { 4.64 - return RegisterOrConstant(value); 4.65 -} 4.66 - 4.67 // Helper to insert argument slots into the stack. 4.68 // arg_slots must be a multiple of stack_move_unit() and < 0 4.69 // rax_argslot is decremented to point to the new (shifted) location of the argslot
5.1 --- a/src/share/vm/code/pcDesc.cpp Sat Jun 04 10:36:22 2011 -0700 5.2 +++ b/src/share/vm/code/pcDesc.cpp Wed Jun 08 17:04:06 2011 -0700 5.3 @@ -44,7 +44,7 @@ 5.4 void PcDesc::print(nmethod* code) { 5.5 #ifndef PRODUCT 5.6 ResourceMark rm; 5.7 - tty->print_cr("PcDesc(pc=0x%lx offset=%x):", real_pc(code), pc_offset()); 5.8 + tty->print_cr("PcDesc(pc=0x%lx offset=%x bits=%x):", real_pc(code), pc_offset(), _flags.bits); 5.9 5.10 if (scope_decode_offset() == DebugInformationRecorder::serialized_null) { 5.11 return;