hotspot/src/share/vm/prims/methodHandles.cpp
changeset 36819 bca375d368ed
parent 36199 855b44ce93c0
child 36822 cdc493d7bc9a
--- 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;