Mercurial > hg > jdk9-shenandoah > nashorn
changeset 410:ad6b18ee4666
8019809: return after break incorrectly sets the block as terminal
Reviewed-by: jlaskey, lagergren
author | attila |
---|---|
date | Thu, 04 Jul 2013 14:10:18 +0200 |
parents | 7b072ebdf5aa |
children | 8c4a6d9b8a23 |
files | src/jdk/nashorn/internal/codegen/Lower.java src/jdk/nashorn/internal/ir/BlockLexicalContext.java test/script/basic/JDK-8019809.js test/script/currently-failing/JDK-8019809.js |
diffstat | 4 files changed, 68 insertions(+), 49 deletions(-) [+] |
line wrap: on
line diff
--- a/src/jdk/nashorn/internal/codegen/Lower.java Wed Jul 03 13:41:18 2013 -0300 +++ b/src/jdk/nashorn/internal/codegen/Lower.java Thu Jul 04 14:10:18 2013 +0200 @@ -32,6 +32,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.ListIterator; import jdk.nashorn.internal.ir.BaseNode; import jdk.nashorn.internal.ir.BinaryNode; import jdk.nashorn.internal.ir.Block; @@ -115,6 +116,21 @@ } return newStatements; } + + @Override + protected Block afterSetStatements(final Block block) { + final List<Statement> stmts = block.getStatements(); + for(final ListIterator<Statement> li = stmts.listIterator(stmts.size()); li.hasPrevious();) { + final Statement stmt = li.previous(); + // popStatements() guarantees that the only thing after a terminal statement are uninitialized + // VarNodes. We skip past those, and set the terminal state of the block to the value of the + // terminal state of the first statement that is not an uninitialized VarNode. + if(!(stmt instanceof VarNode && ((VarNode)stmt).getInit() == null)) { + return block.setIsTerminal(this, stmt.isTerminal()); + } + } + return block.setIsTerminal(this, false); + } }); } @@ -132,11 +148,11 @@ //now we have committed the entire statement list to the block, but we need to truncate //whatever is after the last terminal. block append won't append past it - Statement last = lc.getLastStatement(); if (lc.isFunctionBody()) { final FunctionNode currentFunction = lc.getCurrentFunction(); final boolean isProgram = currentFunction.isProgram(); + final Statement last = lc.getLastStatement(); final ReturnNode returnNode = new ReturnNode( last == null ? block.getLineNumber() : last.getLineNumber(), //TODO? currentFunction.getToken(), @@ -145,11 +161,7 @@ compilerConstant(RETURN) : LiteralNode.newInstance(block, ScriptRuntime.UNDEFINED)); - last = (Statement)returnNode.accept(this); - } - - if (last != null && last.isTerminal()) { - return block.setIsTerminal(lc, true); + returnNode.accept(this); } return block;
--- a/src/jdk/nashorn/internal/ir/BlockLexicalContext.java Wed Jul 03 13:41:18 2013 -0300 +++ b/src/jdk/nashorn/internal/ir/BlockLexicalContext.java Thu Jul 04 14:10:18 2013 +0200 @@ -29,7 +29,6 @@ import java.util.ArrayList; import java.util.Deque; import java.util.List; -import java.util.ListIterator; /** * This is a subclass of lexical context used for filling @@ -63,6 +62,16 @@ return sstack.pop(); } + /** + * Override this method to perform some additional processing on the block after its statements have been set. By + * default does nothing and returns the original block. + * @param block the block to operate on + * @return a modified block. + */ + protected Block afterSetStatements(Block block) { + return block; + } + @SuppressWarnings("unchecked") @Override public <T extends LexicalContextNode> T pop(final T node) { @@ -70,6 +79,7 @@ if (node instanceof Block) { final List<Statement> newStatements = popStatements(); expected = (T)((Block)node).setStatements(this, newStatements); + expected = (T)afterSetStatements((Block)expected); if (!sstack.isEmpty()) { lastStatement = lastStatement(sstack.peek()); } @@ -107,10 +117,7 @@ } private static Statement lastStatement(final List<Statement> statements) { - for (final ListIterator<Statement> iter = statements.listIterator(statements.size()); iter.hasPrevious(); ) { - final Statement node = iter.previous(); - return node; - } - return null; + final int s = statements.size(); + return s == 0 ? null : statements.get(s - 1); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8019809.js Thu Jul 04 14:10:18 2013 +0200 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2010, 2013, 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. + */ + +/** + * JDK-8019809: Break return combo that generates erroneous bytecode + * + * @test + * @run + */ + +//Function("L: {break L;return; }"); + +function f() { + L: { break L; return; } +} + +f();
--- a/test/script/currently-failing/JDK-8019809.js Wed Jul 03 13:41:18 2013 -0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2010, 2013, 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. - */ - -/** - * JDK-8019809: Break return combo that generates erroneous bytecode - * - * @test - * @run - */ - -//Function("L: {break L;return; }"); - -function f() { - L: { break L; return; } -} - -f();