changeset 5580:b1d29549dca7 hs24.80-b02

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
author sspitsyn
date Fri, 14 Feb 2014 01:52:08 -0800
parents eec4f2185a7d
children a1c6662d6d87 418fb371f2b9
files src/cpu/sparc/vm/templateInterpreter_sparc.cpp src/cpu/x86/vm/templateInterpreter_x86_32.cpp src/cpu/x86/vm/templateInterpreter_x86_64.cpp src/share/vm/classfile/javaClasses.cpp src/share/vm/classfile/javaClasses.hpp src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/interpreter/interpreterRuntime.cpp src/share/vm/interpreter/interpreterRuntime.hpp src/share/vm/oops/constantPoolOop.cpp
diffstat 10 files changed, 143 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Wed Feb 12 10:42:52 2014 +0000
+++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Fri Feb 14 01:52:08 2014 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1873,6 +1873,25 @@
   if (ProfileInterpreter) {
     __ set_method_data_pointer_for_bcp();
   }
+
+  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);
+  }
+
   // Resume bytecode interpretation at the current bcp
   __ dispatch_next(vtos);
   // end of JVMTI PopFrame support
--- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Wed Feb 12 10:42:52 2014 +0000
+++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Fri Feb 14 01:52:08 2014 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1789,6 +1789,27 @@
   __ get_thread(thread);
   __ movl(Address(thread, JavaThread::popframe_condition_offset()), JavaThread::popframe_inactive);
 
+  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);
+  }
+
   __ dispatch_next(vtos);
   // end of PopFrame support
 
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Wed Feb 12 10:42:52 2014 +0000
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Fri Feb 14 01:52:08 2014 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1815,6 +1815,27 @@
   __ movl(Address(r15_thread, JavaThread::popframe_condition_offset()),
           JavaThread::popframe_inactive);
 
+  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);
+  }
+
   __ dispatch_next(vtos);
   // end of PopFrame support
 
--- a/src/share/vm/classfile/javaClasses.cpp	Wed Feb 12 10:42:52 2014 +0000
+++ b/src/share/vm/classfile/javaClasses.cpp	Fri Feb 14 01:52:08 2014 -0800
@@ -2388,6 +2388,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() {
+  klassOop 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
 
@@ -3007,6 +3027,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/src/share/vm/classfile/javaClasses.hpp	Wed Feb 12 10:42:52 2014 +0000
+++ b/src/share/vm/classfile/javaClasses.hpp	Fri Feb 14 01:52:08 2014 -0800
@@ -915,6 +915,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(klassOop klass) {
+    return Klass::cast(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/src/share/vm/classfile/systemDictionary.hpp	Wed Feb 12 10:42:52 2014 +0000
+++ b/src/share/vm/classfile/systemDictionary.hpp	Fri Feb 14 01:52:08 2014 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -151,6 +151,7 @@
   do_klass(MemberName_klass,                            java_lang_invoke_MemberName,               Pre_JSR292          ) \
   do_klass(MethodHandleNatives_klass,                   java_lang_invoke_MethodHandleNatives,      Pre_JSR292          ) \
   do_klass(LambdaForm_klass,                            java_lang_invoke_LambdaForm,               Opt                 ) \
+  do_klass(DirectMethodHandle_klass,                    java_lang_invoke_DirectMethodHandle,       Opt                 ) \
   do_klass(MethodType_klass,                            java_lang_invoke_MethodType,               Pre_JSR292          ) \
   do_klass(BootstrapMethodError_klass,                  java_lang_BootstrapMethodError,            Pre_JSR292          ) \
   do_klass(CallSite_klass,                              java_lang_invoke_CallSite,                 Pre_JSR292          ) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Wed Feb 12 10:42:52 2014 +0000
+++ b/src/share/vm/classfile/vmSymbols.hpp	Fri Feb 14 01:52:08 2014 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -243,6 +243,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")            \
@@ -338,6 +339,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/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Feb 12 10:42:52 2014 +0000
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Fri Feb 14 01:52:08 2014 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1222,3 +1222,24 @@
                        size_of_arguments * Interpreter::stackElementSize);
 IRT_END
 #endif
+
+// 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,
+                                                            methodOopDesc* method, address bcp))
+  Bytecodes::Code code = Bytecodes::code_at(method, bcp);
+  if (code != Bytecodes::_invokestatic) {
+    return;
+  }
+  constantPoolOopDesc* cpool = method->constants();
+  int cp_index = Bytes::get_native_u2(bcp + 1) + constantPoolOopDesc::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
--- a/src/share/vm/interpreter/interpreterRuntime.hpp	Wed Feb 12 10:42:52 2014 +0000
+++ b/src/share/vm/interpreter/interpreterRuntime.hpp	Fri Feb 14 01:52:08 2014 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -106,6 +106,7 @@
   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);
+  static void    member_name_arg_or_null(JavaThread* thread, address dmh, methodOopDesc* m, address bcp);
   static void    throw_pending_exception(JavaThread* thread);
 
   // Statics & fields
--- a/src/share/vm/oops/constantPoolOop.cpp	Wed Feb 12 10:42:52 2014 +0000
+++ b/src/share/vm/oops/constantPoolOop.cpp	Fri Feb 14 01:52:08 2014 -0800
@@ -1078,7 +1078,7 @@
   int new_size = old_size + delta_size;
   int min_size = (delta_size > 0) ? old_size : new_size;
 
-  typeArrayHandle new_ops = oopFactory::new_permanent_shortArray(new_size, CHECK);
+  typeArrayHandle new_ops = oopFactory::new_permanent_intArray(new_size, CHECK);
 
   // Set index in the resized array for existing elements only
   for (int idx = 0; idx < min_len; idx++) {
@@ -1106,7 +1106,7 @@
   assert(delta_len  > 0 && delta_size > 0, "extended operands array must be bigger");
 
   if (operand_array_length(operands()) == 0) {
-    typeArrayHandle new_ops = oopFactory::new_permanent_shortArray(delta_size, CHECK);
+    typeArrayHandle new_ops = oopFactory::new_permanent_intArray(delta_size, CHECK);
     // The first element index defines the offset of second part
     operand_offset_at_put(new_ops(), 0, 2*delta_len); // offset in new array
     set_operands(new_ops());
@@ -1150,7 +1150,7 @@
       int from_len = from_cp->operands()->length();
       int old_off  = old_oplen * sizeof(u2);
       int from_off = from_oplen * sizeof(u2);
-      typeArrayHandle new_operands = oopFactory::new_permanent_shortArray(old_len + from_len, CHECK);
+      typeArrayHandle new_operands = oopFactory::new_permanent_intArray(old_len + from_len, CHECK);
       int fillp = 0, len = 0;
       // first part of dest
       Copy::conjoint_memory_atomic(to_cp->operands()->short_at_addr(0),