7047697: MethodHandle.invokeExact call for wrong method causes VM failure if run with -Xcomp
Reviewed-by: never, twisti
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Sat Jun 04 10:36:22 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Wed Jun 08 17:04:06 2011 -0700
@@ -5891,6 +5891,53 @@
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,
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Sat Jun 04 10:36:22 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Wed Jun 08 17:04:06 2011 -0700
@@ -1660,6 +1660,14 @@
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,
--- a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp Sat Jun 04 10:36:22 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp Wed Jun 08 17:04:06 2011 -0700
@@ -45,6 +45,7 @@
_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 @@
// 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) {
--- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Sat Jun 04 10:36:22 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Wed Jun 08 17:04:06 2011 -0700
@@ -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 @@
// 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 @@
__ 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 @@
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
--- a/hotspot/src/share/vm/code/pcDesc.cpp Sat Jun 04 10:36:22 2011 -0700
+++ b/hotspot/src/share/vm/code/pcDesc.cpp Wed Jun 08 17:04:06 2011 -0700
@@ -44,7 +44,7 @@
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;