diff --git a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp index 7b9a494dff0034e2a41ad71780b1c3aa53b17490..b6f8a5a5d1a00772333cbbae4062aeacf2afdef3 100644 --- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp +++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp @@ -1887,6 +1887,27 @@ void TemplateInterpreterGenerator::generate_throw_exception() { if (ProfileInterpreter) { __ set_method_data_pointer_for_bcp(); } + +#if INCLUDE_JVMTI + if (EnableInvokeDynamic) { + Label L_done; + + __ ldub(Address(Lbcp, 0), G1_scratch); // Load current bytecode + __ cmp_and_br_short(G1_scratch, Bytecodes::_invokestatic, Assembler::notEqual, Assembler::pn, L_done); + + // The member name argument must be restored if _invokestatic is re-executed after a PopFrame call. + // Detect such a case in the InterpreterRuntime function and return the member name argument, or NULL. + + __ call_VM(G1_scratch, CAST_FROM_FN_PTR(address, InterpreterRuntime::member_name_arg_or_null), I0, Lmethod, Lbcp); + + __ br_null(G1_scratch, false, Assembler::pn, L_done); + __ delayed()->nop(); + + __ st_ptr(G1_scratch, Lesp, wordSize); + __ bind(L_done); + } +#endif // INCLUDE_JVMTI + // Resume bytecode interpretation at the current bcp __ dispatch_next(vtos); // end of JVMTI PopFrame support diff --git a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp index 2efa59f8b338cd0f449d75755ac83869c4e8a86f..52e459900c7de33f1d9ff3af51d3763d0bbd489e 100644 --- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp +++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp @@ -1920,6 +1920,29 @@ void TemplateInterpreterGenerator::generate_throw_exception() { __ get_thread(thread); __ movl(Address(thread, JavaThread::popframe_condition_offset()), JavaThread::popframe_inactive); +#if INCLUDE_JVMTI + if (EnableInvokeDynamic) { + Label L_done; + const Register local0 = rdi; + + __ cmpb(Address(rsi, 0), Bytecodes::_invokestatic); + __ jcc(Assembler::notEqual, L_done); + + // The member name argument must be restored if _invokestatic is re-executed after a PopFrame call. + // Detect such a case in the InterpreterRuntime function and return the member name argument, or NULL. + + __ get_method(rdx); + __ movptr(rax, Address(local0, 0)); + __ call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::member_name_arg_or_null), rax, rdx, rsi); + + __ testptr(rax, rax); + __ jcc(Assembler::zero, L_done); + + __ movptr(Address(rbx, 0), rax); + __ bind(L_done); + } +#endif // INCLUDE_JVMTI + __ dispatch_next(vtos); // end of PopFrame support diff --git a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp index f0a2258a70e59813c9dd875617dd6662499665c6..4ac85c49578b3c7935a065dd86aa5d23ad41a397 100644 --- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp +++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp @@ -1929,6 +1929,29 @@ void TemplateInterpreterGenerator::generate_throw_exception() { __ movl(Address(r15_thread, JavaThread::popframe_condition_offset()), JavaThread::popframe_inactive); +#if INCLUDE_JVMTI + if (EnableInvokeDynamic) { + Label L_done; + const Register local0 = r14; + + __ cmpb(Address(r13, 0), Bytecodes::_invokestatic); + __ jcc(Assembler::notEqual, L_done); + + // The member name argument must be restored if _invokestatic is re-executed after a PopFrame call. + // Detect such a case in the InterpreterRuntime function and return the member name argument, or NULL. + + __ get_method(rdx); + __ movptr(rax, Address(local0, 0)); + __ call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::member_name_arg_or_null), rax, rdx, r13); + + __ testptr(rax, rax); + __ jcc(Assembler::zero, L_done); + + __ movptr(Address(rbx, 0), rax); + __ bind(L_done); + } +#endif // INCLUDE_JVMTI + __ dispatch_next(vtos); // end of PopFrame support diff --git a/src/share/vm/classfile/javaClasses.cpp b/src/share/vm/classfile/javaClasses.cpp index 678cb2dcd1399510ba54e4c2602b07c9b8e38cf1..8e94d834ad93883b413cf118b606a103f270480e 100644 --- a/src/share/vm/classfile/javaClasses.cpp +++ b/src/share/vm/classfile/javaClasses.cpp @@ -2557,6 +2557,26 @@ void java_lang_ref_SoftReference::set_clock(jlong value) { *offset = value; } +// Support for java_lang_invoke_DirectMethodHandle + +int java_lang_invoke_DirectMethodHandle::_member_offset; + +oop java_lang_invoke_DirectMethodHandle::member(oop dmh) { + oop member_name = NULL; + bool is_dmh = dmh->is_oop() && java_lang_invoke_DirectMethodHandle::is_instance(dmh); + assert(is_dmh, "a DirectMethodHandle oop is expected"); + if (is_dmh) { + member_name = dmh->obj_field(member_offset_in_bytes()); + } + return member_name; +} + +void java_lang_invoke_DirectMethodHandle::compute_offsets() { + Klass* klass_oop = SystemDictionary::DirectMethodHandle_klass(); + if (klass_oop != NULL && EnableInvokeDynamic) { + compute_offset(_member_offset, klass_oop, vmSymbols::member_name(), vmSymbols::java_lang_invoke_MemberName_signature()); + } +} // Support for java_lang_invoke_MethodHandle @@ -3205,6 +3225,7 @@ void JavaClasses::compute_offsets() { java_lang_ThreadGroup::compute_offsets(); if (EnableInvokeDynamic) { java_lang_invoke_MethodHandle::compute_offsets(); + java_lang_invoke_DirectMethodHandle::compute_offsets(); java_lang_invoke_MemberName::compute_offsets(); java_lang_invoke_LambdaForm::compute_offsets(); java_lang_invoke_MethodType::compute_offsets(); diff --git a/src/share/vm/classfile/javaClasses.hpp b/src/share/vm/classfile/javaClasses.hpp index 899d3ba48a33feb113f7cc92d1bdd0e536207920..8a8e801f38737c965fb63c56f770060bfb2cbb27 100644 --- a/src/share/vm/classfile/javaClasses.hpp +++ b/src/share/vm/classfile/javaClasses.hpp @@ -976,6 +976,32 @@ class java_lang_invoke_MethodHandle: AllStatic { static int form_offset_in_bytes() { return _form_offset; } }; +// Interface to java.lang.invoke.DirectMethodHandle objects + +class java_lang_invoke_DirectMethodHandle: AllStatic { + friend class JavaClasses; + + private: + static int _member_offset; // the MemberName of this DMH + + static void compute_offsets(); + + public: + // Accessors + static oop member(oop mh); + + // Testers + static bool is_subclass(Klass* klass) { + return klass->is_subclass_of(SystemDictionary::DirectMethodHandle_klass()); + } + static bool is_instance(oop obj) { + return obj != NULL && is_subclass(obj->klass()); + } + + // Accessors for code generation: + static int member_offset_in_bytes() { return _member_offset; } +}; + // Interface to java.lang.invoke.LambdaForm objects // (These are a private interface for managing adapter code generation.) diff --git a/src/share/vm/classfile/systemDictionary.hpp b/src/share/vm/classfile/systemDictionary.hpp index a2a1a8575173111a982176fd05cbce265f3b0e93..85735a732fa9a9a42a00c8ad70df94fa9e30d1de 100644 --- a/src/share/vm/classfile/systemDictionary.hpp +++ b/src/share/vm/classfile/systemDictionary.hpp @@ -151,6 +151,7 @@ class SymbolPropertyTable; do_klass(reflect_CallerSensitive_klass, sun_reflect_CallerSensitive, Opt ) \ \ /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \ + do_klass(DirectMethodHandle_klass, java_lang_invoke_DirectMethodHandle, Opt ) \ do_klass(MethodHandle_klass, java_lang_invoke_MethodHandle, Pre_JSR292 ) \ do_klass(MemberName_klass, java_lang_invoke_MemberName, Pre_JSR292 ) \ do_klass(MethodHandleNatives_klass, java_lang_invoke_MethodHandleNatives, Pre_JSR292 ) \ diff --git a/src/share/vm/classfile/vmSymbols.hpp b/src/share/vm/classfile/vmSymbols.hpp index df3702371671b6b7108c1207d972bac0d3c865dd..067cf5033057b18c5a742896dc96e4a720b38c0a 100644 --- a/src/share/vm/classfile/vmSymbols.hpp +++ b/src/share/vm/classfile/vmSymbols.hpp @@ -255,6 +255,7 @@ /* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \ template(java_lang_invoke_CallSite, "java/lang/invoke/CallSite") \ template(java_lang_invoke_ConstantCallSite, "java/lang/invoke/ConstantCallSite") \ + template(java_lang_invoke_DirectMethodHandle, "java/lang/invoke/DirectMethodHandle") \ template(java_lang_invoke_MutableCallSite, "java/lang/invoke/MutableCallSite") \ template(java_lang_invoke_VolatileCallSite, "java/lang/invoke/VolatileCallSite") \ template(java_lang_invoke_MethodHandle, "java/lang/invoke/MethodHandle") \ @@ -352,6 +353,7 @@ template(thread_id_name, "tid") \ template(newInstance0_name, "newInstance0") \ template(limit_name, "limit") \ + template(member_name, "member") \ template(forName_name, "forName") \ template(forName0_name, "forName0") \ template(isJavaIdentifierStart_name, "isJavaIdentifierStart") \ diff --git a/src/share/vm/interpreter/interpreterRuntime.cpp b/src/share/vm/interpreter/interpreterRuntime.cpp index f5f9d39bcec27ea576a0ff0f5c02ac4c4226b46a..4a3019f867fdc87ab5b110d6ca7642ad40228dfe 100644 --- a/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/src/share/vm/interpreter/interpreterRuntime.cpp @@ -1209,3 +1209,26 @@ IRT_LEAF(void, InterpreterRuntime::popframe_move_outgoing_args(JavaThread* threa size_of_arguments * Interpreter::stackElementSize); IRT_END #endif + +#if INCLUDE_JVMTI +// This is a support of the JVMTI PopFrame interface. +// Make sure it is an invokestatic of a polymorphic intrinsic that has a member_name argument +// and return it as a vm_result so that it can be reloaded in the list of invokestatic parameters. +// The dmh argument is a reference to a DirectMethoHandle that has a member name field. +IRT_ENTRY(void, InterpreterRuntime::member_name_arg_or_null(JavaThread* thread, address dmh, + Method* method, address bcp)) + Bytecodes::Code code = Bytecodes::code_at(method, bcp); + if (code != Bytecodes::_invokestatic) { + return; + } + ConstantPool* cpool = method->constants(); + int cp_index = Bytes::get_native_u2(bcp + 1) + ConstantPool::CPCACHE_INDEX_TAG; + Symbol* cname = cpool->klass_name_at(cpool->klass_ref_index_at(cp_index)); + Symbol* mname = cpool->name_ref_at(cp_index); + + if (MethodHandles::has_member_arg(cname, mname)) { + oop member_name = java_lang_invoke_DirectMethodHandle::member((oop)dmh); + thread->set_vm_result(member_name); + } +IRT_END +#endif // INCLUDE_JVMTI diff --git a/src/share/vm/interpreter/interpreterRuntime.hpp b/src/share/vm/interpreter/interpreterRuntime.hpp index d46c43e94e0310821ec93735fe9dd234010503fc..ad44210ef4db2aa0fe644fb3115cd5de5039ae33 100644 --- a/src/share/vm/interpreter/interpreterRuntime.hpp +++ b/src/share/vm/interpreter/interpreterRuntime.hpp @@ -95,6 +95,9 @@ class InterpreterRuntime: AllStatic { static void create_exception(JavaThread* thread, char* name, char* message); static void create_klass_exception(JavaThread* thread, char* name, oopDesc* obj); static address exception_handler_for_exception(JavaThread* thread, oopDesc* exception); +#if INCLUDE_JVMTI + static void member_name_arg_or_null(JavaThread* thread, address dmh, Method* m, address bcp); +#endif static void throw_pending_exception(JavaThread* thread); // Statics & fields