Title: [210011] branches/safari-603-branch

Diff

Modified: branches/safari-603-branch/JSTests/ChangeLog (210010 => 210011)


--- branches/safari-603-branch/JSTests/ChangeLog	2016-12-20 02:03:02 UTC (rev 210010)
+++ branches/safari-603-branch/JSTests/ChangeLog	2016-12-20 02:05:52 UTC (rev 210011)
@@ -1,3 +1,17 @@
+2016-12-19  Babak Shafiei  <[email protected]>
+
+        Merge r210010.
+
+    2016-12-19  Mark Lam  <[email protected]>
+
+            Rolling out r209974 and r209952. They break some websites in mysterious ways. Step 2: Rollout r209952.
+            https://bugs.webkit.org/show_bug.cgi?id=166049
+
+            Not reviewed.
+
+            * stress/deeply-nested-finallys.js: Removed.
+            * stress/test-finally.js: Removed.
+
 2016-12-16  Mark Lam  <[email protected]>
 
         De-duplicate finally blocks.

Deleted: branches/safari-603-branch/JSTests/stress/deeply-nested-finallys.js (210010 => 210011)


--- branches/safari-603-branch/JSTests/stress/deeply-nested-finallys.js	2016-12-20 02:03:02 UTC (rev 210010)
+++ branches/safari-603-branch/JSTests/stress/deeply-nested-finallys.js	2016-12-20 02:05:52 UTC (rev 210011)
@@ -1,78 +0,0 @@
-// This test should finish almost instantly.
-
-function exp() {
-    try {
-        try {
-            try {
-                try { 
-                    try {
-                        try {
-                            try {
-                                try {
-                                    try {
-                                        try {
-                                            try {
-                                                try {
-                                                    try { 
-                                                        try {
-                                                            try {
-                                                                try {
-                                                                    try {
-                                                                        try {
-                                                                            try {
-                                                                                try {
-                                                                                    try {
-                                                                                        try { 
-                                                                                            try {
-                                                                                                try {
-                                                                                                    try {
-                                                                                                        try {
-                                                                                                            try {
-                                                                                                                try {
-                                                                                                                    try {
-                                                                                                                        try {
-                                                                                                                            try { 
-                                                                                                                                try {
-                                                                                                                                    try {
-                                                                                                                                        try {
-                                                                                                                                            try {
-                                                                                                                                                try {
-                                                                                                                                                } finally {return 1;}
-                                                                                                                                            } finally { return 1; }
-                                                                                                                                        } finally {return 1;}
-                                                                                                                                    } finally { return 1; }
-                                                                                                                                } finally {return 1;}
-                                                                                                                            } finally {return 1;}
-                                                                                                                        } finally {return 1;}
-                                                                                                                    } finally {return 1;}    
-                                                                                                                } finally { return 1; }
-                                                                                                            } finally {return 1;}
-                                                                                                        } finally { return 1; }
-                                                                                                    } finally {return 1;}
-                                                                                                } finally { return 1; }
-                                                                                            } finally {return 1;}
-                                                                                        } finally {return 1;}
-                                                                                    } finally {return 1;}
-                                                                                } finally {return 1;}    
-                                                                            } finally { return 1; }
-                                                                        } finally {return 1;}
-                                                                    } finally { return 1; }
-                                                                } finally {return 1;}
-                                                            } finally { return 1; }
-                                                        } finally {return 1;}
-                                                    } finally {return 1;}
-                                                } finally {return 1;}
-                                            } finally {return 1;}    
-                                        } finally { return 1; }
-                                    } finally {return 1;}
-                                } finally { return 1; }
-                            } finally {return 1;}
-                        } finally { return 1; }
-                    } finally {return 1;}
-                } finally {return 1;}
-            } finally {return 1;}
-        } finally {return 1;}    
-    } finally { return 1; }
-}
-
-exp();

Deleted: branches/safari-603-branch/JSTests/stress/test-finally.js (210010 => 210011)


--- branches/safari-603-branch/JSTests/stress/test-finally.js	2016-12-20 02:03:02 UTC (rev 210010)
+++ branches/safari-603-branch/JSTests/stress/test-finally.js	2016-12-20 02:05:52 UTC (rev 210011)
@@ -1,1018 +0,0 @@
-// This test just creates functions which exercise various permutations of control flow
-// thru finally blocks. The test passes if it does not throw any exceptions or crash on
-// bytecode validation.
-
-if (this.window)
-    print = console.log;
-
-var steps;
-var returned;
-var thrown;
-var testLineNumber;
-
-let NothingReturned = "NothingReturned";
-let NothingThrown = "NothingThrown";
-
-function assertResults(expectedSteps, expectedReturned, expectedThrown) {
-    let stepsMismatch = (steps != expectedSteps);
-    let returnedMismatch = (returned != expectedReturned);
-    let thrownMismatch = (thrown != expectedThrown && !("" + thrown).startsWith("" + expectedThrown));
-
-    if (stepsMismatch || returnedMismatch || thrownMismatch) {
-        print("FAILED Test @ line " + testLineNumber + ":");
-        print("   Actual:   steps: " + steps + ", returned: " + returned + ", thrown: '" + thrown + "'");
-        print("   Expected: steps: " + expectedSteps + ", returned: " + expectedReturned + ", thrown: '" + expectedThrown + "'");
-    }
-    if (stepsMismatch)
-        throw "FAILED Test @ line " + testLineNumber + ": steps do not match: expected ='" + expectedSteps + "' actual='" + steps + "'";
-    if (returnedMismatch)
-        throw "FAILED Test @ line " + testLineNumber + ": returned value does not match: expected ='" + expectedReturned + "' actual='" + returned + "'";
-    if (thrownMismatch)
-        throw "FAILED Test @ line " + testLineNumber + ": thrown value does does not match: expected ='" + expectedThrown + "' actual='" + thrown + "'";
-}
-
-function resetResults() {
-    steps = [];
-    returned = NothingReturned;
-    thrown = NothingThrown;
-}
-
-function append(step) {
-    let next = steps.length;
-    steps[next] = step;
-}
-
-function test(func, expectedSteps, expectedReturned, expectedThrown) {
-    testLineNumber = new Error().stack.match(/global code@.+\.js:([0-9]+)/)[1];
-    resetResults();
-
-    try {
-        returned = func();
-    } catch (e) {
-        thrown = e;
-    }
-
-    assertResults(expectedSteps, expectedReturned, expectedThrown);
-}
-
-// Test CompletionType::Normal on an empty try blocks.
-test(() =>  {
-    try {
-        append("t2");
-        for (var i = 0; i < 2; i++) {
-            try {
-            } catch(a) {
-                append("c1");
-            } finally {
-                append("f1");
-            }
-        }
-    } catch(b) {
-        append("c2");
-    } finally {
-        append("f2");
-    }
-
-}, "t2,f1,f1,f2", undefined, NothingThrown);
-
-// Test CompletionType::Normal.
-test(() =>  {
-    try {
-        append("t2");
-        for (var i = 0; i < 2; i++) {
-            try {
-                append("t1");
-            } catch(a) {
-                append("c1");
-            } finally {
-                append("f1");
-            }
-        }
-    } catch(b) {
-        append("c2");
-    } finally {
-        append("f2");
-    }
-
-}, "t2,t1,f1,t1,f1,f2", undefined, NothingThrown);
-
-// Test CompletionType::Break.
-test(() =>  {
-    try {
-        append("t2");
-        for (var i = 0; i < 2; i++) {
-            try {
-                append("t1");
-                break;
-            } catch(a) {
-                append("c1");
-            } finally {
-                append("f1");
-            }
-        }
-    } catch(b) {
-        append("c2");
-    } finally {
-        append("f2");
-    }
-
-}, "t2,t1,f1,f2", undefined, NothingThrown);
-
-// Test CompletionType::Continue.
-test(() =>  {
-    try {
-        append("t2");
-        for (var i = 0; i < 2; i++) {
-            try {
-                append("t1");
-                continue;
-            } catch(a) {
-                append("c1");
-            } finally {
-                append("f1");
-            }
-        }
-    } catch(b) {
-        append("c2");
-    } finally {
-        append("f2");
-    }
-
-}, "t2,t1,f1,t1,f1,f2", undefined, NothingThrown);
-
-// Test CompletionType::Return.
-test(() =>  {
-    try {
-        append("t2");
-        for (var i = 0; i < 2; i++) {
-            try {
-                append("t1");
-                return;
-            } catch(a) {
-                append("c1");
-            } finally {
-                append("f1");
-            }
-        }
-    } catch(b) {
-        append("c2");
-    } finally {
-        append("f2");
-    }
-
-}, "t2,t1,f1,f2", undefined, NothingThrown);
-
-// Test CompletionType::Throw.
-test(() =>  {
-    try {
-        append("t2");
-        for (var i = 0; i < 2; i++) {
-            try {
-                append("t1");
-                throw { };
-            } catch(a) {
-                append("c1");
-            } finally {
-                append("f1");
-            }
-        }
-    } catch(b) {
-        append("c2");
-    } finally {
-        append("f2");
-    }
-
-}, "t2,t1,c1,f1,t1,c1,f1,f2", undefined, NothingThrown);
-
-// Test CompletionType::Normal in a for-of loop.
-test(() =>  {
-    let arr = [1, 2];
-    try {
-        append("t2");
-        for (let x of arr) {
-            try {
-                append("t1");
-            } catch(a) {
-                append("c1");
-            } finally {
-                append("f1");
-            }
-        }
-    } catch(b) {
-        append("c2");
-    } finally {
-        append("f2");
-    }
-
-}, "t2,t1,f1,t1,f1,f2", undefined, NothingThrown);
-
-// Test CompletionType::Break in a for-of loop.
-test(() =>  {
-    let arr = [1, 2];
-    try {
-        append("t2");
-        for (let x of arr) {
-            try {
-                append("t1");
-                break;
-            } catch(a) {
-                append("c1");
-            } finally {
-                append("f1");
-            }
-        }
-    } catch(b) {
-        append("c2");
-    } finally {
-        append("f2");
-    }
-
-}, "t2,t1,f1,f2", undefined, NothingThrown);
-
-// Test CompletionType::Continue in a for-of loop.
-test(() =>  {
-    let arr = [1, 2];
-    try {
-        append("t2");
-        for (let x of arr) {
-            try {
-                append("t1");
-                continue;
-            } catch(a) {
-                append("c1");
-            } finally {
-                append("f1");
-            }
-        }
-    } catch(b) {
-        append("c2");
-    } finally {
-        append("f2");
-    }
-
-}, "t2,t1,f1,t1,f1,f2", undefined, NothingThrown);
-
-// Test CompletionType::Return in a for-of loop.
-test(() =>  {
-    let arr = [1, 2];
-    try {
-        append("t2");
-        for (let x of arr) {
-            try {
-                append("t1");
-                return;
-            } catch(a) {
-                append("c1");
-            } finally {
-                append("f1");
-            }
-        }
-    } catch(b) {
-        append("c2");
-    } finally {
-        append("f2");
-    }
-
-}, "t2,t1,f1,f2", undefined, NothingThrown);
-
-// Test CompletionType::Throw in a for-of loop.
-test(() =>  {
-    let arr = [1, 2];
-    try {
-        append("t2");
-        for (let x of arr) {
-            try {
-                append("t1");
-                throw { };
-            } catch(a) {
-                append("c1");
-            } finally {
-                append("f1");
-            }
-        }
-    } catch(b) {
-        append("c2");
-    } finally {
-        append("f2");
-    }
-
-}, "t2,t1,c1,f1,t1,c1,f1,f2", undefined, NothingThrown);
-
-
-// No abrupt completions.
-test(() => {
-    append("a");
-    try {
-        append("b");
-    } finally {
-        append("c");
-    }   
-    append("d");
-    return 400;
-
-}, "a,b,c,d", 400, NothingThrown);
-
-
-// Return after a. Should not execute any finally blocks, and return a's result.
-test(() => {
-    append("a");
-    return 100;
-    try {
-        append("b");
-        return 200;
-        try {
-            append("c");
-            return 300;
-        } finally {
-            append("d");
-        }
-        append("e");
-        return 500;
-    } finally {
-        append("f");
-    }   
-    append("g");
-    return 700;
-
-}, "a", 100, NothingThrown);
-
-// Return after b. Should execute finally block f only, and return b's result.
-test(() => {
-    append("a");
-    try {
-        append("b");
-        return 200;
-        try {
-            append("c");
-            return 300;
-        } finally {
-            append("d");
-        }
-        append("e");
-        return 500;
-    } finally {
-        append("f");
-    }   
-    append("g");
-    return 700;
-
-}, "a,b,f", 200, NothingThrown);
-
-// Return after c. Should execute finally blocks d and f, and return c's result.
-test(() => {
-    append("a");
-    try {
-        append("b");
-        try {
-            append("c");
-            return 300;
-        } finally {
-            append("d");
-        }
-        append("e");
-        return 500;
-    } finally {
-        append("f");
-    }   
-    append("g");
-    return 700;
-
-}, "a,b,c,d,f", 300, NothingThrown);
-
-// Return after c and d. Should execute finally blocks d and f, and return last return value from d.
-test(() => {
-    append("a");
-    try {
-        append("b");
-        try {
-            append("c");
-            return 300;
-        } finally {
-            append("d");
-            return 400;
-        }
-        append("e");
-        return 500;
-    } finally {
-        append("f");
-    }   
-    append("g");
-    return 700;
-
-}, "a,b,c,d,f", 400, NothingThrown);
-
-// Return after c, d, and f. Should execute finally blocks d and f, and return last return value from f.
-test(() => {
-    append("a");
-    try {
-        append("b");
-        try {
-            append("c");
-            return 300;
-        } finally {
-            append("d");
-            return 400;
-        }
-        append("e");
-        return 500;
-    } finally {
-        append("f");
-        return 600;
-    }   
-    append("g");
-    return 700;
-
-}, "a,b,c,d,f", 600, NothingThrown);
-
-// Return after g.
-test(() => {
-    append("a");
-    try {
-        append("b");
-        try {
-            append("c");
-        } finally {
-            append("d");
-        }
-        append("e");
-    } finally {
-        append("f");
-    }   
-    append("g");
-    return 700;
-
-}, "a,b,c,d,e,f,g", 700, NothingThrown);
-
-// Throw after a.
-test(() => {
-    append("a");
-    throw 100;
-    try {
-        append("b");
-        throw 200;
-        try {
-            append("c");
-            throw 300;
-        } finally {
-            append("d");
-        }
-        append("e");
-        throw 500;
-    } finally {
-        append("f");
-    }   
-    append("g");
-    throw 700;
-
-}, "a", NothingReturned, 100);
-
-// Throw after b.
-test(() => {
-    append("a");
-    try {
-        append("b");
-        throw 200;
-        try {
-            append("c");
-            throw 300;
-        } finally {
-            append("d");
-        }
-        append("e");
-        throw 500;
-    } finally {
-        append("f");
-    }   
-    append("g");
-    throw 700;
-
-}, "a,b,f", NothingReturned, 200);
-
-// Throw after c.
-test(() => {
-    append("a");
-    try {
-        append("b");
-        try {
-            append("c");
-            throw 300;
-        } finally {
-            append("d");
-        }
-        append("e");
-        throw 500;
-    } finally {
-        append("f");
-    }   
-    append("g");
-    throw 700;
-
-}, "a,b,c,d,f", NothingReturned, 300);
-
-// Throw after c and d.
-test(() => {
-    append("a");
-    try {
-        append("b");
-        try {
-            append("c");
-            throw 300;
-        } finally {
-            append("d");
-            throw 400;
-        }
-        append("e");
-        throw 500;
-    } finally {
-        append("f");
-    }   
-    append("g");
-    throw 700;
-
-}, "a,b,c,d,f", NothingReturned, 400);
-
-// Throw after c, d, and f.
-test(() => {
-    append("a");
-    try {
-        append("b");
-        try {
-            append("c");
-            throw 300;
-        } finally {
-            append("d");
-            throw 400;
-        }
-        append("e");
-        throw 500;
-    } finally {
-        append("f");
-        throw 600;
-    }   
-    append("g");
-    return 700;
-
-}, "a,b,c,d,f", NothingReturned, 600);
-
-// Throw after g.
-test(() => {
-    append("a");
-    try {
-        append("b");
-        try {
-            append("c");
-        } finally {
-            append("d");
-        }
-        append("e");
-    } finally {
-        append("f");
-    }   
-    append("g");
-    throw 700;
-
-}, "a,b,c,d,e,f,g", NothingReturned, 700);
-
-// Throw after b with catch at z.
-test(() => {
-    append("a");
-    try {
-        append("b");
-        throw 200;
-        try {
-            append("c");
-            throw 300;
-        } finally {
-            append("d");
-        }
-        append("e");
-        throw 500;
-    } catch (e) {
-        append("z");
-    } finally {
-        append("f");
-    }   
-    append("g");
-    return 700;
-
-}, "a,b,z,f,g", 700, NothingThrown);
-
-// Throw after b with catch at z and rethrow at z.
-test(() => {
-    append("a");
-    try {
-        append("b");
-        throw 200;
-        try {
-            append("c");
-            throw 300;
-        } finally {
-            append("d");
-        }
-        append("e");
-        throw 500;
-    } catch (e) {
-        append("z");
-        throw 5000;
-    } finally {
-        append("f");
-    }   
-    append("g");
-    return 700;
-
-}, "a,b,z,f", NothingReturned, 5000);
-
-// Throw after c with catch at y and z.
-test(() => {
-    append("a");
-    try {
-        append("b");
-        try {
-            append("c");
-            throw 300;
-        } catch (e) {
-            append("y");
-        } finally {
-            append("d");
-        }
-        append("e");
-    } catch (e) {
-        append("z");
-    } finally {
-        append("f");
-    }   
-    append("g");
-    return 700;
-
-}, "a,b,c,y,d,e,f,g", 700, NothingThrown);
-
-// Throw after c with catch at y and z, and rethrow at y.
-test(() => {
-    append("a");
-    try {
-        append("b");
-        try {
-            append("c");
-            throw 300;
-        } catch (e) {
-            append("y");
-            throw 3000;
-        } finally {
-            append("d");
-        }
-        append("e");
-    } catch (e) {
-        append("z");
-    } finally {
-        append("f");
-    }   
-    append("g");
-    return 700;
-
-}, "a,b,c,y,d,z,f,g", 700, NothingThrown);
-
-// Throw after c with catch at y and z, and rethrow at y and z.
-test(() => {
-    append("a");
-    try {
-        append("b");
-        try {
-            append("c");
-            throw 300;
-        } catch (e) {
-            append("y");
-            throw 3000;
-        } finally {
-            append("d");
-        }
-        append("e");
-    } catch (e) {
-        append("z");
-        throw 5000;
-    } finally {
-        append("f");
-    }   
-    append("g");
-    return 700;
-
-}, "a,b,c,y,d,z,f", NothingReturned, 5000);
-
-// Throw after c with catch at y and z, and rethrow at y, z, and f.
-test(() => {
-    append("a");
-    try {
-        append("b");
-        try {
-            append("c");
-            throw 300;
-        } catch (e) {
-            append("y");
-            throw 3000;
-        } finally {
-            append("d");
-        }
-        append("e");
-    } catch (e) {
-        append("z");
-        throw 5000;
-    } finally {
-        append("f");
-        throw 600;
-    }   
-    append("g");
-    return 700;
-
-}, "a,b,c,y,d,z,f", NothingReturned, 600);
-
-// No throw or return in for-of loop.
-test(() => {
-    class TestIterator {
-        constructor() {
-            append("c");
-            this.i = 0;
-        }
-        next() {
-            append("n");
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append("r");
-            return { }
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new TestIterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-    }
-    append("x");
-    return 200;
-
-}, "c,n,0,n,1,n,2,n,x", 200, NothingThrown);
-
-// Break in for-of loop.
-test(() => {
-    class TestIterator {
-        constructor() {
-            append("c");
-            this.i = 0;
-        }
-        next() {
-            append("n");
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append("r");
-            return { }
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new TestIterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-        if (element == 1)
-            break;
-    }
-    append("x");
-    return 200;
-
-}, "c,n,0,n,1,r,x", 200, NothingThrown);
-
-// Break in for-of loop with throw in Iterator.return().
-test(() => {
-    class Iterator {
-        constructor() {
-            append("c");
-            this.i = 0;
-        }
-        next() {
-            append("n");
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append("r");
-            throw 300;
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new Iterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-        if (element == 1)
-            break;
-    }
-    append("x");
-    return 200;
-
-}, "c,n,0,n,1,r", NothingReturned, 300);
-
-// Break in for-of loop with Iterator.return() returning a non object.
-test(() => {
-    class Iterator {
-        constructor() {
-            append("c");
-            this.i = 0;
-        }
-        next() {
-            append("n");
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append("r");
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new Iterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-        if (element == 1)
-            break;
-    }
-    append("x");
-    return 200;
-
-}, "c,n,0,n,1,r", NothingReturned, 'TypeError');
-
-// Return in for-of loop.
-test(() => {
-    class TestIterator {
-        constructor() {
-            append("c");
-            this.i = 0;
-        }
-        next() {
-            append("n");
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append("r");
-            return { }
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new TestIterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-        if (element == 1)
-            return 100;
-    }
-    append("x");
-    return 200;
-
-}, "c,n,0,n,1,r", 100, NothingThrown);
-
-// Return in for-of loop with throw in Iterator.return().
-test(() => {
-    class Iterator {
-        constructor() {
-            append("c");
-            this.i = 0;
-        }
-        next() {
-            append("n");
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append("r");
-            throw 300;
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new Iterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-        if (element == 1)
-            return 100;
-    }
-    append("x");
-    return 200;
-
-}, "c,n,0,n,1,r", NothingReturned, 300);
-
-// Return in for-of loop with Iterator.return() returning a non object.
-test(() => {
-    class Iterator {
-        constructor() {
-            append("c");
-            this.i = 0;
-        }
-        next() {
-            append("n");
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append("r");
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new Iterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-        if (element == 1)
-            return 100;
-    }
-    append("x");
-    return 200;
-
-}, "c,n,0,n,1,r", NothingReturned, 'TypeError');
-
-
-// Throw in for-of loop.
-test(() => {
-    class Iterator {
-        constructor() {
-            append("c");
-            this.i = 0;
-        }
-        next() {
-            append("n");
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append("r");
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new Iterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-        if (element == 1)
-            throw 100;
-    }
-    append("x");
-    return 200;
-
-}, "c,n,0,n,1,r", NothingReturned, 100);
-
-// Throw in for-of loop with throw in Iterator.return().
-test(() => {
-    class Iterator {
-        constructor() {
-            append("c");
-            this.i = 0;
-        }
-        next() {
-            append("n");
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append("r");
-            throw 300;
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new Iterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-        if (element == 1)
-            throw 100;
-    }
-    append("x");
-    return 200;
-
-}, "c,n,0,n,1,r", NothingReturned, 100);

Modified: branches/safari-603-branch/Source/_javascript_Core/ChangeLog (210010 => 210011)


--- branches/safari-603-branch/Source/_javascript_Core/ChangeLog	2016-12-20 02:03:02 UTC (rev 210010)
+++ branches/safari-603-branch/Source/_javascript_Core/ChangeLog	2016-12-20 02:05:52 UTC (rev 210011)
@@ -1,5 +1,86 @@
 2016-12-19  Babak Shafiei  <[email protected]>
 
+        Merge r210010.
+
+    2016-12-19  Mark Lam  <[email protected]>
+
+            Rolling out r209974 and r209952. They break some websites in mysterious ways. Step 2: Rollout r209952.
+            https://bugs.webkit.org/show_bug.cgi?id=166049
+
+            Not reviewed.
+
+            * bytecode/HandlerInfo.h:
+            (JSC::HandlerInfoBase::typeName):
+            * bytecompiler/BytecodeGenerator.cpp:
+            (JSC::BytecodeGenerator::generate):
+            (JSC::BytecodeGenerator::BytecodeGenerator):
+            (JSC::BytecodeGenerator::emitReturn):
+            (JSC::BytecodeGenerator::pushFinallyControlFlowScope):
+            (JSC::BytecodeGenerator::pushIteratorCloseControlFlowScope):
+            (JSC::BytecodeGenerator::popFinallyControlFlowScope):
+            (JSC::BytecodeGenerator::popIteratorCloseControlFlowScope):
+            (JSC::BytecodeGenerator::emitComplexPopScopes):
+            (JSC::BytecodeGenerator::emitPopScopes):
+            (JSC::BytecodeGenerator::pushTry):
+            (JSC::BytecodeGenerator::popTryAndEmitCatch):
+            (JSC::BytecodeGenerator::labelScopeDepth):
+            (JSC::BytecodeGenerator::pushLocalControlFlowScope):
+            (JSC::BytecodeGenerator::popLocalControlFlowScope):
+            (JSC::BytecodeGenerator::emitEnumeration):
+            (JSC::BytecodeGenerator::emitYield):
+            (JSC::BytecodeGenerator::emitDelegateYield):
+            (JSC::BytecodeGenerator::popTry): Deleted.
+            (JSC::BytecodeGenerator::emitCatch): Deleted.
+            (JSC::BytecodeGenerator::restoreScopeRegister): Deleted.
+            (JSC::BytecodeGenerator::labelScopeDepthToLexicalScopeIndex): Deleted.
+            (JSC::BytecodeGenerator::emitIsNumber): Deleted.
+            (JSC::BytecodeGenerator::emitJumpViaFinallyIfNeeded): Deleted.
+            (JSC::BytecodeGenerator::emitReturnViaFinallyIfNeeded): Deleted.
+            (JSC::BytecodeGenerator::emitFinallyCompletion): Deleted.
+            (JSC::BytecodeGenerator::allocateFinallyRegisters): Deleted.
+            (JSC::BytecodeGenerator::releaseFinallyRegisters): Deleted.
+            (JSC::BytecodeGenerator::emitCompareFinallyActionAndJumpIf): Deleted.
+            * bytecompiler/BytecodeGenerator.h:
+            (JSC::BytecodeGenerator::isInFinallyBlock):
+            (JSC::FinallyJump::FinallyJump): Deleted.
+            (JSC::FinallyContext::FinallyContext): Deleted.
+            (JSC::FinallyContext::outerContext): Deleted.
+            (JSC::FinallyContext::finallyLabel): Deleted.
+            (JSC::FinallyContext::depth): Deleted.
+            (JSC::FinallyContext::numberOfBreaksOrContinues): Deleted.
+            (JSC::FinallyContext::incNumberOfBreaksOrContinues): Deleted.
+            (JSC::FinallyContext::handlesReturns): Deleted.
+            (JSC::FinallyContext::setHandlesReturns): Deleted.
+            (JSC::FinallyContext::registerJump): Deleted.
+            (JSC::FinallyContext::numberOfJumps): Deleted.
+            (JSC::FinallyContext::jumps): Deleted.
+            (JSC::ControlFlowScope::ControlFlowScope): Deleted.
+            (JSC::ControlFlowScope::isLabelScope): Deleted.
+            (JSC::ControlFlowScope::isFinallyScope): Deleted.
+            (JSC::BytecodeGenerator::currentLexicalScopeIndex): Deleted.
+            (JSC::BytecodeGenerator::FinallyRegistersScope::FinallyRegistersScope): Deleted.
+            (JSC::BytecodeGenerator::FinallyRegistersScope::~FinallyRegistersScope): Deleted.
+            (JSC::BytecodeGenerator::finallyActionRegister): Deleted.
+            (JSC::BytecodeGenerator::finallyReturnValueRegister): Deleted.
+            (JSC::BytecodeGenerator::emitSetFinallyActionToNormalCompletion): Deleted.
+            (JSC::BytecodeGenerator::emitSetFinallyActionToReturnCompletion): Deleted.
+            (JSC::BytecodeGenerator::emitSetFinallyActionToJumpID): Deleted.
+            (JSC::BytecodeGenerator::emitSetFinallyReturnValueRegister): Deleted.
+            (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNormalCompletion): Deleted.
+            (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotJump): Deleted.
+            (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsReturnCompletion): Deleted.
+            (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotReturnCompletion): Deleted.
+            (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotThrowCompletion): Deleted.
+            (JSC::BytecodeGenerator::emitJumpIfCompletionTypeIsThrow): Deleted.
+            (JSC::BytecodeGenerator::bytecodeOffsetToJumpID): Deleted.
+            * bytecompiler/NodesCodegen.cpp:
+            (JSC::ContinueNode::emitBytecode):
+            (JSC::BreakNode::emitBytecode):
+            (JSC::ReturnNode::emitBytecode):
+            (JSC::TryNode::emitBytecode):
+
+2016-12-19  Babak Shafiei  <[email protected]>
+
         Merge r210007.
 
     2016-12-19  Mark Lam  <[email protected]>

Modified: branches/safari-603-branch/Source/_javascript_Core/bytecode/HandlerInfo.h (210010 => 210011)


--- branches/safari-603-branch/Source/_javascript_Core/bytecode/HandlerInfo.h	2016-12-20 02:03:02 UTC (rev 210010)
+++ branches/safari-603-branch/Source/_javascript_Core/bytecode/HandlerInfo.h	2016-12-20 02:05:52 UTC (rev 210011)
@@ -31,9 +31,9 @@
 namespace JSC {
 
 enum class HandlerType {
-    Catch = 0,
-    Finally = 1,
-    SynthesizedCatch = 2,
+    Illegal = 0,
+    Catch = 1,
+    Finally = 2,
     SynthesizedFinally = 3
 };
 
@@ -53,8 +53,6 @@
             return "catch";
         case HandlerType::Finally:
             return "finally";
-        case HandlerType::SynthesizedCatch:
-            return "synthesized catch";
         case HandlerType::SynthesizedFinally:
             return "synthesized finally";
         default:

Modified: branches/safari-603-branch/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (210010 => 210011)


--- branches/safari-603-branch/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-12-20 02:03:02 UTC (rev 210010)
+++ branches/safari-603-branch/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-12-20 02:05:52 UTC (rev 210011)
@@ -156,6 +156,7 @@
         if (end <= start)
             continue;
         
+        ASSERT(range.tryData->handlerType != HandlerType::Illegal);
         UnlinkedHandlerInfo info(static_cast<uint32_t>(start), static_cast<uint32_t>(end),
             static_cast<uint32_t>(range.tryData->target->bind()), range.tryData->handlerType);
         m_codeBlock->addExceptionHandler(info);
@@ -679,25 +680,21 @@
     // because a function's default parameter ExpressionNodes will use temporary registers.
     pushTDZVariables(*parentScopeTDZVariables, TDZCheckOptimization::DoNotOptimize, TDZRequirement::UnderTDZ);
 
-    RefPtr<Label> catchLabel = newLabel();
     TryData* tryFormalParametersData = nullptr;
-    bool needTryCatch = isAsyncFunctionWrapperParseMode(parseMode) && !isSimpleParameterList;
-    if (needTryCatch) {
+    if (isAsyncFunctionWrapperParseMode(parseMode) && !isSimpleParameterList) {
         RefPtr<Label> tryFormalParametersStart = emitLabel(newLabel().get());
-        tryFormalParametersData = pushTry(tryFormalParametersStart.get(), catchLabel.get(), HandlerType::SynthesizedCatch);
+        tryFormalParametersData = pushTry(tryFormalParametersStart.get());
     }
 
     initializeDefaultParameterValuesAndSetupFunctionScopeStack(parameters, isSimpleParameterList, functionNode, functionSymbolTable, symbolTableConstantIndex, captures, shouldCreateArgumentsVariableInParameterScope);
 
-    if (needTryCatch) {
+    if (isAsyncFunctionWrapperParseMode(parseMode) && !isSimpleParameterList) {
         RefPtr<Label> didNotThrow = newLabel();
         emitJump(didNotThrow.get());
-        emitLabel(catchLabel.get());
-        popTry(tryFormalParametersData, catchLabel.get());
-
+        RefPtr<RegisterID> exception = newTemporary();
         RefPtr<RegisterID> thrownValue = newTemporary();
-        RegisterID* unused = newTemporary();
-        emitCatch(unused, thrownValue.get());
+        RefPtr<Label> catchHere = emitLabel(newLabel().get());
+        popTryAndEmitCatch(tryFormalParametersData, exception.get(), thrownValue.get(), catchHere.get(), HandlerType::Catch);
 
         // return promiseCapability.@reject(thrownValue)
         RefPtr<RegisterID> reject = emitGetById(newTemporary(), promiseCapabilityRegister(), m_vm->propertyNames->builtinNames().rejectPrivateName());
@@ -3496,16 +3493,16 @@
     }
 }
 
-RegisterID* BytecodeGenerator::emitReturn(RegisterID* src, ReturnFrom from)
+RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
 {
     if (isConstructor()) {
         bool mightBeDerived = constructorKind() == ConstructorKind::Extends;
         bool srcIsThis = src->index() == m_thisRegister.index();
 
-        if (mightBeDerived && (srcIsThis || from == ReturnFrom::Finally))
+        if (mightBeDerived && srcIsThis)
             emitTDZCheck(src);
 
-        if (!srcIsThis || from == ReturnFrom::Finally) {
+        if (!srcIsThis) {
             RefPtr<Label> isObjectLabel = newLabel();
             emitJumpIfTrue(emitIsObject(newTemporary(), src), isObjectLabel.get());
 
@@ -3683,31 +3680,82 @@
     emitDebugHook(WillLeaveCallFrame, m_scopeNode->lastLine(), m_scopeNode->startOffset(), m_scopeNode->lineStartOffset());
 }
 
-FinallyContext* BytecodeGenerator::pushFinallyControlFlowScope(Label* finallyLabel)
+void BytecodeGenerator::pushFinallyControlFlowScope(StatementNode* finallyBlock)
 {
     // Reclaim free label scopes.
     while (m_labelScopes.size() && !m_labelScopes.last().refCount())
         m_labelScopes.removeLast();
 
-    ControlFlowScope scope(ControlFlowScope::Finally, currentLexicalScopeIndex(), FinallyContext(m_currentFinallyContext, finallyLabel, m_finallyDepth));
-    m_controlFlowScopeStack.append(WTFMove(scope));
+    ControlFlowScope scope;
+    scope.isFinallyBlock = true;
+    FinallyContext context = {
+        finallyBlock,
+        nullptr,
+        nullptr,
+        static_cast<unsigned>(m_controlFlowScopeStack.size()),
+        static_cast<unsigned>(m_switchContextStack.size()),
+        static_cast<unsigned>(m_forInContextStack.size()),
+        static_cast<unsigned>(m_tryContextStack.size()),
+        static_cast<unsigned>(m_labelScopes.size()),
+        static_cast<unsigned>(m_lexicalScopeStack.size()),
+        m_finallyDepth,
+        m_localScopeDepth
+    };
+    scope.finallyContext = context;
+    m_controlFlowScopeStack.append(scope);
+    m_finallyDepth++;
+}
 
+void BytecodeGenerator::pushIteratorCloseControlFlowScope(RegisterID* iterator, ThrowableExpressionData* node)
+{
+    // Reclaim free label scopes.
+    while (m_labelScopes.size() && !m_labelScopes.last().refCount())
+        m_labelScopes.removeLast();
+
+    ControlFlowScope scope;
+    scope.isFinallyBlock = true;
+    FinallyContext context = {
+        nullptr,
+        iterator,
+        node,
+        static_cast<unsigned>(m_controlFlowScopeStack.size()),
+        static_cast<unsigned>(m_switchContextStack.size()),
+        static_cast<unsigned>(m_forInContextStack.size()),
+        static_cast<unsigned>(m_tryContextStack.size()),
+        static_cast<unsigned>(m_labelScopes.size()),
+        static_cast<unsigned>(m_lexicalScopeStack.size()),
+        m_finallyDepth,
+        m_localScopeDepth
+    };
+    scope.finallyContext = context;
+    m_controlFlowScopeStack.append(scope);
     m_finallyDepth++;
-    m_currentFinallyContext = &m_controlFlowScopeStack.last().finallyContext;
-    return m_currentFinallyContext;
 }
 
-FinallyContext BytecodeGenerator::popFinallyControlFlowScope()
+void BytecodeGenerator::popFinallyControlFlowScope()
 {
     ASSERT(m_controlFlowScopeStack.size());
-    ASSERT(m_controlFlowScopeStack.last().isFinallyScope());
+    ASSERT(m_controlFlowScopeStack.last().isFinallyBlock);
+    ASSERT(m_controlFlowScopeStack.last().finallyContext.finallyBlock);
+    ASSERT(!m_controlFlowScopeStack.last().finallyContext.iterator);
+    ASSERT(!m_controlFlowScopeStack.last().finallyContext.enumerationNode);
     ASSERT(m_finallyDepth > 0);
-    ASSERT(m_currentFinallyContext);
-    m_currentFinallyContext = m_currentFinallyContext->outerContext();
+    m_controlFlowScopeStack.removeLast();
     m_finallyDepth--;
-    return m_controlFlowScopeStack.takeLast().finallyContext;
 }
 
+void BytecodeGenerator::popIteratorCloseControlFlowScope()
+{
+    ASSERT(m_controlFlowScopeStack.size());
+    ASSERT(m_controlFlowScopeStack.last().isFinallyBlock);
+    ASSERT(!m_controlFlowScopeStack.last().finallyContext.finallyBlock);
+    ASSERT(m_controlFlowScopeStack.last().finallyContext.iterator);
+    ASSERT(m_controlFlowScopeStack.last().finallyContext.enumerationNode);
+    ASSERT(m_finallyDepth > 0);
+    m_controlFlowScopeStack.removeLast();
+    m_finallyDepth--;
+}
+
 LabelScopePtr BytecodeGenerator::breakTarget(const Identifier& name)
 {
     // Reclaim free label scopes.
@@ -3805,12 +3853,162 @@
     m_topMostScope = addVar();
     emitMove(m_topMostScope, scopeRegister());
 }
+    
+void BytecodeGenerator::emitComplexPopScopes(RegisterID* scope, ControlFlowScope* topScope, ControlFlowScope* bottomScope)
+{
+    while (topScope > bottomScope) {
+        // First we count the number of dynamic scopes we need to remove to get
+        // to a finally block.
+        int numberOfNormalScopes = 0;
+        while (topScope > bottomScope) {
+            if (topScope->isFinallyBlock)
+                break;
+            ++numberOfNormalScopes;
+            --topScope;
+        }
 
-TryData* BytecodeGenerator::pushTry(Label* start, Label* handlerLabel, HandlerType handlerType)
+        if (numberOfNormalScopes) {
+            // We need to remove a number of dynamic scopes to get to the next
+            // finally block
+            RefPtr<RegisterID> parentScope = newTemporary();
+            while (numberOfNormalScopes--) {
+                parentScope = emitGetParentScope(parentScope.get(), scope);
+                emitMove(scope, parentScope.get());
+            }
+
+            // If topScope == bottomScope then there isn't a finally block left to emit.
+            if (topScope == bottomScope)
+                return;
+        }
+        
+        Vector<ControlFlowScope> savedControlFlowScopeStack;
+        Vector<SwitchInfo> savedSwitchContextStack;
+        Vector<RefPtr<ForInContext>> savedForInContextStack;
+        Vector<TryContext> poppedTryContexts;
+        Vector<LexicalScopeStackEntry> savedLexicalScopeStack;
+        LabelScopeStore savedLabelScopes;
+        while (topScope > bottomScope && topScope->isFinallyBlock) {
+            RefPtr<Label> beforeFinally = emitLabel(newLabel().get());
+            
+            // Save the current state of the world while instating the state of the world
+            // for the finally block.
+            FinallyContext finallyContext = topScope->finallyContext;
+            bool flipScopes = finallyContext.controlFlowScopeStackSize != m_controlFlowScopeStack.size();
+            bool flipSwitches = finallyContext.switchContextStackSize != m_switchContextStack.size();
+            bool flipForIns = finallyContext.forInContextStackSize != m_forInContextStack.size();
+            bool flipTries = finallyContext.tryContextStackSize != m_tryContextStack.size();
+            bool flipLabelScopes = finallyContext.labelScopesSize != m_labelScopes.size();
+            bool flipLexicalScopeStack = finallyContext.lexicalScopeStackSize != m_lexicalScopeStack.size();
+            int topScopeIndex = -1;
+            int bottomScopeIndex = -1;
+            if (flipScopes) {
+                topScopeIndex = topScope - m_controlFlowScopeStack.begin();
+                bottomScopeIndex = bottomScope - m_controlFlowScopeStack.begin();
+                savedControlFlowScopeStack = m_controlFlowScopeStack;
+                m_controlFlowScopeStack.shrink(finallyContext.controlFlowScopeStackSize);
+            }
+            if (flipSwitches) {
+                savedSwitchContextStack = m_switchContextStack;
+                m_switchContextStack.shrink(finallyContext.switchContextStackSize);
+            }
+            if (flipForIns) {
+                savedForInContextStack = m_forInContextStack;
+                m_forInContextStack.shrink(finallyContext.forInContextStackSize);
+            }
+            if (flipTries) {
+                while (m_tryContextStack.size() != finallyContext.tryContextStackSize) {
+                    ASSERT(m_tryContextStack.size() > finallyContext.tryContextStackSize);
+                    TryContext context = m_tryContextStack.takeLast();
+                    TryRange range;
+                    range.start = context.start;
+                    range.end = beforeFinally;
+                    range.tryData = context.tryData;
+                    m_tryRanges.append(range);
+                    poppedTryContexts.append(context);
+                }
+            }
+            if (flipLabelScopes) {
+                savedLabelScopes = m_labelScopes;
+                while (m_labelScopes.size() > finallyContext.labelScopesSize)
+                    m_labelScopes.removeLast();
+            }
+            if (flipLexicalScopeStack) {
+                savedLexicalScopeStack = m_lexicalScopeStack;
+                m_lexicalScopeStack.shrink(finallyContext.lexicalScopeStackSize);
+            }
+            int savedFinallyDepth = m_finallyDepth;
+            m_finallyDepth = finallyContext.finallyDepth;
+            int savedDynamicScopeDepth = m_localScopeDepth;
+            m_localScopeDepth = finallyContext.dynamicScopeDepth;
+            
+            if (finallyContext.finallyBlock) {
+                // Emit the finally block.
+                emitNode(finallyContext.finallyBlock);
+            } else {
+                // Emit the IteratorClose block.
+                ASSERT(finallyContext.iterator);
+                emitIteratorClose(finallyContext.iterator, finallyContext.enumerationNode);
+            }
+
+            RefPtr<Label> afterFinally = emitLabel(newLabel().get());
+            
+            // Restore the state of the world.
+            if (flipScopes) {
+                m_controlFlowScopeStack = savedControlFlowScopeStack;
+                topScope = &m_controlFlowScopeStack[topScopeIndex]; // assert it's within bounds
+                bottomScope = m_controlFlowScopeStack.begin() + bottomScopeIndex; // don't assert, since it the index might be -1.
+            }
+            if (flipSwitches)
+                m_switchContextStack = savedSwitchContextStack;
+            if (flipForIns)
+                m_forInContextStack = savedForInContextStack;
+            if (flipTries) {
+                ASSERT(m_tryContextStack.size() == finallyContext.tryContextStackSize);
+                for (unsigned i = poppedTryContexts.size(); i--;) {
+                    TryContext context = poppedTryContexts[i];
+                    context.start = afterFinally;
+                    m_tryContextStack.append(context);
+                }
+                poppedTryContexts.clear();
+            }
+            if (flipLabelScopes)
+                m_labelScopes = savedLabelScopes;
+            if (flipLexicalScopeStack)
+                m_lexicalScopeStack = savedLexicalScopeStack;
+            m_finallyDepth = savedFinallyDepth;
+            m_localScopeDepth = savedDynamicScopeDepth;
+            
+            --topScope;
+        }
+    }
+}
+
+void BytecodeGenerator::emitPopScopes(RegisterID* scope, int targetScopeDepth)
 {
+    ASSERT(labelScopeDepth() - targetScopeDepth >= 0);
+
+    size_t scopeDelta = labelScopeDepth() - targetScopeDepth;
+    ASSERT(scopeDelta <= m_controlFlowScopeStack.size());
+    if (!scopeDelta)
+        return;
+
+    if (!m_finallyDepth) {
+        RefPtr<RegisterID> parentScope = newTemporary();
+        while (scopeDelta--) {
+            parentScope = emitGetParentScope(parentScope.get(), scope);
+            emitMove(scope, parentScope.get());
+        }
+        return;
+    }
+
+    emitComplexPopScopes(scope, &m_controlFlowScopeStack.last(), &m_controlFlowScopeStack.last() - scopeDelta);
+}
+
+TryData* BytecodeGenerator::pushTry(Label* start)
+{
     TryData tryData;
-    tryData.target = handlerLabel;
-    tryData.handlerType = handlerType;
+    tryData.target = newLabel();
+    tryData.handlerType = HandlerType::Illegal;
     m_tryData.append(tryData);
     TryData* result = &m_tryData.last();
     
@@ -3823,7 +4021,7 @@
     return result;
 }
 
-void BytecodeGenerator::popTry(TryData* tryData, Label* end)
+void BytecodeGenerator::popTryAndEmitCatch(TryData* tryData, RegisterID* exceptionRegister, RegisterID* thrownValueRegister, Label* end, HandlerType handlerType)
 {
     m_usesExceptions = true;
     
@@ -3835,52 +4033,28 @@
     tryRange.tryData = m_tryContextStack.last().tryData;
     m_tryRanges.append(tryRange);
     m_tryContextStack.removeLast();
-}
+    
+    emitLabel(tryRange.tryData->target.get());
+    tryRange.tryData->handlerType = handlerType;
 
-void BytecodeGenerator::emitCatch(RegisterID* exceptionRegister, RegisterID* thrownValueRegister)
-{
     emitOpcode(op_catch);
     instructions().append(exceptionRegister->index());
     instructions().append(thrownValueRegister->index());
-}
 
-void BytecodeGenerator::restoreScopeRegister(int lexicalScopeIndex)
-{
-    if (lexicalScopeIndex == CurrentLexicalScopeIndex)
-        return; // No change needed.
-
-    if (lexicalScopeIndex != OutermostLexicalScopeIndex) {
-        ASSERT(lexicalScopeIndex < static_cast<int>(m_lexicalScopeStack.size()));
-        int endIndex = lexicalScopeIndex + 1;
-        for (size_t i = endIndex; i--; ) {
-            if (m_lexicalScopeStack[i].m_scope) {
-                emitMove(scopeRegister(), m_lexicalScopeStack[i].m_scope);
-                return;
-            }
+    bool foundLocalScope = false;
+    for (unsigned i = m_lexicalScopeStack.size(); i--; ) {
+        // Note that if we don't find a local scope in the current function/program, 
+        // we must grab the outer-most scope of this bytecode generation.
+        if (m_lexicalScopeStack[i].m_scope) {
+            foundLocalScope = true;
+            emitMove(scopeRegister(), m_lexicalScopeStack[i].m_scope);
+            break;
         }
     }
-    // Note that if we don't find a local scope in the current function/program,
-    // we must grab the outer-most scope of this bytecode generation.
-    emitMove(scopeRegister(), m_topMostScope);
+    if (!foundLocalScope)
+        emitMove(scopeRegister(), m_topMostScope);
 }
 
-void BytecodeGenerator::restoreScopeRegister()
-{
-    restoreScopeRegister(currentLexicalScopeIndex());
-}
-
-int BytecodeGenerator::labelScopeDepthToLexicalScopeIndex(int targetLabelScopeDepth)
-{
-    ASSERT(labelScopeDepth() - targetLabelScopeDepth >= 0);
-    size_t scopeDelta = labelScopeDepth() - targetLabelScopeDepth;
-    ASSERT(scopeDelta <= m_controlFlowScopeStack.size());
-    if (!scopeDelta)
-        return CurrentLexicalScopeIndex;
-
-    ControlFlowScope& targetScope = m_controlFlowScopeStack[targetLabelScopeDepth];
-    return targetScope.lexicalScopeIndex;
-}
-
 int BytecodeGenerator::localScopeDepth() const
 {
     return m_localScopeDepth;
@@ -3887,10 +4061,8 @@
 }
 
 int BytecodeGenerator::labelScopeDepth() const
-{
-    int depth = localScopeDepth() + m_finallyDepth;
-    ASSERT(depth == static_cast<int>(m_controlFlowScopeStack.size()));
-    return depth;
+{ 
+    return localScopeDepth() + m_finallyDepth;
 }
 
 void BytecodeGenerator::emitThrowStaticError(ErrorType errorType, RegisterID* raw)
@@ -3960,8 +4132,9 @@
 
 void BytecodeGenerator::pushLocalControlFlowScope()
 {
-    ControlFlowScope scope(ControlFlowScope::Label, currentLexicalScopeIndex());
-    m_controlFlowScopeStack.append(WTFMove(scope));
+    ControlFlowScope scope;
+    scope.isFinallyBlock = false;
+    m_controlFlowScopeStack.append(scope);
     m_localScopeDepth++;
 }
 
@@ -3968,7 +4141,7 @@
 void BytecodeGenerator::popLocalControlFlowScope()
 {
     ASSERT(m_controlFlowScopeStack.size());
-    ASSERT(!m_controlFlowScopeStack.last().isFinallyScope());
+    ASSERT(!m_controlFlowScopeStack.last().isFinallyBlock);
     m_controlFlowScopeStack.removeLast();
     m_localScopeDepth--;
 }
@@ -4123,11 +4296,9 @@
     }
     return false;
 }
-
+    
 void BytecodeGenerator::emitEnumeration(ThrowableExpressionData* node, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack, ForOfNode* forLoopNode, RegisterID* forLoopSymbolTable)
 {
-    FinallyRegistersScope finallyRegistersScope(*this);
-
     RefPtr<RegisterID> subject = newTemporary();
     emitNode(subject.get(), subjectNode);
     RefPtr<RegisterID> iterator = emitGetById(newTemporary(), subject.get(), propertyNames().iteratorSymbol);
@@ -4138,15 +4309,8 @@
     }
 
     RefPtr<Label> loopDone = newLabel();
-    RefPtr<Label> tryStartLabel = newLabel();
-    RefPtr<Label> finallyViaThrowLabel = newLabel();
-    RefPtr<Label> finallyLabel = newLabel();
-    RefPtr<Label> catchLabel = newLabel();
-    RefPtr<Label> endCatchLabel = newLabel();
-
     // RefPtr<Register> iterator's lifetime must be longer than IteratorCloseContext.
-    FinallyContext* finallyContext = pushFinallyControlFlowScope(finallyLabel.get());
-
+    pushIteratorCloseControlFlowScope(iterator.get(), node);
     {
         LabelScopePtr scope = newLabelScope(LabelScope::Loop);
         RefPtr<RegisterID> value = newTemporary();
@@ -4158,68 +4322,40 @@
         emitLabel(loopStart.get());
         emitLoopHint();
 
+        RefPtr<Label> tryStartLabel = newLabel();
         emitLabel(tryStartLabel.get());
-        TryData* tryData = pushTry(tryStartLabel.get(), finallyViaThrowLabel.get(), HandlerType::SynthesizedFinally);
+        TryData* tryData = pushTry(tryStartLabel.get());
         callBack(*this, value.get());
         emitJump(scope->continueTarget());
 
-        // IteratorClose sequence for abrupt completions.
+        // IteratorClose sequence for throw-ed control flow.
         {
-            // Finally block for the enumeration.
-            emitLabel(finallyViaThrowLabel.get());
-            popTry(tryData, finallyViaThrowLabel.get());
+            RefPtr<Label> catchHere = emitLabel(newLabel().get());
+            RefPtr<RegisterID> exceptionRegister = newTemporary();
+            RefPtr<RegisterID> thrownValueRegister = newTemporary();
+            popTryAndEmitCatch(tryData, exceptionRegister.get(),
+                thrownValueRegister.get(), catchHere.get(), HandlerType::SynthesizedFinally);
 
-            RegisterID* unused = newTemporary();
-            emitCatch(finallyActionRegister(), unused);
-            // Setting the finallyActionRegister to the caught exception here implies CompletionType::Throw.
+            RefPtr<Label> catchDone = newLabel();
 
-            emitLabel(finallyLabel.get());
-            restoreScopeRegister();
-
-            RefPtr<Label> finallyDone = newLabel();
-
             RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().returnKeyword);
-            emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), finallyDone.get());
+            emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), catchDone.get());
 
-            RefPtr<RegisterID> originalFinallyActionRegister = newTemporary();
-            emitMove(originalFinallyActionRegister.get(), finallyActionRegister());
-
             RefPtr<Label> returnCallTryStart = newLabel();
             emitLabel(returnCallTryStart.get());
-            TryData* returnCallTryData = pushTry(returnCallTryStart.get(), catchLabel.get(), HandlerType::SynthesizedCatch);
+            TryData* returnCallTryData = pushTry(returnCallTryStart.get());
 
             CallArguments returnArguments(*this, nullptr);
             emitMove(returnArguments.thisRegister(), iterator.get());
             emitCall(value.get(), returnMethod.get(), NoExpectedFunction, returnArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No);
-            emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), finallyDone.get());
-            emitThrowTypeError(ASCIILiteral("Iterator result interface is not an object."));
 
-            emitLabel(finallyDone.get());
-            emitFinallyCompletion(*finallyContext, endCatchLabel.get());
+            emitLabel(catchDone.get());
+            emitThrow(exceptionRegister.get());
 
-            popTry(returnCallTryData, finallyDone.get());
-
-            // Catch block for exceptions that may be thrown while calling the return
-            // handler in the enumeration finally block. The only reason we need this
-            // catch block is because if entered the above finally block due to a thrown
-            // exception, then we want to re-throw the original exception on exiting
-            // the finally block. Otherwise, we'll let any new exception pass through.
-            {
-                emitLabel(catchLabel.get());
-                RefPtr<RegisterID> exceptionRegister = newTemporary();
-                RegisterID* unused = newTemporary();
-                emitCatch(exceptionRegister.get(), unused);
-                restoreScopeRegister();
-
-                RefPtr<Label> throwLabel = newLabel();
-                emitJumpIfCompletionTypeIsThrow(originalFinallyActionRegister.get(), throwLabel.get());
-                emitMove(originalFinallyActionRegister.get(), exceptionRegister.get());
-
-                emitLabel(throwLabel.get());
-                emitThrow(originalFinallyActionRegister.get());
-
-                emitLabel(endCatchLabel.get());
-            }
+            // Absorb exception.
+            popTryAndEmitCatch(returnCallTryData, newTemporary(),
+                newTemporary(), catchDone.get(), HandlerType::SynthesizedFinally);
+            emitThrow(exceptionRegister.get());
         }
 
         emitLabel(scope->continueTarget());
@@ -4240,7 +4376,7 @@
     }
 
     // IteratorClose sequence for break-ed control flow.
-    popFinallyControlFlowScope();
+    popIteratorCloseControlFlowScope();
     emitIteratorClose(iterator.get(), node);
     emitLabel(loopDone.get());
 }
@@ -4361,14 +4497,6 @@
     return dst;
 }
 
-RegisterID* BytecodeGenerator::emitIsNumber(RegisterID* dst, RegisterID* src)
-{
-    emitOpcode(op_is_number);
-    instructions().append(dst->index());
-    instructions().append(src->index());
-    return dst;
-}
-
 RegisterID* BytecodeGenerator::emitIsUndefined(RegisterID* dst, RegisterID* src)
 {
     emitOpcode(op_is_undefined);
@@ -4656,9 +4784,11 @@
     // Return.
     {
         RefPtr<RegisterID> returnRegister = generatorValueRegister();
-        bool hasFinally = emitReturnViaFinallyIfNeeded(returnRegister.get());
-        if (!hasFinally)
-            emitReturn(returnRegister.get());
+        if (isInFinallyBlock()) {
+            returnRegister = emitMove(newTemporary(), returnRegister.get());
+            emitPopScopes(scopeRegister(), 0);
+        }
+        emitReturn(returnRegister.get());
     }
 
     // Throw.
@@ -4761,9 +4891,9 @@
                     emitGetById(value.get(), value.get(), propertyNames().value);
 
                     emitLabel(returnSequence.get());
-                    bool hasFinally = emitReturnViaFinallyIfNeeded(value.get());
-                    if (!hasFinally)
-                        emitReturn(value.get());
+                    if (isInFinallyBlock())
+                        emitPopScopes(scopeRegister(), 0);
+                    emitReturn(value.get());
                 }
 
                 // Normal.
@@ -4793,157 +4923,6 @@
     emitPutById(generatorRegister(), propertyNames().builtinNames().generatorStatePrivateName(), completedState);
 }
 
-bool BytecodeGenerator::emitJumpViaFinallyIfNeeded(int targetLabelScopeDepth, Label* jumpTarget)
-{
-    ASSERT(labelScopeDepth() - targetLabelScopeDepth >= 0);
-    size_t scopeDelta = labelScopeDepth() - targetLabelScopeDepth;
-    ASSERT(scopeDelta <= m_controlFlowScopeStack.size());
-    if (!scopeDelta)
-        return false; // No finallys to thread through.
-
-    ControlFlowScope* topScope = &m_controlFlowScopeStack.last();
-    ControlFlowScope* bottomScope = &m_controlFlowScopeStack.last() - scopeDelta;
-
-    FinallyContext* innermostFinallyContext = nullptr;
-    FinallyContext* outermostFinallyContext = nullptr;
-    while (topScope > bottomScope) {
-        if (topScope->isFinallyScope()) {
-            FinallyContext* finallyContext = &topScope->finallyContext;
-            if (!innermostFinallyContext)
-                innermostFinallyContext = finallyContext;
-            outermostFinallyContext = finallyContext;
-            finallyContext->incNumberOfBreaksOrContinues();
-        }
-        --topScope;
-    }
-    if (!outermostFinallyContext)
-        return false; // No finallys to thread through.
-
-    int jumpID = bytecodeOffsetToJumpID(instructions().size());
-    int lexicalScopeIndex = labelScopeDepthToLexicalScopeIndex(targetLabelScopeDepth);
-    outermostFinallyContext->registerJump(jumpID, lexicalScopeIndex, jumpTarget);
-
-    emitSetFinallyActionToJumpID(jumpID);
-    emitJump(innermostFinallyContext->finallyLabel());
-    return true; // We'll be jumping to a finally block.
-}
-
-bool BytecodeGenerator::emitReturnViaFinallyIfNeeded(RegisterID* returnRegister)
-{
-    if (!m_controlFlowScopeStack.size())
-        return false; // No finallys to thread through.
-
-    ControlFlowScope* topScope = &m_controlFlowScopeStack.last();
-    ControlFlowScope* bottomScope = &m_controlFlowScopeStack.first();
-
-    FinallyContext* innermostFinallyContext = nullptr;
-    while (topScope >= bottomScope) {
-        if (topScope->isFinallyScope()) {
-            FinallyContext* finallyContext = &topScope->finallyContext;
-            if (!innermostFinallyContext)
-                innermostFinallyContext = finallyContext;
-            finallyContext->setHandlesReturns();
-        }
-        --topScope;
-    }
-    if (!innermostFinallyContext)
-        return false; // No finallys to thread through.
-
-    emitSetFinallyActionToReturnCompletion();
-    emitSetFinallyReturnValueRegister(returnRegister);
-    emitJump(innermostFinallyContext->finallyLabel());
-    return true; // We'll be jumping to a finally block.
-}
-
-void BytecodeGenerator::emitFinallyCompletion(FinallyContext& context, Label* normalCompletionLabel)
-{
-    // FIXME: switch the finallyActionRegister to only store int values for all CompletionTypes. This is more optimal for JIT type speculation.
-    // https://bugs.webkit.org/show_bug.cgi?id=165979
-    emitJumpIfFinallyActionIsNormalCompletion(normalCompletionLabel);
-
-    if (context.numberOfBreaksOrContinues() || context.handlesReturns()) {
-        FinallyContext* outerContext = context.outerContext();
-        if (outerContext) {
-            // We are not the outermost finally.
-            size_t numberOfJumps = context.numberOfJumps();
-            for (size_t i = 0; i < numberOfJumps; i++) {
-                RefPtr<Label> nextLabel = newLabel();
-                auto& jump = context.jumps(i);
-                emitJumpIfFinallyActionIsNotJump(jump.jumpID, nextLabel.get());
-
-                restoreScopeRegister(jump.targetLexicalScopeIndex);
-                emitSetFinallyActionToNormalCompletion();
-                emitJump(jump.targetLabel.get());
-
-                emitLabel(nextLabel.get());
-            }
-
-            bool hasBreaksOrContinuesNotCoveredByJumps = context.numberOfBreaksOrContinues() > numberOfJumps;
-            if (hasBreaksOrContinuesNotCoveredByJumps || context.handlesReturns())
-                emitJumpIfFinallyActionIsNotThrowCompletion(outerContext->finallyLabel());
-
-        } else {
-            // We are the outermost finally.
-            size_t numberOfJumps = context.numberOfJumps();
-            ASSERT(numberOfJumps == context.numberOfBreaksOrContinues());
-
-            for (size_t i = 0; i < numberOfJumps; i++) {
-                RefPtr<Label> nextLabel = newLabel();
-                auto& jump = context.jumps(i);
-                emitJumpIfFinallyActionIsNotJump(jump.jumpID, nextLabel.get());
-
-                restoreScopeRegister(jump.targetLexicalScopeIndex);
-                emitSetFinallyActionToNormalCompletion();
-                emitJump(jump.targetLabel.get());
-
-                emitLabel(nextLabel.get());
-            }
-
-            if (context.handlesReturns()) {
-                RefPtr<Label> notReturnLabel = newLabel();
-                emitJumpIfFinallyActionIsNotReturnCompletion(notReturnLabel.get());
-
-                emitWillLeaveCallFrameDebugHook();
-                emitReturn(finallyReturnValueRegister(), ReturnFrom::Finally);
-                
-                emitLabel(notReturnLabel.get());
-            }
-        }
-    }
-    emitThrow(finallyActionRegister());
-}
-
-bool BytecodeGenerator::allocateFinallyRegisters()
-{
-    if (m_finallyActionRegister)
-        return false;
-
-    ASSERT(!m_finallyReturnValueRegister);
-    m_finallyActionRegister = newTemporary();
-    m_finallyReturnValueRegister = newTemporary();
-
-    emitSetFinallyActionToNormalCompletion();
-    emitMoveEmptyValue(m_finallyReturnValueRegister.get());
-    return true;
-}
-
-void BytecodeGenerator::releaseFinallyRegisters()
-{
-    ASSERT(m_finallyActionRegister && m_finallyReturnValueRegister);
-    m_finallyActionRegister = nullptr;
-    m_finallyReturnValueRegister = nullptr;
-}
-
-void BytecodeGenerator::emitCompareFinallyActionAndJumpIf(OpcodeID compareOpcode, int value, Label* jumpTarget)
-{
-    RefPtr<RegisterID> tempRegister = newTemporary();
-    RegisterID* valueConstant = addConstantValue(JSValue(value));
-    OperandTypes operandTypes = OperandTypes(ResultType::numberTypeIsInt32(), ResultType::unknownType());
-
-    auto equivalenceResult = emitBinaryOp(compareOpcode, tempRegister.get(), valueConstant, finallyActionRegister(), operandTypes);
-    emitJumpIfTrue(equivalenceResult, jumpTarget);
-}
-
 } // namespace JSC
 
 namespace WTF {

Modified: branches/safari-603-branch/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (210010 => 210011)


--- branches/safari-603-branch/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-12-20 02:03:02 UTC (rev 210010)
+++ branches/safari-603-branch/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-12-20 02:05:52 UTC (rev 210011)
@@ -80,78 +80,22 @@
         unsigned m_padding;
     };
 
-    struct FinallyJump {
-        FinallyJump(int jumpID, int targetLexicalScopeIndex, Label* targetLabel)
-            : jumpID(jumpID)
-            , targetLexicalScopeIndex(targetLexicalScopeIndex)
-            , targetLabel(targetLabel)
-        { }
-
-        int jumpID { 0 };
-        int targetLexicalScopeIndex { 0 };
-        RefPtr<Label> targetLabel;
-    };
-
     struct FinallyContext {
-        FinallyContext() { }
-        FinallyContext(FinallyContext* outerContext, Label* finallyLabel, int finallyDepth)
-            : m_outerContext(outerContext)
-            , m_finallyLabel(finallyLabel)
-            , m_finallyDepth(finallyDepth)
-        {
-            ASSERT(!m_jumps || m_jumps->isEmpty());
-        }
-
-        FinallyContext* outerContext() const { return m_outerContext; }
-        Label* finallyLabel() const { return m_finallyLabel; }
-        int depth() const { return m_finallyDepth; }
-
-        unsigned numberOfBreaksOrContinues() const { return m_numberOfBreaksOrContinues; }
-        void incNumberOfBreaksOrContinues()
-        {
-            ASSERT(m_numberOfBreaksOrContinues < INT_MAX);
-            m_numberOfBreaksOrContinues++;
-        }
-
-        bool handlesReturns() const { return m_handlesReturns; }
-        void setHandlesReturns() { m_handlesReturns = true; }
-
-        void registerJump(int jumpID, int lexicalScopeIndex, Label* targetLabel)
-        {
-            if (!m_jumps)
-                m_jumps = std::make_unique<Vector<FinallyJump>>();
-            m_jumps->append(FinallyJump(jumpID, lexicalScopeIndex, targetLabel));
-        }
-
-        size_t numberOfJumps() const { return m_jumps ? m_jumps->size() : 0; }
-        FinallyJump& jumps(size_t i) { return (*m_jumps)[i]; }
-
-    private:
-        FinallyContext* m_outerContext { nullptr };
-        Label* m_finallyLabel { nullptr };
-        int m_finallyDepth { 0 };
-        unsigned m_numberOfBreaksOrContinues { 0 };
-        bool m_handlesReturns { false };
-        std::unique_ptr<Vector<FinallyJump>> m_jumps;
+        StatementNode* finallyBlock;
+        RegisterID* iterator;
+        ThrowableExpressionData* enumerationNode;
+        unsigned controlFlowScopeStackSize;
+        unsigned switchContextStackSize;
+        unsigned forInContextStackSize;
+        unsigned tryContextStackSize;
+        unsigned labelScopesSize;
+        unsigned lexicalScopeStackSize;
+        int finallyDepth;
+        int dynamicScopeDepth;
     };
 
     struct ControlFlowScope {
-        typedef uint8_t Type;
-        enum {
-            Label,
-            Finally
-        };
-        ControlFlowScope(Type type, int lexicalScopeIndex, FinallyContext&& finallyContext = FinallyContext())
-            : type(type)
-            , lexicalScopeIndex(lexicalScopeIndex)
-            , finallyContext(std::forward<FinallyContext>(finallyContext))
-        { }
-
-        bool isLabelScope() const { return type == Label; }
-        bool isFinallyScope() const { return type == Finally; }
-
-        Type type;
-        int lexicalScopeIndex;
+        bool isFinallyBlock;
         FinallyContext finallyContext;
     };
 
@@ -661,8 +605,7 @@
 
         RegisterID* emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode*);
 
-        enum class ReturnFrom { Normal, Finally };
-        RegisterID* emitReturn(RegisterID* src, ReturnFrom = ReturnFrom::Normal);
+        RegisterID* emitReturn(RegisterID* src);
         RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); }
 
         RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
@@ -683,6 +626,7 @@
         PassRefPtr<Label> emitJumpIfFalse(RegisterID* cond, Label* target);
         PassRefPtr<Label> emitJumpIfNotFunctionCall(RegisterID* cond, Label* target);
         PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target);
+        void emitPopScopes(RegisterID* srcDst, int targetScopeDepth);
 
         void emitEnter();
         void emitWatchdog();
@@ -705,7 +649,6 @@
         RegisterID* emitIsMap(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSMapType); }
         RegisterID* emitIsSet(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSSetType); }
         RegisterID* emitIsObject(RegisterID* dst, RegisterID* src);
-        RegisterID* emitIsNumber(RegisterID* dst, RegisterID* src);
         RegisterID* emitIsUndefined(RegisterID* dst, RegisterID* src);
         RegisterID* emitIsEmpty(RegisterID* dst, RegisterID* src);
         RegisterID* emitIsDerivedArray(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, DerivedArrayType); }
@@ -720,30 +663,10 @@
         bool emitReadOnlyExceptionIfNeeded(const Variable&);
 
         // Start a try block. 'start' must have been emitted.
-        TryData* pushTry(Label* start, Label* handlerLabel, HandlerType);
+        TryData* pushTry(Label* start);
         // End a try block. 'end' must have been emitted.
-        void popTry(TryData*, Label* end);
-        void emitCatch(RegisterID* exceptionRegister, RegisterID* thrownValueRegister);
+        void popTryAndEmitCatch(TryData*, RegisterID* exceptionRegister, RegisterID* thrownValueRegister, Label* end, HandlerType);
 
-    private:
-        static const int CurrentLexicalScopeIndex = -2;
-        static const int OutermostLexicalScopeIndex = -1;
-
-    public:
-        void restoreScopeRegister();
-        void restoreScopeRegister(int lexicalScopeIndex);
-
-        int currentLexicalScopeIndex() const
-        {
-            int size = static_cast<int>(m_lexicalScopeStack.size());
-            ASSERT(static_cast<size_t>(size) == m_lexicalScopeStack.size());
-            ASSERT(size >= 0);
-            int index = size - 1;
-            return index;
-        }
-
-        int labelScopeDepthToLexicalScopeIndex(int labelScopeDepth);
-
         void emitThrow(RegisterID* exc)
         { 
             m_usesExceptions = true;
@@ -775,102 +698,13 @@
         void emitDebugHook(ExpressionNode*);
         void emitWillLeaveCallFrameDebugHook();
 
-        class FinallyRegistersScope {
-        public:
-            FinallyRegistersScope(BytecodeGenerator& generator, bool needFinallyRegisters = true)
-                : m_generator(generator)
-            {
-                if (needFinallyRegisters && m_generator.allocateFinallyRegisters())
-                    m_needToReleaseOnDestruction = true;
-            }
-            ~FinallyRegistersScope()
-            {
-                if (m_needToReleaseOnDestruction)
-                    m_generator.releaseFinallyRegisters();
-            }
+        bool isInFinallyBlock() { return m_finallyDepth > 0; }
 
-        private:
-            BytecodeGenerator& m_generator;
-            bool m_needToReleaseOnDestruction { false };
-        };
+        void pushFinallyControlFlowScope(StatementNode* finallyBlock);
+        void popFinallyControlFlowScope();
+        void pushIteratorCloseControlFlowScope(RegisterID* iterator, ThrowableExpressionData* enumerationNode);
+        void popIteratorCloseControlFlowScope();
 
-        RegisterID* finallyActionRegister() const
-        {
-            ASSERT(m_finallyActionRegister);
-            return m_finallyActionRegister.get();
-        }
-        RegisterID* finallyReturnValueRegister() const
-        {
-            ASSERT(m_finallyReturnValueRegister);
-            return m_finallyReturnValueRegister.get();
-        }
-
-        void emitSetFinallyActionToNormalCompletion()
-        {
-            emitMoveEmptyValue(m_finallyActionRegister.get());
-        }
-        void emitSetFinallyActionToReturnCompletion()
-        {
-            emitLoad(finallyActionRegister(), JSValue(static_cast<int>(CompletionType::Return)));
-        }
-        void emitSetFinallyActionToJumpID(int jumpID)
-        {
-            emitLoad(finallyActionRegister(), JSValue(jumpID));
-        }
-        void emitSetFinallyReturnValueRegister(RegisterID* reg)
-        {
-            emitMove(finallyReturnValueRegister(), reg);
-        }
-
-        void emitJumpIfFinallyActionIsNormalCompletion(Label* jumpTarget)
-        {
-            emitJumpIfTrue(emitIsEmpty(newTemporary(), finallyActionRegister()), jumpTarget);
-        }
-
-        void emitJumpIfFinallyActionIsNotJump(int jumpID, Label* jumpTarget)
-        {
-            emitCompareFinallyActionAndJumpIf(op_nstricteq, jumpID, jumpTarget);
-        }
-
-        void emitJumpIfFinallyActionIsReturnCompletion(Label* jumpTarget)
-        {
-            emitCompareFinallyActionAndJumpIf(op_stricteq, static_cast<int>(CompletionType::Return), jumpTarget);
-        }
-        void emitJumpIfFinallyActionIsNotReturnCompletion(Label* jumpTarget)
-        {
-            emitCompareFinallyActionAndJumpIf(op_nstricteq, static_cast<int>(CompletionType::Return), jumpTarget);
-        }
-
-        void emitJumpIfFinallyActionIsNotThrowCompletion(Label* jumpTarget)
-        {
-            emitJumpIfTrue(emitIsNumber(newTemporary(), finallyActionRegister()), jumpTarget);
-        }
-        void emitJumpIfCompletionTypeIsThrow(RegisterID* reg, Label* jumpTarget)
-        {
-            emitJumpIfFalse(emitIsNumber(newTemporary(), reg), jumpTarget);
-        }
-
-        bool emitJumpViaFinallyIfNeeded(int targetLabelScopeDepth, Label* jumpTarget);
-        bool emitReturnViaFinallyIfNeeded(RegisterID* returnRegister);
-        void emitFinallyCompletion(FinallyContext&, Label* normalCompletionLabel);
-
-    private:
-        void emitCompareFinallyActionAndJumpIf(OpcodeID compareOpcode, int value, Label* jumpTarget);
-
-        int bytecodeOffsetToJumpID(unsigned offset)
-        {
-            int jumpID = offset + static_cast<int>(CompletionType::NumberOfTypes);
-            ASSERT(jumpID >= static_cast<int>(CompletionType::NumberOfTypes));
-            return jumpID;
-        }
-
-        bool allocateFinallyRegisters();
-        void releaseFinallyRegisters();
-
-    public:
-        FinallyContext* pushFinallyControlFlowScope(Label* finallyLabel);
-        FinallyContext popFinallyControlFlowScope();
-
         void pushIndexedForInScope(RegisterID* local, RegisterID* index);
         void popIndexedForInScope(RegisterID* local);
         void pushStructureForInScope(RegisterID* local, RegisterID* index, RegisterID* property, RegisterID* enumerator);
@@ -963,6 +797,7 @@
 
         void allocateCalleeSaveSpace();
         void allocateAndEmitScope();
+        void emitComplexPopScopes(RegisterID*, ControlFlowScope* topScope, ControlFlowScope* bottomScope);
 
         typedef HashMap<double, JSValue> NumberMap;
         typedef HashMap<UniquedStringImpl*, JSString*, IdentifierRepHash> IdentifierStringMap;
@@ -1100,35 +935,6 @@
         RegisterID* m_arrowFunctionContextLexicalEnvironmentRegister { nullptr };
         RegisterID* m_promiseCapabilityRegister { nullptr };
 
-        // The spec at https://tc39.github.io/ecma262/#sec-completion-record-specification-type says
-        // that there are 5 types of completions. Conceptually, we'll set m_finallyActionRegister
-        // to one of these completion types. However, to optimize our implementation, we'll encode
-        // these type info as follows:
-        //
-        //     CompletionType::Normal   - m_finallyActionRegister is empty.
-        //     CompletionType::Break    - m_finallyActionRegister is an int JSValue jumpID.
-        //     CompletionType::Continue - m_finallyActionRegister is an int JSValue jumpID.
-        //     CompletionType::Return   - m_finallyActionRegister is the Return enum as an int JSValue.
-        //     CompletionType::Throw    - m_finallyActionRegister is the Exception object to rethrow.
-        //
-        // Hence, of the 5 completion types, only the CompletionType::Return enum value is used in
-        // our implementation. The rest are just provided for completeness.
-
-        enum class CompletionType : int {
-            Normal,
-            Break,
-            Continue,
-            Return,
-            Throw,
-
-            NumberOfTypes
-        };
-
-        RefPtr<RegisterID> m_finallyActionRegister;
-        RefPtr<RegisterID> m_finallyReturnValueRegister;
-
-        FinallyContext* m_currentFinallyContext { nullptr };
-
         SegmentedVector<RegisterID*, 16> m_localRegistersForCalleeSaveRegisters;
         SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
         SegmentedVector<RegisterID, 32> m_calleeLocals;
@@ -1143,9 +949,7 @@
         void pushLocalControlFlowScope();
         void popLocalControlFlowScope();
 
-        // FIXME: Restore overflow checking with UnsafeVectorOverflow once SegmentVector supports it. 
-        // https://bugs.webkit.org/show_bug.cgi?id=165980
-        SegmentedVector<ControlFlowScope, 16> m_controlFlowScopeStack;
+        Vector<ControlFlowScope, 0, UnsafeVectorOverflow> m_controlFlowScopeStack;
         Vector<SwitchInfo> m_switchContextStack;
         Vector<RefPtr<ForInContext>> m_forInContextStack;
         Vector<TryContext> m_tryContextStack;

Modified: branches/safari-603-branch/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (210010 => 210011)


--- branches/safari-603-branch/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2016-12-20 02:03:02 UTC (rev 210010)
+++ branches/safari-603-branch/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2016-12-20 02:05:52 UTC (rev 210011)
@@ -2998,12 +2998,8 @@
     LabelScopePtr scope = generator.continueTarget(m_ident);
     ASSERT(scope);
 
-    bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope->scopeDepth(), scope->continueTarget());
-    if (!hasFinally) {
-        int lexicalScopeIndex = generator.labelScopeDepthToLexicalScopeIndex(scope->scopeDepth());
-        generator.restoreScopeRegister(lexicalScopeIndex);
-        generator.emitJump(scope->continueTarget());
-    }
+    generator.emitPopScopes(generator.scopeRegister(), scope->scopeDepth());
+    generator.emitJump(scope->continueTarget());
 
     generator.emitProfileControlFlow(endOffset());
 }
@@ -3029,12 +3025,8 @@
     LabelScopePtr scope = generator.breakTarget(m_ident);
     ASSERT(scope);
 
-    bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope->scopeDepth(), scope->breakTarget());
-    if (!hasFinally) {
-        int lexicalScopeIndex = generator.labelScopeDepthToLexicalScopeIndex(scope->scopeDepth());
-        generator.restoreScopeRegister(lexicalScopeIndex);
-        generator.emitJump(scope->breakTarget());
-    }
+    generator.emitPopScopes(generator.scopeRegister(), scope->scopeDepth());
+    generator.emitJump(scope->breakTarget());
 
     generator.emitProfileControlFlow(endOffset());
 }
@@ -3051,14 +3043,14 @@
     RefPtr<RegisterID> returnRegister = m_value ? generator.emitNodeInTailPosition(dst, m_value) : generator.emitLoad(dst, jsUndefined());
 
     generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, divotStart(), divotEnd());
-
-    bool hasFinally = generator.emitReturnViaFinallyIfNeeded(returnRegister.get());
-    if (!hasFinally) {
-        generator.emitWillLeaveCallFrameDebugHook();
-        generator.emitReturn(returnRegister.get());
+    if (generator.isInFinallyBlock()) {
+        returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get());
+        generator.emitPopScopes(generator.scopeRegister(), 0);
     }
 
-    generator.emitProfileControlFlow(endOffset());
+    generator.emitWillLeaveCallFrameDebugHook();
+    generator.emitReturn(returnRegister.get());
+    generator.emitProfileControlFlow(endOffset()); 
     // Emitting an unreachable return here is needed in case this op_profile_control_flow is the 
     // last opcode in a CodeBlock because a CodeBlock's instructions must end with a terminal opcode.
     if (generator.vm()->controlFlowProfiler())
@@ -3287,57 +3279,32 @@
     // optimizer knows they may be jumped to from anywhere.
 
     ASSERT(m_catchBlock || m_finallyBlock);
-    BytecodeGenerator::FinallyRegistersScope finallyRegistersScope(generator, m_finallyBlock);
 
-    RefPtr<Label> catchLabel;
-    RefPtr<Label> catchEndLabel;
-    RefPtr<Label> finallyViaThrowLabel;
-    RefPtr<Label> finallyLabel;
-    RefPtr<Label> finallyEndLabel;
-
     RefPtr<Label> tryStartLabel = generator.newLabel();
     generator.emitLabel(tryStartLabel.get());
+    
+    if (m_finallyBlock)
+        generator.pushFinallyControlFlowScope(m_finallyBlock);
+    TryData* tryData = generator.pushTry(tryStartLabel.get());
 
-    if (m_finallyBlock) {
-        finallyViaThrowLabel = generator.newLabel();
-        finallyLabel = generator.newLabel();
-        finallyEndLabel = generator.newLabel();
+    generator.emitNode(dst, m_tryBlock);
 
-        generator.pushFinallyControlFlowScope(finallyLabel.get());
-    }
     if (m_catchBlock) {
-        catchLabel = generator.newLabel();
-        catchEndLabel = generator.newLabel();
-    }
-
-    Label* tryHandlerLabel = m_catchBlock ? catchLabel.get() : finallyViaThrowLabel.get();
-    HandlerType tryHandlerType = m_catchBlock ? HandlerType::Catch : HandlerType::Finally;
-    TryData* tryData = generator.pushTry(tryStartLabel.get(), tryHandlerLabel, tryHandlerType);
-
-    generator.emitNode(dst, m_tryBlock);
-
-    // The finallyActionRegister is an empty value by default, which implies CompletionType::Normal.
-    if (m_finallyBlock)
-        generator.emitJump(finallyLabel.get());
-    else
+        RefPtr<Label> catchEndLabel = generator.newLabel();
+        
+        // Normal path: jump over the catch block.
         generator.emitJump(catchEndLabel.get());
 
-    RefPtr<Label> endTryLabel = generator.emitLabel(generator.newLabel().get());
-    generator.popTry(tryData, endTryLabel.get());
-
-    if (m_catchBlock) {
         // Uncaught exception path: the catch block.
-        generator.emitLabel(catchLabel.get());
+        RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
+        RefPtr<RegisterID> exceptionRegister = generator.newTemporary();
         RefPtr<RegisterID> thrownValueRegister = generator.newTemporary();
-        RegisterID* unused = generator.newTemporary();
-        generator.emitCatch(unused, thrownValueRegister.get());
-        generator.restoreScopeRegister();
-
-        TryData* tryData = nullptr;
+        generator.popTryAndEmitCatch(tryData, exceptionRegister.get(), thrownValueRegister.get(), here.get(), HandlerType::Catch);
+        
         if (m_finallyBlock) {
             // If the catch block throws an exception and we have a finally block, then the finally
             // block should "catch" that exception.
-            tryData = generator.pushTry(catchLabel.get(), finallyViaThrowLabel.get(), HandlerType::Finally);
+            tryData = generator.pushTry(here.get());
         }
 
         generator.emitPushCatchScope(m_lexicalVariables);
@@ -3349,38 +3316,37 @@
             generator.emitNodeInTailPosition(dst, m_catchBlock);
         generator.emitLoad(thrownValueRegister.get(), jsUndefined());
         generator.emitPopCatchScope(m_lexicalVariables);
-
-        if (m_finallyBlock) {
-            generator.emitSetFinallyActionToNormalCompletion();
-            generator.emitJump(finallyLabel.get());
-            generator.popTry(tryData, finallyViaThrowLabel.get());
-        }
-
         generator.emitLabel(catchEndLabel.get());
-        generator.emitProfileControlFlow(m_catchBlock->endOffset() + 1);
     }
 
     if (m_finallyBlock) {
-        FinallyContext finallyContext = generator.popFinallyControlFlowScope();
+        RefPtr<Label> preFinallyLabel = generator.emitLabel(generator.newLabel().get());
+        
+        generator.popFinallyControlFlowScope();
 
-        // Entry to the finally block for CompletionType::Throw.
-        generator.emitLabel(finallyViaThrowLabel.get());
-        RegisterID* unused = generator.newTemporary();
-        generator.emitCatch(generator.finallyActionRegister(), unused);
-        // Setting the finallyActionRegister to the caught exception here implies CompletionType::Throw.
+        RefPtr<Label> finallyEndLabel = generator.newLabel();
 
-        // Entry to the finally block for CompletionTypes other than Throw.
-        generator.emitLabel(finallyLabel.get());
-        generator.restoreScopeRegister();
+        int finallyStartOffset = m_catchBlock ? m_catchBlock->endOffset() + 1 : m_tryBlock->endOffset() + 1;
 
-        int finallyStartOffset = m_catchBlock ? m_catchBlock->endOffset() + 1 : m_tryBlock->endOffset() + 1;
+        // Normal path: run the finally code, and jump to the end.
         generator.emitProfileControlFlow(finallyStartOffset);
         generator.emitNodeInTailPosition(dst, m_finallyBlock);
+        generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
+        generator.emitJump(finallyEndLabel.get());
 
-        generator.emitFinallyCompletion(finallyContext, finallyEndLabel.get());
+        // Uncaught exception path: invoke the finally block, then re-throw the exception.
+        RefPtr<RegisterID> exceptionRegister = generator.newTemporary();
+        RefPtr<RegisterID> thrownValueRegister = generator.newTemporary();
+        generator.popTryAndEmitCatch(tryData, exceptionRegister.get(), thrownValueRegister.get(), preFinallyLabel.get(), HandlerType::Finally);
+        generator.emitProfileControlFlow(finallyStartOffset);
+        generator.emitNodeInTailPosition(dst, m_finallyBlock);
+        generator.emitThrow(exceptionRegister.get());
+
         generator.emitLabel(finallyEndLabel.get());
         generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
-    }
+    } else
+        generator.emitProfileControlFlow(m_catchBlock->endOffset() + 1);
+
 }
 
 // ------------------------------ ScopeNode -----------------------------

Modified: branches/safari-603-branch/Source/WTF/ChangeLog (210010 => 210011)


--- branches/safari-603-branch/Source/WTF/ChangeLog	2016-12-20 02:03:02 UTC (rev 210010)
+++ branches/safari-603-branch/Source/WTF/ChangeLog	2016-12-20 02:05:52 UTC (rev 210011)
@@ -1,5 +1,21 @@
 2016-12-19  Babak Shafiei  <[email protected]>
 
+        Merge r210010.
+
+    2016-12-19  Mark Lam  <[email protected]>
+
+            Rolling out r209974 and r209952. They break some websites in mysterious ways. Step 2: Rollout r209952.
+            https://bugs.webkit.org/show_bug.cgi?id=166049
+
+            Not reviewed.
+
+            * wtf/SegmentedVector.h:
+            (WTF::SegmentedVector::last):
+            (WTF::SegmentedVector::first): Deleted.
+            (WTF::SegmentedVector::takeLast): Deleted.
+
+2016-12-19  Babak Shafiei  <[email protected]>
+
         Merge patch for rdar://problem/29466493.
 
     2016-12-19  Dean Jackson  <[email protected]>

Modified: branches/safari-603-branch/Source/WTF/wtf/SegmentedVector.h (210010 => 210011)


--- branches/safari-603-branch/Source/WTF/wtf/SegmentedVector.h	2016-12-20 02:03:02 UTC (rev 210010)
+++ branches/safari-603-branch/Source/WTF/wtf/SegmentedVector.h	2016-12-20 02:05:52 UTC (rev 210011)
@@ -127,17 +127,9 @@
             return at(index);
         }
 
-        T& first() { return at(0); }
-        const T& first() const { return at(0); }
-        T& last() { return at(size() - 1); }
-        const T& last() const { return at(size() - 1); }
-
-        T takeLast()
+        T& last()
         {
-            ASSERT_WITH_SECURITY_IMPLICATION(!isEmpty());
-            T result = WTFMove(last());
-            --m_size;
-            return result;
+            return at(size() - 1);
         }
 
         template<typename... Args>
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to