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

bsrbnd bsrbnd at gmail.com
Thu Nov 3 12:28:13 UTC 2016


Here is a short summary of this issue.

1) The problem related to issue 8143388 changeset (which is probably a
new issue) discovered here:
http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010452.html

is solved by the fix proposed here:
http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010487.html

2) The optimization expected in issue 8147527 is obtained with the
following patch:
http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010448.html

3) I've added two additional checks (for the optimization) that verify
if this$n:
a) is synthetic
b) matches the exact regex "this\$\d+" (instead of startsWith("this$")).

The following example (derived from issue 8147527 with some additional
cases) shows the result of the optimization:

class Issue8147527 extends p.P {
    public static void main(String[] args) {
        Issue8147527 self = new Issue8147527();
        self.testAll();
    }

    private void testAll() {
        System.out.println(test());
        System.out.println(i);

        Inner in = new Inner();
        System.out.println(in.test());
        System.out.println(i);

        System.out.println(testParent());
        System.out.println(super.j);

        System.out.println(in.testParent());
        System.out.println(super.j);
    }

    Integer i=0;
    private Integer test() {
        i++;
        return this.i++;
    }
    private Integer testParent() {
        j++;
        return super.j++;
    }

    class Inner {
        private Integer test() {
            i++;
            return Issue8147527.this.i++;
        }
        private Integer testParent() {
            j++;
            return Issue8147527.super.j++;
        }
    }
}

package p;

public class P {
    protected Integer j=20;
}

The desugared code looks like this (as expected in issue 8147527):

class Issue8147527$Inner {

    private Integer test() {
        (let /*synthetic*/ final Integer $647942 = this$0.i in (let
/*synthetic*/ final Integer $29472086 = this$0.i =
Integer.valueOf((int)(this$0.i.intValue() + 1)) in $647942));
        return (let /*synthetic*/ final Integer $8278885 =
(Integer)this$0.i in (let /*synthetic*/ final Integer $16578475 =
this$0.i = Integer.valueOf((int)(this$0.i.intValue() + 1)) in
$8278885));
    }

    private Integer testParent() {
        (let /*synthetic*/ final Integer $798605 =
Issue8147527.access$200(this$0) in (let /*synthetic*/ final Integer
$5995540 = Issue8147527.access$302(this$0,
Integer.valueOf((int)(Issue8147527.access$400(this$0).intValue() +
1))) in $798605));
        return (let /*synthetic*/ final Integer $33017129 =
(Integer)Issue8147527.access$501(this$0) in (let /*synthetic*/ final
Integer $25625839 = Issue8147527.access$603(this$0,
Integer.valueOf((int)(Issue8147527.access$701(this$0).intValue() +
1))) in $33017129));
    }
}

class Issue8147527 extends p.P {

    private Integer test() {
        (let /*synthetic*/ final Integer $21617 = i in (let
/*synthetic*/ final Integer $20066205 = i =
Integer.valueOf((int)(i.intValue() + 1)) in $21617));
        return (let /*synthetic*/ final Integer $32619253 =
(Integer)this.i in (let /*synthetic*/ final Integer $27442939 = this.i
= Integer.valueOf((int)(this.i.intValue() + 1)) in $32619253));
    }

    private Integer testParent() {
        (let /*synthetic*/ final Integer $4208220 = j in (let
/*synthetic*/ final Integer $32359562 = j =
Integer.valueOf((int)(j.intValue() + 1)) in $4208220));
        return (let /*synthetic*/ final Integer $20049680 =
(Integer)super.j in (let /*synthetic*/ final Integer $28368043 =
super.j = Integer.valueOf((int)(super.j.intValue() + 1)) in
$20049680));
    }
}

Putting all (1, 2 and 3) together gives the patch below.

Bernard

diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
@@ -926,7 +926,7 @@
         ClassSymbol accOwner = refSuper && protAccess
             // For access via qualified super (T.super.x), place the
             // access symbol on T.
-            ? (ClassSymbol)((JCFieldAccess) tree).selected.type.tsym
+            ? (ClassSymbol)((JCFieldAccess)((JCFieldAccess)
tree).selected).selected.type.tsym
             // Otherwise pretend that the owner of an accessed
             // protected symbol is the enclosing class of the current
             // class which is a subclass of the symbol's owner.
@@ -1100,6 +1100,7 @@
             tree = make.at(tree.pos).Ident(sym);
         }
         JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess)
tree).selected : null;
+        base = refSuper ? translate(base) : base;
         switch (sym.kind) {
         case TYP:
             if (sym.owner.kind != PCK) {
@@ -2209,16 +2210,20 @@
      */
     JCExpression abstractRval(JCExpression rval, Type type,
TreeBuilder builder) {
         rval = TreeInfo.skipParens(rval);
+        boolean synthetic = false;
         switch (rval.getTag()) {
         case LITERAL:
             return builder.build(rval);
         case IDENT:
             JCIdent id = (JCIdent) rval;
+            synthetic = (id.sym.flags() & SYNTHETIC) != 0;
             if ((id.sym.flags() & FINAL) != 0 && id.sym.owner.kind == MTH)
                 return builder.build(rval);
         }
         Name name = TreeInfo.name(rval);
-        if (name == names._super)
+        String thisDollarN = names._this + "\\" +
target.syntheticNameChar() + "\\d+";
+        boolean matchesThisDollar = synthetic && name != null &&
name.toString().matches(thisDollarN);
+        if (name == names._super || name == names._this || matchesThisDollar)
             return builder.build(rval);
         VarSymbol var =
             new VarSymbol(FINAL|SYNTHETIC,
@@ -3837,7 +3842,7 @@
             tree.selected.hasTag(SELECT) &&
             TreeInfo.name(tree.selected) == names._super &&
             !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym,
currentClass);
-        tree.selected = translate(tree.selected);
+        if (!qualifiedSuperAccess) tree.selected = translate(tree.selected);
         if (tree.name == names._class) {
             result = classOf(tree.selected);
         }


More information about the compiler-dev mailing list