--- a/nashorn/src/jdk/nashorn/internal/codegen/SplitMethodEmitter.java Mon May 05 14:17:20 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/SplitMethodEmitter.java Tue May 13 11:30:40 2014 +0200
@@ -25,13 +25,13 @@
package jdk.nashorn.internal.codegen;
+import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
+
import java.util.ArrayList;
import java.util.List;
-
-import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
-
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.BreakableNode;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.SplitNode;
import jdk.nashorn.internal.runtime.Scope;
@@ -47,6 +47,13 @@
private final SplitNode splitNode;
private final List<Label> externalTargets = new ArrayList<>();
+ /**
+ * In addition to external target labels, we need to track the target breakables too as the code generator needs to
+ * be able to correctly pop the scopes to the target, see {@link CodeGenerator#leaveSplitNode(SplitNode)}. Note that
+ * this is only used within CodeGenerator, which doesn't mutate the AST, so keeping pointers to other nodes is not
+ * incorrect.
+ */
+ private final List<BreakableNode> externalTargetNodes = new ArrayList<>();
SplitMethodEmitter(final ClassEmitter classEmitter, final MethodVisitor mv, SplitNode splitNode) {
super(classEmitter, mv);
@@ -54,9 +61,9 @@
}
@Override
- void splitAwareGoto(final LexicalContext lc, final Label label) {
+ void splitAwareGoto(final LexicalContext lc, final Label label, final BreakableNode targetNode) {
assert splitNode != null;
- final int index = findExternalTarget(lc, label);
+ final int index = findExternalTarget(lc, label, targetNode);
if (index >= 0) {
loadCompilerConstant(SCOPE);
checkcast(Scope.class);
@@ -66,18 +73,19 @@
_return(functionNode.getReturnType());
return;
}
- super.splitAwareGoto(lc, label);
+ super.splitAwareGoto(lc, label, targetNode);
}
- private int findExternalTarget(final LexicalContext lc, final Label label) {
+ private int findExternalTarget(final LexicalContext lc, final Label label, final BreakableNode targetNode) {
final int index = externalTargets.indexOf(label);
if (index >= 0) {
return index;
}
- if (lc.isExternalTarget(splitNode, label)) {
+ if (lc.isExternalTarget(splitNode, targetNode)) {
externalTargets.add(label);
+ externalTargetNodes.add(targetNode);
return externalTargets.size() - 1;
}
return -1;
@@ -93,8 +101,11 @@
return this;
}
- @Override
final List<Label> getExternalTargets() {
return externalTargets;
}
+
+ final List<BreakableNode> getExternalTargetNodes() {
+ return externalTargetNodes;
+ }
}