Bug 1332881 - Handle stack value in correct order when leaving loop and try-finally. r=shu
authorTooru Fujisawa <arai_a@mac.com>
Thu, 26 Jan 2017 08:37:24 +0900
changeset 466655 ad0c4806133ae96c62f4ecc47229d19887934b70
parent 466654 8bf2d6dea785389f334bb368483cdb2644470c83
child 466656 6057588e27441ec4ce22e05b5a9f7eee7774995b
push id42948
push userbmo:gasolin@mozilla.com
push dateThu, 26 Jan 2017 07:49:21 +0000
reviewersshu
bugs1332881
milestone54.0a1
Bug 1332881 - Handle stack value in correct order when leaving loop and try-finally. r=shu
js/src/frontend/BytecodeEmitter.cpp
js/src/tests/ecma_6/Statements/for-inof-finally.js
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -2360,16 +2360,19 @@ NonLocalExitControl::prepareForNonLocalJ
                     return false;
                 if (!bce_->emitJump(JSOP_GOSUB, &finallyControl.gosubs))
                     return false;
             }
             break;
           }
 
           case StatementKind::ForOfLoop:
+            if (!flushPops(bce_))
+                return false;
+
             // The iterator and the current value are on the stack.
             //
             if (emitIteratorClose) {
                 hasForOfLoopsWithIteratorClose = true;
                 if (!control->as<ForOfLoopControl>().finishIterCloseTryNote(bce_))
                     return false;
                 if (!bce_->emit1(JSOP_POP))               // ... ITER
                     return false;
@@ -2379,16 +2382,19 @@ NonLocalExitControl::prepareForNonLocalJ
                 if (!bce_->emit1(JSOP_POP))               // ... ITER
                     return false;
                 if (!bce_->emit1(JSOP_POP))               // ...
                     return false;
             }
             break;
 
           case StatementKind::ForInLoop:
+            if (!flushPops(bce_))
+                return false;
+
             // The iterator and the current value are on the stack.
             if (!bce_->emit1(JSOP_POP))                   // ... ITER
                 return false;
             if (!bce_->emit1(JSOP_ENDITER))               // ...
                 return false;
             break;
 
           default:
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Statements/for-inof-finally.js
@@ -0,0 +1,54 @@
+var BUGNUMBER = 1332881;
+var summary =
+  "Leaving for-in and try should handle stack value in correct order";
+
+print(BUGNUMBER + ": " + summary);
+
+var a = (function () {
+    for (var x in [0]) {
+        try {} finally {
+            return 11;
+        }
+    }
+})();
+assertEq(a, 11);
+
+var b = (function () {
+    for (var x of [0]) {
+        try {} finally {
+            return 12;
+        }
+    }
+})();
+assertEq(b, 12);
+
+var c = (function () {
+    for (var x in [0]) {
+        for (var y of [0]) {
+            try {} finally {
+                return 13;
+            }
+        }
+    }
+})();
+assertEq(c, 13);
+
+var d = (function () {
+    for (var x in [0]) {
+        for (var y of [0]) {
+            try {} finally {
+                for (var z in [0]) {
+                    for (var w of [0]) {
+                        try {} finally {
+                            return 14;
+                        }
+                    }
+                }
+            }
+        }
+    }
+})();
+assertEq(d, 14);
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);