# HG changeset patch # User chegar # Date 1371638885 -3600 # Node ID d0e713f5cabd9cb9a4172b6f8d799653fd1b46d9 # Parent daf2e2653da5248dd7b8d887b28db17c7da2a000 8017045: anti-delta fix for 8013789 Reviewed-by: alanb diff -r daf2e2653da5 -r d0e713f5cabd langtools/src/share/classes/com/sun/tools/javac/code/Types.java --- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Tue Jun 18 20:56:04 2013 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Wed Jun 19 11:48:05 2013 +0100 @@ -33,15 +33,10 @@ import java.util.Set; import java.util.WeakHashMap; -import javax.tools.JavaFileObject; - import com.sun.tools.javac.code.Attribute.RetentionPolicy; import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.Type.UndetVar.InferenceBound; -import com.sun.tools.javac.comp.AttrContext; import com.sun.tools.javac.comp.Check; -import com.sun.tools.javac.comp.Enter; -import com.sun.tools.javac.comp.Env; import com.sun.tools.javac.jvm.ClassReader; import com.sun.tools.javac.util.*; import static com.sun.tools.javac.code.BoundKind.*; @@ -88,7 +83,6 @@ final boolean allowDefaultMethods; final ClassReader reader; final Check chk; - final Enter enter; JCDiagnostic.Factory diags; List warnStack = List.nil(); final Name capturedName; @@ -115,7 +109,6 @@ allowDefaultMethods = source.allowDefaultMethods(); reader = ClassReader.instance(context); chk = Check.instance(context); - enter = Enter.instance(context); capturedName = names.fromString(""); messages = JavacMessages.instance(context); diags = JCDiagnostic.Factory.instance(context); @@ -610,84 +603,6 @@ return site; } } - - /** - * Create a symbol for a class that implements a given functional interface - * and overrides its functional descriptor. This routine is used for two - * main purposes: (i) checking well-formedness of a functional interface; - * (ii) perform functional interface bridge calculation. - */ - public ClassSymbol makeFunctionalInterfaceClass(Env env, Name name, List targets, long cflags) { - Assert.check(targets.nonEmpty() && isFunctionalInterface(targets.head)); - Symbol descSym = findDescriptorSymbol(targets.head.tsym); - Type descType = findDescriptorType(targets.head); - ClassSymbol csym = new ClassSymbol(cflags, name, env.enclClass.sym.outermostClass()); - csym.completer = null; - csym.members_field = new Scope(csym); - MethodSymbol instDescSym = new MethodSymbol(descSym.flags(), descSym.name, descType, csym); - csym.members_field.enter(instDescSym); - Type.ClassType ctype = new Type.ClassType(Type.noType, List.nil(), csym); - ctype.supertype_field = syms.objectType; - ctype.interfaces_field = targets; - csym.type = ctype; - csym.sourcefile = ((ClassSymbol)csym.owner).sourcefile; - return csym; - } - - /** - * Find the minimal set of methods that are overridden by the functional - * descriptor in 'origin'. All returned methods are assumed to have different - * erased signatures. - */ - public List functionalInterfaceBridges(TypeSymbol origin) { - Assert.check(isFunctionalInterface(origin)); - Symbol descSym = findDescriptorSymbol(origin); - CompoundScope members = membersClosure(origin.type, false); - ListBuffer overridden = ListBuffer.lb(); - outer: for (Symbol m2 : members.getElementsByName(descSym.name, bridgeFilter)) { - if (m2 == descSym) continue; - else if (descSym.overrides(m2, origin, Types.this, false)) { - for (Symbol m3 : overridden) { - if (isSameType(m3.erasure(Types.this), m2.erasure(Types.this)) || - (m3.overrides(m2, origin, Types.this, false) && - (pendingBridges((ClassSymbol)origin, m3.enclClass()) || - (((MethodSymbol)m2).binaryImplementation((ClassSymbol)m3.owner, Types.this) != null)))) { - continue outer; - } - } - overridden.add(m2); - } - } - return overridden.toList(); - } - //where - private Filter bridgeFilter = new Filter() { - public boolean accepts(Symbol t) { - return t.kind == Kinds.MTH && - t.name != names.init && - t.name != names.clinit && - (t.flags() & SYNTHETIC) == 0; - } - }; - private boolean pendingBridges(ClassSymbol origin, TypeSymbol s) { - //a symbol will be completed from a classfile if (a) symbol has - //an associated file object with CLASS kind and (b) the symbol has - //not been entered - if (origin.classfile != null && - origin.classfile.getKind() == JavaFileObject.Kind.CLASS && - enter.getEnv(origin) == null) { - return false; - } - if (origin == s) { - return true; - } - for (Type t : interfaces(origin.type)) { - if (pendingBridges((ClassSymbol)t.tsym, s)) { - return true; - } - } - return false; - } // /** @@ -2728,7 +2643,6 @@ public boolean accepts(Symbol s) { return s.kind == Kinds.MTH && s.name == msym.name && - (s.flags() & SYNTHETIC) == 0 && s.isInheritedIn(site.tsym, Types.this) && overrideEquivalent(memberType(site, s), memberType(site, msym)); } diff -r daf2e2653da5 -r d0e713f5cabd langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Tue Jun 18 20:56:04 2013 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Wed Jun 19 11:48:05 2013 +0100 @@ -2327,12 +2327,13 @@ if (pt() != Type.recoveryType) { target = targetChecker.visit(target, that); lambdaType = types.findDescriptorType(target); + chk.checkFunctionalInterface(that, target); } else { target = Type.recoveryType; lambdaType = fallbackDescriptorType(that); } - setFunctionalInfo(localEnv, that, pt(), lambdaType, target, resultInfo.checkContext); + setFunctionalInfo(that, pt(), lambdaType, target, resultInfo.checkContext.inferenceContext()); if (lambdaType.hasTag(FORALL)) { //lambda expression target desc cannot be a generic method @@ -2674,12 +2675,13 @@ if (pt() != Type.recoveryType) { target = targetChecker.visit(pt(), that); desc = types.findDescriptorType(target); + chk.checkFunctionalInterface(that, target); } else { target = Type.recoveryType; desc = fallbackDescriptorType(that); } - setFunctionalInfo(localEnv, that, pt(), desc, target, resultInfo.checkContext); + setFunctionalInfo(that, pt(), desc, target, resultInfo.checkContext.inferenceContext()); List argtypes = desc.getParameterTypes(); Pair refResult = @@ -2881,37 +2883,31 @@ * might contain inference variables, we might need to register an hook in the * current inference context. */ - private void setFunctionalInfo(final Env env, final JCFunctionalExpression fExpr, - final Type pt, final Type descriptorType, final Type primaryTarget, final CheckContext checkContext) { - if (checkContext.inferenceContext().free(descriptorType)) { - checkContext.inferenceContext().addFreeTypeListener(List.of(pt, descriptorType), new FreeTypeListener() { + private void setFunctionalInfo(final JCFunctionalExpression fExpr, final Type pt, + final Type descriptorType, final Type primaryTarget, InferenceContext inferenceContext) { + if (inferenceContext.free(descriptorType)) { + inferenceContext.addFreeTypeListener(List.of(pt, descriptorType), new FreeTypeListener() { public void typesInferred(InferenceContext inferenceContext) { - setFunctionalInfo(env, fExpr, pt, inferenceContext.asInstType(descriptorType), - inferenceContext.asInstType(primaryTarget), checkContext); + setFunctionalInfo(fExpr, pt, inferenceContext.asInstType(descriptorType), + inferenceContext.asInstType(primaryTarget), inferenceContext); } }); } else { - ListBuffer targets = ListBuffer.lb(); + ListBuffer targets = ListBuffer.lb(); if (pt.hasTag(CLASS)) { if (pt.isCompound()) { - targets.append(types.removeWildcards(primaryTarget)); //this goes first + targets.append(primaryTarget.tsym); //this goes first for (Type t : ((IntersectionClassType)pt()).interfaces_field) { if (t != primaryTarget) { - targets.append(types.removeWildcards(t)); + targets.append(t.tsym); } } } else { - targets.append(types.removeWildcards(primaryTarget)); + targets.append(pt.tsym); } } fExpr.targets = targets.toList(); - if (checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK && - pt != Type.recoveryType) { - //check that functional interface class is well-formed - ClassSymbol csym = types.makeFunctionalInterfaceClass(env, - names.empty, List.of(fExpr.targets.head), ABSTRACT); - chk.checkImplementations(env.tree, csym, csym); - } + fExpr.descriptorType = descriptorType; } } @@ -4567,6 +4563,9 @@ @Override public void visitLambda(JCLambda that) { super.visitLambda(that); + if (that.descriptorType == null) { + that.descriptorType = syms.unknownType; + } if (that.targets == null) { that.targets = List.nil(); } @@ -4578,6 +4577,9 @@ if (that.sym == null) { that.sym = new MethodSymbol(0, names.empty, syms.unknownType, syms.noSymbol); } + if (that.descriptorType == null) { + that.descriptorType = syms.unknownType; + } if (that.targets == null) { that.targets = List.nil(); } diff -r daf2e2653da5 -r d0e713f5cabd langtools/src/share/classes/com/sun/tools/javac/comp/Check.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Jun 18 20:56:04 2013 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Wed Jun 19 11:48:05 2013 +0100 @@ -2267,6 +2267,24 @@ c.flags_field |= ACYCLIC; } + /** + * Check that functional interface methods would make sense when seen + * from the perspective of the implementing class + */ + void checkFunctionalInterface(JCTree tree, Type funcInterface) { + ClassType c = new ClassType(Type.noType, List.nil(), null); + ClassSymbol csym = new ClassSymbol(0, names.empty, c, syms.noSymbol); + c.interfaces_field = List.of(types.removeWildcards(funcInterface)); + c.supertype_field = syms.objectType; + c.tsym = csym; + csym.members_field = new Scope(csym); + Symbol descSym = types.findDescriptorSymbol(funcInterface.tsym); + Type descType = types.findDescriptorType(funcInterface); + csym.members_field.enter(new MethodSymbol(PUBLIC, descSym.name, descType, csym)); + csym.completer = null; + checkImplementations(tree, csym, csym); + } + /** Check that all methods which implement some * method conform to the method they implement. * @param tree The class definition whose members are checked. diff -r daf2e2653da5 -r d0e713f5cabd langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Tue Jun 18 20:56:04 2013 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Wed Jun 19 11:48:05 2013 +0100 @@ -100,9 +100,6 @@ /** Flag for alternate metafactories indicating the lambda object has multiple targets */ public static final int FLAG_MARKERS = 1 << 1; - /** Flag for alternate metafactories indicating the lambda object requires multiple bridges */ - public static final int FLAG_BRIDGES = 1 << 2; - private class KlassInfo { /** @@ -324,7 +321,7 @@ int refKind = referenceKind(sym); //convert to an invokedynamic call - result = makeMetaFactoryIndyCall(context, refKind, sym, indy_args); + result = makeMetaFactoryIndyCall(tree, context.needsAltMetafactory(), context.isSerializable(), refKind, sym, indy_args); } private JCIdent makeThis(Type type, Symbol owner) { @@ -385,7 +382,7 @@ //build a sam instance using an indy call to the meta-factory - result = makeMetaFactoryIndyCall(localContext, localContext.referenceKind(), refSym, indy_args); + result = makeMetaFactoryIndyCall(tree, localContext.needsAltMetafactory(), localContext.isSerializable(), localContext.referenceKind(), refSym, indy_args); } /** @@ -911,11 +908,10 @@ /** * Generate an indy method call to the meta factory */ - private JCExpression makeMetaFactoryIndyCall(TranslationContext context, - int refKind, Symbol refSym, List indy_args) { - JCFunctionalExpression tree = context.tree; + private JCExpression makeMetaFactoryIndyCall(JCFunctionalExpression tree, boolean needsAltMetafactory, + boolean isSerializable, int refKind, Symbol refSym, List indy_args) { //determine the static bsm args - Type mtype = types.erasure(tree.getDescriptorType(types)); + Type mtype = types.erasure(tree.descriptorType); MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym); List staticArgs = List.of( new Pool.MethodHandle(ClassFile.REF_invokeInterface, @@ -938,40 +934,25 @@ List.nil(), syms.methodClass); - Name metafactoryName = context.needsAltMetafactory() ? + Name metafactoryName = needsAltMetafactory ? names.altMetaFactory : names.metaFactory; - if (context.needsAltMetafactory()) { + if (needsAltMetafactory) { ListBuffer markers = ListBuffer.lb(); - for (Type t : tree.targets.tail) { - if (t.tsym != syms.serializableType.tsym) { - markers.append(t.tsym); + for (Symbol t : tree.targets.tail) { + if (t != syms.serializableType.tsym) { + markers.append(t); } } - int flags = context.isSerializable() ? FLAG_SERIALIZABLE : 0; + int flags = isSerializable? FLAG_SERIALIZABLE : 0; boolean hasMarkers = markers.nonEmpty(); - boolean hasBridges = context.bridges.nonEmpty(); - if (hasMarkers) { - flags |= FLAG_MARKERS; - } - if (hasBridges) { - flags |= FLAG_BRIDGES; - } + flags |= hasMarkers ? FLAG_MARKERS : 0; staticArgs = staticArgs.append(flags); if (hasMarkers) { staticArgs = staticArgs.append(markers.length()); staticArgs = staticArgs.appendList(markers.toList()); } - if (hasBridges) { - staticArgs = staticArgs.append(context.bridges.length() - 1); - for (Symbol s : context.bridges) { - Type s_erasure = s.erasure(types); - if (!types.isSameType(s_erasure, samSym.erasure(types))) { - staticArgs = staticArgs.append(s.erasure(types)); - } - } - } - if (context.isSerializable()) { + if (isSerializable) { addDeserializationCase(refKind, refSym, tree.type, samSym, tree, staticArgs, indyType); } @@ -1318,6 +1299,7 @@ // Make lambda holding the new-class call JCLambda slam = make.Lambda(params, nc); + slam.descriptorType = tree.descriptorType; slam.targets = tree.targets; slam.type = tree.type; slam.pos = tree.pos; @@ -1652,30 +1634,23 @@ /** the enclosing translation context (set for nested lambdas/mref) */ TranslationContext prev; - /** list of methods to be bridged by the meta-factory */ - List bridges; - TranslationContext(T tree) { this.tree = tree; this.owner = owner(); this.depth = frameStack.size() - 1; this.prev = context(); - ClassSymbol csym = - types.makeFunctionalInterfaceClass(attrEnv, names.empty, tree.targets, ABSTRACT | INTERFACE); - this.bridges = types.functionalInterfaceBridges(csym); } /** does this functional expression need to be created using alternate metafactory? */ boolean needsAltMetafactory() { - return tree.targets.length() > 1 || - isSerializable() || - bridges.length() > 1; + return (tree.targets.length() > 1 || + isSerializable()); } /** does this functional expression require serialization support? */ boolean isSerializable() { - for (Type target : tree.targets) { - if (types.asSuper(target, syms.serializableType.tsym) != null) { + for (Symbol target : tree.targets) { + if (types.asSuper(target.type, syms.serializableType.tsym) != null) { return true; } } @@ -1858,7 +1833,7 @@ } Type generatedLambdaSig() { - return types.erasure(tree.getDescriptorType(types)); + return types.erasure(tree.descriptorType); } } @@ -1934,7 +1909,7 @@ } Type bridgedRefSig() { - return types.erasure(types.findDescriptorSymbol(tree.targets.head.tsym).type); + return types.erasure(types.findDescriptorSymbol(tree.targets.head).type); } } } diff -r daf2e2653da5 -r d0e713f5cabd langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Tue Jun 18 20:56:04 2013 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Wed Jun 19 11:48:05 2013 +0100 @@ -68,7 +68,6 @@ private TreeMaker make; private Enter enter; private boolean allowEnums; - private boolean allowInterfaceBridges; private Types types; private final Resolve resolve; @@ -92,7 +91,6 @@ Source source = Source.instance(context); allowEnums = source.allowEnums(); addBridges = source.addBridges(); - allowInterfaceBridges = source.allowDefaultMethods(); types = Types.instance(context); make = TreeMaker.instance(context); resolve = Resolve.instance(context); @@ -254,8 +252,7 @@ // Create a bridge method symbol and a bridge definition without a body. Type bridgeType = meth.erasure(types); - long flags = impl.flags() & AccessFlags | SYNTHETIC | BRIDGE | - (origin.isInterface() ? DEFAULT : 0); + long flags = impl.flags() & AccessFlags | SYNTHETIC | BRIDGE; if (hypothetical) flags |= HYPOTHETICAL; MethodSymbol bridge = new MethodSymbol(flags, meth.name, @@ -390,12 +387,11 @@ } } // where - private Filter overrideBridgeFilter = new Filter() { + Filter overrideBridgeFilter = new Filter() { public boolean accepts(Symbol s) { return (s.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) != SYNTHETIC; } }; - /** * @param method The symbol for which a bridge might have to be added * @param impl The implementation of method @@ -1003,9 +999,8 @@ ListBuffer bridges = new ListBuffer(); if (false) //see CR: 6996415 bridges.appendList(addOverrideBridgesIfNeeded(tree, c)); - if (allowInterfaceBridges || (tree.sym.flags() & INTERFACE) == 0) { - addBridges(tree.pos(), c, bridges); - } + if ((tree.sym.flags() & INTERFACE) == 0) + addBridges(tree.pos(), tree.sym, bridges); tree.defs = bridges.toList().prependList(tree.defs); } tree.type = erasure(tree.type); diff -r daf2e2653da5 -r d0e713f5cabd langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java --- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java Tue Jun 18 20:56:04 2013 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java Wed Jun 19 11:48:05 2013 +0100 @@ -641,12 +641,10 @@ polyKind = PolyKind.POLY; } + /** target descriptor inferred for this functional expression. */ + public Type descriptorType; /** list of target types inferred for this functional expression. */ - public List targets; - - public Type getDescriptorType(Types types) { - return types.findDescriptorType(targets.head); - } + public List targets; } /** diff -r daf2e2653da5 -r d0e713f5cabd langtools/test/tools/javac/lambda/lambdaExpression/LambdaTest6.java --- a/langtools/test/tools/javac/lambda/lambdaExpression/LambdaTest6.java Tue Jun 18 20:56:04 2013 -0700 +++ b/langtools/test/tools/javac/lambda/lambdaExpression/LambdaTest6.java Wed Jun 19 11:48:05 2013 +0100 @@ -105,7 +105,7 @@ Class returnType = m.getReturnType(); assertTrue(types.remove(returnType.getName())); } - assertTrue(types.size() == 1); //there's a bridge + assertTrue(types.isEmpty()); } diff -r daf2e2653da5 -r d0e713f5cabd langtools/test/tools/javac/lambda/methodReference/BridgeMethod.java --- a/langtools/test/tools/javac/lambda/methodReference/BridgeMethod.java Tue Jun 18 20:56:04 2013 -0700 +++ b/langtools/test/tools/javac/lambda/methodReference/BridgeMethod.java Wed Jun 19 11:48:05 2013 +0100 @@ -112,6 +112,6 @@ Class returnType = m.getReturnType(); assertTrue(types.remove(returnType.getName())); } - assertTrue(types.size() == 1); //there's a bridge + assertTrue(types.isEmpty()); } }