changeset 1831:a2b6e71c5b62

Sync with changes per review comment on TL commit
author rfield
date Fri, 15 Feb 2013 19:52:55 -0800
parents 5868b9c53cfd
children 9e101aaa2c5c
files src/share/classes/com/sun/tools/javac/code/Symtab.java src/share/classes/com/sun/tools/javac/code/Types.java src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java src/share/classes/com/sun/tools/javac/jvm/UninitializedType.java test/tools/javac/lambda/LambdaInnerTypeVarArgsSerialize.java
diffstat 6 files changed, 157 insertions(+), 67 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/code/Symtab.java	Fri Feb 15 14:57:08 2013 +0000
+++ b/src/share/classes/com/sun/tools/javac/code/Symtab.java	Fri Feb 15 19:52:55 2013 -0800
@@ -516,6 +516,7 @@
         synthesizeEmptyInterfaceIfMissing(cloneableType);
         synthesizeEmptyInterfaceIfMissing(serializableType);
         synthesizeEmptyInterfaceIfMissing(lambdaMetafactory);
+        synthesizeEmptyInterfaceIfMissing(serializedLambdaType);
         synthesizeBoxTypeIfMissing(doubleType);
         synthesizeBoxTypeIfMissing(floatType);
         synthesizeBoxTypeIfMissing(voidType);
--- a/src/share/classes/com/sun/tools/javac/code/Types.java	Fri Feb 15 14:57:08 2013 +0000
+++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Fri Feb 15 19:52:55 2013 -0800
@@ -41,13 +41,11 @@
 import com.sun.tools.javac.util.*;
 import static com.sun.tools.javac.code.BoundKind.*;
 import static com.sun.tools.javac.code.Flags.*;
-import static com.sun.tools.javac.code.Kinds.MTH;
 import static com.sun.tools.javac.code.Scope.*;
 import static com.sun.tools.javac.code.Symbol.*;
 import static com.sun.tools.javac.code.Type.*;
 import static com.sun.tools.javac.code.TypeTag.*;
 import static com.sun.tools.javac.jvm.ClassFile.externalize;
-import com.sun.tools.javac.jvm.UninitializedType;
 import static com.sun.tools.javac.util.ListBuffer.lb;
 
 /**
@@ -569,7 +567,7 @@
             return false;
         }
     }
-    
+
     public Type removeWildcards(Type site) {
         if (capture(site) != site) {
             Type formalInterface = site.tsym.type;
@@ -1048,7 +1046,7 @@
                     throw new AssertionError("isSameType " + t.tag);
                 }
             }
-            
+
             abstract boolean sameTypeVars(TypeVar tv1, TypeVar tv2);
 
             @Override
@@ -1145,7 +1143,7 @@
                 return true;
             }
         }
-        
+
         TypeRelation isSameTypeLoose = new SameTypeVisitor() {
             @Override
             boolean sameTypeVars(TypeVar tv1, TypeVar tv2) {
@@ -2076,11 +2074,11 @@
             public Type visitAnnotatedType(AnnotatedType t, Boolean recurse) {
                 return new AnnotatedType(t.typeAnnotations, erasure(t.underlyingType, recurse));
             }
-        };
+    };
 
     private Mapping erasureFun = new Mapping ("erasure") {
             public Type apply(Type t) { return erasure(t); }
-        };
+    };
 
     private Mapping erasureRecFun = new Mapping ("erasureRecursive") {
         public Type apply(Type t) { return erasureRecursive(t); }
@@ -4346,22 +4344,22 @@
         return vis;
     }
     // </editor-fold>
-    
+
     // <editor-fold defaultstate="collapsed" desc="Signature Generation">
 
     public static abstract class SignatureGenerator {
-        
+
         private final Types types;
-        
+
         protected abstract void append(char ch);
         protected abstract void append(byte[] ba);
         protected abstract void append(Name name);
         protected void classReference(ClassSymbol c) { /* by default: no-op */ }
-       
+
         protected SignatureGenerator(Types types) {
             this.types = types;
         }
-        
+
         /**
          * Assemble signature of given type in string buffer.
          */
@@ -4447,12 +4445,6 @@
                     assembleParamsSig(ft.tvars);
                     assembleSig(ft.qtype);
                     break;
-                case UNINITIALIZED_THIS:
-                case UNINITIALIZED_OBJECT:
-                    // we don't yet have a spec for uninitialized types in the
-                    // local variable table
-                    assembleSig(types.erasure(((UninitializedType) type).qtype));
-                    break;
                 default:
                     throw new AssertionError("typeSig " + type.getTag());
             }
@@ -4476,7 +4468,7 @@
             Type outer = ct.getEnclosingType();
             if (outer.allparams().nonEmpty()) {
                 boolean rawOuter =
-                        c.owner.kind == MTH || // either a local class
+                        c.owner.kind == Kinds.MTH || // either a local class
                         c.name == types.names.empty; // or anonymous
                 assembleClassSig(rawOuter
                         ? types.erasure(outer)
@@ -4512,7 +4504,7 @@
             }
             append('>');
         }
-        
+
         private void assembleSig(List<Type> types) {
             for (List<Type> ts = types; ts.nonEmpty(); ts = ts.tail) {
                 assembleSig(ts.head);
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Feb 15 14:57:08 2013 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Feb 15 19:52:55 2013 -0800
@@ -86,38 +86,38 @@
 
     /** current translation context (visitor argument) */
     private TranslationContext<?> context;
-    
+
     /** info about the current class being processed */
     private KlassInfo kInfo;
 
     /** Flag for alternate metafactories indicating the lambda object is intended to be serializable */
     public static final int FLAG_SERIALIZABLE = 1 << 0;
-    
+
     /** Flag for alternate metafactories indicating the lambda object has multiple targets */
     public static final int FLAG_MARKERS = 1 << 1;
-    
+
     private class KlassInfo {
 
         /**
          * list of methods to append
          */
         private ListBuffer<JCTree> appendedMethodList;
-        
+
         /**
          * list of deserialization cases
          */
         private final Map<String, ListBuffer<JCStatement>> deserializeCases;
-        
+
        /**
          * deserialize method symbol
          */
         private final MethodSymbol deserMethodSym;
-        
+
         /**
          * deserialize method parameter symbol
          */
         private final VarSymbol deserParamSym;
-        
+
         private KlassInfo(Symbol kSym) {
             appendedMethodList = ListBuffer.lb();
             deserializeCases = new HashMap<String, ListBuffer<JCStatement>>();
@@ -127,7 +127,7 @@
             deserMethodSym = makeSyntheticMethod(flags, names.deserializeLambda, type, kSym);
             deserParamSym = new VarSymbol(FINAL, names.fromString("lambda"), syms.serializedLambdaType, deserMethodSym);
         }
-        
+
         private void addMethod(JCTree decl) {
             appendedMethodList = appendedMethodList.prepend(decl);
         }
@@ -255,7 +255,7 @@
         //to refer to the static method parameters (rather than i.e. acessing to
         //captured members directly).
         lambdaDecl.body = translate(makeLambdaBody(tree, lambdaDecl));
-        
+
         //Add the method to the list of methods to be added to this class.
         kInfo.addMethod(lambdaDecl);
 
@@ -503,7 +503,7 @@
         }
         return trans_block;
     }
-    
+
     private JCMethodDecl makeDeserializeMethod(Symbol kSym) {
         ListBuffer<JCCase> cases = ListBuffer.lb();
         ListBuffer<JCBreak> breaks = ListBuffer.lb();
@@ -520,7 +520,7 @@
         JCBlock body = make.Block(0L, List.<JCStatement>of(
                 sw,
                 make.Throw(makeNewClass(
-                    syms.illegalArgumentExceptionType, 
+                    syms.illegalArgumentExceptionType,
                     List.<JCExpression>of(make.Literal("Invalid lambda deserialization"))))));
         JCMethodDecl deser = make.MethodDef(make.Modifiers(kInfo.deserMethodSym.flags()),
                         names.deserializeLambda,
@@ -557,7 +557,7 @@
         String implClass = classSig(refSym.owner.type);
         String implMethodName = refSym.getQualifiedName().toString();
         String implMethodSignature = methodSig(types.erasure(refSym.type));
-         
+
         JCExpression kindTest = eqTest(syms.intType, deserGetter("getImplMethodKind", syms.intType), make.Literal(implMethodKind));
         ListBuffer<JCExpression> serArgs = ListBuffer.lb();
         int i = 0;
@@ -569,16 +569,16 @@
         }
         JCStatement stmt = make.If(
                 deserTest(deserTest(deserTest(deserTest(deserTest(
-                    kindTest, 
+                    kindTest,
                     "getFunctionalInterfaceClass", functionalInterfaceClass),
                     "getFunctionalInterfaceMethodName", functionalInterfaceMethodName),
                     "getFunctionalInterfaceMethodSignature", functionalInterfaceMethodSignature),
                     "getImplClass", implClass),
                     "getImplMethodSignature", implMethodSignature),
                 make.Return(makeIndyCall(
-                    pos, 
-                    syms.lambdaMetafactory, 
-                    names.altMetaFactory, 
+                    pos,
+                    syms.lambdaMetafactory,
+                    names.altMetaFactory,
                     staticArgs, indyType, serArgs.toList())),
                 null);
         ListBuffer<JCStatement> stmts = kInfo.deserializeCases.get(implMethodName);
@@ -598,19 +598,19 @@
         ****/
         stmts.append(stmt);
     }
-    
+
     private JCExpression eqTest(Type argType, JCExpression arg1, JCExpression arg2) {
         JCBinary testExpr = make.Binary(JCTree.Tag.EQ, arg1, arg2);
         testExpr.operator = rs.resolveBinaryOperator(null, JCTree.Tag.EQ, attrEnv, argType, argType);
         testExpr.setType(syms.booleanType);
         return testExpr;
     }
-    
+
     private JCExpression deserTest(JCExpression prev, String func, String lit) {
         MethodType eqmt = new MethodType(List.of(syms.objectType), syms.booleanType, List.<Type>nil(), syms.methodClass);
         Symbol eqsym = rs.resolveQualifiedMethod(null, attrEnv, syms.objectType, names.equals, List.of(syms.objectType), List.<Type>nil());
         JCMethodInvocation eqtest = make.Apply(
-                List.<JCExpression>nil(), 
+                List.<JCExpression>nil(),
                 make.Select(deserGetter(func, syms.stringType), eqsym).setType(eqmt),
                 List.<JCExpression>of(make.Literal(lit)));
         eqtest.setType(syms.booleanType);
@@ -619,17 +619,17 @@
         compound.setType(syms.booleanType);
         return compound;
     }
-    
+
     private JCExpression deserGetter(String func, Type type) {
         return deserGetter(func, type, List.<Type>nil(), List.<JCExpression>nil());
     }
-    
+
     private JCExpression deserGetter(String func, Type type, List<Type> argTypes, List<JCExpression> args) {
         MethodType getmt = new MethodType(argTypes, type, List.<Type>nil(), syms.methodClass);
         Symbol getsym = rs.resolveQualifiedMethod(null, attrEnv, syms.serializedLambdaType, names.fromString(func), argTypes, List.<Type>nil());
         return make.Apply(
-                    List.<JCExpression>nil(), 
-                    make.Select(make.Ident(kInfo.deserParamSym).setType(syms.serializedLambdaType), getsym).setType(getmt), 
+                    List.<JCExpression>nil(),
+                    make.Select(make.Ident(kInfo.deserParamSym).setType(syms.serializedLambdaType), getsym).setType(getmt),
                     args).setType(type);
     }
 
@@ -890,7 +890,7 @@
                 tree.type,
                 List.<Type>nil(),
                 syms.methodClass);
-        
+
         Name metafactoryName = needsAltMetafactory ?
                 names.altMetaFactory : names.metaFactory;
 
@@ -1001,7 +1001,7 @@
             }
         }
     }
-   
+
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">\
@@ -1020,14 +1020,14 @@
          * names)
          */
         private int lambdaCount = 0;
-        
+
         /**
          * keep the count of lambda expression defined in given context (used to
          * generate unambiguous names for serializable lambdas)
          */
         private Map<String, Integer> serializableLambdaCounts =
                 new HashMap<String, Integer>();
-        
+
         /**
          * maps for fake clinit symbols to be used as owners of lambda occurring in
          * a static var init context
@@ -1204,11 +1204,11 @@
         @Override
         public void visitVarDef(JCVariableDecl tree) {
             TranslationContext<?> context = context();
-            LambdaTranslationContext ltc = (context != null && context instanceof LambdaTranslationContext)? 
+            LambdaTranslationContext ltc = (context != null && context instanceof LambdaTranslationContext)?
                     (LambdaTranslationContext)context :
                     null;
             if (ltc != null) {
-                if (frameStack.head.tree.hasTag(LAMBDA)) { 
+                if (frameStack.head.tree.hasTag(LAMBDA)) {
                     ltc.addSymbol(tree.sym, LOCAL_VAR);
                 }
                 // Check for type variables (including as type arguments).
@@ -1235,7 +1235,7 @@
         private Name lambdaName() {
             return names.lambda.append(names.fromString("" + lambdaCount++));
         }
-        
+
         private Name serializedLambdaName(Symbol owner) {
             StringBuilder buf = new StringBuilder();
             buf.append(names.lambda);
@@ -1293,7 +1293,7 @@
             Assert.error();
             return null;
         }
-        
+
         private Symbol initSym(ClassSymbol csym, long flags) {
             boolean isStatic = (flags & STATIC) != 0;
             if (isStatic) {
@@ -1468,7 +1468,7 @@
                 locals = locals.prepend(sym);
             }
         }
-        
+
         /**
          * Listener class used to keep track of lambda translation context changes
          */
@@ -1500,13 +1500,13 @@
                 this.depth = frameStack.size() - 1;
                 this.prev = context();
             }
-            
+
             /** does this functional expression need to be created using alternate metafactory? */
             boolean needsAltMetafactory() {
                 return (tree.targets.length() > 1 ||
                         isSerializable());
             }
-            
+
             /** does this functional expression require serialization support? */
             boolean isSerializable() {
                 for (Symbol target : tree.targets) {
@@ -1548,7 +1548,7 @@
             Symbol translatedSym;
 
             List<JCVariableDecl> syntheticParams;
-            
+
             List<LambdaTranslationContextListener> listeners;
 
             LambdaTranslationContext(JCLambda tree) {
@@ -1726,7 +1726,7 @@
             boolean isArrayOp() {
                 return tree.sym.owner == syms.arrayClass;
             }
-            
+
             boolean isPrivateConstructor() {
                 return tree.sym.name == names.init &&
                         (tree.sym.flags() & PRIVATE) != 0;
@@ -1764,19 +1764,19 @@
      * Signature Generation
      * ****************************************************************
      */
-    
+
     private String methodSig(Type type) {
         L2MSignatureGenerator sg = new L2MSignatureGenerator();
         sg.assembleSig(type);
         return sg.toString();
     }
-    
+
     private String classSig(Type type) {
         L2MSignatureGenerator sg = new L2MSignatureGenerator();
         sg.assembleClassSig(type);
         return sg.toString();
     }
-    
+
     /**
      * Signature Generation
      */
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Fri Feb 15 14:57:08 2013 +0000
+++ b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Fri Feb 15 19:52:55 2013 -0800
@@ -153,10 +153,10 @@
 
     /** Access to files. */
     private final JavaFileManager fileManager;
-    
+
     /** Sole signature generator */
     private final CWSignatureGenerator signatureGen;
-    
+
     /** The tags and constants used in compressed stackmap. */
     static final int SAME_FRAME_SIZE = 64;
     static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
@@ -284,6 +284,25 @@
             super(types);
         }
 
+        /**
+         * Assemble signature of given type in string buffer.
+         * Check for uninitialized types before calling the general case.
+         */
+        @Override
+        public void assembleSig(Type type) {
+            type = type.unannotatedType();
+            switch (type.getTag()) {
+                case UNINITIALIZED_THIS:
+                case UNINITIALIZED_OBJECT:
+                    // we don't yet have a spec for uninitialized types in the
+                    // local variable table
+                    assembleSig(types.erasure(((UninitializedType)type).qtype));
+                    break;
+                default:
+                    super.assembleSig(type);
+            }
+        }
+
         @Override
         protected void append(char ch) {
             sigbuf.appendByte(ch);
@@ -303,15 +322,15 @@
         protected void classReference(ClassSymbol c) {
             enterInner(c);
         }
-        
+
         private void reset() {
             sigbuf.reset();
         }
-        
+
         private Name toName() {
             return sigbuf.toName(names);
         }
-        
+
         private boolean isEmpty() {
             return sigbuf.length == 0;
         }
@@ -884,8 +903,6 @@
     void writePosition(TypeAnnotationPosition p) {
         databuf.appendByte(p.type.targetTypeValue()); // TargetType tag is a byte
         switch (p.type) {
-        // type cast
-        case CAST:
         // instanceof
         case INSTANCEOF:
         // new expression
--- a/src/share/classes/com/sun/tools/javac/jvm/UninitializedType.java	Fri Feb 15 14:57:08 2013 +0000
+++ b/src/share/classes/com/sun/tools/javac/jvm/UninitializedType.java	Fri Feb 15 19:52:55 2013 -0800
@@ -38,7 +38,7 @@
  *  This code and its internal interfaces are subject to change or
  *  deletion without notice.</b>
  */
-public class UninitializedType extends Type.DelegatedType {
+class UninitializedType extends Type.DelegatedType {
 
     public static UninitializedType uninitializedThis(Type qtype) {
         return new UninitializedType(UNINITIALIZED_THIS, qtype, -1);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/LambdaInnerTypeVarArgsSerialize.java	Fri Feb 15 19:52:55 2013 -0800
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8005653
+ * @summary A serialized lambda containing an inner class referencing an external type var in class parameter type
+ * @author  Robert Field
+ * @run main LambdaInnerTypeVarArgs
+ */
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.ArrayList;
+
+public class LambdaInnerTypeVarArgsSerialize {
+
+    static int assertionCount = 0;
+
+    static void assertTrue(boolean cond) {
+        assertionCount++;
+        if (!cond)
+            throw new AssertionError();
+    }
+
+    interface I extends Serializable {
+        C doit();
+    }
+
+    abstract class C {
+        abstract Object it();
+    }
+
+    class TV {
+        C go() {
+            List<String> ls = new ArrayList<>();
+            ls.add("Oh");
+            ls.add("my");
+            return foo(ls).doit();
+        }
+
+        <RRRRR> I foo(List<RRRRR> r) {
+            return () -> new C() {
+                List<RRRRR> xxxxx = r;
+                @Override
+                    Object it() { return xxxxx; };
+            };
+        }
+    }
+    
+    void test1() {
+        assertTrue(((List<String>)(new TV().go().it())).get(0).equals("Oh"));
+    }
+
+    public static void main(String[] args) {
+        LambdaInnerTypeVarArgsSerialize t = new LambdaInnerTypeVarArgsSerialize();
+        t.test1();
+        assertTrue(assertionCount == 1);
+    }
+}