<!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>[210008] branches/safari-603-branch/Source/JavaScriptCore</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/210008">210008</a></dd>
<dt>Author</dt> <dd>bshafiei@apple.com</dd>
<dt>Date</dt> <dd>2016-12-19 17:55:06 -0800 (Mon, 19 Dec 2016)</dd>
</dl>

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

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari603branchSourceJavaScriptCoreChangeLog">branches/safari-603-branch/Source/JavaScriptCore/ChangeLog</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>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari603branchSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/ChangeLog (210007 => 210008)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/ChangeLog        2016-12-20 01:48:52 UTC (rev 210007)
+++ branches/safari-603-branch/Source/JavaScriptCore/ChangeLog        2016-12-20 01:55:06 UTC (rev 210008)
</span><span class="lines">@@ -1,3 +1,53 @@
</span><ins>+2016-12-19  Babak Shafiei  &lt;bshafiei@apple.com&gt;
+
+        Merge r210007.
+
+    2016-12-19  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+            Rolling out r209974 and r209952. They break some websites in mysterious ways. Step 1: Rollout r209974.
+            https://bugs.webkit.org/show_bug.cgi?id=166049
+
+            Not reviewed.
+
+            * bytecompiler/BytecodeGenerator.cpp:
+            (JSC::BytecodeGenerator::emitEnumeration):
+            (JSC::BytecodeGenerator::emitJumpViaFinallyIfNeeded):
+            (JSC::BytecodeGenerator::emitReturnViaFinallyIfNeeded):
+            (JSC::BytecodeGenerator::emitFinallyCompletion):
+            (JSC::BytecodeGenerator::allocateFinallyRegisters):
+            (JSC::BytecodeGenerator::releaseFinallyRegisters):
+            (JSC::BytecodeGenerator::emitCompareFinallyActionAndJumpIf):
+            (JSC::BytecodeGenerator::allocateCompletionRecordRegisters): Deleted.
+            (JSC::BytecodeGenerator::releaseCompletionRecordRegisters): Deleted.
+            (JSC::BytecodeGenerator::emitJumpIfCompletionType): Deleted.
+            * bytecompiler/BytecodeGenerator.h:
+            (JSC::FinallyJump::FinallyJump):
+            (JSC::FinallyContext::registerJump):
+            (JSC::BytecodeGenerator::FinallyRegistersScope::FinallyRegistersScope):
+            (JSC::BytecodeGenerator::FinallyRegistersScope::~FinallyRegistersScope):
+            (JSC::BytecodeGenerator::finallyActionRegister):
+            (JSC::BytecodeGenerator::finallyReturnValueRegister):
+            (JSC::BytecodeGenerator::emitSetFinallyActionToNormalCompletion):
+            (JSC::BytecodeGenerator::emitSetFinallyActionToReturnCompletion):
+            (JSC::BytecodeGenerator::emitSetFinallyActionToJumpID):
+            (JSC::BytecodeGenerator::emitSetFinallyReturnValueRegister):
+            (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNormalCompletion):
+            (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotJump):
+            (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsReturnCompletion):
+            (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotReturnCompletion):
+            (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotThrowCompletion):
+            (JSC::BytecodeGenerator::emitJumpIfCompletionTypeIsThrow):
+            (JSC::BytecodeGenerator::bytecodeOffsetToJumpID):
+            (JSC::bytecodeOffsetToJumpID): Deleted.
+            (JSC::BytecodeGenerator::CompletionRecordScope::CompletionRecordScope): Deleted.
+            (JSC::BytecodeGenerator::CompletionRecordScope::~CompletionRecordScope): Deleted.
+            (JSC::BytecodeGenerator::completionTypeRegister): Deleted.
+            (JSC::BytecodeGenerator::completionValueRegister): Deleted.
+            (JSC::BytecodeGenerator::emitSetCompletionType): Deleted.
+            (JSC::BytecodeGenerator::emitSetCompletionValue): Deleted.
+            * bytecompiler/NodesCodegen.cpp:
+            (JSC::TryNode::emitBytecode):
+
</ins><span class="cx"> 2016-12-19  Dean Jackson  &lt;dino@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Merge another patch for rdar://problem/29466493.
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (210007 => 210008)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-12-20 01:48:52 UTC (rev 210007)
+++ branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-12-20 01:55:06 UTC (rev 210008)
</span><span class="lines">@@ -4126,7 +4126,7 @@
</span><span class="cx"> 
</span><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>-    CompletionRecordScope completionRecordScope(*this);
</del><ins>+    FinallyRegistersScope finallyRegistersScope(*this);
</ins><span class="cx"> 
</span><span class="cx">     RefPtr&lt;RegisterID&gt; subject = newTemporary();
</span><span class="cx">     emitNode(subject.get(), subjectNode);
</span><span class="lines">@@ -4169,19 +4169,11 @@
</span><span class="cx">             emitLabel(finallyViaThrowLabel.get());
</span><span class="cx">             popTry(tryData, finallyViaThrowLabel.get());
</span><span class="cx"> 
</span><del>-            RefPtr&lt;Label&gt; finallyBodyLabel = newLabel();
-            RefPtr&lt;RegisterID&gt; finallyExceptionRegister = newTemporary();
</del><span class="cx">             RegisterID* unused = newTemporary();
</span><ins>+            emitCatch(finallyActionRegister(), unused);
+            // Setting the finallyActionRegister to the caught exception here implies CompletionType::Throw.
</ins><span class="cx"> 
</span><del>-            emitCatch(completionValueRegister(), unused);
-            emitSetCompletionType(CompletionType::Throw);
-            emitMove(finallyExceptionRegister.get(), completionValueRegister());
-            emitJump(finallyBodyLabel.get());
-
</del><span class="cx">             emitLabel(finallyLabel.get());
</span><del>-            emitMoveEmptyValue(finallyExceptionRegister.get());
-
-            emitLabel(finallyBodyLabel.get());
</del><span class="cx">             restoreScopeRegister();
</span><span class="cx"> 
</span><span class="cx">             RefPtr&lt;Label&gt; finallyDone = newLabel();
</span><span class="lines">@@ -4189,6 +4181,9 @@
</span><span class="cx">             RefPtr&lt;RegisterID&gt; returnMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().returnKeyword);
</span><span class="cx">             emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), finallyDone.get());
</span><span class="cx"> 
</span><ins>+            RefPtr&lt;RegisterID&gt; originalFinallyActionRegister = newTemporary();
+            emitMove(originalFinallyActionRegister.get(), finallyActionRegister());
+
</ins><span class="cx">             RefPtr&lt;Label&gt; returnCallTryStart = newLabel();
</span><span class="cx">             emitLabel(returnCallTryStart.get());
</span><span class="cx">             TryData* returnCallTryData = pushTry(returnCallTryStart.get(), catchLabel.get(), HandlerType::SynthesizedCatch);
</span><span class="lines">@@ -4214,16 +4209,14 @@
</span><span class="cx">                 RefPtr&lt;RegisterID&gt; exceptionRegister = newTemporary();
</span><span class="cx">                 RegisterID* unused = newTemporary();
</span><span class="cx">                 emitCatch(exceptionRegister.get(), unused);
</span><del>-                // Since this is a synthesized catch block and we're guaranteed to never need
-                // to resolve any symbols from the scope, we can skip restoring the scope
-                // register here.
</del><ins>+                restoreScopeRegister();
</ins><span class="cx"> 
</span><span class="cx">                 RefPtr&lt;Label&gt; throwLabel = newLabel();
</span><del>-                emitJumpIfTrue(emitIsEmpty(newTemporary(), finallyExceptionRegister.get()), throwLabel.get());
-                emitMove(exceptionRegister.get(), finallyExceptionRegister.get());
</del><ins>+                emitJumpIfCompletionTypeIsThrow(originalFinallyActionRegister.get(), throwLabel.get());
+                emitMove(originalFinallyActionRegister.get(), exceptionRegister.get());
</ins><span class="cx"> 
</span><span class="cx">                 emitLabel(throwLabel.get());
</span><del>-                emitThrow(exceptionRegister.get());
</del><ins>+                emitThrow(originalFinallyActionRegister.get());
</ins><span class="cx"> 
</span><span class="cx">                 emitLabel(endCatchLabel.get());
</span><span class="cx">             }
</span><span class="lines">@@ -4826,11 +4819,11 @@
</span><span class="cx">     if (!outermostFinallyContext)
</span><span class="cx">         return false; // No finallys to thread through.
</span><span class="cx"> 
</span><del>-    auto jumpID = bytecodeOffsetToJumpID(instructions().size());
</del><ins>+    int jumpID = bytecodeOffsetToJumpID(instructions().size());
</ins><span class="cx">     int lexicalScopeIndex = labelScopeDepthToLexicalScopeIndex(targetLabelScopeDepth);
</span><span class="cx">     outermostFinallyContext-&gt;registerJump(jumpID, lexicalScopeIndex, jumpTarget);
</span><span class="cx"> 
</span><del>-    emitSetCompletionType(jumpID);
</del><ins>+    emitSetFinallyActionToJumpID(jumpID);
</ins><span class="cx">     emitJump(innermostFinallyContext-&gt;finallyLabel());
</span><span class="cx">     return true; // We'll be jumping to a finally block.
</span><span class="cx"> }
</span><span class="lines">@@ -4856,8 +4849,8 @@
</span><span class="cx">     if (!innermostFinallyContext)
</span><span class="cx">         return false; // No finallys to thread through.
</span><span class="cx"> 
</span><del>-    emitSetCompletionType(CompletionType::Return);
-    emitSetCompletionValue(returnRegister);
</del><ins>+    emitSetFinallyActionToReturnCompletion();
+    emitSetFinallyReturnValueRegister(returnRegister);
</ins><span class="cx">     emitJump(innermostFinallyContext-&gt;finallyLabel());
</span><span class="cx">     return true; // We'll be jumping to a finally block.
</span><span class="cx"> }
</span><span class="lines">@@ -4864,7 +4857,9 @@
</span><span class="cx"> 
</span><span class="cx"> void BytecodeGenerator::emitFinallyCompletion(FinallyContext&amp; context, Label* normalCompletionLabel)
</span><span class="cx"> {
</span><del>-    emitJumpIfCompletionType(op_stricteq, CompletionType::Normal, normalCompletionLabel);
</del><ins>+    // 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);
</ins><span class="cx"> 
</span><span class="cx">     if (context.numberOfBreaksOrContinues() || context.handlesReturns()) {
</span><span class="cx">         FinallyContext* outerContext = context.outerContext();
</span><span class="lines">@@ -4874,10 +4869,10 @@
</span><span class="cx">             for (size_t i = 0; i &lt; numberOfJumps; i++) {
</span><span class="cx">                 RefPtr&lt;Label&gt; nextLabel = newLabel();
</span><span class="cx">                 auto&amp; jump = context.jumps(i);
</span><del>-                emitJumpIfCompletionType(op_nstricteq, jump.jumpID, nextLabel.get());
</del><ins>+                emitJumpIfFinallyActionIsNotJump(jump.jumpID, nextLabel.get());
</ins><span class="cx"> 
</span><span class="cx">                 restoreScopeRegister(jump.targetLexicalScopeIndex);
</span><del>-                emitSetCompletionType(CompletionType::Normal);
</del><ins>+                emitSetFinallyActionToNormalCompletion();
</ins><span class="cx">                 emitJump(jump.targetLabel.get());
</span><span class="cx"> 
</span><span class="cx">                 emitLabel(nextLabel.get());
</span><span class="lines">@@ -4885,7 +4880,7 @@
</span><span class="cx"> 
</span><span class="cx">             bool hasBreaksOrContinuesNotCoveredByJumps = context.numberOfBreaksOrContinues() &gt; numberOfJumps;
</span><span class="cx">             if (hasBreaksOrContinuesNotCoveredByJumps || context.handlesReturns())
</span><del>-                emitJumpIfCompletionType(op_nstricteq, CompletionType::Throw, outerContext-&gt;finallyLabel());
</del><ins>+                emitJumpIfFinallyActionIsNotThrowCompletion(outerContext-&gt;finallyLabel());
</ins><span class="cx"> 
</span><span class="cx">         } else {
</span><span class="cx">             // We are the outermost finally.
</span><span class="lines">@@ -4895,10 +4890,10 @@
</span><span class="cx">             for (size_t i = 0; i &lt; numberOfJumps; i++) {
</span><span class="cx">                 RefPtr&lt;Label&gt; nextLabel = newLabel();
</span><span class="cx">                 auto&amp; jump = context.jumps(i);
</span><del>-                emitJumpIfCompletionType(op_nstricteq, jump.jumpID, nextLabel.get());
</del><ins>+                emitJumpIfFinallyActionIsNotJump(jump.jumpID, nextLabel.get());
</ins><span class="cx"> 
</span><span class="cx">                 restoreScopeRegister(jump.targetLexicalScopeIndex);
</span><del>-                emitSetCompletionType(CompletionType::Normal);
</del><ins>+                emitSetFinallyActionToNormalCompletion();
</ins><span class="cx">                 emitJump(jump.targetLabel.get());
</span><span class="cx"> 
</span><span class="cx">                 emitLabel(nextLabel.get());
</span><span class="lines">@@ -4906,46 +4901,46 @@
</span><span class="cx"> 
</span><span class="cx">             if (context.handlesReturns()) {
</span><span class="cx">                 RefPtr&lt;Label&gt; notReturnLabel = newLabel();
</span><del>-                emitJumpIfCompletionType(op_nstricteq, CompletionType::Return, notReturnLabel.get());
</del><ins>+                emitJumpIfFinallyActionIsNotReturnCompletion(notReturnLabel.get());
</ins><span class="cx"> 
</span><span class="cx">                 emitWillLeaveCallFrameDebugHook();
</span><del>-                emitReturn(completionValueRegister(), ReturnFrom::Finally);
</del><ins>+                emitReturn(finallyReturnValueRegister(), ReturnFrom::Finally);
</ins><span class="cx">                 
</span><span class="cx">                 emitLabel(notReturnLabel.get());
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-    emitThrow(completionValueRegister());
</del><ins>+    emitThrow(finallyActionRegister());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool BytecodeGenerator::allocateCompletionRecordRegisters()
</del><ins>+bool BytecodeGenerator::allocateFinallyRegisters()
</ins><span class="cx"> {
</span><del>-    if (m_completionTypeRegister)
</del><ins>+    if (m_finallyActionRegister)
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    ASSERT(!m_completionValueRegister);
-    m_completionTypeRegister = newTemporary();
-    m_completionValueRegister = newTemporary();
</del><ins>+    ASSERT(!m_finallyReturnValueRegister);
+    m_finallyActionRegister = newTemporary();
+    m_finallyReturnValueRegister = newTemporary();
</ins><span class="cx"> 
</span><del>-    emitSetCompletionType(CompletionType::Normal);
-    emitMoveEmptyValue(m_completionValueRegister.get());
</del><ins>+    emitSetFinallyActionToNormalCompletion();
+    emitMoveEmptyValue(m_finallyReturnValueRegister.get());
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BytecodeGenerator::releaseCompletionRecordRegisters()
</del><ins>+void BytecodeGenerator::releaseFinallyRegisters()
</ins><span class="cx"> {
</span><del>-    ASSERT(m_completionTypeRegister &amp;&amp; m_completionValueRegister);
-    m_completionTypeRegister = nullptr;
-    m_completionValueRegister = nullptr;
</del><ins>+    ASSERT(m_finallyActionRegister &amp;&amp; m_finallyReturnValueRegister);
+    m_finallyActionRegister = nullptr;
+    m_finallyReturnValueRegister = nullptr;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BytecodeGenerator::emitJumpIfCompletionType(OpcodeID compareOpcode, CompletionType type, Label* jumpTarget)
</del><ins>+void BytecodeGenerator::emitCompareFinallyActionAndJumpIf(OpcodeID compareOpcode, int value, Label* jumpTarget)
</ins><span class="cx"> {
</span><span class="cx">     RefPtr&lt;RegisterID&gt; tempRegister = newTemporary();
</span><del>-    RegisterID* valueConstant = addConstantValue(JSValue(static_cast&lt;int&gt;(type)));
</del><ins>+    RegisterID* valueConstant = addConstantValue(JSValue(value));
</ins><span class="cx">     OperandTypes operandTypes = OperandTypes(ResultType::numberTypeIsInt32(), ResultType::unknownType());
</span><span class="cx"> 
</span><del>-    auto equivalenceResult = emitBinaryOp(compareOpcode, tempRegister.get(), valueConstant, completionTypeRegister(), operandTypes);
</del><ins>+    auto equivalenceResult = emitBinaryOp(compareOpcode, tempRegister.get(), valueConstant, finallyActionRegister(), operandTypes);
</ins><span class="cx">     emitJumpIfTrue(equivalenceResult, jumpTarget);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (210007 => 210008)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-12-20 01:48:52 UTC (rev 210007)
+++ branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-12-20 01:55:06 UTC (rev 210008)
</span><span class="lines">@@ -80,41 +80,15 @@
</span><span class="cx">         unsigned m_padding;
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    // https://tc39.github.io/ecma262/#sec-completion-record-specification-type
-    //
-    // For the Break and Continue cases, instead of using the Break and Continue enum values
-    // below, we use the unique jumpID of the break and continue statement as the encoding
-    // for the CompletionType value. emitFinallyCompletion() uses this jumpID value later
-    // to determine the appropriate jump target to jump to after executing the relevant finally
-    // blocks. The jumpID is computed as:
-    //     jumpID = bytecodeOffset (of the break/continue node) + CompletionType::NumberOfTypes.
-    // Hence, there won't be any collision between jumpIDs and CompletionType enums.
-    enum class CompletionType : int {
-        Normal,
-        Break,
-        Continue,
-        Return,
-        Throw,
-        
-        NumberOfTypes
-    };
-
-    inline CompletionType bytecodeOffsetToJumpID(unsigned offset)
-    {
-        int jumpIDAsInt = offset + static_cast&lt;int&gt;(CompletionType::NumberOfTypes);
-        ASSERT(jumpIDAsInt &gt;= static_cast&lt;int&gt;(CompletionType::NumberOfTypes));
-        return static_cast&lt;CompletionType&gt;(jumpIDAsInt);
-    }
-
</del><span class="cx">     struct FinallyJump {
</span><del>-        FinallyJump(CompletionType jumpID, int targetLexicalScopeIndex, Label* targetLabel)
</del><ins>+        FinallyJump(int jumpID, int targetLexicalScopeIndex, Label* targetLabel)
</ins><span class="cx">             : jumpID(jumpID)
</span><span class="cx">             , targetLexicalScopeIndex(targetLexicalScopeIndex)
</span><span class="cx">             , targetLabel(targetLabel)
</span><span class="cx">         { }
</span><span class="cx"> 
</span><del>-        CompletionType jumpID;
-        int targetLexicalScopeIndex;
</del><ins>+        int jumpID { 0 };
+        int targetLexicalScopeIndex { 0 };
</ins><span class="cx">         RefPtr&lt;Label&gt; targetLabel;
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="lines">@@ -142,7 +116,7 @@
</span><span class="cx">         bool handlesReturns() const { return m_handlesReturns; }
</span><span class="cx">         void setHandlesReturns() { m_handlesReturns = true; }
</span><span class="cx"> 
</span><del>-        void registerJump(CompletionType jumpID, int lexicalScopeIndex, Label* targetLabel)
</del><ins>+        void registerJump(int jumpID, int lexicalScopeIndex, Label* targetLabel)
</ins><span class="cx">         {
</span><span class="cx">             if (!m_jumps)
</span><span class="cx">                 m_jumps = std::make_unique&lt;Vector&lt;FinallyJump&gt;&gt;();
</span><span class="lines">@@ -801,18 +775,18 @@
</span><span class="cx">         void emitDebugHook(ExpressionNode*);
</span><span class="cx">         void emitWillLeaveCallFrameDebugHook();
</span><span class="cx"> 
</span><del>-        class CompletionRecordScope {
</del><ins>+        class FinallyRegistersScope {
</ins><span class="cx">         public:
</span><del>-            CompletionRecordScope(BytecodeGenerator&amp; generator, bool needCompletionRecordRegisters = true)
</del><ins>+            FinallyRegistersScope(BytecodeGenerator&amp; generator, bool needFinallyRegisters = true)
</ins><span class="cx">                 : m_generator(generator)
</span><span class="cx">             {
</span><del>-                if (needCompletionRecordRegisters &amp;&amp; m_generator.allocateCompletionRecordRegisters())
</del><ins>+                if (needFinallyRegisters &amp;&amp; m_generator.allocateFinallyRegisters())
</ins><span class="cx">                     m_needToReleaseOnDestruction = true;
</span><span class="cx">             }
</span><del>-            ~CompletionRecordScope()
</del><ins>+            ~FinallyRegistersScope()
</ins><span class="cx">             {
</span><span class="cx">                 if (m_needToReleaseOnDestruction)
</span><del>-                    m_generator.releaseCompletionRecordRegisters();
</del><ins>+                    m_generator.releaseFinallyRegisters();
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">         private:
</span><span class="lines">@@ -820,36 +794,79 @@
</span><span class="cx">             bool m_needToReleaseOnDestruction { false };
</span><span class="cx">         };
</span><span class="cx"> 
</span><del>-        RegisterID* completionTypeRegister() const
</del><ins>+        RegisterID* finallyActionRegister() const
</ins><span class="cx">         {
</span><del>-            ASSERT(m_completionTypeRegister);
-            return m_completionTypeRegister.get();
</del><ins>+            ASSERT(m_finallyActionRegister);
+            return m_finallyActionRegister.get();
</ins><span class="cx">         }
</span><del>-        RegisterID* completionValueRegister() const
</del><ins>+        RegisterID* finallyReturnValueRegister() const
</ins><span class="cx">         {
</span><del>-            ASSERT(m_completionValueRegister);
-            return m_completionValueRegister.get();
</del><ins>+            ASSERT(m_finallyReturnValueRegister);
+            return m_finallyReturnValueRegister.get();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        void emitSetCompletionType(CompletionType type)
</del><ins>+        void emitSetFinallyActionToNormalCompletion()
</ins><span class="cx">         {
</span><del>-            emitLoad(completionTypeRegister(), JSValue(static_cast&lt;int&gt;(type)));
</del><ins>+            emitMoveEmptyValue(m_finallyActionRegister.get());
</ins><span class="cx">         }
</span><del>-        void emitSetCompletionValue(RegisterID* reg)
</del><ins>+        void emitSetFinallyActionToReturnCompletion()
</ins><span class="cx">         {
</span><del>-            emitMove(completionValueRegister(), reg);
</del><ins>+            emitLoad(finallyActionRegister(), JSValue(static_cast&lt;int&gt;(CompletionType::Return)));
</ins><span class="cx">         }
</span><ins>+        void emitSetFinallyActionToJumpID(int jumpID)
+        {
+            emitLoad(finallyActionRegister(), JSValue(jumpID));
+        }
+        void emitSetFinallyReturnValueRegister(RegisterID* reg)
+        {
+            emitMove(finallyReturnValueRegister(), reg);
+        }
</ins><span class="cx"> 
</span><del>-        void emitJumpIfCompletionType(OpcodeID compareOpcode, CompletionType, Label* jumpTarget);
</del><ins>+        void emitJumpIfFinallyActionIsNormalCompletion(Label* jumpTarget)
+        {
+            emitJumpIfTrue(emitIsEmpty(newTemporary(), finallyActionRegister()), jumpTarget);
+        }
</ins><span class="cx"> 
</span><ins>+        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);
+        }
+
</ins><span class="cx">         bool emitJumpViaFinallyIfNeeded(int targetLabelScopeDepth, Label* jumpTarget);
</span><span class="cx">         bool emitReturnViaFinallyIfNeeded(RegisterID* returnRegister);
</span><span class="cx">         void emitFinallyCompletion(FinallyContext&amp;, Label* normalCompletionLabel);
</span><span class="cx"> 
</span><span class="cx">     private:
</span><del>-        bool allocateCompletionRecordRegisters();
-        void releaseCompletionRecordRegisters();
</del><ins>+        void emitCompareFinallyActionAndJumpIf(OpcodeID compareOpcode, int value, Label* jumpTarget);
</ins><span class="cx"> 
</span><ins>+        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();
+
</ins><span class="cx">     public:
</span><span class="cx">         FinallyContext* pushFinallyControlFlowScope(Label* finallyLabel);
</span><span class="cx">         FinallyContext popFinallyControlFlowScope();
</span><span class="lines">@@ -1083,9 +1100,33 @@
</span><span class="cx">         RegisterID* m_arrowFunctionContextLexicalEnvironmentRegister { nullptr };
</span><span class="cx">         RegisterID* m_promiseCapabilityRegister { nullptr };
</span><span class="cx"> 
</span><del>-        RefPtr&lt;RegisterID&gt; m_completionTypeRegister;
-        RefPtr&lt;RegisterID&gt; m_completionValueRegister;
</del><ins>+        // 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.
</ins><span class="cx"> 
</span><ins>+        enum class CompletionType : int {
+            Normal,
+            Break,
+            Continue,
+            Return,
+            Throw,
+
+            NumberOfTypes
+        };
+
+        RefPtr&lt;RegisterID&gt; m_finallyActionRegister;
+        RefPtr&lt;RegisterID&gt; m_finallyReturnValueRegister;
+
</ins><span class="cx">         FinallyContext* m_currentFinallyContext { nullptr };
</span><span class="cx"> 
</span><span class="cx">         SegmentedVector&lt;RegisterID*, 16&gt; m_localRegistersForCalleeSaveRegisters;
</span><span class="lines">@@ -1102,7 +1143,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.
</del><ins>+        // FIXME: Restore overflow checking with UnsafeVectorOverflow once SegmentVector supports it. 
</ins><span class="cx">         // https://bugs.webkit.org/show_bug.cgi?id=165980
</span><span class="cx">         SegmentedVector&lt;ControlFlowScope, 16&gt; m_controlFlowScopeStack;
</span><span class="cx">         Vector&lt;SwitchInfo&gt; m_switchContextStack;
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (210007 => 210008)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2016-12-20 01:48:52 UTC (rev 210007)
+++ branches/safari-603-branch/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2016-12-20 01:55:06 UTC (rev 210008)
</span><span class="lines">@@ -3287,7 +3287,7 @@
</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::CompletionRecordScope completionRecordScope(generator, m_finallyBlock);
</del><ins>+    BytecodeGenerator::FinallyRegistersScope finallyRegistersScope(generator, m_finallyBlock);
</ins><span class="cx"> 
</span><span class="cx">     RefPtr&lt;Label&gt; catchLabel;
</span><span class="cx">     RefPtr&lt;Label&gt; catchEndLabel;
</span><span class="lines">@@ -3316,6 +3316,7 @@
</span><span class="cx"> 
</span><span class="cx">     generator.emitNode(dst, m_tryBlock);
</span><span class="cx"> 
</span><ins>+    // The finallyActionRegister is an empty value by default, which implies CompletionType::Normal.
</ins><span class="cx">     if (m_finallyBlock)
</span><span class="cx">         generator.emitJump(finallyLabel.get());
</span><span class="cx">     else
</span><span class="lines">@@ -3350,7 +3351,7 @@
</span><span class="cx">         generator.emitPopCatchScope(m_lexicalVariables);
</span><span class="cx"> 
</span><span class="cx">         if (m_finallyBlock) {
</span><del>-            generator.emitSetCompletionType(CompletionType::Normal);
</del><ins>+            generator.emitSetFinallyActionToNormalCompletion();
</ins><span class="cx">             generator.emitJump(finallyLabel.get());
</span><span class="cx">             generator.popTry(tryData, finallyViaThrowLabel.get());
</span><span class="cx">         }
</span><span class="lines">@@ -3365,8 +3366,8 @@
</span><span class="cx">         // Entry to the finally block for CompletionType::Throw.
</span><span class="cx">         generator.emitLabel(finallyViaThrowLabel.get());
</span><span class="cx">         RegisterID* unused = generator.newTemporary();
</span><del>-        generator.emitCatch(generator.completionValueRegister(), unused);
-        generator.emitSetCompletionType(CompletionType::Throw);
</del><ins>+        generator.emitCatch(generator.finallyActionRegister(), unused);
+        // Setting the finallyActionRegister to the caught exception here implies CompletionType::Throw.
</ins><span class="cx"> 
</span><span class="cx">         // Entry to the finally block for CompletionTypes other than Throw.
</span><span class="cx">         generator.emitLabel(finallyLabel.get());
</span></span></pre>
</div>
</div>

</body>
</html>