7133185: Update 292 overload resolution logic to match JLS
authormcimadamore
Mon, 26 Mar 2012 15:28:49 +0100
changeset 12335 4725d88691dd
parent 12334 29e1bfdcba4e
child 12336 6291eb84bea7
7133185: Update 292 overload resolution logic to match JLS Summary: Re-implement special overload resolution support for method handles according to the JLS SE 7 definition Reviewed-by: jjg, dlsmith, jrose
langtools/src/share/classes/com/sun/tools/javac/code/Flags.java
langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java
langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java
langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java
langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties
langtools/test/tools/javac/diags/examples.not-yet.txt
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java	Mon Mar 26 15:28:22 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java	Mon Mar 26 15:28:49 2012 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
@@ -221,7 +221,7 @@
 
     /** Flag that marks a hypothetical method that need not really be
      *  generated in the binary, but is present in the symbol table to
-     *  simplify checking for erasure clashes.
+     *  simplify checking for erasure clashes - also used for 292 poly sig methods.
      */
     public static final long HYPOTHETICAL   = 1L<<37;
 
@@ -236,26 +236,20 @@
     public static final long UNION = 1L<<39;
 
     /**
-     * Flag that marks a signature-polymorphic invoke method.
-     * (These occur inside java.lang.invoke.MethodHandle.)
-     */
-    public static final long POLYMORPHIC_SIGNATURE = 1L<<40;
-
-    /**
      * Flag that marks a special kind of bridge methods (the ones that
      * come from restricted supertype bounds)
      */
-    public static final long OVERRIDE_BRIDGE = 1L<<41;
+    public static final long OVERRIDE_BRIDGE = 1L<<40;
 
     /**
      * Flag that marks an 'effectively final' local variable
      */
-    public static final long EFFECTIVELY_FINAL = 1L<<42;
+    public static final long EFFECTIVELY_FINAL = 1L<<41;
 
     /**
      * Flag that marks non-override equivalent methods with the same signature
      */
-    public static final long CLASH = 1L<<43;
+    public static final long CLASH = 1L<<42;
 
     /** Modifier masks.
      */
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java	Mon Mar 26 15:28:22 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java	Mon Mar 26 15:28:49 2012 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
@@ -202,16 +202,6 @@
         return (flags() & INTERFACE) != 0;
     }
 
-    /** Recognize if this symbol was marked @PolymorphicSignature in the source. */
-    public boolean isPolymorphicSignatureGeneric() {
-        return (flags() & (POLYMORPHIC_SIGNATURE | HYPOTHETICAL)) == POLYMORPHIC_SIGNATURE;
-    }
-
-    /** Recognize if this symbol was split from a @PolymorphicSignature symbol in the source. */
-    public boolean isPolymorphicSignatureInstance() {
-        return (flags() & (POLYMORPHIC_SIGNATURE | HYPOTHETICAL)) == (POLYMORPHIC_SIGNATURE | HYPOTHETICAL);
-    }
-
     /** Is this symbol declared (directly or indirectly) local
      *  to a method or variable initializer?
      *  Also includes fields of inner classes which are in
@@ -1316,6 +1306,25 @@
                     getKind() == ElementKind.INSTANCE_INIT;
         }
 
+        /**
+         * A polymorphic signature method (JLS SE 7, 8.4.1) 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.
+         */
+        public boolean isSignaturePolymorphic(Types types) {
+            List<Type> argtypes = type.getParameterTypes();
+            Type firstElemType = argtypes.nonEmpty() ?
+                    types.elemtype(argtypes.head) :
+                    null;
+            return owner == types.syms.methodHandleType.tsym &&
+                    argtypes.length() == 1 &&
+                    firstElemType != null &&
+                    types.isSameType(firstElemType, types.syms.objectType) &&
+                    types.isSameType(type.getReturnType(), types.syms.objectType) &&
+                    (flags() & NATIVE) != 0;
+        }
+
         public Attribute getDefaultValue() {
             return defaultValue;
         }
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java	Mon Mar 26 15:28:22 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java	Mon Mar 26 15:28:49 2012 +0100
@@ -127,7 +127,6 @@
     public final Type serializableType;
     public final Type methodHandleType;
     public final Type nativeHeaderType;
-    public final Type polymorphicSignatureType;
     public final Type throwableType;
     public final Type errorType;
     public final Type interruptedExceptionType;
@@ -436,7 +435,6 @@
         throwableType = enterClass("java.lang.Throwable");
         serializableType = enterClass("java.io.Serializable");
         methodHandleType = enterClass("java.lang.invoke.MethodHandle");
-        polymorphicSignatureType = enterClass("java.lang.invoke.MethodHandle$PolymorphicSignature");
         errorType = enterClass("java.lang.Error");
         illegalArgumentExceptionType = enterClass("java.lang.IllegalArgumentException");
         interruptedExceptionType = enterClass("java.lang.InterruptedException");
@@ -483,7 +481,6 @@
         synthesizeEmptyInterfaceIfMissing(autoCloseableType);
         synthesizeEmptyInterfaceIfMissing(cloneableType);
         synthesizeEmptyInterfaceIfMissing(serializableType);
-        synthesizeEmptyInterfaceIfMissing(polymorphicSignatureType);
         synthesizeBoxTypeIfMissing(doubleType);
         synthesizeBoxTypeIfMissing(floatType);
         synthesizeBoxTypeIfMissing(voidType);
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Mar 26 15:28:22 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Mar 26 15:28:49 2012 +0100
@@ -593,7 +593,7 @@
                     Symbol sym = TreeInfo.symbol(apply.meth);
                     is292targetTypeCast = sym != null &&
                         sym.kind == MTH &&
-                        (sym.flags() & POLYMORPHIC_SIGNATURE) != 0;
+                        (sym.flags() & HYPOTHETICAL) != 0;
                 }
                 return is292targetTypeCast;
             }
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Mar 26 15:28:22 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Mar 26 15:28:49 2012 +0100
@@ -603,8 +603,7 @@
      * method signature. The target return type is computed from the immediately
      * enclosing scope surrounding the polymorphic-signature call.
      */
-    Type instantiatePolymorphicSignatureInstance(Env<AttrContext> env, Type site,
-                                            Name name,
+    Type instantiatePolymorphicSignatureInstance(Env<AttrContext> env,
                                             MethodSymbol spMethod,  // sig. poly. method or null if none
                                             List<Type> argtypes) {
         final Type restype;
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Mon Mar 26 15:28:22 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Mon Mar 26 15:28:49 2012 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, 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
@@ -781,20 +781,6 @@
                 && s.owner.kind != MTH
                 && types.isSameType(c.type, syms.deprecatedType))
                 s.flags_field |= Flags.DEPRECATED;
-            // Internally to java.lang.invoke, a @PolymorphicSignature annotation
-            // acts like a classfile attribute.
-            if (!c.type.isErroneous() &&
-                types.isSameType(c.type, syms.polymorphicSignatureType)) {
-                if (!target.hasMethodHandles()) {
-                    // Somebody is compiling JDK7 source code to a JDK6 target.
-                    // Make it an error, since it is unlikely but important.
-                    log.error(env.tree.pos(),
-                            "wrong.target.for.polymorphic.signature.definition",
-                            target.name);
-                }
-                // Pull the flag through for better diagnostics, even on a bad target.
-                s.flags_field |= Flags.POLYMORPHIC_SIGNATURE;
-            }
             if (!annotated.add(a.type.tsym))
                 log.error(a.pos, "duplicate.annotation");
         }
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Mar 26 15:28:22 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Mar 26 15:28:49 2012 +0100
@@ -399,7 +399,6 @@
         else {
             Symbol s2 = ((MethodSymbol)sym).implementation(site.tsym, types, true);
             return (s2 == null || s2 == sym || sym.owner == s2.owner ||
-                    s2.isPolymorphicSignatureGeneric() ||
                     !types.isSubSignature(types.memberType(site, s2), types.memberType(site, sym)));
         }
     }
@@ -449,7 +448,6 @@
                         boolean useVarargs,
                         Warner warn)
         throws Infer.InferenceException {
-        boolean polymorphicSignature = m.isPolymorphicSignatureGeneric() && allowMethodHandles;
         if (useVarargs && (m.flags() & VARARGS) == 0)
             throw inapplicableMethodException.setMessage();
         Type mt = types.memberType(site, m);
@@ -490,8 +488,7 @@
         }
 
         // find out whether we need to go the slow route via infer
-        boolean instNeeded = tvars.tail != null || /*inlined: tvars.nonEmpty()*/
-                polymorphicSignature;
+        boolean instNeeded = tvars.tail != null; /*inlined: tvars.nonEmpty()*/
         for (List<Type> l = argtypes;
              l.tail != null/*inlined: l.nonEmpty()*/ && !instNeeded;
              l = l.tail) {
@@ -499,9 +496,7 @@
         }
 
         if (instNeeded)
-            return polymorphicSignature ?
-                infer.instantiatePolymorphicSignatureInstance(env, site, m.name, (MethodSymbol)m, argtypes) :
-                infer.instantiateMethod(env,
+            return infer.instantiateMethod(env,
                                     tvars,
                                     (MethodType)mt,
                                     m,
@@ -1740,25 +1735,18 @@
                 steps = steps.tail;
             }
             if (sym.kind >= AMBIGUOUS) {
-                if (site.tsym.isPolymorphicSignatureGeneric()) {
-                    //polymorphic receiver - synthesize new method symbol
+                //if nothing is found return the 'first' error
+                MethodResolutionPhase errPhase =
+                        currentResolutionContext.firstErroneousResolutionPhase();
+                sym = access(currentResolutionContext.resolutionCache.get(errPhase),
+                        pos, location, site, name, true, argtypes, typeargtypes);
+                env.info.varArgs = errPhase.isVarargsRequired;
+            } else if (allowMethodHandles) {
+                MethodSymbol msym = (MethodSymbol)sym;
+                if (msym.isSignaturePolymorphic(types)) {
                     env.info.varArgs = false;
-                    sym = findPolymorphicSignatureInstance(env,
-                            site, name, null, argtypes);
+                    return findPolymorphicSignatureInstance(env, sym, argtypes);
                 }
-                else {
-                    //if nothing is found return the 'first' error
-                    MethodResolutionPhase errPhase =
-                            currentResolutionContext.firstErroneousResolutionPhase();
-                    sym = access(currentResolutionContext.resolutionCache.get(errPhase),
-                            pos, location, site, name, true, argtypes, typeargtypes);
-                    env.info.varArgs = errPhase.isVarargsRequired;
-                }
-            } else if (allowMethodHandles && sym.isPolymorphicSignatureGeneric()) {
-                //non-instantiated polymorphic signature - synthesize new method symbol
-                env.info.varArgs = false;
-                sym = findPolymorphicSignatureInstance(env,
-                        site, name, (MethodSymbol)sym, argtypes);
             }
             return sym;
         }
@@ -1771,40 +1759,25 @@
      *  Searches in a side table, not the main scope of the site.
      *  This emulates the lookup process required by JSR 292 in JVM.
      *  @param env       Attribution environment
-     *  @param site      The original type from where the selection takes place.
-     *  @param name      The method's name.
-     *  @param spMethod  A template for the implicit method, or null.
-     *  @param argtypes  The required argument types.
-     *  @param typeargtypes  The required type arguments.
+     *  @param spMethod  signature polymorphic method - i.e. MH.invokeExact
+     *  @param argtypes  The required argument types
      */
-    Symbol findPolymorphicSignatureInstance(Env<AttrContext> env, Type site,
-                                            Name name,
-                                            MethodSymbol spMethod,  // sig. poly. method or null if none
+    Symbol findPolymorphicSignatureInstance(Env<AttrContext> env,
+                                            Symbol spMethod,
                                             List<Type> argtypes) {
         Type mtype = infer.instantiatePolymorphicSignatureInstance(env,
-                site, name, spMethod, argtypes);
-        long flags = ABSTRACT | HYPOTHETICAL | POLYMORPHIC_SIGNATURE |
-                    (spMethod != null ?
-                        spMethod.flags() & Flags.AccessFlags :
-                        Flags.PUBLIC | Flags.STATIC);
-        Symbol m = null;
-        for (Scope.Entry e = polymorphicSignatureScope.lookup(name);
-             e.scope != null;
-             e = e.next()) {
-            Symbol sym = e.sym;
-            if (types.isSameType(mtype, sym.type) &&
-                (sym.flags() & Flags.STATIC) == (flags & Flags.STATIC) &&
-                types.isSameType(sym.owner.type, site)) {
-               m = sym;
-               break;
+                (MethodSymbol)spMethod, argtypes);
+        for (Symbol sym : polymorphicSignatureScope.getElementsByName(spMethod.name)) {
+            if (types.isSameType(mtype, sym.type)) {
+               return sym;
             }
         }
-        if (m == null) {
-            // create the desired method
-            m = new MethodSymbol(flags, name, mtype, site.tsym);
-            polymorphicSignatureScope.enter(m);
-        }
-        return m;
+
+        // create the desired method
+        long flags = ABSTRACT | HYPOTHETICAL | spMethod.flags() & Flags.AccessFlags;
+        Symbol msym = new MethodSymbol(flags, spMethod.name, mtype, spMethod.owner);
+        polymorphicSignatureScope.enter(msym);
+        return msym;
     }
 
     /** Resolve a qualified method identifier, throw a fatal error if not
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Mar 26 15:28:22 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Mar 26 15:28:49 2012 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
@@ -1320,10 +1320,6 @@
                     sym.flags_field |= PROPRIETARY;
                 else
                     proxies.append(proxy);
-                if (majorVersion >= V51.major &&
-                    proxy.type.tsym == syms.polymorphicSignatureType.tsym) {
-                    sym.flags_field |= POLYMORPHIC_SIGNATURE;
-                }
             }
             annotate.later(new AnnotationCompleter(sym, proxies.toList()));
         }
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Mar 26 15:28:22 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Mar 26 15:28:49 2012 +0100
@@ -217,9 +217,6 @@
 compiler.err.no.superclass=\
     {0} has no superclass
 
-compiler.err.wrong.target.for.polymorphic.signature.definition=\
-    MethodHandle API building requires -target 7 runtimes or better; current is -target {0}
-
 # 0: symbol, 1: type, 2: symbol, 3: type, 4: unused
 compiler.err.concrete.inheritance.conflict=\
     methods {0} from {1} and {2} from {3} are inherited with the same signature
--- a/langtools/test/tools/javac/diags/examples.not-yet.txt	Mon Mar 26 15:28:22 2012 +0100
+++ b/langtools/test/tools/javac/diags/examples.not-yet.txt	Mon Mar 26 15:28:49 2012 +0100
@@ -37,7 +37,6 @@
 compiler.err.type.var.more.than.once.in.result          # UNUSED
 compiler.err.unexpected.type
 compiler.err.unsupported.cross.fp.lit                   # Scanner: host system dependent
-compiler.err.wrong.target.for.polymorphic.signature.definition     # Transitional 292
 compiler.misc.bad.class.file.header                     # bad class file
 compiler.misc.bad.class.signature                       # bad class file
 compiler.misc.bad.const.pool.tag                        # bad class file