<!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>[210007] trunk/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/210007">210007</a></dd>
<dt>Author</dt> <dd>mark.lam@apple.com</dd>
<dt>Date</dt> <dd>2016-12-19 17:48:52 -0800 (Mon, 19 Dec 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>Rolling out <a href="http://trac.webkit.org/projects/webkit/changeset/209974">r209974</a> and <a href="http://trac.webkit.org/projects/webkit/changeset/209952">r209952</a>. They break some websites in mysterious ways. Step 1: Rollout <a href="http://trac.webkit.org/projects/webkit/changeset/209974">r209974</a>.
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):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerNodesCodegencpp">trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (210006 => 210007)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-12-20 01:18:57 UTC (rev 210006)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-12-20 01:48:52 UTC (rev 210007)
</span><span class="lines">@@ -1,3 +1,49 @@
</span><ins>+2016-12-19 Mark Lam <mark.lam@apple.com>
+
+ 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 Joseph Pecoraro <pecoraro@apple.com>
</span><span class="cx">
</span><span class="cx"> Web Inspector: Assertion seen in InspectorDebuggerAgent::refAsyncCallData with Inspector open
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (210006 => 210007)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-12-20 01:18:57 UTC (rev 210006)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-12-20 01:48:52 UTC (rev 210007)
</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<void(BytecodeGenerator&, RegisterID*)>& 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<RegisterID> 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<Label> finallyBodyLabel = newLabel();
- RefPtr<RegisterID> 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<Label> finallyDone = newLabel();
</span><span class="lines">@@ -4189,6 +4181,9 @@
</span><span class="cx"> RefPtr<RegisterID> 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<RegisterID> originalFinallyActionRegister = newTemporary();
+ emitMove(originalFinallyActionRegister.get(), finallyActionRegister());
+
</ins><span class="cx"> RefPtr<Label> 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<RegisterID> 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<Label> 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->registerJump(jumpID, lexicalScopeIndex, jumpTarget);
</span><span class="cx">
</span><del>- emitSetCompletionType(jumpID);
</del><ins>+ emitSetFinallyActionToJumpID(jumpID);
</ins><span class="cx"> emitJump(innermostFinallyContext->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->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& 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 < numberOfJumps; i++) {
</span><span class="cx"> RefPtr<Label> nextLabel = newLabel();
</span><span class="cx"> auto& 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() > numberOfJumps;
</span><span class="cx"> if (hasBreaksOrContinuesNotCoveredByJumps || context.handlesReturns())
</span><del>- emitJumpIfCompletionType(op_nstricteq, CompletionType::Throw, outerContext->finallyLabel());
</del><ins>+ emitJumpIfFinallyActionIsNotThrowCompletion(outerContext->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 < numberOfJumps; i++) {
</span><span class="cx"> RefPtr<Label> nextLabel = newLabel();
</span><span class="cx"> auto& 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<Label> 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 && m_completionValueRegister);
- m_completionTypeRegister = nullptr;
- m_completionValueRegister = nullptr;
</del><ins>+ ASSERT(m_finallyActionRegister && 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<RegisterID> tempRegister = newTemporary();
</span><del>- RegisterID* valueConstant = addConstantValue(JSValue(static_cast<int>(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="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (210006 => 210007)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-12-20 01:18:57 UTC (rev 210006)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-12-20 01:48:52 UTC (rev 210007)
</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<int>(CompletionType::NumberOfTypes);
- ASSERT(jumpIDAsInt >= static_cast<int>(CompletionType::NumberOfTypes));
- return static_cast<CompletionType>(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<Label> 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<Vector<FinallyJump>>();
</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& generator, bool needCompletionRecordRegisters = true)
</del><ins>+ FinallyRegistersScope(BytecodeGenerator& generator, bool needFinallyRegisters = true)
</ins><span class="cx"> : m_generator(generator)
</span><span class="cx"> {
</span><del>- if (needCompletionRecordRegisters && m_generator.allocateCompletionRecordRegisters())
</del><ins>+ if (needFinallyRegisters && 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<int>(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<int>(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<int>(CompletionType::Return), jumpTarget);
+ }
+ void emitJumpIfFinallyActionIsNotReturnCompletion(Label* jumpTarget)
+ {
+ emitCompareFinallyActionAndJumpIf(op_nstricteq, static_cast<int>(CompletionType::Return), jumpTarget);
+ }
+
+ void emitJumpIfFinallyActionIsNotThrowCompletion(Label* jumpTarget)
+ {
+ emitJumpIfTrue(emitIsNumber(newTemporary(), finallyActionRegister()), jumpTarget);
+ }
+ void emitJumpIfCompletionTypeIsThrow(RegisterID* reg, Label* jumpTarget)
+ {
+ emitJumpIfFalse(emitIsNumber(newTemporary(), reg), jumpTarget);
+ }
+
</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&, 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<int>(CompletionType::NumberOfTypes);
+ ASSERT(jumpID >= static_cast<int>(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<RegisterID> m_completionTypeRegister;
- RefPtr<RegisterID> 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<RegisterID> m_finallyActionRegister;
+ RefPtr<RegisterID> m_finallyReturnValueRegister;
+
</ins><span class="cx"> FinallyContext* m_currentFinallyContext { nullptr };
</span><span class="cx">
</span><span class="cx"> SegmentedVector<RegisterID*, 16> 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<ControlFlowScope, 16> m_controlFlowScopeStack;
</span><span class="cx"> Vector<SwitchInfo> m_switchContextStack;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (210006 => 210007)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2016-12-20 01:18:57 UTC (rev 210006)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2016-12-20 01:48:52 UTC (rev 210007)
</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<Label> catchLabel;
</span><span class="cx"> RefPtr<Label> 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>