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
--- 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