8013919: Original exception no longer thrown away when a finally rethrows

Reviewed-by: jlaskey, sundar
This commit is contained in:
Marcus Lagergren 2013-05-16 13:44:25 +02:00
parent 6e91576480
commit aeda283b75
4 changed files with 87 additions and 24 deletions

View File

@ -261,8 +261,14 @@ final class Lower extends NodeOperatorVisitor {
return throwNode; return throwNode;
} }
private static Node ensureUniqueLabelsIn(final Node node) { private static Node ensureUniqueNamesIn(final LexicalContext lc, final Node node) {
return node.accept(new NodeVisitor() { return node.accept(new NodeVisitor() {
@Override
public Node leaveFunctionNode(final FunctionNode functionNode) {
final String name = functionNode.getName();
return functionNode.setName(getLexicalContext(), lc.getCurrentFunction().uniqueName(name));
}
@Override @Override
public Node leaveDefault(final Node labelledNode) { public Node leaveDefault(final Node labelledNode) {
return labelledNode.ensureUniqueLabels(getLexicalContext()); return labelledNode.ensureUniqueLabels(getLexicalContext());
@ -270,10 +276,10 @@ final class Lower extends NodeOperatorVisitor {
}); });
} }
private static List<Statement> copyFinally(final Block finallyBody) { private static List<Statement> copyFinally(final LexicalContext lc, final Block finallyBody) {
final List<Statement> newStatements = new ArrayList<>(); final List<Statement> newStatements = new ArrayList<>();
for (final Statement statement : finallyBody.getStatements()) { for (final Statement statement : finallyBody.getStatements()) {
newStatements.add((Statement)ensureUniqueLabelsIn(statement)); newStatements.add((Statement)ensureUniqueNamesIn(lc, statement));
if (statement.hasTerminalFlags()) { if (statement.hasTerminalFlags()) {
return newStatements; return newStatements;
} }
@ -316,9 +322,9 @@ final class Lower extends NodeOperatorVisitor {
* @return new try node after splicing finally code (same if nop) * @return new try node after splicing finally code (same if nop)
*/ */
private Node spliceFinally(final TryNode tryNode, final List<ThrowNode> rethrows, final Block finallyBody) { private Node spliceFinally(final TryNode tryNode, final List<ThrowNode> rethrows, final Block finallyBody) {
final int finish = tryNode.getFinish();
assert tryNode.getFinallyBody() == null; assert tryNode.getFinallyBody() == null;
final int finish = tryNode.getFinish();
final LexicalContext lc = getLexicalContext();
final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor() { final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor() {
final List<Node> insideTry = new ArrayList<>(); final List<Node> insideTry = new ArrayList<>();
@ -338,7 +344,7 @@ final class Lower extends NodeOperatorVisitor {
@Override @Override
public Node leaveThrowNode(final ThrowNode throwNode) { public Node leaveThrowNode(final ThrowNode throwNode) {
if (rethrows.contains(throwNode)) { if (rethrows.contains(throwNode)) {
final List<Statement> newStatements = copyFinally(finallyBody); final List<Statement> newStatements = copyFinally(lc, finallyBody);
if (!isTerminal(newStatements)) { if (!isTerminal(newStatements)) {
newStatements.add(throwNode); newStatements.add(throwNode);
} }
@ -372,7 +378,7 @@ final class Lower extends NodeOperatorVisitor {
resultNode = null; resultNode = null;
} }
newStatements.addAll(copyFinally(finallyBody)); newStatements.addAll(copyFinally(lc, finallyBody));
if (!isTerminal(newStatements)) { if (!isTerminal(newStatements)) {
newStatements.add(expr == null ? returnNode : returnNode.setExpression(resultNode)); newStatements.add(expr == null ? returnNode : returnNode.setExpression(resultNode));
} }
@ -382,7 +388,7 @@ final class Lower extends NodeOperatorVisitor {
private Node copy(final Statement endpoint, final Node targetNode) { private Node copy(final Statement endpoint, final Node targetNode) {
if (!insideTry.contains(targetNode)) { if (!insideTry.contains(targetNode)) {
final List<Statement> newStatements = copyFinally(finallyBody); final List<Statement> newStatements = copyFinally(lc, finallyBody);
if (!isTerminal(newStatements)) { if (!isTerminal(newStatements)) {
newStatements.add(endpoint); newStatements.add(endpoint);
} }
@ -548,7 +554,7 @@ final class Lower extends NodeOperatorVisitor {
final FunctionNode currentFunction = getLexicalContext().getCurrentFunction(); final FunctionNode currentFunction = getLexicalContext().getCurrentFunction();
return callNode.setEvalArgs( return callNode.setEvalArgs(
new CallNode.EvalArgs( new CallNode.EvalArgs(
ensureUniqueLabelsIn(args.get(0)).accept(this), ensureUniqueNamesIn(getLexicalContext(), args.get(0)).accept(this),
compilerConstant(THIS), compilerConstant(THIS),
evalLocation(callee), evalLocation(callee),
currentFunction.isStrict())); currentFunction.isStrict()));

View File

@ -250,6 +250,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
final FunctionNode functionNode, final FunctionNode functionNode,
final long lastToken, final long lastToken,
final int flags, final int flags,
final String name,
final Type returnType, final Type returnType,
final CompileUnit compileUnit, final CompileUnit compileUnit,
final EnumSet<CompilationState> compilationState, final EnumSet<CompilationState> compilationState,
@ -260,6 +261,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
super(functionNode); super(functionNode);
this.flags = flags; this.flags = flags;
this.name = name;
this.returnType = returnType; this.returnType = returnType;
this.compileUnit = compileUnit; this.compileUnit = compileUnit;
this.lastToken = lastToken; this.lastToken = lastToken;
@ -271,7 +273,6 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
// the fields below never change - they are final and assigned in constructor // the fields below never change - they are final and assigned in constructor
this.source = functionNode.source; this.source = functionNode.source;
this.name = functionNode.name;
this.ident = functionNode.ident; this.ident = functionNode.ident;
this.namespace = functionNode.namespace; this.namespace = functionNode.namespace;
this.declaredSymbols = functionNode.declaredSymbols; this.declaredSymbols = functionNode.declaredSymbols;
@ -315,7 +316,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
if (this.snapshot == null) { if (this.snapshot == null) {
return this; return this;
} }
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, null, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, null, hints));
} }
/** /**
@ -331,7 +332,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
if (isProgram() || parameters.isEmpty()) { if (isProgram() || parameters.isEmpty()) {
return this; //never specialize anything that won't be recompiled return this; //never specialize anything that won't be recompiled
} }
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, this, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, this, hints));
} }
/** /**
@ -389,7 +390,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
} }
final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState); final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
newState.add(state); newState.add(state);
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, newState, body, parameters, snapshot, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, newState, body, parameters, snapshot, hints));
} }
/** /**
@ -410,7 +411,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
if (this.hints == hints) { if (this.hints == hints) {
return this; return this;
} }
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
} }
/** /**
@ -463,7 +464,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
if (this.flags == flags) { if (this.flags == flags) {
return this; return this;
} }
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
} }
@Override @Override
@ -529,7 +530,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
} }
/** /**
* Get the identifier for this function * Get the identifier for this function, this is its symbol.
* @return the identifier as an IdentityNode * @return the identifier as an IdentityNode
*/ */
public IdentNode getIdent() { public IdentNode getIdent() {
@ -572,7 +573,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
if(this.body == body) { if(this.body == body) {
return this; return this;
} }
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
} }
/** /**
@ -640,7 +641,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
if (this.lastToken == lastToken) { if (this.lastToken == lastToken) {
return this; return this;
} }
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
} }
/** /**
@ -651,6 +652,20 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
return name; return name;
} }
/**
* Set the internal name for this function
* @param lc lexical context
* @param name new name
* @return new function node if changed, otherwise the same
*/
public FunctionNode setName(final LexicalContext lc, final String name) {
if (this.name.equals(name)) {
return this;
}
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
}
/** /**
* Check if this function should have all its variables in its own scope. Scripts, split sub-functions, and * Check if this function should have all its variables in its own scope. Scripts, split sub-functions, and
* functions having with and/or eval blocks are such. * functions having with and/or eval blocks are such.
@ -698,7 +713,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
if (this.parameters == parameters) { if (this.parameters == parameters) {
return this; return this;
} }
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
} }
/** /**
@ -762,6 +777,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
this, this,
lastToken, lastToken,
flags, flags,
name,
Type.widest(this.returnType, returnType.isObject() ? Type.widest(this.returnType, returnType.isObject() ?
Type.OBJECT : Type.OBJECT :
returnType), returnType),
@ -801,7 +817,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
if (this.compileUnit == compileUnit) { if (this.compileUnit == compileUnit) {
return this; return this;
} }
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
} }
/** /**

View File

@ -0,0 +1,39 @@
/*
* 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-8013913: finally cloning of function node declarations caused
* method collissions
*
* @test
* @run
*/
try {
print("a");
} finally {
var b = function() {
print("b");
}
b();
}

View File

@ -0,0 +1,2 @@
a
b