6990212: JSR 292 JVMTI MethodEnter hook is not called for JSR 292 bootstrap and target methods

Fri, 15 Jul 2011 15:35:50 -0700

author
never
date
Fri, 15 Jul 2011 15:35:50 -0700
changeset 3005
341a57af9b0a
parent 3004
3fbb609d9e96
child 3006
968305b802ee
child 3035
43f9d800f276

6990212: JSR 292 JVMTI MethodEnter hook is not called for JSR 292 bootstrap and target methods
Summary: check for single stepping when dispatching invokes from method handles
Reviewed-by: coleenp, twisti, kvn, dsamersoff

src/cpu/sparc/vm/methodHandles_sparc.cpp file | annotate | diff | comparison | revisions
src/cpu/sparc/vm/methodHandles_sparc.hpp file | annotate | diff | comparison | revisions
src/cpu/x86/vm/interp_masm_x86_32.cpp file | annotate | diff | comparison | revisions
src/cpu/x86/vm/interp_masm_x86_64.cpp file | annotate | diff | comparison | revisions
src/cpu/x86/vm/methodHandles_x86.cpp file | annotate | diff | comparison | revisions
src/cpu/x86/vm/methodHandles_x86.hpp file | annotate | diff | comparison | revisions
test/compiler/6990212/Test6990212.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/cpu/sparc/vm/methodHandles_sparc.cpp	Thu Jul 14 15:39:40 2011 -0700
     1.2 +++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp	Fri Jul 15 15:35:50 2011 -0700
     1.3 @@ -524,6 +524,30 @@
     1.4  }
     1.5  #endif // ASSERT
     1.6  
     1.7 +
     1.8 +void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register target, Register temp) {
     1.9 +  assert(method == G5_method, "interpreter calling convention");
    1.10 +  __ verify_oop(method);
    1.11 +  __ ld_ptr(G5_method, in_bytes(methodOopDesc::from_interpreted_offset()), target);
    1.12 +  if (JvmtiExport::can_post_interpreter_events()) {
    1.13 +    // JVMTI events, such as single-stepping, are implemented partly by avoiding running
    1.14 +    // compiled code in threads for which the event is enabled.  Check here for
    1.15 +    // interp_only_mode if these events CAN be enabled.
    1.16 +    __ verify_thread();
    1.17 +    Label skip_compiled_code;
    1.18 +
    1.19 +    const Address interp_only(G2_thread, JavaThread::interp_only_mode_offset());
    1.20 +    __ ld(interp_only, temp);
    1.21 +    __ tst(temp);
    1.22 +    __ br(Assembler::notZero, true, Assembler::pn, skip_compiled_code);
    1.23 +    __ delayed()->ld_ptr(G5_method, in_bytes(methodOopDesc::interpreter_entry_offset()), target);
    1.24 +    __ bind(skip_compiled_code);
    1.25 +  }
    1.26 +  __ jmp(target, 0);
    1.27 +  __ delayed()->nop();
    1.28 +}
    1.29 +
    1.30 +
    1.31  // Code generation
    1.32  address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) {
    1.33    // I5_savedSP/O5_savedSP: sender SP (must preserve)
    1.34 @@ -1105,9 +1129,6 @@
    1.35    guarantee(java_lang_invoke_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets");
    1.36  
    1.37    // Some handy addresses:
    1.38 -  Address G5_method_fie(    G5_method,        in_bytes(methodOopDesc::from_interpreted_offset()));
    1.39 -  Address G5_method_fce(    G5_method,        in_bytes(methodOopDesc::from_compiled_offset()));
    1.40 -
    1.41    Address G3_mh_vmtarget(   G3_method_handle, java_lang_invoke_MethodHandle::vmtarget_offset_in_bytes());
    1.42  
    1.43    Address G3_dmh_vmindex(   G3_method_handle, java_lang_invoke_DirectMethodHandle::vmindex_offset_in_bytes());
    1.44 @@ -1136,24 +1157,23 @@
    1.45    case _raise_exception:
    1.46      {
    1.47        // Not a real MH entry, but rather shared code for raising an
    1.48 -      // exception.  Since we use the compiled entry, arguments are
    1.49 -      // expected in compiler argument registers.
    1.50 +      // exception.  For sharing purposes the arguments are passed into registers
    1.51 +      // and then placed in the intepreter calling convention here.
    1.52        assert(raise_exception_method(), "must be set");
    1.53        assert(raise_exception_method()->from_compiled_entry(), "method must be linked");
    1.54  
    1.55 -      __ mov(O5_savedSP, SP);  // Cut the stack back to where the caller started.
    1.56 -
    1.57 -      Label L_no_method;
    1.58 -      // FIXME: fill in _raise_exception_method with a suitable java.lang.invoke method
    1.59        __ set(AddressLiteral((address) &_raise_exception_method), G5_method);
    1.60        __ ld_ptr(Address(G5_method, 0), G5_method);
    1.61  
    1.62        const int jobject_oop_offset = 0;
    1.63        __ ld_ptr(Address(G5_method, jobject_oop_offset), G5_method);
    1.64  
    1.65 -      __ verify_oop(G5_method);
    1.66 -      __ jump_indirect_to(G5_method_fce, O3_scratch);  // jump to compiled entry
    1.67 -      __ delayed()->nop();
    1.68 +      adjust_SP_and_Gargs_down_by_slots(_masm, 3, noreg, noreg);
    1.69 +
    1.70 +      __ st_ptr(O0_code,     __ argument_address(constant(2), noreg, 0));
    1.71 +      __ st_ptr(O1_actual,   __ argument_address(constant(1), noreg, 0));
    1.72 +      __ st_ptr(O2_required, __ argument_address(constant(0), noreg, 0));
    1.73 +      jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch);
    1.74      }
    1.75      break;
    1.76  
    1.77 @@ -1161,7 +1181,6 @@
    1.78    case _invokespecial_mh:
    1.79      {
    1.80        __ load_heap_oop(G3_mh_vmtarget, G5_method);  // target is a methodOop
    1.81 -      __ verify_oop(G5_method);
    1.82        // Same as TemplateTable::invokestatic or invokespecial,
    1.83        // minus the CP setup and profiling:
    1.84        if (ek == _invokespecial_mh) {
    1.85 @@ -1171,8 +1190,7 @@
    1.86          __ null_check(G3_method_handle);
    1.87          __ verify_oop(G3_method_handle);
    1.88        }
    1.89 -      __ jump_indirect_to(G5_method_fie, O1_scratch);
    1.90 -      __ delayed()->nop();
    1.91 +      jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch);
    1.92      }
    1.93      break;
    1.94  
    1.95 @@ -1204,9 +1222,7 @@
    1.96        Address vtable_entry_addr(O0_klass, base + vtableEntry::method_offset_in_bytes());
    1.97        __ ld_ptr(vtable_entry_addr, G5_method);
    1.98  
    1.99 -      __ verify_oop(G5_method);
   1.100 -      __ jump_indirect_to(G5_method_fie, O1_scratch);
   1.101 -      __ delayed()->nop();
   1.102 +      jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch);
   1.103      }
   1.104      break;
   1.105  
   1.106 @@ -1237,9 +1253,7 @@
   1.107                                   O3_scratch,
   1.108                                   no_such_interface);
   1.109  
   1.110 -      __ verify_oop(G5_method);
   1.111 -      __ jump_indirect_to(G5_method_fie, O1_scratch);
   1.112 -      __ delayed()->nop();
   1.113 +      jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch);
   1.114  
   1.115        __ bind(no_such_interface);
   1.116        // Throw an exception.
   1.117 @@ -1283,9 +1297,7 @@
   1.118  
   1.119        if (direct_to_method) {
   1.120          __ load_heap_oop(G3_mh_vmtarget, G5_method);  // target is a methodOop
   1.121 -        __ verify_oop(G5_method);
   1.122 -        __ jump_indirect_to(G5_method_fie, O1_scratch);
   1.123 -        __ delayed()->nop();
   1.124 +        jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch);
   1.125        } else {
   1.126          __ load_heap_oop(G3_mh_vmtarget, G3_method_handle);  // target is a methodOop
   1.127          __ verify_oop(G3_method_handle);
     2.1 --- a/src/cpu/sparc/vm/methodHandles_sparc.hpp	Thu Jul 14 15:39:40 2011 -0700
     2.2 +++ b/src/cpu/sparc/vm/methodHandles_sparc.hpp	Fri Jul 15 15:35:50 2011 -0700
     2.3 @@ -221,4 +221,8 @@
     2.4                   "reference is a MH");
     2.5    }
     2.6  
     2.7 +  // Similar to InterpreterMacroAssembler::jump_from_interpreted.
     2.8 +  // Takes care of special dispatch from single stepping too.
     2.9 +  static void jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp, Register temp2);
    2.10 +
    2.11    static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN;
     3.1 --- a/src/cpu/x86/vm/interp_masm_x86_32.cpp	Thu Jul 14 15:39:40 2011 -0700
     3.2 +++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp	Fri Jul 15 15:35:50 2011 -0700
     3.3 @@ -403,9 +403,9 @@
     3.4      // interp_only_mode if these events CAN be enabled.
     3.5      get_thread(temp);
     3.6      // interp_only is an int, on little endian it is sufficient to test the byte only
     3.7 -    // Is a cmpl faster (ce
     3.8 +    // Is a cmpl faster?
     3.9      cmpb(Address(temp, JavaThread::interp_only_mode_offset()), 0);
    3.10 -    jcc(Assembler::zero, run_compiled_code);
    3.11 +    jccb(Assembler::zero, run_compiled_code);
    3.12      jmp(Address(method, methodOopDesc::interpreter_entry_offset()));
    3.13      bind(run_compiled_code);
    3.14    }
     4.1 --- a/src/cpu/x86/vm/interp_masm_x86_64.cpp	Thu Jul 14 15:39:40 2011 -0700
     4.2 +++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp	Fri Jul 15 15:35:50 2011 -0700
     4.3 @@ -402,7 +402,7 @@
     4.4      // interp_only is an int, on little endian it is sufficient to test the byte only
     4.5      // Is a cmpl faster?
     4.6      cmpb(Address(r15_thread, JavaThread::interp_only_mode_offset()), 0);
     4.7 -    jcc(Assembler::zero, run_compiled_code);
     4.8 +    jccb(Assembler::zero, run_compiled_code);
     4.9      jmp(Address(method, methodOopDesc::interpreter_entry_offset()));
    4.10      bind(run_compiled_code);
    4.11    }
     5.1 --- a/src/cpu/x86/vm/methodHandles_x86.cpp	Thu Jul 14 15:39:40 2011 -0700
     5.2 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp	Fri Jul 15 15:35:50 2011 -0700
     5.3 @@ -546,6 +546,28 @@
     5.4  }
     5.5  #endif //ASSERT
     5.6  
     5.7 +void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp) {
     5.8 +  if (JvmtiExport::can_post_interpreter_events()) {
     5.9 +    Label run_compiled_code;
    5.10 +    // JVMTI events, such as single-stepping, are implemented partly by avoiding running
    5.11 +    // compiled code in threads for which the event is enabled.  Check here for
    5.12 +    // interp_only_mode if these events CAN be enabled.
    5.13 +#ifdef _LP64
    5.14 +    Register rthread = r15_thread;
    5.15 +#else
    5.16 +    Register rthread = temp;
    5.17 +    __ get_thread(rthread);
    5.18 +#endif
    5.19 +    // interp_only is an int, on little endian it is sufficient to test the byte only
    5.20 +    // Is a cmpl faster?
    5.21 +    __ cmpb(Address(rthread, JavaThread::interp_only_mode_offset()), 0);
    5.22 +    __ jccb(Assembler::zero, run_compiled_code);
    5.23 +    __ jmp(Address(method, methodOopDesc::interpreter_entry_offset()));
    5.24 +    __ bind(run_compiled_code);
    5.25 +  }
    5.26 +  __ jmp(Address(method, methodOopDesc::from_interpreted_offset()));
    5.27 +}
    5.28 +
    5.29  // Code generation
    5.30  address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) {
    5.31    // rbx: methodOop
    5.32 @@ -1120,9 +1142,6 @@
    5.33    guarantee(java_lang_invoke_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets");
    5.34  
    5.35    // some handy addresses
    5.36 -  Address rbx_method_fie(     rbx,      methodOopDesc::from_interpreted_offset() );
    5.37 -  Address rbx_method_fce(     rbx,      methodOopDesc::from_compiled_offset() );
    5.38 -
    5.39    Address rcx_mh_vmtarget(    rcx_recv, java_lang_invoke_MethodHandle::vmtarget_offset_in_bytes() );
    5.40    Address rcx_dmh_vmindex(    rcx_recv, java_lang_invoke_DirectMethodHandle::vmindex_offset_in_bytes() );
    5.41  
    5.42 @@ -1163,8 +1182,8 @@
    5.43        assert(raise_exception_method(), "must be set");
    5.44        assert(raise_exception_method()->from_compiled_entry(), "method must be linked");
    5.45  
    5.46 -      const Register rdi_pc = rax;
    5.47 -      __ pop(rdi_pc);  // caller PC
    5.48 +      const Register rax_pc = rax;
    5.49 +      __ pop(rax_pc);  // caller PC
    5.50        __ mov(rsp, saved_last_sp);  // cut the stack back to where the caller started
    5.51  
    5.52        Register rbx_method = rbx_temp;
    5.53 @@ -1172,11 +1191,15 @@
    5.54  
    5.55        const int jobject_oop_offset = 0;
    5.56        __ movptr(rbx_method, Address(rbx_method, jobject_oop_offset));  // dereference the jobject
    5.57 -      __ verify_oop(rbx_method);
    5.58  
    5.59 -      NOT_LP64(__ push(rarg2_required));
    5.60 -      __ push(rdi_pc);         // restore caller PC
    5.61 -      __ jmp(rbx_method_fce);  // jump to compiled entry
    5.62 +      __ movptr(rsi, rsp);
    5.63 +      __ subptr(rsp, 3 * wordSize);
    5.64 +      __ push(rax_pc);         // restore caller PC
    5.65 +
    5.66 +      __ movptr(__ argument_address(constant(2)), rarg0_code);
    5.67 +      __ movptr(__ argument_address(constant(1)), rarg1_actual);
    5.68 +      __ movptr(__ argument_address(constant(0)), rarg2_required);
    5.69 +      jump_from_method_handle(_masm, rbx_method, rax);
    5.70      }
    5.71      break;
    5.72  
    5.73 @@ -1195,7 +1218,7 @@
    5.74          __ null_check(rcx_recv);
    5.75          __ verify_oop(rcx_recv);
    5.76        }
    5.77 -      __ jmp(rbx_method_fie);
    5.78 +      jump_from_method_handle(_masm, rbx_method, rax);
    5.79      }
    5.80      break;
    5.81  
    5.82 @@ -1228,7 +1251,7 @@
    5.83        __ movptr(rbx_method, vtable_entry_addr);
    5.84  
    5.85        __ verify_oop(rbx_method);
    5.86 -      __ jmp(rbx_method_fie);
    5.87 +      jump_from_method_handle(_masm, rbx_method, rax);
    5.88      }
    5.89      break;
    5.90  
    5.91 @@ -1263,7 +1286,7 @@
    5.92                                   no_such_interface);
    5.93  
    5.94        __ verify_oop(rbx_method);
    5.95 -      __ jmp(rbx_method_fie);
    5.96 +      jump_from_method_handle(_masm, rbx_method, rax);
    5.97        __ hlt();
    5.98  
    5.99        __ bind(no_such_interface);
   5.100 @@ -1311,7 +1334,7 @@
   5.101          Register rbx_method = rbx_temp;
   5.102          __ load_heap_oop(rbx_method, rcx_mh_vmtarget);
   5.103          __ verify_oop(rbx_method);
   5.104 -        __ jmp(rbx_method_fie);
   5.105 +        jump_from_method_handle(_masm, rbx_method, rax);
   5.106        } else {
   5.107          __ load_heap_oop(rcx_recv, rcx_mh_vmtarget);
   5.108          __ verify_oop(rcx_recv);
     6.1 --- a/src/cpu/x86/vm/methodHandles_x86.hpp	Thu Jul 14 15:39:40 2011 -0700
     6.2 +++ b/src/cpu/x86/vm/methodHandles_x86.hpp	Fri Jul 15 15:35:50 2011 -0700
     6.3 @@ -291,6 +291,10 @@
     6.4                   "reference is a MH");
     6.5    }
     6.6  
     6.7 +  // Similar to InterpreterMacroAssembler::jump_from_interpreted.
     6.8 +  // Takes care of special dispatch from single stepping too.
     6.9 +  static void jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp);
    6.10 +
    6.11    static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN;
    6.12  
    6.13    static Register saved_last_sp_register() {
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/test/compiler/6990212/Test6990212.java	Fri Jul 15 15:35:50 2011 -0700
     7.3 @@ -0,0 +1,56 @@
     7.4 +/*
     7.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
     7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.7 + *
     7.8 + * This code is free software; you can redistribute it and/or modify it
     7.9 + * under the terms of the GNU General Public License version 2 only, as
    7.10 + * published by the Free Software Foundation.
    7.11 + *
    7.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    7.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    7.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    7.15 + * version 2 for more details (a copy is included in the LICENSE file that
    7.16 + * accompanied this code).
    7.17 + *
    7.18 + * You should have received a copy of the GNU General Public License version
    7.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    7.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    7.21 + *
    7.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    7.23 + * or visit www.oracle.com if you need additional information or have any
    7.24 + * questions.
    7.25 + *
    7.26 + */
    7.27 +
    7.28 +/**
    7.29 + * @test
    7.30 + * @bug 6990212
    7.31 + * @summary JSR 292 JVMTI MethodEnter hook is not called for JSR 292 bootstrap and target methods
    7.32 + *
    7.33 + * @run main Test6990212
    7.34 + */
    7.35 +
    7.36 +import java.lang.invoke.*;
    7.37 +
    7.38 +interface intf {
    7.39 +    public Object target();
    7.40 +}
    7.41 +
    7.42 +public class Test6990212 implements intf {
    7.43 +    public Object target() {
    7.44 +        return null;
    7.45 +    }
    7.46 +
    7.47 +    public static void main(String[] args) throws Throwable {
    7.48 +        // Build an interface invoke and then invoke it on something
    7.49 +        // that doesn't implement the interface to test the
    7.50 +        // raiseException path.
    7.51 +        MethodHandle target = MethodHandles.lookup().findVirtual(intf.class, "target",  MethodType.methodType(Object.class));
    7.52 +        try {
    7.53 +            target.invoke(new Object());
    7.54 +        } catch (ClassCastException cce) {
    7.55 +            // everything is ok
    7.56 +            System.out.println("got expected ClassCastException");
    7.57 +        }
    7.58 +    }
    7.59 +}

mercurial