nashorn/src/jdk/nashorn/internal/codegen/SplitMethodEmitter.java
changeset 24751 ccbd9cd3f720
parent 19095 0b215bda525d
child 24778 2ff5d7041566
--- 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;
+    }
 }