Bug 1332881 - Handle stack value in correct order when leaving loop and try-finally. r=shu, a=lizzard
authorTooru Fujisawa <arai_a@mac.com>
Thu, 26 Jan 2017 08:37:24 +0900
changeset 378001 af6f4d39c3f061041425c840d021e8a2d70f12eb
parent 378000 c82f913134cba5626f4421372afa545a0c9d94a1
child 378002 13b5876f5d0ca6e12e65806530b230148c8cd54e
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu, lizzard
bugs1332881
milestone53.0a2
Bug 1332881 - Handle stack value in correct order when leaving loop and try-finally. r=shu, a=lizzard
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);