From 8c50b3e660b97bd395f8de86cc2cfa88ed1266f0 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Wed, 6 Dec 2017 13:36:34 -0500 Subject: [PATCH] 8192885: Compiler in JDK 10-ea+33 misses to include entry in LineNumberTable for goto instruction of foreach loop Reviewed-by: mcimadamore --- .../com/sun/tools/javac/comp/Lower.java | 27 ++-- .../AddGotoAfterForLoopToLNTTest.java | 116 ++++++++++++++++++ .../javac/flow/tests/TestCaseForEach.java | 2 +- 3 files changed, 124 insertions(+), 21 deletions(-) create mode 100644 test/langtools/tools/javac/T8192885/AddGotoAfterForLoopToLNTTest.java 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 index f95f6640506..fe9f0945797 100644 --- 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 @@ -3236,12 +3236,10 @@ public class Lower extends TreeTranslator { 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 @@ public class Lower extends TreeTranslator { 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 @@ public class Lower extends TreeTranslator { 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 @@ public class Lower extends TreeTranslator { 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 @@ public class Lower extends TreeTranslator { 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) { diff --git a/test/langtools/tools/javac/T8192885/AddGotoAfterForLoopToLNTTest.java b/test/langtools/tools/javac/T8192885/AddGotoAfterForLoopToLNTTest.java new file mode 100644 index 00000000000..5d5df2c4ff4 --- /dev/null +++ b/test/langtools/tools/javac/T8192885/AddGotoAfterForLoopToLNTTest.java @@ -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); + } +} diff --git a/test/langtools/tools/javac/flow/tests/TestCaseForEach.java b/test/langtools/tools/javac/flow/tests/TestCaseForEach.java index e97070bc0fb..978ae3fbb7e 100644 --- a/test/langtools/tools/javac/flow/tests/TestCaseForEach.java +++ b/test/langtools/tools/javac/flow/tests/TestCaseForEach.java @@ -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) {