<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[210011] branches/safari-603-branch</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/210011">210011</a></dd>
<dt>Author</dt> <dd>bshafiei@apple.com</dd>
<dt>Date</dt> <dd>2016-12-19 18:05:52 -0800 (Mon, 19 Dec 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merged <a href="http://trac.webkit.org/projects/webkit/changeset/210010">r210010</a>.  rdar://problem/29745006</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari603branchJSTestsChangeLog">branches/safari-603-branch/JSTests/ChangeLog</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreChangeLog">branches/safari-603-branch/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCorebytecodeHandlerInfoh">branches/safari-603-branch/Source/JavaScriptCore/bytecode/HandlerInfo.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCorebytecompilerBytecodeGeneratorh">branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCorebytecompilerNodesCodegencpp">branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</a></li>
<li><a href="#branchessafari603branchSourceWTFChangeLog">branches/safari-603-branch/Source/WTF/ChangeLog</a></li>
<li><a href="#branchessafari603branchSourceWTFwtfSegmentedVectorh">branches/safari-603-branch/Source/WTF/wtf/SegmentedVector.h</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#branchessafari603branchJSTestsstressdeeplynestedfinallysjs">branches/safari-603-branch/JSTests/stress/deeply-nested-finallys.js</a></li>
<li><a href="#branchessafari603branchJSTestsstresstestfinallyjs">branches/safari-603-branch/JSTests/stress/test-finally.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari603branchJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/JSTests/ChangeLog (210010 => 210011)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2016-12-19  Babak Shafiei  &lt;bshafiei@apple.com&gt;
+
+        Merge r210010.
+
+    2016-12-19  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+            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.
+
</ins><span class="cx"> 2016-12-16  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         De-duplicate finally blocks.
</span></span></pre></div>
<a id="branchessafari603branchJSTestsstressdeeplynestedfinallysjs"></a>
<div class="delfile"><h4>Deleted: branches/safari-603-branch/JSTests/stress/deeply-nested-finallys.js (210010 => 210011)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,78 +0,0 @@
</span><del>-// 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();
</del></span></pre></div>
<a id="branchessafari603branchJSTestsstresstestfinallyjs"></a>
<div class="delfile"><h4>Deleted: branches/safari-603-branch/JSTests/stress/test-finally.js (210010 => 210011)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,1018 +0,0 @@
</span><del>-// 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 = &quot;NothingReturned&quot;;
-let NothingThrown = &quot;NothingThrown&quot;;
-
-function assertResults(expectedSteps, expectedReturned, expectedThrown) {
-    let stepsMismatch = (steps != expectedSteps);
-    let returnedMismatch = (returned != expectedReturned);
-    let thrownMismatch = (thrown != expectedThrown &amp;&amp; !(&quot;&quot; + thrown).startsWith(&quot;&quot; + expectedThrown));
-
-    if (stepsMismatch || returnedMismatch || thrownMismatch) {
-        print(&quot;FAILED Test @ line &quot; + testLineNumber + &quot;:&quot;);
-        print(&quot;   Actual:   steps: &quot; + steps + &quot;, returned: &quot; + returned + &quot;, thrown: '&quot; + thrown + &quot;'&quot;);
-        print(&quot;   Expected: steps: &quot; + expectedSteps + &quot;, returned: &quot; + expectedReturned + &quot;, thrown: '&quot; + expectedThrown + &quot;'&quot;);
-    }
-    if (stepsMismatch)
-        throw &quot;FAILED Test @ line &quot; + testLineNumber + &quot;: steps do not match: expected ='&quot; + expectedSteps + &quot;' actual='&quot; + steps + &quot;'&quot;;
-    if (returnedMismatch)
-        throw &quot;FAILED Test @ line &quot; + testLineNumber + &quot;: returned value does not match: expected ='&quot; + expectedReturned + &quot;' actual='&quot; + returned + &quot;'&quot;;
-    if (thrownMismatch)
-        throw &quot;FAILED Test @ line &quot; + testLineNumber + &quot;: thrown value does does not match: expected ='&quot; + expectedThrown + &quot;' actual='&quot; + thrown + &quot;'&quot;;
-}
-
-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(() =&gt;  {
-    try {
-        append(&quot;t2&quot;);
-        for (var i = 0; i &lt; 2; i++) {
-            try {
-            } catch(a) {
-                append(&quot;c1&quot;);
-            } finally {
-                append(&quot;f1&quot;);
-            }
-        }
-    } catch(b) {
-        append(&quot;c2&quot;);
-    } finally {
-        append(&quot;f2&quot;);
-    }
-
-}, &quot;t2,f1,f1,f2&quot;, undefined, NothingThrown);
-
-// Test CompletionType::Normal.
-test(() =&gt;  {
-    try {
-        append(&quot;t2&quot;);
-        for (var i = 0; i &lt; 2; i++) {
-            try {
-                append(&quot;t1&quot;);
-            } catch(a) {
-                append(&quot;c1&quot;);
-            } finally {
-                append(&quot;f1&quot;);
-            }
-        }
-    } catch(b) {
-        append(&quot;c2&quot;);
-    } finally {
-        append(&quot;f2&quot;);
-    }
-
-}, &quot;t2,t1,f1,t1,f1,f2&quot;, undefined, NothingThrown);
-
-// Test CompletionType::Break.
-test(() =&gt;  {
-    try {
-        append(&quot;t2&quot;);
-        for (var i = 0; i &lt; 2; i++) {
-            try {
-                append(&quot;t1&quot;);
-                break;
-            } catch(a) {
-                append(&quot;c1&quot;);
-            } finally {
-                append(&quot;f1&quot;);
-            }
-        }
-    } catch(b) {
-        append(&quot;c2&quot;);
-    } finally {
-        append(&quot;f2&quot;);
-    }
-
-}, &quot;t2,t1,f1,f2&quot;, undefined, NothingThrown);
-
-// Test CompletionType::Continue.
-test(() =&gt;  {
-    try {
-        append(&quot;t2&quot;);
-        for (var i = 0; i &lt; 2; i++) {
-            try {
-                append(&quot;t1&quot;);
-                continue;
-            } catch(a) {
-                append(&quot;c1&quot;);
-            } finally {
-                append(&quot;f1&quot;);
-            }
-        }
-    } catch(b) {
-        append(&quot;c2&quot;);
-    } finally {
-        append(&quot;f2&quot;);
-    }
-
-}, &quot;t2,t1,f1,t1,f1,f2&quot;, undefined, NothingThrown);
-
-// Test CompletionType::Return.
-test(() =&gt;  {
-    try {
-        append(&quot;t2&quot;);
-        for (var i = 0; i &lt; 2; i++) {
-            try {
-                append(&quot;t1&quot;);
-                return;
-            } catch(a) {
-                append(&quot;c1&quot;);
-            } finally {
-                append(&quot;f1&quot;);
-            }
-        }
-    } catch(b) {
-        append(&quot;c2&quot;);
-    } finally {
-        append(&quot;f2&quot;);
-    }
-
-}, &quot;t2,t1,f1,f2&quot;, undefined, NothingThrown);
-
-// Test CompletionType::Throw.
-test(() =&gt;  {
-    try {
-        append(&quot;t2&quot;);
-        for (var i = 0; i &lt; 2; i++) {
-            try {
-                append(&quot;t1&quot;);
-                throw { };
-            } catch(a) {
-                append(&quot;c1&quot;);
-            } finally {
-                append(&quot;f1&quot;);
-            }
-        }
-    } catch(b) {
-        append(&quot;c2&quot;);
-    } finally {
-        append(&quot;f2&quot;);
-    }
-
-}, &quot;t2,t1,c1,f1,t1,c1,f1,f2&quot;, undefined, NothingThrown);
-
-// Test CompletionType::Normal in a for-of loop.
-test(() =&gt;  {
-    let arr = [1, 2];
-    try {
-        append(&quot;t2&quot;);
-        for (let x of arr) {
-            try {
-                append(&quot;t1&quot;);
-            } catch(a) {
-                append(&quot;c1&quot;);
-            } finally {
-                append(&quot;f1&quot;);
-            }
-        }
-    } catch(b) {
-        append(&quot;c2&quot;);
-    } finally {
-        append(&quot;f2&quot;);
-    }
-
-}, &quot;t2,t1,f1,t1,f1,f2&quot;, undefined, NothingThrown);
-
-// Test CompletionType::Break in a for-of loop.
-test(() =&gt;  {
-    let arr = [1, 2];
-    try {
-        append(&quot;t2&quot;);
-        for (let x of arr) {
-            try {
-                append(&quot;t1&quot;);
-                break;
-            } catch(a) {
-                append(&quot;c1&quot;);
-            } finally {
-                append(&quot;f1&quot;);
-            }
-        }
-    } catch(b) {
-        append(&quot;c2&quot;);
-    } finally {
-        append(&quot;f2&quot;);
-    }
-
-}, &quot;t2,t1,f1,f2&quot;, undefined, NothingThrown);
-
-// Test CompletionType::Continue in a for-of loop.
-test(() =&gt;  {
-    let arr = [1, 2];
-    try {
-        append(&quot;t2&quot;);
-        for (let x of arr) {
-            try {
-                append(&quot;t1&quot;);
-                continue;
-            } catch(a) {
-                append(&quot;c1&quot;);
-            } finally {
-                append(&quot;f1&quot;);
-            }
-        }
-    } catch(b) {
-        append(&quot;c2&quot;);
-    } finally {
-        append(&quot;f2&quot;);
-    }
-
-}, &quot;t2,t1,f1,t1,f1,f2&quot;, undefined, NothingThrown);
-
-// Test CompletionType::Return in a for-of loop.
-test(() =&gt;  {
-    let arr = [1, 2];
-    try {
-        append(&quot;t2&quot;);
-        for (let x of arr) {
-            try {
-                append(&quot;t1&quot;);
-                return;
-            } catch(a) {
-                append(&quot;c1&quot;);
-            } finally {
-                append(&quot;f1&quot;);
-            }
-        }
-    } catch(b) {
-        append(&quot;c2&quot;);
-    } finally {
-        append(&quot;f2&quot;);
-    }
-
-}, &quot;t2,t1,f1,f2&quot;, undefined, NothingThrown);
-
-// Test CompletionType::Throw in a for-of loop.
-test(() =&gt;  {
-    let arr = [1, 2];
-    try {
-        append(&quot;t2&quot;);
-        for (let x of arr) {
-            try {
-                append(&quot;t1&quot;);
-                throw { };
-            } catch(a) {
-                append(&quot;c1&quot;);
-            } finally {
-                append(&quot;f1&quot;);
-            }
-        }
-    } catch(b) {
-        append(&quot;c2&quot;);
-    } finally {
-        append(&quot;f2&quot;);
-    }
-
-}, &quot;t2,t1,c1,f1,t1,c1,f1,f2&quot;, undefined, NothingThrown);
-
-
-// No abrupt completions.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    try {
-        append(&quot;b&quot;);
-    } finally {
-        append(&quot;c&quot;);
-    }   
-    append(&quot;d&quot;);
-    return 400;
-
-}, &quot;a,b,c,d&quot;, 400, NothingThrown);
-
-
-// Return after a. Should not execute any finally blocks, and return a's result.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    return 100;
-    try {
-        append(&quot;b&quot;);
-        return 200;
-        try {
-            append(&quot;c&quot;);
-            return 300;
-        } finally {
-            append(&quot;d&quot;);
-        }
-        append(&quot;e&quot;);
-        return 500;
-    } finally {
-        append(&quot;f&quot;);
-    }   
-    append(&quot;g&quot;);
-    return 700;
-
-}, &quot;a&quot;, 100, NothingThrown);
-
-// Return after b. Should execute finally block f only, and return b's result.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    try {
-        append(&quot;b&quot;);
-        return 200;
-        try {
-            append(&quot;c&quot;);
-            return 300;
-        } finally {
-            append(&quot;d&quot;);
-        }
-        append(&quot;e&quot;);
-        return 500;
-    } finally {
-        append(&quot;f&quot;);
-    }   
-    append(&quot;g&quot;);
-    return 700;
-
-}, &quot;a,b,f&quot;, 200, NothingThrown);
-
-// Return after c. Should execute finally blocks d and f, and return c's result.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    try {
-        append(&quot;b&quot;);
-        try {
-            append(&quot;c&quot;);
-            return 300;
-        } finally {
-            append(&quot;d&quot;);
-        }
-        append(&quot;e&quot;);
-        return 500;
-    } finally {
-        append(&quot;f&quot;);
-    }   
-    append(&quot;g&quot;);
-    return 700;
-
-}, &quot;a,b,c,d,f&quot;, 300, NothingThrown);
-
-// Return after c and d. Should execute finally blocks d and f, and return last return value from d.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    try {
-        append(&quot;b&quot;);
-        try {
-            append(&quot;c&quot;);
-            return 300;
-        } finally {
-            append(&quot;d&quot;);
-            return 400;
-        }
-        append(&quot;e&quot;);
-        return 500;
-    } finally {
-        append(&quot;f&quot;);
-    }   
-    append(&quot;g&quot;);
-    return 700;
-
-}, &quot;a,b,c,d,f&quot;, 400, NothingThrown);
-
-// Return after c, d, and f. Should execute finally blocks d and f, and return last return value from f.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    try {
-        append(&quot;b&quot;);
-        try {
-            append(&quot;c&quot;);
-            return 300;
-        } finally {
-            append(&quot;d&quot;);
-            return 400;
-        }
-        append(&quot;e&quot;);
-        return 500;
-    } finally {
-        append(&quot;f&quot;);
-        return 600;
-    }   
-    append(&quot;g&quot;);
-    return 700;
-
-}, &quot;a,b,c,d,f&quot;, 600, NothingThrown);
-
-// Return after g.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    try {
-        append(&quot;b&quot;);
-        try {
-            append(&quot;c&quot;);
-        } finally {
-            append(&quot;d&quot;);
-        }
-        append(&quot;e&quot;);
-    } finally {
-        append(&quot;f&quot;);
-    }   
-    append(&quot;g&quot;);
-    return 700;
-
-}, &quot;a,b,c,d,e,f,g&quot;, 700, NothingThrown);
-
-// Throw after a.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    throw 100;
-    try {
-        append(&quot;b&quot;);
-        throw 200;
-        try {
-            append(&quot;c&quot;);
-            throw 300;
-        } finally {
-            append(&quot;d&quot;);
-        }
-        append(&quot;e&quot;);
-        throw 500;
-    } finally {
-        append(&quot;f&quot;);
-    }   
-    append(&quot;g&quot;);
-    throw 700;
-
-}, &quot;a&quot;, NothingReturned, 100);
-
-// Throw after b.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    try {
-        append(&quot;b&quot;);
-        throw 200;
-        try {
-            append(&quot;c&quot;);
-            throw 300;
-        } finally {
-            append(&quot;d&quot;);
-        }
-        append(&quot;e&quot;);
-        throw 500;
-    } finally {
-        append(&quot;f&quot;);
-    }   
-    append(&quot;g&quot;);
-    throw 700;
-
-}, &quot;a,b,f&quot;, NothingReturned, 200);
-
-// Throw after c.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    try {
-        append(&quot;b&quot;);
-        try {
-            append(&quot;c&quot;);
-            throw 300;
-        } finally {
-            append(&quot;d&quot;);
-        }
-        append(&quot;e&quot;);
-        throw 500;
-    } finally {
-        append(&quot;f&quot;);
-    }   
-    append(&quot;g&quot;);
-    throw 700;
-
-}, &quot;a,b,c,d,f&quot;, NothingReturned, 300);
-
-// Throw after c and d.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    try {
-        append(&quot;b&quot;);
-        try {
-            append(&quot;c&quot;);
-            throw 300;
-        } finally {
-            append(&quot;d&quot;);
-            throw 400;
-        }
-        append(&quot;e&quot;);
-        throw 500;
-    } finally {
-        append(&quot;f&quot;);
-    }   
-    append(&quot;g&quot;);
-    throw 700;
-
-}, &quot;a,b,c,d,f&quot;, NothingReturned, 400);
-
-// Throw after c, d, and f.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    try {
-        append(&quot;b&quot;);
-        try {
-            append(&quot;c&quot;);
-            throw 300;
-        } finally {
-            append(&quot;d&quot;);
-            throw 400;
-        }
-        append(&quot;e&quot;);
-        throw 500;
-    } finally {
-        append(&quot;f&quot;);
-        throw 600;
-    }   
-    append(&quot;g&quot;);
-    return 700;
-
-}, &quot;a,b,c,d,f&quot;, NothingReturned, 600);
-
-// Throw after g.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    try {
-        append(&quot;b&quot;);
-        try {
-            append(&quot;c&quot;);
-        } finally {
-            append(&quot;d&quot;);
-        }
-        append(&quot;e&quot;);
-    } finally {
-        append(&quot;f&quot;);
-    }   
-    append(&quot;g&quot;);
-    throw 700;
-
-}, &quot;a,b,c,d,e,f,g&quot;, NothingReturned, 700);
-
-// Throw after b with catch at z.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    try {
-        append(&quot;b&quot;);
-        throw 200;
-        try {
-            append(&quot;c&quot;);
-            throw 300;
-        } finally {
-            append(&quot;d&quot;);
-        }
-        append(&quot;e&quot;);
-        throw 500;
-    } catch (e) {
-        append(&quot;z&quot;);
-    } finally {
-        append(&quot;f&quot;);
-    }   
-    append(&quot;g&quot;);
-    return 700;
-
-}, &quot;a,b,z,f,g&quot;, 700, NothingThrown);
-
-// Throw after b with catch at z and rethrow at z.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    try {
-        append(&quot;b&quot;);
-        throw 200;
-        try {
-            append(&quot;c&quot;);
-            throw 300;
-        } finally {
-            append(&quot;d&quot;);
-        }
-        append(&quot;e&quot;);
-        throw 500;
-    } catch (e) {
-        append(&quot;z&quot;);
-        throw 5000;
-    } finally {
-        append(&quot;f&quot;);
-    }   
-    append(&quot;g&quot;);
-    return 700;
-
-}, &quot;a,b,z,f&quot;, NothingReturned, 5000);
-
-// Throw after c with catch at y and z.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    try {
-        append(&quot;b&quot;);
-        try {
-            append(&quot;c&quot;);
-            throw 300;
-        } catch (e) {
-            append(&quot;y&quot;);
-        } finally {
-            append(&quot;d&quot;);
-        }
-        append(&quot;e&quot;);
-    } catch (e) {
-        append(&quot;z&quot;);
-    } finally {
-        append(&quot;f&quot;);
-    }   
-    append(&quot;g&quot;);
-    return 700;
-
-}, &quot;a,b,c,y,d,e,f,g&quot;, 700, NothingThrown);
-
-// Throw after c with catch at y and z, and rethrow at y.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    try {
-        append(&quot;b&quot;);
-        try {
-            append(&quot;c&quot;);
-            throw 300;
-        } catch (e) {
-            append(&quot;y&quot;);
-            throw 3000;
-        } finally {
-            append(&quot;d&quot;);
-        }
-        append(&quot;e&quot;);
-    } catch (e) {
-        append(&quot;z&quot;);
-    } finally {
-        append(&quot;f&quot;);
-    }   
-    append(&quot;g&quot;);
-    return 700;
-
-}, &quot;a,b,c,y,d,z,f,g&quot;, 700, NothingThrown);
-
-// Throw after c with catch at y and z, and rethrow at y and z.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    try {
-        append(&quot;b&quot;);
-        try {
-            append(&quot;c&quot;);
-            throw 300;
-        } catch (e) {
-            append(&quot;y&quot;);
-            throw 3000;
-        } finally {
-            append(&quot;d&quot;);
-        }
-        append(&quot;e&quot;);
-    } catch (e) {
-        append(&quot;z&quot;);
-        throw 5000;
-    } finally {
-        append(&quot;f&quot;);
-    }   
-    append(&quot;g&quot;);
-    return 700;
-
-}, &quot;a,b,c,y,d,z,f&quot;, NothingReturned, 5000);
-
-// Throw after c with catch at y and z, and rethrow at y, z, and f.
-test(() =&gt; {
-    append(&quot;a&quot;);
-    try {
-        append(&quot;b&quot;);
-        try {
-            append(&quot;c&quot;);
-            throw 300;
-        } catch (e) {
-            append(&quot;y&quot;);
-            throw 3000;
-        } finally {
-            append(&quot;d&quot;);
-        }
-        append(&quot;e&quot;);
-    } catch (e) {
-        append(&quot;z&quot;);
-        throw 5000;
-    } finally {
-        append(&quot;f&quot;);
-        throw 600;
-    }   
-    append(&quot;g&quot;);
-    return 700;
-
-}, &quot;a,b,c,y,d,z,f&quot;, NothingReturned, 600);
-
-// No throw or return in for-of loop.
-test(() =&gt; {
-    class TestIterator {
-        constructor() {
-            append(&quot;c&quot;);
-            this.i = 0;
-        }
-        next() {
-            append(&quot;n&quot;);
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append(&quot;r&quot;);
-            return { }
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new TestIterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-    }
-    append(&quot;x&quot;);
-    return 200;
-
-}, &quot;c,n,0,n,1,n,2,n,x&quot;, 200, NothingThrown);
-
-// Break in for-of loop.
-test(() =&gt; {
-    class TestIterator {
-        constructor() {
-            append(&quot;c&quot;);
-            this.i = 0;
-        }
-        next() {
-            append(&quot;n&quot;);
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append(&quot;r&quot;);
-            return { }
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new TestIterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-        if (element == 1)
-            break;
-    }
-    append(&quot;x&quot;);
-    return 200;
-
-}, &quot;c,n,0,n,1,r,x&quot;, 200, NothingThrown);
-
-// Break in for-of loop with throw in Iterator.return().
-test(() =&gt; {
-    class Iterator {
-        constructor() {
-            append(&quot;c&quot;);
-            this.i = 0;
-        }
-        next() {
-            append(&quot;n&quot;);
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append(&quot;r&quot;);
-            throw 300;
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new Iterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-        if (element == 1)
-            break;
-    }
-    append(&quot;x&quot;);
-    return 200;
-
-}, &quot;c,n,0,n,1,r&quot;, NothingReturned, 300);
-
-// Break in for-of loop with Iterator.return() returning a non object.
-test(() =&gt; {
-    class Iterator {
-        constructor() {
-            append(&quot;c&quot;);
-            this.i = 0;
-        }
-        next() {
-            append(&quot;n&quot;);
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append(&quot;r&quot;);
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new Iterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-        if (element == 1)
-            break;
-    }
-    append(&quot;x&quot;);
-    return 200;
-
-}, &quot;c,n,0,n,1,r&quot;, NothingReturned, 'TypeError');
-
-// Return in for-of loop.
-test(() =&gt; {
-    class TestIterator {
-        constructor() {
-            append(&quot;c&quot;);
-            this.i = 0;
-        }
-        next() {
-            append(&quot;n&quot;);
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append(&quot;r&quot;);
-            return { }
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new TestIterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-        if (element == 1)
-            return 100;
-    }
-    append(&quot;x&quot;);
-    return 200;
-
-}, &quot;c,n,0,n,1,r&quot;, 100, NothingThrown);
-
-// Return in for-of loop with throw in Iterator.return().
-test(() =&gt; {
-    class Iterator {
-        constructor() {
-            append(&quot;c&quot;);
-            this.i = 0;
-        }
-        next() {
-            append(&quot;n&quot;);
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append(&quot;r&quot;);
-            throw 300;
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new Iterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-        if (element == 1)
-            return 100;
-    }
-    append(&quot;x&quot;);
-    return 200;
-
-}, &quot;c,n,0,n,1,r&quot;, NothingReturned, 300);
-
-// Return in for-of loop with Iterator.return() returning a non object.
-test(() =&gt; {
-    class Iterator {
-        constructor() {
-            append(&quot;c&quot;);
-            this.i = 0;
-        }
-        next() {
-            append(&quot;n&quot;);
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append(&quot;r&quot;);
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new Iterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-        if (element == 1)
-            return 100;
-    }
-    append(&quot;x&quot;);
-    return 200;
-
-}, &quot;c,n,0,n,1,r&quot;, NothingReturned, 'TypeError');
-
-
-// Throw in for-of loop.
-test(() =&gt; {
-    class Iterator {
-        constructor() {
-            append(&quot;c&quot;);
-            this.i = 0;
-        }
-        next() {
-            append(&quot;n&quot;);
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append(&quot;r&quot;);
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new Iterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-        if (element == 1)
-            throw 100;
-    }
-    append(&quot;x&quot;);
-    return 200;
-
-}, &quot;c,n,0,n,1,r&quot;, NothingReturned, 100);
-
-// Throw in for-of loop with throw in Iterator.return().
-test(() =&gt; {
-    class Iterator {
-        constructor() {
-            append(&quot;c&quot;);
-            this.i = 0;
-        }
-        next() {
-            append(&quot;n&quot;);
-            let done = (this.i == 3);
-            return { done, value: this.i++ };
-        }
-        return() {
-            append(&quot;r&quot;);
-            throw 300;
-        }
-    }
-
-    var arr = [];
-    arr[Symbol.iterator] = function() {
-        return new Iterator();
-    }
-
-    for (var element of arr) {
-        append(element);
-        if (element == 1)
-            throw 100;
-    }
-    append(&quot;x&quot;);
-    return 200;
-
-}, &quot;c,n,0,n,1,r&quot;, NothingReturned, 100);
</del></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/ChangeLog (210010 => 210011)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/ChangeLog        2016-12-20 02:03:02 UTC (rev 210010)
+++ branches/safari-603-branch/Source/JavaScriptCore/ChangeLog        2016-12-20 02:05:52 UTC (rev 210011)
</span><span class="lines">@@ -1,5 +1,86 @@
</span><span class="cx"> 2016-12-19  Babak Shafiei  &lt;bshafiei@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r210010.
+
+    2016-12-19  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+            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  &lt;bshafiei@apple.com&gt;
+
</ins><span class="cx">         Merge r210007.
</span><span class="cx"> 
</span><span class="cx">     2016-12-19  Mark Lam  &lt;mark.lam@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCorebytecodeHandlerInfoh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/bytecode/HandlerInfo.h (210010 => 210011)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/bytecode/HandlerInfo.h        2016-12-20 02:03:02 UTC (rev 210010)
+++ branches/safari-603-branch/Source/JavaScriptCore/bytecode/HandlerInfo.h        2016-12-20 02:05:52 UTC (rev 210011)
</span><span class="lines">@@ -31,9 +31,9 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> enum class HandlerType {
</span><del>-    Catch = 0,
-    Finally = 1,
-    SynthesizedCatch = 2,
</del><ins>+    Illegal = 0,
+    Catch = 1,
+    Finally = 2,
</ins><span class="cx">     SynthesizedFinally = 3
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -53,8 +53,6 @@
</span><span class="cx">             return &quot;catch&quot;;
</span><span class="cx">         case HandlerType::Finally:
</span><span class="cx">             return &quot;finally&quot;;
</span><del>-        case HandlerType::SynthesizedCatch:
-            return &quot;synthesized catch&quot;;
</del><span class="cx">         case HandlerType::SynthesizedFinally:
</span><span class="cx">             return &quot;synthesized finally&quot;;
</span><span class="cx">         default:
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (210010 => 210011)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-12-20 02:03:02 UTC (rev 210010)
+++ branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-12-20 02:05:52 UTC (rev 210011)
</span><span class="lines">@@ -156,6 +156,7 @@
</span><span class="cx">         if (end &lt;= start)
</span><span class="cx">             continue;
</span><span class="cx">         
</span><ins>+        ASSERT(range.tryData-&gt;handlerType != HandlerType::Illegal);
</ins><span class="cx">         UnlinkedHandlerInfo info(static_cast&lt;uint32_t&gt;(start), static_cast&lt;uint32_t&gt;(end),
</span><span class="cx">             static_cast&lt;uint32_t&gt;(range.tryData-&gt;target-&gt;bind()), range.tryData-&gt;handlerType);
</span><span class="cx">         m_codeBlock-&gt;addExceptionHandler(info);
</span><span class="lines">@@ -679,25 +680,21 @@
</span><span class="cx">     // because a function's default parameter ExpressionNodes will use temporary registers.
</span><span class="cx">     pushTDZVariables(*parentScopeTDZVariables, TDZCheckOptimization::DoNotOptimize, TDZRequirement::UnderTDZ);
</span><span class="cx"> 
</span><del>-    RefPtr&lt;Label&gt; catchLabel = newLabel();
</del><span class="cx">     TryData* tryFormalParametersData = nullptr;
</span><del>-    bool needTryCatch = isAsyncFunctionWrapperParseMode(parseMode) &amp;&amp; !isSimpleParameterList;
-    if (needTryCatch) {
</del><ins>+    if (isAsyncFunctionWrapperParseMode(parseMode) &amp;&amp; !isSimpleParameterList) {
</ins><span class="cx">         RefPtr&lt;Label&gt; tryFormalParametersStart = emitLabel(newLabel().get());
</span><del>-        tryFormalParametersData = pushTry(tryFormalParametersStart.get(), catchLabel.get(), HandlerType::SynthesizedCatch);
</del><ins>+        tryFormalParametersData = pushTry(tryFormalParametersStart.get());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     initializeDefaultParameterValuesAndSetupFunctionScopeStack(parameters, isSimpleParameterList, functionNode, functionSymbolTable, symbolTableConstantIndex, captures, shouldCreateArgumentsVariableInParameterScope);
</span><span class="cx"> 
</span><del>-    if (needTryCatch) {
</del><ins>+    if (isAsyncFunctionWrapperParseMode(parseMode) &amp;&amp; !isSimpleParameterList) {
</ins><span class="cx">         RefPtr&lt;Label&gt; didNotThrow = newLabel();
</span><span class="cx">         emitJump(didNotThrow.get());
</span><del>-        emitLabel(catchLabel.get());
-        popTry(tryFormalParametersData, catchLabel.get());
-
</del><ins>+        RefPtr&lt;RegisterID&gt; exception = newTemporary();
</ins><span class="cx">         RefPtr&lt;RegisterID&gt; thrownValue = newTemporary();
</span><del>-        RegisterID* unused = newTemporary();
-        emitCatch(unused, thrownValue.get());
</del><ins>+        RefPtr&lt;Label&gt; catchHere = emitLabel(newLabel().get());
+        popTryAndEmitCatch(tryFormalParametersData, exception.get(), thrownValue.get(), catchHere.get(), HandlerType::Catch);
</ins><span class="cx"> 
</span><span class="cx">         // return promiseCapability.@reject(thrownValue)
</span><span class="cx">         RefPtr&lt;RegisterID&gt; reject = emitGetById(newTemporary(), promiseCapabilityRegister(), m_vm-&gt;propertyNames-&gt;builtinNames().rejectPrivateName());
</span><span class="lines">@@ -3496,16 +3493,16 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RegisterID* BytecodeGenerator::emitReturn(RegisterID* src, ReturnFrom from)
</del><ins>+RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
</ins><span class="cx"> {
</span><span class="cx">     if (isConstructor()) {
</span><span class="cx">         bool mightBeDerived = constructorKind() == ConstructorKind::Extends;
</span><span class="cx">         bool srcIsThis = src-&gt;index() == m_thisRegister.index();
</span><span class="cx"> 
</span><del>-        if (mightBeDerived &amp;&amp; (srcIsThis || from == ReturnFrom::Finally))
</del><ins>+        if (mightBeDerived &amp;&amp; srcIsThis)
</ins><span class="cx">             emitTDZCheck(src);
</span><span class="cx"> 
</span><del>-        if (!srcIsThis || from == ReturnFrom::Finally) {
</del><ins>+        if (!srcIsThis) {
</ins><span class="cx">             RefPtr&lt;Label&gt; isObjectLabel = newLabel();
</span><span class="cx">             emitJumpIfTrue(emitIsObject(newTemporary(), src), isObjectLabel.get());
</span><span class="cx"> 
</span><span class="lines">@@ -3683,31 +3680,82 @@
</span><span class="cx">     emitDebugHook(WillLeaveCallFrame, m_scopeNode-&gt;lastLine(), m_scopeNode-&gt;startOffset(), m_scopeNode-&gt;lineStartOffset());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-FinallyContext* BytecodeGenerator::pushFinallyControlFlowScope(Label* finallyLabel)
</del><ins>+void BytecodeGenerator::pushFinallyControlFlowScope(StatementNode* finallyBlock)
</ins><span class="cx"> {
</span><span class="cx">     // Reclaim free label scopes.
</span><span class="cx">     while (m_labelScopes.size() &amp;&amp; !m_labelScopes.last().refCount())
</span><span class="cx">         m_labelScopes.removeLast();
</span><span class="cx"> 
</span><del>-    ControlFlowScope scope(ControlFlowScope::Finally, currentLexicalScopeIndex(), FinallyContext(m_currentFinallyContext, finallyLabel, m_finallyDepth));
-    m_controlFlowScopeStack.append(WTFMove(scope));
</del><ins>+    ControlFlowScope scope;
+    scope.isFinallyBlock = true;
+    FinallyContext context = {
+        finallyBlock,
+        nullptr,
+        nullptr,
+        static_cast&lt;unsigned&gt;(m_controlFlowScopeStack.size()),
+        static_cast&lt;unsigned&gt;(m_switchContextStack.size()),
+        static_cast&lt;unsigned&gt;(m_forInContextStack.size()),
+        static_cast&lt;unsigned&gt;(m_tryContextStack.size()),
+        static_cast&lt;unsigned&gt;(m_labelScopes.size()),
+        static_cast&lt;unsigned&gt;(m_lexicalScopeStack.size()),
+        m_finallyDepth,
+        m_localScopeDepth
+    };
+    scope.finallyContext = context;
+    m_controlFlowScopeStack.append(scope);
+    m_finallyDepth++;
+}
</ins><span class="cx"> 
</span><ins>+void BytecodeGenerator::pushIteratorCloseControlFlowScope(RegisterID* iterator, ThrowableExpressionData* node)
+{
+    // Reclaim free label scopes.
+    while (m_labelScopes.size() &amp;&amp; !m_labelScopes.last().refCount())
+        m_labelScopes.removeLast();
+
+    ControlFlowScope scope;
+    scope.isFinallyBlock = true;
+    FinallyContext context = {
+        nullptr,
+        iterator,
+        node,
+        static_cast&lt;unsigned&gt;(m_controlFlowScopeStack.size()),
+        static_cast&lt;unsigned&gt;(m_switchContextStack.size()),
+        static_cast&lt;unsigned&gt;(m_forInContextStack.size()),
+        static_cast&lt;unsigned&gt;(m_tryContextStack.size()),
+        static_cast&lt;unsigned&gt;(m_labelScopes.size()),
+        static_cast&lt;unsigned&gt;(m_lexicalScopeStack.size()),
+        m_finallyDepth,
+        m_localScopeDepth
+    };
+    scope.finallyContext = context;
+    m_controlFlowScopeStack.append(scope);
</ins><span class="cx">     m_finallyDepth++;
</span><del>-    m_currentFinallyContext = &amp;m_controlFlowScopeStack.last().finallyContext;
-    return m_currentFinallyContext;
</del><span class="cx"> }
</span><span class="cx"> 
</span><del>-FinallyContext BytecodeGenerator::popFinallyControlFlowScope()
</del><ins>+void BytecodeGenerator::popFinallyControlFlowScope()
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_controlFlowScopeStack.size());
</span><del>-    ASSERT(m_controlFlowScopeStack.last().isFinallyScope());
</del><ins>+    ASSERT(m_controlFlowScopeStack.last().isFinallyBlock);
+    ASSERT(m_controlFlowScopeStack.last().finallyContext.finallyBlock);
+    ASSERT(!m_controlFlowScopeStack.last().finallyContext.iterator);
+    ASSERT(!m_controlFlowScopeStack.last().finallyContext.enumerationNode);
</ins><span class="cx">     ASSERT(m_finallyDepth &gt; 0);
</span><del>-    ASSERT(m_currentFinallyContext);
-    m_currentFinallyContext = m_currentFinallyContext-&gt;outerContext();
</del><ins>+    m_controlFlowScopeStack.removeLast();
</ins><span class="cx">     m_finallyDepth--;
</span><del>-    return m_controlFlowScopeStack.takeLast().finallyContext;
</del><span class="cx"> }
</span><span class="cx"> 
</span><ins>+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 &gt; 0);
+    m_controlFlowScopeStack.removeLast();
+    m_finallyDepth--;
+}
+
</ins><span class="cx"> LabelScopePtr BytecodeGenerator::breakTarget(const Identifier&amp; name)
</span><span class="cx"> {
</span><span class="cx">     // Reclaim free label scopes.
</span><span class="lines">@@ -3805,12 +3853,162 @@
</span><span class="cx">     m_topMostScope = addVar();
</span><span class="cx">     emitMove(m_topMostScope, scopeRegister());
</span><span class="cx"> }
</span><ins>+    
+void BytecodeGenerator::emitComplexPopScopes(RegisterID* scope, ControlFlowScope* topScope, ControlFlowScope* bottomScope)
+{
+    while (topScope &gt; bottomScope) {
+        // First we count the number of dynamic scopes we need to remove to get
+        // to a finally block.
+        int numberOfNormalScopes = 0;
+        while (topScope &gt; bottomScope) {
+            if (topScope-&gt;isFinallyBlock)
+                break;
+            ++numberOfNormalScopes;
+            --topScope;
+        }
</ins><span class="cx"> 
</span><del>-TryData* BytecodeGenerator::pushTry(Label* start, Label* handlerLabel, HandlerType handlerType)
</del><ins>+        if (numberOfNormalScopes) {
+            // We need to remove a number of dynamic scopes to get to the next
+            // finally block
+            RefPtr&lt;RegisterID&gt; 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&lt;ControlFlowScope&gt; savedControlFlowScopeStack;
+        Vector&lt;SwitchInfo&gt; savedSwitchContextStack;
+        Vector&lt;RefPtr&lt;ForInContext&gt;&gt; savedForInContextStack;
+        Vector&lt;TryContext&gt; poppedTryContexts;
+        Vector&lt;LexicalScopeStackEntry&gt; savedLexicalScopeStack;
+        LabelScopeStore savedLabelScopes;
+        while (topScope &gt; bottomScope &amp;&amp; topScope-&gt;isFinallyBlock) {
+            RefPtr&lt;Label&gt; 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-&gt;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() &gt; 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() &gt; 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&lt;Label&gt; afterFinally = emitLabel(newLabel().get());
+            
+            // Restore the state of the world.
+            if (flipScopes) {
+                m_controlFlowScopeStack = savedControlFlowScopeStack;
+                topScope = &amp;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)
</ins><span class="cx"> {
</span><ins>+    ASSERT(labelScopeDepth() - targetScopeDepth &gt;= 0);
+
+    size_t scopeDelta = labelScopeDepth() - targetScopeDepth;
+    ASSERT(scopeDelta &lt;= m_controlFlowScopeStack.size());
+    if (!scopeDelta)
+        return;
+
+    if (!m_finallyDepth) {
+        RefPtr&lt;RegisterID&gt; parentScope = newTemporary();
+        while (scopeDelta--) {
+            parentScope = emitGetParentScope(parentScope.get(), scope);
+            emitMove(scope, parentScope.get());
+        }
+        return;
+    }
+
+    emitComplexPopScopes(scope, &amp;m_controlFlowScopeStack.last(), &amp;m_controlFlowScopeStack.last() - scopeDelta);
+}
+
+TryData* BytecodeGenerator::pushTry(Label* start)
+{
</ins><span class="cx">     TryData tryData;
</span><del>-    tryData.target = handlerLabel;
-    tryData.handlerType = handlerType;
</del><ins>+    tryData.target = newLabel();
+    tryData.handlerType = HandlerType::Illegal;
</ins><span class="cx">     m_tryData.append(tryData);
</span><span class="cx">     TryData* result = &amp;m_tryData.last();
</span><span class="cx">     
</span><span class="lines">@@ -3823,7 +4021,7 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BytecodeGenerator::popTry(TryData* tryData, Label* end)
</del><ins>+void BytecodeGenerator::popTryAndEmitCatch(TryData* tryData, RegisterID* exceptionRegister, RegisterID* thrownValueRegister, Label* end, HandlerType handlerType)
</ins><span class="cx"> {
</span><span class="cx">     m_usesExceptions = true;
</span><span class="cx">     
</span><span class="lines">@@ -3835,52 +4033,28 @@
</span><span class="cx">     tryRange.tryData = m_tryContextStack.last().tryData;
</span><span class="cx">     m_tryRanges.append(tryRange);
</span><span class="cx">     m_tryContextStack.removeLast();
</span><del>-}
</del><ins>+    
+    emitLabel(tryRange.tryData-&gt;target.get());
+    tryRange.tryData-&gt;handlerType = handlerType;
</ins><span class="cx"> 
</span><del>-void BytecodeGenerator::emitCatch(RegisterID* exceptionRegister, RegisterID* thrownValueRegister)
-{
</del><span class="cx">     emitOpcode(op_catch);
</span><span class="cx">     instructions().append(exceptionRegister-&gt;index());
</span><span class="cx">     instructions().append(thrownValueRegister-&gt;index());
</span><del>-}
</del><span class="cx"> 
</span><del>-void BytecodeGenerator::restoreScopeRegister(int lexicalScopeIndex)
-{
-    if (lexicalScopeIndex == CurrentLexicalScopeIndex)
-        return; // No change needed.
-
-    if (lexicalScopeIndex != OutermostLexicalScopeIndex) {
-        ASSERT(lexicalScopeIndex &lt; static_cast&lt;int&gt;(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;
-            }
</del><ins>+    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;
</ins><span class="cx">         }
</span><span class="cx">     }
</span><del>-    // 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);
</del><ins>+    if (!foundLocalScope)
+        emitMove(scopeRegister(), m_topMostScope);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BytecodeGenerator::restoreScopeRegister()
-{
-    restoreScopeRegister(currentLexicalScopeIndex());
-}
-
-int BytecodeGenerator::labelScopeDepthToLexicalScopeIndex(int targetLabelScopeDepth)
-{
-    ASSERT(labelScopeDepth() - targetLabelScopeDepth &gt;= 0);
-    size_t scopeDelta = labelScopeDepth() - targetLabelScopeDepth;
-    ASSERT(scopeDelta &lt;= m_controlFlowScopeStack.size());
-    if (!scopeDelta)
-        return CurrentLexicalScopeIndex;
-
-    ControlFlowScope&amp; targetScope = m_controlFlowScopeStack[targetLabelScopeDepth];
-    return targetScope.lexicalScopeIndex;
-}
-
</del><span class="cx"> int BytecodeGenerator::localScopeDepth() const
</span><span class="cx"> {
</span><span class="cx">     return m_localScopeDepth;
</span><span class="lines">@@ -3887,10 +4061,8 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> int BytecodeGenerator::labelScopeDepth() const
</span><del>-{
-    int depth = localScopeDepth() + m_finallyDepth;
-    ASSERT(depth == static_cast&lt;int&gt;(m_controlFlowScopeStack.size()));
-    return depth;
</del><ins>+{ 
+    return localScopeDepth() + m_finallyDepth;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void BytecodeGenerator::emitThrowStaticError(ErrorType errorType, RegisterID* raw)
</span><span class="lines">@@ -3960,8 +4132,9 @@
</span><span class="cx"> 
</span><span class="cx"> void BytecodeGenerator::pushLocalControlFlowScope()
</span><span class="cx"> {
</span><del>-    ControlFlowScope scope(ControlFlowScope::Label, currentLexicalScopeIndex());
-    m_controlFlowScopeStack.append(WTFMove(scope));
</del><ins>+    ControlFlowScope scope;
+    scope.isFinallyBlock = false;
+    m_controlFlowScopeStack.append(scope);
</ins><span class="cx">     m_localScopeDepth++;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -3968,7 +4141,7 @@
</span><span class="cx"> void BytecodeGenerator::popLocalControlFlowScope()
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_controlFlowScopeStack.size());
</span><del>-    ASSERT(!m_controlFlowScopeStack.last().isFinallyScope());
</del><ins>+    ASSERT(!m_controlFlowScopeStack.last().isFinallyBlock);
</ins><span class="cx">     m_controlFlowScopeStack.removeLast();
</span><span class="cx">     m_localScopeDepth--;
</span><span class="cx"> }
</span><span class="lines">@@ -4123,11 +4296,9 @@
</span><span class="cx">     }
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><del>-
</del><ins>+    
</ins><span class="cx"> void BytecodeGenerator::emitEnumeration(ThrowableExpressionData* node, ExpressionNode* subjectNode, const std::function&lt;void(BytecodeGenerator&amp;, RegisterID*)&gt;&amp; callBack, ForOfNode* forLoopNode, RegisterID* forLoopSymbolTable)
</span><span class="cx"> {
</span><del>-    FinallyRegistersScope finallyRegistersScope(*this);
-
</del><span class="cx">     RefPtr&lt;RegisterID&gt; subject = newTemporary();
</span><span class="cx">     emitNode(subject.get(), subjectNode);
</span><span class="cx">     RefPtr&lt;RegisterID&gt; iterator = emitGetById(newTemporary(), subject.get(), propertyNames().iteratorSymbol);
</span><span class="lines">@@ -4138,15 +4309,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;Label&gt; loopDone = newLabel();
</span><del>-    RefPtr&lt;Label&gt; tryStartLabel = newLabel();
-    RefPtr&lt;Label&gt; finallyViaThrowLabel = newLabel();
-    RefPtr&lt;Label&gt; finallyLabel = newLabel();
-    RefPtr&lt;Label&gt; catchLabel = newLabel();
-    RefPtr&lt;Label&gt; endCatchLabel = newLabel();
-
</del><span class="cx">     // RefPtr&lt;Register&gt; iterator's lifetime must be longer than IteratorCloseContext.
</span><del>-    FinallyContext* finallyContext = pushFinallyControlFlowScope(finallyLabel.get());
-
</del><ins>+    pushIteratorCloseControlFlowScope(iterator.get(), node);
</ins><span class="cx">     {
</span><span class="cx">         LabelScopePtr scope = newLabelScope(LabelScope::Loop);
</span><span class="cx">         RefPtr&lt;RegisterID&gt; value = newTemporary();
</span><span class="lines">@@ -4158,68 +4322,40 @@
</span><span class="cx">         emitLabel(loopStart.get());
</span><span class="cx">         emitLoopHint();
</span><span class="cx"> 
</span><ins>+        RefPtr&lt;Label&gt; tryStartLabel = newLabel();
</ins><span class="cx">         emitLabel(tryStartLabel.get());
</span><del>-        TryData* tryData = pushTry(tryStartLabel.get(), finallyViaThrowLabel.get(), HandlerType::SynthesizedFinally);
</del><ins>+        TryData* tryData = pushTry(tryStartLabel.get());
</ins><span class="cx">         callBack(*this, value.get());
</span><span class="cx">         emitJump(scope-&gt;continueTarget());
</span><span class="cx"> 
</span><del>-        // IteratorClose sequence for abrupt completions.
</del><ins>+        // IteratorClose sequence for throw-ed control flow.
</ins><span class="cx">         {
</span><del>-            // Finally block for the enumeration.
-            emitLabel(finallyViaThrowLabel.get());
-            popTry(tryData, finallyViaThrowLabel.get());
</del><ins>+            RefPtr&lt;Label&gt; catchHere = emitLabel(newLabel().get());
+            RefPtr&lt;RegisterID&gt; exceptionRegister = newTemporary();
+            RefPtr&lt;RegisterID&gt; thrownValueRegister = newTemporary();
+            popTryAndEmitCatch(tryData, exceptionRegister.get(),
+                thrownValueRegister.get(), catchHere.get(), HandlerType::SynthesizedFinally);
</ins><span class="cx"> 
</span><del>-            RegisterID* unused = newTemporary();
-            emitCatch(finallyActionRegister(), unused);
-            // Setting the finallyActionRegister to the caught exception here implies CompletionType::Throw.
</del><ins>+            RefPtr&lt;Label&gt; catchDone = newLabel();
</ins><span class="cx"> 
</span><del>-            emitLabel(finallyLabel.get());
-            restoreScopeRegister();
-
-            RefPtr&lt;Label&gt; finallyDone = newLabel();
-
</del><span class="cx">             RefPtr&lt;RegisterID&gt; returnMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().returnKeyword);
</span><del>-            emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), finallyDone.get());
</del><ins>+            emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), catchDone.get());
</ins><span class="cx"> 
</span><del>-            RefPtr&lt;RegisterID&gt; originalFinallyActionRegister = newTemporary();
-            emitMove(originalFinallyActionRegister.get(), finallyActionRegister());
-
</del><span class="cx">             RefPtr&lt;Label&gt; returnCallTryStart = newLabel();
</span><span class="cx">             emitLabel(returnCallTryStart.get());
</span><del>-            TryData* returnCallTryData = pushTry(returnCallTryStart.get(), catchLabel.get(), HandlerType::SynthesizedCatch);
</del><ins>+            TryData* returnCallTryData = pushTry(returnCallTryStart.get());
</ins><span class="cx"> 
</span><span class="cx">             CallArguments returnArguments(*this, nullptr);
</span><span class="cx">             emitMove(returnArguments.thisRegister(), iterator.get());
</span><span class="cx">             emitCall(value.get(), returnMethod.get(), NoExpectedFunction, returnArguments, node-&gt;divot(), node-&gt;divotStart(), node-&gt;divotEnd(), DebuggableCall::No);
</span><del>-            emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), finallyDone.get());
-            emitThrowTypeError(ASCIILiteral(&quot;Iterator result interface is not an object.&quot;));
</del><span class="cx"> 
</span><del>-            emitLabel(finallyDone.get());
-            emitFinallyCompletion(*finallyContext, endCatchLabel.get());
</del><ins>+            emitLabel(catchDone.get());
+            emitThrow(exceptionRegister.get());
</ins><span class="cx"> 
</span><del>-            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&lt;RegisterID&gt; exceptionRegister = newTemporary();
-                RegisterID* unused = newTemporary();
-                emitCatch(exceptionRegister.get(), unused);
-                restoreScopeRegister();
-
-                RefPtr&lt;Label&gt; throwLabel = newLabel();
-                emitJumpIfCompletionTypeIsThrow(originalFinallyActionRegister.get(), throwLabel.get());
-                emitMove(originalFinallyActionRegister.get(), exceptionRegister.get());
-
-                emitLabel(throwLabel.get());
-                emitThrow(originalFinallyActionRegister.get());
-
-                emitLabel(endCatchLabel.get());
-            }
</del><ins>+            // Absorb exception.
+            popTryAndEmitCatch(returnCallTryData, newTemporary(),
+                newTemporary(), catchDone.get(), HandlerType::SynthesizedFinally);
+            emitThrow(exceptionRegister.get());
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         emitLabel(scope-&gt;continueTarget());
</span><span class="lines">@@ -4240,7 +4376,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // IteratorClose sequence for break-ed control flow.
</span><del>-    popFinallyControlFlowScope();
</del><ins>+    popIteratorCloseControlFlowScope();
</ins><span class="cx">     emitIteratorClose(iterator.get(), node);
</span><span class="cx">     emitLabel(loopDone.get());
</span><span class="cx"> }
</span><span class="lines">@@ -4361,14 +4497,6 @@
</span><span class="cx">     return dst;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RegisterID* BytecodeGenerator::emitIsNumber(RegisterID* dst, RegisterID* src)
-{
-    emitOpcode(op_is_number);
-    instructions().append(dst-&gt;index());
-    instructions().append(src-&gt;index());
-    return dst;
-}
-
</del><span class="cx"> RegisterID* BytecodeGenerator::emitIsUndefined(RegisterID* dst, RegisterID* src)
</span><span class="cx"> {
</span><span class="cx">     emitOpcode(op_is_undefined);
</span><span class="lines">@@ -4656,9 +4784,11 @@
</span><span class="cx">     // Return.
</span><span class="cx">     {
</span><span class="cx">         RefPtr&lt;RegisterID&gt; returnRegister = generatorValueRegister();
</span><del>-        bool hasFinally = emitReturnViaFinallyIfNeeded(returnRegister.get());
-        if (!hasFinally)
-            emitReturn(returnRegister.get());
</del><ins>+        if (isInFinallyBlock()) {
+            returnRegister = emitMove(newTemporary(), returnRegister.get());
+            emitPopScopes(scopeRegister(), 0);
+        }
+        emitReturn(returnRegister.get());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Throw.
</span><span class="lines">@@ -4761,9 +4891,9 @@
</span><span class="cx">                     emitGetById(value.get(), value.get(), propertyNames().value);
</span><span class="cx"> 
</span><span class="cx">                     emitLabel(returnSequence.get());
</span><del>-                    bool hasFinally = emitReturnViaFinallyIfNeeded(value.get());
-                    if (!hasFinally)
-                        emitReturn(value.get());
</del><ins>+                    if (isInFinallyBlock())
+                        emitPopScopes(scopeRegister(), 0);
+                    emitReturn(value.get());
</ins><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 // Normal.
</span><span class="lines">@@ -4793,157 +4923,6 @@
</span><span class="cx">     emitPutById(generatorRegister(), propertyNames().builtinNames().generatorStatePrivateName(), completedState);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool BytecodeGenerator::emitJumpViaFinallyIfNeeded(int targetLabelScopeDepth, Label* jumpTarget)
-{
-    ASSERT(labelScopeDepth() - targetLabelScopeDepth &gt;= 0);
-    size_t scopeDelta = labelScopeDepth() - targetLabelScopeDepth;
-    ASSERT(scopeDelta &lt;= m_controlFlowScopeStack.size());
-    if (!scopeDelta)
-        return false; // No finallys to thread through.
-
-    ControlFlowScope* topScope = &amp;m_controlFlowScopeStack.last();
-    ControlFlowScope* bottomScope = &amp;m_controlFlowScopeStack.last() - scopeDelta;
-
-    FinallyContext* innermostFinallyContext = nullptr;
-    FinallyContext* outermostFinallyContext = nullptr;
-    while (topScope &gt; bottomScope) {
-        if (topScope-&gt;isFinallyScope()) {
-            FinallyContext* finallyContext = &amp;topScope-&gt;finallyContext;
-            if (!innermostFinallyContext)
-                innermostFinallyContext = finallyContext;
-            outermostFinallyContext = finallyContext;
-            finallyContext-&gt;incNumberOfBreaksOrContinues();
-        }
-        --topScope;
-    }
-    if (!outermostFinallyContext)
-        return false; // No finallys to thread through.
-
-    int jumpID = bytecodeOffsetToJumpID(instructions().size());
-    int lexicalScopeIndex = labelScopeDepthToLexicalScopeIndex(targetLabelScopeDepth);
-    outermostFinallyContext-&gt;registerJump(jumpID, lexicalScopeIndex, jumpTarget);
-
-    emitSetFinallyActionToJumpID(jumpID);
-    emitJump(innermostFinallyContext-&gt;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 = &amp;m_controlFlowScopeStack.last();
-    ControlFlowScope* bottomScope = &amp;m_controlFlowScopeStack.first();
-
-    FinallyContext* innermostFinallyContext = nullptr;
-    while (topScope &gt;= bottomScope) {
-        if (topScope-&gt;isFinallyScope()) {
-            FinallyContext* finallyContext = &amp;topScope-&gt;finallyContext;
-            if (!innermostFinallyContext)
-                innermostFinallyContext = finallyContext;
-            finallyContext-&gt;setHandlesReturns();
-        }
-        --topScope;
-    }
-    if (!innermostFinallyContext)
-        return false; // No finallys to thread through.
-
-    emitSetFinallyActionToReturnCompletion();
-    emitSetFinallyReturnValueRegister(returnRegister);
-    emitJump(innermostFinallyContext-&gt;finallyLabel());
-    return true; // We'll be jumping to a finally block.
-}
-
-void BytecodeGenerator::emitFinallyCompletion(FinallyContext&amp; 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 &lt; numberOfJumps; i++) {
-                RefPtr&lt;Label&gt; nextLabel = newLabel();
-                auto&amp; jump = context.jumps(i);
-                emitJumpIfFinallyActionIsNotJump(jump.jumpID, nextLabel.get());
-
-                restoreScopeRegister(jump.targetLexicalScopeIndex);
-                emitSetFinallyActionToNormalCompletion();
-                emitJump(jump.targetLabel.get());
-
-                emitLabel(nextLabel.get());
-            }
-
-            bool hasBreaksOrContinuesNotCoveredByJumps = context.numberOfBreaksOrContinues() &gt; numberOfJumps;
-            if (hasBreaksOrContinuesNotCoveredByJumps || context.handlesReturns())
-                emitJumpIfFinallyActionIsNotThrowCompletion(outerContext-&gt;finallyLabel());
-
-        } else {
-            // We are the outermost finally.
-            size_t numberOfJumps = context.numberOfJumps();
-            ASSERT(numberOfJumps == context.numberOfBreaksOrContinues());
-
-            for (size_t i = 0; i &lt; numberOfJumps; i++) {
-                RefPtr&lt;Label&gt; nextLabel = newLabel();
-                auto&amp; jump = context.jumps(i);
-                emitJumpIfFinallyActionIsNotJump(jump.jumpID, nextLabel.get());
-
-                restoreScopeRegister(jump.targetLexicalScopeIndex);
-                emitSetFinallyActionToNormalCompletion();
-                emitJump(jump.targetLabel.get());
-
-                emitLabel(nextLabel.get());
-            }
-
-            if (context.handlesReturns()) {
-                RefPtr&lt;Label&gt; 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 &amp;&amp; m_finallyReturnValueRegister);
-    m_finallyActionRegister = nullptr;
-    m_finallyReturnValueRegister = nullptr;
-}
-
-void BytecodeGenerator::emitCompareFinallyActionAndJumpIf(OpcodeID compareOpcode, int value, Label* jumpTarget)
-{
-    RefPtr&lt;RegisterID&gt; 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);
-}
-
</del><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (210010 => 210011)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-12-20 02:03:02 UTC (rev 210010)
+++ branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-12-20 02:05:52 UTC (rev 210011)
</span><span class="lines">@@ -80,78 +80,22 @@
</span><span class="cx">         unsigned m_padding;
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    struct FinallyJump {
-        FinallyJump(int jumpID, int targetLexicalScopeIndex, Label* targetLabel)
-            : jumpID(jumpID)
-            , targetLexicalScopeIndex(targetLexicalScopeIndex)
-            , targetLabel(targetLabel)
-        { }
-
-        int jumpID { 0 };
-        int targetLexicalScopeIndex { 0 };
-        RefPtr&lt;Label&gt; targetLabel;
-    };
-
</del><span class="cx">     struct FinallyContext {
</span><del>-        FinallyContext() { }
-        FinallyContext(FinallyContext* outerContext, Label* finallyLabel, int finallyDepth)
-            : m_outerContext(outerContext)
-            , m_finallyLabel(finallyLabel)
-            , m_finallyDepth(finallyDepth)
-        {
-            ASSERT(!m_jumps || m_jumps-&gt;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 &lt; 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&lt;Vector&lt;FinallyJump&gt;&gt;();
-            m_jumps-&gt;append(FinallyJump(jumpID, lexicalScopeIndex, targetLabel));
-        }
-
-        size_t numberOfJumps() const { return m_jumps ? m_jumps-&gt;size() : 0; }
-        FinallyJump&amp; 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&lt;Vector&lt;FinallyJump&gt;&gt; m_jumps;
</del><ins>+        StatementNode* finallyBlock;
+        RegisterID* iterator;
+        ThrowableExpressionData* enumerationNode;
+        unsigned controlFlowScopeStackSize;
+        unsigned switchContextStackSize;
+        unsigned forInContextStackSize;
+        unsigned tryContextStackSize;
+        unsigned labelScopesSize;
+        unsigned lexicalScopeStackSize;
+        int finallyDepth;
+        int dynamicScopeDepth;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     struct ControlFlowScope {
</span><del>-        typedef uint8_t Type;
-        enum {
-            Label,
-            Finally
-        };
-        ControlFlowScope(Type type, int lexicalScopeIndex, FinallyContext&amp;&amp; finallyContext = FinallyContext())
-            : type(type)
-            , lexicalScopeIndex(lexicalScopeIndex)
-            , finallyContext(std::forward&lt;FinallyContext&gt;(finallyContext))
-        { }
-
-        bool isLabelScope() const { return type == Label; }
-        bool isFinallyScope() const { return type == Finally; }
-
-        Type type;
-        int lexicalScopeIndex;
</del><ins>+        bool isFinallyBlock;
</ins><span class="cx">         FinallyContext finallyContext;
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="lines">@@ -661,8 +605,7 @@
</span><span class="cx"> 
</span><span class="cx">         RegisterID* emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode*);
</span><span class="cx"> 
</span><del>-        enum class ReturnFrom { Normal, Finally };
-        RegisterID* emitReturn(RegisterID* src, ReturnFrom = ReturnFrom::Normal);
</del><ins>+        RegisterID* emitReturn(RegisterID* src);
</ins><span class="cx">         RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); }
</span><span class="cx"> 
</span><span class="cx">         RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&amp;, const JSTextPosition&amp; divot, const JSTextPosition&amp; divotStart, const JSTextPosition&amp; divotEnd);
</span><span class="lines">@@ -683,6 +626,7 @@
</span><span class="cx">         PassRefPtr&lt;Label&gt; emitJumpIfFalse(RegisterID* cond, Label* target);
</span><span class="cx">         PassRefPtr&lt;Label&gt; emitJumpIfNotFunctionCall(RegisterID* cond, Label* target);
</span><span class="cx">         PassRefPtr&lt;Label&gt; emitJumpIfNotFunctionApply(RegisterID* cond, Label* target);
</span><ins>+        void emitPopScopes(RegisterID* srcDst, int targetScopeDepth);
</ins><span class="cx"> 
</span><span class="cx">         void emitEnter();
</span><span class="cx">         void emitWatchdog();
</span><span class="lines">@@ -705,7 +649,6 @@
</span><span class="cx">         RegisterID* emitIsMap(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSMapType); }
</span><span class="cx">         RegisterID* emitIsSet(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSSetType); }
</span><span class="cx">         RegisterID* emitIsObject(RegisterID* dst, RegisterID* src);
</span><del>-        RegisterID* emitIsNumber(RegisterID* dst, RegisterID* src);
</del><span class="cx">         RegisterID* emitIsUndefined(RegisterID* dst, RegisterID* src);
</span><span class="cx">         RegisterID* emitIsEmpty(RegisterID* dst, RegisterID* src);
</span><span class="cx">         RegisterID* emitIsDerivedArray(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, DerivedArrayType); }
</span><span class="lines">@@ -720,30 +663,10 @@
</span><span class="cx">         bool emitReadOnlyExceptionIfNeeded(const Variable&amp;);
</span><span class="cx"> 
</span><span class="cx">         // Start a try block. 'start' must have been emitted.
</span><del>-        TryData* pushTry(Label* start, Label* handlerLabel, HandlerType);
</del><ins>+        TryData* pushTry(Label* start);
</ins><span class="cx">         // End a try block. 'end' must have been emitted.
</span><del>-        void popTry(TryData*, Label* end);
-        void emitCatch(RegisterID* exceptionRegister, RegisterID* thrownValueRegister);
</del><ins>+        void popTryAndEmitCatch(TryData*, RegisterID* exceptionRegister, RegisterID* thrownValueRegister, Label* end, HandlerType);
</ins><span class="cx"> 
</span><del>-    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&lt;int&gt;(m_lexicalScopeStack.size());
-            ASSERT(static_cast&lt;size_t&gt;(size) == m_lexicalScopeStack.size());
-            ASSERT(size &gt;= 0);
-            int index = size - 1;
-            return index;
-        }
-
-        int labelScopeDepthToLexicalScopeIndex(int labelScopeDepth);
-
</del><span class="cx">         void emitThrow(RegisterID* exc)
</span><span class="cx">         { 
</span><span class="cx">             m_usesExceptions = true;
</span><span class="lines">@@ -775,102 +698,13 @@
</span><span class="cx">         void emitDebugHook(ExpressionNode*);
</span><span class="cx">         void emitWillLeaveCallFrameDebugHook();
</span><span class="cx"> 
</span><del>-        class FinallyRegistersScope {
-        public:
-            FinallyRegistersScope(BytecodeGenerator&amp; generator, bool needFinallyRegisters = true)
-                : m_generator(generator)
-            {
-                if (needFinallyRegisters &amp;&amp; m_generator.allocateFinallyRegisters())
-                    m_needToReleaseOnDestruction = true;
-            }
-            ~FinallyRegistersScope()
-            {
-                if (m_needToReleaseOnDestruction)
-                    m_generator.releaseFinallyRegisters();
-            }
</del><ins>+        bool isInFinallyBlock() { return m_finallyDepth &gt; 0; }
</ins><span class="cx"> 
</span><del>-        private:
-            BytecodeGenerator&amp; m_generator;
-            bool m_needToReleaseOnDestruction { false };
-        };
</del><ins>+        void pushFinallyControlFlowScope(StatementNode* finallyBlock);
+        void popFinallyControlFlowScope();
+        void pushIteratorCloseControlFlowScope(RegisterID* iterator, ThrowableExpressionData* enumerationNode);
+        void popIteratorCloseControlFlowScope();
</ins><span class="cx"> 
</span><del>-        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&lt;int&gt;(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&lt;int&gt;(CompletionType::Return), jumpTarget);
-        }
-        void emitJumpIfFinallyActionIsNotReturnCompletion(Label* jumpTarget)
-        {
-            emitCompareFinallyActionAndJumpIf(op_nstricteq, static_cast&lt;int&gt;(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&amp;, Label* normalCompletionLabel);
-
-    private:
-        void emitCompareFinallyActionAndJumpIf(OpcodeID compareOpcode, int value, Label* jumpTarget);
-
-        int bytecodeOffsetToJumpID(unsigned offset)
-        {
-            int jumpID = offset + static_cast&lt;int&gt;(CompletionType::NumberOfTypes);
-            ASSERT(jumpID &gt;= static_cast&lt;int&gt;(CompletionType::NumberOfTypes));
-            return jumpID;
-        }
-
-        bool allocateFinallyRegisters();
-        void releaseFinallyRegisters();
-
-    public:
-        FinallyContext* pushFinallyControlFlowScope(Label* finallyLabel);
-        FinallyContext popFinallyControlFlowScope();
-
</del><span class="cx">         void pushIndexedForInScope(RegisterID* local, RegisterID* index);
</span><span class="cx">         void popIndexedForInScope(RegisterID* local);
</span><span class="cx">         void pushStructureForInScope(RegisterID* local, RegisterID* index, RegisterID* property, RegisterID* enumerator);
</span><span class="lines">@@ -963,6 +797,7 @@
</span><span class="cx"> 
</span><span class="cx">         void allocateCalleeSaveSpace();
</span><span class="cx">         void allocateAndEmitScope();
</span><ins>+        void emitComplexPopScopes(RegisterID*, ControlFlowScope* topScope, ControlFlowScope* bottomScope);
</ins><span class="cx"> 
</span><span class="cx">         typedef HashMap&lt;double, JSValue&gt; NumberMap;
</span><span class="cx">         typedef HashMap&lt;UniquedStringImpl*, JSString*, IdentifierRepHash&gt; IdentifierStringMap;
</span><span class="lines">@@ -1100,35 +935,6 @@
</span><span class="cx">         RegisterID* m_arrowFunctionContextLexicalEnvironmentRegister { nullptr };
</span><span class="cx">         RegisterID* m_promiseCapabilityRegister { nullptr };
</span><span class="cx"> 
</span><del>-        // 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&lt;RegisterID&gt; m_finallyActionRegister;
-        RefPtr&lt;RegisterID&gt; m_finallyReturnValueRegister;
-
-        FinallyContext* m_currentFinallyContext { nullptr };
-
</del><span class="cx">         SegmentedVector&lt;RegisterID*, 16&gt; m_localRegistersForCalleeSaveRegisters;
</span><span class="cx">         SegmentedVector&lt;RegisterID, 32&gt; m_constantPoolRegisters;
</span><span class="cx">         SegmentedVector&lt;RegisterID, 32&gt; m_calleeLocals;
</span><span class="lines">@@ -1143,9 +949,7 @@
</span><span class="cx">         void pushLocalControlFlowScope();
</span><span class="cx">         void popLocalControlFlowScope();
</span><span class="cx"> 
</span><del>-        // FIXME: Restore overflow checking with UnsafeVectorOverflow once SegmentVector supports it. 
-        // https://bugs.webkit.org/show_bug.cgi?id=165980
-        SegmentedVector&lt;ControlFlowScope, 16&gt; m_controlFlowScopeStack;
</del><ins>+        Vector&lt;ControlFlowScope, 0, UnsafeVectorOverflow&gt; m_controlFlowScopeStack;
</ins><span class="cx">         Vector&lt;SwitchInfo&gt; m_switchContextStack;
</span><span class="cx">         Vector&lt;RefPtr&lt;ForInContext&gt;&gt; m_forInContextStack;
</span><span class="cx">         Vector&lt;TryContext&gt; m_tryContextStack;
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (210010 => 210011)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2016-12-20 02:03:02 UTC (rev 210010)
+++ branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2016-12-20 02:05:52 UTC (rev 210011)
</span><span class="lines">@@ -2998,12 +2998,8 @@
</span><span class="cx">     LabelScopePtr scope = generator.continueTarget(m_ident);
</span><span class="cx">     ASSERT(scope);
</span><span class="cx"> 
</span><del>-    bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope-&gt;scopeDepth(), scope-&gt;continueTarget());
-    if (!hasFinally) {
-        int lexicalScopeIndex = generator.labelScopeDepthToLexicalScopeIndex(scope-&gt;scopeDepth());
-        generator.restoreScopeRegister(lexicalScopeIndex);
-        generator.emitJump(scope-&gt;continueTarget());
-    }
</del><ins>+    generator.emitPopScopes(generator.scopeRegister(), scope-&gt;scopeDepth());
+    generator.emitJump(scope-&gt;continueTarget());
</ins><span class="cx"> 
</span><span class="cx">     generator.emitProfileControlFlow(endOffset());
</span><span class="cx"> }
</span><span class="lines">@@ -3029,12 +3025,8 @@
</span><span class="cx">     LabelScopePtr scope = generator.breakTarget(m_ident);
</span><span class="cx">     ASSERT(scope);
</span><span class="cx"> 
</span><del>-    bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope-&gt;scopeDepth(), scope-&gt;breakTarget());
-    if (!hasFinally) {
-        int lexicalScopeIndex = generator.labelScopeDepthToLexicalScopeIndex(scope-&gt;scopeDepth());
-        generator.restoreScopeRegister(lexicalScopeIndex);
-        generator.emitJump(scope-&gt;breakTarget());
-    }
</del><ins>+    generator.emitPopScopes(generator.scopeRegister(), scope-&gt;scopeDepth());
+    generator.emitJump(scope-&gt;breakTarget());
</ins><span class="cx"> 
</span><span class="cx">     generator.emitProfileControlFlow(endOffset());
</span><span class="cx"> }
</span><span class="lines">@@ -3051,14 +3043,14 @@
</span><span class="cx">     RefPtr&lt;RegisterID&gt; returnRegister = m_value ? generator.emitNodeInTailPosition(dst, m_value) : generator.emitLoad(dst, jsUndefined());
</span><span class="cx"> 
</span><span class="cx">     generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, divotStart(), divotEnd());
</span><del>-
-    bool hasFinally = generator.emitReturnViaFinallyIfNeeded(returnRegister.get());
-    if (!hasFinally) {
-        generator.emitWillLeaveCallFrameDebugHook();
-        generator.emitReturn(returnRegister.get());
</del><ins>+    if (generator.isInFinallyBlock()) {
+        returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get());
+        generator.emitPopScopes(generator.scopeRegister(), 0);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    generator.emitProfileControlFlow(endOffset());
</del><ins>+    generator.emitWillLeaveCallFrameDebugHook();
+    generator.emitReturn(returnRegister.get());
+    generator.emitProfileControlFlow(endOffset()); 
</ins><span class="cx">     // Emitting an unreachable return here is needed in case this op_profile_control_flow is the 
</span><span class="cx">     // last opcode in a CodeBlock because a CodeBlock's instructions must end with a terminal opcode.
</span><span class="cx">     if (generator.vm()-&gt;controlFlowProfiler())
</span><span class="lines">@@ -3287,57 +3279,32 @@
</span><span class="cx">     // optimizer knows they may be jumped to from anywhere.
</span><span class="cx"> 
</span><span class="cx">     ASSERT(m_catchBlock || m_finallyBlock);
</span><del>-    BytecodeGenerator::FinallyRegistersScope finallyRegistersScope(generator, m_finallyBlock);
</del><span class="cx"> 
</span><del>-    RefPtr&lt;Label&gt; catchLabel;
-    RefPtr&lt;Label&gt; catchEndLabel;
-    RefPtr&lt;Label&gt; finallyViaThrowLabel;
-    RefPtr&lt;Label&gt; finallyLabel;
-    RefPtr&lt;Label&gt; finallyEndLabel;
-
</del><span class="cx">     RefPtr&lt;Label&gt; tryStartLabel = generator.newLabel();
</span><span class="cx">     generator.emitLabel(tryStartLabel.get());
</span><ins>+    
+    if (m_finallyBlock)
+        generator.pushFinallyControlFlowScope(m_finallyBlock);
+    TryData* tryData = generator.pushTry(tryStartLabel.get());
</ins><span class="cx"> 
</span><del>-    if (m_finallyBlock) {
-        finallyViaThrowLabel = generator.newLabel();
-        finallyLabel = generator.newLabel();
-        finallyEndLabel = generator.newLabel();
</del><ins>+    generator.emitNode(dst, m_tryBlock);
</ins><span class="cx"> 
</span><del>-        generator.pushFinallyControlFlowScope(finallyLabel.get());
-    }
</del><span class="cx">     if (m_catchBlock) {
</span><del>-        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
</del><ins>+        RefPtr&lt;Label&gt; catchEndLabel = generator.newLabel();
+        
+        // Normal path: jump over the catch block.
</ins><span class="cx">         generator.emitJump(catchEndLabel.get());
</span><span class="cx"> 
</span><del>-    RefPtr&lt;Label&gt; endTryLabel = generator.emitLabel(generator.newLabel().get());
-    generator.popTry(tryData, endTryLabel.get());
-
-    if (m_catchBlock) {
</del><span class="cx">         // Uncaught exception path: the catch block.
</span><del>-        generator.emitLabel(catchLabel.get());
</del><ins>+        RefPtr&lt;Label&gt; here = generator.emitLabel(generator.newLabel().get());
+        RefPtr&lt;RegisterID&gt; exceptionRegister = generator.newTemporary();
</ins><span class="cx">         RefPtr&lt;RegisterID&gt; thrownValueRegister = generator.newTemporary();
</span><del>-        RegisterID* unused = generator.newTemporary();
-        generator.emitCatch(unused, thrownValueRegister.get());
-        generator.restoreScopeRegister();
-
-        TryData* tryData = nullptr;
</del><ins>+        generator.popTryAndEmitCatch(tryData, exceptionRegister.get(), thrownValueRegister.get(), here.get(), HandlerType::Catch);
+        
</ins><span class="cx">         if (m_finallyBlock) {
</span><span class="cx">             // If the catch block throws an exception and we have a finally block, then the finally
</span><span class="cx">             // block should &quot;catch&quot; that exception.
</span><del>-            tryData = generator.pushTry(catchLabel.get(), finallyViaThrowLabel.get(), HandlerType::Finally);
</del><ins>+            tryData = generator.pushTry(here.get());
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         generator.emitPushCatchScope(m_lexicalVariables);
</span><span class="lines">@@ -3349,38 +3316,37 @@
</span><span class="cx">             generator.emitNodeInTailPosition(dst, m_catchBlock);
</span><span class="cx">         generator.emitLoad(thrownValueRegister.get(), jsUndefined());
</span><span class="cx">         generator.emitPopCatchScope(m_lexicalVariables);
</span><del>-
-        if (m_finallyBlock) {
-            generator.emitSetFinallyActionToNormalCompletion();
-            generator.emitJump(finallyLabel.get());
-            generator.popTry(tryData, finallyViaThrowLabel.get());
-        }
-
</del><span class="cx">         generator.emitLabel(catchEndLabel.get());
</span><del>-        generator.emitProfileControlFlow(m_catchBlock-&gt;endOffset() + 1);
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (m_finallyBlock) {
</span><del>-        FinallyContext finallyContext = generator.popFinallyControlFlowScope();
</del><ins>+        RefPtr&lt;Label&gt; preFinallyLabel = generator.emitLabel(generator.newLabel().get());
+        
+        generator.popFinallyControlFlowScope();
</ins><span class="cx"> 
</span><del>-        // 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.
</del><ins>+        RefPtr&lt;Label&gt; finallyEndLabel = generator.newLabel();
</ins><span class="cx"> 
</span><del>-        // Entry to the finally block for CompletionTypes other than Throw.
-        generator.emitLabel(finallyLabel.get());
-        generator.restoreScopeRegister();
</del><ins>+        int finallyStartOffset = m_catchBlock ? m_catchBlock-&gt;endOffset() + 1 : m_tryBlock-&gt;endOffset() + 1;
</ins><span class="cx"> 
</span><del>-        int finallyStartOffset = m_catchBlock ? m_catchBlock-&gt;endOffset() + 1 : m_tryBlock-&gt;endOffset() + 1;
</del><ins>+        // Normal path: run the finally code, and jump to the end.
</ins><span class="cx">         generator.emitProfileControlFlow(finallyStartOffset);
</span><span class="cx">         generator.emitNodeInTailPosition(dst, m_finallyBlock);
</span><ins>+        generator.emitProfileControlFlow(m_finallyBlock-&gt;endOffset() + 1);
+        generator.emitJump(finallyEndLabel.get());
</ins><span class="cx"> 
</span><del>-        generator.emitFinallyCompletion(finallyContext, finallyEndLabel.get());
</del><ins>+        // Uncaught exception path: invoke the finally block, then re-throw the exception.
+        RefPtr&lt;RegisterID&gt; exceptionRegister = generator.newTemporary();
+        RefPtr&lt;RegisterID&gt; 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());
+
</ins><span class="cx">         generator.emitLabel(finallyEndLabel.get());
</span><span class="cx">         generator.emitProfileControlFlow(m_finallyBlock-&gt;endOffset() + 1);
</span><del>-    }
</del><ins>+    } else
+        generator.emitProfileControlFlow(m_catchBlock-&gt;endOffset() + 1);
+
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // ------------------------------ ScopeNode -----------------------------
</span></span></pre></div>
<a id="branchessafari603branchSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/WTF/ChangeLog (210010 => 210011)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,5 +1,21 @@
</span><span class="cx"> 2016-12-19  Babak Shafiei  &lt;bshafiei@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r210010.
+
+    2016-12-19  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+            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  &lt;bshafiei@apple.com&gt;
+
</ins><span class="cx">         Merge patch for rdar://problem/29466493.
</span><span class="cx"> 
</span><span class="cx">     2016-12-19  Dean Jackson  &lt;dino@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari603branchSourceWTFwtfSegmentedVectorh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/WTF/wtf/SegmentedVector.h (210010 => 210011)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -127,17 +127,9 @@
</span><span class="cx">             return at(index);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        T&amp; first() { return at(0); }
-        const T&amp; first() const { return at(0); }
-        T&amp; last() { return at(size() - 1); }
-        const T&amp; last() const { return at(size() - 1); }
-
-        T takeLast()
</del><ins>+        T&amp; last()
</ins><span class="cx">         {
</span><del>-            ASSERT_WITH_SECURITY_IMPLICATION(!isEmpty());
-            T result = WTFMove(last());
-            --m_size;
-            return result;
</del><ins>+            return at(size() - 1);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         template&lt;typename... Args&gt;
</span></span></pre>
</div>
</div>

</body>
</html>