changeset 2517:5cf771a79037

7047697: MethodHandle.invokeExact call for wrong method causes VM failure if run with -Xcomp Reviewed-by: never, twisti
author jrose
date Wed, 08 Jun 2011 17:04:06 -0700
parents 642c68c75db9
children c8f2186acf6d f8c9417e3571
files src/cpu/x86/vm/assembler_x86.cpp src/cpu/x86/vm/assembler_x86.hpp src/cpu/x86/vm/frame_x86.inline.hpp src/cpu/x86/vm/methodHandles_x86.cpp src/share/vm/code/pcDesc.cpp
diffstat 5 files changed, 78 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/x86/vm/assembler_x86.cpp	Sat Jun 04 10:36:22 2011 -0700
+++ b/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/src/cpu/x86/vm/assembler_x86.hpp	Sat Jun 04 10:36:22 2011 -0700
+++ b/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/src/cpu/x86/vm/frame_x86.inline.hpp	Sat Jun 04 10:36:22 2011 -0700
+++ b/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/src/cpu/x86/vm/methodHandles_x86.cpp	Sat Jun 04 10:36:22 2011 -0700
+++ b/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/src/share/vm/code/pcDesc.cpp	Sat Jun 04 10:36:22 2011 -0700
+++ b/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;