7187554: JSR 292: JVMTI PopFrame needs to handle appendix arguments
Summary: Restore the appendix argument after PopFrame() call
Reviewed-by: twisti, coleenp
Contributed-by: serguei.spitsyn@oracle.com
--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Tue Aug 06 14:28:48 2013 +0400
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Tue Aug 06 16:33:59 2013 -0700
@@ -1887,6 +1887,27 @@
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
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Tue Aug 06 14:28:48 2013 +0400
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Tue Aug 06 16:33:59 2013 -0700
@@ -1920,6 +1920,29 @@
__ 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
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Tue Aug 06 14:28:48 2013 +0400
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Tue Aug 06 16:33:59 2013 -0700
@@ -1929,6 +1929,29 @@
__ 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
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Tue Aug 06 14:28:48 2013 +0400
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Tue Aug 06 16:33:59 2013 -0700
@@ -2557,6 +2557,26 @@
*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 @@
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();
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp Tue Aug 06 14:28:48 2013 +0400
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp Tue Aug 06 16:33:59 2013 -0700
@@ -976,6 +976,32 @@
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.)
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Tue Aug 06 14:28:48 2013 +0400
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Tue Aug 06 16:33:59 2013 -0700
@@ -151,6 +151,7 @@
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 ) \
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Tue Aug 06 14:28:48 2013 +0400
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Tue Aug 06 16:33:59 2013 -0700
@@ -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") \
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Tue Aug 06 14:28:48 2013 +0400
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Tue Aug 06 16:33:59 2013 -0700
@@ -1209,3 +1209,26 @@
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
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Tue Aug 06 14:28:48 2013 +0400
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Tue Aug 06 16:33:59 2013 -0700
@@ -95,6 +95,9 @@
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