<!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>[186822] branches/jsc-tailcall/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/186822">186822</a></dd>
<dt>Author</dt> <dd>basile_clement@apple.com</dd>
<dt>Date</dt> <dd>2015-07-14 15:33:32 -0700 (Tue, 14 Jul 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>[ES6] Recognize calls in tail position
https://bugs.webkit.org/show_bug.cgi?id=146481
Reviewed by Saam Barati.
This patch adds the capability for the bytecode generator to recognize
and dispatch tail calls, as per ES6 spec:
http://www.ecma-international.org/ecma-262/6.0/#sec-isintailposition
This does not change the generated bytecode, but merely provides the
hook for generating tail calls in subsequent patches toward
https://bugs.webkit.org/show_bug.cgi?id=146477
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitTailCall):
(JSC::BytecodeGenerator::emitTailCallVarargs):
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::emitNode):
* bytecompiler/NodesCodegen.cpp:
(JSC::ConstantNode::emitBytecode):
(JSC::NumberNode::emitBytecode):
(JSC::RegExpNode::emitBytecode):
(JSC::ThisNode::emitBytecode):
(JSC::SuperNode::emitBytecode):
(JSC::ResolveNode::emitBytecode):
(JSC::TemplateStringNode::emitBytecode):
(JSC::TemplateLiteralNode::emitBytecode):
(JSC::TaggedTemplateNode::emitBytecode):
(JSC::ArrayNode::emitBytecode):
(JSC::ObjectLiteralNode::emitBytecode):
(JSC::PropertyListNode::emitBytecode):
(JSC::BracketAccessorNode::emitBytecode):
(JSC::DotAccessorNode::emitBytecode):
(JSC::ArgumentListNode::emitBytecode):
(JSC::NewExprNode::emitBytecode):
(JSC::EvalFunctionCallNode::emitBytecode):
(JSC::FunctionCallValueNode::emitBytecode):
(JSC::FunctionCallResolveNode::emitBytecode):
(JSC::BytecodeIntrinsicNode::emitBytecode):
(JSC::FunctionCallBracketNode::emitBytecode):
(JSC::FunctionCallDotNode::emitBytecode):
(JSC::CallFunctionCallDotNode::emitBytecode):
(JSC::ApplyFunctionCallDotNode::emitBytecode):
(JSC::PostfixNode::emitBytecode):
(JSC::DeleteResolveNode::emitBytecode):
(JSC::DeleteBracketNode::emitBytecode):
(JSC::DeleteDotNode::emitBytecode):
(JSC::DeleteValueNode::emitBytecode):
(JSC::VoidNode::emitBytecode):
(JSC::TypeOfResolveNode::emitBytecode):
(JSC::TypeOfValueNode::emitBytecode):
(JSC::PrefixNode::emitBytecode):
(JSC::UnaryOpNode::emitBytecode):
(JSC::BitwiseNotNode::emitBytecode):
(JSC::BinaryOpNode::emitBytecode):
(JSC::EqualNode::emitBytecode):
(JSC::StrictEqualNode::emitBytecode):
(JSC::ThrowableBinaryOpNode::emitBytecode):
(JSC::InstanceOfNode::emitBytecode):
(JSC::LogicalOpNode::emitBytecode):
(JSC::ConditionalNode::emitBytecode):
(JSC::ReadModifyResolveNode::emitBytecode):
(JSC::AssignResolveNode::emitBytecode):
(JSC::AssignDotNode::emitBytecode):
(JSC::ReadModifyDotNode::emitBytecode):
(JSC::AssignErrorNode::emitBytecode):
(JSC::AssignBracketNode::emitBytecode):
(JSC::ReadModifyBracketNode::emitBytecode):
(JSC::CommaNode::emitBytecode):
(JSC::ConstDeclNode::emitBytecode):
(JSC::ConstStatementNode::emitBytecode):
(JSC::SourceElements::emitBytecode):
(JSC::BlockNode::emitBytecode):
(JSC::EmptyStatementNode::emitBytecode):
(JSC::DebuggerStatementNode::emitBytecode):
(JSC::ExprStatementNode::emitBytecode):
(JSC::VarStatementNode::emitBytecode):
(JSC::EmptyVarExpression::emitBytecode):
(JSC::IfElseNode::emitBytecode):
(JSC::DoWhileNode::emitBytecode):
(JSC::WhileNode::emitBytecode):
(JSC::ForNode::emitBytecode):
(JSC::ForInNode::emitBytecode):
(JSC::ForOfNode::emitBytecode):
(JSC::ContinueNode::emitBytecode):
(JSC::BreakNode::emitBytecode):
(JSC::ReturnNode::emitBytecode):
(JSC::WithNode::emitBytecode):
(JSC::CaseClauseNode::emitBytecode):
(JSC::CaseBlockNode::emitBytecodeForBlock):
(JSC::SwitchNode::emitBytecode):
(JSC::LabelNode::emitBytecode):
(JSC::ThrowNode::emitBytecode):
(JSC::TryNode::emitBytecode):
(JSC::ScopeNode::emitStatementsBytecode):
(JSC::ProgramNode::emitBytecode):
(JSC::EvalNode::emitBytecode):
(JSC::FunctionBodyNode::emitBytecode):
(JSC::FunctionNode::emitBytecode):
(JSC::FuncDeclNode::emitBytecode):
(JSC::FuncExprNode::emitBytecode):
(JSC::ClassDeclNode::emitBytecode):
(JSC::ClassExprNode::emitBytecode):
(JSC::DestructuringAssignmentNode::emitBytecode):
(JSC::SpreadExpressionNode::emitBytecode):
* parser/Nodes.h:</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#branchesjsctailcallSourceJavaScriptCoreChangeLog">branches/jsc-tailcall/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchesjsctailcallSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">branches/jsc-tailcall/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#branchesjsctailcallSourceJavaScriptCorebytecompilerBytecodeGeneratorh">branches/jsc-tailcall/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h</a></li>
<li><a href="#branchesjsctailcallSourceJavaScriptCorebytecompilerNodesCodegencpp">branches/jsc-tailcall/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</a></li>
<li><a href="#branchesjsctailcallSourceJavaScriptCoreparserNodesh">branches/jsc-tailcall/Source/JavaScriptCore/parser/Nodes.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchesjsctailcallSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/jsc-tailcall/Source/JavaScriptCore/ChangeLog (186821 => 186822)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/ChangeLog        2015-07-14 22:24:54 UTC (rev 186821)
+++ branches/jsc-tailcall/Source/JavaScriptCore/ChangeLog        2015-07-14 22:33:32 UTC (rev 186822)
</span><span class="lines">@@ -1,3 +1,112 @@
</span><ins>+2015-07-14 Basile Clement <basile_clement@apple.com>
+
+ [ES6] Recognize calls in tail position
+ https://bugs.webkit.org/show_bug.cgi?id=146481
+
+ Reviewed by Saam Barati.
+
+ This patch adds the capability for the bytecode generator to recognize
+ and dispatch tail calls, as per ES6 spec:
+ http://www.ecma-international.org/ecma-262/6.0/#sec-isintailposition
+
+ This does not change the generated bytecode, but merely provides the
+ hook for generating tail calls in subsequent patches toward
+ https://bugs.webkit.org/show_bug.cgi?id=146477
+
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitTailCall):
+ (JSC::BytecodeGenerator::emitTailCallVarargs):
+ * bytecompiler/BytecodeGenerator.h:
+ (JSC::BytecodeGenerator::emitNode):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::ConstantNode::emitBytecode):
+ (JSC::NumberNode::emitBytecode):
+ (JSC::RegExpNode::emitBytecode):
+ (JSC::ThisNode::emitBytecode):
+ (JSC::SuperNode::emitBytecode):
+ (JSC::ResolveNode::emitBytecode):
+ (JSC::TemplateStringNode::emitBytecode):
+ (JSC::TemplateLiteralNode::emitBytecode):
+ (JSC::TaggedTemplateNode::emitBytecode):
+ (JSC::ArrayNode::emitBytecode):
+ (JSC::ObjectLiteralNode::emitBytecode):
+ (JSC::PropertyListNode::emitBytecode):
+ (JSC::BracketAccessorNode::emitBytecode):
+ (JSC::DotAccessorNode::emitBytecode):
+ (JSC::ArgumentListNode::emitBytecode):
+ (JSC::NewExprNode::emitBytecode):
+ (JSC::EvalFunctionCallNode::emitBytecode):
+ (JSC::FunctionCallValueNode::emitBytecode):
+ (JSC::FunctionCallResolveNode::emitBytecode):
+ (JSC::BytecodeIntrinsicNode::emitBytecode):
+ (JSC::FunctionCallBracketNode::emitBytecode):
+ (JSC::FunctionCallDotNode::emitBytecode):
+ (JSC::CallFunctionCallDotNode::emitBytecode):
+ (JSC::ApplyFunctionCallDotNode::emitBytecode):
+ (JSC::PostfixNode::emitBytecode):
+ (JSC::DeleteResolveNode::emitBytecode):
+ (JSC::DeleteBracketNode::emitBytecode):
+ (JSC::DeleteDotNode::emitBytecode):
+ (JSC::DeleteValueNode::emitBytecode):
+ (JSC::VoidNode::emitBytecode):
+ (JSC::TypeOfResolveNode::emitBytecode):
+ (JSC::TypeOfValueNode::emitBytecode):
+ (JSC::PrefixNode::emitBytecode):
+ (JSC::UnaryOpNode::emitBytecode):
+ (JSC::BitwiseNotNode::emitBytecode):
+ (JSC::BinaryOpNode::emitBytecode):
+ (JSC::EqualNode::emitBytecode):
+ (JSC::StrictEqualNode::emitBytecode):
+ (JSC::ThrowableBinaryOpNode::emitBytecode):
+ (JSC::InstanceOfNode::emitBytecode):
+ (JSC::LogicalOpNode::emitBytecode):
+ (JSC::ConditionalNode::emitBytecode):
+ (JSC::ReadModifyResolveNode::emitBytecode):
+ (JSC::AssignResolveNode::emitBytecode):
+ (JSC::AssignDotNode::emitBytecode):
+ (JSC::ReadModifyDotNode::emitBytecode):
+ (JSC::AssignErrorNode::emitBytecode):
+ (JSC::AssignBracketNode::emitBytecode):
+ (JSC::ReadModifyBracketNode::emitBytecode):
+ (JSC::CommaNode::emitBytecode):
+ (JSC::ConstDeclNode::emitBytecode):
+ (JSC::ConstStatementNode::emitBytecode):
+ (JSC::SourceElements::emitBytecode):
+ (JSC::BlockNode::emitBytecode):
+ (JSC::EmptyStatementNode::emitBytecode):
+ (JSC::DebuggerStatementNode::emitBytecode):
+ (JSC::ExprStatementNode::emitBytecode):
+ (JSC::VarStatementNode::emitBytecode):
+ (JSC::EmptyVarExpression::emitBytecode):
+ (JSC::IfElseNode::emitBytecode):
+ (JSC::DoWhileNode::emitBytecode):
+ (JSC::WhileNode::emitBytecode):
+ (JSC::ForNode::emitBytecode):
+ (JSC::ForInNode::emitBytecode):
+ (JSC::ForOfNode::emitBytecode):
+ (JSC::ContinueNode::emitBytecode):
+ (JSC::BreakNode::emitBytecode):
+ (JSC::ReturnNode::emitBytecode):
+ (JSC::WithNode::emitBytecode):
+ (JSC::CaseClauseNode::emitBytecode):
+ (JSC::CaseBlockNode::emitBytecodeForBlock):
+ (JSC::SwitchNode::emitBytecode):
+ (JSC::LabelNode::emitBytecode):
+ (JSC::ThrowNode::emitBytecode):
+ (JSC::TryNode::emitBytecode):
+ (JSC::ScopeNode::emitStatementsBytecode):
+ (JSC::ProgramNode::emitBytecode):
+ (JSC::EvalNode::emitBytecode):
+ (JSC::FunctionBodyNode::emitBytecode):
+ (JSC::FunctionNode::emitBytecode):
+ (JSC::FuncDeclNode::emitBytecode):
+ (JSC::FuncExprNode::emitBytecode):
+ (JSC::ClassDeclNode::emitBytecode):
+ (JSC::ClassExprNode::emitBytecode):
+ (JSC::DestructuringAssignmentNode::emitBytecode):
+ (JSC::SpreadExpressionNode::emitBytecode):
+ * parser/Nodes.h:
+
</ins><span class="cx"> 2015-07-13 Basile Clement <basile_clement@apple.com>
</span><span class="cx">
</span><span class="cx"> jsc-tailcall: Get rid of the arity fixup return thunk
</span></span></pre></div>
<a id="branchesjsctailcallSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: branches/jsc-tailcall/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (186821 => 186822)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-07-14 22:24:54 UTC (rev 186821)
+++ branches/jsc-tailcall/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-07-14 22:33:32 UTC (rev 186822)
</span><span class="lines">@@ -1836,6 +1836,13 @@
</span><span class="cx"> return emitCall(op_call, dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+RegisterID* BytecodeGenerator::emitTailCall(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
+{
+ // FIXME: We should be emitting a new op_tail_call here
+ // https://bugs.webkit.org/show_bug.cgi?id=146484
+ return emitCall(op_call, dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd);
+}
+
</ins><span class="cx"> RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
</span><span class="cx"> {
</span><span class="cx"> return emitCall(op_call_eval, dst, func, NoExpectedFunction, callArguments, divot, divotStart, divotEnd);
</span><span class="lines">@@ -1985,6 +1992,13 @@
</span><span class="cx"> return emitCallVarargs(op_call_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+RegisterID* BytecodeGenerator::emitTailCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
+{
+ // FIXME: We should be emitting a new op_tail_call_varargs here
+ // https://bugs.webkit.org/show_bug.cgi?id=146484
+ return emitCallVarargs(op_call_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
+}
+
</ins><span class="cx"> RegisterID* BytecodeGenerator::emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
</span><span class="cx"> {
</span><span class="cx"> return emitCallVarargs(op_construct_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
</span></span></pre></div>
<a id="branchesjsctailcallSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: branches/jsc-tailcall/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (186821 => 186822)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2015-07-14 22:24:54 UTC (rev 186821)
+++ branches/jsc-tailcall/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2015-07-14 22:33:32 UTC (rev 186822)
</span><span class="lines">@@ -344,7 +344,7 @@
</span><span class="cx"> LabelScopePtr newLabelScope(LabelScope::Type, const Identifier* = 0);
</span><span class="cx"> PassRefPtr<Label> newLabel();
</span><span class="cx">
</span><del>- void emitNode(RegisterID* dst, StatementNode* n)
</del><ins>+ void emitNode(RegisterID* dst, StatementNode* n, TailCallMode tailCallMode = NoTailCalls)
</ins><span class="cx"> {
</span><span class="cx"> // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
</span><span class="cx"> ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
</span><span class="lines">@@ -352,7 +352,7 @@
</span><span class="cx"> emitThrowExpressionTooDeepException();
</span><span class="cx"> return;
</span><span class="cx"> }
</span><del>- n->emitBytecode(*this, dst);
</del><ins>+ n->emitBytecode(*this, dst, tailCallMode);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void emitNode(StatementNode* n)
</span><span class="lines">@@ -360,13 +360,13 @@
</span><span class="cx"> emitNode(0, n);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- RegisterID* emitNode(RegisterID* dst, ExpressionNode* n)
</del><ins>+ RegisterID* emitNode(RegisterID* dst, ExpressionNode* n, TailCallMode tailCallMode = NoTailCalls)
</ins><span class="cx"> {
</span><span class="cx"> // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
</span><span class="cx"> ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
</span><span class="cx"> if (!m_vm->isSafeToRecurse())
</span><span class="cx"> return emitThrowExpressionTooDeepException();
</span><del>- return n->emitBytecode(*this, dst);
</del><ins>+ return n->emitBytecode(*this, dst, tailCallMode);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> RegisterID* emitNode(ExpressionNode* n)
</span><span class="lines">@@ -492,8 +492,10 @@
</span><span class="cx">
</span><span class="cx"> ExpectedFunction expectedFunctionForIdentifier(const Identifier&);
</span><span class="cx"> RegisterID* emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><ins>+ RegisterID* emitTailCall(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</ins><span class="cx"> RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx"> RegisterID* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><ins>+ RegisterID* emitTailCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</ins><span class="cx">
</span><span class="cx"> enum PropertyDescriptorOption {
</span><span class="cx"> PropertyConfigurable = 1,
</span></span></pre></div>
<a id="branchesjsctailcallSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: branches/jsc-tailcall/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (186821 => 186822)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-07-14 22:24:54 UTC (rev 186821)
+++ branches/jsc-tailcall/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-07-14 22:33:32 UTC (rev 186822)
</span><span class="lines">@@ -112,7 +112,7 @@
</span><span class="cx"> // All other cases are unconditional fall-throughs, like "if (true)".
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* ConstantNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* ConstantNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (dst == generator.ignoredResult())
</span><span class="cx"> return 0;
</span><span class="lines">@@ -126,7 +126,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ NumberNode ----------------------------------
</span><span class="cx">
</span><del>-RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (dst == generator.ignoredResult())
</span><span class="cx"> return nullptr;
</span><span class="lines">@@ -135,7 +135,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ RegExpNode -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (dst == generator.ignoredResult())
</span><span class="cx"> return 0;
</span><span class="lines">@@ -144,7 +144,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ ThisNode -------------------------------------
</span><span class="cx">
</span><del>-RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (m_shouldAlwaysEmitTDZCheck || generator.constructorKind() == ConstructorKind::Derived)
</span><span class="cx"> generator.emitTDZCheck(generator.thisRegister());
</span><span class="lines">@@ -163,7 +163,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ SuperNode -------------------------------------
</span><span class="cx">
</span><del>-RegisterID* SuperNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* SuperNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (dst == generator.ignoredResult())
</span><span class="cx"> return 0;
</span><span class="lines">@@ -192,7 +192,7 @@
</span><span class="cx"> return generator.variable(m_ident).offset().isStack();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> Variable var = generator.variable(m_ident);
</span><span class="cx"> if (RegisterID* local = var.local()) {
</span><span class="lines">@@ -220,7 +220,7 @@
</span><span class="cx"> #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
</span><span class="cx"> // ------------------------------ TemplateStringNode -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* TemplateStringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* TemplateStringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (dst == generator.ignoredResult())
</span><span class="cx"> return nullptr;
</span><span class="lines">@@ -229,7 +229,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ TemplateLiteralNode -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* TemplateLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* TemplateLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (!m_templateExpressions) {
</span><span class="cx"> TemplateStringNode* templateString = m_templateStrings->value();
</span><span class="lines">@@ -265,7 +265,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ TaggedTemplateNode -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* TaggedTemplateNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* TaggedTemplateNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> ExpectedFunction expectedFunction = NoExpectedFunction;
</span><span class="cx"> RefPtr<RegisterID> tag = nullptr;
</span><span class="lines">@@ -327,7 +327,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ ArrayNode ------------------------------------
</span><span class="cx">
</span><del>-RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> // FIXME: Should we put all of this code into emitNewArray?
</span><span class="cx">
</span><span class="lines">@@ -417,7 +417,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ ObjectLiteralNode ----------------------------
</span><span class="cx">
</span><del>-RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (!m_list) {
</span><span class="cx"> if (dst == generator.ignoredResult())
</span><span class="lines">@@ -436,7 +436,7 @@
</span><span class="cx"> generator.emitPutById(function, generator.propertyNames().homeObjectPrivateName, homeObject);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> // Fast case: this loop just handles regular value properties.
</span><span class="cx"> PropertyListNode* p = this;
</span><span class="lines">@@ -586,7 +586,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ BracketAccessorNode --------------------------------
</span><span class="cx">
</span><del>-RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (m_base->isSuperNode()) {
</span><span class="cx"> // FIXME: Should we generate the profiler info?
</span><span class="lines">@@ -620,7 +620,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ DotAccessorNode --------------------------------
</span><span class="cx">
</span><del>-RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> base = m_base->isSuperNode() ? emitSuperBaseForCallee(generator) : generator.emitNode(m_base);
</span><span class="cx"> generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><span class="lines">@@ -635,7 +635,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ ArgumentListNode -----------------------------
</span><span class="cx">
</span><del>-RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(m_expr);
</span><span class="cx"> return generator.emitNode(dst, m_expr);
</span><span class="lines">@@ -643,7 +643,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ NewExprNode ----------------------------------
</span><span class="cx">
</span><del>-RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> ExpectedFunction expectedFunction;
</span><span class="cx"> if (m_expr->isResolveNode())
</span><span class="lines">@@ -684,7 +684,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ EvalFunctionCallNode ----------------------------------
</span><span class="cx">
</span><del>-RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> Variable var = generator.variable(generator.propertyNames().eval);
</span><span class="cx"> if (RegisterID* local = var.local()) {
</span><span class="lines">@@ -707,7 +707,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ FunctionCallValueNode ----------------------------------
</span><span class="cx">
</span><del>-RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> func = generator.emitNode(m_expr);
</span><span class="cx"> RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
</span><span class="lines">@@ -721,7 +721,11 @@
</span><span class="cx"> return ret;
</span><span class="cx"> }
</span><span class="cx"> generator.emitLoad(callArguments.thisRegister(), jsUndefined());
</span><del>- RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</del><ins>+ RegisterID* ret;
+ if (tailCallMode == CanHaveTailCalls)
+ ret = generator.emitTailCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ else
+ ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</ins><span class="cx"> if (generator.vm()->typeProfiler()) {
</span><span class="cx"> generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
</span><span class="cx"> generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
</span><span class="lines">@@ -731,7 +735,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ FunctionCallResolveNode ----------------------------------
</span><span class="cx">
</span><del>-RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident);
</span><span class="cx">
</span><span class="lines">@@ -743,7 +747,11 @@
</span><span class="cx"> generator.emitLoad(callArguments.thisRegister(), jsUndefined());
</span><span class="cx"> // This passes NoExpectedFunction because we expect that if the function is in a
</span><span class="cx"> // local variable, then it's not one of our built-in constructors.
</span><del>- RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</del><ins>+ RegisterID* ret;
+ if (tailCallMode == CanHaveTailCalls)
+ ret = generator.emitTailCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ else
+ ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</ins><span class="cx"> if (generator.vm()->typeProfiler()) {
</span><span class="cx"> generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
</span><span class="cx"> generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
</span><span class="lines">@@ -761,7 +769,11 @@
</span><span class="cx"> callArguments.thisRegister(),
</span><span class="cx"> generator.emitResolveScope(callArguments.thisRegister(), var));
</span><span class="cx"> generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
</span><del>- RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
</del><ins>+ RegisterID* ret;
+ if (tailCallMode == CanHaveTailCalls)
+ ret = generator.emitTailCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ else
+ ret = generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
</ins><span class="cx"> if (generator.vm()->typeProfiler()) {
</span><span class="cx"> generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
</span><span class="cx"> generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
</span><span class="lines">@@ -771,7 +783,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ BytecodeIntrinsicNode ----------------------------------
</span><span class="cx">
</span><del>-RegisterID* BytecodeIntrinsicNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* BytecodeIntrinsicNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> return (this->*m_emitter)(generator, dst);
</span><span class="cx"> }
</span><span class="lines">@@ -801,7 +813,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ FunctionCallBracketNode ----------------------------------
</span><span class="cx">
</span><del>-RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> bool baseIsSuper = m_base->isSuperNode();
</span><span class="cx"> bool subscriptIsString = m_subscript->isString();
</span><span class="lines">@@ -832,7 +844,11 @@
</span><span class="cx"> generator.emitMove(callArguments.thisRegister(), generator.thisRegister());
</span><span class="cx"> else
</span><span class="cx"> generator.emitMove(callArguments.thisRegister(), base.get());
</span><del>- RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</del><ins>+ RegisterID* ret;
+ if (tailCallMode == CanHaveTailCalls)
+ ret = generator.emitTailCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ else
+ ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</ins><span class="cx"> if (generator.vm()->typeProfiler()) {
</span><span class="cx"> generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
</span><span class="cx"> generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
</span><span class="lines">@@ -842,7 +858,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ FunctionCallDotNode ----------------------------------
</span><span class="cx">
</span><del>-RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> function = generator.tempDestination(dst);
</span><span class="cx"> RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
</span><span class="lines">@@ -854,7 +870,11 @@
</span><span class="cx"> generator.emitNode(callArguments.thisRegister(), m_base);
</span><span class="cx"> generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
</span><span class="cx"> generator.emitGetById(function.get(), baseIsSuper ? emitSuperBaseForCallee(generator) : callArguments.thisRegister(), m_ident);
</span><del>- RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</del><ins>+ RegisterID* ret;
+ if (tailCallMode == CanHaveTailCalls)
+ ret = generator.emitTailCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ else
+ ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</ins><span class="cx"> if (generator.vm()->typeProfiler()) {
</span><span class="cx"> generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
</span><span class="cx"> generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
</span><span class="lines">@@ -862,7 +882,7 @@
</span><span class="cx"> return ret;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<Label> realCall = generator.newLabel();
</span><span class="cx"> RefPtr<Label> end = generator.newLabel();
</span><span class="lines">@@ -886,7 +906,10 @@
</span><span class="cx"> argumentsRegister = generator.emitNode(subject);
</span><span class="cx"> generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd());
</span><span class="cx"> RefPtr<RegisterID> thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0)));
</span><del>- generator.emitCallVarargs(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, profileHookRegister.get(), divot(), divotStart(), divotEnd());
</del><ins>+ if (tailCallMode == CanHaveTailCalls)
+ generator.emitTailCallVarargs(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, profileHookRegister.get(), divot(), divotStart(), divotEnd());
+ else
+ generator.emitCallVarargs(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, profileHookRegister.get(), divot(), divotStart(), divotEnd());
</ins><span class="cx"> } else if (m_args->m_listNode && m_args->m_listNode->m_expr) {
</span><span class="cx"> ArgumentListNode* oldList = m_args->m_listNode;
</span><span class="cx"> m_args->m_listNode = m_args->m_listNode->m_next;
</span><span class="lines">@@ -894,13 +917,19 @@
</span><span class="cx"> RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
</span><span class="cx"> CallArguments callArguments(generator, m_args);
</span><span class="cx"> generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
</span><del>- generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</del><ins>+ if (tailCallMode == CanHaveTailCalls)
+ generator.emitTailCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ else
+ generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</ins><span class="cx"> m_args->m_listNode = oldList;
</span><span class="cx"> } else {
</span><span class="cx"> RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
</span><span class="cx"> CallArguments callArguments(generator, m_args);
</span><span class="cx"> generator.emitLoad(callArguments.thisRegister(), jsUndefined());
</span><del>- generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</del><ins>+ if (tailCallMode == CanHaveTailCalls)
+ generator.emitTailCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ else
+ generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx"> if (emitCallCheck) {
</span><span class="lines">@@ -909,7 +938,10 @@
</span><span class="cx"> {
</span><span class="cx"> CallArguments callArguments(generator, m_args);
</span><span class="cx"> generator.emitMove(callArguments.thisRegister(), base.get());
</span><del>- generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</del><ins>+ if (tailCallMode == CanHaveTailCalls)
+ generator.emitTailCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ else
+ generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</ins><span class="cx"> }
</span><span class="cx"> generator.emitLabel(end.get());
</span><span class="cx"> }
</span><span class="lines">@@ -926,7 +958,7 @@
</span><span class="cx"> || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> // A few simple cases can be trivially handled as ordinary function calls.
</span><span class="cx"> // function.apply(), function.apply(arg) -> identical to function.call
</span><span class="lines">@@ -975,7 +1007,10 @@
</span><span class="cx"> generator.emitLabel(end.get());
</span><span class="cx"> };
</span><span class="cx"> generator.emitEnumeration(this, spread->expression(), extractor);
</span><del>- generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
</del><ins>+ if (tailCallMode == CanHaveTailCalls)
+ generator.emitTailCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
+ else
+ generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
</ins><span class="cx"> } else if (m_args->m_listNode->m_next) {
</span><span class="cx"> ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
</span><span class="cx"> ASSERT(!m_args->m_listNode->m_next->m_next);
</span><span class="lines">@@ -983,20 +1018,29 @@
</span><span class="cx"> RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
</span><span class="cx"> CallArguments callArguments(generator, m_args);
</span><span class="cx"> generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
</span><del>- generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</del><ins>+ if (tailCallMode == CanHaveTailCalls)
+ generator.emitTailCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ else
+ generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</ins><span class="cx"> } else {
</span><span class="cx"> m_args->m_listNode = m_args->m_listNode->m_next;
</span><span class="cx"> RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
</span><span class="cx"> CallArguments callArguments(generator, m_args);
</span><span class="cx"> generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
</span><del>- generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</del><ins>+ if (tailCallMode == CanHaveTailCalls)
+ generator.emitTailCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ else
+ generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</ins><span class="cx"> }
</span><span class="cx"> m_args->m_listNode = oldList;
</span><span class="cx"> } else {
</span><span class="cx"> RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
</span><span class="cx"> CallArguments callArguments(generator, m_args);
</span><span class="cx"> generator.emitLoad(callArguments.thisRegister(), jsUndefined());
</span><del>- generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</del><ins>+ if (tailCallMode == CanHaveTailCalls)
+ generator.emitTailCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ else
+ generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</ins><span class="cx"> }
</span><span class="cx"> } else {
</span><span class="cx"> ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
</span><span class="lines">@@ -1014,14 +1058,20 @@
</span><span class="cx"> while ((args = args->m_next))
</span><span class="cx"> generator.emitNode(args->m_expr);
</span><span class="cx">
</span><del>- generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
</del><ins>+ if (tailCallMode == CanHaveTailCalls)
+ generator.emitTailCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
+ else
+ generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
</ins><span class="cx"> }
</span><span class="cx"> if (emitCallCheck) {
</span><span class="cx"> generator.emitJump(end.get());
</span><span class="cx"> generator.emitLabel(realCall.get());
</span><span class="cx"> CallArguments callArguments(generator, m_args);
</span><span class="cx"> generator.emitMove(callArguments.thisRegister(), base.get());
</span><del>- generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</del><ins>+ if (tailCallMode == CanHaveTailCalls)
+ generator.emitTailCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ else
+ generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</ins><span class="cx"> generator.emitLabel(end.get());
</span><span class="cx"> }
</span><span class="cx"> if (generator.vm()->typeProfiler()) {
</span><span class="lines">@@ -1139,7 +1189,7 @@
</span><span class="cx"> return generator.moveToDestinationIfNeeded(dst, oldValue);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (m_expr->isResolveNode())
</span><span class="cx"> return emitResolve(generator, dst);
</span><span class="lines">@@ -1157,7 +1207,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ DeleteResolveNode -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> Variable var = generator.variable(m_ident);
</span><span class="cx"> if (var.local())
</span><span class="lines">@@ -1170,7 +1220,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ DeleteBracketNode -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> r0 = generator.emitNode(m_base);
</span><span class="cx"> RefPtr<RegisterID> r1 = generator.emitNode(m_subscript);
</span><span class="lines">@@ -1183,7 +1233,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ DeleteDotNode -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> r0 = generator.emitNode(m_base);
</span><span class="cx">
</span><span class="lines">@@ -1195,7 +1245,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ DeleteValueNode -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> generator.emitNode(generator.ignoredResult(), m_expr);
</span><span class="cx">
</span><span class="lines">@@ -1205,7 +1255,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ VoidNode -------------------------------------
</span><span class="cx">
</span><del>-RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (dst == generator.ignoredResult()) {
</span><span class="cx"> generator.emitNode(generator.ignoredResult(), m_expr);
</span><span class="lines">@@ -1217,7 +1267,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ TypeOfResolveNode -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> Variable var = generator.variable(m_ident);
</span><span class="cx"> if (RegisterID* local = var.local()) {
</span><span class="lines">@@ -1235,7 +1285,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ TypeOfValueNode -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (dst == generator.ignoredResult()) {
</span><span class="cx"> generator.emitNode(generator.ignoredResult(), m_expr);
</span><span class="lines">@@ -1329,7 +1379,7 @@
</span><span class="cx"> return generator.moveToDestinationIfNeeded(dst, propDst.get());
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (m_expr->isResolveNode())
</span><span class="cx"> return emitResolve(generator, dst);
</span><span class="lines">@@ -1347,7 +1397,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ Unary Operation Nodes -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> src = generator.emitNode(m_expr);
</span><span class="cx"> generator.emitExpressionInfo(position(), position(), position());
</span><span class="lines">@@ -1356,7 +1406,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ BitwiseNotNode -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> src2 = generator.emitLoad(generator.newTemporary(), jsNumber(-1));
</span><span class="cx"> RefPtr<RegisterID> src1 = generator.emitNode(m_expr);
</span><span class="lines">@@ -1549,7 +1599,7 @@
</span><span class="cx"> branchCondition = triState(!value.pureToBoolean());
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> OpcodeID opcodeID = this->opcodeID();
</span><span class="cx">
</span><span class="lines">@@ -1593,7 +1643,7 @@
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (m_expr1->isNull() || m_expr2->isNull()) {
</span><span class="cx"> RefPtr<RegisterID> src = generator.tempDestination(dst);
</span><span class="lines">@@ -1611,7 +1661,7 @@
</span><span class="cx"> return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> ExpressionNode* left = m_expr1;
</span><span class="cx"> ExpressionNode* right = m_expr2;
</span><span class="lines">@@ -1623,7 +1673,7 @@
</span><span class="cx"> return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
</span><span class="cx"> RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
</span><span class="lines">@@ -1631,7 +1681,7 @@
</span><span class="cx"> return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
</span><span class="cx"> RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
</span><span class="lines">@@ -1653,7 +1703,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ LogicalOpNode ----------------------------
</span><span class="cx">
</span><del>-RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> temp = generator.tempDestination(dst);
</span><span class="cx"> RefPtr<Label> target = generator.newLabel();
</span><span class="lines">@@ -1663,7 +1713,7 @@
</span><span class="cx"> generator.emitJumpIfFalse(temp.get(), target.get());
</span><span class="cx"> else
</span><span class="cx"> generator.emitJumpIfTrue(temp.get(), target.get());
</span><del>- generator.emitNode(temp.get(), m_expr2);
</del><ins>+ generator.emitNode(temp.get(), m_expr2, tailCallMode);
</ins><span class="cx"> generator.emitLabel(target.get());
</span><span class="cx">
</span><span class="cx"> return generator.moveToDestinationIfNeeded(dst, temp.get());
</span><span class="lines">@@ -1683,7 +1733,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ ConditionalNode ------------------------------
</span><span class="cx">
</span><del>-RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> newDst = generator.finalDestination(dst);
</span><span class="cx"> RefPtr<Label> beforeElse = generator.newLabel();
</span><span class="lines">@@ -1694,12 +1744,12 @@
</span><span class="cx"> generator.emitLabel(beforeThen.get());
</span><span class="cx">
</span><span class="cx"> generator.emitProfileControlFlow(m_expr1->startOffset());
</span><del>- generator.emitNode(newDst.get(), m_expr1);
</del><ins>+ generator.emitNode(newDst.get(), m_expr1, tailCallMode);
</ins><span class="cx"> generator.emitJump(afterElse.get());
</span><span class="cx">
</span><span class="cx"> generator.emitLabel(beforeElse.get());
</span><span class="cx"> generator.emitProfileControlFlow(m_expr1->endOffset() + 1);
</span><del>- generator.emitNode(newDst.get(), m_expr2);
</del><ins>+ generator.emitNode(newDst.get(), m_expr2, tailCallMode);
</ins><span class="cx">
</span><span class="cx"> generator.emitLabel(afterElse.get());
</span><span class="cx">
</span><span class="lines">@@ -1767,7 +1817,7 @@
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> JSTextPosition newDivot = divotStart() + m_ident.length();
</span><span class="cx"> Variable var = generator.variable(m_ident);
</span><span class="lines">@@ -1808,7 +1858,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ AssignResolveNode -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> Variable var = generator.variable(m_ident);
</span><span class="cx"> if (RegisterID* local = var.local()) {
</span><span class="lines">@@ -1847,7 +1897,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ AssignDotNode -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
</span><span class="cx"> RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
</span><span class="lines">@@ -1864,7 +1914,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ ReadModifyDotNode -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
</span><span class="cx">
</span><span class="lines">@@ -1883,14 +1933,14 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ AssignErrorNode -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
</del><ins>+RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> return emitThrowReferenceError(generator, ASCIILiteral("Left side of assignment is not a reference."));
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // ------------------------------ AssignBracketNode -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
</span><span class="cx"> RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
</span><span class="lines">@@ -1914,7 +1964,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ ReadModifyBracketNode -----------------------------------
</span><span class="cx">
</span><del>-RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
</span><span class="cx"> RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
</span><span class="lines">@@ -1935,12 +1985,12 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ CommaNode ------------------------------------
</span><span class="cx">
</span><del>-RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> CommaNode* node = this;
</span><span class="cx"> for (; node && node->next(); node = node->next())
</span><span class="cx"> generator.emitNode(generator.ignoredResult(), node->m_expr);
</span><del>- return generator.emitNode(dst, node->m_expr);
</del><ins>+ return generator.emitNode(dst, node->m_expr, tailCallMode);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // ------------------------------ ConstDeclNode ------------------------------------
</span><span class="lines">@@ -1988,7 +2038,7 @@
</span><span class="cx"> return generator.emitPutToScope(scope.get(), var, value.get(), DoNotThrowIfNotFound);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
</del><ins>+RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RegisterID* result = 0;
</span><span class="cx"> for (ConstDeclNode* n = this; n; n = n->m_next)
</span><span class="lines">@@ -1999,7 +2049,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ ConstStatementNode -----------------------------
</span><span class="cx">
</span><del>-void ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
</del><ins>+void ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><span class="cx"> generator.emitNode(m_next);
</span><span class="lines">@@ -2013,10 +2063,10 @@
</span><span class="cx"> return m_tail;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> for (StatementNode* statement = m_head; statement; statement = statement->next())
</span><del>- generator.emitNode(dst, statement);
</del><ins>+ generator.emitNode(dst, statement, tailCallMode);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // ------------------------------ BlockNode ------------------------------------
</span><span class="lines">@@ -2031,30 +2081,30 @@
</span><span class="cx"> return m_statements ? m_statements->singleStatement() : 0;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (!m_statements)
</span><span class="cx"> return;
</span><del>- m_statements->emitBytecode(generator, dst);
</del><ins>+ m_statements->emitBytecode(generator, dst, tailCallMode);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // ------------------------------ EmptyStatementNode ---------------------------
</span><span class="cx">
</span><del>-void EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
</del><ins>+void EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // ------------------------------ DebuggerStatementNode ---------------------------
</span><span class="cx">
</span><del>-void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
</del><ins>+void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> generator.emitDebugHook(DidReachBreakpoint, lastLine(), startOffset(), lineStartOffset());
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // ------------------------------ ExprStatementNode ----------------------------
</span><span class="cx">
</span><del>-void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(m_expr);
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><span class="lines">@@ -2063,7 +2113,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ VarStatementNode ----------------------------
</span><span class="cx">
</span><del>-void VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
</del><ins>+void VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(m_expr);
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><span class="lines">@@ -2072,7 +2122,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ EmptyVarExpression ----------------------------
</span><span class="cx">
</span><del>-RegisterID* EmptyVarExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
</del><ins>+RegisterID* EmptyVarExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (!generator.vm()->typeProfiler())
</span><span class="cx"> return nullptr;
</span><span class="lines">@@ -2131,7 +2181,7 @@
</span><span class="cx"> return false;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><span class="cx">
</span><span class="lines">@@ -2149,7 +2199,7 @@
</span><span class="cx"> generator.emitProfileControlFlow(m_ifBlock->startOffset());
</span><span class="cx">
</span><span class="cx"> if (!didFoldIfBlock) {
</span><del>- generator.emitNode(dst, m_ifBlock);
</del><ins>+ generator.emitNode(dst, m_ifBlock, tailCallMode);
</ins><span class="cx"> if (m_elseBlock)
</span><span class="cx"> generator.emitJump(afterElse.get());
</span><span class="cx"> }
</span><span class="lines">@@ -2158,7 +2208,7 @@
</span><span class="cx">
</span><span class="cx"> if (m_elseBlock) {
</span><span class="cx"> generator.emitProfileControlFlow(m_ifBlock->endOffset() + (m_ifBlock->isBlock() ? 1 : 0));
</span><del>- generator.emitNode(dst, m_elseBlock);
</del><ins>+ generator.emitNode(dst, m_elseBlock, tailCallMode);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> generator.emitLabel(afterElse.get());
</span><span class="lines">@@ -2168,7 +2218,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ DoWhileNode ----------------------------------
</span><span class="cx">
</span><del>-void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
</span><span class="cx">
</span><span class="lines">@@ -2177,7 +2227,7 @@
</span><span class="cx"> generator.emitLoopHint();
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
</span><span class="cx">
</span><del>- generator.emitNode(dst, m_statement);
</del><ins>+ generator.emitNode(dst, m_statement, tailCallMode);
</ins><span class="cx">
</span><span class="cx"> generator.emitLabel(scope->continueTarget());
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
</span><span class="lines">@@ -2188,7 +2238,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ WhileNode ------------------------------------
</span><span class="cx">
</span><del>-void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
</span><span class="cx"> RefPtr<Label> topOfLoop = generator.newLabel();
</span><span class="lines">@@ -2200,7 +2250,7 @@
</span><span class="cx"> generator.emitLoopHint();
</span><span class="cx">
</span><span class="cx"> generator.emitProfileControlFlow(m_statement->startOffset());
</span><del>- generator.emitNode(dst, m_statement);
</del><ins>+ generator.emitNode(dst, m_statement, tailCallMode);
</ins><span class="cx">
</span><span class="cx"> generator.emitLabel(scope->continueTarget());
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><span class="lines">@@ -2214,7 +2264,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ ForNode --------------------------------------
</span><span class="cx">
</span><del>-void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
</span><span class="cx">
</span><span class="lines">@@ -2231,7 +2281,7 @@
</span><span class="cx"> generator.emitLoopHint();
</span><span class="cx"> generator.emitProfileControlFlow(m_statement->startOffset());
</span><span class="cx">
</span><del>- generator.emitNode(dst, m_statement);
</del><ins>+ generator.emitNode(dst, m_statement, tailCallMode);
</ins><span class="cx">
</span><span class="cx"> generator.emitLabel(scope->continueTarget());
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><span class="lines">@@ -2481,13 +2531,13 @@
</span><span class="cx"> generator.emitProfileControlFlow(profilerEndOffset);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> this->emitMultiLoopBytecode(generator, dst);
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // ------------------------------ ForOfNode ------------------------------------
</span><del>-void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (!m_lexpr->isAssignmentLocation()) {
</span><span class="cx"> emitThrowReferenceError(generator, ASCIILiteral("Left side of for-of statement is not a reference."));
</span><span class="lines">@@ -2563,7 +2613,7 @@
</span><span class="cx"> return scope->continueTarget();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
</del><ins>+void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><span class="cx">
</span><span class="lines">@@ -2592,7 +2642,7 @@
</span><span class="cx"> return scope->breakTarget();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
</del><ins>+void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><span class="cx">
</span><span class="lines">@@ -2607,7 +2657,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ ReturnNode -----------------------------------
</span><span class="cx">
</span><del>-void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><span class="cx"> ASSERT(generator.codeType() == FunctionCode);
</span><span class="lines">@@ -2615,7 +2665,7 @@
</span><span class="cx"> if (dst == generator.ignoredResult())
</span><span class="cx"> dst = 0;
</span><span class="cx">
</span><del>- RefPtr<RegisterID> returnRegister = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
</del><ins>+ RefPtr<RegisterID> returnRegister = m_value ? generator.emitNode(dst, m_value, tailCallMode) : generator.emitLoad(dst, jsUndefined());
</ins><span class="cx"> if (generator.vm()->typeProfiler()) {
</span><span class="cx"> generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, nullptr);
</span><span class="cx"> generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
</span><span class="lines">@@ -2636,25 +2686,25 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ WithNode -------------------------------------
</span><span class="cx">
</span><del>-void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><span class="cx">
</span><span class="cx"> RefPtr<RegisterID> scope = generator.emitNode(m_expr);
</span><span class="cx"> generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
</span><span class="cx"> generator.emitPushWithScope(generator.scopeRegister(), scope.get());
</span><del>- generator.emitNode(dst, m_statement);
</del><ins>+ generator.emitNode(dst, m_statement, tailCallMode);
</ins><span class="cx"> generator.emitPopScope(generator.scopeRegister());
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // ------------------------------ CaseClauseNode --------------------------------
</span><span class="cx">
</span><del>-inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> generator.emitProfileControlFlow(m_startOffset);
</span><span class="cx"> if (!m_statements)
</span><span class="cx"> return;
</span><del>- m_statements->emitBytecode(generator, dst);
</del><ins>+ m_statements->emitBytecode(generator, dst, tailCallMode);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // ------------------------------ CaseBlockNode --------------------------------
</span><span class="lines">@@ -2748,7 +2798,7 @@
</span><span class="cx"> return SwitchInfo::SwitchString;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
</del><ins>+void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<Label> defaultLabel;
</span><span class="cx"> Vector<RefPtr<Label>, 8> labelVector;
</span><span class="lines">@@ -2787,17 +2837,17 @@
</span><span class="cx"> size_t i = 0;
</span><span class="cx"> for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
</span><span class="cx"> generator.emitLabel(labelVector[i++].get());
</span><del>- list->getClause()->emitBytecode(generator, dst);
</del><ins>+ list->getClause()->emitBytecode(generator, dst, tailCallMode);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (m_defaultClause) {
</span><span class="cx"> generator.emitLabel(defaultLabel.get());
</span><del>- m_defaultClause->emitBytecode(generator, dst);
</del><ins>+ m_defaultClause->emitBytecode(generator, dst, tailCallMode);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
</span><span class="cx"> generator.emitLabel(labelVector[i++].get());
</span><del>- list->getClause()->emitBytecode(generator, dst);
</del><ins>+ list->getClause()->emitBytecode(generator, dst, tailCallMode);
</ins><span class="cx"> }
</span><span class="cx"> if (!m_defaultClause)
</span><span class="cx"> generator.emitLabel(defaultLabel.get());
</span><span class="lines">@@ -2811,14 +2861,14 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ SwitchNode -----------------------------------
</span><span class="cx">
</span><del>-void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><span class="cx">
</span><span class="cx"> LabelScopePtr scope = generator.newLabelScope(LabelScope::Switch);
</span><span class="cx">
</span><span class="cx"> RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
</span><del>- m_block->emitBytecodeForBlock(generator, r0.get(), dst);
</del><ins>+ m_block->emitBytecodeForBlock(generator, r0.get(), dst, tailCallMode);
</ins><span class="cx">
</span><span class="cx"> generator.emitLabel(scope->breakTarget());
</span><span class="cx"> generator.emitProfileControlFlow(endOffset());
</span><span class="lines">@@ -2826,7 +2876,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ LabelNode ------------------------------------
</span><span class="cx">
</span><del>-void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><span class="cx">
</span><span class="lines">@@ -2840,7 +2890,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ ThrowNode ------------------------------------
</span><span class="cx">
</span><del>-void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><span class="cx">
</span><span class="lines">@@ -2855,7 +2905,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ TryNode --------------------------------------
</span><span class="cx">
</span><del>-void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode tailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> // NOTE: The catch and finally blocks must be labeled explicitly, so the
</span><span class="cx"> // optimizer knows they may be jumped to from anywhere.
</span><span class="lines">@@ -2893,7 +2943,7 @@
</span><span class="cx">
</span><span class="cx"> generator.emitPushCatchScope(generator.scopeRegister(), m_thrownValueIdent, thrownValueRegister.get(), DontDelete);
</span><span class="cx"> generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1);
</span><del>- generator.emitNode(dst, m_catchBlock);
</del><ins>+ generator.emitNode(dst, m_catchBlock, m_finallyBlock ? NoTailCalls : tailCallMode);
</ins><span class="cx"> generator.emitPopScope(generator.scopeRegister());
</span><span class="cx"> generator.emitLabel(catchEndLabel.get());
</span><span class="cx"> }
</span><span class="lines">@@ -2909,7 +2959,7 @@
</span><span class="cx">
</span><span class="cx"> // Normal path: run the finally code, and jump to the end.
</span><span class="cx"> generator.emitProfileControlFlow(finallyStartOffset);
</span><del>- generator.emitNode(dst, m_finallyBlock);
</del><ins>+ generator.emitNode(dst, m_finallyBlock, tailCallMode);
</ins><span class="cx"> generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
</span><span class="cx"> generator.emitJump(finallyEndLabel.get());
</span><span class="cx">
</span><span class="lines">@@ -2918,7 +2968,7 @@
</span><span class="cx"> RefPtr<RegisterID> thrownValueRegister = generator.newTemporary();
</span><span class="cx"> generator.popTryAndEmitCatch(tryData, exceptionRegister.get(), thrownValueRegister.get(), preFinallyLabel.get(), HandlerType::Finally);
</span><span class="cx"> generator.emitProfileControlFlow(finallyStartOffset);
</span><del>- generator.emitNode(dst, m_finallyBlock);
</del><ins>+ generator.emitNode(dst, m_finallyBlock, tailCallMode);
</ins><span class="cx"> generator.emitThrow(exceptionRegister.get());
</span><span class="cx">
</span><span class="cx"> generator.emitLabel(finallyEndLabel.get());
</span><span class="lines">@@ -2934,12 +2984,12 @@
</span><span class="cx"> {
</span><span class="cx"> if (!m_statements)
</span><span class="cx"> return;
</span><del>- m_statements->emitBytecode(generator, dst);
</del><ins>+ m_statements->emitBytecode(generator, dst, isStrictMode() ? CanHaveTailCalls : NoTailCalls);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // ------------------------------ ProgramNode -----------------------------
</span><span class="cx">
</span><del>-void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
</del><ins>+void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
</span><span class="cx">
</span><span class="lines">@@ -2954,7 +3004,7 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ EvalNode -----------------------------
</span><span class="cx">
</span><del>-void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
</del><ins>+void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
</span><span class="cx">
</span><span class="lines">@@ -2968,11 +3018,11 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ FunctionBodyNode -----------------------------
</span><span class="cx">
</span><del>-void FunctionBodyNode::emitBytecode(BytecodeGenerator&, RegisterID*)
</del><ins>+void FunctionBodyNode::emitBytecode(BytecodeGenerator&, RegisterID*, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void FunctionNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
</del><ins>+void FunctionNode::emitBytecode(BytecodeGenerator& generator, RegisterID*, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (generator.vm()->typeProfiler()) {
</span><span class="cx"> for (size_t i = 0; i < m_parameters->size(); i++) {
</span><span class="lines">@@ -3014,13 +3064,13 @@
</span><span class="cx">
</span><span class="cx"> // ------------------------------ FuncDeclNode ---------------------------------
</span><span class="cx">
</span><del>-void FuncDeclNode::emitBytecode(BytecodeGenerator&, RegisterID*)
</del><ins>+void FuncDeclNode::emitBytecode(BytecodeGenerator&, RegisterID*, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // ------------------------------ FuncExprNode ---------------------------------
</span><span class="cx">
</span><del>-RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
</span><span class="cx"> }
</span><span class="lines">@@ -3028,14 +3078,14 @@
</span><span class="cx"> #if ENABLE(ES6_CLASS_SYNTAX)
</span><span class="cx"> // ------------------------------ ClassDeclNode ---------------------------------
</span><span class="cx">
</span><del>-void ClassDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+void ClassDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> generator.emitNode(dst, m_classDeclaration);
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // ------------------------------ ClassExprNode ---------------------------------
</span><span class="cx">
</span><del>-RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<RegisterID> superclass;
</span><span class="cx"> if (m_classHeritage) {
</span><span class="lines">@@ -3106,7 +3156,7 @@
</span><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> // ------------------------------ DestructuringAssignmentNode -----------------
</span><del>-RegisterID* DestructuringAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
</del><ins>+RegisterID* DestructuringAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> if (RegisterID* result = m_bindings->emitDirectBinding(generator, dst, m_initializer))
</span><span class="cx"> return result;
</span><span class="lines">@@ -3351,7 +3401,7 @@
</span><span class="cx"> identifiers.append(m_boundProperty);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
</del><ins>+RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*, TailCallMode)
</ins><span class="cx"> {
</span><span class="cx"> RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> return 0;
</span></span></pre></div>
<a id="branchesjsctailcallSourceJavaScriptCoreparserNodesh"></a>
<div class="modfile"><h4>Modified: branches/jsc-tailcall/Source/JavaScriptCore/parser/Nodes.h (186821 => 186822)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/parser/Nodes.h        2015-07-14 22:24:54 UTC (rev 186821)
+++ branches/jsc-tailcall/Source/JavaScriptCore/parser/Nodes.h        2015-07-14 22:33:32 UTC (rev 186822)
</span><span class="lines">@@ -76,6 +76,11 @@
</span><span class="cx"> };
</span><span class="cx"> inline FallThroughMode invert(FallThroughMode fallThroughMode) { return static_cast<FallThroughMode>(!fallThroughMode); }
</span><span class="cx">
</span><ins>+ enum TailCallMode {
+ CanHaveTailCalls,
+ NoTailCalls,
+ };
+
</ins><span class="cx"> typedef HashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash> IdentifierSet;
</span><span class="cx">
</span><span class="cx"> namespace DeclarationStacks {
</span><span class="lines">@@ -144,7 +149,7 @@
</span><span class="cx"> ExpressionNode(const JSTokenLocation&, ResultType = ResultType::unknownType());
</span><span class="cx">
</span><span class="cx"> public:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* destination = 0, TailCallMode = NoTailCalls) = 0;
</ins><span class="cx">
</span><span class="cx"> virtual bool isNumber() const { return false; }
</span><span class="cx"> virtual bool isString() const { return false; }
</span><span class="lines">@@ -181,7 +186,7 @@
</span><span class="cx"> StatementNode(const JSTokenLocation&);
</span><span class="cx">
</span><span class="cx"> public:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* destination = 0, TailCallMode = NoTailCalls) = 0;
</ins><span class="cx">
</span><span class="cx"> void setLoc(unsigned firstLine, unsigned lastLine, int startOffset, int lineStartOffset);
</span><span class="cx"> unsigned lastLine() const { return m_lastLine; }
</span><span class="lines">@@ -209,7 +214,7 @@
</span><span class="cx"> virtual bool isConstant() const override { return true; }
</span><span class="cx"> virtual JSValue jsValue(BytecodeGenerator&) const = 0;
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode) override;
</span><span class="cx"> };
</span><span class="cx">
</span><span class="lines">@@ -239,7 +244,7 @@
</span><span class="cx"> NumberNode(const JSTokenLocation&, double value);
</span><span class="cx"> double value() const { return m_value; }
</span><span class="cx"> virtual bool isIntegerNode() const = 0;
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override final;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override final;
</ins><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> virtual bool isNumber() const override final { return true; }
</span><span class="lines">@@ -449,7 +454,7 @@
</span><span class="cx"> const Identifier& raw() { return m_raw; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> const Identifier& m_cooked;
</span><span class="cx"> const Identifier& m_raw;
</span><span class="lines">@@ -477,7 +482,7 @@
</span><span class="cx"> TemplateExpressionListNode* templateExpressions() const { return m_templateExpressions; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> TemplateStringListNode* m_templateStrings;
</span><span class="cx"> TemplateExpressionListNode* m_templateExpressions;
</span><span class="lines">@@ -490,7 +495,7 @@
</span><span class="cx"> TemplateLiteralNode* templateLiteral() const { return m_templateLiteral; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_tag;
</span><span class="cx"> TemplateLiteralNode* m_templateLiteral;
</span><span class="lines">@@ -502,7 +507,7 @@
</span><span class="cx"> RegExpNode(const JSTokenLocation&, const Identifier& pattern, const Identifier& flags);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> const Identifier& m_pattern;
</span><span class="cx"> const Identifier& m_flags;
</span><span class="lines">@@ -513,7 +518,7 @@
</span><span class="cx"> ThisNode(const JSTokenLocation&, ThisTDZMode);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> bool m_shouldAlwaysEmitTDZCheck;
</span><span class="cx"> };
</span><span class="lines">@@ -524,7 +529,7 @@
</span><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> virtual bool isSuperNode() const override { return true; }
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> class ResolveNode : public ExpressionNode {
</span><span class="lines">@@ -534,7 +539,7 @@
</span><span class="cx"> const Identifier& identifier() const { return m_ident; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> virtual bool isPure(BytecodeGenerator&) const override;
</span><span class="cx"> virtual bool isLocation() const override { return true; }
</span><span class="lines">@@ -569,7 +574,7 @@
</span><span class="cx">
</span><span class="cx"> ElementNode* elements() const { ASSERT(isSimpleArray()); return m_element; }
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> virtual bool isSimpleArray() const override;
</span><span class="cx">
</span><span class="lines">@@ -609,7 +614,7 @@
</span><span class="cx"> PropertyListNode(const JSTokenLocation&, PropertyNode*, PropertyListNode*);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> void emitPutConstantProperty(BytecodeGenerator&, RegisterID*, PropertyNode&);
</span><span class="cx">
</span><span class="cx"> PropertyNode* m_node;
</span><span class="lines">@@ -622,7 +627,7 @@
</span><span class="cx"> ObjectLiteralNode(const JSTokenLocation&, PropertyListNode*);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> PropertyListNode* m_list;
</span><span class="cx"> };
</span><span class="lines">@@ -637,7 +642,7 @@
</span><span class="cx"> bool subscriptHasAssignments() const { return m_subscriptHasAssignments; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> virtual bool isLocation() const override { return true; }
</span><span class="cx"> virtual bool isBracketAccessorNode() const override { return true; }
</span><span class="lines">@@ -655,7 +660,7 @@
</span><span class="cx"> const Identifier& identifier() const { return m_ident; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> virtual bool isLocation() const override { return true; }
</span><span class="cx"> virtual bool isDotAccessorNode() const override { return true; }
</span><span class="lines">@@ -671,7 +676,7 @@
</span><span class="cx"> ExpressionNode* expression() const { return m_expression; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> virtual bool isSpreadExpression() const override { return true; }
</span><span class="cx"> ExpressionNode* m_expression;
</span><span class="lines">@@ -686,7 +691,7 @@
</span><span class="cx"> ExpressionNode* m_expr;
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> class ArgumentsNode : public ParserArenaFreeable {
</span><span class="lines">@@ -703,7 +708,7 @@
</span><span class="cx"> NewExprNode(const JSTokenLocation&, ExpressionNode*, ArgumentsNode*);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_expr;
</span><span class="cx"> ArgumentsNode* m_args;
</span><span class="lines">@@ -714,7 +719,7 @@
</span><span class="cx"> EvalFunctionCallNode(const JSTokenLocation&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ArgumentsNode* m_args;
</span><span class="cx"> };
</span><span class="lines">@@ -724,7 +729,7 @@
</span><span class="cx"> FunctionCallValueNode(const JSTokenLocation&, ExpressionNode*, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_expr;
</span><span class="cx"> ArgumentsNode* m_args;
</span><span class="lines">@@ -735,7 +740,7 @@
</span><span class="cx"> FunctionCallResolveNode(const JSTokenLocation&, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> const Identifier& m_ident;
</span><span class="cx"> ArgumentsNode* m_args;
</span><span class="lines">@@ -746,7 +751,7 @@
</span><span class="cx"> FunctionCallBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_base;
</span><span class="cx"> ExpressionNode* m_subscript;
</span><span class="lines">@@ -759,7 +764,7 @@
</span><span class="cx"> FunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> protected:
</span><span class="cx"> ExpressionNode* m_base;
</span><span class="lines">@@ -780,7 +785,7 @@
</span><span class="cx"> #undef JSC_DECLARE_BYTECODE_INTRINSIC_FUNCTIONS
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> EmitterType m_emitter;
</span><span class="cx"> const Identifier& m_ident;
</span><span class="lines">@@ -792,7 +797,7 @@
</span><span class="cx"> CallFunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> class ApplyFunctionCallDotNode : public FunctionCallDotNode {
</span><span class="lines">@@ -800,7 +805,7 @@
</span><span class="cx"> ApplyFunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> class DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData {
</span><span class="lines">@@ -808,7 +813,7 @@
</span><span class="cx"> DeleteResolveNode(const JSTokenLocation&, const Identifier&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> const Identifier& m_ident;
</span><span class="cx"> };
</span><span class="lines">@@ -818,7 +823,7 @@
</span><span class="cx"> DeleteBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_base;
</span><span class="cx"> ExpressionNode* m_subscript;
</span><span class="lines">@@ -829,7 +834,7 @@
</span><span class="cx"> DeleteDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_base;
</span><span class="cx"> const Identifier& m_ident;
</span><span class="lines">@@ -840,7 +845,7 @@
</span><span class="cx"> DeleteValueNode(const JSTokenLocation&, ExpressionNode*);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_expr;
</span><span class="cx"> };
</span><span class="lines">@@ -850,7 +855,7 @@
</span><span class="cx"> VoidNode(const JSTokenLocation&, ExpressionNode*);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_expr;
</span><span class="cx"> };
</span><span class="lines">@@ -862,7 +867,7 @@
</span><span class="cx"> const Identifier& identifier() const { return m_ident; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> const Identifier& m_ident;
</span><span class="cx"> };
</span><span class="lines">@@ -872,7 +877,7 @@
</span><span class="cx"> TypeOfValueNode(const JSTokenLocation&, ExpressionNode*);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_expr;
</span><span class="cx"> };
</span><span class="lines">@@ -882,7 +887,7 @@
</span><span class="cx"> PrefixNode(const JSTokenLocation&, ExpressionNode*, Operator, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> protected:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> virtual RegisterID* emitResolve(BytecodeGenerator&, RegisterID* = 0);
</span><span class="cx"> virtual RegisterID* emitBracket(BytecodeGenerator&, RegisterID* = 0);
</span><span class="cx"> virtual RegisterID* emitDot(BytecodeGenerator&, RegisterID* = 0);
</span><span class="lines">@@ -896,7 +901,7 @@
</span><span class="cx"> PostfixNode(const JSTokenLocation&, ExpressionNode*, Operator, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> virtual RegisterID* emitResolve(BytecodeGenerator&, RegisterID* = 0) override;
</span><span class="cx"> virtual RegisterID* emitBracket(BytecodeGenerator&, RegisterID* = 0) override;
</span><span class="cx"> virtual RegisterID* emitDot(BytecodeGenerator&, RegisterID* = 0) override;
</span><span class="lines">@@ -911,7 +916,7 @@
</span><span class="cx"> const ExpressionNode* expr() const { return m_expr; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> OpcodeID opcodeID() const { return m_opcodeID; }
</span><span class="cx">
</span><span class="lines">@@ -941,7 +946,7 @@
</span><span class="cx"> const ExpressionNode* expr() const { return m_expr; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_expr;
</span><span class="cx"> };
</span><span class="lines">@@ -966,7 +971,7 @@
</span><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> void tryFoldToBranch(BytecodeGenerator&, TriState& branchCondition, ExpressionNode*& branchExpression);
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> protected:
</span><span class="cx"> OpcodeID opcodeID() const { return m_opcodeID; }
</span><span class="lines">@@ -1050,7 +1055,7 @@
</span><span class="cx"> ThrowableBinaryOpNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> class InstanceOfNode : public ThrowableBinaryOpNode {
</span><span class="lines">@@ -1058,7 +1063,7 @@
</span><span class="cx"> InstanceOfNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> class InNode : public ThrowableBinaryOpNode {
</span><span class="lines">@@ -1071,7 +1076,7 @@
</span><span class="cx"> EqualNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> class NotEqualNode : public BinaryOpNode {
</span><span class="lines">@@ -1084,7 +1089,7 @@
</span><span class="cx"> StrictEqualNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> class NotStrictEqualNode : public BinaryOpNode {
</span><span class="lines">@@ -1113,7 +1118,7 @@
</span><span class="cx"> LogicalOpNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode) override;
</span><span class="cx">
</span><span class="cx"> ExpressionNode* m_expr1;
</span><span class="lines">@@ -1127,7 +1132,7 @@
</span><span class="cx"> ConditionalNode(const JSTokenLocation&, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_logical;
</span><span class="cx"> ExpressionNode* m_expr1;
</span><span class="lines">@@ -1139,7 +1144,7 @@
</span><span class="cx"> ReadModifyResolveNode(const JSTokenLocation&, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> const Identifier& m_ident;
</span><span class="cx"> ExpressionNode* m_right;
</span><span class="lines">@@ -1152,7 +1157,7 @@
</span><span class="cx"> AssignResolveNode(const JSTokenLocation&, const Identifier&, ExpressionNode* right);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> const Identifier& m_ident;
</span><span class="cx"> ExpressionNode* m_right;
</span><span class="lines">@@ -1163,7 +1168,7 @@
</span><span class="cx"> ReadModifyBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_base;
</span><span class="cx"> ExpressionNode* m_subscript;
</span><span class="lines">@@ -1178,7 +1183,7 @@
</span><span class="cx"> AssignBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_base;
</span><span class="cx"> ExpressionNode* m_subscript;
</span><span class="lines">@@ -1192,7 +1197,7 @@
</span><span class="cx"> AssignDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_base;
</span><span class="cx"> const Identifier& m_ident;
</span><span class="lines">@@ -1205,7 +1210,7 @@
</span><span class="cx"> ReadModifyDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_base;
</span><span class="cx"> const Identifier& m_ident;
</span><span class="lines">@@ -1219,7 +1224,7 @@
</span><span class="cx"> AssignErrorNode(const JSTokenLocation&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> class CommaNode final : public ExpressionNode {
</span><span class="lines">@@ -1231,7 +1236,7 @@
</span><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> virtual bool isCommaNode() const override { return true; }
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_expr;
</span><span class="cx"> CommaNode* m_next;
</span><span class="lines">@@ -1245,7 +1250,7 @@
</span><span class="cx"> const Identifier& ident() { return m_ident; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> virtual RegisterID* emitCodeSingle(BytecodeGenerator&);
</span><span class="cx">
</span><span class="cx"> const Identifier& m_ident;
</span><span class="lines">@@ -1262,7 +1267,7 @@
</span><span class="cx"> ConstStatementNode(const JSTokenLocation&, ConstDeclNode* next);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ConstDeclNode* m_next;
</span><span class="cx"> };
</span><span class="lines">@@ -1276,7 +1281,7 @@
</span><span class="cx"> StatementNode* singleStatement() const;
</span><span class="cx"> StatementNode* lastStatement() const;
</span><span class="cx">
</span><del>- void emitBytecode(BytecodeGenerator&, RegisterID* destination);
</del><ins>+ void emitBytecode(BytecodeGenerator&, RegisterID* destination, TailCallMode);
</ins><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> StatementNode* m_head;
</span><span class="lines">@@ -1291,7 +1296,7 @@
</span><span class="cx"> StatementNode* lastStatement() const;
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> virtual bool isBlock() const override { return true; }
</span><span class="cx">
</span><span class="lines">@@ -1303,7 +1308,7 @@
</span><span class="cx"> EmptyStatementNode(const JSTokenLocation&);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> virtual bool isEmptyStatement() const override { return true; }
</span><span class="cx"> };
</span><span class="lines">@@ -1313,7 +1318,7 @@
</span><span class="cx"> DebuggerStatementNode(const JSTokenLocation&);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> class ExprStatementNode : public StatementNode {
</span><span class="lines">@@ -1325,7 +1330,7 @@
</span><span class="cx"> private:
</span><span class="cx"> virtual bool isExprStatement() const override { return true; }
</span><span class="cx">
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_expr;
</span><span class="cx"> };
</span><span class="lines">@@ -1334,7 +1339,7 @@
</span><span class="cx"> public:
</span><span class="cx"> VarStatementNode(const JSTokenLocation&, ExpressionNode*);
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_expr;
</span><span class="cx"> };
</span><span class="lines">@@ -1344,7 +1349,7 @@
</span><span class="cx"> EmptyVarExpression(const JSTokenLocation&, const Identifier&);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> const Identifier& m_ident;
</span><span class="cx"> };
</span><span class="lines">@@ -1355,7 +1360,7 @@
</span><span class="cx"> IfElseNode(const JSTokenLocation&, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> bool tryFoldBreakAndContinue(BytecodeGenerator&, StatementNode* ifBlock,
</span><span class="cx"> Label*& trueTarget, FallThroughMode&);
</span><span class="cx">
</span><span class="lines">@@ -1369,7 +1374,7 @@
</span><span class="cx"> DoWhileNode(const JSTokenLocation&, StatementNode*, ExpressionNode*);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> StatementNode* m_statement;
</span><span class="cx"> ExpressionNode* m_expr;
</span><span class="lines">@@ -1380,7 +1385,7 @@
</span><span class="cx"> WhileNode(const JSTokenLocation&, ExpressionNode*, StatementNode*);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_expr;
</span><span class="cx"> StatementNode* m_statement;
</span><span class="lines">@@ -1391,7 +1396,7 @@
</span><span class="cx"> ForNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode*);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_expr1;
</span><span class="cx"> ExpressionNode* m_expr2;
</span><span class="lines">@@ -1420,7 +1425,7 @@
</span><span class="cx"> void emitLoopHeader(BytecodeGenerator&, RegisterID* propertyName);
</span><span class="cx"> void emitMultiLoopBytecode(BytecodeGenerator&, RegisterID* dst);
</span><span class="cx">
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> class ForOfNode : public EnumerationNode {
</span><span class="lines">@@ -1428,7 +1433,7 @@
</span><span class="cx"> ForOfNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> class ContinueNode : public StatementNode, public ThrowableExpressionData {
</span><span class="lines">@@ -1438,7 +1443,7 @@
</span><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> virtual bool isContinue() const override { return true; }
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> const Identifier& m_ident;
</span><span class="cx"> };
</span><span class="lines">@@ -1450,7 +1455,7 @@
</span><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> virtual bool isBreak() const override { return true; }
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> const Identifier& m_ident;
</span><span class="cx"> };
</span><span class="lines">@@ -1462,7 +1467,7 @@
</span><span class="cx"> ExpressionNode* value() { return m_value; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> virtual bool isReturnNode() const override { return true; }
</span><span class="cx">
</span><span class="lines">@@ -1474,7 +1479,7 @@
</span><span class="cx"> WithNode(const JSTokenLocation&, ExpressionNode*, StatementNode*, const JSTextPosition& divot, uint32_t expressionLength);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_expr;
</span><span class="cx"> StatementNode* m_statement;
</span><span class="lines">@@ -1487,7 +1492,7 @@
</span><span class="cx"> LabelNode(const JSTokenLocation&, const Identifier& name, StatementNode*);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> const Identifier& m_name;
</span><span class="cx"> StatementNode* m_statement;
</span><span class="lines">@@ -1498,7 +1503,7 @@
</span><span class="cx"> ThrowNode(const JSTokenLocation&, ExpressionNode*);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_expr;
</span><span class="cx"> };
</span><span class="lines">@@ -1508,7 +1513,7 @@
</span><span class="cx"> TryNode(const JSTokenLocation&, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> StatementNode* m_tryBlock;
</span><span class="cx"> const Identifier& m_thrownValueIdent;
</span><span class="lines">@@ -1609,7 +1614,7 @@
</span><span class="cx"> const Vector<RefPtr<UniquedStringImpl>>& closedVariables() const { return m_closedVariables; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx"> Vector<RefPtr<UniquedStringImpl>> m_closedVariables;
</span><span class="cx"> unsigned m_startColumn;
</span><span class="cx"> unsigned m_endColumn;
</span><span class="lines">@@ -1625,7 +1630,7 @@
</span><span class="cx"> static const bool scopeIsFunction = false;
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> unsigned m_endColumn;
</span><span class="cx"> };
</span><span class="lines">@@ -1661,7 +1666,7 @@
</span><span class="cx">
</span><span class="cx"> FunctionParameters* parameters() const { return m_parameters.get(); }
</span><span class="cx">
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> void finishParsing(const SourceCode&, ParameterNode*, const Identifier&, FunctionMode);
</span><span class="cx">
</span><span class="lines">@@ -1708,7 +1713,7 @@
</span><span class="cx">
</span><span class="cx"> FunctionParameters* parameters() const { return m_parameters.get(); }
</span><span class="cx">
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> void finishParsing(PassRefPtr<FunctionParameters>, const Identifier&, FunctionMode);
</span><span class="cx">
</span><span class="lines">@@ -1736,7 +1741,7 @@
</span><span class="cx"> FunctionBodyNode* body() { return m_body; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> virtual bool isFuncExprNode() const override { return true; }
</span><span class="cx">
</span><span class="lines">@@ -1752,7 +1757,7 @@
</span><span class="cx"> const Identifier& name() { return m_name; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> const Identifier& m_name;
</span><span class="cx"> ExpressionNode* m_constructorExpression;
</span><span class="lines">@@ -1863,7 +1868,7 @@
</span><span class="cx"> private:
</span><span class="cx"> virtual bool isAssignmentLocation() const override { return true; }
</span><span class="cx"> virtual bool isDestructuringNode() const override { return true; }
</span><del>- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> RefPtr<DestructuringPatternNode> m_bindings;
</span><span class="cx"> ExpressionNode* m_initializer;
</span><span class="lines">@@ -1877,7 +1882,7 @@
</span><span class="cx"> FunctionBodyNode* body() { return m_body; }
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> FunctionBodyNode* m_body;
</span><span class="cx"> };
</span><span class="lines">@@ -1888,7 +1893,7 @@
</span><span class="cx"> ClassDeclNode(const JSTokenLocation&, ExpressionNode* classExpression);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_classDeclaration;
</span><span class="cx"> };
</span><span class="lines">@@ -1900,7 +1905,7 @@
</span><span class="cx">
</span><span class="cx"> ExpressionNode* expr() const { return m_expr; }
</span><span class="cx">
</span><del>- void emitBytecode(BytecodeGenerator&, RegisterID* destination);
</del><ins>+ void emitBytecode(BytecodeGenerator&, RegisterID* destination, TailCallMode);
</ins><span class="cx"> void setStartOffset(int offset) { m_startOffset = offset; }
</span><span class="cx">
</span><span class="cx"> private:
</span><span class="lines">@@ -1926,7 +1931,7 @@
</span><span class="cx"> public:
</span><span class="cx"> CaseBlockNode(ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2);
</span><span class="cx">
</span><del>- void emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* destination);
</del><ins>+ void emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* destination, TailCallMode);
</ins><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> SwitchInfo::SwitchType tryTableSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num);
</span><span class="lines">@@ -1941,7 +1946,7 @@
</span><span class="cx"> SwitchNode(const JSTokenLocation&, ExpressionNode*, CaseBlockNode*);
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
</del><ins>+ virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0, TailCallMode = NoTailCalls) override;
</ins><span class="cx">
</span><span class="cx"> ExpressionNode* m_expr;
</span><span class="cx"> CaseBlockNode* m_block;
</span></span></pre>
</div>
</div>
</body>
</html>