<!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>[189884] 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/189884">189884</a></dd>
<dt>Author</dt> <dd>msaboff@apple.com</dd>
<dt>Date</dt> <dd>2015-09-16 16:40:35 -0700 (Wed, 16 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
Fix for the breakage of Speedometer/Full.html (https://bugs.webkit.org/show_bug.cgi?id=149162).
Reviewed by Filip Pizlo.
Changed SetupVarargsFrame.cpp::emitSetVarargsFrame to align the callframe size to be a
multiple of stackAlignmentRegisters() in addition to the location of the new frame.
Fixed Reviewed by Filip Pizlo.
* 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/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):
(JSC::calleeFrameForVarargs):
* 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/SetupVarargsFrame.cpp:
(JSC::emitSetVarargsFrame):
* 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):</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="#trunkSourceJavaScriptCorejitSetupVarargsFramecpp">trunk/Source/JavaScriptCore/jit/SetupVarargsFrame.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>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2015-09-16 23:40:35 UTC (rev 189884)
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-09-16 23:40:35 UTC (rev 189884)
</span><span class="lines">@@ -1,3 +1,169 @@
</span><ins>+2015-09-16 Michael Saboff <msaboff@apple.com>
+
+ [ES6] Implement tail calls in the LLInt and Baseline JIT
+ https://bugs.webkit.org/show_bug.cgi?id=148661
+
+ Fix for the breakage of Speedometer/Full.html (https://bugs.webkit.org/show_bug.cgi?id=149162).
+
+ Reviewed by Filip Pizlo.
+ Changed SetupVarargsFrame.cpp::emitSetVarargsFrame to align the callframe size to be a
+ multiple of stackAlignmentRegisters() in addition to the location of the new frame.
+
+ Fixed Reviewed by Filip Pizlo.
+
+ * 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/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):
+ (JSC::calleeFrameForVarargs):
+ * 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/SetupVarargsFrame.cpp:
+ (JSC::emitSetVarargsFrame):
+ * 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):
+
</ins><span class="cx"> 2015-09-15 Michael Saboff <msaboff@apple.com>
</span><span class="cx">
</span><span class="cx"> Rollout r189774 and 189818.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-09-16 23:40:35 UTC (rev 189884)
</span><span class="lines">@@ -319,6 +319,7 @@
</span><span class="cx"> <ClCompile Include="..\bytecode\CallEdge.cpp" />
</span><span class="cx"> <ClCompile Include="..\bytecode\CallLinkInfo.cpp" />
</span><span class="cx"> <ClCompile Include="..\bytecode\CallLinkStatus.cpp" />
</span><ins>+ <ClCompile Include="..\bytecode\CallMode.cpp" />
</ins><span class="cx"> <ClCompile Include="..\bytecode\CallVariant.cpp" />
</span><span class="cx"> <ClCompile Include="..\bytecode\CodeBlock.cpp" />
</span><span class="cx"> <ClCompile Include="..\bytecode\CodeBlockHash.cpp" />
</span><span class="lines">@@ -1012,6 +1013,7 @@
</span><span class="cx"> <ClInclude Include="..\bytecode\CallEdge.h" />
</span><span class="cx"> <ClInclude Include="..\bytecode\CallLinkInfo.h" />
</span><span class="cx"> <ClInclude Include="..\bytecode\CallLinkStatus.h" />
</span><ins>+ <ClInclude Include="..\bytecode\CallMode.h" />
</ins><span class="cx"> <ClInclude Include="..\bytecode\CallReturnOffsetToBytecodeOffset.h" />
</span><span class="cx"> <ClInclude Include="..\bytecode\CallVariant.h" />
</span><span class="cx"> <ClInclude Include="..\bytecode\CodeBlock.h" />
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-09-16 23:40:35 UTC (rev 189884)
</span><span class="lines">@@ -162,6 +162,9 @@
</span><span class="cx"> <ClCompile Include="..\bytecode\CallLinkStatus.cpp">
</span><span class="cx"> <Filter>bytecode</Filter>
</span><span class="cx"> </ClCompile>
</span><ins>+ <ClCompile Include="..\bytecode\CallMode.cpp">
+ <Filter>bytecode</Filter>
+ </ClCompile>
</ins><span class="cx"> <ClCompile Include="..\bytecode\CodeBlock.cpp">
</span><span class="cx"> <Filter>bytecode</Filter>
</span><span class="cx"> </ClCompile>
</span><span class="lines">@@ -2034,6 +2037,9 @@
</span><span class="cx"> <ClInclude Include="..\bytecode\CallLinkStatus.h">
</span><span class="cx"> <Filter>bytecode</Filter>
</span><span class="cx"> </ClInclude>
</span><ins>+ <ClInclude Include="..\bytecode\CallMode.h">
+ <Filter>bytecode</Filter>
+ </ClInclude>
</ins><span class="cx"> <ClInclude Include="..\bytecode\CallReturnOffsetToBytecodeOffset.h">
</span><span class="cx"> <Filter>bytecode</Filter>
</span><span class="cx"> </ClInclude>
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-09-16 23:40:35 UTC (rev 189884)
</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 = "<group>"; };
</span><span class="cx">                 623A37EB1B87A7BD00754209 /* RegisterMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterMap.h; sourceTree = "<group>"; };
</span><ins>+                627673211B680C1E00FD9F2E /* CallMode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallMode.cpp; sourceTree = "<group>"; };
+                627673221B680C1E00FD9F2E /* CallMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallMode.h; sourceTree = "<group>"; };
</ins><span class="cx">                 62A9A29E1B0BED4800BD54CA /* DFGLazyNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGLazyNode.cpp; path = dfg/DFGLazyNode.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 62A9A29F1B0BED4800BD54CA /* DFGLazyNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGLazyNode.h; path = dfg/DFGLazyNode.h; sourceTree = "<group>"; };
</span><span class="cx">                 62D2D38D1ADF103F000206C1 /* FunctionRareData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FunctionRareData.cpp; sourceTree = "<group>"; };
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/AbortReason.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/assembler/AbortReason.h        2015-09-16 23:40:35 UTC (rev 189884)
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h        2015-09-16 23:40:35 UTC (rev 189884)
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/CodeLocation.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/assembler/CodeLocation.h        2015-09-16 23:40:35 UTC (rev 189884)
</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<char*>(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<char*>(dataLocation()) + offset);
</del><ins>+ return CodeLocationNearCall(reinterpret_cast<char*>(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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/LinkBuffer.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/assembler/LinkBuffer.h        2015-09-16 23:40:35 UTC (rev 189884)
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM.h        2015-09-16 23:40:35 UTC (rev 189884)
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h        2015-09-16 23:40:35 UTC (rev 189884)
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h        2015-09-16 23:40:35 UTC (rev 189884)
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h        2015-09-16 23:40:35 UTC (rev 189884)
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h        2015-09-16 23:40:35 UTC (rev 189884)
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86.h        2015-09-16 23:40:35 UTC (rev 189884)
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h        2015-09-16 23:40:35 UTC (rev 189884)
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h        2015-09-16 23:40:35 UTC (rev 189884)
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2015-09-16 23:40:35 UTC (rev 189884)
</span><span class="lines">@@ -92,8 +92,10 @@
</span><span class="cx"> { "name" : "op_new_func_exp", "length" : 4 },
</span><span class="cx"> { "name" : "op_new_arrow_func_exp", "length" : 5 },
</span><span class="cx"> { "name" : "op_call", "length" : 9 },
</span><ins>+ { "name" : "op_tail_call", "length" : 9 },
</ins><span class="cx"> { "name" : "op_call_eval", "length" : 9 },
</span><span class="cx"> { "name" : "op_call_varargs", "length" : 9 },
</span><ins>+ { "name" : "op_tail_call_varargs", "length" : 9 },
</ins><span class="cx"> { "name" : "op_ret", "length" : 2 },
</span><span class="cx"> { "name" : "op_construct", "length" : 9 },
</span><span class="cx"> { "name" : "op_construct_varargs", "length" : 9 },
</span><span class="lines">@@ -144,7 +146,10 @@
</span><span class="cx"> { "name" : "llint_cloop_did_return_from_js_5" },
</span><span class="cx"> { "name" : "llint_cloop_did_return_from_js_6" },
</span><span class="cx"> { "name" : "llint_cloop_did_return_from_js_7" },
</span><del>- { "name" : "llint_cloop_did_return_from_js_8" }
</del><ins>+ { "name" : "llint_cloop_did_return_from_js_8" },
+ { "name" : "llint_cloop_did_return_from_js_9" },
+ { "name" : "llint_cloop_did_return_from_js_10" },
+ { "name" : "llint_cloop_did_return_from_js_11" }
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2015-09-16 23:40:35 UTC (rev 189884)
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2015-09-16 23:40:35 UTC (rev 189884)
</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 "CallMode.h"
</ins><span class="cx"> #include "CodeLocation.h"
</span><span class="cx"> #include "CodeSpecializationKind.h"
</span><span class="cx"> #include "JITWriteBarrier.h"
</span><span class="lines">@@ -41,19 +42,36 @@
</span><span class="cx">
</span><span class="cx"> class CallLinkInfo : public BasicRawSentinelNode<CallLinkInfo> {
</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<unsigned>(RegisterPreservationNotRequired))
</span><span class="cx"> , m_hasSeenShouldRepatch(false)
</span><span class="lines">@@ -83,6 +101,40 @@
</span><span class="cx"> return specializationKindFor(static_cast<CallType>(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<CallType>(m_callType));
+ }
+
+ bool isTailCall() const
+ {
+ return callMode() == CallMode::Tail;
+ }
+
+ bool isVarargs() const
+ {
+ return isVarargsCallType(static_cast<CallType>(m_callType));
+ }
+
</ins><span class="cx"> RegisterPreservationMode registerPreservationMode() const
</span><span class="cx"> {
</span><span class="cx"> return static_cast<RegisterPreservationMode>(m_registerPreservationMode);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkStatuscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp        2015-09-16 23:40:35 UTC (rev 189884)
</span><span class="lines">@@ -69,7 +69,7 @@
</span><span class="cx">
</span><span class="cx"> Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
</span><span class="cx"> OpcodeID op = vm.interpreter->getOpcodeID(instruction[0].u.opcode);
</span><del>- if (op != op_call && op != op_construct)
</del><ins>+ if (op != op_call && op != op_construct && 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="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-09-16 23:40:35 UTC (rev 189884)
</span><span class="lines">@@ -1248,13 +1248,18 @@
</span><span class="cx"> printCallOp(out, exec, location, it, "call", DumpCaches, hasPrintedProfiling, callLinkInfos);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><ins>+ case op_tail_call: {
+ printCallOp(out, exec, location, it, "tail_call", DumpCaches, hasPrintedProfiling, callLinkInfos);
+ break;
+ }
</ins><span class="cx"> case op_call_eval: {
</span><span class="cx"> printCallOp(out, exec, location, it, "call_eval", 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)->u.operand;
</span><span class="cx"> int callee = (++it)->u.operand;
</span><span class="cx"> int thisValue = (++it)->u.operand;
</span><span class="lines">@@ -1262,7 +1267,7 @@
</span><span class="cx"> int firstFreeRegister = (++it)->u.operand;
</span><span class="cx"> int varArgOffset = (++it)->u.operand;
</span><span class="cx"> ++it;
</span><del>- printLocationAndOp(out, exec, location, it, opcode == op_call_varargs ? "call_varargs" : "construct_varargs");
</del><ins>+ printLocationAndOp(out, exec, location, it, opcode == op_call_varargs ? "call_varargs" : opcode == op_construct_varargs ? "construct_varargs" : "tail_call_varargs");
</ins><span class="cx"> out.printf("%s, %s, %s, %s, %d, %d", 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 = &m_valueProfiles[pc[opLength - 1].u.operand];
</span><span class="cx"> ASSERT(profile->m_bytecodeOffset == -1);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-09-16 23:40:35 UTC (rev 189884)
</span><span class="lines">@@ -193,7 +193,12 @@
</span><span class="cx"> , m_vm(&vm)
</span><span class="cx"> , m_isBuiltinFunction(codeBlock->isBuiltinFunction())
</span><span class="cx"> , m_usesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode())
</span><del>- , m_inTailPosition(Options::enableTailCalls() && constructorKind() == ConstructorKind::None && 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() && constructorKind() == ConstructorKind::None && isStrictMode() && !m_shouldEmitProfileHooks)
</ins><span class="cx"> {
</span><span class="cx"> for (auto& 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& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& 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& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& 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& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& 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->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<RegisterID> argumentRegister;
</span><span class="cx"> argumentRegister = expression->emitBytecode(*this, callArguments.argumentRegister(0));
</span><span class="cx"> RefPtr<RegisterID> 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->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& divot, const JSTextPosition& divotStart, const JSTextPosition& 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& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-09-16 23:40:35 UTC (rev 189884)
</span><span class="lines">@@ -678,6 +678,12 @@
</span><span class="cx"> m_argv[i] = generator.newTemporary();
</span><span class="cx"> ASSERT(static_cast<size_t>(i) == m_argv.size() - 1 || m_argv[i]->index() == m_argv[i + 1]->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, &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->breakTarget());
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-09-16 23:40:35 UTC (rev 189884)
</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 > 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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-09-16 23:40:35 UTC (rev 189884)
</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->numChildren() - 1;
- int numArgs = numPassedArgs;
</del><ins>+ int numArgs = m_node->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<LValue> 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 -> %rax
</span><span class="cx"> arguments.append(getUndef(m_out.int64)); // code block
</span><span class="cx"> arguments.append(jsCallee); // callee -> 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 < numPassedArgs; ++i)
</del><ins>+ for (int i = 0; i < numArgs; ++i)
</ins><span class="cx"> arguments.append(lowJSValue(m_graph.varArgChild(m_node, 1 + i)));
</span><ins>+ for (unsigned i = 0; i < 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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.h        2015-09-16 23:40:35 UTC (rev 189884)
</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 class="lines">@@ -277,6 +277,15 @@
</span><span class="cx">
</span><span class="cx"> inline CallFrame* calleeFrameForVarargs(CallFrame* callFrame, unsigned numUsedStackSlots, unsigned argumentCountIncludingThis)
</span><span class="cx"> {
</span><ins>+#if 1
+ // We want the new frame to be allocated on a stack aligned offset with a stack
+ // aligned size. Align the size here.
+ argumentCountIncludingThis = WTF::roundUpToMultipleOf(
+ stackAlignmentRegisters(),
+ argumentCountIncludingThis + JSStack::CallFrameHeaderSize) - JSStack::CallFrameHeaderSize;
+
+ // Align the frame offset here.
+#endif
</ins><span class="cx"> unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(
</span><span class="cx"> stackAlignmentRegisters(),
</span><span class="cx"> numUsedStackSlots + argumentCountIncludingThis + JSStack::CallFrameHeaderSize);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitCCallHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/CCallHelpers.h (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CCallHelpers.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/jit/CCallHelpers.h        2015-09-16 23:40:35 UTC (rev 189884)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx">
</span><span class="cx"> #include "AssemblyHelpers.h"
</span><span class="cx"> #include "GPRInfo.h"
</span><ins>+#include "StackAlignment.h"
</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(&vm()->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<int>(sizeof(Register)) + PayloadOffset), argCountGPR);
+
+ {
+ GPRReg numParametersGPR = temp1;
+ {
+ GPRReg codeBlockGPR = numParametersGPR;
+ loadPtr(Address(framePointerRegister, JSStack::CodeBlock * static_cast<int>(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 < 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<int>(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC)),
+ newFrameSizeGPR);
+ add32(TrustedImm32(stackAlignmentRegisters() + JSStack::CallFrameHeaderSize - 1), newFrameSizeGPR);
+ and32(TrustedImm32(-stackAlignmentRegisters()), newFrameSizeGPR);
+ // We assume < 2^28 arguments
+ mul32(TrustedImm32(sizeof(Register)), newFrameSizeGPR, newFrameSizeGPR);
+ }
+
+ GPRReg tempGPR = temp3;
+ ASSERT(tempGPR != newFramePointer && 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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp        2015-09-16 23:40:35 UTC (rev 189884)
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2015-09-16 23:40:35 UTC (rev 189884)
</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<SlowCaseEntry>::iterator&);
</span><span class="cx"> void emitSlow_op_bitxor(Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><span class="cx"> void emitSlow_op_call(Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><ins>+ void emitSlow_op_tail_call(Instruction*, Vector<SlowCaseEntry>::iterator&);
</ins><span class="cx"> void emitSlow_op_call_eval(Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><span class="cx"> void emitSlow_op_call_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><ins>+ void emitSlow_op_tail_call_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&);
</ins><span class="cx"> void emitSlow_op_construct_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><span class="cx"> void emitSlow_op_construct(Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><span class="cx"> void emitSlow_op_to_this(Instruction*, Vector<SlowCaseEntry>::iterator&);
</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& failures);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCallcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCall.cpp (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall.cpp        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/jit/JITCall.cpp        2015-09-16 23:40:35 UTC (rev 189884)
</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->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<int>(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->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<SlowCaseEntry>::iterator& iter)
+{
+ compileOpCallSlowCase(op_tail_call, currentInstruction, iter, m_callLinkInfoIndex++);
+}
+
</ins><span class="cx"> void JIT::emitSlow_op_call_eval(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& 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<SlowCaseEntry>::iterator& 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<SlowCaseEntry>::iterator& 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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2015-09-16 23:40:35 UTC (rev 189884)
</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<SlowCaseEntry>::iterator& iter)
+{
+ compileOpCallSlowCase(op_tail_call, currentInstruction, iter, m_callLinkInfoIndex++);
+}
+
</ins><span class="cx"> void JIT::emitSlow_op_call_eval(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& 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<SlowCaseEntry>::iterator& 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<SlowCaseEntry>::iterator& 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->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->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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITInlines.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/jit/JITInlines.h        2015-09-16 23:40:35 UTC (rev 189884)
</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<unsigned>::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<int>(m_bytecodeOffset) >= 0);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-09-16 23:40:35 UTC (rev 189884)
</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->callerFrame();
</span><span class="cx"> VM* vm = &exec->vm();
</span><span class="cx">
</span><span class="cx"> execCallee->setCodeBlock(0);
</span><span class="cx">
</span><del>- if (kind == CodeForCall) {
</del><ins>+ if (callLinkInfo->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->setCallee(asObject(callee));
</span><span class="cx"> vm->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
</span><del>- if (vm->exception())
- return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
</del><ins>+ if (vm->exception()) {
+ return encodeResult(
+ vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
+ reinterpret_cast<void*>(KeepTheFrame));
+ }
</ins><span class="cx">
</span><del>- return reinterpret_cast<void*>(getHostCallReturnValue);
</del><ins>+ return encodeResult(
+ bitwise_cast<void*>(getHostCallReturnValue),
+ reinterpret_cast<void*>(callLinkInfo->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->vm().throwException(exec, createNotAFunctionError(exec, callee));
</span><del>- return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
</del><ins>+ return encodeResult(
+ vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
+ reinterpret_cast<void*>(KeepTheFrame));
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- ASSERT(kind == CodeForConstruct);
</del><ins>+ ASSERT(callLinkInfo->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->setCallee(asObject(callee));
</span><span class="cx"> vm->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
</span><del>- if (vm->exception())
- return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
</del><ins>+ if (vm->exception()) {
+ return encodeResult(
+ vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
+ reinterpret_cast<void*>(KeepTheFrame));
+ }
</ins><span class="cx">
</span><del>- return reinterpret_cast<void*>(getHostCallReturnValue);
</del><ins>+ return encodeResult(bitwise_cast<void*>(getHostCallReturnValue), reinterpret_cast<void*>(KeepTheFrame));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> ASSERT(constructType == ConstructTypeNone);
</span><span class="cx"> exec->vm().throwException(exec, createNotAConstructorError(exec, callee));
</span><del>- return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
</del><ins>+ return encodeResult(
+ vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
+ reinterpret_cast<void*>(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->callerFrame();
</span><span class="cx"> VM* vm = &exec->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<char*>(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<JSFunction*>(calleeAsFunctionCell);
</span><span class="lines">@@ -774,17 +786,21 @@
</span><span class="cx">
</span><span class="cx"> if (!isCall(kind) && functionExecutable->constructAbility() == ConstructAbility::CannotConstruct) {
</span><span class="cx"> exec->vm().throwException(exec, createNotAConstructorError(exec, callee));
</span><del>- return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
</del><ins>+ return encodeResult(
+ vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
+ reinterpret_cast<void*>(KeepTheFrame));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> JSObject* error = functionExecutable->prepareForExecution(execCallee, callee, scope, kind);
</span><span class="cx"> if (error) {
</span><span class="cx"> exec->vm().throwException(exec, error);
</span><del>- return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
</del><ins>+ return encodeResult(
+ vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
+ reinterpret_cast<void*>(KeepTheFrame));
</ins><span class="cx"> }
</span><span class="cx"> codeBlock = functionExecutable->codeBlockFor(kind);
</span><span class="cx"> ArityCheckMode arity;
</span><del>- if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo->callType() == CallLinkInfo::CallVarargs || callLinkInfo->callType() == CallLinkInfo::ConstructVarargs)
</del><ins>+ if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo->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<char*>(codePtr.executableAddress());
</del><ins>+ return encodeResult(codePtr.executableAddress(), reinterpret_cast<void*>(callLinkInfo->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*& calleeAsFunctionCell)
</span><span class="cx"> {
</span><span class="cx"> ExecState* exec = execCallee->callerFrame();
</span><span class="lines">@@ -809,7 +825,7 @@
</span><span class="cx"> JSValue calleeAsValue = execCallee->calleeAsValue();
</span><span class="cx"> calleeAsFunctionCell = getJSFunction(calleeAsValue);
</span><span class="cx"> if (UNLIKELY(!calleeAsFunctionCell))
</span><del>- return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind));
</del><ins>+ return handleHostCall(execCallee, calleeAsValue, callLinkInfo);
</ins><span class="cx">
</span><span class="cx"> JSFunction* function = jsCast<JSFunction*>(calleeAsFunctionCell);
</span><span class="cx"> JSScope* scope = function->scopeUnchecked();
</span><span class="lines">@@ -824,13 +840,17 @@
</span><span class="cx">
</span><span class="cx"> if (!isCall(kind) && functionExecutable->constructAbility() == ConstructAbility::CannotConstruct) {
</span><span class="cx"> exec->vm().throwException(exec, createNotAConstructorError(exec, function));
</span><del>- return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
</del><ins>+ return encodeResult(
+ vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
+ reinterpret_cast<void*>(KeepTheFrame));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> JSObject* error = functionExecutable->prepareForExecution(execCallee, function, scope, kind);
</span><span class="cx"> if (error) {
</span><span class="cx"> exec->vm().throwException(exec, error);
</span><del>- return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
</del><ins>+ return encodeResult(
+ vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
+ reinterpret_cast<void*>(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<char*>(executable->entrypointFor(
- *vm, kind, MustCheckArity, callLinkInfo->registerPreservationMode()).executableAddress());
</del><ins>+ return encodeResult(executable->entrypointFor(
+ *vm, kind, MustCheckArity, callLinkInfo->registerPreservationMode()).executableAddress(),
+ reinterpret_cast<void*>(callLinkInfo->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->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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-09-16 23:40:35 UTC (rev 189884)
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.cpp        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/jit/Repatch.cpp        2015-09-16 23:40:35 UTC (rev 189884)
</span><span class="lines">@@ -609,7 +609,7 @@
</span><span class="cx"> {
</span><span class="cx"> CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock();
</span><span class="cx"> VM* vm = callerCodeBlock->vm();
</span><del>-
</del><ins>+
</ins><span class="cx"> if (shouldShowDisassemblyFor(callerCodeBlock))
</span><span class="cx"> dataLog("Linking virtual call at ", *callerCodeBlock, " ", exec->callerFrame()->codeOrigin(), "\n");
</span><span class="cx">
</span><span class="lines">@@ -680,7 +680,7 @@
</span><span class="cx"> codeBlock = jsCast<FunctionExecutable*>(executable)->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->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo.callType() == CallLinkInfo::CallVarargs || callLinkInfo.callType() == CallLinkInfo::ConstructVarargs) {
</del><ins>+ if (exec->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->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="trunkSourceJavaScriptCorejitSetupVarargsFramecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/SetupVarargsFrame.cpp (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/SetupVarargsFrame.cpp        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/jit/SetupVarargsFrame.cpp        2015-09-16 23:40:35 UTC (rev 189884)
</span><span class="lines">@@ -37,6 +37,15 @@
</span><span class="cx"> void emitSetVarargsFrame(CCallHelpers& jit, GPRReg lengthGPR, bool lengthIncludesThis, GPRReg numUsedSlotsGPR, GPRReg resultGPR)
</span><span class="cx"> {
</span><span class="cx"> jit.move(numUsedSlotsGPR, resultGPR);
</span><ins>+ // We really want to make sure the size of the new call frame is a multiple of
+ // stackAlignmentRegisters(), however it is easier to accomplish this by
+ // rounding numUsedSlotsGPR to the next multiple of stackAlignmentRegisters().
+ // Together with the rounding below, we will assure that the new call frame is
+ // located on a stackAlignmentRegisters() boundary and a multiple of
+ // stackAlignmentRegisters() in size.
+ jit.addPtr(CCallHelpers::TrustedImm32(stackAlignmentRegisters() - 1), resultGPR);
+ jit.andPtr(CCallHelpers::TrustedImm32(~(stackAlignmentRegisters() - 1)), resultGPR);
+
</ins><span class="cx"> jit.addPtr(lengthGPR, resultGPR);
</span><span class="cx"> jit.addPtr(CCallHelpers::TrustedImm32(JSStack::CallFrameHeaderSize + (lengthIncludesThis? 0 : 1)), resultGPR);
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitThunkGeneratorscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2015-09-16 23:40:35 UTC (rev 189884)
</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& jit, VM* vm, P_JITOperation_ECli slowPathFunction)
</del><ins>+ CCallHelpers& 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, &vm->topCallFrame);
</span><ins>+#if OS(WINDOWS) && 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<void*>(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<void*>(KeepTheFrame) == reinterpret_cast<void*>(0));
+ CCallHelpers::Jump doNotTrash = jit.branchTestPtr(CCallHelpers::Zero, GPRInfo::returnValueGPR2);
+
+ jit.preserveReturnAddressAfterCall(GPRInfo::nonPreservedNonReturnGPR);
+ jit.prepareForTailCallSlow(GPRInfo::returnValueGPR);
+
+ doNotTrash.link(&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(&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>- ("Virtual %s%s slow path thunk",
- callLinkInfo.specializationKind() == CodeForCall ? "call" : "construct",
- callLinkInfo.registerPreservationMode() == MustPreserveRegisters ? " that preserves registers" : ""));
</del><ins>+ ("Virtual %s slow path thunk",
+ callLinkInfo.callMode() == CallMode::Regular ? "call" : callLinkInfo.callMode() == CallMode::Tail ? "tail call" : "construct"));
</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, &jit);
+ jit.and32(JSInterfaceJIT::TrustedImm32(-stackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
+ JSInterfaceJIT::Jump done = jit.branchTest32(MacroAssembler::Zero, JSInterfaceJIT::argumentGPR0);
+ noExtraSlot.link(&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, &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(&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, &jit);
+ jit.and32(JSInterfaceJIT::TrustedImm32(-stackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
+ JSInterfaceJIT::Jump done = jit.branchTest32(MacroAssembler::Zero, JSInterfaceJIT::argumentGPR0);
+ noExtraSlot.link(&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, &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, &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(&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, ("fixup arity"));
</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, ("unreachable thunk"));
+}
+
</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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.h        2015-09-16 23:40:35 UTC (rev 189884)
</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&, 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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2015-09-16 23:40:35 UTC (rev 189884)
</span><span class="lines">@@ -167,6 +167,7 @@
</span><span class="cx"> const DirectArguments_storage = (sizeof DirectArguments + SlotSize - 1) & ~(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 < 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 < 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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2015-09-16 23:40:35 UTC (rev 189884)
</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 "t1 * 2" 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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-09-16 23:40:35 UTC (rev 189884)
</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 "t1 * 2" 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 (189883 => 189884)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2015-09-16 23:25:22 UTC (rev 189883)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2015-09-16 23:40:35 UTC (rev 189884)
</span><span class="lines">@@ -59,13 +59,14 @@
</span><span class="cx"> int argumentCountIncludingThis = exec->argumentCountIncludingThis();
</span><span class="cx">
</span><span class="cx"> ASSERT(argumentCountIncludingThis < newCodeBlock->numParameters());
</span><del>- int missingArgumentCount = newCodeBlock->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->numParameters() + JSStack::CallFrameHeaderSize);
+ int paddedStackSpace = alignedFrameSizeForParameters - frameSize;
</ins><span class="cx">
</span><del>- if (!stack->ensureCapacityFor(exec->registers() - paddedStackSpace))
</del><ins>+ if (!stack->ensureCapacityFor(exec->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>
</div>
</body>
</html>