8149644: Integrate VarHandles
authorpsandoz
Thu, 24 Mar 2016 11:21:49 +0100
changeset 36819 bca375d368ed
parent 36818 b40330c06dea
child 36821 cd1a170c9019
8149644: Integrate VarHandles Reviewed-by: kvn, vlivanov
hotspot/src/share/vm/ci/ciEnv.cpp
hotspot/src/share/vm/classfile/systemDictionary.cpp
hotspot/src/share/vm/classfile/systemDictionary.hpp
hotspot/src/share/vm/classfile/vmSymbols.hpp
hotspot/src/share/vm/interpreter/linkResolver.cpp
hotspot/src/share/vm/interpreter/linkResolver.hpp
hotspot/src/share/vm/interpreter/rewriter.cpp
hotspot/src/share/vm/oops/method.cpp
hotspot/src/share/vm/prims/methodHandles.cpp
hotspot/src/share/vm/prims/methodHandles.hpp
--- a/hotspot/src/share/vm/ci/ciEnv.cpp	Thu Mar 24 09:09:52 2016 +0100
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp	Thu Mar 24 11:21:49 2016 +0100
@@ -773,7 +773,7 @@
     Symbol* sig_sym  = cpool->signature_ref_at(index);
 
     if (cpool->has_preresolution()
-        || (holder == ciEnv::MethodHandle_klass() &&
+        || ((holder == ciEnv::MethodHandle_klass() || holder == ciEnv::VarHandle_klass()) &&
             MethodHandles::is_signature_polymorphic_name(holder->get_Klass(), name_sym))) {
       // Short-circuit lookups for JSR 292-related call sites.
       // That is, do not rely only on name-based lookups, because they may fail
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Thu Mar 24 09:09:52 2016 +0100
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Thu Mar 24 11:21:49 2016 +0100
@@ -2405,7 +2405,8 @@
   return empty;
 }
 
-methodHandle SystemDictionary::find_method_handle_invoker(Symbol* name,
+methodHandle SystemDictionary::find_method_handle_invoker(KlassHandle klass,
+                                                          Symbol* name,
                                                           Symbol* signature,
                                                           KlassHandle accessing_klass,
                                                           Handle *appendix_result,
@@ -2416,7 +2417,6 @@
   Handle method_type =
     SystemDictionary::find_method_handle_type(signature, accessing_klass, CHECK_(empty));
 
-  KlassHandle  mh_klass = SystemDictionary::MethodHandle_klass();
   int ref_kind = JVM_REF_invokeVirtual;
   Handle name_str = StringTable::intern(name, CHECK_(empty));
   objArrayHandle appendix_box = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1, CHECK_(empty));
@@ -2431,7 +2431,7 @@
   JavaCallArguments args;
   args.push_oop(accessing_klass()->java_mirror());
   args.push_int(ref_kind);
-  args.push_oop(mh_klass()->java_mirror());
+  args.push_oop(klass()->java_mirror());
   args.push_oop(name_str());
   args.push_oop(method_type());
   args.push_oop(appendix_box());
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp	Thu Mar 24 09:09:52 2016 +0100
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp	Thu Mar 24 11:21:49 2016 +0100
@@ -152,6 +152,7 @@
   /* 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                 ) \
+  do_klass(VarHandle_klass,                             java_lang_invoke_VarHandle,                Pre                 ) \
   do_klass(MemberName_klass,                            java_lang_invoke_MemberName,               Pre                 ) \
   do_klass(MethodHandleNatives_klass,                   java_lang_invoke_MethodHandleNatives,      Pre                 ) \
   do_klass(LambdaForm_klass,                            java_lang_invoke_LambdaForm,               Opt                 ) \
@@ -515,7 +516,8 @@
   // JSR 292
   // find a java.lang.invoke.MethodHandle.invoke* method for a given signature
   // (asks Java to compute it if necessary, except in a compiler thread)
-  static methodHandle find_method_handle_invoker(Symbol* name,
+  static methodHandle find_method_handle_invoker(KlassHandle klass,
+                                                 Symbol* name,
                                                  Symbol* signature,
                                                  KlassHandle accessing_klass,
                                                  Handle *appendix_result,
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Thu Mar 24 09:09:52 2016 +0100
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Thu Mar 24 11:21:49 2016 +0100
@@ -279,6 +279,7 @@
   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")            \
+  template(java_lang_invoke_VarHandle,                "java/lang/invoke/VarHandle")               \
   template(java_lang_invoke_MethodType,               "java/lang/invoke/MethodType")              \
   template(java_lang_invoke_MethodType_signature,     "Ljava/lang/invoke/MethodType;")            \
   template(java_lang_invoke_MemberName_signature,     "Ljava/lang/invoke/MemberName;")            \
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp	Thu Mar 24 09:09:52 2016 +0100
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp	Thu Mar 24 11:21:49 2016 +0100
@@ -90,10 +90,16 @@
 void CallInfo::set_handle(const methodHandle& resolved_method,
                           Handle resolved_appendix,
                           Handle resolved_method_type, TRAPS) {
+  set_handle(SystemDictionary::MethodHandle_klass(), resolved_method, resolved_appendix, resolved_method_type, CHECK);
+}
+
+void CallInfo::set_handle(KlassHandle resolved_klass,
+                          const methodHandle& resolved_method,
+                          Handle resolved_appendix,
+                          Handle resolved_method_type, TRAPS) {
   if (resolved_method.is_null()) {
     THROW_MSG(vmSymbols::java_lang_InternalError(), "resolved method is null");
   }
-  KlassHandle resolved_klass = SystemDictionary::MethodHandle_klass();
   assert(resolved_method->intrinsic_id() == vmIntrinsics::_invokeBasic ||
          resolved_method->is_compiled_lambda_form(),
          "linkMethod must return one of these");
@@ -426,7 +432,8 @@
                   vmIntrinsics::name_at(iid), klass->external_name(),
                   name->as_C_string(), full_signature->as_C_string());
   }
-  if (klass() == SystemDictionary::MethodHandle_klass() &&
+  if ((klass() == SystemDictionary::MethodHandle_klass() ||
+       klass() == SystemDictionary::VarHandle_klass()) &&
       iid != vmIntrinsics::_none) {
     if (MethodHandles::is_signature_polymorphic_intrinsic(iid)) {
       // Most of these do not need an up-call to Java to resolve, so can be done anywhere.
@@ -475,6 +482,7 @@
       Handle appendix;
       Handle method_type;
       methodHandle result = SystemDictionary::find_method_handle_invoker(
+                                                            klass,
                                                             name,
                                                             full_signature,
                                                             link_info.current_klass(),
@@ -1554,13 +1562,15 @@
                                        const LinkInfo& link_info,
                                        TRAPS) {
   // JSR 292:  this must be an implicitly generated method MethodHandle.invokeExact(*...) or similar
-  assert(link_info.resolved_klass()() == SystemDictionary::MethodHandle_klass(), "");
+  KlassHandle resolved_klass = link_info.resolved_klass();
+  assert(resolved_klass() == SystemDictionary::MethodHandle_klass() ||
+         resolved_klass() == SystemDictionary::VarHandle_klass(), "");
   assert(MethodHandles::is_signature_polymorphic_name(link_info.name()), "");
   Handle       resolved_appendix;
   Handle       resolved_method_type;
   methodHandle resolved_method = lookup_polymorphic_method(link_info,
                                        &resolved_appendix, &resolved_method_type, CHECK);
-  result.set_handle(resolved_method, resolved_appendix, resolved_method_type, CHECK);
+  result.set_handle(resolved_klass, resolved_method, resolved_appendix, resolved_method_type, CHECK);
 }
 
 static void wrap_invokedynamic_exception(TRAPS) {
--- a/hotspot/src/share/vm/interpreter/linkResolver.hpp	Thu Mar 24 09:09:52 2016 +0100
+++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp	Thu Mar 24 11:21:49 2016 +0100
@@ -69,6 +69,9 @@
                    int vtable_index, TRAPS);
   void set_handle(const methodHandle& resolved_method,
                   Handle resolved_appendix, Handle resolved_method_type, TRAPS);
+  void set_handle(KlassHandle resolved_klass,
+                  const methodHandle& resolved_method,
+                  Handle resolved_appendix, Handle resolved_method_type, TRAPS);
   void set_common(KlassHandle resolved_klass, KlassHandle selected_klass,
                   const methodHandle& resolved_method,
                   const methodHandle& selected_method,
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp	Thu Mar 24 09:09:52 2016 +0100
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp	Thu Mar 24 11:21:49 2016 +0100
@@ -54,8 +54,10 @@
         add_resolved_references_entry(i);
         break;
       case JVM_CONSTANT_Utf8:
-        if (_pool->symbol_at(i) == vmSymbols::java_lang_invoke_MethodHandle())
+        if (_pool->symbol_at(i) == vmSymbols::java_lang_invoke_MethodHandle() ||
+            _pool->symbol_at(i) == vmSymbols::java_lang_invoke_VarHandle()) {
           saw_mh_symbol = true;
+        }
         break;
     }
   }
@@ -200,6 +202,12 @@
           // we may need a resolved_refs entry for the appendix
           add_invokedynamic_resolved_references_entries(cp_index, cache_index);
           status = +1;
+        } else if (_pool->klass_ref_at_noresolve(cp_index) == vmSymbols::java_lang_invoke_VarHandle() &&
+                   MethodHandles::is_signature_polymorphic_name(SystemDictionary::VarHandle_klass(),
+                                                                _pool->name_ref_at(cp_index))) {
+          // we may need a resolved_refs entry for the appendix
+          add_invokedynamic_resolved_references_entries(cp_index, cache_index);
+          status = +1;
         } else {
           status = -1;
         }
--- a/hotspot/src/share/vm/oops/method.cpp	Thu Mar 24 09:09:52 2016 +0100
+++ b/hotspot/src/share/vm/oops/method.cpp	Thu Mar 24 11:21:49 2016 +0100
@@ -1351,11 +1351,16 @@
   // ditto for method and signature:
   vmSymbols::SID  name_id = vmSymbols::find_sid(name());
   if (klass_id != vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_MethodHandle)
-      && name_id == vmSymbols::NO_SID)
+      && klass_id != vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_VarHandle)
+      && name_id == vmSymbols::NO_SID) {
     return;
+  }
   vmSymbols::SID   sig_id = vmSymbols::find_sid(signature());
   if (klass_id != vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_MethodHandle)
-      && sig_id == vmSymbols::NO_SID)  return;
+      && klass_id != vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_VarHandle)
+      && sig_id == vmSymbols::NO_SID) {
+    return;
+  }
   jshort flags = access_flags().as_short();
 
   vmIntrinsics::ID id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags);
@@ -1383,8 +1388,9 @@
     }
     break;
 
-  // Signature-polymorphic methods: MethodHandle.invoke*, InvokeDynamic.*.
+  // Signature-polymorphic methods: MethodHandle.invoke*, InvokeDynamic.*., VarHandle
   case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_MethodHandle):
+  case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_VarHandle):
     if (!is_native())  break;
     id = MethodHandles::signature_polymorphic_name_id(method_holder(), name());
     if (is_static() != MethodHandles::is_signature_polymorphic_static(id))
--- a/hotspot/src/share/vm/prims/methodHandles.cpp	Thu Mar 24 09:09:52 2016 +0100
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp	Thu Mar 24 11:21:49 2016 +0100
@@ -318,9 +318,9 @@
 
 // JVM 2.9 Special Methods:
 // A method is signature polymorphic if and only if all of the following conditions hold :
-// * It is declared in the java.lang.invoke.MethodHandle class.
+// * It is declared in the java.lang.invoke.MethodHandle/VarHandle classes.
 // * It has a single formal parameter of type Object[].
-// * It has a return type of Object.
+// * It has a return type of Object for a polymorphic return type, otherwise a fixed return type.
 // * It has the ACC_VARARGS and ACC_NATIVE flags set.
 bool MethodHandles::is_method_handle_invoke_name(Klass* klass, Symbol* name) {
   if (klass == NULL)
@@ -328,14 +328,36 @@
   // The following test will fail spuriously during bootstrap of MethodHandle itself:
   //    if (klass != SystemDictionary::MethodHandle_klass())
   // Test the name instead:
-  if (klass->name() != vmSymbols::java_lang_invoke_MethodHandle())
+  if (klass->name() != vmSymbols::java_lang_invoke_MethodHandle() &&
+      klass->name() != vmSymbols::java_lang_invoke_VarHandle()) {
     return false;
+  }
+
+  // Look up signature polymorphic method with polymorphic return type
   Symbol* poly_sig = vmSymbols::object_array_object_signature();
-  Method* m = InstanceKlass::cast(klass)->find_method(name, poly_sig);
-  if (m == NULL)  return false;
-  int required = JVM_ACC_NATIVE | JVM_ACC_VARARGS;
-  int flags = m->access_flags().as_int();
-  return (flags & required) == required;
+  InstanceKlass* iklass = InstanceKlass::cast(klass);
+  Method* m = iklass->find_method(name, poly_sig);
+  if (m != NULL) {
+    int required = JVM_ACC_NATIVE | JVM_ACC_VARARGS;
+    int flags = m->access_flags().as_int();
+    if ((flags & required) == required) {
+      return true;
+    }
+  }
+
+  // Look up signature polymorphic method with non-polymorphic (non Object) return type
+  int me;
+  int ms = iklass->find_method_by_name(name, &me);
+  if (ms == -1) return false;
+  for (; ms < me; ms++) {
+    Method* m = iklass->methods()->at(ms);
+    int required = JVM_ACC_NATIVE | JVM_ACC_VARARGS;
+    int flags = m->access_flags().as_int();
+    if ((flags & required) == required && ArgumentCount(m->signature()).size() == 1) {
+      return true;
+    }
+  }
+  return false;
 }
 
 
@@ -395,8 +417,16 @@
   // Cover the case of invokeExact and any future variants of invokeFoo.
   Klass* mh_klass = SystemDictionary::well_known_klass(
                               SystemDictionary::WK_KLASS_ENUM_NAME(MethodHandle_klass) );
-  if (mh_klass != NULL && is_method_handle_invoke_name(mh_klass, name))
+  if (mh_klass != NULL && is_method_handle_invoke_name(mh_klass, name)) {
     return vmIntrinsics::_invokeGeneric;
+  }
+
+  // Cover the case of methods on VarHandle.
+  Klass* vh_klass = SystemDictionary::well_known_klass(
+                              SystemDictionary::WK_KLASS_ENUM_NAME(VarHandle_klass) );
+  if (vh_klass != NULL && is_method_handle_invoke_name(vh_klass, name)) {
+    return vmIntrinsics::_invokeGeneric;
+  }
 
   // Note: The pseudo-intrinsic _compiledLambdaForm is never linked against.
   // Instead it is used to mark lambda forms bound to invokehandle or invokedynamic.
@@ -405,7 +435,8 @@
 
 vmIntrinsics::ID MethodHandles::signature_polymorphic_name_id(Klass* klass, Symbol* name) {
   if (klass != NULL &&
-      klass->name() == vmSymbols::java_lang_invoke_MethodHandle()) {
+      (klass->name() == vmSymbols::java_lang_invoke_MethodHandle() ||
+       klass->name() == vmSymbols::java_lang_invoke_VarHandle())) {
     vmIntrinsics::ID iid = signature_polymorphic_name_id(name);
     if (iid != vmIntrinsics::_none)
       return iid;
--- a/hotspot/src/share/vm/prims/methodHandles.hpp	Thu Mar 24 09:09:52 2016 +0100
+++ b/hotspot/src/share/vm/prims/methodHandles.hpp	Thu Mar 24 11:21:49 2016 +0100
@@ -120,7 +120,8 @@
             iid <= vmIntrinsics::_linkToInterface);
   }
   static bool has_member_arg(Symbol* klass, Symbol* name) {
-    if ((klass == vmSymbols::java_lang_invoke_MethodHandle()) &&
+    if ((klass == vmSymbols::java_lang_invoke_MethodHandle() ||
+         klass == vmSymbols::java_lang_invoke_VarHandle()) &&
         is_signature_polymorphic_name(name)) {
       vmIntrinsics::ID iid = signature_polymorphic_name_id(name);
       return has_member_arg(iid);