changeset 3511:ca533bf26159

Misc specialized local class fixes: * free variables are incorrectly erased eagerly * generic method translation should patch local class types * enhance ClassReader/PoolReader so that enclosing method attribute can be parsed correctly
author mcimadamore
date Mon, 04 Jul 2016 18:14:21 +0100
parents 515df83430aa
children 2edcdbb2943a
files src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolReader.java
diffstat 5 files changed, 94 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Wed Jun 15 18:05:40 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Mon Jul 04 18:14:21 2016 +0100
@@ -1096,6 +1096,7 @@
 
         public void setEnclosingType(Type outer) {
             outer_field = outer;
+            allparams_field = null; //rebuild the cache
         }
 
         public List<Type> allparams() {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Wed Jun 15 18:05:40 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Mon Jul 04 18:14:21 2016 +0100
@@ -1604,7 +1604,7 @@
         for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
             VarSymbol v = l.head;
             VarSymbol proxy = new VarSymbol(
-                flags, proxyName(v.name), v.erasure(types), owner);
+                flags, proxyName(v.name), v.type, owner);
             proxies.enter(proxy);
             JCVariableDecl vd = make.at(pos).VarDef(proxy, null);
             vd.vartype = access(vd.vartype);
@@ -1968,10 +1968,12 @@
         Symbol lhs = it.next();
         Assert.check(rhs.owner.owner == lhs.owner);
         make.at(pos);
+        JCExpression thiz = make.This(lhs.owner.erasure(types));
+        thiz.unerasedType = lhs.owner.type;
         return
             make.Exec(
                 make.Assign(
-                    make.Select(make.This(lhs.owner.erasure(types)), lhs),
+                    make.Select(thiz, lhs),
                     make.Ident(rhs)).setType(lhs.erasure(types)));
     }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java	Wed Jun 15 18:05:40 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java	Mon Jul 04 18:14:21 2016 +0100
@@ -26,14 +26,12 @@
 package com.sun.tools.javac.comp;
 
 import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.code.Flags.Flag;
 import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol;
 import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol.BootstrapArgument;
 import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol.BootstrapArgument.Kind;
-import com.sun.tools.javac.code.Symbol.MethodHandleSymbol;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
 import com.sun.tools.javac.code.Symbol.TypeVariableSymbol;
 import com.sun.tools.javac.code.Symbol.VarSymbol;
@@ -42,8 +40,10 @@
 import com.sun.tools.javac.code.Type.ClassType;
 import com.sun.tools.javac.code.Type.ForAll;
 import com.sun.tools.javac.code.Type.MethodType;
+import com.sun.tools.javac.code.Type.TypeMapping;
 import com.sun.tools.javac.code.Type.TypeVar;
 import com.sun.tools.javac.code.Type.UndetVar;
+import com.sun.tools.javac.code.TypeMetadata;
 import com.sun.tools.javac.code.TypeTag;
 import com.sun.tools.javac.code.Types;
 import com.sun.tools.javac.code.Types.TypeVarContext;
@@ -84,16 +84,16 @@
 import com.sun.tools.javac.util.ListBuffer;
 import com.sun.tools.javac.util.Log;
 import com.sun.tools.javac.util.Name;
-import com.sun.tools.javac.util.Options;
 import com.sun.tools.javac.util.Tuple.Tuple2;
 
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 import java.util.function.BiFunction;
 import java.util.function.Function;
 import java.util.function.Supplier;
-import java.util.function.ToIntBiFunction;
 import java.util.function.ToIntFunction;
 import java.util.stream.Collectors;
 
@@ -879,6 +879,7 @@
             Map<Symbol, Symbol> paramMap;
             List<Type> oldTypeVars, newTypeVars;
             Symbol oldMeth, newMeth;
+            Set<Symbol> localClassSyms = new HashSet<>();
 
             GenericMethodPatcher(JCMethodDecl oldMeth, JCMethodDecl newMeth,
                                  List<Type> oldTypeVars, List<Type> newTypeVars) {
@@ -895,7 +896,7 @@
             public <T extends JCTree> T translate(T tree) {
                 JCTree newTree = super.translate(tree);
                 if (newTree != null && newTree.type != null) {
-                    newTree.type = patchTypeVars(newTree.type);
+                    newTree.type = patchType(newTree.type);
                 }
                 return (T)newTree;
             }
@@ -904,7 +905,8 @@
             public void visitNewClass(JCNewClass tree) {
                 super.visitNewClass(tree);
                 JCNewClass newTree = (JCNewClass)result;
-                newTree.constructorType = patchTypeVars(newTree.constructorType);
+                newTree.constructorType = patchType(newTree.constructorType);
+                newTree.type = patchType(newTree.type);
             }
 
             @Override
@@ -912,7 +914,7 @@
                 super.visitLambda(tree);
                 JCLambda newTree = (JCLambda)result;
                 newTree.targets = newTree.targets.stream()
-                        .map(this::patchTypeVars).collect(List.collector());
+                        .map(this::patchType).collect(List.collector());
             }
 
             @Override
@@ -920,9 +922,9 @@
                 super.visitReference(tree);
                 JCMemberReference newTree = (JCMemberReference)result;
                 newTree.targets = newTree.targets.stream()
-                        .map(this::patchTypeVars).collect(List.collector());
-                newTree.referentSite = patchTypeVars(newTree.referentSite);
-                newTree.referentType = patchTypeVars(newTree.referentType);
+                        .map(this::patchType).collect(List.collector());
+                newTree.referentSite = patchType(newTree.referentSite);
+                newTree.referentType = patchType(newTree.referentType);
             }
 
             @Override
@@ -951,11 +953,11 @@
                     sel.type = tree.type;
                     result = sel;
                 } else if (tree.sym.kind == TYP && tree.type.hasTag(TYPEVAR)) {
-                    tree.type = patchTypeVars(tree.type);
+                    tree.type = patchType(tree.type);
                     tree.sym = tree.type.tsym;
                     result = tree;
                 } else {
-                    tree.type = patchTypeVars(tree.type);
+                    tree.type = patchType(tree.type);
                     tree.sym = patchParam(tree.sym);
                     result = tree;
                 }
@@ -968,31 +970,50 @@
                 if (newTree.sym.owner == oldMeth) {
                     newTree.sym.owner = newMeth;
                 }
-                newTree.type = newTree.sym.type = patchTypeVars(newTree.type);
+                newTree.type = newTree.sym.type = patchType(newTree.type);
             }
 
             @Override
             public void visitMethodDef(JCMethodDecl tree) {
                 super.visitMethodDef(tree);
                 JCMethodDecl newTree = (JCMethodDecl)result;
-                newTree.type = newTree.sym.type = patchTypeVars(newTree.type);
+                newTree.type = newTree.sym.type = patchType(newTree.type);
             }
 
-        @Override
+            @Override
             public void visitClassDef(JCClassDecl tree) {
+                if (tree.sym.owner == oldMeth) {
+                    tree.sym.owner = newMeth;
+                    if (tree.type.getEnclosingType().hasTag(NONE)) {
+                        //make it species static
+                        tree.sym.flags_field |= Flags.STATIC | Flags.SPECIES | Flags.NOOUTERTHIS;
+                    }
+                    ClassType ctype = (ClassType)tree.sym.type.cloneWithMetadata(TypeMetadata.EMPTY);
+                    ctype.setEnclosingType(newMeth.enclClass().type);
+                    Type prevType = tree.type;
+                    tree.type = tree.sym.type = ctype;
+                    localClassSyms.add(tree.sym);
+                    ctype.supertype_field = patchType(types.supertype(prevType));
+                    ctype.interfaces_field = types.interfaces(prevType).stream()
+                            .map(this::patchType)
+                            .collect(List.collector());
+                }
+                tree.sym.flatname = chk.localClassName(tree.sym);
                 super.visitClassDef(tree);
-                JCClassDecl newTree = (JCClassDecl)result;
-                if (newTree.sym.owner == oldMeth) {
-                    newTree.sym.owner = newMeth;
-                }
-                newTree.sym.flatname = chk.localClassName(newTree.sym);
+            }
+
+            @Override
+            public void visitTypeApply(JCTypeApply tree) {
+                super.visitTypeApply(tree);
+                JCTypeApply newTree = (JCTypeApply)result;
+                newTree.type = patchType(newTree.type);
             }
 
             @Override
             public void visitSelect(JCFieldAccess tree) {
                 super.visitSelect(tree);
                 JCFieldAccess newTree = (JCFieldAccess)result;
-                newTree.type = patchTypeVars(newTree.type);
+                newTree.type = patchType(newTree.type);
                 newTree.sym = patchParam(newTree.sym);
             }
 
@@ -1001,18 +1022,35 @@
                 super.visitApply(tree);
                 JCMethodInvocation meth = (JCMethodInvocation)result;
                 meth.typeargs = translate(meth.typeargs);
-                meth.meth.type = patchTypeVars(meth.meth.type);
+                meth.meth.type = patchType(meth.meth.type);
                 result = meth;
             }
 
-            Type patchTypeVars(Type t) {
-                Type t2 = types.subst(t, oldTypeVars, newTypeVars);
+            TypeMapping<Void> localVarMapping = new TypeMapping<Void>() {
+                @Override
+                public Type visitClassType(ClassType t, Void _unused) {
+                    if (localClassSyms.contains(t.tsym)) {
+                        return t.getTypeArguments().nonEmpty() ?
+                                new ClassType(newMeth.enclClass().type, t.getTypeArguments(), t.tsym) :
+                                t.tsym.type;
+                    } else {
+                        return super.visitClassType(t, null);
+                    }
+                }
+            };
+
+            Type patchType(Type t) {
+                Type t2 = t.map(localVarMapping);
+                t2 = types.subst(t2, oldTypeVars, newTypeVars);
                 if (t instanceof InferredMethodType) {
                     InferredMethodType imt = (InferredMethodType)t;
                     for (Type uv : imt.inferenceContext.undetvars) {
-                        ((UndetVar)uv).setInst(patchTypeVars(((UndetVar)uv).getInst()));
+                        ((UndetVar)uv).setInst(patchType(((UndetVar)uv).getInst()));
                     }
                     t2 = new InferredMethodType(t2.asMethodType(), imt.inferenceContext);
+                } else if (t instanceof ForAll) {
+                    ForAll fa = (ForAll)t;
+                    t2 = new ForAll(fa.tvars, t2);
                 }
                 return t2;
             }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Wed Jun 15 18:05:40 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Jul 04 18:14:21 2016 +0100
@@ -1017,7 +1017,14 @@
         int methodIndex = nextChar();
         Tuple2<Name, Type> nt = null;
         if (methodIndex > 0) {
-            nt = poolReader.getNameAndType(methodIndex);
+            try {
+                //we need to augment pool reader's variables temporarily to parse the enclosing method
+                //correctly (as it might contain references to type-vars declared in the gen method class)
+                nt = poolReader.withEnclosingClass(c, r -> r.getNameAndType(methodIndex));
+            } catch (Throwable ex) {
+                //recovery
+                nt = poolReader.getNameAndType(methodIndex);
+            }
         }
 
         if (c.members_field == null)
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolReader.java	Wed Jun 15 18:05:40 2016 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolReader.java	Mon Jul 04 18:14:21 2016 +0100
@@ -41,6 +41,7 @@
 import com.sun.tools.javac.util.Tuple.Tuple2;
 
 import java.util.Optional;
+import java.util.function.Function;
 
 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_ArrayType;
 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Class;
@@ -91,12 +92,26 @@
 
     Type[] typeVars() {
         if (typeVarsByOwner == null) {
-            typeVarsByOwner = types.typeVarsByOwner(poolClass).stream()
+            typeVarsByOwner = computeTypeVars(poolClass);
+        }
+        return typeVarsByOwner;
+    }
+
+    <Z> Z withEnclosingClass(ClassSymbol csym, Function<PoolReader, Z> action) {
+        Type[] prevTypeVars = typeVarsByOwner;
+        try {
+            typeVarsByOwner = computeTypeVars(csym);
+            return action.apply(this);
+        } finally {
+            typeVarsByOwner = prevTypeVars;
+        }
+    }
+
+    private Type[] computeTypeVars(Symbol s) {
+        return types.typeVarsByOwner(s).stream()
                     .filter(p -> p.elem0.kind == Kind.TYP)
                     .flatMap(t -> t.elem1.stream())
                     .toArray(Type[]::new);
-        }
-        return typeVarsByOwner;
     }
 
     /**