8192885: Compiler in JDK 10-ea+33 misses to include entry in LineNumberTable for goto instruction of foreach loop jdk-10+35
authorvromero
Wed, 06 Dec 2017 13:36:34 -0500
changeset 48082 d8c634b016c6
parent 48081 89829dd3cc54
child 48084 1826a0130c59
child 48210 0310d6fe7a88
8192885: Compiler in JDK 10-ea+33 misses to include entry in LineNumberTable for goto instruction of foreach loop Reviewed-by: mcimadamore
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
test/langtools/tools/javac/T8192885/AddGotoAfterForLoopToLNTTest.java
test/langtools/tools/javac/flow/tests/TestCaseForEach.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Fri Nov 03 10:01:08 2017 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Wed Dec 06 13:36:34 2017 -0500
@@ -3236,12 +3236,10 @@
                                                     make.Ident(index)).setType(elemtype);
             JCVariableDecl loopvardef = (JCVariableDecl)make.VarDef(tree.var.mods,
                                                   tree.var.name,
-                                                  tree.var.vartype, null).setType(tree.var.type);
+                                                  tree.var.vartype, loopvarinit).setType(tree.var.type);
             loopvardef.sym = tree.var.sym;
 
-            JCStatement loopVarAssign = make.Assignment(tree.var.sym, loopvarinit);
-            JCBlock body = make.
-                Block(0, List.of(loopVarAssign, tree.body));
+            JCBlock body = make.Block(0, List.of(loopvardef, tree.body));
 
             arraycachedef = translate(arraycachedef);
             result = translate(make.
@@ -3251,12 +3249,7 @@
                                        body));
             patchTargets(body, tree, result);
             JCStatement nullAssignToArr = make.Assignment(arraycache, make.Literal(BOT, null).setType(syms.botType));
-            JCStatement nullAssignToLoopVar = tree.var.type.isPrimitive() ?
-                    null :
-                    make.Assignment(tree.var.sym, make.Literal(BOT, null).setType(syms.botType));
-            result = nullAssignToLoopVar == null ?
-                    make.Block(0, List.of(arraycachedef, loopvardef, (JCStatement)result, nullAssignToArr)):
-                    make.Block(0, List.of(arraycachedef, loopvardef, (JCStatement)result, nullAssignToArr, nullAssignToLoopVar));
+            result = make.Block(0, List.of(arraycachedef, (JCStatement)result, nullAssignToArr));
         }
         /** Patch up break and continue targets. */
         private void patchTargets(JCTree body, final JCTree src, final JCTree dest) {
@@ -3310,7 +3303,7 @@
                                             types.erasure(types.asSuper(iterator.type.getReturnType(), syms.iteratorType.tsym)),
                                             currentMethodSym);
 
-             JCStatement init = make.
+            JCStatement init = make.
                 VarDef(itvar, make.App(make.Select(tree.expr, iterator)
                      .setType(types.erasure(iterator.type))));
 
@@ -3331,10 +3324,9 @@
             JCVariableDecl indexDef = (JCVariableDecl)make.VarDef(tree.var.mods,
                                                   tree.var.name,
                                                   tree.var.vartype,
-                                                  null).setType(tree.var.type);
+                                                  vardefinit).setType(tree.var.type);
             indexDef.sym = tree.var.sym;
-            JCStatement loopVarAssign = make.Assignment(tree.var.sym, vardefinit);
-            JCBlock body = make.Block(0, List.of(loopVarAssign, tree.body));
+            JCBlock body = make.Block(0, List.of(indexDef, tree.body));
             body.endpos = TreeInfo.endPos(tree.body);
             init = translate(init);
             result = translate(make.
@@ -3344,12 +3336,7 @@
                         body));
             patchTargets(body, tree, result);
             JCStatement nullAssignToIterator = make.Assignment(itvar, make.Literal(BOT, null).setType(syms.botType));
-            JCStatement nullAssignToLoopVar = tree.var.type.isPrimitive() ?
-                    null :
-                    make.Assignment(tree.var.sym, make.Literal(BOT, null).setType(syms.botType));
-            result = nullAssignToLoopVar == null ?
-                    make.Block(0, List.of(init, indexDef, (JCStatement)result, nullAssignToIterator)):
-                    make.Block(0, List.of(init, indexDef, (JCStatement)result, nullAssignToIterator, nullAssignToLoopVar));
+            result = make.Block(0, List.of(init, (JCStatement)result, nullAssignToIterator));
         }
 
     public void visitVarDef(JCVariableDecl tree) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/T8192885/AddGotoAfterForLoopToLNTTest.java	Wed Dec 06 13:36:34 2017 -0500
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017, 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 8192885
+ * @summary Compiler in JDK 10-ea+33 misses to include entry in LineNumberTable for goto instruction of foreach loop
+ * @library /tools/lib
+ * @modules jdk.jdeps/com.sun.tools.classfile
+ *          jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.compiler/com.sun.tools.javac.util
+ *          jdk.jdeps/com.sun.tools.javap
+ * @build toolbox.ToolBox toolbox.JavacTask
+ * @run main AddGotoAfterForLoopToLNTTest
+ */
+
+import java.io.File;
+import java.nio.file.Paths;
+
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.Code_attribute;
+import com.sun.tools.classfile.LineNumberTable_attribute;
+import com.sun.tools.classfile.Method;
+import com.sun.tools.javac.util.Assert;
+
+import toolbox.JavacTask;
+import toolbox.ToolBox;
+
+public class AddGotoAfterForLoopToLNTTest {
+
+    static final String testSource =
+    /* 01 */        "class GotoAtEnhancedForTest {\n" +
+    /* 02 */        "    void lookForThisMethod() {\n" +
+    /* 03 */        "        for (Object o : java.util.Collections.emptyList()) {\n" +
+    /* 04 */        "        }\n" +
+    /* 05 */        "    }\n" +
+    /* 06 */        "}";
+
+    static final int[][] expectedLNT = {
+    //  {line-number, start-pc},
+        {3,           0},
+        {4,           25},
+        {3,           28},
+        {5,           30},
+    };
+
+    static final String methodToLookFor = "lookForThisMethod";
+
+    public static void main(String[] args) throws Exception {
+        new AddGotoAfterForLoopToLNTTest().run();
+    }
+
+    ToolBox tb = new ToolBox();
+
+    void run() throws Exception {
+        compileTestClass();
+        checkClassFile(new File(Paths.get(System.getProperty("user.dir"),
+                "GotoAtEnhancedForTest.class").toUri()), methodToLookFor);
+    }
+
+    void compileTestClass() throws Exception {
+        new JavacTask(tb)
+                .sources(testSource)
+                .run();
+    }
+
+    void checkClassFile(final File cfile, String methodToFind) throws Exception {
+        ClassFile classFile = ClassFile.read(cfile);
+        boolean methodFound = false;
+        for (Method method : classFile.methods) {
+            if (method.getName(classFile.constant_pool).equals(methodToFind)) {
+                methodFound = true;
+                Code_attribute code = (Code_attribute) method.attributes.get("Code");
+                LineNumberTable_attribute lnt =
+                        (LineNumberTable_attribute) code.attributes.get("LineNumberTable");
+                Assert.check(lnt.line_number_table_length == expectedLNT.length,
+                        "The LineNumberTable found has a length different to the expected one");
+                int i = 0;
+                for (LineNumberTable_attribute.Entry entry: lnt.line_number_table) {
+                    Assert.check(entry.line_number == expectedLNT[i][0] &&
+                            entry.start_pc == expectedLNT[i][1],
+                            "LNT entry at pos " + i + " differ from expected." +
+                            "Found " + entry.line_number + ":" + entry.start_pc +
+                            ". Expected " + expectedLNT[i][0] + ":" + expectedLNT[i][1]);
+                    i++;
+                }
+            }
+        }
+        Assert.check(methodFound, "The seek method was not found");
+    }
+
+    void error(String msg) {
+        throw new AssertionError(msg);
+    }
+}
--- a/test/langtools/tools/javac/flow/tests/TestCaseForEach.java	Fri Nov 03 10:01:08 2017 -0700
+++ b/test/langtools/tools/javac/flow/tests/TestCaseForEach.java	Wed Dec 06 13:36:34 2017 -0500
@@ -3,7 +3,7 @@
 public class TestCaseForEach {
 
     @AliveRange(varName="o", bytecodeStart=25, bytecodeLength=11)
-    @AliveRange(varName="o", bytecodeStart=44, bytecodeLength=1)
+    @AliveRange(varName="o", bytecodeStart=41, bytecodeLength=1)
     void m(String[] args) {
         Object o;
         for (String s : args) {