<!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>[189774] trunk/Source/JavaScriptCore</title>
</head>
<body>

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

<h3>Log Message</h3>
<pre>[ES6] Implement tail calls in the LLInt and Baseline JIT
https://bugs.webkit.org/show_bug.cgi?id=148661

Patch by Basile Clement &lt;basile_clement@apple.com&gt; on 2015-09-14
Reviewed by Filip Pizlo.

This patch introduces two new opcodes, op_tail_call and
op_tail_call_varargs, to perform tail calls, and implements them in the
LLInt and baseline JIT. Their use prevents DFG and FTL compilation for
now. They are currently implemented by sliding the call frame and
masquerading as our own caller right before performing an actual call.

This required to change the operationLink family of operation to return
a SlowPathReturnType instead of a char* in order to distinguish between
exception cases and actual call cases. We introduce a new FrameAction
enum that indicates whether to reuse (non-exceptional tail call) or
keep the current call frame (non-tail call, and exceptional cases).

This is also a semantics change, since the Function.caller property is
now leaking tail calls. Since tail calls are only used in strict mode,
which poisons this property, the only way of seeing this semantics
change is when a sloppy function calls a strict function that then
tail-calls a sloppy function. Previously, the second sloppy function's
caller would have been the strict function (i.e. raises a TypeError
when the .caller attribute is accessed), while it is now the first
sloppy function. Tests have been updated to reflect that.

This also changes the assumptions we make about call frames. In order
to be relatively efficient, we want to be able to compute the frame
size based only on the argument count, which was not possible
previously. To enable this, we now enforce at the bytecode generator,
DFG and FTL level that any space reserved for a call frame is
stack-aligned, which allows to easily compute its size when performing
a tail call. In all the &quot;special call cases&quot; (calls from native code,
inlined cache calls, etc.), we are starting the frame at the current
stack pointer and thus will always have a stack-aligned frame size.

Finally, this patch adds a couple of tests to check that tail calls run
in constant stack space, as well as tests checking that tail calls are
recognized correctly. Those tests use the handy aforementioned leaking
of tail calls through Function.caller to detect tail calls. 

Given that this patch only implements tail calls for the LLInt and
Baseline JIT, tail calls are disabled by default.  Until changes are
landed for all tiers, tail call testing and use requires the
--enableTailCalls=true or equivalent.

* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/AbortReason.h:
* assembler/AbstractMacroAssembler.h:
(JSC::AbstractMacroAssembler::Call::Call):
(JSC::AbstractMacroAssembler::repatchNearCall):
(JSC::AbstractMacroAssembler::repatchCompact):
* assembler/CodeLocation.h:
(JSC::CodeLocationNearCall::CodeLocationNearCall):
(JSC::CodeLocationNearCall::callMode):
(JSC::CodeLocationCommon::callAtOffset):
(JSC::CodeLocationCommon::nearCallAtOffset):
(JSC::CodeLocationCommon::dataLabelPtrAtOffset):
* assembler/LinkBuffer.h:
(JSC::LinkBuffer::locationOfNearCall):
(JSC::LinkBuffer::locationOf):
* assembler/MacroAssemblerARM.h:
(JSC::MacroAssemblerARM::nearCall):
(JSC::MacroAssemblerARM::nearTailCall):
(JSC::MacroAssemblerARM::call):
(JSC::MacroAssemblerARM::linkCall):
* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::nearCall):
(JSC::MacroAssemblerARM64::nearTailCall):
(JSC::MacroAssemblerARM64::ret):
(JSC::MacroAssemblerARM64::linkCall):
* assembler/MacroAssemblerARMv7.h:
(JSC::MacroAssemblerARMv7::nearCall):
(JSC::MacroAssemblerARMv7::nearTailCall):
(JSC::MacroAssemblerARMv7::call):
(JSC::MacroAssemblerARMv7::linkCall):
* assembler/MacroAssemblerMIPS.h:
(JSC::MacroAssemblerMIPS::nearCall):
(JSC::MacroAssemblerMIPS::nearTailCall):
(JSC::MacroAssemblerMIPS::call):
(JSC::MacroAssemblerMIPS::linkCall):
(JSC::MacroAssemblerMIPS::repatchCall):
* assembler/MacroAssemblerSH4.h:
(JSC::MacroAssemblerSH4::call):
(JSC::MacroAssemblerSH4::nearTailCall):
(JSC::MacroAssemblerSH4::nearCall):
(JSC::MacroAssemblerSH4::linkCall):
(JSC::MacroAssemblerSH4::repatchCall):
* assembler/MacroAssemblerX86.h:
(JSC::MacroAssemblerX86::linkCall):
* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::breakpoint):
(JSC::MacroAssemblerX86Common::nearTailCall):
(JSC::MacroAssemblerX86Common::nearCall):
* assembler/MacroAssemblerX86_64.h:
(JSC::MacroAssemblerX86_64::linkCall):
* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CallLinkInfo.h:
(JSC::CallLinkInfo::callTypeFor):
(JSC::CallLinkInfo::isVarargsCallType):
(JSC::CallLinkInfo::CallLinkInfo):
(JSC::CallLinkInfo::specializationKind):
(JSC::CallLinkInfo::callModeFor):
(JSC::CallLinkInfo::callMode):
(JSC::CallLinkInfo::isTailCall):
(JSC::CallLinkInfo::isVarargs):
(JSC::CallLinkInfo::registerPreservationMode):
* bytecode/CallLinkStatus.cpp:
(JSC::CallLinkStatus::computeFromLLInt):
* bytecode/CallMode.cpp: Added.
(WTF::printInternal):
* bytecode/CallMode.h: Added.
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::CodeBlock):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitCallInTailPosition):
(JSC::BytecodeGenerator::emitCallEval):
(JSC::BytecodeGenerator::emitCall):
(JSC::BytecodeGenerator::emitCallVarargsInTailPosition):
(JSC::BytecodeGenerator::emitConstructVarargs):
* bytecompiler/NodesCodegen.cpp:
(JSC::CallArguments::CallArguments):
(JSC::LabelNode::emitBytecode):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::addCallWithoutSettingResult):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::compileCallOrConstruct):
* interpreter/Interpreter.h:
(JSC::Interpreter::isCallBytecode):
* jit/CCallHelpers.h:
(JSC::CCallHelpers::jumpToExceptionHandler):
(JSC::CCallHelpers::prepareForTailCallSlow):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
* jit/JITCall.cpp:
(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):
(JSC::JIT::emit_op_call):
(JSC::JIT::emit_op_tail_call):
(JSC::JIT::emit_op_call_eval):
(JSC::JIT::emit_op_call_varargs):
(JSC::JIT::emit_op_tail_call_varargs):
(JSC::JIT::emit_op_construct_varargs):
(JSC::JIT::emitSlow_op_call):
(JSC::JIT::emitSlow_op_tail_call):
(JSC::JIT::emitSlow_op_call_eval):
(JSC::JIT::emitSlow_op_call_varargs):
(JSC::JIT::emitSlow_op_tail_call_varargs):
(JSC::JIT::emitSlow_op_construct_varargs):
* jit/JITCall32_64.cpp:
(JSC::JIT::emitSlow_op_call):
(JSC::JIT::emitSlow_op_tail_call):
(JSC::JIT::emitSlow_op_call_eval):
(JSC::JIT::emitSlow_op_call_varargs):
(JSC::JIT::emitSlow_op_tail_call_varargs):
(JSC::JIT::emitSlow_op_construct_varargs):
(JSC::JIT::emit_op_call):
(JSC::JIT::emit_op_tail_call):
(JSC::JIT::emit_op_call_eval):
(JSC::JIT::emit_op_call_varargs):
(JSC::JIT::emit_op_tail_call_varargs):
(JSC::JIT::emit_op_construct_varargs):
(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):
* jit/JITInlines.h:
(JSC::JIT::emitNakedCall):
(JSC::JIT::emitNakedTailCall):
(JSC::JIT::updateTopCallFrame):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* jit/Repatch.cpp:
(JSC::linkVirtualFor):
(JSC::linkPolymorphicCall):
* jit/ThunkGenerators.cpp:
(JSC::throwExceptionFromCallSlowPathGenerator):
(JSC::slowPathFor):
(JSC::linkCallThunkGenerator):
(JSC::virtualThunkFor):
(JSC::arityFixupGenerator):
(JSC::unreachableGenerator):
(JSC::baselineGetterReturnThunkGenerator):
* jit/ThunkGenerators.h:
* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/CommonSlowPaths.h:
(JSC::CommonSlowPaths::arityCheckFor):
(JSC::CommonSlowPaths::opIn):
* runtime/Options.h:
* tests/stress/mutual-tail-call-no-stack-overflow.js: Added.
(shouldThrow):
(sloppyCountdown.even):
(sloppyCountdown.odd):
(strictCountdown.even):
(strictCountdown.odd):
(strictCountdown):
(odd):
(even):
* tests/stress/tail-call-no-stack-overflow.js: Added.
(shouldThrow):
(strictLoop):
(strictLoopArityFixup1):
(strictLoopArityFixup2):
* tests/stress/tail-call-recognize.js: Added.
(callerMustBeRun):
(callerMustBeStrict):
(runTests):
* tests/stress/tail-call-varargs-no-stack-overflow.js: Added.
(shouldThrow):
(strictLoop):
* tests/stress/tail-calls-dont-overwrite-live-stack.js: Added.
(tail):
(obj.method):
(obj.get fromNative):
(getThis):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerAbortReasonh">trunk/Source/JavaScriptCore/assembler/AbortReason.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerAbstractMacroAssemblerh">trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerCodeLocationh">trunk/Source/JavaScriptCore/assembler/CodeLocation.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerLinkBufferh">trunk/Source/JavaScriptCore/assembler/LinkBuffer.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerARMh">trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerARM64h">trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerARMv7h">trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerMIPSh">trunk/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerSH4h">trunk/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerX86h">trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerX86Commonh">trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerX86_64h">trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeListjson">trunk/Source/JavaScriptCore/bytecode/BytecodeList.json</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeUseDefh">trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallLinkInfoh">trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallLinkStatuscpp">trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerNodesCodegencpp">trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpreterh">trunk/Source/JavaScriptCore/interpreter/Interpreter.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitCCallHelpersh">trunk/Source/JavaScriptCore/jit/CCallHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITcpp">trunk/Source/JavaScriptCore/jit/JIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCallcpp">trunk/Source/JavaScriptCore/jit/JITCall.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCall32_64cpp">trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITInlinesh">trunk/Source/JavaScriptCore/jit/JITInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationsh">trunk/Source/JavaScriptCore/jit/JITOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRepatchcpp">trunk/Source/JavaScriptCore/jit/Repatch.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitThunkGeneratorscpp">trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitThunkGeneratorsh">trunk/Source/JavaScriptCore/jit/ThunkGenerators.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreterasm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathsh">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallModecpp">trunk/Source/JavaScriptCore/bytecode/CallMode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallModeh">trunk/Source/JavaScriptCore/bytecode/CallMode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressmutualtailcallnostackoverflowjs">trunk/Source/JavaScriptCore/tests/stress/mutual-tail-call-no-stack-overflow.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresstailcallnostackoverflowjs">trunk/Source/JavaScriptCore/tests/stress/tail-call-no-stack-overflow.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresstailcallrecognizejs">trunk/Source/JavaScriptCore/tests/stress/tail-call-recognize.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresstailcallvarargsnostackoverflowjs">trunk/Source/JavaScriptCore/tests/stress/tail-call-varargs-no-stack-overflow.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresstailcallsdontoverwritelivestackjs">trunk/Source/JavaScriptCore/tests/stress/tail-calls-dont-overwrite-live-stack.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -80,6 +80,7 @@
</span><span class="cx">     bytecode/CallEdge.cpp
</span><span class="cx">     bytecode/CallLinkInfo.cpp
</span><span class="cx">     bytecode/CallLinkStatus.cpp
</span><ins>+    bytecode/CallMode.cpp
</ins><span class="cx">     bytecode/CallVariant.cpp
</span><span class="cx">     bytecode/CodeBlock.cpp
</span><span class="cx">     bytecode/CodeBlockHash.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -1,3 +1,231 @@
</span><ins>+2015-09-14  Basile Clement  &lt;basile_clement@apple.com&gt;
+
+        [ES6] Implement tail calls in the LLInt and Baseline JIT
+        https://bugs.webkit.org/show_bug.cgi?id=148661
+
+        Reviewed by Filip Pizlo.
+
+        This patch introduces two new opcodes, op_tail_call and
+        op_tail_call_varargs, to perform tail calls, and implements them in the
+        LLInt and baseline JIT. Their use prevents DFG and FTL compilation for
+        now. They are currently implemented by sliding the call frame and
+        masquerading as our own caller right before performing an actual call.
+
+        This required to change the operationLink family of operation to return
+        a SlowPathReturnType instead of a char* in order to distinguish between
+        exception cases and actual call cases. We introduce a new FrameAction
+        enum that indicates whether to reuse (non-exceptional tail call) or
+        keep the current call frame (non-tail call, and exceptional cases).
+
+        This is also a semantics change, since the Function.caller property is
+        now leaking tail calls. Since tail calls are only used in strict mode,
+        which poisons this property, the only way of seeing this semantics
+        change is when a sloppy function calls a strict function that then
+        tail-calls a sloppy function. Previously, the second sloppy function's
+        caller would have been the strict function (i.e. raises a TypeError
+        when the .caller attribute is accessed), while it is now the first
+        sloppy function. Tests have been updated to reflect that.
+
+        This also changes the assumptions we make about call frames. In order
+        to be relatively efficient, we want to be able to compute the frame
+        size based only on the argument count, which was not possible
+        previously. To enable this, we now enforce at the bytecode generator,
+        DFG and FTL level that any space reserved for a call frame is
+        stack-aligned, which allows to easily compute its size when performing
+        a tail call. In all the &quot;special call cases&quot; (calls from native code,
+        inlined cache calls, etc.), we are starting the frame at the current
+        stack pointer and thus will always have a stack-aligned frame size.
+
+        Finally, this patch adds a couple of tests to check that tail calls run
+        in constant stack space, as well as tests checking that tail calls are
+        recognized correctly. Those tests use the handy aforementioned leaking
+        of tail calls through Function.caller to detect tail calls. 
+
+        Given that this patch only implements tail calls for the LLInt and
+        Baseline JIT, tail calls are disabled by default.  Until changes are
+        landed for all tiers, tail call testing and use requires the
+        --enableTailCalls=true or equivalent.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * assembler/AbortReason.h:
+        * assembler/AbstractMacroAssembler.h:
+        (JSC::AbstractMacroAssembler::Call::Call):
+        (JSC::AbstractMacroAssembler::repatchNearCall):
+        (JSC::AbstractMacroAssembler::repatchCompact):
+        * assembler/CodeLocation.h:
+        (JSC::CodeLocationNearCall::CodeLocationNearCall):
+        (JSC::CodeLocationNearCall::callMode):
+        (JSC::CodeLocationCommon::callAtOffset):
+        (JSC::CodeLocationCommon::nearCallAtOffset):
+        (JSC::CodeLocationCommon::dataLabelPtrAtOffset):
+        * assembler/LinkBuffer.h:
+        (JSC::LinkBuffer::locationOfNearCall):
+        (JSC::LinkBuffer::locationOf):
+        * assembler/MacroAssemblerARM.h:
+        (JSC::MacroAssemblerARM::nearCall):
+        (JSC::MacroAssemblerARM::nearTailCall):
+        (JSC::MacroAssemblerARM::call):
+        (JSC::MacroAssemblerARM::linkCall):
+        * assembler/MacroAssemblerARM64.h:
+        (JSC::MacroAssemblerARM64::nearCall):
+        (JSC::MacroAssemblerARM64::nearTailCall):
+        (JSC::MacroAssemblerARM64::ret):
+        (JSC::MacroAssemblerARM64::linkCall):
+        * assembler/MacroAssemblerARMv7.h:
+        (JSC::MacroAssemblerARMv7::nearCall):
+        (JSC::MacroAssemblerARMv7::nearTailCall):
+        (JSC::MacroAssemblerARMv7::call):
+        (JSC::MacroAssemblerARMv7::linkCall):
+        * assembler/MacroAssemblerMIPS.h:
+        (JSC::MacroAssemblerMIPS::nearCall):
+        (JSC::MacroAssemblerMIPS::nearTailCall):
+        (JSC::MacroAssemblerMIPS::call):
+        (JSC::MacroAssemblerMIPS::linkCall):
+        (JSC::MacroAssemblerMIPS::repatchCall):
+        * assembler/MacroAssemblerSH4.h:
+        (JSC::MacroAssemblerSH4::call):
+        (JSC::MacroAssemblerSH4::nearTailCall):
+        (JSC::MacroAssemblerSH4::nearCall):
+        (JSC::MacroAssemblerSH4::linkCall):
+        (JSC::MacroAssemblerSH4::repatchCall):
+        * assembler/MacroAssemblerX86.h:
+        (JSC::MacroAssemblerX86::linkCall):
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::breakpoint):
+        (JSC::MacroAssemblerX86Common::nearTailCall):
+        (JSC::MacroAssemblerX86Common::nearCall):
+        * assembler/MacroAssemblerX86_64.h:
+        (JSC::MacroAssemblerX86_64::linkCall):
+        * bytecode/BytecodeList.json:
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CallLinkInfo.h:
+        (JSC::CallLinkInfo::callTypeFor):
+        (JSC::CallLinkInfo::isVarargsCallType):
+        (JSC::CallLinkInfo::CallLinkInfo):
+        (JSC::CallLinkInfo::specializationKind):
+        (JSC::CallLinkInfo::callModeFor):
+        (JSC::CallLinkInfo::callMode):
+        (JSC::CallLinkInfo::isTailCall):
+        (JSC::CallLinkInfo::isVarargs):
+        (JSC::CallLinkInfo::registerPreservationMode):
+        * bytecode/CallLinkStatus.cpp:
+        (JSC::CallLinkStatus::computeFromLLInt):
+        * bytecode/CallMode.cpp: Added.
+        (WTF::printInternal):
+        * bytecode/CallMode.h: Added.
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpBytecode):
+        (JSC::CodeBlock::CodeBlock):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::emitCallInTailPosition):
+        (JSC::BytecodeGenerator::emitCallEval):
+        (JSC::BytecodeGenerator::emitCall):
+        (JSC::BytecodeGenerator::emitCallVarargsInTailPosition):
+        (JSC::BytecodeGenerator::emitConstructVarargs):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::CallArguments::CallArguments):
+        (JSC::LabelNode::emitBytecode):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::addCallWithoutSettingResult):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileCallOrConstruct):
+        * interpreter/Interpreter.h:
+        (JSC::Interpreter::isCallBytecode):
+        * jit/CCallHelpers.h:
+        (JSC::CCallHelpers::jumpToExceptionHandler):
+        (JSC::CCallHelpers::prepareForTailCallSlow):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::privateCompileSlowCases):
+        * jit/JIT.h:
+        * jit/JITCall.cpp:
+        (JSC::JIT::compileOpCall):
+        (JSC::JIT::compileOpCallSlowCase):
+        (JSC::JIT::emit_op_call):
+        (JSC::JIT::emit_op_tail_call):
+        (JSC::JIT::emit_op_call_eval):
+        (JSC::JIT::emit_op_call_varargs):
+        (JSC::JIT::emit_op_tail_call_varargs):
+        (JSC::JIT::emit_op_construct_varargs):
+        (JSC::JIT::emitSlow_op_call):
+        (JSC::JIT::emitSlow_op_tail_call):
+        (JSC::JIT::emitSlow_op_call_eval):
+        (JSC::JIT::emitSlow_op_call_varargs):
+        (JSC::JIT::emitSlow_op_tail_call_varargs):
+        (JSC::JIT::emitSlow_op_construct_varargs):
+        * jit/JITCall32_64.cpp:
+        (JSC::JIT::emitSlow_op_call):
+        (JSC::JIT::emitSlow_op_tail_call):
+        (JSC::JIT::emitSlow_op_call_eval):
+        (JSC::JIT::emitSlow_op_call_varargs):
+        (JSC::JIT::emitSlow_op_tail_call_varargs):
+        (JSC::JIT::emitSlow_op_construct_varargs):
+        (JSC::JIT::emit_op_call):
+        (JSC::JIT::emit_op_tail_call):
+        (JSC::JIT::emit_op_call_eval):
+        (JSC::JIT::emit_op_call_varargs):
+        (JSC::JIT::emit_op_tail_call_varargs):
+        (JSC::JIT::emit_op_construct_varargs):
+        (JSC::JIT::compileOpCall):
+        (JSC::JIT::compileOpCallSlowCase):
+        * jit/JITInlines.h:
+        (JSC::JIT::emitNakedCall):
+        (JSC::JIT::emitNakedTailCall):
+        (JSC::JIT::updateTopCallFrame):
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+        * jit/Repatch.cpp:
+        (JSC::linkVirtualFor):
+        (JSC::linkPolymorphicCall):
+        * jit/ThunkGenerators.cpp:
+        (JSC::throwExceptionFromCallSlowPathGenerator):
+        (JSC::slowPathFor):
+        (JSC::linkCallThunkGenerator):
+        (JSC::virtualThunkFor):
+        (JSC::arityFixupGenerator):
+        (JSC::unreachableGenerator):
+        (JSC::baselineGetterReturnThunkGenerator):
+        * jit/ThunkGenerators.h:
+        * llint/LowLevelInterpreter.asm:
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * runtime/CommonSlowPaths.h:
+        (JSC::CommonSlowPaths::arityCheckFor):
+        (JSC::CommonSlowPaths::opIn):
+        * runtime/Options.h:
+        * tests/stress/mutual-tail-call-no-stack-overflow.js: Added.
+        (shouldThrow):
+        (sloppyCountdown.even):
+        (sloppyCountdown.odd):
+        (strictCountdown.even):
+        (strictCountdown.odd):
+        (strictCountdown):
+        (odd):
+        (even):
+        * tests/stress/tail-call-no-stack-overflow.js: Added.
+        (shouldThrow):
+        (strictLoop):
+        (strictLoopArityFixup1):
+        (strictLoopArityFixup2):
+        * tests/stress/tail-call-recognize.js: Added.
+        (callerMustBeRun):
+        (callerMustBeStrict):
+        (runTests):
+        * tests/stress/tail-call-varargs-no-stack-overflow.js: Added.
+        (shouldThrow):
+        (strictLoop):
+        * tests/stress/tail-calls-dont-overwrite-live-stack.js: Added.
+        (tail):
+        (obj.method):
+        (obj.get fromNative):
+        (getThis):
+
</ins><span class="cx"> 2015-09-14  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         LLInt get/put inline caches shouldn't use tons of opcodes
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -319,6 +319,7 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\CallEdge.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\CallLinkInfo.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\CallLinkStatus.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\bytecode\CallMode.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\CallVariant.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\CodeBlock.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\CodeBlockHash.cpp&quot; /&gt;
</span><span class="lines">@@ -1012,6 +1013,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\CallEdge.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\CallLinkInfo.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\CallLinkStatus.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\bytecode\CallMode.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\CallReturnOffsetToBytecodeOffset.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\CallVariant.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\CodeBlock.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -162,6 +162,9 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\CallLinkStatus.cpp&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;bytecode&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClCompile&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\bytecode\CallMode.cpp&quot;&gt;
+      &lt;Filter&gt;bytecode&lt;/Filter&gt;
+    &lt;/ClCompile&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\CodeBlock.cpp&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;bytecode&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClCompile&gt;
</span><span class="lines">@@ -2034,6 +2037,9 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\CallLinkStatus.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;bytecode&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\bytecode\CallMode.h&quot;&gt;
+      &lt;Filter&gt;bytecode&lt;/Filter&gt;
+    &lt;/ClInclude&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\CallReturnOffsetToBytecodeOffset.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;bytecode&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -969,6 +969,8 @@
</span><span class="cx">                 5DBB1525131D0BD70056AD36 /* minidom.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 1412110D0A48788700480255 /* minidom.js */; };
</span><span class="cx">                 5DE6E5B30E1728EC00180407 /* create_hash_table in Headers */ = {isa = PBXBuildFile; fileRef = F692A8540255597D01FF60F7 /* create_hash_table */; settings = {ATTRIBUTES = (); }; };
</span><span class="cx">                 623A37EC1B87A7C000754209 /* RegisterMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 623A37EB1B87A7BD00754209 /* RegisterMap.h */; };
</span><ins>+                627673231B680C1E00FD9F2E /* CallMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 627673211B680C1E00FD9F2E /* CallMode.cpp */; };
+                627673241B680C1E00FD9F2E /* CallMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 627673221B680C1E00FD9F2E /* CallMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 62D2D38F1ADF103F000206C1 /* FunctionRareData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 62D2D38D1ADF103F000206C1 /* FunctionRareData.cpp */; };
</span><span class="cx">                 62D2D3901ADF103F000206C1 /* FunctionRareData.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D2D38E1ADF103F000206C1 /* FunctionRareData.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 62E3D5F01B8D0B7300B868BB /* DataFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 62E3D5EF1B8D0B7300B868BB /* DataFormat.cpp */; };
</span><span class="lines">@@ -2772,6 +2774,8 @@
</span><span class="cx">                 5DDDF44614FEE72200B4FB4D /* LLIntDesiredOffsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntDesiredOffsets.h; path = LLIntOffsets/LLIntDesiredOffsets.h; sourceTree = BUILT_PRODUCTS_DIR; };
</span><span class="cx">                 5DE3D0F40DD8DDFB00468714 /* WebKitAvailability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitAvailability.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 623A37EB1B87A7BD00754209 /* RegisterMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterMap.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                627673211B680C1E00FD9F2E /* CallMode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallMode.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                627673221B680C1E00FD9F2E /* CallMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallMode.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 62A9A29E1B0BED4800BD54CA /* DFGLazyNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGLazyNode.cpp; path = dfg/DFGLazyNode.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 62A9A29F1B0BED4800BD54CA /* DFGLazyNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGLazyNode.h; path = dfg/DFGLazyNode.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 62D2D38D1ADF103F000206C1 /* FunctionRareData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FunctionRareData.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5538,6 +5542,8 @@
</span><span class="cx">                                 0F0B83AF14BCF71400885B4F /* CallLinkInfo.h */,
</span><span class="cx">                                 0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */,
</span><span class="cx">                                 0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */,
</span><ins>+                                627673211B680C1E00FD9F2E /* CallMode.cpp */,
+                                627673221B680C1E00FD9F2E /* CallMode.h */,
</ins><span class="cx">                                 0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */,
</span><span class="cx">                                 0F3B7E2419A11B8000D9BC56 /* CallVariant.cpp */,
</span><span class="cx">                                 0F3B7E2519A11B8000D9BC56 /* CallVariant.h */,
</span><span class="lines">@@ -6190,6 +6196,7 @@
</span><span class="cx">                                 E33B3E261B7ABD750048DB2E /* InspectorInstrumentationObject.lut.h in Headers */,
</span><span class="cx">                                 A7D89CFE17A0B8CC00773AD8 /* DFGOSRAvailabilityAnalysisPhase.h in Headers */,
</span><span class="cx">                                 0FD82E57141DAF1000179C94 /* DFGOSREntry.h in Headers */,
</span><ins>+                                627673241B680C1E00FD9F2E /* CallMode.h in Headers */,
</ins><span class="cx">                                 0FD8A32617D51F5700CA2C40 /* DFGOSREntrypointCreationPhase.h in Headers */,
</span><span class="cx">                                 62F2AA381B0BEDE300610C7A /* DFGLazyNode.h in Headers */,
</span><span class="cx">                                 0FC0976A1468A6F700CF2442 /* DFGOSRExit.h in Headers */,
</span><span class="lines">@@ -7971,6 +7978,7 @@
</span><span class="cx">                                 0F2D4DEF19832DD3007D4B19 /* TypeSet.cpp in Sources */,
</span><span class="cx">                                 9335F24D12E6765B002B5553 /* StringRecursionChecker.cpp in Sources */,
</span><span class="cx">                                 BCDE3B430E6C832D001453A7 /* Structure.cpp in Sources */,
</span><ins>+                                627673231B680C1E00FD9F2E /* CallMode.cpp in Sources */,
</ins><span class="cx">                                 7E4EE70F0EBB7A5B005934AA /* StructureChain.cpp in Sources */,
</span><span class="cx">                                 C2F0F2D116BAEEE900187C19 /* StructureRareData.cpp in Sources */,
</span><span class="cx">                                 0FD3E40B1B618B6600C80E1E /* ObjectPropertyConditionSet.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerAbortReasonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/AbortReason.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/AbortReason.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/assembler/AbortReason.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -58,6 +58,7 @@
</span><span class="cx">     DFGUnreachableBasicBlock                          = 220,
</span><span class="cx">     DFGUnreasonableOSREntryJumpDestination            = 230,
</span><span class="cx">     DFGVarargsThrowingPathDidNotThrow                 = 235,
</span><ins>+    JITDidReturnFromTailCall                          = 237,
</ins><span class="cx">     JITDivOperandsAreNotNumbers                       = 240,
</span><span class="cx">     JITGetByValResultIsNotEmpty                       = 250,
</span><span class="cx">     JITNotSupported                                   = 260,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerAbstractMacroAssemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -507,7 +507,9 @@
</span><span class="cx">             None = 0x0,
</span><span class="cx">             Linkable = 0x1,
</span><span class="cx">             Near = 0x2,
</span><ins>+            Tail = 0x4,
</ins><span class="cx">             LinkableNear = 0x3,
</span><ins>+            LinkableNearTail = 0x7,
</ins><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Call()
</span><span class="lines">@@ -962,7 +964,15 @@
</span><span class="cx"> 
</span><span class="cx">     static void repatchNearCall(CodeLocationNearCall nearCall, CodeLocationLabel destination)
</span><span class="cx">     {
</span><del>-        AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
</del><ins>+        switch (nearCall.callMode()) {
+        case NearCallMode::Tail:
+            AssemblerType::relinkJump(nearCall.dataLocation(), destination.executableAddress());
+            return;
+        case NearCallMode::Regular:
+            AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
+            return;
+        }
+        RELEASE_ASSERT_NOT_REACHED();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerCodeLocationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/CodeLocation.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/CodeLocation.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/assembler/CodeLocation.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -32,6 +32,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+enum NearCallMode { Regular, Tail };
+
</ins><span class="cx"> class CodeLocationInstruction;
</span><span class="cx"> class CodeLocationLabel;
</span><span class="cx"> class CodeLocationJump;
</span><span class="lines">@@ -59,7 +61,7 @@
</span><span class="cx">     CodeLocationLabel labelAtOffset(int offset);
</span><span class="cx">     CodeLocationJump jumpAtOffset(int offset);
</span><span class="cx">     CodeLocationCall callAtOffset(int offset);
</span><del>-    CodeLocationNearCall nearCallAtOffset(int offset);
</del><ins>+    CodeLocationNearCall nearCallAtOffset(int offset, NearCallMode);
</ins><span class="cx">     CodeLocationDataLabelPtr dataLabelPtrAtOffset(int offset);
</span><span class="cx">     CodeLocationDataLabel32 dataLabel32AtOffset(int offset);
</span><span class="cx">     CodeLocationDataLabelCompact dataLabelCompactAtOffset(int offset);
</span><span class="lines">@@ -115,10 +117,13 @@
</span><span class="cx"> class CodeLocationNearCall : public CodeLocationCommon {
</span><span class="cx"> public:
</span><span class="cx">     CodeLocationNearCall() {}
</span><del>-    explicit CodeLocationNearCall(MacroAssemblerCodePtr location)
-        : CodeLocationCommon(location) {}
-    explicit CodeLocationNearCall(void* location)
-        : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
</del><ins>+    explicit CodeLocationNearCall(MacroAssemblerCodePtr location, NearCallMode callMode)
+        : CodeLocationCommon(location), m_callMode(callMode) { }
+    explicit CodeLocationNearCall(void* location, NearCallMode callMode)
+        : CodeLocationCommon(MacroAssemblerCodePtr(location)), m_callMode(callMode) { }
+    NearCallMode callMode() { return m_callMode; }
+private:
+    NearCallMode m_callMode = NearCallMode::Regular;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class CodeLocationDataLabel32 : public CodeLocationCommon {
</span><span class="lines">@@ -181,10 +186,10 @@
</span><span class="cx">     return CodeLocationCall(reinterpret_cast&lt;char*&gt;(dataLocation()) + offset);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline CodeLocationNearCall CodeLocationCommon::nearCallAtOffset(int offset)
</del><ins>+inline CodeLocationNearCall CodeLocationCommon::nearCallAtOffset(int offset, NearCallMode callMode)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT_VALID_CODE_OFFSET(offset);
</span><del>-    return CodeLocationNearCall(reinterpret_cast&lt;char*&gt;(dataLocation()) + offset);
</del><ins>+    return CodeLocationNearCall(reinterpret_cast&lt;char*&gt;(dataLocation()) + offset, callMode);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline CodeLocationDataLabelPtr CodeLocationCommon::dataLabelPtrAtOffset(int offset)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerLinkBufferh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/LinkBuffer.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/LinkBuffer.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/assembler/LinkBuffer.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -180,7 +180,8 @@
</span><span class="cx">     {
</span><span class="cx">         ASSERT(call.isFlagSet(Call::Linkable));
</span><span class="cx">         ASSERT(call.isFlagSet(Call::Near));
</span><del>-        return CodeLocationNearCall(MacroAssembler::getLinkerAddress(code(), applyOffset(call.m_label)));
</del><ins>+        return CodeLocationNearCall(MacroAssembler::getLinkerAddress(code(), applyOffset(call.m_label)),
+            call.isFlagSet(Call::Tail) ? NearCallMode::Tail : NearCallMode::Regular);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     CodeLocationLabel locationOf(PatchableJump jump)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerARMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -904,6 +904,11 @@
</span><span class="cx">         return Call(m_assembler.blx(ARMRegisters::S1), Call::LinkableNear);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    Call nearTailCall()
+    {
+        return Call(m_assembler.jmp(), Call::LinkableNearTail);
+    }
+
</ins><span class="cx">     Call call(RegisterID target)
</span><span class="cx">     {
</span><span class="cx">         return Call(m_assembler.blx(target), Call::None);
</span><span class="lines">@@ -1488,7 +1493,10 @@
</span><span class="cx"> 
</span><span class="cx">     static void linkCall(void* code, Call call, FunctionPtr function)
</span><span class="cx">     {
</span><del>-        ARMAssembler::linkCall(code, call.m_label, function.value());
</del><ins>+        if (call.isFlagSet(Call::Tail))
+            ARMAssembler::linkJump(code, call.m_label, function.value());
+        else
+            ARMAssembler::linkCall(code, call.m_label, function.value());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerARM64h"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -2204,6 +2204,13 @@
</span><span class="cx">         return Call(m_assembler.label(), Call::LinkableNear);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ALWAYS_INLINE Call nearTailCall()
+    {
+        AssemblerLabel label = m_assembler.label();
+        m_assembler.b();
+        return Call(label, Call::LinkableNearTail);
+    }
+
</ins><span class="cx">     ALWAYS_INLINE void ret()
</span><span class="cx">     {
</span><span class="cx">         m_assembler.ret();
</span><span class="lines">@@ -2882,10 +2889,12 @@
</span><span class="cx"> 
</span><span class="cx">     static void linkCall(void* code, Call call, FunctionPtr function)
</span><span class="cx">     {
</span><del>-        if (call.isFlagSet(Call::Near))
</del><ins>+        if (!call.isFlagSet(Call::Near))
+            ARM64Assembler::linkPointer(code, call.m_label.labelAtOffset(REPATCH_OFFSET_CALL_TO_POINTER), function.value());
+        else if (call.isFlagSet(Call::Tail))
+            ARM64Assembler::linkJump(code, call.m_label, function.value());
+        else
</ins><span class="cx">             ARM64Assembler::linkCall(code, call.m_label, function.value());
</span><del>-        else
-            ARM64Assembler::linkPointer(code, call.m_label.labelAtOffset(REPATCH_OFFSET_CALL_TO_POINTER), function.value());
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     CachedTempRegister m_dataMemoryTempRegister;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerARMv7h"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -1677,6 +1677,12 @@
</span><span class="cx">         return Call(m_assembler.blx(dataTempRegister), Call::LinkableNear);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ALWAYS_INLINE Call nearTailCall()
+    {
+        moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister);
+        return Call(m_assembler.bx(dataTempRegister), Call::LinkableNearTail);
+    }
+
</ins><span class="cx">     ALWAYS_INLINE Call call()
</span><span class="cx">     {
</span><span class="cx">         moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister);
</span><span class="lines">@@ -2012,7 +2018,10 @@
</span><span class="cx"> 
</span><span class="cx">     static void linkCall(void* code, Call call, FunctionPtr function)
</span><span class="cx">     {
</span><del>-        ARMv7Assembler::linkCall(code, call.m_label, function.value());
</del><ins>+        if (call.isFlagSet(Call::Tail))
+            ARMv7Assembler::linkJump(code, call.m_label, function.value());
+        else
+            ARMv7Assembler::linkCall(code, call.m_label, function.value());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MASM_PROBE)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerMIPSh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -1975,6 +1975,16 @@
</span><span class="cx">         return Call(m_assembler.label(), Call::LinkableNear);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    Call nearTailCall()
+    {
+        m_assembler.nop();
+        m_assembler.nop();
+        m_assembler.beq(MIPSRegisters::zero, MIPSRegisters::zero, 0);
+        m_assembler.nop();
+        insertRelaxationWords();
+        return Call(m_assembler.label(), Call::LinkableNearTail);
+    }
+
</ins><span class="cx">     Call call()
</span><span class="cx">     {
</span><span class="cx">         m_assembler.lui(MIPSRegisters::t9, 0);
</span><span class="lines">@@ -2800,7 +2810,10 @@
</span><span class="cx"> 
</span><span class="cx">     static void linkCall(void* code, Call call, FunctionPtr function)
</span><span class="cx">     {
</span><del>-        MIPSAssembler::linkCall(code, call.m_label, function.value());
</del><ins>+        if (call.isFlagSet(Call::Tail))
+            MIPSAssembler::linkJump(code, call.m_label, function.value());
+        else
+            MIPSAssembler::linkCall(code, call.m_label, function.value());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerSH4h"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -2403,6 +2403,11 @@
</span><span class="cx">         return Call(m_assembler.call(), Call::Linkable);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    Call nearTailCall()
+    {
+        return Call(m_assembler.jump(), Call::LinkableNearTail);
+    }
+
</ins><span class="cx">     Call nearCall()
</span><span class="cx">     {
</span><span class="cx">         return Call(m_assembler.call(), Call::LinkableNear);
</span><span class="lines">@@ -2608,7 +2613,10 @@
</span><span class="cx"> 
</span><span class="cx">     static void linkCall(void* code, Call call, FunctionPtr function)
</span><span class="cx">     {
</span><del>-        SH4Assembler::linkCall(code, call.m_label, function.value());
</del><ins>+        if (call.isFlagSet(Call::Tail))
+            SH4Assembler::linkJump(code, call.m_label, function.value());
+        else
+            SH4Assembler::linkCall(code, call.m_label, function.value());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerX86h"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -361,7 +361,10 @@
</span><span class="cx"> 
</span><span class="cx">     static void linkCall(void* code, Call call, FunctionPtr function)
</span><span class="cx">     {
</span><del>-        X86Assembler::linkCall(code, call.m_label, function.value());
</del><ins>+        if (call.isFlagSet(Call::Tail))
+            X86Assembler::linkJump(code, call.m_label, function.value());
+        else
+            X86Assembler::linkCall(code, call.m_label, function.value());
</ins><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerX86Commonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -1403,6 +1403,11 @@
</span><span class="cx">         m_assembler.int3();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    Call nearTailCall()
+    {
+        return Call(m_assembler.jmp(), Call::LinkableNearTail);
+    }
+
</ins><span class="cx">     Call nearCall()
</span><span class="cx">     {
</span><span class="cx">         return Call(m_assembler.call(), Call::LinkableNear);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerX86_64h"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -872,6 +872,8 @@
</span><span class="cx">     {
</span><span class="cx">         if (!call.isFlagSet(Call::Near))
</span><span class="cx">             X86Assembler::linkPointer(code, call.m_label.labelAtOffset(-REPATCH_OFFSET_CALL_R11), function.value());
</span><ins>+        else if (call.isFlagSet(Call::Tail))
+            X86Assembler::linkJump(code, call.m_label, function.value());
</ins><span class="cx">         else
</span><span class="cx">             X86Assembler::linkCall(code, call.m_label, function.value());
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeListjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeList.json (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -92,8 +92,10 @@
</span><span class="cx">             { &quot;name&quot; : &quot;op_new_func_exp&quot;, &quot;length&quot; : 4 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_new_arrow_func_exp&quot;, &quot;length&quot; : 5 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_call&quot;, &quot;length&quot; : 9 },
</span><ins>+            { &quot;name&quot; : &quot;op_tail_call&quot;, &quot;length&quot; : 9 },
</ins><span class="cx">             { &quot;name&quot; : &quot;op_call_eval&quot;, &quot;length&quot; : 9 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_call_varargs&quot;, &quot;length&quot; : 9 },
</span><ins>+            { &quot;name&quot; : &quot;op_tail_call_varargs&quot;, &quot;length&quot; : 9 },
</ins><span class="cx">             { &quot;name&quot; : &quot;op_ret&quot;, &quot;length&quot; : 2 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_construct&quot;, &quot;length&quot; : 9 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_construct_varargs&quot;, &quot;length&quot; : 9 },
</span><span class="lines">@@ -144,7 +146,8 @@
</span><span class="cx">             { &quot;name&quot; : &quot;llint_cloop_did_return_from_js_5&quot; },
</span><span class="cx">             { &quot;name&quot; : &quot;llint_cloop_did_return_from_js_6&quot; },
</span><span class="cx">             { &quot;name&quot; : &quot;llint_cloop_did_return_from_js_7&quot; },
</span><del>-            { &quot;name&quot; : &quot;llint_cloop_did_return_from_js_8&quot; }
</del><ins>+            { &quot;name&quot; : &quot;llint_cloop_did_return_from_js_8&quot; },
+            { &quot;name&quot; : &quot;llint_cloop_did_return_from_js_9&quot; }
</ins><span class="cx">         ]
</span><span class="cx">     },
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeUseDefh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -191,7 +191,8 @@
</span><span class="cx">     }
</span><span class="cx">     case op_has_structure_property:
</span><span class="cx">     case op_construct_varargs:
</span><del>-    case op_call_varargs: {
</del><ins>+    case op_call_varargs:
+    case op_tail_call_varargs: {
</ins><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
</span><span class="lines">@@ -220,7 +221,8 @@
</span><span class="cx">     }
</span><span class="cx">     case op_construct:
</span><span class="cx">     case op_call_eval:
</span><del>-    case op_call: {
</del><ins>+    case op_call:
+    case op_tail_call: {
</ins><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
</span><span class="cx">         int argCount = instruction[3].u.operand;
</span><span class="cx">         int registerOffset = -instruction[4].u.operand;
</span><span class="lines">@@ -311,9 +313,11 @@
</span><span class="cx">     case op_new_func_exp:
</span><span class="cx">     case op_new_arrow_func_exp:
</span><span class="cx">     case op_call_varargs:
</span><ins>+    case op_tail_call_varargs:
</ins><span class="cx">     case op_construct_varargs:
</span><span class="cx">     case op_get_from_scope:
</span><span class="cx">     case op_call:
</span><ins>+    case op_tail_call:
</ins><span class="cx">     case op_call_eval:
</span><span class="cx">     case op_construct:
</span><span class="cx">     case op_get_by_id:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #ifndef CallLinkInfo_h
</span><span class="cx"> #define CallLinkInfo_h
</span><span class="cx"> 
</span><ins>+#include &quot;CallMode.h&quot;
</ins><span class="cx"> #include &quot;CodeLocation.h&quot;
</span><span class="cx"> #include &quot;CodeSpecializationKind.h&quot;
</span><span class="cx"> #include &quot;JITWriteBarrier.h&quot;
</span><span class="lines">@@ -41,19 +42,36 @@
</span><span class="cx"> 
</span><span class="cx"> class CallLinkInfo : public BasicRawSentinelNode&lt;CallLinkInfo&gt; {
</span><span class="cx"> public:
</span><del>-    enum CallType { None, Call, CallVarargs, Construct, ConstructVarargs };
</del><ins>+    enum CallType { None, Call, CallVarargs, Construct, ConstructVarargs, TailCall, TailCallVarargs };
</ins><span class="cx">     static CallType callTypeFor(OpcodeID opcodeID)
</span><span class="cx">     {
</span><span class="cx">         if (opcodeID == op_call || opcodeID == op_call_eval)
</span><span class="cx">             return Call;
</span><ins>+        if (opcodeID == op_call_varargs)
+            return CallVarargs;
</ins><span class="cx">         if (opcodeID == op_construct)
</span><span class="cx">             return Construct;
</span><span class="cx">         if (opcodeID == op_construct_varargs)
</span><span class="cx">             return ConstructVarargs;
</span><del>-        ASSERT(opcodeID == op_call_varargs);
-        return CallVarargs;
</del><ins>+        if (opcodeID == op_tail_call)
+            return TailCall;
+        ASSERT(opcodeID == op_tail_call_varargs);
+        return TailCallVarargs;
</ins><span class="cx">     }
</span><del>-    
</del><ins>+
+    static bool isVarargsCallType(CallType callType)
+    {
+        switch (callType) {
+        case CallVarargs:
+        case ConstructVarargs:
+        case TailCallVarargs:
+            return true;
+
+        default:
+            return false;
+        }
+    }
+
</ins><span class="cx">     CallLinkInfo()
</span><span class="cx">         : m_registerPreservationMode(static_cast&lt;unsigned&gt;(RegisterPreservationNotRequired))
</span><span class="cx">         , m_hasSeenShouldRepatch(false)
</span><span class="lines">@@ -83,6 +101,40 @@
</span><span class="cx">         return specializationKindFor(static_cast&lt;CallType&gt;(m_callType));
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static CallMode callModeFor(CallType callType)
+    {
+        switch (callType) {
+        case Call:
+        case CallVarargs:
+            return CallMode::Regular;
+        case TailCall:
+        case TailCallVarargs:
+            return CallMode::Tail;
+        case Construct:
+        case ConstructVarargs:
+            return CallMode::Construct;
+        case None:
+            RELEASE_ASSERT_NOT_REACHED();
+        }
+
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+
+    CallMode callMode() const
+    {
+        return callModeFor(static_cast&lt;CallType&gt;(m_callType));
+    }
+
+    bool isTailCall() const
+    {
+        return callMode() == CallMode::Tail;
+    }
+
+    bool isVarargs() const
+    {
+        return isVarargsCallType(static_cast&lt;CallType&gt;(m_callType));
+    }
+
</ins><span class="cx">     RegisterPreservationMode registerPreservationMode() const
</span><span class="cx">     {
</span><span class="cx">         return static_cast&lt;RegisterPreservationMode&gt;(m_registerPreservationMode);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkStatuscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -69,7 +69,7 @@
</span><span class="cx">     
</span><span class="cx">     Instruction* instruction = profiledBlock-&gt;instructions().begin() + bytecodeIndex;
</span><span class="cx">     OpcodeID op = vm.interpreter-&gt;getOpcodeID(instruction[0].u.opcode);
</span><del>-    if (op != op_call &amp;&amp; op != op_construct)
</del><ins>+    if (op != op_call &amp;&amp; op != op_construct &amp;&amp; op != op_tail_call)
</ins><span class="cx">         return CallLinkStatus();
</span><span class="cx">     
</span><span class="cx">     LLIntCallLinkInfo* callLinkInfo = instruction[5].u.callLinkInfo;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallModecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/CallMode.cpp (0 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallMode.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/CallMode.cpp        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -0,0 +1,49 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;CallMode.h&quot;
+
+#include &lt;wtf/PrintStream.h&gt;
+
+namespace WTF {
+
+void printInternal(PrintStream&amp; out, JSC::CallMode callMode)
+{
+    switch (callMode) {
+    case JSC::CallMode::Tail:
+        out.print(&quot;TailCall&quot;);
+        return;
+    case JSC::CallMode::Regular:
+        out.print(&quot;Call&quot;);
+        return;
+    case JSC::CallMode::Construct:
+        out.print(&quot;Construct&quot;);
+        return;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+} // namespace WTF
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallModeh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/CallMode.h (0 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallMode.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/CallMode.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -0,0 +1,45 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef CallMode_h
+#define CallMode_h
+
+namespace JSC {
+
+enum class CallMode { Regular, Tail, Construct };
+
+enum FrameAction { KeepTheFrame = 0, ReuseTheFrame };
+
+} // namespace JSC
+
+namespace WTF {
+
+class PrintStream;
+void printInternal(PrintStream&amp;, JSC::CallMode);
+
+} // namespace WTF
+
+#endif // CallMode_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -1248,13 +1248,18 @@
</span><span class="cx">             printCallOp(out, exec, location, it, &quot;call&quot;, DumpCaches, hasPrintedProfiling, callLinkInfos);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><ins>+        case op_tail_call: {
+            printCallOp(out, exec, location, it, &quot;tail_call&quot;, DumpCaches, hasPrintedProfiling, callLinkInfos);
+            break;
+        }
</ins><span class="cx">         case op_call_eval: {
</span><span class="cx">             printCallOp(out, exec, location, it, &quot;call_eval&quot;, DontDumpCaches, hasPrintedProfiling, callLinkInfos);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         case op_construct_varargs:
</span><del>-        case op_call_varargs: {
</del><ins>+        case op_call_varargs:
+        case op_tail_call_varargs: {
</ins><span class="cx">             int result = (++it)-&gt;u.operand;
</span><span class="cx">             int callee = (++it)-&gt;u.operand;
</span><span class="cx">             int thisValue = (++it)-&gt;u.operand;
</span><span class="lines">@@ -1262,7 +1267,7 @@
</span><span class="cx">             int firstFreeRegister = (++it)-&gt;u.operand;
</span><span class="cx">             int varArgOffset = (++it)-&gt;u.operand;
</span><span class="cx">             ++it;
</span><del>-            printLocationAndOp(out, exec, location, it, opcode == op_call_varargs ? &quot;call_varargs&quot; : &quot;construct_varargs&quot;);
</del><ins>+            printLocationAndOp(out, exec, location, it, opcode == op_call_varargs ? &quot;call_varargs&quot; : opcode == op_construct_varargs ? &quot;construct_varargs&quot; : &quot;tail_call_varargs&quot;);
</ins><span class="cx">             out.printf(&quot;%s, %s, %s, %s, %d, %d&quot;, registerName(result).data(), registerName(callee).data(), registerName(thisValue).data(), registerName(arguments).data(), firstFreeRegister, varArgOffset);
</span><span class="cx">             dumpValueProfiling(out, it, hasPrintedProfiling);
</span><span class="cx">             break;
</span><span class="lines">@@ -1829,6 +1834,7 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case op_call_varargs:
</span><ins>+        case op_tail_call_varargs:
</ins><span class="cx">         case op_construct_varargs:
</span><span class="cx">         case op_get_by_val: {
</span><span class="cx">             int arrayProfileIndex = pc[opLength - 2].u.operand;
</span><span class="lines">@@ -1878,6 +1884,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case op_call:
</span><ins>+        case op_tail_call:
</ins><span class="cx">         case op_call_eval: {
</span><span class="cx">             ValueProfile* profile = &amp;m_valueProfiles[pc[opLength - 1].u.operand];
</span><span class="cx">             ASSERT(profile-&gt;m_bytecodeOffset == -1);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -193,7 +193,12 @@
</span><span class="cx">     , m_vm(&amp;vm)
</span><span class="cx">     , m_isBuiltinFunction(codeBlock-&gt;isBuiltinFunction())
</span><span class="cx">     , m_usesNonStrictEval(codeBlock-&gt;usesEval() &amp;&amp; !codeBlock-&gt;isStrictMode())
</span><del>-    , m_inTailPosition(Options::enableTailCalls() &amp;&amp; constructorKind() == ConstructorKind::None &amp;&amp; isStrictMode())
</del><ins>+    // FIXME: We should be able to have tail call elimination with the profiler
+    // enabled. This is currently not possible because the profiler expects
+    // op_will_call / op_did_call pairs before and after a call, which are not
+    // compatible with tail calls (we have no way of emitting op_did_call).
+    // https://bugs.webkit.org/show_bug.cgi?id=148819
+    , m_inTailPosition(Options::enableTailCalls() &amp;&amp; constructorKind() == ConstructorKind::None &amp;&amp; isStrictMode() &amp;&amp; !m_shouldEmitProfileHooks)
</ins><span class="cx"> {
</span><span class="cx">     for (auto&amp; constantRegister : m_linkTimeConstantRegisters)
</span><span class="cx">         constantRegister = nullptr;
</span><span class="lines">@@ -2513,10 +2518,7 @@
</span><span class="cx"> 
</span><span class="cx"> RegisterID* BytecodeGenerator::emitCallInTailPosition(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments&amp; callArguments, const JSTextPosition&amp; divot, const JSTextPosition&amp; divotStart, const JSTextPosition&amp; divotEnd)
</span><span class="cx"> {
</span><del>-    // FIXME: We should be emitting a new op_tail_call here when
-    // m_inTailPosition is false
-    // https://bugs.webkit.org/show_bug.cgi?id=148661
-    return emitCall(op_call, dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd);
</del><ins>+    return emitCall(m_inTailPosition ? op_tail_call : op_call, dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&amp; callArguments, const JSTextPosition&amp; divot, const JSTextPosition&amp; divotStart, const JSTextPosition&amp; divotEnd)
</span><span class="lines">@@ -2601,7 +2603,7 @@
</span><span class="cx"> 
</span><span class="cx"> RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments&amp; callArguments, const JSTextPosition&amp; divot, const JSTextPosition&amp; divotStart, const JSTextPosition&amp; divotEnd)
</span><span class="cx"> {
</span><del>-    ASSERT(opcodeID == op_call || opcodeID == op_call_eval);
</del><ins>+    ASSERT(opcodeID == op_call || opcodeID == op_call_eval || opcodeID == op_tail_call);
</ins><span class="cx">     ASSERT(func-&gt;refCount());
</span><span class="cx"> 
</span><span class="cx">     if (m_shouldEmitProfileHooks)
</span><span class="lines">@@ -2617,7 +2619,7 @@
</span><span class="cx">             RefPtr&lt;RegisterID&gt; argumentRegister;
</span><span class="cx">             argumentRegister = expression-&gt;emitBytecode(*this, callArguments.argumentRegister(0));
</span><span class="cx">             RefPtr&lt;RegisterID&gt; thisRegister = emitMove(newTemporary(), callArguments.thisRegister());
</span><del>-            return emitCallVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, callArguments.profileHookRegister(), divot, divotStart, divotEnd);
</del><ins>+            return emitCallVarargs(opcodeID == op_tail_call ? op_tail_call_varargs : op_call_varargs, dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, callArguments.profileHookRegister(), divot, divotStart, divotEnd);
</ins><span class="cx">         }
</span><span class="cx">         for (; n; n = n-&gt;m_next)
</span><span class="cx">             emitNode(callArguments.argumentRegister(argument++), n);
</span><span class="lines">@@ -2670,10 +2672,7 @@
</span><span class="cx"> 
</span><span class="cx"> RegisterID* BytecodeGenerator::emitCallVarargsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition&amp; divot, const JSTextPosition&amp; divotStart, const JSTextPosition&amp; divotEnd)
</span><span class="cx"> {
</span><del>-    // FIXME: We should be emitting a new op_tail_call here when
-    // m_inTailPosition is false
-    // https://bugs.webkit.org/show_bug.cgi?id=148661
-    return emitCallVarargs(op_call_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
</del><ins>+    return emitCallVarargs(m_inTailPosition ? op_tail_call_varargs : op_call_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RegisterID* BytecodeGenerator::emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition&amp; divot, const JSTextPosition&amp; divotStart, const JSTextPosition&amp; divotEnd)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -678,6 +678,12 @@
</span><span class="cx">         m_argv[i] = generator.newTemporary();
</span><span class="cx">         ASSERT(static_cast&lt;size_t&gt;(i) == m_argv.size() - 1 || m_argv[i]-&gt;index() == m_argv[i + 1]-&gt;index() - 1);
</span><span class="cx">     }
</span><ins>+
+    // We need to ensure that the frame size is stack-aligned
+    while ((JSStack::CallFrameHeaderSize + m_argv.size()) % stackAlignmentRegisters()) {
+        m_argv.insert(0, generator.newTemporary());
+        m_padding++;
+    }
</ins><span class="cx">     
</span><span class="cx">     while (stackOffset() % stackAlignmentRegisters()) {
</span><span class="cx">         m_argv.insert(0, generator.newTemporary());
</span><span class="lines">@@ -2786,7 +2792,7 @@
</span><span class="cx">     ASSERT(!generator.breakTarget(m_name));
</span><span class="cx"> 
</span><span class="cx">     LabelScopePtr scope = generator.newLabelScope(LabelScope::NamedLabel, &amp;m_name);
</span><del>-    generator.emitNode(dst, m_statement);
</del><ins>+    generator.emitNodeInTailPosition(dst, m_statement);
</ins><span class="cx"> 
</span><span class="cx">     generator.emitLabel(scope-&gt;breakTarget());
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -741,7 +741,10 @@
</span><span class="cx">         SpeculatedType prediction)
</span><span class="cx">     {
</span><span class="cx">         addVarArgChild(callee);
</span><del>-        size_t parameterSlots = JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize + argCount;
</del><ins>+        size_t frameSize = JSStack::CallFrameHeaderSize + argCount;
+        size_t alignedFrameSize = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), frameSize);
+        size_t parameterSlots = alignedFrameSize - JSStack::CallerFrameAndPCSize;
+
</ins><span class="cx">         if (parameterSlots &gt; m_parameterSlots)
</span><span class="cx">             m_parameterSlots = parameterSlots;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -4329,24 +4329,29 @@
</span><span class="cx"> 
</span><span class="cx">     void compileCallOrConstruct()
</span><span class="cx">     {
</span><del>-        int numPassedArgs = m_node-&gt;numChildren() - 1;
-        int numArgs = numPassedArgs;
</del><ins>+        int numArgs = m_node-&gt;numChildren() - 1;
</ins><span class="cx"> 
</span><span class="cx">         LValue jsCallee = lowJSValue(m_graph.varArgChild(m_node, 0));
</span><span class="cx"> 
</span><span class="cx">         unsigned stackmapID = m_stackmapIDs++;
</span><del>-        
</del><ins>+
+        unsigned frameSize = JSStack::CallFrameHeaderSize + numArgs;
+        unsigned alignedFrameSize = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), frameSize);
+        unsigned padding = alignedFrameSize - frameSize;
+
</ins><span class="cx">         Vector&lt;LValue&gt; arguments;
</span><span class="cx">         arguments.append(m_out.constInt64(stackmapID));
</span><span class="cx">         arguments.append(m_out.constInt32(sizeOfCall()));
</span><span class="cx">         arguments.append(constNull(m_out.ref8));
</span><del>-        arguments.append(m_out.constInt32(1 + JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize + numArgs));
</del><ins>+        arguments.append(m_out.constInt32(1 + alignedFrameSize - JSStack::CallerFrameAndPCSize));
</ins><span class="cx">         arguments.append(jsCallee); // callee -&gt; %rax
</span><span class="cx">         arguments.append(getUndef(m_out.int64)); // code block
</span><span class="cx">         arguments.append(jsCallee); // callee -&gt; stack
</span><span class="cx">         arguments.append(m_out.constInt64(numArgs)); // argument count and zeros for the tag
</span><del>-        for (int i = 0; i &lt; numPassedArgs; ++i)
</del><ins>+        for (int i = 0; i &lt; numArgs; ++i)
</ins><span class="cx">             arguments.append(lowJSValue(m_graph.varArgChild(m_node, 1 + i)));
</span><ins>+        for (unsigned i = 0; i &lt; padding; ++i)
+            arguments.append(getUndef(m_out.int64));
</ins><span class="cx">         
</span><span class="cx">         callPreflight();
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpreterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -253,7 +253,7 @@
</span><span class="cx"> 
</span><span class="cx">         void dumpRegisters(CallFrame*);
</span><span class="cx">         
</span><del>-        bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); }
</del><ins>+        bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval) || opcode == getOpcode(op_tail_call); }
</ins><span class="cx"> 
</span><span class="cx">         void enableSampler();
</span><span class="cx">         int m_sampleEntryDepth;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitCCallHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/CCallHelpers.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CCallHelpers.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/jit/CCallHelpers.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;AssemblyHelpers.h&quot;
</span><span class="cx"> #include &quot;GPRInfo.h&quot;
</span><ins>+#include &quot;StackAlignment.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -2082,6 +2083,95 @@
</span><span class="cx">         loadPtr(&amp;vm()-&gt;targetMachinePCForThrow, GPRInfo::regT1);
</span><span class="cx">         jump(GPRInfo::regT1);
</span><span class="cx">     }
</span><ins>+
+    void prepareForTailCallSlow(GPRReg calleeGPR = InvalidGPRReg)
+    {
+        GPRReg temp1 = calleeGPR == GPRInfo::regT0 ? GPRInfo::regT3 : GPRInfo::regT0;
+        GPRReg temp2 = calleeGPR == GPRInfo::regT1 ? GPRInfo::regT3 : GPRInfo::regT1;
+        GPRReg temp3 = calleeGPR == GPRInfo::regT2 ? GPRInfo::regT3 : GPRInfo::regT2;
+
+        GPRReg newFramePointer = temp1;
+        GPRReg newFrameSizeGPR = temp2;
+        {
+            // The old frame size is its number of arguments (or number of
+            // parameters in case of arity fixup), plus the frame header size,
+            // aligned
+            GPRReg oldFrameSizeGPR = temp2;
+            {
+                GPRReg argCountGPR = oldFrameSizeGPR;
+                load32(Address(framePointerRegister, JSStack::ArgumentCount * static_cast&lt;int&gt;(sizeof(Register)) + PayloadOffset), argCountGPR);
+
+                {
+                    GPRReg numParametersGPR = temp1;
+                    {
+                        GPRReg codeBlockGPR = numParametersGPR;
+                        loadPtr(Address(framePointerRegister, JSStack::CodeBlock * static_cast&lt;int&gt;(sizeof(Register))), codeBlockGPR);
+                        load32(Address(codeBlockGPR, CodeBlock::offsetOfNumParameters()), numParametersGPR);
+                    }
+
+                    ASSERT(numParametersGPR != argCountGPR);
+                    Jump argumentCountWasNotFixedUp = branch32(BelowOrEqual, numParametersGPR, argCountGPR);
+                    move(numParametersGPR, argCountGPR);
+                    argumentCountWasNotFixedUp.link(this);
+                }
+
+                add32(TrustedImm32(stackAlignmentRegisters() + JSStack::CallFrameHeaderSize - 1), argCountGPR, oldFrameSizeGPR);
+                and32(TrustedImm32(-stackAlignmentRegisters()), oldFrameSizeGPR);
+                // We assume &lt; 2^28 arguments
+                mul32(TrustedImm32(sizeof(Register)), oldFrameSizeGPR, oldFrameSizeGPR);
+            }
+
+            // The new frame pointer is at framePointer + oldFrameSize - newFrameSize
+            ASSERT(newFramePointer != oldFrameSizeGPR);
+            move(framePointerRegister, newFramePointer);
+            addPtr(oldFrameSizeGPR, newFramePointer);
+
+            // The new frame size is just the number of arguments plus the
+            // frame header size, aligned
+            ASSERT(newFrameSizeGPR != newFramePointer);
+            load32(Address(stackPointerRegister, JSStack::ArgumentCount * static_cast&lt;int&gt;(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC)),
+                newFrameSizeGPR);
+            add32(TrustedImm32(stackAlignmentRegisters() + JSStack::CallFrameHeaderSize - 1), newFrameSizeGPR);
+            and32(TrustedImm32(-stackAlignmentRegisters()), newFrameSizeGPR);
+            // We assume &lt; 2^28 arguments
+            mul32(TrustedImm32(sizeof(Register)), newFrameSizeGPR, newFrameSizeGPR);
+        }
+
+        GPRReg tempGPR = temp3;
+        ASSERT(tempGPR != newFramePointer &amp;&amp; tempGPR != newFrameSizeGPR);
+
+        // We don't need the current frame beyond this point. Masquerade as our
+        // caller.
+#if CPU(ARM) || CPU(SH4) || CPU(ARM64)
+        loadPtr(Address(framePointerRegister, sizeof(void*)), linkRegister);
+        subPtr(TrustedImm32(2 * sizeof(void*)), newFrameSizeGPR);
+#elif CPU(MIPS)
+        loadPtr(Address(framePointerRegister, sizeof(void*)), returnAddressRegister);
+        subPtr(TrustedImm32(2 * sizeof(void*)), newFrameSizeGPR);
+#elif CPU(X86) || CPU(X86_64)
+        loadPtr(Address(framePointerRegister, sizeof(void*)), tempGPR);
+        push(tempGPR);
+        subPtr(TrustedImm32(sizeof(void*)), newFrameSizeGPR);
+#else
+        UNREACHABLE_FOR_PLATFORM();
+#endif
+        subPtr(newFrameSizeGPR, newFramePointer);
+        loadPtr(Address(framePointerRegister), framePointerRegister);
+
+
+        // We need to move the newFrameSizeGPR slots above the stack pointer by
+        // newFramePointer registers. We use pointer-sized chunks.
+        MacroAssembler::Label copyLoop(label());
+
+        subPtr(TrustedImm32(sizeof(void*)), newFrameSizeGPR);
+        loadPtr(BaseIndex(stackPointerRegister, newFrameSizeGPR, TimesOne), tempGPR);
+        storePtr(tempGPR, BaseIndex(newFramePointer, newFrameSizeGPR, TimesOne));
+
+        branchTest32(MacroAssembler::NonZero, newFrameSizeGPR).linkTo(copyLoop, this);
+
+        // Ready for a jump!
+        move(newFramePointer, stackPointerRegister);
+    }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.cpp (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -197,8 +197,10 @@
</span><span class="cx">         DEFINE_OP(op_bitor)
</span><span class="cx">         DEFINE_OP(op_bitxor)
</span><span class="cx">         DEFINE_OP(op_call)
</span><ins>+        DEFINE_OP(op_tail_call)
</ins><span class="cx">         DEFINE_OP(op_call_eval)
</span><span class="cx">         DEFINE_OP(op_call_varargs)
</span><ins>+        DEFINE_OP(op_tail_call_varargs)
</ins><span class="cx">         DEFINE_OP(op_construct_varargs)
</span><span class="cx">         DEFINE_OP(op_catch)
</span><span class="cx">         DEFINE_OP(op_construct)
</span><span class="lines">@@ -371,8 +373,10 @@
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_bitor)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_bitxor)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_call)
</span><ins>+        DEFINE_SLOWCASE_OP(op_tail_call)
</ins><span class="cx">         DEFINE_SLOWCASE_OP(op_call_eval)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_call_varargs)
</span><ins>+        DEFINE_SLOWCASE_OP(op_tail_call_varargs)
</ins><span class="cx">         DEFINE_SLOWCASE_OP(op_construct_varargs)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_construct)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_to_this)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -487,8 +487,10 @@
</span><span class="cx">         void emit_op_bitor(Instruction*);
</span><span class="cx">         void emit_op_bitxor(Instruction*);
</span><span class="cx">         void emit_op_call(Instruction*);
</span><ins>+        void emit_op_tail_call(Instruction*);
</ins><span class="cx">         void emit_op_call_eval(Instruction*);
</span><span class="cx">         void emit_op_call_varargs(Instruction*);
</span><ins>+        void emit_op_tail_call_varargs(Instruction*);
</ins><span class="cx">         void emit_op_construct_varargs(Instruction*);
</span><span class="cx">         void emit_op_catch(Instruction*);
</span><span class="cx">         void emit_op_construct(Instruction*);
</span><span class="lines">@@ -600,8 +602,10 @@
</span><span class="cx">         void emitSlow_op_bitor(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_bitxor(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_call(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><ins>+        void emitSlow_op_tail_call(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</ins><span class="cx">         void emitSlow_op_call_eval(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_call_varargs(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><ins>+        void emitSlow_op_tail_call_varargs(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</ins><span class="cx">         void emitSlow_op_construct_varargs(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_construct(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_to_this(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="lines">@@ -824,6 +828,7 @@
</span><span class="cx">         void updateTopCallFrame();
</span><span class="cx"> 
</span><span class="cx">         Call emitNakedCall(CodePtr function = CodePtr());
</span><ins>+        Call emitNakedTailCall(CodePtr function = CodePtr());
</ins><span class="cx"> 
</span><span class="cx">         // Loads the character value of a single character string into dst.
</span><span class="cx">         void emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList&amp; failures);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCallcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCall.cpp (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall.cpp        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/jit/JITCall.cpp        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -145,10 +145,12 @@
</span><span class="cx">     COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct), call_and_construct_opcodes_must_be_same_length);
</span><span class="cx">     COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_varargs), call_and_call_varargs_opcodes_must_be_same_length);
</span><span class="cx">     COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct_varargs), call_and_construct_varargs_opcodes_must_be_same_length);
</span><ins>+    COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_tail_call), call_and_tail_call_opcodes_must_be_same_length);
+    COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_tail_call_varargs), call_and_tail_call_varargs_opcodes_must_be_same_length);
</ins><span class="cx">     CallLinkInfo* info;
</span><span class="cx">     if (opcodeID != op_call_eval)
</span><span class="cx">         info = m_codeBlock-&gt;addCallLinkInfo();
</span><del>-    if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs)
</del><ins>+    if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs || opcodeID == op_tail_call_varargs)
</ins><span class="cx">         compileSetupVarargsFrame(instruction, info);
</span><span class="cx">     else {
</span><span class="cx">         int argCount = instruction[3].u.operand;
</span><span class="lines">@@ -172,12 +174,15 @@
</span><span class="cx">     emitGetVirtualRegister(callee, regT0); // regT0 holds callee.
</span><span class="cx"> 
</span><span class="cx">     store64(regT0, Address(stackPointerRegister, JSStack::Callee * static_cast&lt;int&gt;(sizeof(Register)) - sizeof(CallerFrameAndPC)));
</span><del>-    
</del><ins>+
</ins><span class="cx">     if (opcodeID == op_call_eval) {
</span><span class="cx">         compileCallEval(instruction);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs)
+        emitRestoreCalleeSaves();
+
</ins><span class="cx">     DataLabelPtr addressOfLinkedFunctionCheck;
</span><span class="cx">     Jump slowCase = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, TrustedImmPtr(0));
</span><span class="cx">     addSlowCase(slowCase);
</span><span class="lines">@@ -188,6 +193,12 @@
</span><span class="cx">     m_callCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
</span><span class="cx">     m_callCompilationInfo[callLinkInfoIndex].callLinkInfo = info;
</span><span class="cx"> 
</span><ins>+    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs) {
+        prepareForTailCallSlow();
+        m_callCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedTailCall();
+        return;
+    }
+
</ins><span class="cx">     m_callCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall();
</span><span class="cx"> 
</span><span class="cx">     addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
</span><span class="lines">@@ -208,8 +219,14 @@
</span><span class="cx">     linkSlowCase(iter);
</span><span class="cx"> 
</span><span class="cx">     move(TrustedImmPtr(m_callCompilationInfo[callLinkInfoIndex].callLinkInfo), regT2);
</span><ins>+
</ins><span class="cx">     m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm-&gt;getCTIStub(linkCallThunkGenerator).code());
</span><span class="cx"> 
</span><ins>+    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs) {
+        abortWithReason(JITDidReturnFromTailCall);
+        return;
+    }
+
</ins><span class="cx">     addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
</span><span class="cx">     checkStackPointerAlignment();
</span><span class="cx"> 
</span><span class="lines">@@ -223,6 +240,11 @@
</span><span class="cx">     compileOpCall(op_call, currentInstruction, m_callLinkInfoIndex++);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JIT::emit_op_tail_call(Instruction* currentInstruction)
+{
+    compileOpCall(op_tail_call, currentInstruction, m_callLinkInfoIndex++);
+}
+
</ins><span class="cx"> void JIT::emit_op_call_eval(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx">     compileOpCall(op_call_eval, currentInstruction, m_callLinkInfoIndex);
</span><span class="lines">@@ -232,7 +254,12 @@
</span><span class="cx"> {
</span><span class="cx">     compileOpCall(op_call_varargs, currentInstruction, m_callLinkInfoIndex++);
</span><span class="cx"> }
</span><del>-    
</del><ins>+
+void JIT::emit_op_tail_call_varargs(Instruction* currentInstruction)
+{
+    compileOpCall(op_tail_call_varargs, currentInstruction, m_callLinkInfoIndex++);
+}
+
</ins><span class="cx"> void JIT::emit_op_construct_varargs(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx">     compileOpCall(op_construct_varargs, currentInstruction, m_callLinkInfoIndex++);
</span><span class="lines">@@ -248,6 +275,11 @@
</span><span class="cx">     compileOpCallSlowCase(op_call, currentInstruction, iter, m_callLinkInfoIndex++);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JIT::emitSlow_op_tail_call(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
+{
+    compileOpCallSlowCase(op_tail_call, currentInstruction, iter, m_callLinkInfoIndex++);
+}
+
</ins><span class="cx"> void JIT::emitSlow_op_call_eval(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
</span><span class="cx"> {
</span><span class="cx">     compileOpCallSlowCase(op_call_eval, currentInstruction, iter, m_callLinkInfoIndex);
</span><span class="lines">@@ -257,6 +289,11 @@
</span><span class="cx"> {
</span><span class="cx">     compileOpCallSlowCase(op_call_varargs, currentInstruction, iter, m_callLinkInfoIndex++);
</span><span class="cx"> }
</span><ins>+
+void JIT::emitSlow_op_tail_call_varargs(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
+{
+    compileOpCallSlowCase(op_tail_call_varargs, currentInstruction, iter, m_callLinkInfoIndex++);
+}
</ins><span class="cx">     
</span><span class="cx"> void JIT::emitSlow_op_construct_varargs(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCall32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -69,6 +69,11 @@
</span><span class="cx">     compileOpCallSlowCase(op_call, currentInstruction, iter, m_callLinkInfoIndex++);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JIT::emitSlow_op_tail_call(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
+{
+    compileOpCallSlowCase(op_tail_call, currentInstruction, iter, m_callLinkInfoIndex++);
+}
+
</ins><span class="cx"> void JIT::emitSlow_op_call_eval(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
</span><span class="cx"> {
</span><span class="cx">     compileOpCallSlowCase(op_call_eval, currentInstruction, iter, m_callLinkInfoIndex);
</span><span class="lines">@@ -78,6 +83,11 @@
</span><span class="cx"> {
</span><span class="cx">     compileOpCallSlowCase(op_call_varargs, currentInstruction, iter, m_callLinkInfoIndex++);
</span><span class="cx"> }
</span><ins>+
+void JIT::emitSlow_op_tail_call_varargs(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
+{
+    compileOpCallSlowCase(op_tail_call_varargs, currentInstruction, iter, m_callLinkInfoIndex++);
+}
</ins><span class="cx">     
</span><span class="cx"> void JIT::emitSlow_op_construct_varargs(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
</span><span class="cx"> {
</span><span class="lines">@@ -94,6 +104,11 @@
</span><span class="cx">     compileOpCall(op_call, currentInstruction, m_callLinkInfoIndex++);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JIT::emit_op_tail_call(Instruction* currentInstruction)
+{
+    compileOpCall(op_tail_call, currentInstruction, m_callLinkInfoIndex++);
+}
+
</ins><span class="cx"> void JIT::emit_op_call_eval(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx">     compileOpCall(op_call_eval, currentInstruction, m_callLinkInfoIndex);
</span><span class="lines">@@ -103,6 +118,11 @@
</span><span class="cx"> {
</span><span class="cx">     compileOpCall(op_call_varargs, currentInstruction, m_callLinkInfoIndex++);
</span><span class="cx"> }
</span><ins>+
+void JIT::emit_op_tail_call_varargs(Instruction* currentInstruction)
+{
+    compileOpCall(op_tail_call_varargs, currentInstruction, m_callLinkInfoIndex++);
+}
</ins><span class="cx">     
</span><span class="cx"> void JIT::emit_op_construct_varargs(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="lines">@@ -210,7 +230,7 @@
</span><span class="cx">     CallLinkInfo* info;
</span><span class="cx">     if (opcodeID != op_call_eval)
</span><span class="cx">         info = m_codeBlock-&gt;addCallLinkInfo();
</span><del>-    if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs)
</del><ins>+    if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs || opcodeID == op_tail_call_varargs)
</ins><span class="cx">         compileSetupVarargsFrame(instruction, info);
</span><span class="cx">     else {
</span><span class="cx">         int argCount = instruction[3].u.operand;
</span><span class="lines">@@ -241,6 +261,9 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs)
+        emitRestoreCalleeSaves();
+
</ins><span class="cx">     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
</span><span class="cx"> 
</span><span class="cx">     DataLabelPtr addressOfLinkedFunctionCheck;
</span><span class="lines">@@ -255,6 +278,12 @@
</span><span class="cx">     m_callCompilationInfo[callLinkInfoIndex].callLinkInfo = info;
</span><span class="cx"> 
</span><span class="cx">     checkStackPointerAlignment();
</span><ins>+    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs) {
+        prepareForTailCallSlow();
+        m_callCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedTailCall();
+        return;
+    }
+
</ins><span class="cx">     m_callCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall();
</span><span class="cx"> 
</span><span class="cx">     addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
</span><span class="lines">@@ -275,8 +304,17 @@
</span><span class="cx">     linkSlowCase(iter);
</span><span class="cx"> 
</span><span class="cx">     move(TrustedImmPtr(m_callCompilationInfo[callLinkInfoIndex].callLinkInfo), regT2);
</span><ins>+
+    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs)
+        emitRestoreCalleeSaves();
+
</ins><span class="cx">     m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm-&gt;getCTIStub(linkCallThunkGenerator).code());
</span><span class="cx"> 
</span><ins>+    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs) {
+        abortWithReason(JITDidReturnFromTailCall);
+        return;
+    }
+
</ins><span class="cx">     addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
</span><span class="cx">     checkStackPointerAlignment();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITInlines.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITInlines.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/jit/JITInlines.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -125,6 +125,14 @@
</span><span class="cx">     return nakedCall;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE JIT::Call JIT::emitNakedTailCall(CodePtr function)
+{
+    ASSERT(m_bytecodeOffset != std::numeric_limits&lt;unsigned&gt;::max()); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
+    Call nakedCall = nearTailCall();
+    m_calls.append(CallRecord(nakedCall, m_bytecodeOffset, function.executableAddress()));
+    return nakedCall;
+}
+
</ins><span class="cx"> ALWAYS_INLINE void JIT::updateTopCallFrame()
</span><span class="cx"> {
</span><span class="cx">     ASSERT(static_cast&lt;int&gt;(m_bytecodeOffset) &gt;= 0);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -682,14 +682,14 @@
</span><span class="cx">     return JSValue::encode(result);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializationKind kind)
</del><ins>+static SlowPathReturnType handleHostCall(ExecState* execCallee, JSValue callee, CallLinkInfo* callLinkInfo)
</ins><span class="cx"> {
</span><span class="cx">     ExecState* exec = execCallee-&gt;callerFrame();
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx"> 
</span><span class="cx">     execCallee-&gt;setCodeBlock(0);
</span><span class="cx"> 
</span><del>-    if (kind == CodeForCall) {
</del><ins>+    if (callLinkInfo-&gt;specializationKind() == CodeForCall) {
</ins><span class="cx">         CallData callData;
</span><span class="cx">         CallType callType = getCallData(callee, callData);
</span><span class="cx">     
</span><span class="lines">@@ -699,18 +699,25 @@
</span><span class="cx">             NativeCallFrameTracer tracer(vm, execCallee);
</span><span class="cx">             execCallee-&gt;setCallee(asObject(callee));
</span><span class="cx">             vm-&gt;hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
</span><del>-            if (vm-&gt;exception())
-                return vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
</del><ins>+            if (vm-&gt;exception()) {
+                return encodeResult(
+                    vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
+                    reinterpret_cast&lt;void*&gt;(KeepTheFrame));
+            }
</ins><span class="cx"> 
</span><del>-            return reinterpret_cast&lt;void*&gt;(getHostCallReturnValue);
</del><ins>+            return encodeResult(
+                bitwise_cast&lt;void*&gt;(getHostCallReturnValue),
+                reinterpret_cast&lt;void*&gt;(callLinkInfo-&gt;callMode() == CallMode::Tail ? ReuseTheFrame : KeepTheFrame));
</ins><span class="cx">         }
</span><span class="cx">     
</span><span class="cx">         ASSERT(callType == CallTypeNone);
</span><span class="cx">         exec-&gt;vm().throwException(exec, createNotAFunctionError(exec, callee));
</span><del>-        return vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
</del><ins>+        return encodeResult(
+            vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
+            reinterpret_cast&lt;void*&gt;(KeepTheFrame));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ASSERT(kind == CodeForConstruct);
</del><ins>+    ASSERT(callLinkInfo-&gt;specializationKind() == CodeForConstruct);
</ins><span class="cx">     
</span><span class="cx">     ConstructData constructData;
</span><span class="cx">     ConstructType constructType = getConstructData(callee, constructData);
</span><span class="lines">@@ -721,18 +728,23 @@
</span><span class="cx">         NativeCallFrameTracer tracer(vm, execCallee);
</span><span class="cx">         execCallee-&gt;setCallee(asObject(callee));
</span><span class="cx">         vm-&gt;hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
</span><del>-        if (vm-&gt;exception())
-            return vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
</del><ins>+        if (vm-&gt;exception()) {
+            return encodeResult(
+                vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
+                reinterpret_cast&lt;void*&gt;(KeepTheFrame));
+        }
</ins><span class="cx"> 
</span><del>-        return reinterpret_cast&lt;void*&gt;(getHostCallReturnValue);
</del><ins>+        return encodeResult(bitwise_cast&lt;void*&gt;(getHostCallReturnValue), reinterpret_cast&lt;void*&gt;(KeepTheFrame));
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     ASSERT(constructType == ConstructTypeNone);
</span><span class="cx">     exec-&gt;vm().throwException(exec, createNotAConstructorError(exec, callee));
</span><del>-    return vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
</del><ins>+    return encodeResult(
+        vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
+        reinterpret_cast&lt;void*&gt;(KeepTheFrame));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-char* JIT_OPERATION operationLinkCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
</del><ins>+SlowPathReturnType JIT_OPERATION operationLinkCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
</ins><span class="cx"> {
</span><span class="cx">     ExecState* exec = execCallee-&gt;callerFrame();
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="lines">@@ -745,7 +757,7 @@
</span><span class="cx">         // FIXME: We should cache these kinds of calls. They can be common and currently they are
</span><span class="cx">         // expensive.
</span><span class="cx">         // https://bugs.webkit.org/show_bug.cgi?id=144458
</span><del>-        return reinterpret_cast&lt;char*&gt;(handleHostCall(execCallee, calleeAsValue, kind));
</del><ins>+        return handleHostCall(execCallee, calleeAsValue, callLinkInfo);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     JSFunction* callee = jsCast&lt;JSFunction*&gt;(calleeAsFunctionCell);
</span><span class="lines">@@ -774,17 +786,21 @@
</span><span class="cx"> 
</span><span class="cx">         if (!isCall(kind) &amp;&amp; functionExecutable-&gt;constructAbility() == ConstructAbility::CannotConstruct) {
</span><span class="cx">             exec-&gt;vm().throwException(exec, createNotAConstructorError(exec, callee));
</span><del>-            return reinterpret_cast&lt;char*&gt;(vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
</del><ins>+            return encodeResult(
+                vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
+                reinterpret_cast&lt;void*&gt;(KeepTheFrame));
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         JSObject* error = functionExecutable-&gt;prepareForExecution(execCallee, callee, scope, kind);
</span><span class="cx">         if (error) {
</span><span class="cx">             exec-&gt;vm().throwException(exec, error);
</span><del>-            return reinterpret_cast&lt;char*&gt;(vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
</del><ins>+            return encodeResult(
+                vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
+                reinterpret_cast&lt;void*&gt;(KeepTheFrame));
</ins><span class="cx">         }
</span><span class="cx">         codeBlock = functionExecutable-&gt;codeBlockFor(kind);
</span><span class="cx">         ArityCheckMode arity;
</span><del>-        if (execCallee-&gt;argumentCountIncludingThis() &lt; static_cast&lt;size_t&gt;(codeBlock-&gt;numParameters()) || callLinkInfo-&gt;callType() == CallLinkInfo::CallVarargs || callLinkInfo-&gt;callType() == CallLinkInfo::ConstructVarargs)
</del><ins>+        if (execCallee-&gt;argumentCountIncludingThis() &lt; static_cast&lt;size_t&gt;(codeBlock-&gt;numParameters()) || callLinkInfo-&gt;isVarargs())
</ins><span class="cx">             arity = MustCheckArity;
</span><span class="cx">         else
</span><span class="cx">             arity = ArityCheckNotRequired;
</span><span class="lines">@@ -795,10 +811,10 @@
</span><span class="cx">     else
</span><span class="cx">         linkFor(execCallee, *callLinkInfo, codeBlock, callee, codePtr);
</span><span class="cx">     
</span><del>-    return reinterpret_cast&lt;char*&gt;(codePtr.executableAddress());
</del><ins>+    return encodeResult(codePtr.executableAddress(), reinterpret_cast&lt;void*&gt;(callLinkInfo-&gt;callMode() == CallMode::Tail ? ReuseTheFrame : KeepTheFrame));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline char* virtualForWithFunction(
</del><ins>+inline SlowPathReturnType virtualForWithFunction(
</ins><span class="cx">     ExecState* execCallee, CallLinkInfo* callLinkInfo, JSCell*&amp; calleeAsFunctionCell)
</span><span class="cx"> {
</span><span class="cx">     ExecState* exec = execCallee-&gt;callerFrame();
</span><span class="lines">@@ -809,7 +825,7 @@
</span><span class="cx">     JSValue calleeAsValue = execCallee-&gt;calleeAsValue();
</span><span class="cx">     calleeAsFunctionCell = getJSFunction(calleeAsValue);
</span><span class="cx">     if (UNLIKELY(!calleeAsFunctionCell))
</span><del>-        return reinterpret_cast&lt;char*&gt;(handleHostCall(execCallee, calleeAsValue, kind));
</del><ins>+        return handleHostCall(execCallee, calleeAsValue, callLinkInfo);
</ins><span class="cx">     
</span><span class="cx">     JSFunction* function = jsCast&lt;JSFunction*&gt;(calleeAsFunctionCell);
</span><span class="cx">     JSScope* scope = function-&gt;scopeUnchecked();
</span><span class="lines">@@ -824,13 +840,17 @@
</span><span class="cx"> 
</span><span class="cx">             if (!isCall(kind) &amp;&amp; functionExecutable-&gt;constructAbility() == ConstructAbility::CannotConstruct) {
</span><span class="cx">                 exec-&gt;vm().throwException(exec, createNotAConstructorError(exec, function));
</span><del>-                return reinterpret_cast&lt;char*&gt;(vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
</del><ins>+                return encodeResult(
+                    vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
+                    reinterpret_cast&lt;void*&gt;(KeepTheFrame));
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             JSObject* error = functionExecutable-&gt;prepareForExecution(execCallee, function, scope, kind);
</span><span class="cx">             if (error) {
</span><span class="cx">                 exec-&gt;vm().throwException(exec, error);
</span><del>-                return reinterpret_cast&lt;char*&gt;(vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
</del><ins>+                return encodeResult(
+                    vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
+                    reinterpret_cast&lt;void*&gt;(KeepTheFrame));
</ins><span class="cx">             }
</span><span class="cx">         } else {
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="lines">@@ -844,22 +864,23 @@
</span><span class="cx"> #endif
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-    return reinterpret_cast&lt;char*&gt;(executable-&gt;entrypointFor(
-        *vm, kind, MustCheckArity, callLinkInfo-&gt;registerPreservationMode()).executableAddress());
</del><ins>+    return encodeResult(executable-&gt;entrypointFor(
+        *vm, kind, MustCheckArity, callLinkInfo-&gt;registerPreservationMode()).executableAddress(),
+        reinterpret_cast&lt;void*&gt;(callLinkInfo-&gt;callMode() == CallMode::Tail ? ReuseTheFrame : KeepTheFrame));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-char* JIT_OPERATION operationLinkPolymorphicCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
</del><ins>+SlowPathReturnType JIT_OPERATION operationLinkPolymorphicCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(callLinkInfo-&gt;specializationKind() == CodeForCall);
</span><span class="cx">     JSCell* calleeAsFunctionCell;
</span><del>-    char* result = virtualForWithFunction(execCallee, callLinkInfo, calleeAsFunctionCell);
</del><ins>+    SlowPathReturnType result = virtualForWithFunction(execCallee, callLinkInfo, calleeAsFunctionCell);
</ins><span class="cx"> 
</span><span class="cx">     linkPolymorphicCall(execCallee, *callLinkInfo, CallVariant(calleeAsFunctionCell));
</span><span class="cx">     
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-char* JIT_OPERATION operationVirtualCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
</del><ins>+SlowPathReturnType JIT_OPERATION operationVirtualCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
</ins><span class="cx"> {
</span><span class="cx">     JSCell* calleeAsFunctionCellIgnored;
</span><span class="cx">     return virtualForWithFunction(execCallee, callLinkInfo, calleeAsFunctionCellIgnored);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -237,6 +237,7 @@
</span><span class="cx"> typedef char* JIT_OPERATION (*P_JITOperation_EStSS)(ExecState*, Structure*, size_t, size_t);
</span><span class="cx"> typedef char* JIT_OPERATION (*P_JITOperation_EStZ)(ExecState*, Structure*, int32_t);
</span><span class="cx"> typedef char* JIT_OPERATION (*P_JITOperation_EZZ)(ExecState*, int32_t, int32_t);
</span><ins>+typedef SlowPathReturnType JIT_OPERATION (*Sprt_JITOperation_ECli)(ExecState*, CallLinkInfo*);
</ins><span class="cx"> typedef StringImpl* JIT_OPERATION (*T_JITOperation_EJss)(ExecState*, JSString*);
</span><span class="cx"> typedef JSString* JIT_OPERATION (*Jss_JITOperation_EZ)(ExecState*, int32_t);
</span><span class="cx"> 
</span><span class="lines">@@ -278,9 +279,9 @@
</span><span class="cx"> void JIT_OPERATION operationPutByValGeneric(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*) WTF_INTERNAL;
</span><span class="cx"> void JIT_OPERATION operationDirectPutByValGeneric(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationCallEval(ExecState*, ExecState*) WTF_INTERNAL;
</span><del>-char* JIT_OPERATION operationLinkCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
-char* JIT_OPERATION operationLinkPolymorphicCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
-char* JIT_OPERATION operationVirtualCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
</del><ins>+SlowPathReturnType JIT_OPERATION operationLinkCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
+SlowPathReturnType JIT_OPERATION operationLinkPolymorphicCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
+SlowPathReturnType JIT_OPERATION operationVirtualCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
</ins><span class="cx"> 
</span><span class="cx"> size_t JIT_OPERATION operationCompareLess(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
</span><span class="cx"> size_t JIT_OPERATION operationCompareLessEq(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.cpp (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.cpp        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/jit/Repatch.cpp        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -609,7 +609,7 @@
</span><span class="cx"> {
</span><span class="cx">     CodeBlock* callerCodeBlock = exec-&gt;callerFrame()-&gt;codeBlock();
</span><span class="cx">     VM* vm = callerCodeBlock-&gt;vm();
</span><del>-    
</del><ins>+
</ins><span class="cx">     if (shouldShowDisassemblyFor(callerCodeBlock))
</span><span class="cx">         dataLog(&quot;Linking virtual call at &quot;, *callerCodeBlock, &quot; &quot;, exec-&gt;callerFrame()-&gt;codeOrigin(), &quot;\n&quot;);
</span><span class="cx">     
</span><span class="lines">@@ -680,7 +680,7 @@
</span><span class="cx">                 codeBlock = jsCast&lt;FunctionExecutable*&gt;(executable)-&gt;codeBlockForCall();
</span><span class="cx">             // If we cannot handle a callee, assume that it's better for this whole thing to be a
</span><span class="cx">             // virtual call.
</span><del>-            if (exec-&gt;argumentCountIncludingThis() &lt; static_cast&lt;size_t&gt;(codeBlock-&gt;numParameters()) || callLinkInfo.callType() == CallLinkInfo::CallVarargs || callLinkInfo.callType() == CallLinkInfo::ConstructVarargs) {
</del><ins>+            if (exec-&gt;argumentCountIncludingThis() &lt; static_cast&lt;size_t&gt;(codeBlock-&gt;numParameters()) || callLinkInfo.isVarargs()) {
</ins><span class="cx">                 linkVirtualFor(exec, callLinkInfo);
</span><span class="cx">                 return;
</span><span class="cx">             }
</span><span class="lines">@@ -803,7 +803,11 @@
</span><span class="cx">                 CCallHelpers::TrustedImm32(1),
</span><span class="cx">                 CCallHelpers::Address(fastCountsBaseGPR, caseIndex * sizeof(uint32_t)));
</span><span class="cx">         }
</span><del>-        calls[caseIndex].call = stubJit.nearCall();
</del><ins>+        if (callLinkInfo.isTailCall()) {
+            stubJit.prepareForTailCallSlow();
+            calls[caseIndex].call = stubJit.nearTailCall();
+        } else
+            calls[caseIndex].call = stubJit.nearCall();
</ins><span class="cx">         calls[caseIndex].codePtr = codePtr;
</span><span class="cx">         done.append(stubJit.jump());
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitThunkGeneratorscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -79,10 +79,26 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void slowPathFor(
</span><del>-    CCallHelpers&amp; jit, VM* vm, P_JITOperation_ECli slowPathFunction)
</del><ins>+    CCallHelpers&amp; jit, VM* vm, Sprt_JITOperation_ECli slowPathFunction)
</ins><span class="cx"> {
</span><span class="cx">     jit.emitFunctionPrologue();
</span><span class="cx">     jit.storePtr(GPRInfo::callFrameRegister, &amp;vm-&gt;topCallFrame);
</span><ins>+#if OS(WINDOWS) &amp;&amp; CPU(X86_64)
+    // Windows X86_64 needs some space pointed to by arg0 for return types larger than 64 bits.
+    // Other argument values are shift by 1. Use space on the stack for our two return values.
+    // Moving the stack down maxFrameExtentForSlowPathCall bytes gives us room for our 3 arguments
+    // and space for the 16 byte return area.
+    jit.addPtr(CCallHelpers::TrustedImm32(-maxFrameExtentForSlowPathCall), CCallHelpers::stackPointerRegister);
+    jit.move(GPRInfo::regT2, GPRInfo::argumentGPR2);
+    jit.addPtr(CCallHelpers::TrustedImm32(32), CCallHelpers::stackPointerRegister, GPRInfo::argumentGPR0);
+    jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
+    jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast&lt;void*&gt;(slowPathFunction)), GPRInfo::nonArgGPR0);
+    emitPointerValidation(jit, GPRInfo::nonArgGPR0);
+    jit.call(GPRInfo::nonArgGPR0);
+    jit.loadPtr(CCallHelpers::Address(GPRInfo::returnValueGPR, 8), GPRInfo::returnValueGPR2);
+    jit.loadPtr(CCallHelpers::Address(GPRInfo::returnValueGPR), GPRInfo::returnValueGPR);
+    jit.addPtr(CCallHelpers::TrustedImm32(maxFrameExtentForSlowPathCall), CCallHelpers::stackPointerRegister);
+#else
</ins><span class="cx">     if (maxFrameExtentForSlowPathCall)
</span><span class="cx">         jit.addPtr(CCallHelpers::TrustedImm32(-maxFrameExtentForSlowPathCall), CCallHelpers::stackPointerRegister);
</span><span class="cx">     jit.setupArgumentsWithExecState(GPRInfo::regT2);
</span><span class="lines">@@ -91,13 +107,24 @@
</span><span class="cx">     jit.call(GPRInfo::nonArgGPR0);
</span><span class="cx">     if (maxFrameExtentForSlowPathCall)
</span><span class="cx">         jit.addPtr(CCallHelpers::TrustedImm32(maxFrameExtentForSlowPathCall), CCallHelpers::stackPointerRegister);
</span><del>-    
</del><ins>+#endif
+
</ins><span class="cx">     // This slow call will return the address of one of the following:
</span><span class="cx">     // 1) Exception throwing thunk.
</span><span class="cx">     // 2) Host call return value returner thingy.
</span><span class="cx">     // 3) The function to call.
</span><ins>+    // The second return value GPR will hold a non-zero value for tail calls.
+
</ins><span class="cx">     emitPointerValidation(jit, GPRInfo::returnValueGPR);
</span><span class="cx">     jit.emitFunctionEpilogue();
</span><ins>+
+    RELEASE_ASSERT(reinterpret_cast&lt;void*&gt;(KeepTheFrame) == reinterpret_cast&lt;void*&gt;(0));
+    CCallHelpers::Jump doNotTrash = jit.branchTestPtr(CCallHelpers::Zero, GPRInfo::returnValueGPR2);
+
+    jit.preserveReturnAddressAfterCall(GPRInfo::nonPreservedNonReturnGPR);
+    jit.prepareForTailCallSlow(GPRInfo::returnValueGPR);
+
+    doNotTrash.link(&amp;jit);
</ins><span class="cx">     jit.jump(GPRInfo::returnValueGPR);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -108,7 +135,6 @@
</span><span class="cx">     // to perform linking and lazy compilation if necessary. We expect the callee
</span><span class="cx">     // to be in regT0/regT1 (payload/tag), the CallFrame to have already
</span><span class="cx">     // been adjusted, and all other registers to be available for use.
</span><del>-    
</del><span class="cx">     CCallHelpers jit(vm);
</span><span class="cx">     
</span><span class="cx">     slowPathFor(jit, vm, operationLinkCall);
</span><span class="lines">@@ -185,6 +211,10 @@
</span><span class="cx">     
</span><span class="cx">     // Make a tail call. This will return back to JIT code.
</span><span class="cx">     emitPointerValidation(jit, GPRInfo::regT4);
</span><ins>+    if (callLinkInfo.isTailCall()) {
+        jit.preserveReturnAddressAfterCall(GPRInfo::regT0);
+        jit.prepareForTailCallSlow(GPRInfo::regT4);
+    }
</ins><span class="cx">     jit.jump(GPRInfo::regT4);
</span><span class="cx"> 
</span><span class="cx">     slowCase.link(&amp;jit);
</span><span class="lines">@@ -196,9 +226,8 @@
</span><span class="cx">     LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
</span><span class="cx">     return FINALIZE_CODE(
</span><span class="cx">         patchBuffer,
</span><del>-        (&quot;Virtual %s%s slow path thunk&quot;,
-        callLinkInfo.specializationKind() == CodeForCall ? &quot;call&quot; : &quot;construct&quot;,
-        callLinkInfo.registerPreservationMode() == MustPreserveRegisters ? &quot; that preserves registers&quot; : &quot;&quot;));
</del><ins>+        (&quot;Virtual %s slow path thunk&quot;,
+        callLinkInfo.callMode() == CallMode::Regular ? &quot;call&quot; : callLinkInfo.callMode() == CallMode::Tail ? &quot;tail call&quot; : &quot;construct&quot;));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> enum ThunkEntryType { EnterViaCall, EnterViaJump };
</span><span class="lines">@@ -367,7 +396,7 @@
</span><span class="cx"> {
</span><span class="cx">     JSInterfaceJIT jit(vm);
</span><span class="cx"> 
</span><del>-    // We enter with fixup count, in aligned stack units, in argumentGPR0 and the return thunk in argumentGPR1
</del><ins>+    // We enter with fixup count in argumentGPR0
</ins><span class="cx">     // We have the guarantee that a0, a1, a2, t3, t4 and t5 (or t0 for Windows) are all distinct :-)
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx"> #if OS(WINDOWS)
</span><span class="lines">@@ -378,12 +407,25 @@
</span><span class="cx"> #  if CPU(X86_64)
</span><span class="cx">     jit.pop(JSInterfaceJIT::regT4);
</span><span class="cx"> #  endif
</span><del>-    jit.lshift32(JSInterfaceJIT::TrustedImm32(logStackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
-    jit.neg64(JSInterfaceJIT::argumentGPR0);
</del><span class="cx">     jit.move(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::regT3);
</span><span class="cx">     jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * sizeof(Register)), JSInterfaceJIT::argumentGPR2);
</span><span class="cx">     jit.add32(JSInterfaceJIT::TrustedImm32(JSStack::CallFrameHeaderSize), JSInterfaceJIT::argumentGPR2);
</span><span class="cx"> 
</span><ins>+    // Check to see if we have extra slots we can use
+    jit.move(JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::argumentGPR1);
+    jit.and32(JSInterfaceJIT::TrustedImm32(stackAlignmentRegisters() - 1), JSInterfaceJIT::argumentGPR1);
+    JSInterfaceJIT::Jump noExtraSlot = jit.branchTest32(MacroAssembler::Zero, JSInterfaceJIT::argumentGPR1);
+    jit.move(JSInterfaceJIT::TrustedImm64(ValueUndefined), extraTemp);
+    JSInterfaceJIT::Label fillExtraSlots(jit.label());
+    jit.store64(extraTemp, MacroAssembler::BaseIndex(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::argumentGPR2, JSInterfaceJIT::TimesEight));
+    jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2);
+    jit.branchSub32(JSInterfaceJIT::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR1).linkTo(fillExtraSlots, &amp;jit);
+    jit.and32(JSInterfaceJIT::TrustedImm32(-stackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
+    JSInterfaceJIT::Jump done = jit.branchTest32(MacroAssembler::Zero, JSInterfaceJIT::argumentGPR0);
+    noExtraSlot.link(&amp;jit);
+
+    jit.neg64(JSInterfaceJIT::argumentGPR0);
+
</ins><span class="cx">     // Move current frame down argumentGPR0 number of slots
</span><span class="cx">     JSInterfaceJIT::Label copyLoop(jit.label());
</span><span class="cx">     jit.load64(JSInterfaceJIT::regT3, extraTemp);
</span><span class="lines">@@ -391,10 +433,9 @@
</span><span class="cx">     jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3);
</span><span class="cx">     jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2).linkTo(copyLoop, &amp;jit);
</span><span class="cx"> 
</span><del>-    // Fill in argumentGPR0 - 1 missing arg slots with undefined
</del><ins>+    // Fill in argumentGPR0 missing arg slots with undefined
</ins><span class="cx">     jit.move(JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::argumentGPR2);
</span><span class="cx">     jit.move(JSInterfaceJIT::TrustedImm64(ValueUndefined), extraTemp);
</span><del>-    jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2);
</del><span class="cx">     JSInterfaceJIT::Label fillUndefinedLoop(jit.label());
</span><span class="cx">     jit.store64(extraTemp, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
</span><span class="cx">     jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3);
</span><span class="lines">@@ -406,6 +447,8 @@
</span><span class="cx">     jit.addPtr(extraTemp, JSInterfaceJIT::callFrameRegister);
</span><span class="cx">     jit.addPtr(extraTemp, JSInterfaceJIT::stackPointerRegister);
</span><span class="cx"> 
</span><ins>+    done.link(&amp;jit);
+
</ins><span class="cx"> #  if CPU(X86_64)
</span><span class="cx">     jit.push(JSInterfaceJIT::regT4);
</span><span class="cx"> #  endif
</span><span class="lines">@@ -414,29 +457,43 @@
</span><span class="cx"> #  if CPU(X86)
</span><span class="cx">     jit.pop(JSInterfaceJIT::regT4);
</span><span class="cx"> #  endif
</span><del>-    jit.lshift32(JSInterfaceJIT::TrustedImm32(logStackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
-    jit.neg32(JSInterfaceJIT::argumentGPR0);
</del><span class="cx">     jit.move(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::regT3);
</span><span class="cx">     jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * sizeof(Register)), JSInterfaceJIT::argumentGPR2);
</span><span class="cx">     jit.add32(JSInterfaceJIT::TrustedImm32(JSStack::CallFrameHeaderSize), JSInterfaceJIT::argumentGPR2);
</span><span class="cx"> 
</span><ins>+    // Check to see if we have extra slots we can use
+    jit.move(JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::argumentGPR1);
+    jit.and32(JSInterfaceJIT::TrustedImm32(stackAlignmentRegisters() - 1), JSInterfaceJIT::argumentGPR1);
+    JSInterfaceJIT::Jump noExtraSlot = jit.branchTest32(MacroAssembler::Zero, JSInterfaceJIT::argumentGPR1);
+    JSInterfaceJIT::Label fillExtraSlots(jit.label());
+    jit.move(JSInterfaceJIT::TrustedImm32(0), JSInterfaceJIT::regT5);
+    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::argumentGPR2, JSInterfaceJIT::TimesEight, PayloadOffset));
+    jit.move(JSInterfaceJIT::TrustedImm32(JSValue::UndefinedTag), JSInterfaceJIT::regT5);
+    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::argumentGPR2, JSInterfaceJIT::TimesEight, TagOffset));
+    jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2);
+    jit.branchSub32(JSInterfaceJIT::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR1).linkTo(fillExtraSlots, &amp;jit);
+    jit.and32(JSInterfaceJIT::TrustedImm32(-stackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
+    JSInterfaceJIT::Jump done = jit.branchTest32(MacroAssembler::Zero, JSInterfaceJIT::argumentGPR0);
+    noExtraSlot.link(&amp;jit);
+
+    jit.neg32(JSInterfaceJIT::argumentGPR0);
+
</ins><span class="cx">     // Move current frame down argumentGPR0 number of slots
</span><span class="cx">     JSInterfaceJIT::Label copyLoop(jit.label());
</span><del>-    jit.load32(JSInterfaceJIT::regT3, JSInterfaceJIT::regT5);
-    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
-    jit.load32(MacroAssembler::Address(JSInterfaceJIT::regT3, 4), JSInterfaceJIT::regT5);
-    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, 4));
</del><ins>+    jit.load32(MacroAssembler::Address(JSInterfaceJIT::regT3, PayloadOffset), JSInterfaceJIT::regT5);
+    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, PayloadOffset));
+    jit.load32(MacroAssembler::Address(JSInterfaceJIT::regT3, TagOffset), JSInterfaceJIT::regT5);
+    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, TagOffset));
</ins><span class="cx">     jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3);
</span><span class="cx">     jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2).linkTo(copyLoop, &amp;jit);
</span><span class="cx"> 
</span><del>-    // Fill in argumentGPR0 - 1 missing arg slots with undefined
</del><ins>+    // Fill in argumentGPR0 missing arg slots with undefined
</ins><span class="cx">     jit.move(JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::argumentGPR2);
</span><del>-    jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2);
</del><span class="cx">     JSInterfaceJIT::Label fillUndefinedLoop(jit.label());
</span><span class="cx">     jit.move(JSInterfaceJIT::TrustedImm32(0), JSInterfaceJIT::regT5);
</span><del>-    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
</del><ins>+    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, PayloadOffset));
</ins><span class="cx">     jit.move(JSInterfaceJIT::TrustedImm32(JSValue::UndefinedTag), JSInterfaceJIT::regT5);
</span><del>-    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, 4));
</del><ins>+    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, TagOffset));
</ins><span class="cx"> 
</span><span class="cx">     jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3);
</span><span class="cx">     jit.branchAdd32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2).linkTo(fillUndefinedLoop, &amp;jit);
</span><span class="lines">@@ -447,6 +504,8 @@
</span><span class="cx">     jit.addPtr(JSInterfaceJIT::regT5, JSInterfaceJIT::callFrameRegister);
</span><span class="cx">     jit.addPtr(JSInterfaceJIT::regT5, JSInterfaceJIT::stackPointerRegister);
</span><span class="cx"> 
</span><ins>+    done.link(&amp;jit);
+
</ins><span class="cx"> #  if CPU(X86)
</span><span class="cx">     jit.push(JSInterfaceJIT::regT4);
</span><span class="cx"> #  endif
</span><span class="lines">@@ -457,6 +516,16 @@
</span><span class="cx">     return FINALIZE_CODE(patchBuffer, (&quot;fixup arity&quot;));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+MacroAssemblerCodeRef unreachableGenerator(VM* vm)
+{
+    JSInterfaceJIT jit(vm);
+
+    jit.breakpoint();
+
+    LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
+    return FINALIZE_CODE(patchBuffer, (&quot;unreachable thunk&quot;));
+}
+
</ins><span class="cx"> MacroAssemblerCodeRef baselineGetterReturnThunkGenerator(VM* vm)
</span><span class="cx"> {
</span><span class="cx">     JSInterfaceJIT jit(vm);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitThunkGeneratorsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ThunkGenerators.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -34,9 +34,11 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> class CallLinkInfo;
</span><ins>+class CCallHelpers;
</ins><span class="cx"> 
</span><span class="cx"> MacroAssemblerCodeRef throwExceptionFromCallSlowPathGenerator(VM*);
</span><span class="cx"> 
</span><ins>+MacroAssemblerCodeRef linkCallThunk(VM*, CallLinkInfo&amp;, CodeSpecializationKind, RegisterPreservationMode);
</ins><span class="cx"> MacroAssemblerCodeRef linkCallThunkGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef linkPolymorphicCallThunkGenerator(VM*);
</span><span class="cx"> 
</span><span class="lines">@@ -46,6 +48,7 @@
</span><span class="cx"> MacroAssemblerCodeRef nativeConstructGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef nativeTailCallGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef arityFixupGenerator(VM*);
</span><ins>+MacroAssemblerCodeRef unreachableGenerator(VM*);
</ins><span class="cx"> 
</span><span class="cx"> MacroAssemblerCodeRef baselineGetterReturnThunkGenerator(VM* vm);
</span><span class="cx"> MacroAssemblerCodeRef baselineSetterReturnThunkGenerator(VM* vm);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -167,6 +167,7 @@
</span><span class="cx"> const DirectArguments_storage = (sizeof DirectArguments + SlotSize - 1) &amp; ~(SlotSize - 1)
</span><span class="cx"> 
</span><span class="cx"> const StackAlignment = 16
</span><ins>+const StackAlignmentSlots = 2
</ins><span class="cx"> const StackAlignmentMask = StackAlignment - 1
</span><span class="cx"> 
</span><span class="cx"> const CallerFrameAndPCSize = 2 * PtrSize
</span><span class="lines">@@ -697,36 +698,79 @@
</span><span class="cx">     end
</span><span class="cx"> end
</span><span class="cx"> 
</span><del>-macro callTargetFunction(callLinkInfo, calleeFramePtr)
-    move calleeFramePtr, sp
</del><ins>+macro callTargetFunction(callee)
</ins><span class="cx">     if C_LOOP
</span><del>-        cloopCallJSFunction LLIntCallLinkInfo::machineCodeTarget[callLinkInfo]
</del><ins>+        cloopCallJSFunction callee
</ins><span class="cx">     else
</span><del>-        call LLIntCallLinkInfo::machineCodeTarget[callLinkInfo]
</del><ins>+        call callee
</ins><span class="cx">     end
</span><span class="cx">     restoreStackPointerAfterCall()
</span><span class="cx">     dispatchAfterCall()
</span><span class="cx"> end
</span><span class="cx"> 
</span><del>-macro slowPathForCall(slowPath)
</del><ins>+macro prepareForRegularCall(callee, temp1, temp2, temp3)
+    addp CallerFrameAndPCSize, sp
+end
+
+# sp points to the new frame
+macro prepareForTailCall(callee, temp1, temp2, temp3)
+    restoreCalleeSavesUsedByLLInt()
+
+    loadi PayloadOffset + ArgumentCount[cfr], temp2
+    loadp CodeBlock[cfr], temp1
+    loadp CodeBlock::m_numParameters[temp1], temp1
+    bilteq temp1, temp2, .noArityFixup
+    move temp1, temp2
+
+.noArityFixup:
+    # We assume &lt; 2^28 arguments
+    muli SlotSize, temp2
+    addi StackAlignment - 1 + CallFrameHeaderSize, temp2
+    andi ~StackAlignmentMask, temp2
+
+    move cfr, temp1
+    addp temp2, temp1
+
+    loadi PayloadOffset + ArgumentCount[sp], temp2
+    # We assume &lt; 2^28 arguments
+    muli SlotSize, temp2
+    addi StackAlignment - 1 + CallFrameHeaderSize, temp2
+    andi ~StackAlignmentMask, temp2
+
+    if ARM or SH4 or ARM64 or C_LOOP or MIPS
+        addp 2 * PtrSize, sp
+        subi 2 * PtrSize, temp2
+        loadp PtrSize[cfr], lr
+    else
+        addp PtrSize, sp
+        subi PtrSize, temp2
+        loadp PtrSize[cfr], temp3
+        storep temp3, [sp]
+    end
+
+    subp temp2, temp1
+    loadp [cfr], cfr
+
+.copyLoop:
+    subi PtrSize, temp2
+    loadp [sp, temp2, 1], temp3
+    storep temp3, [temp1, temp2, 1]
+    btinz temp2, .copyLoop
+
+    move temp1, sp
+    jmp callee
+end
+
+macro slowPathForCall(slowPath, prepareCall)
</ins><span class="cx">     callCallSlowPath(
</span><span class="cx">         slowPath,
</span><del>-        macro (callee, calleeFrame)
-            btpz calleeFrame, .dontUpdateSP
-            if ARMv7
-                addp CallerFrameAndPCSize, calleeFrame, calleeFrame
-                move calleeFrame, sp
-            else
-                addp CallerFrameAndPCSize, calleeFrame, sp
-            end
</del><ins>+        # Those are r0 and r1
+        macro (callee, calleeFramePtr)
+            btpz calleeFramePtr, .dontUpdateSP
+            move calleeFramePtr, sp
+            prepareCall(callee, t2, t3, t4)
</ins><span class="cx">         .dontUpdateSP:
</span><del>-            if C_LOOP
-                cloopCallJSFunction callee
-            else
-                call callee
-            end
-            restoreStackPointerAfterCall()
-            dispatchAfterCall()
</del><ins>+            callTargetFunction(callee)
</ins><span class="cx">         end)
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="lines">@@ -1415,16 +1459,19 @@
</span><span class="cx"> _llint_op_call:
</span><span class="cx">     traceExecution()
</span><span class="cx">     arrayProfileForCall()
</span><del>-    doCall(_llint_slow_path_call)
</del><ins>+    doCall(_llint_slow_path_call, prepareForRegularCall)
</ins><span class="cx"> 
</span><ins>+_llint_op_tail_call:
+    traceExecution()
+    arrayProfileForCall()
+    checkSwitchToJITForEpilogue()
+    doCall(_llint_slow_path_call, prepareForTailCall)
</ins><span class="cx"> 
</span><span class="cx"> _llint_op_construct:
</span><span class="cx">     traceExecution()
</span><del>-    doCall(_llint_slow_path_construct)
</del><ins>+    doCall(_llint_slow_path_construct, prepareForRegularCall)
</ins><span class="cx"> 
</span><del>-
-_llint_op_call_varargs:
-    traceExecution()
</del><ins>+macro doCallVarargs(slowPath, prepareCall)
</ins><span class="cx">     callSlowPath(_llint_slow_path_size_frame_for_varargs)
</span><span class="cx">     branchIfException(_llint_throw_from_slow_path_trampoline)
</span><span class="cx">     # calleeFrame in r1
</span><span class="lines">@@ -1439,25 +1486,23 @@
</span><span class="cx">             subp r1, CallerFrameAndPCSize, sp
</span><span class="cx">         end
</span><span class="cx">     end
</span><del>-    slowPathForCall(_llint_slow_path_call_varargs)
</del><ins>+    slowPathForCall(slowPath, prepareCall)
+end
</ins><span class="cx"> 
</span><ins>+_llint_op_call_varargs:
+    traceExecution()
+    doCallVarargs(_llint_slow_path_call_varargs, prepareForRegularCall)
+
+_llint_op_tail_call_varargs:
+    traceExecution()
+    checkSwitchToJITForEpilogue()
+    # We lie and perform the tail call instead of preparing it since we can't
+    # prepare the frame for a call opcode
+    doCallVarargs(_llint_slow_path_call_varargs, prepareForTailCall)
+
</ins><span class="cx"> _llint_op_construct_varargs:
</span><span class="cx">     traceExecution()
</span><del>-    callSlowPath(_llint_slow_path_size_frame_for_varargs)
-    branchIfException(_llint_throw_from_slow_path_trampoline)
-    # calleeFrame in r1
-    if JSVALUE64
-        move r1, sp
-    else
-        # The calleeFrame is not stack aligned, move down by CallerFrameAndPCSize to align
-        if ARMv7
-            subp r1, CallerFrameAndPCSize, t2
-            move t2, sp
-        else
-            subp r1, CallerFrameAndPCSize, sp
-        end
-    end
-    slowPathForCall(_llint_slow_path_construct_varargs)
</del><ins>+    doCallVarargs(_llint_slow_path_construct_varargs, prepareForRegularCall)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> _llint_op_call_eval:
</span><span class="lines">@@ -1496,7 +1541,7 @@
</span><span class="cx">     # and a PC to call, and that PC may be a dummy thunk that just
</span><span class="cx">     # returns the JS value that the eval returned.
</span><span class="cx">     
</span><del>-    slowPathForCall(_llint_slow_path_call_eval)
</del><ins>+    slowPathForCall(_llint_slow_path_call_eval, prepareForRegularCall)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> _llint_generic_return_point:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -602,13 +602,27 @@
</span><span class="cx"> .proceedInline:
</span><span class="cx">     loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[r1], t1
</span><span class="cx">     btiz t1, .continue
</span><ins>+    loadi PayloadOffset + ArgumentCount[cfr], t2
+    addi CallFrameHeaderSlots, t2
</ins><span class="cx"> 
</span><del>-    // Move frame up &quot;t1 * 2&quot; slots
-    lshiftp 1, t1
</del><ins>+    // Check if there are some unaligned slots we can use
+    move t1, t3
+    andi StackAlignmentSlots - 1, t3
+    btiz t3, .noExtraSlot
+.fillExtraSlots:
+    move 0, t0
+    storei t0, PayloadOffset[cfr, t2, 8]
+    move UndefinedTag, t0
+    storei t0, TagOffset[cfr, t2, 8]
+    addi 1, t2
+    bsubinz 1, t3, .fillExtraSlots
+    andi ~(StackAlignmentSlots - 1), t1
+    btiz t1, .continue
+
+.noExtraSlot:
+    // Move frame up t1 slots
</ins><span class="cx">     negi t1
</span><span class="cx">     move cfr, t3
</span><del>-    loadi PayloadOffset + ArgumentCount[cfr], t2
-    addi CallFrameHeaderSlots, t2
</del><span class="cx"> .copyLoop:
</span><span class="cx">     loadi PayloadOffset[t3], t0
</span><span class="cx">     storei t0, PayloadOffset[t3, t1, 8]
</span><span class="lines">@@ -1764,7 +1778,7 @@
</span><span class="cx"> .done:
</span><span class="cx"> end
</span><span class="cx"> 
</span><del>-macro doCall(slowPath)
</del><ins>+macro doCall(slowPath, prepareCall)
</ins><span class="cx">     loadi 8[PC], t0
</span><span class="cx">     loadi 20[PC], t1
</span><span class="cx">     loadp LLIntCallLinkInfo::callee[t1], t2
</span><span class="lines">@@ -1779,14 +1793,14 @@
</span><span class="cx">     storei PC, ArgumentCount + TagOffset[cfr]
</span><span class="cx">     storei t2, ArgumentCount + PayloadOffset[t3]
</span><span class="cx">     storei CellTag, Callee + TagOffset[t3]
</span><del>-    addp CallerFrameAndPCSize, t3
-    callTargetFunction(t1, t3)
</del><ins>+    move t3, sp
+    prepareCall(LLIntCallLinkInfo::machineCodeTarget[t1], t2, t3, t4)
+    callTargetFunction(LLIntCallLinkInfo::machineCodeTarget[t1])
</ins><span class="cx"> 
</span><span class="cx"> .opCallSlow:
</span><del>-    slowPathForCall(slowPath)
</del><ins>+    slowPathForCall(slowPath, prepareCall)
</ins><span class="cx"> end
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> _llint_op_ret:
</span><span class="cx">     traceExecution()
</span><span class="cx">     checkSwitchToJITForEpilogue()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -510,14 +510,27 @@
</span><span class="cx"> .noError:
</span><span class="cx">     loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[r1], t1
</span><span class="cx">     btiz t1, .continue
</span><ins>+    loadi PayloadOffset + ArgumentCount[cfr], t2
+    addi CallFrameHeaderSlots, t2
</ins><span class="cx"> 
</span><del>-    // Move frame up &quot;t1 * 2&quot; slots
-    lshiftp 1, t1
</del><ins>+    // Check if there are some unaligned slots we can use
+    move t1, t3
+    andi StackAlignmentSlots - 1, t3
+    btiz t3, .noExtraSlot
+    move ValueUndefined, t0
+.fillExtraSlots:
+    storeq t0, [cfr, t2, 8]
+    addi 1, t2
+    bsubinz 1, t3, .fillExtraSlots
+    andi ~(StackAlignmentSlots - 1), t1
+    btiz t1, .continue
+
+.noExtraSlot:
+    // Move frame up t1 slots
</ins><span class="cx">     negq t1
</span><span class="cx">     move cfr, t3
</span><span class="cx">     subp CalleeSaveSpaceAsVirtualRegisters * 8, t3
</span><del>-    loadi PayloadOffset + ArgumentCount[cfr], t2
-    addi CallFrameHeaderSlots + CalleeSaveSpaceAsVirtualRegisters, t2
</del><ins>+    addi CalleeSaveSpaceAsVirtualRegisters, t2
</ins><span class="cx"> .copyLoop:
</span><span class="cx">     loadq [t3], t0
</span><span class="cx">     storeq t0, [t3, t1, 8]
</span><span class="lines">@@ -1653,7 +1666,7 @@
</span><span class="cx"> .done:
</span><span class="cx"> end
</span><span class="cx"> 
</span><del>-macro doCall(slowPath)
</del><ins>+macro doCall(slowPath, prepareCall)
</ins><span class="cx">     loadisFromInstruction(2, t0)
</span><span class="cx">     loadpFromInstruction(5, t1)
</span><span class="cx">     loadp LLIntCallLinkInfo::callee[t1], t2
</span><span class="lines">@@ -1667,14 +1680,14 @@
</span><span class="cx">     loadisFromInstruction(3, t2)
</span><span class="cx">     storei PC, ArgumentCount + TagOffset[cfr]
</span><span class="cx">     storei t2, ArgumentCount + PayloadOffset[t3]
</span><del>-    addp CallerFrameAndPCSize, t3
-    callTargetFunction(t1, t3)
</del><ins>+    move t3, sp
+    prepareCall(LLIntCallLinkInfo::machineCodeTarget[t1], t2, t3, t4)
+    callTargetFunction(LLIntCallLinkInfo::machineCodeTarget[t1])
</ins><span class="cx"> 
</span><span class="cx"> .opCallSlow:
</span><del>-    slowPathForCall(slowPath)
</del><ins>+    slowPathForCall(slowPath, prepareCall)
</ins><span class="cx"> end
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> _llint_op_ret:
</span><span class="cx">     traceExecution()
</span><span class="cx">     checkSwitchToJITForEpilogue()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -59,13 +59,14 @@
</span><span class="cx">     int argumentCountIncludingThis = exec-&gt;argumentCountIncludingThis();
</span><span class="cx">     
</span><span class="cx">     ASSERT(argumentCountIncludingThis &lt; newCodeBlock-&gt;numParameters());
</span><del>-    int missingArgumentCount = newCodeBlock-&gt;numParameters() - argumentCountIncludingThis;
-    int neededStackSpace = missingArgumentCount + 1; // Allow space to save the original return PC.
-    int paddedStackSpace = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), neededStackSpace);
</del><ins>+    int frameSize = argumentCountIncludingThis + JSStack::CallFrameHeaderSize;
+    int alignedFrameSizeForParameters = WTF::roundUpToMultipleOf(stackAlignmentRegisters(),
+        newCodeBlock-&gt;numParameters() + JSStack::CallFrameHeaderSize);
+    int paddedStackSpace = alignedFrameSizeForParameters - frameSize;
</ins><span class="cx"> 
</span><del>-    if (!stack-&gt;ensureCapacityFor(exec-&gt;registers() - paddedStackSpace))
</del><ins>+    if (!stack-&gt;ensureCapacityFor(exec-&gt;registers() - paddedStackSpace % stackAlignmentRegisters()))
</ins><span class="cx">         return -1;
</span><del>-    return paddedStackSpace / stackAlignmentRegisters();
</del><ins>+    return paddedStackSpace;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline bool opIn(ExecState* exec, JSValue propName, JSValue baseVal)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (189773 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2015-09-15 02:42:39 UTC (rev 189773)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -128,7 +128,7 @@
</span><span class="cx">     v(bool, forceProfilerBytecodeGeneration, false, nullptr) \
</span><span class="cx">     \
</span><span class="cx">     v(bool, enableFunctionDotArguments, true, nullptr) \
</span><del>-    v(bool, enableTailCalls, true, nullptr) \
</del><ins>+    v(bool, enableTailCalls, false, nullptr) \
</ins><span class="cx">     \
</span><span class="cx">     /* showDisassembly implies showDFGDisassembly. */ \
</span><span class="cx">     v(bool, showDisassembly, false, &quot;dumps disassembly of all JIT compiled code upon compilation&quot;) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressmutualtailcallnostackoverflowjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/mutual-tail-call-no-stack-overflow.js (0 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/mutual-tail-call-no-stack-overflow.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/mutual-tail-call-no-stack-overflow.js        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -0,0 +1,75 @@
</span><ins>+//@ run(&quot;default&quot;, &quot;--enableTailCalls=true&quot;, &quot;--useDFGJIT=false&quot;)
+//@ run(&quot;no-llint&quot;, &quot;--enableTailCalls=true&quot;, &quot;--useLLInt=false&quot;)
+//@ run(&quot;no-cjit&quot;, &quot;--enableTailCalls=true&quot;, &quot;--useDFGJIT=false&quot;, *NO_CJIT_OPTIONS)
+
+function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+
+function sloppyCountdown(n) {
+    function even(n) {
+        if (n == 0)
+            return n;
+        return odd(n - 1);
+    }
+
+    function odd(n) {
+        if (n == 1)
+            return n;
+        return even(n - 1);
+    }
+
+    if (n % 2 === 0)
+        return even(n);
+    else
+        return odd(n);
+}
+
+function strictCountdown(n) {
+    &quot;use strict&quot;;
+
+    function even(n) {
+        if (n == 0)
+            return n;
+        return odd(n - 1);
+    }
+
+    function odd(n) {
+        if (n == 1)
+            return n;
+        return even(n - 1);
+    }
+
+    if (n % 2 === 0)
+        return even(n);
+    else
+        return odd(n);
+}
+
+shouldThrow(function () { sloppyCountdown(100000); }, &quot;RangeError: Maximum call stack size exceeded.&quot;);
+strictCountdown(100000);
+
+// Parity alterning
+function odd(n) {
+    &quot;use strict&quot;;
+    if (n &gt; 0)
+        return even(n, 0);
+}
+
+function even(n) {
+    &quot;use strict&quot;;
+    return odd(n - 1);
+}
+
+odd(100000);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresstailcallnostackoverflowjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/tail-call-no-stack-overflow.js (0 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/tail-call-no-stack-overflow.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/tail-call-no-stack-overflow.js        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -0,0 +1,48 @@
</span><ins>+//@ run(&quot;default&quot;, &quot;--enableTailCalls=true&quot;, &quot;--useDFGJIT=false&quot;)
+//@ run(&quot;no-llint&quot;, &quot;--enableTailCalls=true&quot;, &quot;--useLLInt=false&quot;)
+
+function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+
+function sloppyLoop(n) {
+    if (n &gt; 0)
+        return sloppyLoop(n - 1);
+}
+
+function strictLoop(n) {
+    &quot;use strict&quot;;
+    if (n &gt; 0)
+        return strictLoop(n - 1);
+}
+
+// We have two of these so that we can test different stack alignments
+function strictLoopArityFixup1(n, dummy) {
+    &quot;use strict&quot;;
+    if (n &gt; 0)
+        return strictLoopArityFixup1(n - 1);
+}
+
+function strictLoopArityFixup2(n, dummy1, dummy2) {
+    &quot;use strict&quot;;
+    if (n &gt; 0)
+        return strictLoopArityFixup2(n - 1);
+}
+
+shouldThrow(function () { sloppyLoop(100000); }, 'RangeError: Maximum call stack size exceeded.');
+
+// These should not throw
+strictLoop(100000);
+strictLoopArityFixup1(1000000);
+strictLoopArityFixup2(1000000);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresstailcallrecognizejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/tail-call-recognize.js (0 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/tail-call-recognize.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/tail-call-recognize.js        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -0,0 +1,183 @@
</span><ins>+//@ run(&quot;default&quot;, &quot;--enableTailCalls=true&quot;, &quot;--useDFGJIT=false&quot;)
+//@ run(&quot;no-llint&quot;, &quot;--enableTailCalls=true&quot;, &quot;--useLLInt=false&quot;)
+//@ run(&quot;no-cjit&quot;, &quot;--enableTailCalls=true&quot;, &quot;--useDFGJIT=false&quot;, *NO_CJIT_OPTIONS)
+// run(&quot;-no-inline&quot;, &quot;--maximumInliningDepth=1&quot;)
+
+function callerMustBeRun() {
+    if (!Object.is(callerMustBeRun.caller, runTests))
+        throw Error(&quot;Wrong caller, expected run but got &quot;, callerMustBeRun.caller);
+}
+
+function callerMustBeStrict() {
+    var errorThrown = false;
+    try {
+        callerMustBeStrict.caller;
+    } catch (e) {
+        errorThrown = true;
+    }
+    if (!errorThrown)
+        throw Error(&quot;Wrong caller, expected strict caller but got &quot;, callerMustBeStrict.caller);
+}
+
+function runTests() {
+    // Statement tests
+    (function simpleTailCall() {
+        &quot;use strict&quot;;
+        return callerMustBeRun();
+    })();
+
+    (function noTailCallInTry() {
+        &quot;use strict&quot;;
+        try {
+            return callerMustBeStrict();
+        } catch (e) {
+            throw e;
+        }
+    })();
+
+    (function tailCallInCatch() {
+        &quot;use strict&quot;;
+        try { } catch (e) { return callerMustBeRun(); }
+    })();
+
+    (function tailCallInFinally() {
+        &quot;use strict&quot;;
+        try { } finally { return callerMustBeRun(); }
+    })();
+
+    (function tailCallInFinallyWithCatch() {
+        &quot;use strict&quot;;
+        try { } catch (e) { } finally { return callerMustBeRun(); }
+    })();
+
+    (function tailCallInFinallyWithCatchTaken() {
+        &quot;use strict&quot;;
+        try { throw null; } catch (e) { } finally { return callerMustBeRun(); }
+    })();
+
+    (function noTailCallInCatchIfFinally() {
+        &quot;use strict&quot;;
+        try { throw null; } catch (e) { return callerMustBeStrict(); } finally { }
+    })();
+
+    (function tailCallInFor() {
+        &quot;use strict&quot;;
+        for (var i = 0; i &lt; 10; ++i)
+            return callerMustBeRun();
+    })();
+
+    (function tailCallInWhile() {
+        &quot;use strict&quot;;
+        while (true)
+            return callerMustBeRun();
+    })();
+
+    (function tailCallInDoWhile() {
+        &quot;use strict&quot;;
+        do
+            return callerMustBeRun();
+        while (true);
+    })();
+
+    (function noTailCallInForIn() {
+        &quot;use strict&quot;;
+        for (var x in [1, 2])
+            return callerMustBeStrict();
+    })();
+
+    (function noTailCallInForOf() {
+        &quot;use strict&quot;;
+        for (var x of [1, 2])
+            return callerMustBeStrict();
+    })();
+
+    (function tailCallInIf() {
+        &quot;use strict&quot;;
+        if (true)
+            return callerMustBeRun();
+    })();
+
+    (function tailCallInElse() {
+        &quot;use strict&quot;;
+        if (false) throw new Error(&quot;WTF&quot;);
+        else return callerMustBeRun();
+    })();
+
+    (function tailCallInSwitchCase() {
+        &quot;use strict&quot;;
+        switch (0) {
+        case 0: return callerMustBeRun();
+        }
+    })();
+
+    (function tailCallInSwitchDefault() {
+        &quot;use strict&quot;;
+        switch (0) {
+        default: return callerMustBeRun();
+        }
+    })();
+
+    (function tailCallWithLabel() {
+        &quot;use strict&quot;;
+        dummy: return callerMustBeRun();
+    })();
+
+    // Expression tests, we don't enumerate all the cases where there
+    // *shouldn't* be a tail call
+
+    (function tailCallComma() {
+        &quot;use strict&quot;;
+        return callerMustBeStrict(), callerMustBeRun();
+    })();
+
+    (function tailCallTernaryLeft() {
+        &quot;use strict&quot;;
+        return true ? callerMustBeRun() : unreachable();
+    })();
+
+    (function tailCallTernaryRight() {
+        &quot;use strict&quot;;
+        return false ? unreachable() : callerMustBeRun();
+    })();
+
+    (function tailCallLogicalAnd() {
+        &quot;use strict&quot;;
+        return true &amp;&amp; callerMustBeRun();
+    })();
+
+    (function tailCallLogicalOr() {
+        &quot;use strict&quot;;
+        return false || callerMustBeRun();
+    })();
+
+    (function memberTailCall() {
+        &quot;use strict&quot;;
+        return { f: callerMustBeRun }.f();
+    })();
+
+    (function bindTailCall() {
+        &quot;use strict&quot;;
+        return callerMustBeRun.bind()();
+    })();
+
+    // Function.prototype tests
+
+    (function applyTailCall() {
+        &quot;use strict&quot;;
+        return callerMustBeRun.apply();
+    })();
+
+    (function callTailCall() {
+        &quot;use strict&quot;;
+        return callerMustBeRun.call();
+    })();
+
+    // No tail call for constructors
+    (function noTailConstruct() {
+        &quot;use strict&quot;;
+        return new callerMustBeStrict();
+    })();
+}
+
+for (var i = 0; i &lt; 10000; ++i)
+    runTests();
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresstailcallvarargsnostackoverflowjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/tail-call-varargs-no-stack-overflow.js (0 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/tail-call-varargs-no-stack-overflow.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/tail-call-varargs-no-stack-overflow.js        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -0,0 +1,32 @@
</span><ins>+//@ run(&quot;default&quot;, &quot;--enableTailCalls=true&quot;, &quot;--useDFGJIT=false&quot;)
+//@ run(&quot;no-llint&quot;, &quot;--enableTailCalls=true&quot;, &quot;--useLLInt=false&quot;)
+//@ run(&quot;no-cjit&quot;, &quot;--enableTailCalls=true&quot;, &quot;--useDFGJIT=false&quot;, *NO_CJIT_OPTIONS)
+
+function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+
+function sloppyLoop(n) {
+    if (n &gt; 0)
+        return sloppyLoop(...[n - 1]);
+}
+
+function strictLoop(n) {
+    &quot;use strict&quot;;
+    if (n &gt; 0)
+        return strictLoop(...[n - 1]);
+}
+
+shouldThrow(function () { sloppyLoop(100000); }, 'RangeError: Maximum call stack size exceeded.');
+strictLoop(100000);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresstailcallsdontoverwritelivestackjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/tail-calls-dont-overwrite-live-stack.js (0 => 189774)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/tail-calls-dont-overwrite-live-stack.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/tail-calls-dont-overwrite-live-stack.js        2015-09-15 03:00:34 UTC (rev 189774)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+&quot;use strict&quot;;
+
+function tail(a, b) { }
+noInline(tail);
+
+var obj = {
+    method: function (x) {
+        return tail(x, x);
+    },
+
+    get fromNative() { return tail(0, 0); }
+};
+noInline(obj.method);
+
+function getThis(x) { return this; }
+noInline(getThis);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var that = getThis(obj.method(42));
+
+    if (!Object.is(that, undefined))
+        throw new Error(&quot;Wrong 'this' value in call, expected undefined but got &quot; + that);
+
+    that = getThis(obj.method(...[42]));
+    if (!Object.is(that, undefined))
+        throw new Error(&quot;Wrong 'this' value in varargs call, expected undefined but got &quot; + that);
+
+    if (!Object.is(obj.fromNative, undefined))
+        throw new Error(&quot;Wrong 'fromNative' value, expected undefined but got &quot; + obj.fromNative);
+}
</ins></span></pre>
</div>
</div>

</body>
</html>