langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
changeset 6592 dc56420a69bc
parent 6356 af24929939ca
child 6710 b14e6fe7b290
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Tue Sep 07 17:31:54 2010 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Tue Sep 07 17:32:27 2010 +0100
@@ -69,9 +69,13 @@
     JCDiagnostic.Factory diags;
     public final boolean boxingEnabled; // = source.allowBoxing();
     public final boolean varargsEnabled; // = source.allowVarargs();
-    public final boolean allowPolymorphicSignature;
+    public final boolean allowMethodHandles;
+    public final boolean allowInvokeDynamic;
+    public final boolean allowTransitionalJSR292;
     private final boolean debugResolve;
 
+    Scope polymorphicSignatureScope;
+
     public static Resolve instance(Context context) {
         Resolve instance = context.get(resolveKey);
         if (instance == null)
@@ -107,7 +111,14 @@
         varargsEnabled = source.allowVarargs();
         Options options = Options.instance(context);
         debugResolve = options.get("debugresolve") != null;
-        allowPolymorphicSignature = source.allowPolymorphicSignature() || options.get("invokedynamic") != null;
+        allowTransitionalJSR292 = options.get("allowTransitionalJSR292") != null;
+        Target target = Target.instance(context);
+        allowMethodHandles = allowTransitionalJSR292 ||
+                target.hasMethodHandles();
+        allowInvokeDynamic = (allowTransitionalJSR292 ||
+                target.hasInvokedynamic()) &&
+                options.get("invokedynamic") != null;
+        polymorphicSignatureScope = new Scope(syms.noSymbol);
     }
 
     /** error symbols, which are returned when resolution fails
@@ -246,7 +257,8 @@
     /* `sym' is accessible only if not overridden by
      * another symbol which is a member of `site'
      * (because, if it is overridden, `sym' is not strictly
-     * speaking a member of `site'.)
+     * speaking a member of `site'). A polymorphic signature method
+     * cannot be overridden (e.g. MH.invokeExact(Object[])).
      */
     private boolean notOverriddenIn(Type site, Symbol sym) {
         if (sym.kind != MTH || sym.isConstructor() || sym.isStatic())
@@ -254,6 +266,7 @@
         else {
             Symbol s2 = ((MethodSymbol)sym).implementation(site.tsym, types, true);
             return (s2 == null || s2 == sym ||
+                    s2.isPolymorphicSignatureGeneric() ||
                     !types.isSubSignature(types.memberType(site, s2), types.memberType(site, sym)));
         }
     }
@@ -303,7 +316,8 @@
                         boolean useVarargs,
                         Warner warn)
         throws Infer.InferenceException {
-        assert ((m.flags() & (POLYMORPHIC_SIGNATURE|HYPOTHETICAL)) != POLYMORPHIC_SIGNATURE);
+        boolean polymorphicSignature = (m.isPolymorphicSignatureGeneric() && allowMethodHandles) ||
+                                        isTransitionalDynamicCallSite(site, m);
         if (useVarargs && (m.flags() & VARARGS) == 0) return null;
         Type mt = types.memberType(site, m);
 
@@ -311,7 +325,10 @@
         // need to inferred.
         List<Type> tvars = env.info.tvars;
         if (typeargtypes == null) typeargtypes = List.nil();
-        if (mt.tag != FORALL && typeargtypes.nonEmpty()) {
+        if (allowTransitionalJSR292 && polymorphicSignature && typeargtypes.nonEmpty()) {
+            //transitional 292 call sites might have wrong number of targs
+        }
+        else if (mt.tag != FORALL && typeargtypes.nonEmpty()) {
             // This is not a polymorphic method, but typeargs are supplied
             // which is fine, see JLS3 15.12.2.1
         } else if (mt.tag == FORALL && typeargtypes.nonEmpty()) {
@@ -339,7 +356,8 @@
         }
 
         // find out whether we need to go the slow route via infer
-        boolean instNeeded = tvars.tail != null/*inlined: tvars.nonEmpty()*/;
+        boolean instNeeded = tvars.tail != null || /*inlined: tvars.nonEmpty()*/
+                polymorphicSignature;
         for (List<Type> l = argtypes;
              l.tail != null/*inlined: l.nonEmpty()*/ && !instNeeded;
              l = l.tail) {
@@ -347,8 +365,9 @@
         }
 
         if (instNeeded)
-            return
-            infer.instantiateMethod(env,
+            return polymorphicSignature ?
+                infer.instantiatePolymorphicSignatureInstance(env, site, m.name, (MethodSymbol)m, argtypes, typeargtypes) :
+                infer.instantiateMethod(env,
                                     tvars,
                                     (MethodType)mt,
                                     m,
@@ -363,6 +382,14 @@
             : null;
     }
 
+    boolean isTransitionalDynamicCallSite(Type site, Symbol sym) {
+        return allowTransitionalJSR292 &&  // old logic that doesn't use annotations
+                !sym.isPolymorphicSignatureInstance() &&
+                ((allowMethodHandles && site == syms.methodHandleType && // invokeExact, invokeGeneric, invoke
+                    (sym.name == names.invoke && sym.isPolymorphicSignatureGeneric())) ||
+                (site == syms.invokeDynamicType && allowInvokeDynamic)); // InvokeDynamic.XYZ
+    }
+
     /** Same but returns null instead throwing a NoInstanceException
      */
     Type instantiate(Env<AttrContext> env,
@@ -580,14 +607,6 @@
         if (sym.kind == ERR) return bestSoFar;
         if (!sym.isInheritedIn(site.tsym, types)) return bestSoFar;
         assert sym.kind < AMBIGUOUS;
-        if ((sym.flags() & POLYMORPHIC_SIGNATURE) != 0 && allowPolymorphicSignature) {
-            assert(site.tag == CLASS);
-            // Never match a MethodHandle.invoke directly.
-            if (useVarargs | allowBoxing | operator)
-                return bestSoFar;
-            // Supply an exactly-typed implicit method instead.
-            sym = findPolymorphicSignatureInstance(env, sym.owner.type, sym.name, (MethodSymbol) sym, argtypes, typeargtypes);
-        }
         try {
             if (rawInstantiate(env, site, sym, argtypes, typeargtypes,
                                allowBoxing, useVarargs, Warner.noWarnings) == null) {
@@ -759,13 +778,6 @@
                       boolean useVarargs,
                       boolean operator) {
         Symbol bestSoFar = methodNotFound;
-        if ((site.tsym.flags() & POLYMORPHIC_SIGNATURE) != 0 &&
-            allowPolymorphicSignature &&
-            site.tag == CLASS &&
-            !(useVarargs | allowBoxing | operator)) {
-            // supply an exactly-typed implicit method in java.dyn.InvokeDynamic
-            bestSoFar = findPolymorphicSignatureInstance(env, site, name, null, argtypes, typeargtypes);
-        }
         return findMethod(env,
                           site,
                           name,
@@ -907,90 +919,6 @@
         return bestSoFar;
     }
 
-    /** Find or create an implicit method of exactly the given type (after erasure).
-     *  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       The current environment.
-     *  @param site      The original type from where the selection
-     *                   takes place.
-     *  @param name      The method's name.
-     *  @param argtypes  The method's value arguments.
-     *  @param typeargtypes The method's type arguments
-     */
-    Symbol findPolymorphicSignatureInstance(Env<AttrContext> env,
-                                            Type site,
-                                            Name name,
-                                            MethodSymbol spMethod,  // sig. poly. method or null if none
-                                            List<Type> argtypes,
-                                            List<Type> typeargtypes) {
-        assert allowPolymorphicSignature;
-        //assert site == syms.invokeDynamicType || site == syms.methodHandleType : site;
-        ClassSymbol c = (ClassSymbol) site.tsym;
-        Scope implicit = c.members().next;
-        if (implicit == null) {
-            c.members().next = implicit = new Scope(c);
-        }
-        Type restype;
-        if (typeargtypes.isEmpty()) {
-            restype = syms.objectType;
-        } else {
-            restype = typeargtypes.head;
-            if (!typeargtypes.tail.isEmpty())
-                return methodNotFound;
-        }
-        List<Type> paramtypes = Type.map(argtypes, implicitArgType);
-        long flags;
-        List<Type> exType;
-        if (spMethod != null) {
-            exType = spMethod.getThrownTypes();
-            flags = spMethod.flags() & AccessFlags;
-        } else {
-            // make it throw all exceptions
-            //assert(site == syms.invokeDynamicType);
-            exType = List.of(syms.throwableType);
-            flags = PUBLIC | STATIC;
-        }
-        MethodType mtype = new MethodType(paramtypes,
-                                          restype,
-                                          exType,
-                                          syms.methodClass);
-        flags |= ABSTRACT | HYPOTHETICAL | POLYMORPHIC_SIGNATURE;
-        Symbol m = null;
-        for (Scope.Entry e = implicit.lookup(name);
-             e.scope != null;
-             e = e.next()) {
-            Symbol sym = e.sym;
-            assert sym.kind == MTH;
-            if (types.isSameType(mtype, sym.type)
-                && (sym.flags() & STATIC) == (flags & STATIC)) {
-                m = sym;
-                break;
-            }
-        }
-        if (m == null) {
-            // create the desired method
-            m = new MethodSymbol(flags, name, mtype, c);
-            implicit.enter(m);
-        }
-        assert argumentsAcceptable(argtypes, types.memberType(site, m).getParameterTypes(),
-                                   false, false, Warner.noWarnings);
-        assert null != instantiate(env, site, m, argtypes, typeargtypes, false, false, Warner.noWarnings);
-        return m;
-    }
-    //where
-        Mapping implicitArgType = new Mapping ("implicitArgType") {
-                public Type apply(Type t) { return implicitArgType(t); }
-            };
-        Type implicitArgType(Type argType) {
-            argType = types.erasure(argType);
-            if (argType.tag == BOT)
-                // nulls type as the marker type Null (which has no instances)
-                // TO DO: figure out how to access java.lang.Null safely, else throw nice error
-                //argType = types.boxedClass(syms.botType).type;
-                argType = types.boxedClass(syms.voidType).type;  // REMOVE
-            return argType;
-        }
-
     /** Load toplevel or member class with given fully qualified name and
      *  verify that it is accessible.
      *  @param env       The current environment.
@@ -1369,16 +1297,77 @@
             methodResolutionCache.put(steps.head, sym);
             steps = steps.tail;
         }
-        if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error
-            MethodResolutionPhase errPhase =
-                    firstErroneousResolutionPhase();
-            sym = access(methodResolutionCache.get(errPhase),
-                    pos, site, name, true, argtypes, typeargtypes);
-            env.info.varArgs = errPhase.isVarargsRequired;
+        if (sym.kind >= AMBIGUOUS) {
+            if (site.tsym.isPolymorphicSignatureGeneric() ||
+                    isTransitionalDynamicCallSite(site, sym)) {
+                //polymorphic receiver - synthesize new method symbol
+                env.info.varArgs = false;
+                sym = findPolymorphicSignatureInstance(env,
+                        site, name, null, argtypes, typeargtypes);
+            }
+            else {
+                //if nothing is found return the 'first' error
+                MethodResolutionPhase errPhase =
+                        firstErroneousResolutionPhase();
+                sym = access(methodResolutionCache.get(errPhase),
+                        pos, 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, typeargtypes);
         }
         return sym;
     }
 
+    /** Find or create an implicit method of exactly the given type (after erasure).
+     *  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.
+     */
+    Symbol findPolymorphicSignatureInstance(Env<AttrContext> env, Type site,
+                                            Name name,
+                                            MethodSymbol spMethod,  // sig. poly. method or null if none
+                                            List<Type> argtypes,
+                                            List<Type> typeargtypes) {
+        if (typeargtypes.nonEmpty() && (site.tsym.isPolymorphicSignatureGeneric() ||
+                (spMethod != null && spMethod.isPolymorphicSignatureGeneric()))) {
+            log.warning(env.tree.pos(), "type.parameter.on.polymorphic.signature");
+        }
+
+        Type mtype = infer.instantiatePolymorphicSignatureInstance(env,
+                site, name, spMethod, argtypes, typeargtypes);
+        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;
+            }
+        }
+        if (m == null) {
+            // create the desired method
+            m = new MethodSymbol(flags, name, mtype, site.tsym);
+            polymorphicSignatureScope.enter(m);
+        }
+        return m;
+    }
+
     /** Resolve a qualified method identifier, throw a fatal error if not
      *  found.
      *  @param pos       The position to use for error reporting.