changeset 2992:c5b28bea0a2b

Fix: normalize specializer signatures containing captured types Tweaked internal routines to handle captured types pointing to avars. Added normalization step to remove captured types from BytecodeMapping attribute signatures. Added tests
author mcimadamore
date Thu, 28 May 2015 12:34:24 +0100
parents be15fb529cd3
children b91634e5f051
files src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java test/tools/javac/valhalla/typespec/TestCapture.java test/tools/javac/valhalla/typespec/items/tests/TestCapture.java
diffstat 5 files changed, 160 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Mon May 25 12:55:54 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Thu May 28 12:34:24 2015 +0100
@@ -365,10 +365,44 @@
             public Boolean visitArrayType(ArrayType t, Predicate<Type> typeArgsFilter) {
                 return visit(t.elemtype, typeArgsFilter);
             }
+
+            @Override
+            public Boolean visitCapturedType(CapturedType t, Predicate<Type> typePredicate) {
+                return visitWildcardType(t.wildcard, typePredicate);
+            }
         };
 
         Predicate<Type> containsAnyRecursive = t -> true;
         Predicate<Type> getContainsAnyFlat = t -> t.hasTag(TYPEVAR) || t.hasTag(WILDCARD);
+
+    /**
+     * Is given type argument specializable?
+     */
+    public boolean isTypeArgumentSpecializable(Type t) {
+        return specializableTypeArg.visit(t);
+    }
+
+    private UnaryVisitor<Boolean> specializableTypeArg = new UnaryVisitor<Boolean>() {
+        @Override
+        public Boolean visitType(Type t, Void aVoid) {
+            return t.isPrimitiveOrValue();
+        }
+
+        @Override
+        public Boolean visitCapturedType(CapturedType t, Void aVoid) {
+            return visitWildcardType(t.wildcard, null);
+        }
+
+        @Override
+        public Boolean visitWildcardType(WildcardType t, Void aVoid) {
+            return visit(t.type, null);
+        }
+
+        @Override
+        public Boolean visitTypeVar(TypeVar t, Void aVoid) {
+            return isSpecializableTypeVar(t);
+        }
+    };
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="isUnbounded">
@@ -2070,11 +2104,6 @@
     public boolean isTypeArgumentReifiable(Type t) {
         return isValueCompatible(t) || t.isUnbound();
     }
-
-    public boolean isTypeArgumentSpecializable(Type t) {
-        return (t.hasTag(WILDCARD) && isTypeArgumentSpecializable(((WildcardType)t).type)) ||
-                        t.isPrimitiveOrValue() || isSpecializableTypeVar(t);
-    }
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="Array Utils">
@@ -5611,10 +5640,6 @@
             append('>');
         }
 
-        public void assembleTypeVarName(Type tvar) {
-            append(tvar.tsym.name);
-        }
-
         private void assembleSig(List<Type> types) {
             for (List<Type> ts = types; ts.nonEmpty(); ts = ts.tail) {
                 assembleSig(ts.head);
@@ -5662,29 +5687,24 @@
         SignatureGenerator sg = new BuilderSignatureGenerator(this);
         sg.assembleSig(type);
         return names.fromString(sg.toString());
-    }
-
-    public Name typeVariableOwnerName(Symbol owner) {
-        switch (owner.kind) {
-            case TYP:
-                return owner.getQualifiedName();
-            case MTH:
-                return typeVariableOwnerName(owner.owner)
-                        .append(names.fromString("."))
-                        .append(owner.name);
-            default:
-                throw new AssertionError("Wrong kind " + owner.kind + "  " + owner);
-        }
-    }
+   }
 
     public Name specializerSig(Type type) {
         SignatureGenerator sg = new BuilderSignatureGenerator(this) {
             @Override
-            public void assembleTypeVarName(Type tvar) {
-                TypeSymbol tvarSym = tvar.tsym;
-                append(typeVariableOwnerName(tvarSym.owner)
-                        .append(names.fromString("::"))
-                        .append(tvarSym.name));
+            public void assembleSig(Type type) {
+                super.assembleSig(normalize(type));
+            }
+
+            private Type normalize(Type t) {
+                switch (t.getTag()) {
+                    case TYPEVAR:
+                        TypeVar tv = (TypeVar)t;
+                        return ((TypeVar)t).isCaptured() ?
+                                normalize(((CapturedType)t).wildcard) : tv;
+                    default:
+                        return t;
+                }
             }
         };
         sg.assembleSig(type);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java	Mon May 25 12:55:54 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java	Thu May 28 12:34:24 2015 +0100
@@ -201,12 +201,11 @@
                                                List<JCExpression> args, JCExpression receiverExpr,
                                                List<Type> typeargs, Type receiverType, Type varargsElement) {
         if (typeargs.nonEmpty()) {
-            Predicate<Type> needsIndy = t -> t.isPrimitiveOrValue() || types.isSpecializableTypeVar(t);
-            if (typeargs.stream().anyMatch(needsIndy)) {
+            if (typeargs.stream().anyMatch(types::isTypeArgumentSpecializable)) {
                 receiverType = types.referenceArgTypesAsErasedFormals(receiverType);
 
                 List<Object> staticArgs = typeargs.stream()
-                        .map(ta -> needsIndy.test(ta) ? types.typeSig(ta).toString() : "")
+                        .map(ta -> types.isTypeArgumentSpecializable(ta) ? types.specializerSig(ta).toString() : "")
                         .collect(List.collector());
 
                 Symbol unspecializedMeth = msym.baseSymbol();
@@ -242,7 +241,7 @@
 
                 List<Type> formals = uninstantiatedMethodType.tvars;
                 List<Type> instTypes = Tuple2.zip(formals, typeargs).stream()
-                        .map(p -> needsIndy.test(p.elem1) ?
+                        .map(p -> types.isTypeArgumentSpecializable(p.elem1) ?
                                 p.elem1 :
                                 types.asSuper(p.elem1, types.erasure(p.elem0).tsym))
                         .collect(List.collector());
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java	Mon May 25 12:55:54 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java	Thu May 28 12:34:24 2015 +0100
@@ -514,7 +514,7 @@
         }
 
         protected Name getSig(int opcode) {
-            return types.typeSig(originalType);
+            return types.specializerSig(originalType);
         }
 
         /**
@@ -620,8 +620,8 @@
         protected Name getSig(int opcode) {
             return isMemberAcccess(opcode) ?
                     names.fromString(String.join("::",
-                            types.typeSig(ownerType),
-                            types.typeSig(memberType))) :
+                            types.specializerSig(ownerType),
+                            types.specializerSig(memberType))) :
                     super.getSig(opcode);
         }
     }
@@ -644,7 +644,7 @@
         @Override
         protected Name getSig(int opcode) {
             return needsMapping(opcode) ?
-                    types.typeSig(indyType) :
+                    types.specializerSig(indyType) :
                     super.getSig(opcode);
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/TestCapture.java	Thu May 28 12:34:24 2015 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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
+ * @summary Smoke test for normalization of captured types in generated specializer signatures.
+ */
+public class TestCapture {
+    static class List<any E> { }
+
+    static class Foo<any X> {
+        void m(List<? extends X> l) {
+            g(l);
+            new Bar<>(l);
+        }
+
+        <any Z> void g(List<Z> lz) { }
+    }
+
+    static class Bar<any B> {
+       Bar(List<B> lb) { }
+    }
+
+    public static void main(String[] args) {
+		new Foo<int>().m(new List<int>());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/typespec/items/tests/TestCapture.java	Thu May 28 12:34:24 2015 +0100
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+class TestCapture<any X> {
+    static class AnyClass<any X> { }
+
+    @BytecodeMapping(opcode = Opcodes.INVOKEDYNAMIC, sig = "(LTestCapture<TX;>;LTestCapture$AnyClass<-TX;>;)V")
+    void testInvokeSuper(AnyClass<? super X> a) {
+        m(a);
+    }
+
+    @BytecodeMapping(opcode = Opcodes.INVOKEDYNAMIC, sig = "(LTestCapture<TX;>;LTestCapture$AnyClass<+TX;>;)V")
+    void testInvokeExtends(AnyClass<? extends X> a) {
+        m(a);
+    }
+
+    @BytecodeMapping(opcode = Opcodes.NEW, sig = "LTestCapture$Wrap<-TX;>;")
+    @BytecodeMapping(opcode = Opcodes.INVOKESPECIAL, sig = "LTestCapture$Wrap<-TX;>;::(LTestCapture$AnyClass<-TX;>;)V")
+    void testNewSuper(AnyClass<? super X> a) {
+        new Wrap<>(a);
+    }
+
+    @BytecodeMapping(opcode = Opcodes.NEW, sig = "LTestCapture$Wrap<+TX;>;")
+    @BytecodeMapping(opcode = Opcodes.INVOKESPECIAL, sig = "LTestCapture$Wrap<+TX;>;::(LTestCapture$AnyClass<+TX;>;)V")
+    void testNewExtends(AnyClass<? extends X> a) {
+        new Wrap<>(a);
+    }
+
+    static class Wrap<any X> {
+        Wrap(AnyClass<X> a) { }
+    }
+
+    <any Z> void m(AnyClass<Z> anyClass) { }
+}