changeset 48839:4dc46c132c2e lworld

Initial support for code generation using defaultvalue and withfield
author sadayapalam
date Tue, 06 Feb 2018 18:13:17 +0530
parents 59af66a8c1be
children 5df93aa2bdc4
files src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ByteCodes.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java src/jdk.jdeps/share/classes/com/sun/tools/classfile/Opcode.java test/langtools/tools/javac/valhalla/lworld-values/CheckFlags.java test/langtools/tools/javac/valhalla/lworld-values/ValueCreationTest.java
diffstat 10 files changed, 230 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Mon Feb 05 16:07:09 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Tue Feb 06 18:13:17 2018 +0530
@@ -5038,12 +5038,6 @@
                     break;
                 case CLASS:
                     append('L');
-                    /* TODO(Srikanth): Figure out the right thing in the L-world
-                    if (types.isValue(type))
-                        append('Q');
-                    else
-                        append('L');
-                    */
                     assembleClassSig(type);
                     append(';');
                     break;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ByteCodes.java	Mon Feb 05 16:07:09 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ByteCodes.java	Tue Feb 06 18:13:17 2018 +0530
@@ -242,7 +242,12 @@
         goto_w          = 200,
         jsr_w           = 201,
         breakpoint      = 202,
-        ByteCodeCount   = 203;
+
+        // value-type bytecodes
+        defaultvalue    = 203,
+        withfield       = 204,
+
+        ByteCodeCount   = 205;
 
     /** Virtual instruction codes; used for constant folding.
      */
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Feb 05 16:07:09 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Tue Feb 06 18:13:17 2018 +0530
@@ -2919,6 +2919,8 @@
             flags &= ~ACC_MODULE;
             flags |= MODULE;
         }
+        if ((flags & ACC_VALUE) != 0)
+            flags = (flags ^ ACC_VALUE) | VALUE;
         return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
     }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Mon Feb 05 16:07:09 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Tue Feb 06 18:13:17 2018 +0530
@@ -1715,7 +1715,7 @@
         } else {
             flags = adjustFlags(c.flags() & ~DEFAULT);
             if ((flags & PROTECTED) != 0) flags |= PUBLIC;
-            flags = flags & ClassFlags & ~STRICTFP;
+            flags = flags & (ClassFlags | ACC_VALUE) & ~STRICTFP;
             if ((flags & INTERFACE) == 0) flags |= ACC_SUPER;
         }
 
@@ -1855,6 +1855,8 @@
             result |= ACC_VARARGS;
         if ((flags & DEFAULT) != 0)
             result &= ~ABSTRACT;
+        if ((flags & VALUE) != 0)
+            result |= ACC_VALUE;
         return result;
     }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java	Mon Feb 05 16:07:09 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java	Tue Feb 06 18:13:17 2018 +0530
@@ -1024,6 +1024,17 @@
             }
             state.push(uninitializedObject(sym.erasure(types), cp-3));
             break;
+        case defaultvalue:
+            if (pool.pool[od] instanceof UniqueType) {
+                // Required by change in Gen.makeRef to allow
+                // annotated types.
+                // TODO: is this needed anywhere else?
+                sym = ((UniqueType)(pool.pool[od])).type.tsym;
+            } else {
+                sym = (Symbol)(pool.pool[od]);
+            }
+            state.push(sym.erasure(types));
+            break;
         case sipush:
             state.push(syms.intType);
             break;
@@ -1050,6 +1061,9 @@
         case goto_:
             markDead();
             break;
+        case withfield:
+            state.pop(((Symbol)(pool.pool[od])).erasure(types));
+            break;
         case putfield:
             state.pop(((Symbol)(pool.pool[od])).erasure(types));
             state.pop(1); // object ref
@@ -2431,6 +2445,8 @@
             mnem[goto_w] = "goto_w";
             mnem[jsr_w] = "jsr_w";
             mnem[breakpoint] = "breakpoint";
+            mnem[defaultvalue] = "defaultvalue";
+            mnem[withfield] = "withfield";
         }
     }
 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Mon Feb 05 16:07:09 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Tue Feb 06 18:13:17 2018 +0530
@@ -25,6 +25,7 @@
 
 package com.sun.tools.javac.jvm;
 
+import com.sun.source.tree.NewClassTree.CreationMode;
 import com.sun.tools.javac.tree.TreeInfo.PosKind;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
@@ -1728,15 +1729,23 @@
         Assert.check(tree.encl == null && tree.def == null);
         setTypeAnnotationPositions(tree.pos);
 
-        code.emitop2(new_, makeRef(tree.pos(), tree.type));
-        code.emitop0(dup);
+        Type newType = tree.type;
 
-        // Generate code for all arguments, where the expected types are
-        // the parameters of the constructor's external type (that is,
-        // any implicit outer instance appears as first parameter).
-        genArgs(tree.args, tree.constructor.externalType(types).getParameterTypes());
+        if (types.isValue(newType)) {
+            Assert.check(tree.creationMode == CreationMode.DEFAULT_VALUE);
+            Assert.check(tree.constructorType.getParameterTypes().isEmpty());
+            code.emitop2(defaultvalue, makeRef(tree.pos(), newType));
+        } else {
+            code.emitop2(new_, makeRef(tree.pos(), tree.type));
+            code.emitop0(dup);
 
-        items.makeMemberItem(tree.constructor, true).invoke();
+            // Generate code for all arguments, where the expected types are
+            // the parameters of the constructor's external type (that is,
+            // any implicit outer instance appears as first parameter).
+            genArgs(tree.args, tree.constructor.externalType(types).getParameterTypes());
+
+            items.makeMemberItem(tree.constructor, true).invoke();
+        }
         result = items.makeStackItem(tree.type);
     }
 
@@ -2111,10 +2120,17 @@
                     code.emitop0(arraylength);
                     result = items.makeStackItem(syms.intType);
                 } else {
+                    boolean requireCopyOnWrite = false;
+                    if (sym.kind == VAR && (sym.flags() & FINAL) != 0) {
+                        if ((env.enclMethod.mods.flags & STATICVALUEFACTORY) != 0) {
+                            if (sym.owner == env.enclClass.sym)
+                                requireCopyOnWrite = true;
+                        }
+                    }
                     result = items.
                         makeMemberItem(sym,
                                        (sym.flags() & PRIVATE) != 0 ||
-                                       selectSuper || accessSuper);
+                                       selectSuper || accessSuper, (requireCopyOnWrite ? base : null));
                 }
             }
         }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java	Mon Feb 05 16:07:09 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java	Tue Feb 06 18:13:17 2018 +0530
@@ -150,9 +150,19 @@
      *  @param member       The represented symbol.
      *  @param nonvirtual   Is the reference not virtual? (true for constructors
      *                      and private members).
+     *  @param baseToCopyOnWrite Updates to fields imply copy on write to this receiver
+     */
+    Item makeMemberItem(Symbol member, boolean nonvirtual, Item baseToCopyOnWrite) {
+        return  baseToCopyOnWrite != null ? new CopyOnWriteMemberItem(baseToCopyOnWrite, member) : new MemberItem(member, nonvirtual);
+    }
+
+    /** Make an item representing an instance variable or method.
+     *  @param member       The represented symbol.
+     *  @param nonvirtual   Is the reference not virtual? (true for constructors
+     *                      and private members).
      */
     Item makeMemberItem(Symbol member, boolean nonvirtual) {
-        return new MemberItem(member, nonvirtual);
+        return makeMemberItem(member, nonvirtual, null);
     }
 
     /** Make an item representing a literal.
@@ -554,6 +564,21 @@
         }
     }
 
+    class CopyOnWriteMemberItem extends MemberItem {
+
+        Item rcvItem;
+
+        CopyOnWriteMemberItem(Item rcvItem, Symbol member) {
+            super(member, false);
+            this.rcvItem = rcvItem;
+        }
+
+        void store() {
+            code.emitop2(withfield, pool.put(member));
+            rcvItem.store();
+        }
+    }
+
     /** An item representing a literal.
      */
     class ImmediateItem extends Item {
--- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Opcode.java	Mon Feb 05 16:07:09 2018 +0530
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Opcode.java	Tue Feb 06 18:13:17 2018 +0530
@@ -243,17 +243,8 @@
     GOTO_W(0xc8, BRANCH_W),
     JSR_W(0xc9, BRANCH_W),
 
-    VLOAD(203, LOCAL),
-    VSTORE(204, LOCAL),
-    VALOAD(205),
-    VASTORE(206),
-    VRETURN(207),
-
-    VDEFAULT(208, CPREF_W),
-    VWITHFIELD(209, CPREF_W),
-
-    VBOX(210, CPREF_W),
-    VUNBOX(211, CPREF_W),
+    DEFAULTVALUE(203, CPREF_W),
+    WITHFIELD(204, CPREF_W),
 
     // impdep 0xfe: PicoJava nonpriv
     // impdep 0xff: Picojava priv
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/valhalla/lworld-values/CheckFlags.java	Tue Feb 06 18:13:17 2018 +0530
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018, 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 Check value flag in class file
+ * @modules jdk.jdeps/com.sun.tools.classfile
+ * @compile Point.java
+ * @run main CheckFlags
+ */
+
+import com.sun.tools.classfile.*;
+
+public class CheckFlags {
+    public static void main(String[] args) throws Exception {
+        ClassFile cls = ClassFile.read(CheckFlags.class.getResourceAsStream("Point.class"));
+
+        if (!cls.access_flags.is(AccessFlags.ACC_VALUE))
+            throw new Exception("Value flag not set");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/valhalla/lworld-values/ValueCreationTest.java	Tue Feb 06 18:13:17 2018 +0530
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2018, 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
+ * @summary Check code generation for value creation ops
+ * @modules jdk.compiler/com.sun.tools.javac.util jdk.jdeps/com.sun.tools.javap
+ * @compile ValueCreationTest.java
+ * @run main/othervm -Xverify:none -XX:+EnableValhalla ValueCreationTest
+ * @modules jdk.compiler
+ */
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.file.Paths;
+
+public class ValueCreationTest {
+
+    __ByValue
+    static final class Point {
+
+        final int x;
+        final int y;
+
+        Point () {
+            x = 10;
+            y = 10;
+        }
+
+        __ValueFactory static Point makePoint(int x, int y) {
+           Point p = __MakeDefault Point();
+           p.x = x;
+           p.y = y;
+           return p;
+        }
+
+        public static void main(String [] args) {
+            Point p = makePoint(10, 20);
+        }
+    }
+
+    public static void main(String[] args) {
+        new ValueCreationTest().run();
+    }
+
+    void run() {
+        String [] params = new String [] { "-v",
+                                            Paths.get(System.getProperty("test.classes"),
+                                                "ValueCreationTest$Point.class").toString() };
+        runCheck(params, new String [] {
+
+         "0: defaultvalue  #4                  // class ValueCreationTest$Point",
+         "3: astore_2",
+         "4: aload_2",
+         "5: iload_0",
+         "6: withfield     #2                  // Field x:I",
+         "9: astore_2",
+        "10: aload_2",
+        "11: iload_1",
+        "12: withfield     #3                  // Field y:I",
+        "15: astore_2",
+        "16: aload_2",
+        "17: areturn"
+           
+         });
+
+     }
+
+     void runCheck(String [] params, String [] expectedOut) {
+        StringWriter s;
+        String out;
+
+        try (PrintWriter pw = new PrintWriter(s = new StringWriter())) {
+            com.sun.tools.javap.Main.run(params, pw);
+            out = s.toString();
+        }
+        int errors = 0;
+        for (String eo: expectedOut) {
+            if (!out.contains(eo)) {
+                System.err.println("Match not found for string: " + eo);
+                errors++;
+            }
+        }
+         if (errors > 0) {
+             throw new AssertionError("Unexpected javap output: " + out);
+         }
+    }
+}