[PATCH] 8147527: Non-optimal code generated for postfix unary operators

bsrbnd bsrbnd at gmail.com
Sat Nov 12 16:58:08 UTC 2016


Hi,

2016-11-03 14:45 GMT+01:00 Jan Lahoda <jan.lahoda at oracle.com>:
> Hi Bernard,
>
> Thanks for looking at this. For the avoidance of the modification of
> tree.selected in Lower.visitSelect, what I meant was more that we would
> create a new instance of JCFieldAccess, to carry the new select. Might be
> easier that trying to work with the existing select.
>
> I think it might be useful to have a set of tests covering the usecases, so
> that we can more easily test patches (we will need tests eventually anyway).
> I can look at that, unless you want to.
>
Next is a test (derived from issue 8143388 test, too) for the
optimization of "super" and "this$n".
In this case, the test() method has to be examined instruction by
instruction as explained in comments within the test.

Bernard

diff --git a/test/tools/javac/boxing/BoxedPostOpOpti2.java
b/test/tools/javac/boxing/BoxedPostOpOpti2.java
new file mode 100644
--- /dev/null
+++ b/test/tools/javac/boxing/BoxedPostOpOpti2.java
@@ -0,0 +1,114 @@
+/*
+ * @test
+ * @bug 8147527
+ * @summary "super" and "this$n" code optimization for boxed unary
post-operations.
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
+ *          jdk.jdeps/com.sun.tools.classfile
+ * @build toolbox.ToolBox toolbox.JavacTask
+ * @run main BoxedPostOpOpti2
+ */
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+
+import toolbox.JavacTask;
+import toolbox.ToolBox;
+
+import com.sun.tools.classfile.*;
+
+public class BoxedPostOpOpti2 {
+    public static void main(String... args) throws Exception {
+        new BoxedPostOpOpti2().run();
+    }
+
+    void run() throws Exception {
+        ToolBox tb = new ToolBox();
+
+        Path expected = Paths.get("expected");
+        Files.createDirectories(expected);
+        tb.cleanDirectory(expected);
+        new JavacTask(tb).sources(
+                "package p1;" +
+                "public class P {" +
+                "    protected Integer j=20;" +
+                "}",
+                "package p2;" +
+                "class C extends p1.P {" +
+                "    private Integer test() {" +
+                "        return j++;" +
+                "    }" +
+                "    class Inner {" +
+                "        private Integer test() {" +
+                "            return j++;" +
+                "        }" +
+                "    }" +
+                "}"
+            ).outdir(expected).run();
+
+        Path actual = Paths.get("actual");
+        Files.createDirectories(actual);
+        tb.cleanDirectory(actual);
+        new JavacTask(tb).sources(
+                "package p1;" +
+                "public class P {" +
+                "    protected Integer j=20;" +
+                "}",
+                "package p2;" +
+                "class C extends p1.P {" +
+                "    private Integer test() {" +
+                "        return super.j++;" +
+                "    }" +
+                "    class Inner {" +
+                "        private Integer test() {" +
+                "            return C.super.j++;" +
+                "        }" +
+                "    }" +
+                "}"
+            ).outdir(actual).run();
+
+        String error = "", sep = "";
+        for (Path p1: tb.findFiles(".class", expected)) {
+            for (Path p2: tb.findFiles(p1.getFileName().toString(), actual)) {
+                ClassFile c1 = ClassFile.read(p1);
+                ClassFile c2 = ClassFile.read(p2);
+                Method m1 = test(c1), m2 = test(c2);
+
+                if (m1 != null && m2 != null) {
+                    Code_attribute code1 =
(Code_attribute)m1.attributes.get(Attribute.Code);
+                    Code_attribute code2 =
(Code_attribute)m2.attributes.get(Attribute.Code);
+
+                    Iterator<Instruction> it1 =
code1.getInstructions().iterator();
+                    Iterator<Instruction> it2 =
code2.getInstructions().iterator();
+                    Instruction i1 = it1.next(), i2 = it2.next();
+                    boolean same = true;
+                    for (; it1.hasNext() && it2.hasNext();
i1=it1.next(), i2=it2.next()) {
+                        // Checks only matching of instruction's opcode since:
+                        // - accessor's name might be different
depending on "qualified super" selection.
+                        // - accessed field might be different
depending on "super" selection.
+                        same &= i1.getOpcode().opcode == i2.getOpcode().opcode;
+                    }
+                    same &= !it1.hasNext() && !it2.hasNext();
+                    if (!same) {
+                        error += sep + p1 + " differs from " + p2;
+                        sep = ", ";
+                    }
+                }
+            }
+        }
+        if (error.length() > 0) throw new Error(error);
+    }
+
+    Method test(ClassFile c) throws ConstantPoolException {
+        for (Method m: c.methods) {
+            if (m.getName(c.constant_pool).equals("test"))
+                return m;
+        }
+        return null;
+    }
+}


More information about the compiler-dev mailing list