8149644: Integrate VarHandles
authorpsandoz
Thu, 24 Mar 2016 11:21:37 +0100
changeset 36995 e19153419efd
parent 36706 ccbc5ff54c9a
child 36996 2c3a5307865f
8149644: Integrate VarHandles Reviewed-by: mcimadamore, forax
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Tue Mar 15 14:50:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Thu Mar 24 11:21:37 2016 +0100
@@ -151,6 +151,7 @@
     public final Type cloneableType;
     public final Type serializableType;
     public final Type serializedLambdaType;
+    public final Type varHandleType;
     public final Type methodHandleType;
     public final Type methodHandleLookupType;
     public final Type methodTypeType;
@@ -419,6 +420,7 @@
         throwableType = enterClass("java.lang.Throwable");
         serializableType = enterClass("java.io.Serializable");
         serializedLambdaType = enterClass("java.lang.invoke.SerializedLambda");
+        varHandleType = enterClass("java.lang.invoke.VarHandle");
         methodHandleType = enterClass("java.lang.invoke.MethodHandle");
         methodHandleLookupType = enterClass("java.lang.invoke.MethodHandles$Lookup");
         methodTypeType = enterClass("java.lang.invoke.MethodType");
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Tue Mar 15 14:50:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Thu Mar 24 11:21:37 2016 +0100
@@ -1062,18 +1062,19 @@
     }
 
     /**
-    * A polymorphic signature method (JLS 15.12.3) is a method that
-    * (i) is declared in the java.lang.invoke.MethodHandle class, (ii) takes
-    * a single variable arity parameter (iii) whose declared type is Object[],
-    * (iv) has a return type of Object and (v) is native.
+     * A polymorphic signature method (JLS 15.12.3) is a method that
+     *   (i) is declared in the java.lang.invoke.MethodHandle/VarHandle classes;
+     *  (ii) takes a single variable arity parameter;
+     * (iii) whose declared type is Object[];
+     *  (iv) has any return type, Object signifying a polymorphic return type; and
+     *   (v) is native.
     */
    public boolean isSignaturePolymorphic(MethodSymbol msym) {
        List<Type> argtypes = msym.type.getParameterTypes();
        return (msym.flags_field & NATIVE) != 0 &&
-               msym.owner == syms.methodHandleType.tsym &&
+              (msym.owner == syms.methodHandleType.tsym || msym.owner == syms.varHandleType.tsym) &&
                argtypes.tail.tail == null &&
                argtypes.head.hasTag(TypeTag.ARRAY) &&
-               msym.type.getReturnType().tsym == syms.objectType.tsym &&
                ((ArrayType)argtypes.head).elemtype.tsym == syms.objectType.tsym;
    }
 
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java	Tue Mar 15 14:50:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java	Thu Mar 24 11:21:37 2016 +0100
@@ -560,30 +560,37 @@
                                             List<Type> argtypes) {
         final Type restype;
 
-        //The return type for a polymorphic signature call is computed from
-        //the enclosing tree E, as follows: if E is a cast, then use the
-        //target type of the cast expression as a return type; if E is an
-        //expression statement, the return type is 'void' - otherwise the
-        //return type is simply 'Object'. A correctness check ensures that
-        //env.next refers to the lexically enclosing environment in which
-        //the polymorphic signature call environment is nested.
+        if (spMethod == null || types.isSameType(spMethod.getReturnType(), syms.objectType, true)) {
+            // The return type of the polymorphic signature is polymorphic,
+            // and is computed from the enclosing tree E, as follows:
+            // if E is a cast, then use the target type of the cast expression
+            // as a return type; if E is an expression statement, the return
+            // type is 'void'; otherwise
+            // the return type is simply 'Object'. A correctness check ensures
+            // that env.next refers to the lexically enclosing environment in
+            // which the polymorphic signature call environment is nested.
 
-        switch (env.next.tree.getTag()) {
-            case TYPECAST:
-                JCTypeCast castTree = (JCTypeCast)env.next.tree;
-                restype = (TreeInfo.skipParens(castTree.expr) == env.tree) ?
-                    castTree.clazz.type :
-                    syms.objectType;
-                break;
-            case EXEC:
-                JCTree.JCExpressionStatement execTree =
-                        (JCTree.JCExpressionStatement)env.next.tree;
-                restype = (TreeInfo.skipParens(execTree.expr) == env.tree) ?
-                    syms.voidType :
-                    syms.objectType;
-                break;
-            default:
-                restype = syms.objectType;
+            switch (env.next.tree.getTag()) {
+                case TYPECAST:
+                    JCTypeCast castTree = (JCTypeCast)env.next.tree;
+                    restype = (TreeInfo.skipParens(castTree.expr) == env.tree) ?
+                              castTree.clazz.type :
+                              syms.objectType;
+                    break;
+                case EXEC:
+                    JCTree.JCExpressionStatement execTree =
+                            (JCTree.JCExpressionStatement)env.next.tree;
+                    restype = (TreeInfo.skipParens(execTree.expr) == env.tree) ?
+                              syms.voidType :
+                              syms.objectType;
+                    break;
+                default:
+                    restype = syms.objectType;
+            }
+        } else {
+            // The return type of the polymorphic signature is fixed
+            // (not polymorphic)
+            restype = spMethod.getReturnType();
         }
 
         List<Type> paramtypes = argtypes.map(new ImplicitArgType(spMethod, resolveContext.step));
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Tue Mar 15 14:50:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Mar 24 11:21:37 2016 +0100
@@ -2461,13 +2461,19 @@
         Type mtype = infer.instantiatePolymorphicSignatureInstance(env,
                 (MethodSymbol)spMethod, currentResolutionContext, argtypes);
         for (Symbol sym : polymorphicSignatureScope.getSymbolsByName(spMethod.name)) {
-            if (types.isSameType(mtype, sym.type)) {
-               return sym;
+            // Check that there is already a method symbol for the method
+            // type and owner
+            if (types.isSameType(mtype, sym.type) &&
+                spMethod.owner == sym.owner) {
+                return sym;
             }
         }
 
-        // create the desired method
-        long flags = ABSTRACT | HYPOTHETICAL | spMethod.flags() & Flags.AccessFlags;
+        // Create the desired method
+        // Retain static modifier is to support invocations to
+        // MethodHandle.linkTo* methods
+        long flags = ABSTRACT | HYPOTHETICAL |
+                     spMethod.flags() & (Flags.AccessFlags | Flags.STATIC);
         Symbol msym = new MethodSymbol(flags, spMethod.name, mtype, spMethod.owner) {
             @Override
             public Symbol baseSymbol() {