<!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>[160893] branches/jsCStack/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/160893">160893</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2013-12-19 19:33:24 -0800 (Thu, 19 Dec 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>FTL should be able to do call ICs
https://bugs.webkit.org/show_bug.cgi?id=125811

Reviewed by Geoffrey Garen.
        
Add Call/Construct inline caching to the FTL. That part is super easy.
        
But to make it possible for the FTL (which preserves system ABI callee-save registers
and expects calls to preserve them) to call into non-FTL JSC JITs (which don't preserve
any registers), we need to have some special thunks. That's most of the patch. In
particular, all JITCode's can now give you entrypoints with or without register
preservation and this may mean lazily creating wrapper thunks that preserve registers.
FTL OSR exit may involve exiting into a register restoration thunk and it may also
involve decoding FTL unwind info in order to figure out where registers were preserved.

* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/MacroAssemblerCodeRef.h:
(JSC::MacroAssemblerCodePtr::operator UnspecifiedBoolType*):
(JSC::MacroAssemblerCodeRef::operator UnspecifiedBoolType*):
* bytecode/CallLinkInfo.cpp:
(JSC::CallLinkInfo::unlink):
* bytecode/CallLinkInfo.h:
(JSC::CallLinkInfo::CallLinkInfo):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::setJITCode):
(JSC::CodeBlock::jitCode):
* dfg/DFGDriver.cpp:
(JSC::DFG::compileImpl):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
* dfg/DFGJITFinalizer.cpp:
(JSC::DFG::JITFinalizer::finalize):
(JSC::DFG::JITFinalizer::finalizeFunction):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLCompile.cpp:
(JSC::FTL::mmAllocateCodeSection):
(JSC::FTL::fixFunctionBasedOnStackMaps):
(JSC::FTL::compile):
* ftl/FTLInlineCacheSize.cpp:
(JSC::FTL::sizeOfCall):
* ftl/FTLInlineCacheSize.h:
* ftl/FTLIntrinsicRepository.h:
* ftl/FTLJITCode.cpp:
(JSC::FTL::JITCode::initializeArityCheckEntrypoint):
(JSC::FTL::JITCode::addressForCall):
(JSC::FTL::JITCode::executableAddressAtOffset):
(JSC::FTL::JITCode::dataAddressAtOffset):
(JSC::FTL::JITCode::offsetOf):
(JSC::FTL::JITCode::size):
(JSC::FTL::JITCode::contains):
* ftl/FTLJITCode.h:
* ftl/FTLJITFinalizer.cpp:
(JSC::FTL::JITFinalizer::finalizeFunction):
* ftl/FTLJSCall.cpp: Added.
(JSC::FTL::JSCall::JSCall):
(JSC::FTL::JSCall::emit):
(JSC::FTL::JSCall::link):
* ftl/FTLJSCall.h: Added.
(JSC::FTL::JSCall::stackmapID):
(JSC::FTL::JSCall::operator&lt;):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::lower):
(JSC::FTL::LowerDFGToLLVM::compileGetById):
(JSC::FTL::LowerDFGToLLVM::compilePutById):
(JSC::FTL::LowerDFGToLLVM::compileCallOrConstruct):
(JSC::FTL::LowerDFGToLLVM::callStackmap):
* ftl/FTLOSREntry.cpp:
(JSC::FTL::prepareOSREntry):
* ftl/FTLOSRExitCompiler.cpp:
(JSC::FTL::compileStub):
* ftl/FTLRegisterAtOffset.cpp: Added.
(JSC::FTL::RegisterAtOffset::dump):
* ftl/FTLRegisterAtOffset.h: Added.
(JSC::FTL::RegisterAtOffset::RegisterAtOffset):
(JSC::FTL::RegisterAtOffset::operator!):
(JSC::FTL::RegisterAtOffset::gpr):
(JSC::FTL::RegisterAtOffset::offset):
(JSC::FTL::RegisterAtOffset::operator==):
(JSC::FTL::RegisterAtOffset::operator&lt;):
(JSC::FTL::RegisterAtOffset::getGPR):
* ftl/FTLStackMaps.cpp:
(JSC::FTL::StackMaps::Record::parse):
* ftl/FTLState.cpp:
(JSC::FTL::State::State):
* ftl/FTLState.h:
* ftl/FTLUnwindInfo.cpp: Added.
(JSC::FTL::UnwindInfo::UnwindInfo):
(JSC::FTL::UnwindInfo::~UnwindInfo):
(JSC::FTL::UnwindInfo::parse):
(JSC::FTL::UnwindInfo::dump):
(JSC::FTL::UnwindInfo::find):
(JSC::FTL::UnwindInfo::indexOf):
* ftl/FTLUnwindInfo.h: Added.
* jit/JIT.cpp:
(JSC::JIT::privateCompile):
* jit/JIT.h:
* jit/JITCall.cpp:
(JSC::JIT::compileOpCallSlowCase):
* jit/JITCall32_64.cpp:
(JSC::JIT::compileOpCallSlowCase):
* jit/JITCode.cpp:
(JSC::JITCode::hostFunction):
(JSC::JITCodeWithCodeRef::JITCodeWithCodeRef):
(JSC::JITCodeWithCodeRef::~JITCodeWithCodeRef):
(JSC::JITCodeWithCodeRef::executableAddressAtOffset):
(JSC::JITCodeWithCodeRef::dataAddressAtOffset):
(JSC::JITCodeWithCodeRef::offsetOf):
(JSC::JITCodeWithCodeRef::size):
(JSC::JITCodeWithCodeRef::contains):
(JSC::DirectJITCode::DirectJITCode):
(JSC::DirectJITCode::~DirectJITCode):
(JSC::DirectJITCode::initializeCodeRef):
(JSC::DirectJITCode::ensureWrappers):
(JSC::DirectJITCode::addressForCall):
(JSC::NativeJITCode::NativeJITCode):
(JSC::NativeJITCode::~NativeJITCode):
(JSC::NativeJITCode::initializeCodeRef):
(JSC::NativeJITCode::addressForCall):
* jit/JITCode.h:
* jit/JITOperations.cpp:
* jit/JITOperations.h:
(JSC::operationLinkFor):
(JSC::operationVirtualFor):
(JSC::operationLinkClosureCallFor):
* jit/RegisterPreservationWrapperGenerator.cpp: Added.
(JSC::registersToPreserve):
(JSC::registerPreservationOffset):
(JSC::generateWrapper):
(JSC::generateRegisterRestoration):
(JSC::registerRestorationThunkGenerator):
* jit/RegisterPreservationWrapperGenerator.h: Added.
* jit/Repatch.cpp:
(JSC::linkSlowFor):
(JSC::linkFor):
(JSC::linkClosureCall):
* jit/Repatch.h:
* jit/ThunkGenerators.cpp:
(JSC::linkForThunkGenerator):
(JSC::linkCallThunkGenerator):
(JSC::linkConstructThunkGenerator):
(JSC::linkCallThatPreservesRegsThunkGenerator):
(JSC::linkConstructThatPreservesRegsThunkGenerator):
(JSC::linkClosureCallForThunkGenerator):
(JSC::linkClosureCallThunkGenerator):
(JSC::linkClosureCallThatPreservesRegsThunkGenerator):
(JSC::virtualForThunkGenerator):
(JSC::virtualCallThunkGenerator):
(JSC::virtualConstructThunkGenerator):
(JSC::virtualCallThatPreservesRegsThunkGenerator):
(JSC::virtualConstructThatPreservesRegsThunkGenerator):
* jit/ThunkGenerators.h:
(JSC::linkThunkGeneratorFor):
(JSC::linkClosureCallThunkGeneratorFor):
(JSC::virtualThunkGeneratorFor):
* llint/LLIntEntrypoint.cpp:
(JSC::LLInt::setFunctionEntrypoint):
(JSC::LLInt::setEvalEntrypoint):
(JSC::LLInt::setProgramEntrypoint):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::entryOSR):
(JSC::LLInt::setUpCall):
* llint/LowLevelInterpreter.asm:
* runtime/ArityCheckMode.h: Added.
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/Executable.cpp:
(JSC::ScriptExecutable::installCode):
* runtime/Executable.h:
(JSC::ExecutableBase::entrypointFor):
(JSC::ExecutableBase::offsetOfJITCodeWithArityCheckFor):
(JSC::NativeExecutable::finishCreation):
* runtime/RegisterPreservationMode.h: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchesjsCStackSourceJavaScriptCoreChangeLog">branches/jsCStack/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">branches/jsCStack/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreassemblerMacroAssemblerCodeRefh">branches/jsCStack/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorebytecodeCallLinkInfocpp">branches/jsCStack/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorebytecodeCallLinkInfoh">branches/jsCStack/Source/JavaScriptCore/bytecode/CallLinkInfo.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorebytecodeCodeBlockh">branches/jsCStack/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoredfgDFGDrivercpp">branches/jsCStack/Source/JavaScriptCore/dfg/DFGDriver.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoredfgDFGJITCompilercpp">branches/jsCStack/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoredfgDFGJITFinalizercpp">branches/jsCStack/Source/JavaScriptCore/dfg/DFGJITFinalizer.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">branches/jsCStack/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLCapabilitiescpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLCompilecpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLCompile.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLInlineCacheSizecpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLInlineCacheSizeh">branches/jsCStack/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLIntrinsicRepositoryh">branches/jsCStack/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLJITCodecpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITCode.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLJITCodeh">branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITCode.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLJITFinalizercpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLOSREntrycpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLOSREntry.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLOSRExith">branches/jsCStack/Source/JavaScriptCore/ftl/FTLOSRExit.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLOSRExitCompilercpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLStackMapscpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLStackMaps.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLStatecpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLState.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLStateh">branches/jsCStack/Source/JavaScriptCore/ftl/FTLState.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitJITcpp">branches/jsCStack/Source/JavaScriptCore/jit/JIT.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitJITh">branches/jsCStack/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitJITCallcpp">branches/jsCStack/Source/JavaScriptCore/jit/JITCall.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitJITCall32_64cpp">branches/jsCStack/Source/JavaScriptCore/jit/JITCall32_64.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitJITCodecpp">branches/jsCStack/Source/JavaScriptCore/jit/JITCode.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitJITCodeh">branches/jsCStack/Source/JavaScriptCore/jit/JITCode.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitJITOperationscpp">branches/jsCStack/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitJITOperationsh">branches/jsCStack/Source/JavaScriptCore/jit/JITOperations.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitRepatchcpp">branches/jsCStack/Source/JavaScriptCore/jit/Repatch.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitRepatchh">branches/jsCStack/Source/JavaScriptCore/jit/Repatch.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitThunkGeneratorscpp">branches/jsCStack/Source/JavaScriptCore/jit/ThunkGenerators.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitThunkGeneratorsh">branches/jsCStack/Source/JavaScriptCore/jit/ThunkGenerators.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorellintLLIntEntrypointcpp">branches/jsCStack/Source/JavaScriptCore/llint/LLIntEntrypoint.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorellintLLIntSlowPathscpp">branches/jsCStack/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreruntimeExecutablecpp">branches/jsCStack/Source/JavaScriptCore/runtime/Executable.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreruntimeExecutableh">branches/jsCStack/Source/JavaScriptCore/runtime/Executable.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLJSCallcpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLJSCall.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLJSCallh">branches/jsCStack/Source/JavaScriptCore/ftl/FTLJSCall.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLRegisterAtOffsetcpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLRegisterAtOffset.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLRegisterAtOffseth">branches/jsCStack/Source/JavaScriptCore/ftl/FTLRegisterAtOffset.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLUnwindInfocpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLUnwindInfo.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLUnwindInfoh">branches/jsCStack/Source/JavaScriptCore/ftl/FTLUnwindInfo.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitRegisterPreservationWrapperGeneratorcpp">branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitRegisterPreservationWrapperGeneratorh">branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreruntimeArityCheckModeh">branches/jsCStack/Source/JavaScriptCore/runtime/ArityCheckMode.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreruntimeRegisterPreservationModeh">branches/jsCStack/Source/JavaScriptCore/runtime/RegisterPreservationMode.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchesjsCStackSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ChangeLog (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ChangeLog        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/ChangeLog        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -1,3 +1,181 @@
</span><ins>+2013-12-18  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        FTL should be able to do call ICs
+        https://bugs.webkit.org/show_bug.cgi?id=125811
+
+        Reviewed by Geoffrey Garen.
+        
+        Add Call/Construct inline caching to the FTL. That part is super easy.
+        
+        But to make it possible for the FTL (which preserves system ABI callee-save registers
+        and expects calls to preserve them) to call into non-FTL JSC JITs (which don't preserve
+        any registers), we need to have some special thunks. That's most of the patch. In
+        particular, all JITCode's can now give you entrypoints with or without register
+        preservation and this may mean lazily creating wrapper thunks that preserve registers.
+        FTL OSR exit may involve exiting into a register restoration thunk and it may also
+        involve decoding FTL unwind info in order to figure out where registers were preserved.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * assembler/MacroAssemblerCodeRef.h:
+        (JSC::MacroAssemblerCodePtr::operator UnspecifiedBoolType*):
+        (JSC::MacroAssemblerCodeRef::operator UnspecifiedBoolType*):
+        * bytecode/CallLinkInfo.cpp:
+        (JSC::CallLinkInfo::unlink):
+        * bytecode/CallLinkInfo.h:
+        (JSC::CallLinkInfo::CallLinkInfo):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::setJITCode):
+        (JSC::CodeBlock::jitCode):
+        * dfg/DFGDriver.cpp:
+        (JSC::DFG::compileImpl):
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::link):
+        * dfg/DFGJITFinalizer.cpp:
+        (JSC::DFG::JITFinalizer::finalize):
+        (JSC::DFG::JITFinalizer::finalizeFunction):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::emitCall):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLCompile.cpp:
+        (JSC::FTL::mmAllocateCodeSection):
+        (JSC::FTL::fixFunctionBasedOnStackMaps):
+        (JSC::FTL::compile):
+        * ftl/FTLInlineCacheSize.cpp:
+        (JSC::FTL::sizeOfCall):
+        * ftl/FTLInlineCacheSize.h:
+        * ftl/FTLIntrinsicRepository.h:
+        * ftl/FTLJITCode.cpp:
+        (JSC::FTL::JITCode::initializeArityCheckEntrypoint):
+        (JSC::FTL::JITCode::addressForCall):
+        (JSC::FTL::JITCode::executableAddressAtOffset):
+        (JSC::FTL::JITCode::dataAddressAtOffset):
+        (JSC::FTL::JITCode::offsetOf):
+        (JSC::FTL::JITCode::size):
+        (JSC::FTL::JITCode::contains):
+        * ftl/FTLJITCode.h:
+        * ftl/FTLJITFinalizer.cpp:
+        (JSC::FTL::JITFinalizer::finalizeFunction):
+        * ftl/FTLJSCall.cpp: Added.
+        (JSC::FTL::JSCall::JSCall):
+        (JSC::FTL::JSCall::emit):
+        (JSC::FTL::JSCall::link):
+        * ftl/FTLJSCall.h: Added.
+        (JSC::FTL::JSCall::stackmapID):
+        (JSC::FTL::JSCall::operator&lt;):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::lower):
+        (JSC::FTL::LowerDFGToLLVM::compileGetById):
+        (JSC::FTL::LowerDFGToLLVM::compilePutById):
+        (JSC::FTL::LowerDFGToLLVM::compileCallOrConstruct):
+        (JSC::FTL::LowerDFGToLLVM::callStackmap):
+        * ftl/FTLOSREntry.cpp:
+        (JSC::FTL::prepareOSREntry):
+        * ftl/FTLOSRExitCompiler.cpp:
+        (JSC::FTL::compileStub):
+        * ftl/FTLRegisterAtOffset.cpp: Added.
+        (JSC::FTL::RegisterAtOffset::dump):
+        * ftl/FTLRegisterAtOffset.h: Added.
+        (JSC::FTL::RegisterAtOffset::RegisterAtOffset):
+        (JSC::FTL::RegisterAtOffset::operator!):
+        (JSC::FTL::RegisterAtOffset::gpr):
+        (JSC::FTL::RegisterAtOffset::offset):
+        (JSC::FTL::RegisterAtOffset::operator==):
+        (JSC::FTL::RegisterAtOffset::operator&lt;):
+        (JSC::FTL::RegisterAtOffset::getGPR):
+        * ftl/FTLStackMaps.cpp:
+        (JSC::FTL::StackMaps::Record::parse):
+        * ftl/FTLState.cpp:
+        (JSC::FTL::State::State):
+        * ftl/FTLState.h:
+        * ftl/FTLUnwindInfo.cpp: Added.
+        (JSC::FTL::UnwindInfo::UnwindInfo):
+        (JSC::FTL::UnwindInfo::~UnwindInfo):
+        (JSC::FTL::UnwindInfo::parse):
+        (JSC::FTL::UnwindInfo::dump):
+        (JSC::FTL::UnwindInfo::find):
+        (JSC::FTL::UnwindInfo::indexOf):
+        * ftl/FTLUnwindInfo.h: Added.
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompile):
+        * jit/JIT.h:
+        * jit/JITCall.cpp:
+        (JSC::JIT::compileOpCallSlowCase):
+        * jit/JITCall32_64.cpp:
+        (JSC::JIT::compileOpCallSlowCase):
+        * jit/JITCode.cpp:
+        (JSC::JITCode::hostFunction):
+        (JSC::JITCodeWithCodeRef::JITCodeWithCodeRef):
+        (JSC::JITCodeWithCodeRef::~JITCodeWithCodeRef):
+        (JSC::JITCodeWithCodeRef::executableAddressAtOffset):
+        (JSC::JITCodeWithCodeRef::dataAddressAtOffset):
+        (JSC::JITCodeWithCodeRef::offsetOf):
+        (JSC::JITCodeWithCodeRef::size):
+        (JSC::JITCodeWithCodeRef::contains):
+        (JSC::DirectJITCode::DirectJITCode):
+        (JSC::DirectJITCode::~DirectJITCode):
+        (JSC::DirectJITCode::initializeCodeRef):
+        (JSC::DirectJITCode::ensureWrappers):
+        (JSC::DirectJITCode::addressForCall):
+        (JSC::NativeJITCode::NativeJITCode):
+        (JSC::NativeJITCode::~NativeJITCode):
+        (JSC::NativeJITCode::initializeCodeRef):
+        (JSC::NativeJITCode::addressForCall):
+        * jit/JITCode.h:
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+        (JSC::operationLinkFor):
+        (JSC::operationVirtualFor):
+        (JSC::operationLinkClosureCallFor):
+        * jit/RegisterPreservationWrapperGenerator.cpp: Added.
+        (JSC::registersToPreserve):
+        (JSC::registerPreservationOffset):
+        (JSC::generateWrapper):
+        (JSC::generateRegisterRestoration):
+        (JSC::registerRestorationThunkGenerator):
+        * jit/RegisterPreservationWrapperGenerator.h: Added.
+        * jit/Repatch.cpp:
+        (JSC::linkSlowFor):
+        (JSC::linkFor):
+        (JSC::linkClosureCall):
+        * jit/Repatch.h:
+        * jit/ThunkGenerators.cpp:
+        (JSC::linkForThunkGenerator):
+        (JSC::linkCallThunkGenerator):
+        (JSC::linkConstructThunkGenerator):
+        (JSC::linkCallThatPreservesRegsThunkGenerator):
+        (JSC::linkConstructThatPreservesRegsThunkGenerator):
+        (JSC::linkClosureCallForThunkGenerator):
+        (JSC::linkClosureCallThunkGenerator):
+        (JSC::linkClosureCallThatPreservesRegsThunkGenerator):
+        (JSC::virtualForThunkGenerator):
+        (JSC::virtualCallThunkGenerator):
+        (JSC::virtualConstructThunkGenerator):
+        (JSC::virtualCallThatPreservesRegsThunkGenerator):
+        (JSC::virtualConstructThatPreservesRegsThunkGenerator):
+        * jit/ThunkGenerators.h:
+        (JSC::linkThunkGeneratorFor):
+        (JSC::linkClosureCallThunkGeneratorFor):
+        (JSC::virtualThunkGeneratorFor):
+        * llint/LLIntEntrypoint.cpp:
+        (JSC::LLInt::setFunctionEntrypoint):
+        (JSC::LLInt::setEvalEntrypoint):
+        (JSC::LLInt::setProgramEntrypoint):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::entryOSR):
+        (JSC::LLInt::setUpCall):
+        * llint/LowLevelInterpreter.asm:
+        * runtime/ArityCheckMode.h: Added.
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/Executable.cpp:
+        (JSC::ScriptExecutable::installCode):
+        * runtime/Executable.h:
+        (JSC::ExecutableBase::entrypointFor):
+        (JSC::ExecutableBase::offsetOfJITCodeWithArityCheckFor):
+        (JSC::NativeExecutable::finishCreation):
+        * runtime/RegisterPreservationMode.h: Added.
+
</ins><span class="cx"> 2013-12-19  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         CStack: The JIT does not need a slow path stack check.
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -267,6 +267,16 @@
</span><span class="cx">                 0F666ECD1836B37E00D017F1 /* DFGResurrectionForValidationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F666ECB1836B37E00D017F1 /* DFGResurrectionForValidationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F66E16B14DF3F1600B7B2E4 /* DFGAdjacencyList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F66E16C14DF3F1600B7B2E4 /* DFGEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F6B1CB5185FC9E900845D97 /* FTLJSCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6B1CB3185FC9E900845D97 /* FTLJSCall.cpp */; };
+                0F6B1CB6185FC9E900845D97 /* FTLJSCall.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6B1CB4185FC9E900845D97 /* FTLJSCall.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F6B1CB91861244C00845D97 /* ArityCheckMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6B1CB71861244C00845D97 /* ArityCheckMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F6B1CBA1861244C00845D97 /* RegisterPreservationMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6B1CB81861244C00845D97 /* RegisterPreservationMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F6B1CBD1861246A00845D97 /* RegisterPreservationWrapperGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6B1CBB1861246A00845D97 /* RegisterPreservationWrapperGenerator.cpp */; };
+                0F6B1CBE1861246A00845D97 /* RegisterPreservationWrapperGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6B1CBC1861246A00845D97 /* RegisterPreservationWrapperGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F6B1CC31862C47800845D97 /* FTLRegisterAtOffset.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6B1CBF1862C47800845D97 /* FTLRegisterAtOffset.cpp */; };
+                0F6B1CC41862C47800845D97 /* FTLRegisterAtOffset.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6B1CC01862C47800845D97 /* FTLRegisterAtOffset.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F6B1CC51862C47800845D97 /* FTLUnwindInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6B1CC11862C47800845D97 /* FTLUnwindInfo.cpp */; };
+                0F6B1CC61862C47800845D97 /* FTLUnwindInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6B1CC21862C47800845D97 /* FTLUnwindInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F7025A91714B0FA00382C0E /* DFGOSRExitCompilerCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7025A71714B0F800382C0E /* DFGOSRExitCompilerCommon.cpp */; };
</span><span class="cx">                 0F7025AA1714B0FC00382C0E /* DFGOSRExitCompilerCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7025A81714B0F800382C0E /* DFGOSRExitCompilerCommon.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F714CA416EA92F000F3EBEB /* DFGBackwardsPropagationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F714CA116EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.cpp */; };
</span><span class="lines">@@ -1579,6 +1589,16 @@
</span><span class="cx">                 0F666ECB1836B37E00D017F1 /* DFGResurrectionForValidationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGResurrectionForValidationPhase.h; path = dfg/DFGResurrectionForValidationPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAdjacencyList.h; path = dfg/DFGAdjacencyList.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGEdge.h; path = dfg/DFGEdge.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F6B1CB3185FC9E900845D97 /* FTLJSCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLJSCall.cpp; path = ftl/FTLJSCall.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F6B1CB4185FC9E900845D97 /* FTLJSCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLJSCall.h; path = ftl/FTLJSCall.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F6B1CB71861244C00845D97 /* ArityCheckMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArityCheckMode.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F6B1CB81861244C00845D97 /* RegisterPreservationMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterPreservationMode.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F6B1CBB1861246A00845D97 /* RegisterPreservationWrapperGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterPreservationWrapperGenerator.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F6B1CBC1861246A00845D97 /* RegisterPreservationWrapperGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterPreservationWrapperGenerator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F6B1CBF1862C47800845D97 /* FTLRegisterAtOffset.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLRegisterAtOffset.cpp; path = ftl/FTLRegisterAtOffset.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F6B1CC01862C47800845D97 /* FTLRegisterAtOffset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLRegisterAtOffset.h; path = ftl/FTLRegisterAtOffset.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F6B1CC11862C47800845D97 /* FTLUnwindInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLUnwindInfo.cpp; path = ftl/FTLUnwindInfo.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F6B1CC21862C47800845D97 /* FTLUnwindInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLUnwindInfo.h; path = ftl/FTLUnwindInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F7025A71714B0F800382C0E /* DFGOSRExitCompilerCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGOSRExitCompilerCommon.cpp; path = dfg/DFGOSRExitCompilerCommon.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F7025A81714B0F800382C0E /* DFGOSRExitCompilerCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSRExitCompilerCommon.h; path = dfg/DFGOSRExitCompilerCommon.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F714CA116EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGBackwardsPropagationPhase.cpp; path = dfg/DFGBackwardsPropagationPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -2858,6 +2878,8 @@
</span><span class="cx">                                 0FEA0A03170513DB00BB722C /* FTLJITCode.h */,
</span><span class="cx">                                 A78A977D179738D5009DF744 /* FTLJITFinalizer.cpp */,
</span><span class="cx">                                 A78A977E179738D5009DF744 /* FTLJITFinalizer.h */,
</span><ins>+                                0F6B1CB3185FC9E900845D97 /* FTLJSCall.cpp */,
+                                0F6B1CB4185FC9E900845D97 /* FTLJSCall.h */,
</ins><span class="cx">                                 0F8F2B93172E049E007DBDA5 /* FTLLink.cpp */,
</span><span class="cx">                                 0F8F2B94172E049E007DBDA5 /* FTLLink.h */,
</span><span class="cx">                                 0FCEFADD180738C000472CE4 /* FTLLocation.cpp */,
</span><span class="lines">@@ -2874,6 +2896,8 @@
</span><span class="cx">                                 0F235BCA17178E1C00690C7F /* FTLOSRExitCompiler.h */,
</span><span class="cx">                                 0FEA0A291709629600BB722C /* FTLOutput.cpp */,
</span><span class="cx">                                 0FEA0A06170513DB00BB722C /* FTLOutput.h */,
</span><ins>+                                0F6B1CBF1862C47800845D97 /* FTLRegisterAtOffset.cpp */,
+                                0F6B1CC01862C47800845D97 /* FTLRegisterAtOffset.h */,
</ins><span class="cx">                                 0FCEFAA91804C13E00472CE4 /* FTLSaveRestore.cpp */,
</span><span class="cx">                                 0FCEFAAA1804C13E00472CE4 /* FTLSaveRestore.h */,
</span><span class="cx">                                 0F25F1AA181635F300522F39 /* FTLSlowPathCall.cpp */,
</span><span class="lines">@@ -2888,6 +2912,8 @@
</span><span class="cx">                                 0F235BCB17178E1C00690C7F /* FTLThunks.cpp */,
</span><span class="cx">                                 0F235BCC17178E1C00690C7F /* FTLThunks.h */,
</span><span class="cx">                                 0FEA0A1B1708B00700BB722C /* FTLTypedPointer.h */,
</span><ins>+                                0F6B1CC11862C47800845D97 /* FTLUnwindInfo.cpp */,
+                                0F6B1CC21862C47800845D97 /* FTLUnwindInfo.h */,
</ins><span class="cx">                                 0F235BCD17178E1C00690C7F /* FTLValueFormat.cpp */,
</span><span class="cx">                                 0F235BCE17178E1C00690C7F /* FTLValueFormat.h */,
</span><span class="cx">                                 0FDB2CC8173DA51E007B3C1B /* FTLValueFromBlock.h */,
</span><span class="lines">@@ -3032,6 +3058,8 @@
</span><span class="cx">                                 0FC712E117CD878F008CC93C /* JITToDFGDeferredCompilationCallback.h */,
</span><span class="cx">                                 A76F54A213B28AAB00EF2BCE /* JITWriteBarrier.h */,
</span><span class="cx">                                 A76C51741182748D00715B05 /* JSInterfaceJIT.h */,
</span><ins>+                                0F6B1CBB1861246A00845D97 /* RegisterPreservationWrapperGenerator.cpp */,
+                                0F6B1CBC1861246A00845D97 /* RegisterPreservationWrapperGenerator.h */,
</ins><span class="cx">                                 0FC3141418146D7000033232 /* RegisterSet.cpp */,
</span><span class="cx">                                 0FC314101814559100033232 /* RegisterSet.h */,
</span><span class="cx">                                 0F24E54917EE274900ABB217 /* Repatch.cpp */,
</span><span class="lines">@@ -3369,6 +3397,7 @@
</span><span class="cx">                                 A76140C8182982CB00750624 /* ArgumentsIteratorConstructor.h */,
</span><span class="cx">                                 A76140C9182982CB00750624 /* ArgumentsIteratorPrototype.cpp */,
</span><span class="cx">                                 A76140CA182982CB00750624 /* ArgumentsIteratorPrototype.h */,
</span><ins>+                                0F6B1CB71861244C00845D97 /* ArityCheckMode.h */,
</ins><span class="cx">                                 A7A8AF2517ADB5F2005AB174 /* ArrayBuffer.cpp */,
</span><span class="cx">                                 A7A8AF2617ADB5F3005AB174 /* ArrayBuffer.h */,
</span><span class="cx">                                 0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */,
</span><span class="lines">@@ -3667,6 +3696,7 @@
</span><span class="cx">                                 F692A87C0255597D01FF60F7 /* RegExpObject.h */,
</span><span class="cx">                                 BCD202BF0E1706A7002C7E82 /* RegExpPrototype.cpp */,
</span><span class="cx">                                 BCD202C00E1706A7002C7E82 /* RegExpPrototype.h */,
</span><ins>+                                0F6B1CB81861244C00845D97 /* RegisterPreservationMode.h */,
</ins><span class="cx">                                 0FB7F39115ED8E3800F167B2 /* Reject.h */,
</span><span class="cx">                                 0F7700911402FF280078EB39 /* SamplingCounter.cpp */,
</span><span class="cx">                                 0F77008E1402FDD60078EB39 /* SamplingCounter.h */,
</span><span class="lines">@@ -4325,6 +4355,7 @@
</span><span class="cx">                                 C2EAA3FA149A835E00FCE112 /* CopiedSpace.h in Headers */,
</span><span class="cx">                                 C2C8D02D14A3C6E000578E65 /* CopiedSpaceInlines.h in Headers */,
</span><span class="cx">                                 0F5A52D017ADD717008ECB2D /* CopyToken.h in Headers */,
</span><ins>+                                0F6B1CC61862C47800845D97 /* FTLUnwindInfo.h in Headers */,
</ins><span class="cx">                                 C2239D1816262BDD005AC5FD /* CopyVisitor.h in Headers */,
</span><span class="cx">                                 C2239D1916262BDD005AC5FD /* CopyVisitorInlines.h in Headers */,
</span><span class="cx">                                 C218D1401655CFD50062BB81 /* CopyWorkList.h in Headers */,
</span><span class="lines">@@ -4395,6 +4426,7 @@
</span><span class="cx">                                 0FBC0AE81496C7C700D4FBDD /* DFGExitProfile.h in Headers */,
</span><span class="cx">                                 A78A9775179738B8009DF744 /* DFGFailedFinalizer.h in Headers */,
</span><span class="cx">                                 A78A9777179738B8009DF744 /* DFGFinalizer.h in Headers */,
</span><ins>+                                0F6B1CB6185FC9E900845D97 /* FTLJSCall.h in Headers */,
</ins><span class="cx">                                 0F2BDC16151C5D4F00CD8910 /* DFGFixupPhase.h in Headers */,
</span><span class="cx">                                 0F9D339717FFC4E60073C2BC /* DFGFlushedAt.h in Headers */,
</span><span class="cx">                                 A7D89CF817A0B8CC00773AD8 /* DFGFlushFormat.h in Headers */,
</span><span class="lines">@@ -4430,6 +4462,7 @@
</span><span class="cx">                                 0FD8A32617D51F5700CA2C40 /* DFGOSREntrypointCreationPhase.h in Headers */,
</span><span class="cx">                                 0FC0976A1468A6F700CF2442 /* DFGOSRExit.h in Headers */,
</span><span class="cx">                                 0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */,
</span><ins>+                                0F6B1CBA1861244C00845D97 /* RegisterPreservationMode.h in Headers */,
</ins><span class="cx">                                 0F235BEC17178E7300690C7F /* DFGOSRExitBase.h in Headers */,
</span><span class="cx">                                 A5BA15ED182340B400A82E69 /* RemoteInspectorXPCConnection.h in Headers */,
</span><span class="cx">                                 0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */,
</span><span class="lines">@@ -4588,6 +4621,7 @@
</span><span class="cx">                                 0F46808214BA572D00BFE272 /* JITExceptions.h in Headers */,
</span><span class="cx">                                 0FB14E1F18124ACE009B6B4D /* JITInlineCacheGenerator.h in Headers */,
</span><span class="cx">                                 86CC85A10EE79A4700288682 /* JITInlines.h in Headers */,
</span><ins>+                                0F6B1CBE1861246A00845D97 /* RegisterPreservationWrapperGenerator.h in Headers */,
</ins><span class="cx">                                 0F24E54D17EE274900ABB217 /* JITOperations.h in Headers */,
</span><span class="cx">                                 A790DD70182F499700588807 /* JSSetIterator.h in Headers */,
</span><span class="cx">                                 0F24E54E17EE274900ABB217 /* JITOperationWrappers.h in Headers */,
</span><span class="lines">@@ -4603,6 +4637,7 @@
</span><span class="cx">                                 0FC712E317CD8793008CC93C /* JITToDFGDeferredCompilationCallback.h in Headers */,
</span><span class="cx">                                 A76F54A313B28AAB00EF2BCE /* JITWriteBarrier.h in Headers */,
</span><span class="cx">                                 BC18C4160E16F5CD00B34460 /* JSActivation.h in Headers */,
</span><ins>+                                0F6B1CB91861244C00845D97 /* ArityCheckMode.h in Headers */,
</ins><span class="cx">                                 840480131021A1D9008E7F01 /* JSAPIValueWrapper.h in Headers */,
</span><span class="cx">                                 C2CF39C216E15A8100DD69BE /* JSAPIWrapperObject.h in Headers */,
</span><span class="cx">                                 A76140D2182982CB00750624 /* JSArgumentsIterator.h in Headers */,
</span><span class="lines">@@ -4655,6 +4690,7 @@
</span><span class="cx">                                 BC18C4230E16F5CD00B34460 /* JSLock.h in Headers */,
</span><span class="cx">                                 C25D709C16DE99F400FCA6BC /* JSManagedValue.h in Headers */,
</span><span class="cx">                                 A700874217CBE8EB00C3E643 /* JSMap.h in Headers */,
</span><ins>+                                0F6B1CC41862C47800845D97 /* FTLRegisterAtOffset.h in Headers */,
</ins><span class="cx">                                 14874AE415EBDE4A002E3587 /* JSNameScope.h in Headers */,
</span><span class="cx">                                 BC18C4240E16F5CD00B34460 /* JSObject.h in Headers */,
</span><span class="cx">                                 BC18C4250E16F5CD00B34460 /* JSObjectRef.h in Headers */,
</span><span class="lines">@@ -5495,6 +5531,7 @@
</span><span class="cx">                                 86880F4D14353B2100B08D42 /* DFGSpeculativeJIT64.cpp in Sources */,
</span><span class="cx">                                 A7D89CFF17A0B8CC00773AD8 /* DFGSSAConversionPhase.cpp in Sources */,
</span><span class="cx">                                 0F9FB4F417FCB91700CB67F8 /* DFGStackLayoutPhase.cpp in Sources */,
</span><ins>+                                0F6B1CBD1861246A00845D97 /* RegisterPreservationWrapperGenerator.cpp in Sources */,
</ins><span class="cx">                                 0FC097A1146B28CA00CF2442 /* DFGThunks.cpp in Sources */,
</span><span class="cx">                                 0FD8A32717D51F5700CA2C40 /* DFGTierUpCheckInjectionPhase.cpp in Sources */,
</span><span class="cx">                                 0FD8A32917D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.cpp in Sources */,
</span><span class="lines">@@ -5549,8 +5586,10 @@
</span><span class="cx">                                 0FCEFAAB1804C13E00472CE4 /* FTLSaveRestore.cpp in Sources */,
</span><span class="cx">                                 0F25F1B1181635F300522F39 /* FTLSlowPathCall.cpp in Sources */,
</span><span class="cx">                                 0F25F1B3181635F300522F39 /* FTLSlowPathCallKey.cpp in Sources */,
</span><ins>+                                0F6B1CC51862C47800845D97 /* FTLUnwindInfo.cpp in Sources */,
</ins><span class="cx">                                 0F9D339A1803ADB70073C2BC /* FTLStackMaps.cpp in Sources */,
</span><span class="cx">                                 0FEA0A161706BB9000BB722C /* FTLState.cpp in Sources */,
</span><ins>+                                0F6B1CB5185FC9E900845D97 /* FTLJSCall.cpp in Sources */,
</ins><span class="cx">                                 0F235BE117178E1C00690C7F /* FTLThunks.cpp in Sources */,
</span><span class="cx">                                 0F235BE317178E1C00690C7F /* FTLValueFormat.cpp in Sources */,
</span><span class="cx">                                 147F39CB107EC37600427A48 /* FunctionConstructor.cpp in Sources */,
</span><span class="lines">@@ -5737,6 +5776,7 @@
</span><span class="cx">                                 0F666ECC1836B37E00D017F1 /* DFGResurrectionForValidationPhase.cpp in Sources */,
</span><span class="cx">                                 0FB1058B1675483100F8AB6E /* ProfilerOSRExit.cpp in Sources */,
</span><span class="cx">                                 0FB1058D1675483700F8AB6E /* ProfilerOSRExitSite.cpp in Sources */,
</span><ins>+                                0F6B1CC31862C47800845D97 /* FTLRegisterAtOffset.cpp in Sources */,
</ins><span class="cx">                                 0F13912B16771C3A009CCB07 /* ProfilerProfiledBytecodes.cpp in Sources */,
</span><span class="cx">                                 A7FB60A4103F7DC20017A286 /* PropertyDescriptor.cpp in Sources */,
</span><span class="cx">                                 14469DE7107EC7E700650446 /* PropertyNameArray.cpp in Sources */,
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreassemblerMacroAssemblerCodeRefh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -309,9 +309,10 @@
</span><span class="cx">     void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return m_value; }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    bool operator!() const
</del><ins>+    typedef void* (MacroAssemblerCodePtr::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType*() const
</ins><span class="cx">     {
</span><del>-        return !m_value;
</del><ins>+        return !!m_value ? reinterpret_cast&lt;UnspecifiedBoolType*&gt;(1) : 0;
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     bool operator==(const MacroAssemblerCodePtr&amp; other) const
</span><span class="lines">@@ -434,7 +435,11 @@
</span><span class="cx">         return JSC::tryToDisassemble(m_codePtr, size(), prefix, WTF::dataFile());
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    bool operator!() const { return !m_codePtr; }
</del><ins>+    typedef void* (MacroAssemblerCodeRef::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType*() const
+    {
+        return !!m_codePtr ? reinterpret_cast&lt;UnspecifiedBoolType*&gt;(1) : 0;
+    }
</ins><span class="cx">     
</span><span class="cx">     void dump(PrintStream&amp; out) const
</span><span class="cx">     {
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorebytecodeCallLinkInfocpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -37,15 +37,15 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(isLinked());
</span><span class="cx">     
</span><ins>+    if (Options::showDisassembly())
+        dataLog(&quot;Unlinking call in &quot;, *repatchBuffer.codeBlock(), &quot; at &quot;, codeOrigin, &quot;\n&quot;);
+    
</ins><span class="cx">     repatchBuffer.revertJumpReplacementToBranchPtrWithPatch(RepatchBuffer::startOfBranchPtrWithPatchOnRegister(hotPathBegin), static_cast&lt;MacroAssembler::RegisterID&gt;(calleeGPR), 0);
</span><del>-    if (isDFG) {
-#if ENABLE(DFG_JIT)
-        repatchBuffer.relink(callReturnLocation, (callType == Construct ? vm.getCTIStub(linkConstructThunkGenerator) : vm.getCTIStub(linkCallThunkGenerator)).code());
-#else
-        RELEASE_ASSERT_NOT_REACHED();
-#endif
-    } else
-        repatchBuffer.relink(callReturnLocation, callType == Construct ? vm.getCTIStub(linkConstructThunkGenerator).code() : vm.getCTIStub(linkCallThunkGenerator).code());
</del><ins>+    repatchBuffer.relink(
+        callReturnLocation,
+        vm.getCTIStub(linkThunkGeneratorFor(
+            callType == Construct ? CodeForConstruct : CodeForCall,
+            repatchBuffer.codeBlock()-&gt;jitType() == JITCode::FTLJIT ? MustPreserveRegisters : RegisterPreservationNotRequired)).code());
</ins><span class="cx">     hasSeenShouldRepatch = false;
</span><span class="cx">     callee.clear();
</span><span class="cx">     stub.clear();
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorebytecodeCallLinkInfoh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/bytecode/CallLinkInfo.h (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -56,7 +56,6 @@
</span><span class="cx">         
</span><span class="cx">     CallLinkInfo()
</span><span class="cx">         : hasSeenShouldRepatch(false)
</span><del>-        , isDFG(false)
</del><span class="cx">         , hasSeenClosure(false)
</span><span class="cx">         , callType(None)
</span><span class="cx">     {
</span><span class="lines">@@ -80,7 +79,6 @@
</span><span class="cx">     WriteBarrier&lt;JSFunction&gt; lastSeenCallee;
</span><span class="cx">     RefPtr&lt;ClosureCallStubRoutine&gt; stub;
</span><span class="cx">     bool hasSeenShouldRepatch : 1;
</span><del>-    bool isDFG : 1;
</del><span class="cx">     bool hasSeenClosure : 1;
</span><span class="cx">     unsigned callType : 5; // CallType
</span><span class="cx">     unsigned calleeGPR : 8;
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/bytecode/CodeBlock.h (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/bytecode/CodeBlock.h        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/bytecode/CodeBlock.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -257,17 +257,15 @@
</span><span class="cx">     // Exactly equivalent to codeBlock-&gt;ownerExecutable()-&gt;newReplacementCodeBlockFor(codeBlock-&gt;specializationKind())
</span><span class="cx">     PassRefPtr&lt;CodeBlock&gt; newReplacement();
</span><span class="cx">     
</span><del>-    void setJITCode(PassRefPtr&lt;JITCode&gt; code, MacroAssemblerCodePtr codeWithArityCheck)
</del><ins>+    void setJITCode(PassRefPtr&lt;JITCode&gt; code)
</ins><span class="cx">     {
</span><span class="cx">         ASSERT(m_heap-&gt;isDeferred());
</span><span class="cx">         m_heap-&gt;reportExtraMemoryCost(code-&gt;size());
</span><span class="cx">         ConcurrentJITLocker locker(m_lock);
</span><span class="cx">         WTF::storeStoreFence(); // This is probably not needed because the lock will also do something similar, but it's good to be paranoid.
</span><span class="cx">         m_jitCode = code;
</span><del>-        m_jitCodeWithArityCheck = codeWithArityCheck;
</del><span class="cx">     }
</span><span class="cx">     PassRefPtr&lt;JITCode&gt; jitCode() { return m_jitCode; }
</span><del>-    MacroAssemblerCodePtr jitCodeWithArityCheck() { return m_jitCodeWithArityCheck; }
</del><span class="cx">     JITCode::JITType jitType() const
</span><span class="cx">     {
</span><span class="cx">         JITCode* jitCode = m_jitCode.get();
</span><span class="lines">@@ -1067,7 +1065,6 @@
</span><span class="cx">     SentinelLinkedList&lt;LLIntCallLinkInfo, BasicRawSentinelNode&lt;LLIntCallLinkInfo&gt;&gt; m_incomingLLIntCalls;
</span><span class="cx"> #endif
</span><span class="cx">     RefPtr&lt;JITCode&gt; m_jitCode;
</span><del>-    MacroAssemblerCodePtr m_jitCodeWithArityCheck;
</del><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     Bag&lt;StructureStubInfo&gt; m_stubInfos;
</span><span class="cx">     Vector&lt;ByValInfo&gt; m_byValInfos;
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoredfgDFGDrivercpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/dfg/DFGDriver.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/dfg/DFGDriver.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/dfg/DFGDriver.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -80,11 +80,19 @@
</span><span class="cx">     // make sure that all JIT code generation does finalization on the main thread.
</span><span class="cx">     vm.getCTIStub(osrExitGenerationThunkGenerator);
</span><span class="cx">     vm.getCTIStub(throwExceptionFromCallSlowPathGenerator);
</span><del>-    vm.getCTIStub(linkCallThunkGenerator);
-    vm.getCTIStub(linkConstructThunkGenerator);
-    vm.getCTIStub(linkClosureCallThunkGenerator);
-    vm.getCTIStub(virtualCallThunkGenerator);
-    vm.getCTIStub(virtualConstructThunkGenerator);
</del><ins>+    if (mode == DFGMode) {
+        vm.getCTIStub(linkCallThunkGenerator);
+        vm.getCTIStub(linkConstructThunkGenerator);
+        vm.getCTIStub(linkClosureCallThunkGenerator);
+        vm.getCTIStub(virtualCallThunkGenerator);
+        vm.getCTIStub(virtualConstructThunkGenerator);
+    } else {
+        vm.getCTIStub(linkCallThatPreservesRegsThunkGenerator);
+        vm.getCTIStub(linkConstructThatPreservesRegsThunkGenerator);
+        vm.getCTIStub(linkClosureCallThatPreservesRegsThunkGenerator);
+        vm.getCTIStub(virtualCallThatPreservesRegsThunkGenerator);
+        vm.getCTIStub(virtualConstructThatPreservesRegsThunkGenerator);
+    }
</ins><span class="cx">     
</span><span class="cx">     RefPtr&lt;Plan&gt; plan = adoptRef(
</span><span class="cx">         new Plan(codeBlock, mode, osrEntryBytecodeIndex, mustHandleValues));
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoredfgDFGJITCompilercpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -230,9 +230,11 @@
</span><span class="cx">     for (unsigned i = 0; i &lt; m_jsCalls.size(); ++i) {
</span><span class="cx">         CallLinkInfo&amp; info = m_codeBlock-&gt;callLinkInfo(i);
</span><span class="cx">         info.callType = m_jsCalls[i].m_callType;
</span><del>-        info.isDFG = true;
</del><span class="cx">         info.codeOrigin = m_jsCalls[i].m_codeOrigin;
</span><del>-        linkBuffer.link(m_jsCalls[i].m_slowCall, FunctionPtr((m_vm-&gt;getCTIStub(info.callType == CallLinkInfo::Construct ? linkConstructThunkGenerator : linkCallThunkGenerator)).code().executableAddress()));
</del><ins>+        ThunkGenerator generator = linkThunkGeneratorFor(
+            info.callType == CallLinkInfo::Construct ? CodeForConstruct : CodeForCall,
+            RegisterPreservationNotRequired);
+        linkBuffer.link(m_jsCalls[i].m_slowCall, FunctionPtr(m_vm-&gt;getCTIStub(generator).code().executableAddress()));
</ins><span class="cx">         info.callReturnLocation = linkBuffer.locationOfNearCall(m_jsCalls[i].m_slowCall);
</span><span class="cx">         info.hotPathBegin = linkBuffer.locationOf(m_jsCalls[i].m_targetToCheck);
</span><span class="cx">         info.hotPathOther = linkBuffer.locationOfNearCall(m_jsCalls[i].m_fastCall);
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoredfgDFGJITFinalizercpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/dfg/DFGJITFinalizer.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/dfg/DFGJITFinalizer.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/dfg/DFGJITFinalizer.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -48,8 +48,9 @@
</span><span class="cx"> 
</span><span class="cx"> bool JITFinalizer::finalize()
</span><span class="cx"> {
</span><del>-    m_jitCode-&gt;initializeCodeRef(m_linkBuffer-&gt;finalizeCodeWithoutDisassembly());
-    m_plan.codeBlock-&gt;setJITCode(m_jitCode, MacroAssemblerCodePtr());
</del><ins>+    m_jitCode-&gt;initializeCodeRef(
+        m_linkBuffer-&gt;finalizeCodeWithoutDisassembly(), MacroAssemblerCodePtr());
+    m_plan.codeBlock-&gt;setJITCode(m_jitCode);
</ins><span class="cx">     
</span><span class="cx">     finalizeCommon();
</span><span class="cx">     
</span><span class="lines">@@ -59,8 +60,9 @@
</span><span class="cx"> bool JITFinalizer::finalizeFunction()
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(!m_withArityCheck.isEmptyValue());
</span><del>-    m_jitCode-&gt;initializeCodeRef(m_linkBuffer-&gt;finalizeCodeWithoutDisassembly());
-    m_plan.codeBlock-&gt;setJITCode(m_jitCode, m_withArityCheck);
</del><ins>+    m_jitCode-&gt;initializeCodeRef(
+        m_linkBuffer-&gt;finalizeCodeWithoutDisassembly(), m_withArityCheck);
+    m_plan.codeBlock-&gt;setJITCode(m_jitCode);
</ins><span class="cx">     
</span><span class="cx">     finalizeCommon();
</span><span class="cx">     
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -704,11 +704,11 @@
</span><span class="cx">     GPRReg resultGPR = result.gpr();
</span><span class="cx"> 
</span><span class="cx">     JITCompiler::DataLabelPtr targetToCheck;
</span><del>-    JITCompiler::JumpList slowPath;
</del><ins>+    JITCompiler::Jump slowPath;
</ins><span class="cx"> 
</span><span class="cx">     m_jit.emitStoreCodeOrigin(node-&gt;codeOrigin);
</span><span class="cx">     
</span><del>-    slowPath.append(m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(0)));
</del><ins>+    slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(0));
</ins><span class="cx"> 
</span><span class="cx">     m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scope)), resultGPR);
</span><span class="cx">     m_jit.store64(resultGPR, calleeFrameSlot(JSStack::ScopeChain));
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -103,6 +103,8 @@
</span><span class="cx">     case FunctionReentryWatchpoint:
</span><span class="cx">     case VariableWatchpoint:
</span><span class="cx">     case NotifyWrite:
</span><ins>+    case Call:
+    case Construct:
</ins><span class="cx">         // These are OK.
</span><span class="cx">         break;
</span><span class="cx">     case GetById:
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLCompilecpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLCompile.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLCompile.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLCompile.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -37,6 +37,7 @@
</span><span class="cx"> #include &quot;FTLInlineCacheSize.h&quot;
</span><span class="cx"> #include &quot;FTLJITCode.h&quot;
</span><span class="cx"> #include &quot;FTLThunks.h&quot;
</span><ins>+#include &quot;FTLUnwindInfo.h&quot;
</ins><span class="cx"> #include &quot;JITStubs.h&quot;
</span><span class="cx"> #include &quot;LLVMAPI.h&quot;
</span><span class="cx"> #include &quot;LinkBuffer.h&quot;
</span><span class="lines">@@ -49,7 +50,6 @@
</span><span class="cx"> static uint8_t* mmAllocateCodeSection(
</span><span class="cx">     void* opaqueState, uintptr_t size, unsigned alignment, unsigned, const char* sectionName)
</span><span class="cx"> {
</span><del>-    
</del><span class="cx">     State&amp; state = *static_cast&lt;State*&gt;(opaqueState);
</span><span class="cx">     
</span><span class="cx">     RELEASE_ASSERT(alignment &lt;= jitAllocationGranule);
</span><span class="lines">@@ -58,6 +58,11 @@
</span><span class="cx">         state.graph.m_vm.executableAllocator.allocate(
</span><span class="cx">             state.graph.m_vm, size, state.graph.m_codeBlock, JITCompilationMustSucceed);
</span><span class="cx">     
</span><ins>+    if (!strcmp(sectionName, &quot;__compact_unwind&quot;)) {
+        state.compactUnwind = result-&gt;start();
+        state.compactUnwindSize = result-&gt;sizeInBytes();
+    }
+    
</ins><span class="cx">     state.jitCode-&gt;addHandle(result);
</span><span class="cx">     state.codeSectionNames.append(sectionName);
</span><span class="cx">     
</span><span class="lines">@@ -299,6 +304,44 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    // Handling JS calls is weird: we need to ensure that we sort them by the PC in LLVM
+    // generated code. That implies first pruning the ones that LLVM didn't generate.
+    for (unsigned i = 0; i &lt; state.jsCalls.size(); ++i) {
+        JSCall&amp; call = state.jsCalls[i];
+        
+        StackMaps::RecordMap::iterator iter = recordMap.find(call.stackmapID());
+        if (iter == recordMap.end()) {
+            // It was optimized out. Prune it.
+            call = state.jsCalls.last();
+            state.jsCalls.removeLast();
+            i--;
+            continue;
+        }
+        
+        call.m_instructionOffset = iter-&gt;value.instructionOffset;
+    }
+    
+    std::sort(state.jsCalls.begin(), state.jsCalls.end());
+    
+    codeBlock-&gt;setNumberOfCallLinkInfos(state.jsCalls.size());
+    for (unsigned i = state.jsCalls.size(); i--;) {
+        JSCall&amp; call = state.jsCalls[i];
+
+        CCallHelpers fastPathJIT(&amp;vm, codeBlock);
+        call.emit(fastPathJIT);
+        
+        char* startOfIC = bitwise_cast&lt;char*&gt;(generatedFunction) + call.m_instructionOffset;
+        
+        LinkBuffer linkBuffer(vm, &amp;fastPathJIT, startOfIC, sizeOfCall());
+        RELEASE_ASSERT(linkBuffer.isValid());
+        
+        MacroAssembler::AssemblerType_T::fillNops(
+            startOfIC + linkBuffer.size(), sizeOfCall() - linkBuffer.size());
+        
+        CallLinkInfo&amp; info = codeBlock-&gt;callLinkInfo(i);
+        call.link(vm, linkBuffer, info);
+    }
+    
</ins><span class="cx">     RepatchBuffer repatchBuffer(codeBlock);
</span><span class="cx">     
</span><span class="cx">     for (unsigned exitIndex = jitCode-&gt;osrExit.size(); exitIndex--;) {
</span><span class="lines">@@ -398,7 +441,7 @@
</span><span class="cx">             ExecutableMemoryHandle* handle = state.jitCode-&gt;handles()[i].get();
</span><span class="cx">             dataLog(
</span><span class="cx">                 &quot;Generated LLVM code for &quot;,
</span><del>-                CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::DFGJIT),
</del><ins>+                CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT),
</ins><span class="cx">                 &quot; #&quot;, i, &quot;, &quot;, state.codeSectionNames[i], &quot;:\n&quot;);
</span><span class="cx">             disassemble(
</span><span class="cx">                 MacroAssemblerCodePtr(handle-&gt;start()), handle-&gt;sizeInBytes(),
</span><span class="lines">@@ -409,17 +452,21 @@
</span><span class="cx">             const RefCountedArray&lt;LSectionWord&gt;&amp; section = state.jitCode-&gt;dataSections()[i];
</span><span class="cx">             dataLog(
</span><span class="cx">                 &quot;Generated LLVM data section for &quot;,
</span><del>-                CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::DFGJIT),
</del><ins>+                CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT),
</ins><span class="cx">                 &quot; #&quot;, i, &quot;, &quot;, state.dataSectionNames[i], &quot;:\n&quot;);
</span><span class="cx">             dumpDataSection(section, &quot;    &quot;);
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    state.jitCode-&gt;unwindInfo.parse(state.compactUnwind, state.compactUnwindSize);
+    if (DFG::shouldShowDisassembly())
+        dataLog(&quot;Unwind info for &quot;, CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT), &quot;:\n    &quot;, state.jitCode-&gt;unwindInfo, &quot;\n&quot;);
+    
</ins><span class="cx">     if (state.stackmapsSection.size()) {
</span><span class="cx">         if (shouldShowDisassembly()) {
</span><span class="cx">             dataLog(
</span><span class="cx">                 &quot;Generated LLVM stackmaps section for &quot;,
</span><del>-                CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::DFGJIT), &quot;:\n&quot;);
</del><ins>+                CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT), &quot;:\n&quot;);
</ins><span class="cx">             dataLog(&quot;    Raw data:\n&quot;);
</span><span class="cx">             dumpDataSection(state.stackmapsSection, &quot;    &quot;);
</span><span class="cx">         }
</span><span class="lines">@@ -446,7 +493,7 @@
</span><span class="cx">                 ExecutableMemoryHandle* handle = state.jitCode-&gt;handles()[i].get();
</span><span class="cx">                 dataLog(
</span><span class="cx">                     &quot;Generated LLVM code after stackmap-based fix-up for &quot;,
</span><del>-                    CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::DFGJIT),
</del><ins>+                    CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT),
</ins><span class="cx">                     &quot; #&quot;, i, &quot;, &quot;, state.codeSectionNames[i], &quot;:\n&quot;);
</span><span class="cx">                 disassemble(
</span><span class="cx">                     MacroAssemblerCodePtr(handle-&gt;start()), handle-&gt;sizeInBytes(),
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLInlineCacheSizecpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -47,6 +47,11 @@
</span><span class="cx">     return 32;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+size_t sizeOfCall()
+{
+    return 43;
+}
+
</ins><span class="cx"> } } // namespace JSC::FTL
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(FTL_JIT)
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLInlineCacheSizeh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> 
</span><span class="cx"> size_t sizeOfGetById();
</span><span class="cx"> size_t sizeOfPutById();
</span><ins>+size_t sizeOfCall();
</ins><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::FTL
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLIntrinsicRepositoryh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -43,9 +43,9 @@
</span><span class="cx">     macro(frameAddress, &quot;llvm.frameaddress&quot;, functionType(pointerType(int8), int32)) \
</span><span class="cx">     macro(mulWithOverflow32, &quot;llvm.smul.with.overflow.i32&quot;, functionType(structType(m_context, int32, boolean), int32, int32)) \
</span><span class="cx">     macro(mulWithOverflow64, &quot;llvm.smul.with.overflow.i64&quot;, functionType(structType(m_context, int64, boolean), int64, int64)) \
</span><del>-    macro(patchpointInt64, &quot;llvm.experimental.patchpoint.i64&quot;, functionType(int64, int32, int32, ref8, int32, Variadic)) \
-    macro(patchpointVoid, &quot;llvm.experimental.patchpoint.void&quot;, functionType(voidType, int32, int32, ref8, int32, Variadic)) \
-    macro(stackmap, &quot;llvm.experimental.stackmap&quot;, functionType(voidType, int32, int32, Variadic)) \
</del><ins>+    macro(patchpointInt64, &quot;llvm.experimental.patchpoint.i64&quot;, functionType(int64, int64, int32, ref8, int32, Variadic)) \
+    macro(patchpointVoid, &quot;llvm.experimental.patchpoint.void&quot;, functionType(voidType, int64, int32, ref8, int32, Variadic)) \
+    macro(stackmap, &quot;llvm.experimental.stackmap&quot;, functionType(voidType, int64, int32, Variadic)) \
</ins><span class="cx">     macro(subWithOverflow32, &quot;llvm.ssub.with.overflow.i32&quot;, functionType(structType(m_context, int32, boolean), int32, int32)) \
</span><span class="cx">     macro(subWithOverflow64, &quot;llvm.ssub.with.overflow.i64&quot;, functionType(structType(m_context, int64, boolean), int64, int64)) \
</span><span class="cx">     macro(trap, &quot;llvm.trap&quot;, functionType(voidType)) \
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLJITCodecpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITCode.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITCode.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITCode.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -54,9 +54,9 @@
</span><span class="cx">     m_dataSections.append(dataSection);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JITCode::initializeEntrypoint(CodeRef entrypoint)
</del><ins>+void JITCode::initializeArityCheckEntrypoint(CodeRef entrypoint)
</ins><span class="cx"> {
</span><del>-    m_entrypoint = entrypoint;
</del><ins>+    m_arityCheckEntrypoint = entrypoint;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JITCode::initializeAddressForCall(CodePtr address)
</span><span class="lines">@@ -64,21 +64,25 @@
</span><span class="cx">     m_addressForCall = address;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JITCode::CodePtr JITCode::addressForCall()
</del><ins>+JITCode::CodePtr JITCode::addressForCall(VM&amp;, ExecutableBase*, ArityCheckMode arityCheck, RegisterPreservationMode)
</ins><span class="cx"> {
</span><del>-    return m_addressForCall;
</del><ins>+    switch (arityCheck) {
+    case ArityCheckNotRequired:
+        return m_addressForCall;
+    case MustCheckArity:
+        return m_arityCheckEntrypoint.code();
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return CodePtr();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void* JITCode::executableAddressAtOffset(size_t offset)
</span><span class="cx"> {
</span><del>-    RELEASE_ASSERT(m_entrypoint);
</del><span class="cx">     return reinterpret_cast&lt;char*&gt;(m_addressForCall.executableAddress()) + offset;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void* JITCode::dataAddressAtOffset(size_t)
</span><span class="cx"> {
</span><del>-    RELEASE_ASSERT(m_entrypoint);
-
</del><span class="cx">     // We can't patch FTL code, yet. Even if we did, it's not clear that we would do so
</span><span class="cx">     // through this API.
</span><span class="cx">     RELEASE_ASSERT_NOT_REACHED();
</span><span class="lines">@@ -87,8 +91,6 @@
</span><span class="cx"> 
</span><span class="cx"> unsigned JITCode::offsetOf(void*)
</span><span class="cx"> {
</span><del>-    RELEASE_ASSERT(m_entrypoint);
-
</del><span class="cx">     // We currently don't have visibility into the FTL code.
</span><span class="cx">     RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">     return 0;
</span><span class="lines">@@ -96,8 +98,6 @@
</span><span class="cx"> 
</span><span class="cx"> size_t JITCode::size()
</span><span class="cx"> {
</span><del>-    RELEASE_ASSERT(m_entrypoint);
-
</del><span class="cx">     // We don't know the size of FTL code, yet. Make a wild guess. This is mostly used for
</span><span class="cx">     // GC load estimates.
</span><span class="cx">     return 1000;
</span><span class="lines">@@ -105,8 +105,6 @@
</span><span class="cx"> 
</span><span class="cx"> bool JITCode::contains(void*)
</span><span class="cx"> {
</span><del>-    RELEASE_ASSERT(m_entrypoint);
-
</del><span class="cx">     // We have no idea what addresses the FTL code contains, yet.
</span><span class="cx">     RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">     return false;
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLJITCodeh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITCode.h (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITCode.h        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITCode.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #include &quot;DFGCommonData.h&quot;
</span><span class="cx"> #include &quot;FTLOSRExit.h&quot;
</span><span class="cx"> #include &quot;FTLStackMaps.h&quot;
</span><ins>+#include &quot;FTLUnwindInfo.h&quot;
</ins><span class="cx"> #include &quot;JITCode.h&quot;
</span><span class="cx"> #include &quot;LLVMAPI.h&quot;
</span><span class="cx"> #include &lt;wtf/RefCountedArray.h&gt;
</span><span class="lines">@@ -46,17 +47,17 @@
</span><span class="cx">     JITCode();
</span><span class="cx">     ~JITCode();
</span><span class="cx">     
</span><del>-    CodePtr addressForCall();
-    void* executableAddressAtOffset(size_t offset);
-    void* dataAddressAtOffset(size_t offset);
-    unsigned offsetOf(void* pointerIntoCode);
-    size_t size();
-    bool contains(void*);
</del><ins>+    CodePtr addressForCall(VM&amp;, ExecutableBase*, ArityCheckMode, RegisterPreservationMode) OVERRIDE;
+    void* executableAddressAtOffset(size_t offset) OVERRIDE;
+    void* dataAddressAtOffset(size_t offset) OVERRIDE;
+    unsigned offsetOf(void* pointerIntoCode) OVERRIDE;
+    size_t size() OVERRIDE;
+    bool contains(void*) OVERRIDE;
</ins><span class="cx">     
</span><span class="cx">     void initializeExitThunks(CodeRef);
</span><span class="cx">     void addHandle(PassRefPtr&lt;ExecutableMemoryHandle&gt;);
</span><span class="cx">     void addDataSection(RefCountedArray&lt;LSectionWord&gt;);
</span><del>-    void initializeEntrypoint(CodeRef);
</del><ins>+    void initializeArityCheckEntrypoint(CodeRef);
</ins><span class="cx">     void initializeAddressForCall(CodePtr);
</span><span class="cx">     
</span><span class="cx">     const Vector&lt;RefPtr&lt;ExecutableMemoryHandle&gt;&gt;&amp; handles() const { return m_handles; }
</span><span class="lines">@@ -70,12 +71,13 @@
</span><span class="cx">     DFG::CommonData common;
</span><span class="cx">     SegmentedVector&lt;OSRExit, 8&gt; osrExit;
</span><span class="cx">     StackMaps stackmaps;
</span><ins>+    UnwindInfo unwindInfo;
</ins><span class="cx">     
</span><span class="cx"> private:
</span><span class="cx">     Vector&lt;RefCountedArray&lt;LSectionWord&gt;&gt; m_dataSections;
</span><span class="cx">     Vector&lt;RefPtr&lt;ExecutableMemoryHandle&gt;&gt; m_handles;
</span><span class="cx">     CodePtr m_addressForCall;
</span><del>-    CodeRef m_entrypoint;
</del><ins>+    CodeRef m_arityCheckEntrypoint;
</ins><span class="cx">     CodeRef m_exitThunks;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLJITFinalizercpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -103,12 +103,12 @@
</span><span class="cx">     MacroAssemblerCodePtr withArityCheck;
</span><span class="cx">     if (arityCheck.isSet())
</span><span class="cx">         withArityCheck = entrypointLinkBuffer-&gt;locationOf(arityCheck);
</span><del>-    jitCode-&gt;initializeEntrypoint(
</del><ins>+    jitCode-&gt;initializeArityCheckEntrypoint(
</ins><span class="cx">         FINALIZE_DFG_CODE(
</span><span class="cx">             *entrypointLinkBuffer,
</span><span class="cx">             (&quot;FTL entrypoint thunk for %s with LLVM generated code at %p&quot;, toCString(CodeBlockWithJITType(m_plan.codeBlock.get(), JITCode::FTLJIT)).data(), function)));
</span><span class="cx">     
</span><del>-    m_plan.codeBlock-&gt;setJITCode(jitCode, withArityCheck);
</del><ins>+    m_plan.codeBlock-&gt;setJITCode(jitCode);
</ins><span class="cx">     
</span><span class="cx">     return true;
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLJSCallcpp"></a>
<div class="addfile"><h4>Added: branches/jsCStack/Source/JavaScriptCore/ftl/FTLJSCall.cpp (0 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLJSCall.cpp                                (rev 0)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLJSCall.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -0,0 +1,85 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;FTLJSCall.h&quot;
+
+#if ENABLE(FTL_JIT)
+
+namespace JSC { namespace FTL {
+
+JSCall::JSCall(unsigned stackmapID, CallLinkInfo::CallType callType, CodeOrigin codeOrigin)
+    : m_stackmapID(stackmapID)
+    , m_callType(callType)
+    , m_codeOrigin(codeOrigin)
+    , m_instructionOffset(0)
+{
+}
+
+void JSCall::emit(CCallHelpers&amp; jit)
+{
+    CCallHelpers::Jump slowPath = jit.branchPtrWithPatch(
+        CCallHelpers::NotEqual, GPRInfo::regT0, m_targetToCheck,
+        CCallHelpers::TrustedImmPtr(0));
+    
+    jit.loadPtr(
+        CCallHelpers::Address(GPRInfo::regT0, JSFunction::offsetOfScopeChain()),
+        GPRInfo::regT1);
+    jit.store64(
+        GPRInfo::regT1,
+        CCallHelpers::Address(
+            CCallHelpers::stackPointerRegister,
+            sizeof(Register) * (JSStack::ScopeChain - JSStack::CallerFrameAndPCSize)));
+    
+    m_fastCall = jit.nearCall();
+    CCallHelpers::Jump done = jit.jump();
+    
+    slowPath.link(&amp;jit);
+    m_slowCall = jit.nearCall();
+    
+    done.link(&amp;jit);
+}
+
+void JSCall::link(VM&amp; vm, LinkBuffer&amp; linkBuffer, CallLinkInfo&amp; callInfo)
+{
+    ThunkGenerator generator = linkThunkGeneratorFor(
+        m_callType == CallLinkInfo::Construct ? CodeForConstruct : CodeForCall,
+        MustPreserveRegisters);
+    
+    linkBuffer.link(
+        m_slowCall, FunctionPtr(vm.getCTIStub(generator).code().executableAddress()));
+    
+    callInfo.callType = m_callType;
+    callInfo.codeOrigin = m_codeOrigin;
+    callInfo.callReturnLocation = linkBuffer.locationOfNearCall(m_slowCall);
+    callInfo.hotPathBegin = linkBuffer.locationOf(m_targetToCheck);
+    callInfo.hotPathOther = linkBuffer.locationOfNearCall(m_fastCall);
+    callInfo.calleeGPR = GPRInfo::regT0;
+}
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT)
+
</ins></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLJSCallh"></a>
<div class="addfile"><h4>Added: branches/jsCStack/Source/JavaScriptCore/ftl/FTLJSCall.h (0 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLJSCall.h                                (rev 0)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLJSCall.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -0,0 +1,69 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef FTLJSCall_h
+#define FTLJSCall_h
+
+#if ENABLE(FTL_JIT)
+
+#include &quot;CCallHelpers.h&quot;
+#include &quot;CallLinkInfo.h&quot;
+#include &quot;CodeOrigin.h&quot;
+#include &quot;LinkBuffer.h&quot;
+
+namespace JSC { namespace FTL {
+
+class JSCall {
+public:
+    JSCall(unsigned stackmapID, CallLinkInfo::CallType, CodeOrigin);
+    
+    void emit(CCallHelpers&amp;);
+    void link(VM&amp;, LinkBuffer&amp;, CallLinkInfo&amp;);
+    
+    unsigned stackmapID() const { return m_stackmapID; }
+    
+    bool operator&lt;(const JSCall&amp; other) const
+    {
+        return m_instructionOffset &lt; other.m_instructionOffset;
+    }
+    
+private:
+    unsigned m_stackmapID;
+    CallLinkInfo::CallType m_callType;
+    CodeOrigin m_codeOrigin;
+    CCallHelpers::DataLabelPtr m_targetToCheck;
+    CCallHelpers::Call m_fastCall;
+    CCallHelpers::Call m_slowCall;
+
+public:
+    uint32_t m_instructionOffset;
+};
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT)
+
+#endif // FTLJSCall_h
+
</ins></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -123,7 +123,7 @@
</span><span class="cx">         
</span><span class="cx">         m_ftlState.capturedStackmapID = m_stackmapIDs++;
</span><span class="cx">         m_out.call(
</span><del>-            m_out.stackmapIntrinsic(), m_out.constInt32(m_ftlState.capturedStackmapID),
</del><ins>+            m_out.stackmapIntrinsic(), m_out.constInt64(m_ftlState.capturedStackmapID),
</ins><span class="cx">             m_out.int32Zero, capturedAlloca);
</span><span class="cx">         
</span><span class="cx">         m_callFrame = m_out.ptrToInt(
</span><span class="lines">@@ -1297,7 +1297,7 @@
</span><span class="cx">         
</span><span class="cx">         LValue call = m_out.call(
</span><span class="cx">             m_out.patchpointInt64Intrinsic(),
</span><del>-            m_out.constInt32(stackmapID), m_out.constInt32(sizeOfGetById()),
</del><ins>+            m_out.constInt64(stackmapID), m_out.constInt32(sizeOfGetById()),
</ins><span class="cx">             constNull(m_out.ref8), m_out.constInt32(1), base);
</span><span class="cx">         setInstructionCallingConvention(call, LLVMAnyRegCallConv);
</span><span class="cx">         setJSValue(call);
</span><span class="lines">@@ -1322,7 +1322,7 @@
</span><span class="cx">         
</span><span class="cx">         LValue call = m_out.call(
</span><span class="cx">             m_out.patchpointVoidIntrinsic(),
</span><del>-            m_out.constInt32(stackmapID), m_out.constInt32(sizeOfPutById()),
</del><ins>+            m_out.constInt64(stackmapID), m_out.constInt32(sizeOfPutById()),
</ins><span class="cx">             constNull(m_out.ref8), m_out.constInt32(2), base, value);
</span><span class="cx">         setInstructionCallingConvention(call, LLVMAnyRegCallConv);
</span><span class="cx">         
</span><span class="lines">@@ -2437,35 +2437,40 @@
</span><span class="cx">     
</span><span class="cx">     void compileCallOrConstruct()
</span><span class="cx">     {
</span><del>-        // FIXME: This is unacceptably slow.
-        // https://bugs.webkit.org/show_bug.cgi?id=113621
</del><ins>+        int dummyThisArgument = m_node-&gt;op() == Call ? 0 : 1;
+        int numPassedArgs = m_node-&gt;numChildren() - 1;
+        int numArgs = numPassedArgs + dummyThisArgument;
</ins><span class="cx">         
</span><del>-        J_JITOperation_E function =
-            m_node-&gt;op() == Call ? operationFTLCall : operationFTLConstruct;
</del><ins>+        LValue callee = lowJSValue(m_graph.varArgChild(m_node, 0));
</ins><span class="cx">         
</span><del>-        int dummyThisArgument = m_node-&gt;op() == Call ? 0 : 1;
</del><ins>+        unsigned stackmapID = m_stackmapIDs++;
</ins><span class="cx">         
</span><del>-        int numPassedArgs = m_node-&gt;numChildren() - 1;
</del><ins>+        Vector&lt;LValue&gt; arguments;
+        arguments.append(m_out.constInt64(stackmapID));
+        arguments.append(m_out.constInt32(sizeOfCall()));
+        arguments.append(constNull(m_out.ref8));
+        arguments.append(m_out.constInt32(1 + JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize + numArgs));
+        arguments.append(callee); // callee -&gt; %rax
+        arguments.append(getUndef(m_out.int64)); // code block
+        arguments.append(getUndef(m_out.int64)); // scope chain
+        arguments.append(callee); // callee -&gt; stack
+        arguments.append(m_out.constInt64(numArgs)); // argument count and zeros for the tag
+        if (dummyThisArgument)
+            arguments.append(getUndef(m_out.int64));
+        for (int i = 0; i &lt; numPassedArgs; ++i)
+            arguments.append(lowJSValue(m_graph.varArgChild(m_node, 1 + i)));
</ins><span class="cx">         
</span><del>-        LValue calleeFrame = m_out.add(
-            m_callFrame,
-            m_out.constIntPtr(m_graph.stackPointerOffset() * sizeof(Register));
</del><ins>+        callPreflight();
</ins><span class="cx">         
</span><del>-        m_out.store32(
-            m_out.constInt32(numPassedArgs + dummyThisArgument),
-            payloadFor(calleeFrame, JSStack::ArgumentCount));
-        m_out.store64(m_callFrame, calleeFrame, m_heaps.CallFrame_callerFrame);
-        m_out.store64(
-            lowJSValue(m_graph.varArgChild(m_node, 0)),
-            addressFor(calleeFrame, JSStack::Callee));
</del><ins>+        LValue call = m_out.call(m_out.patchpointInt64Intrinsic(), arguments);
+        setInstructionCallingConvention(call, LLVMWebKitJSCallConv);
</ins><span class="cx">         
</span><del>-        for (int i = 0; i &lt; numPassedArgs; ++i) {
-            m_out.store64(
-                lowJSValue(m_graph.varArgChild(m_node, 1 + i)),
-                addressFor(calleeFrame, virtualRegisterForArgument(i + dummyThisArgument).offset()));
-        }
</del><ins>+        m_ftlState.jsCalls.append(JSCall(
+            stackmapID,
+            m_node-&gt;op() == Call ? CallLinkInfo::Call : CallLinkInfo::Construct,
+            m_node-&gt;codeOrigin));
</ins><span class="cx">         
</span><del>-        setJSValue(vmCall(m_out.operation(function), calleeFrame));
</del><ins>+        setJSValue(call);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void compileJump()
</span><span class="lines">@@ -4092,7 +4097,7 @@
</span><span class="cx">     {
</span><span class="cx">         exit.m_stackmapID = m_stackmapIDs++;
</span><span class="cx">         arguments.insert(0, m_out.constInt32(MacroAssembler::maxJumpReplacementSize()));
</span><del>-        arguments.insert(0, m_out.constInt32(exit.m_stackmapID));
</del><ins>+        arguments.insert(0, m_out.constInt64(exit.m_stackmapID));
</ins><span class="cx">         
</span><span class="cx">         m_out.call(m_out.stackmapIntrinsic(), arguments);
</span><span class="cx">     }
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLOSREntrycpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLOSREntry.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLOSREntry.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLOSREntry.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -42,6 +42,7 @@
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     CodeBlock* baseline = dfgCodeBlock-&gt;baselineVersion();
</span><ins>+    ExecutableBase* executable = dfgCodeBlock-&gt;ownerExecutable();
</ins><span class="cx">     DFG::JITCode* dfgCode = dfgCodeBlock-&gt;jitCode()-&gt;dfg();
</span><span class="cx">     ForOSREntryJITCode* entryCode = entryCodeBlock-&gt;jitCode()-&gt;ftlForOSREntry();
</span><span class="cx">     
</span><span class="lines">@@ -87,7 +88,9 @@
</span><span class="cx">     
</span><span class="cx">     exec-&gt;setCodeBlock(entryCodeBlock);
</span><span class="cx">     
</span><del>-    void* result = entryCode-&gt;addressForCall().executableAddress();
</del><ins>+    void* result = entryCode-&gt;addressForCall(
+        vm, executable, ArityCheckNotRequired,
+        RegisterPreservationNotRequired).executableAddress();
</ins><span class="cx">     if (Options::verboseOSR())
</span><span class="cx">         dataLog(&quot;    Entry will succeed, going to address&quot;, RawPointer(result), &quot;\n&quot;);
</span><span class="cx">     
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLOSRExith"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLOSRExit.h (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLOSRExit.h        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLOSRExit.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -149,6 +149,7 @@
</span><span class="cx">         unsigned numberOfArguments, unsigned numberOfLocals);
</span><span class="cx">     
</span><span class="cx">     MacroAssemblerCodeRef m_code;
</span><ins>+    RefPtr&lt;JITStubRoutine&gt; m_registerRestoration;
</ins><span class="cx">     
</span><span class="cx">     // The first argument to the exit call may be a value we wish to profile.
</span><span class="cx">     // If that's the case, the format will be not Invalid and we'll have a
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLOSRExitCompilercpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -34,7 +34,9 @@
</span><span class="cx"> #include &quot;FTLJITCode.h&quot;
</span><span class="cx"> #include &quot;FTLOSRExit.h&quot;
</span><span class="cx"> #include &quot;FTLSaveRestore.h&quot;
</span><ins>+#include &quot;MaxFrameExtentForSlowPathCall.h&quot;
</ins><span class="cx"> #include &quot;Operations.h&quot;
</span><ins>+#include &quot;RegisterPreservationWrapperGenerator.h&quot;
</ins><span class="cx"> #include &quot;RepatchBuffer.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace FTL {
</span><span class="lines">@@ -44,6 +46,14 @@
</span><span class="cx"> static void compileStub(
</span><span class="cx">     unsigned exitID, JITCode* jitCode, OSRExit&amp; exit, VM* vm, CodeBlock* codeBlock)
</span><span class="cx"> {
</span><ins>+    // Register restoration is a GC-aware JIT stub routine since we need it to stay alive
+    // if it's on the stack but all of our other things (like the FTL::OSRExit) are dead.
+    exit.m_registerRestoration = createJITStubRoutine(
+        generateRegisterRestoration(
+            *vm, codeBlock-&gt;ownerExecutable(),
+            codeBlock-&gt;codeType() == FunctionCode ? MustCheckArity : ArityCheckNotRequired),
+        *vm, codeBlock-&gt;ownerExecutable(), true);
+    
</ins><span class="cx">     StackMaps::Record* record;
</span><span class="cx">     
</span><span class="cx">     for (unsigned i = jitCode-&gt;stackmaps.records.size(); i--;) {
</span><span class="lines">@@ -61,9 +71,10 @@
</span><span class="cx">     
</span><span class="cx">     // We need scratch space to save all registers and to build up the JSStack.
</span><span class="cx">     // Use a scratch buffer to transfer all values.
</span><del>-    ScratchBuffer* scratchBuffer = vm-&gt;scratchBufferForSize(sizeof(EncodedJSValue) * exit.m_values.size() + requiredScratchMemorySizeInBytes());
</del><ins>+    ScratchBuffer* scratchBuffer = vm-&gt;scratchBufferForSize(sizeof(EncodedJSValue) * exit.m_values.size() + requiredScratchMemorySizeInBytes() + jitCode-&gt;unwindInfo.m_registers.size() * sizeof(uint64_t));
</ins><span class="cx">     EncodedJSValue* scratch = scratchBuffer ? static_cast&lt;EncodedJSValue*&gt;(scratchBuffer-&gt;dataBuffer()) : 0;
</span><span class="cx">     char* registerScratch = bitwise_cast&lt;char*&gt;(scratch + exit.m_values.size());
</span><ins>+    uint64_t* unwindScratch = bitwise_cast&lt;uint64_t*&gt;(registerScratch + requiredScratchMemorySizeInBytes());
</ins><span class="cx">     
</span><span class="cx">     // Make sure that saveAllRegisters() has a place on top of the stack to spill things. That
</span><span class="cx">     // function expects to be able to use top of stack for scratch memory.
</span><span class="lines">@@ -139,6 +150,78 @@
</span><span class="cx">         jit.store64(GPRInfo::regT0, scratch + index);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    // Henceforth we make it look like the exiting function was called through a register
+    // preservation wrapper. This implies that FP must be nudged down by a certain amount. Then
+    // we restore the various things according to either exit.m_values or by copying from the
+    // old frame, and finally we save the various callee-save registers into where the
+    // restoration thunk would restore them from.
+    
+    ptrdiff_t offset = registerPreservationOffset();
+    RegisterSet toSave = registersToPreserve();
+    
+    // Before we start messing with the frame, we need to set aside any registers that the
+    // FTL code was preserving.
+    for (unsigned i = jitCode-&gt;unwindInfo.m_registers.size(); i--;) {
+        RegisterAtOffset entry = jitCode-&gt;unwindInfo.m_registers[i];
+        jit.load64(
+            MacroAssembler::Address(MacroAssembler::framePointerRegister, entry.offset()),
+            GPRInfo::regT0);
+        jit.store64(GPRInfo::regT0, unwindScratch + i);
+    }
+    
+    jit.load32(CCallHelpers::payloadFor(JSStack::ArgumentCount), GPRInfo::regT2);
+
+    // First set up SP so that our data doesn't get clobbered by signals.
+    jit.addPtr(
+        MacroAssembler::TrustedImm32(
+            -registerPreservationOffset() - exit.m_values.numberOfLocals() * sizeof(Register) -
+            maxFrameExtentForSlowPathCall),
+        MacroAssembler::framePointerRegister, MacroAssembler::stackPointerRegister);
+    
+    jit.subPtr(
+        MacroAssembler::TrustedImm32(registerPreservationOffset()),
+        MacroAssembler::framePointerRegister);
+    
+    // Copy the old frame data into its new location.
+    jit.add32(MacroAssembler::TrustedImm32(JSStack::CallFrameHeaderSize), GPRInfo::regT2);
+    jit.move(MacroAssembler::framePointerRegister, GPRInfo::regT1);
+    MacroAssembler::Label loop = jit.label();
+    jit.sub32(MacroAssembler::TrustedImm32(1), GPRInfo::regT2);
+    jit.load64(MacroAssembler::Address(GPRInfo::regT1, offset), GPRInfo::regT0);
+    jit.store64(GPRInfo::regT0, GPRInfo::regT1);
+    jit.addPtr(MacroAssembler::TrustedImm32(sizeof(Register)), GPRInfo::regT1);
+    jit.branchTest32(MacroAssembler::NonZero, GPRInfo::regT2).linkTo(loop, &amp;jit);
+    
+    // At this point regT1 points to where we would save our registers. Save them here.
+    ptrdiff_t currentOffset = 0;
+    for (GPRReg gpr = AssemblyHelpers::firstRegister(); gpr &lt;= AssemblyHelpers::lastRegister(); gpr = static_cast&lt;GPRReg&gt;(gpr + 1)) {
+        if (!toSave.get(gpr))
+            continue;
+        currentOffset += sizeof(Register);
+        unsigned unwindIndex = jitCode-&gt;unwindInfo.indexOf(gpr);
+        if (unwindIndex == UINT_MAX) {
+            // The FTL compilation didn't preserve this register. This means that it also
+            // didn't use the register. So its value at the beginning of OSR exit should be
+            // preserved by the thunk. Luckily, we saved all registers into the register
+            // scratch buffer, so we can restore them from there.
+            jit.load64(registerScratch + offsetOfGPR(gpr), GPRInfo::regT0);
+        } else {
+            // The FTL compilation preserved the register. Its new value is therefore
+            // irrelevant, but we can get the value that was preserved by using the unwind
+            // data. We've already copied all unwind-able preserved registers into the unwind
+            // scratch buffer, so we can get it from there.
+            jit.load64(unwindScratch + unwindIndex, GPRInfo::regT0);
+        }
+        jit.store64(GPRInfo::regT0, AssemblyHelpers::Address(GPRInfo::regT1, currentOffset));
+    }
+    
+    // We need to make sure that we return into the register restoration thunk.
+    jit.loadPtr(MacroAssembler::Address(MacroAssembler::framePointerRegister, CallFrame::returnPCOffset()), GPRInfo::regT0);
+    jit.storePtr(GPRInfo::regT0, GPRInfo::regT1);
+    jit.storePtr(
+        MacroAssembler::TrustedImmPtr(exit.m_registerRestoration-&gt;code().code().executableAddress()),
+        MacroAssembler::Address(MacroAssembler::framePointerRegister, CallFrame::returnPCOffset()));
+    
</ins><span class="cx">     // Now get state out of the scratch buffer and place it back into the stack. This part does
</span><span class="cx">     // all reboxing.
</span><span class="cx">     for (unsigned index = exit.m_values.size(); index--;) {
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLRegisterAtOffsetcpp"></a>
<div class="addfile"><h4>Added: branches/jsCStack/Source/JavaScriptCore/ftl/FTLRegisterAtOffset.cpp (0 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLRegisterAtOffset.cpp                                (rev 0)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLRegisterAtOffset.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -0,0 +1,41 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;FTLRegisterAtOffset.h&quot;
+
+#if ENABLE(FTL_JIT)
+
+namespace JSC { namespace FTL {
+
+void RegisterAtOffset::dump(PrintStream&amp; out) const
+{
+    out.print(gpr(), &quot; at &quot;, offset());
+}
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT)
+
</ins></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLRegisterAtOffseth"></a>
<div class="addfile"><h4>Added: branches/jsCStack/Source/JavaScriptCore/ftl/FTLRegisterAtOffset.h (0 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLRegisterAtOffset.h                                (rev 0)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLRegisterAtOffset.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -0,0 +1,81 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef FTLRegisterAtOffset_h
+#define FTLRegisterAtOffset_h
+
+#if ENABLE(FTL_JIT)
+
+#include &quot;GPRInfo.h&quot;
+#include &lt;wtf/PrintStream.h&gt;
+
+namespace JSC { namespace FTL {
+
+class RegisterAtOffset {
+public:
+    RegisterAtOffset()
+        : m_gpr(InvalidGPRReg)
+        , m_offset(0)
+    {
+    }
+    
+    RegisterAtOffset(GPRReg gpr, ptrdiff_t offset)
+        : m_gpr(gpr)
+        , m_offset(offset)
+    {
+    }
+    
+    bool operator!() const { return m_gpr == InvalidGPRReg; }
+    
+    GPRReg gpr() const { return m_gpr; }
+    ptrdiff_t offset() const { return m_offset; }
+    
+    bool operator==(const RegisterAtOffset&amp; other) const
+    {
+        return gpr() == other.gpr() &amp;&amp; offset() == other.offset();
+    }
+    
+    bool operator&lt;(const RegisterAtOffset&amp; other) const
+    {
+        if (gpr() != other.gpr())
+            return gpr() &lt; other.gpr();
+        return offset() &lt; other.offset();
+    }
+    
+    static GPRReg getGPR(RegisterAtOffset* value) { return value-&gt;gpr(); }
+    
+    void dump(PrintStream&amp; out) const;
+
+private:
+    GPRReg m_gpr;
+    ptrdiff_t m_offset;
+};
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT)
+
+#endif // FTLRegisterAtOffset_h
+
</ins></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLStackMapscpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLStackMaps.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLStackMaps.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLStackMaps.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -79,7 +79,9 @@
</span><span class="cx"> 
</span><span class="cx"> bool StackMaps::Record::parse(DataView* view, unsigned&amp; offset)
</span><span class="cx"> {
</span><del>-    patchpointID = view-&gt;read&lt;uint32_t&gt;(offset, true);
</del><ins>+    int64_t id = view-&gt;read&lt;int64_t&gt;(offset, true);
+    ASSERT(static_cast&lt;int32_t&gt;(id) == id);
+    patchpointID = static_cast&lt;uint32_t&gt;(id);
</ins><span class="cx">     if (static_cast&lt;int32_t&gt;(patchpointID) &lt; 0)
</span><span class="cx">         return false;
</span><span class="cx">     
</span><span class="lines">@@ -90,6 +92,13 @@
</span><span class="cx">     while (length--)
</span><span class="cx">         locations.append(readObject&lt;Location&gt;(view, offset));
</span><span class="cx">     
</span><ins>+    unsigned numLiveOuts = view-&gt;read&lt;uint16_t&gt;(offset, true);
+    while (numLiveOuts--) {
+        view-&gt;read&lt;uint16_t&gt;(offset, true); // regnum
+        view-&gt;read&lt;uint8_t&gt;(offset, true); // reserved
+        view-&gt;read&lt;uint8_t&gt;(offset, true); // size in bytes
+    }
+    
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLStatecpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLState.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLState.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLState.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -43,6 +43,8 @@
</span><span class="cx">     , module(0)
</span><span class="cx">     , function(0)
</span><span class="cx">     , generatedFunction(0)
</span><ins>+    , compactUnwind(0)
+    , compactUnwindSize(0)
</ins><span class="cx"> {
</span><span class="cx">     switch (graph.m_plan.mode) {
</span><span class="cx">     case FTLMode: {
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLStateh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLState.h (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLState.h        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLState.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> #include &quot;FTLInlineCacheDescriptor.h&quot;
</span><span class="cx"> #include &quot;FTLJITCode.h&quot;
</span><span class="cx"> #include &quot;FTLJITFinalizer.h&quot;
</span><ins>+#include &quot;FTLJSCall.h&quot;
</ins><span class="cx"> #include &quot;FTLStackMaps.h&quot;
</span><span class="cx"> #include &lt;wtf/Noncopyable.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -60,8 +61,11 @@
</span><span class="cx">     unsigned capturedStackmapID;
</span><span class="cx">     SegmentedVector&lt;GetByIdDescriptor&gt; getByIds;
</span><span class="cx">     SegmentedVector&lt;PutByIdDescriptor&gt; putByIds;
</span><ins>+    Vector&lt;JSCall&gt; jsCalls;
</ins><span class="cx">     Vector&lt;CString&gt; codeSectionNames;
</span><span class="cx">     Vector&lt;CString&gt; dataSectionNames;
</span><ins>+    void* compactUnwind;
+    size_t compactUnwindSize;
</ins><span class="cx">     RefCountedArray&lt;LSectionWord&gt; stackmapsSection;
</span><span class="cx">     
</span><span class="cx">     void dumpState(const char* when);
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLUnwindInfocpp"></a>
<div class="addfile"><h4>Added: branches/jsCStack/Source/JavaScriptCore/ftl/FTLUnwindInfo.cpp (0 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLUnwindInfo.cpp                                (rev 0)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLUnwindInfo.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -0,0 +1,134 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;FTLUnwindInfo.h&quot;
+
+#if ENABLE(FTL_JIT)
+
+#include &lt;wtf/ListDump.h&gt;
+#include &lt;mach-o/compact_unwind_encoding.h&gt;
+
+namespace JSC { namespace FTL {
+
+UnwindInfo::UnwindInfo() { }
+UnwindInfo::~UnwindInfo() { }
+
+namespace {
+
+struct CompactUnwind {
+    void* function;
+    uint32_t size;
+    compact_unwind_encoding_t encoding;
+    void* personality;
+    void* lsda;
+};
+
+} // anonymous namespace
+
+void UnwindInfo::parse(void* section, size_t size)
+{
+    m_registers.clear();
+    
+    RELEASE_ASSERT(section);
+    RELEASE_ASSERT(size &gt;= sizeof(CompactUnwind));
+    
+    CompactUnwind* data = bitwise_cast&lt;CompactUnwind*&gt;(section);
+    
+    RELEASE_ASSERT(!data-&gt;personality); // We don't know how to handle this.
+    RELEASE_ASSERT(!data-&gt;lsda); // We don't know how to handle this.
+    RELEASE_ASSERT(size == sizeof(CompactUnwind) || !data[1].function); // There will only be one function.
+    
+    compact_unwind_encoding_t encoding = data-&gt;encoding;
+    RELEASE_ASSERT(!(encoding &amp; UNWIND_IS_NOT_FUNCTION_START));
+    RELEASE_ASSERT(!(encoding &amp; UNWIND_HAS_LSDA));
+    RELEASE_ASSERT(!(encoding &amp; UNWIND_PERSONALITY_MASK));
+    RELEASE_ASSERT((encoding &amp; UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_RBP_FRAME);
+    
+    int32_t offset = -((encoding &amp; UNWIND_X86_64_RBP_FRAME_OFFSET) &gt;&gt; 16) * 8;
+    uint32_t nextRegisters = encoding;
+    for (unsigned i = 5; i--;) {
+        uint32_t currentRegister = nextRegisters &amp; 7;
+        nextRegisters &gt;&gt;= 3;
+        
+        switch (currentRegister) {
+        case UNWIND_X86_64_REG_NONE:
+            break;
+            
+        case UNWIND_X86_64_REG_RBX:
+            m_registers.append(RegisterAtOffset(X86Registers::ebx, offset));
+            break;
+            
+        case UNWIND_X86_64_REG_R12:
+            m_registers.append(RegisterAtOffset(X86Registers::r12, offset));
+            break;
+            
+        case UNWIND_X86_64_REG_R13:
+            m_registers.append(RegisterAtOffset(X86Registers::r13, offset));
+            break;
+            
+        case UNWIND_X86_64_REG_R14:
+            m_registers.append(RegisterAtOffset(X86Registers::r14, offset));
+            break;
+            
+        case UNWIND_X86_64_REG_R15:
+            m_registers.append(RegisterAtOffset(X86Registers::r15, offset));
+            break;
+            
+        case UNWIND_X86_64_REG_RBP:
+            m_registers.append(RegisterAtOffset(X86Registers::ebp, offset));
+            break;
+            
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+        }
+        
+        offset += 8;
+    }
+    
+    std::sort(m_registers.begin(), m_registers.end());
+}
+
+void UnwindInfo::dump(PrintStream&amp; out) const
+{
+    out.print(listDump(m_registers));
+}
+
+RegisterAtOffset* UnwindInfo::find(GPRReg gpr) const
+{
+    return tryBinarySearch&lt;RegisterAtOffset, GPRReg&gt;(m_registers, m_registers.size(), gpr, RegisterAtOffset::getGPR);
+}
+
+unsigned UnwindInfo::indexOf(GPRReg gpr) const
+{
+    if (RegisterAtOffset* pointer = find(gpr))
+        return pointer - m_registers.begin();
+    return UINT_MAX;
+}
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT)
+
</ins></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLUnwindInfoh"></a>
<div class="addfile"><h4>Added: branches/jsCStack/Source/JavaScriptCore/ftl/FTLUnwindInfo.h (0 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLUnwindInfo.h                                (rev 0)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLUnwindInfo.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef FTLUnwindInfo_h
+#define FTLUnwindInfo_h
+
+#if ENABLE(FTL_JIT)
+
+#include &quot;FTLRegisterAtOffset.h&quot;
+
+namespace JSC { namespace FTL {
+
+struct UnwindInfo {
+    UnwindInfo();
+    ~UnwindInfo();
+    
+    void parse(void*, size_t);
+    
+    void dump(PrintStream&amp;) const;
+    
+    RegisterAtOffset* find(GPRReg gpr) const;
+    unsigned indexOf(GPRReg gpr) const; // Returns UINT_MAX if not found.
+    
+    Vector&lt;RegisterAtOffset&gt; m_registers;
+};
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT)
+
+#endif // FTLUnwindInfo_h
+
</ins></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/jit/JIT.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/JIT.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/jit/JIT.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -698,8 +698,7 @@
</span><span class="cx">     
</span><span class="cx">     m_codeBlock-&gt;shrinkToFit(CodeBlock::LateShrink);
</span><span class="cx">     m_codeBlock-&gt;setJITCode(
</span><del>-        adoptRef(new DirectJITCode(result, JITCode::BaselineJIT)),
-        withArityCheck);
</del><ins>+        adoptRef(new DirectJITCode(result, withArityCheck, JITCode::BaselineJIT)));
</ins><span class="cx">     
</span><span class="cx"> #if ENABLE(JIT_VERBOSE)
</span><span class="cx">     dataLogF(&quot;JIT generated code for %p at [%p, %p).\n&quot;, m_codeBlock, result.executableMemory()-&gt;start(), result.executableMemory()-&gt;end());
</span><span class="lines">@@ -708,42 +707,6 @@
</span><span class="cx">     return CompilationSuccessful;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JIT::linkFor(ExecState* exec, JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, JIT::CodePtr code, CallLinkInfo* callLinkInfo, VM* vm, CodeSpecializationKind kind)
-{
-    RepatchBuffer repatchBuffer(callerCodeBlock);
-
-    ASSERT(!callLinkInfo-&gt;isLinked());
-    callLinkInfo-&gt;callee.set(*vm, callLinkInfo-&gt;hotPathBegin, callerCodeBlock-&gt;ownerExecutable(), callee);
-    callLinkInfo-&gt;lastSeenCallee.set(*vm, callerCodeBlock-&gt;ownerExecutable(), callee);
-    repatchBuffer.relink(callLinkInfo-&gt;hotPathOther, code);
-
-    if (calleeCodeBlock)
-        calleeCodeBlock-&gt;linkIncomingCall(exec, callLinkInfo);
-
-    // Patch the slow patch so we do not continue to try to link.
-    if (kind == CodeForCall) {
-        ASSERT(callLinkInfo-&gt;callType == CallLinkInfo::Call
-               || callLinkInfo-&gt;callType == CallLinkInfo::CallVarargs);
-        if (callLinkInfo-&gt;callType == CallLinkInfo::Call) {
-            repatchBuffer.relink(callLinkInfo-&gt;callReturnLocation, vm-&gt;getCTIStub(linkClosureCallThunkGenerator).code());
-            return;
-        }
-
-        repatchBuffer.relink(callLinkInfo-&gt;callReturnLocation, vm-&gt;getCTIStub(virtualCallThunkGenerator).code());
-        return;
-    }
-
-    ASSERT(kind == CodeForConstruct);
-    repatchBuffer.relink(callLinkInfo-&gt;callReturnLocation, vm-&gt;getCTIStub(virtualConstructThunkGenerator).code());
-}
-
-void JIT::linkSlowCall(CodeBlock* callerCodeBlock, CallLinkInfo* callLinkInfo)
-{
-    RepatchBuffer repatchBuffer(callerCodeBlock);
-
-    repatchBuffer.relink(callLinkInfo-&gt;callReturnLocation, callerCodeBlock-&gt;vm()-&gt;getCTIStub(virtualCallThunkGenerator).code());
-}
-
</del><span class="cx"> void JIT::privateCompileExceptionHandlers()
</span><span class="cx"> {
</span><span class="cx">     if (m_exceptionChecks.empty() &amp;&amp; m_exceptionChecksWithCallFrameRollback.empty())
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/jit/JIT.h (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/JIT.h        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/jit/JIT.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -241,9 +241,6 @@
</span><span class="cx">             return jit.privateCompileCTINativeCall(vm, func);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        static void linkFor(ExecState*, JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, CodePtr, CallLinkInfo*, VM*, CodeSpecializationKind);
-        static void linkSlowCall(CodeBlock* callerCodeBlock, CallLinkInfo*);
-        
</del><span class="cx">         static unsigned frameRegisterCountFor(CodeBlock*);
</span><span class="cx">         static int stackPointerOffsetFor(CodeBlock*);
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitJITCallcpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/jit/JITCall.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/JITCall.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/jit/JITCall.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -235,7 +235,11 @@
</span><span class="cx"> 
</span><span class="cx">     addPtr(TrustedImm32(JSStack::CallerFrameAndPCSize * static_cast&lt;int&gt;(sizeof(Register))), regT1, stackPointerRegister);
</span><span class="cx"> 
</span><del>-    m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(opcodeID == op_construct ? m_vm-&gt;getCTIStub(linkConstructThunkGenerator).code() : m_vm-&gt;getCTIStub(linkCallThunkGenerator).code());
</del><ins>+    ThunkGenerator generator = linkThunkGeneratorFor(
+        opcodeID == op_construct ? CodeForConstruct : CodeForCall,
+        RegisterPreservationNotRequired);
+    
+    m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm-&gt;getCTIStub(generator).code());
</ins><span class="cx"> 
</span><span class="cx">     addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
</span><span class="cx">     checkStackPointerAlignment();
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitJITCall32_64cpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/jit/JITCall32_64.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/JITCall32_64.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/jit/JITCall32_64.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -299,7 +299,11 @@
</span><span class="cx">     linkSlowCase(iter);
</span><span class="cx">     linkSlowCase(iter);
</span><span class="cx"> 
</span><del>-    m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(opcodeID == op_construct ? m_vm-&gt;getCTIStub(linkConstructThunkGenerator).code() : m_vm-&gt;getCTIStub(linkCallThunkGenerator).code());
</del><ins>+    ThunkGenerator generator = linkCallThunkGeneratorFor(
+        opcodeID == op_construct ? CodeForConstruct : CodeForCall,
+        RegisterPreservationNotRequired);
+    
+    m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm-&gt;getCTIStub(generator).code());
</ins><span class="cx"> 
</span><span class="cx">     sampleCodeBlock(m_codeBlock);
</span><span class="cx">     emitPutCallResult(instruction);
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitJITCodecpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/jit/JITCode.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/JITCode.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/jit/JITCode.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;LLIntThunks.h&quot;
</span><span class="cx"> #include &quot;Operations.h&quot;
</span><ins>+#include &quot;RegisterPreservationWrapperGenerator.h&quot;
</ins><span class="cx"> #include &lt;wtf/PrintStream.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -73,50 +74,38 @@
</span><span class="cx"> 
</span><span class="cx"> PassRefPtr&lt;JITCode&gt; JITCode::hostFunction(JITCode::CodeRef code)
</span><span class="cx"> {
</span><del>-    return adoptRef(new DirectJITCode(code, HostCallThunk));
</del><ins>+    return adoptRef(new NativeJITCode(code, HostCallThunk));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-DirectJITCode::DirectJITCode(JITType jitType)
</del><ins>+JITCodeWithCodeRef::JITCodeWithCodeRef(JITType jitType)
</ins><span class="cx">     : JITCode(jitType)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-DirectJITCode::DirectJITCode(const JITCode::CodeRef ref, JITType jitType)
</del><ins>+JITCodeWithCodeRef::JITCodeWithCodeRef(CodeRef ref, JITType jitType)
</ins><span class="cx">     : JITCode(jitType)
</span><span class="cx">     , m_ref(ref)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-DirectJITCode::~DirectJITCode()
</del><ins>+JITCodeWithCodeRef::~JITCodeWithCodeRef()
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void DirectJITCode::initializeCodeRef(const JITCode::CodeRef ref)
</del><ins>+void* JITCodeWithCodeRef::executableAddressAtOffset(size_t offset)
</ins><span class="cx"> {
</span><del>-    RELEASE_ASSERT(!m_ref);
-    m_ref = ref;
-}
-
-JITCode::CodePtr DirectJITCode::addressForCall()
-{
</del><span class="cx">     RELEASE_ASSERT(m_ref);
</span><del>-    return m_ref.code();
-}
-
-void* DirectJITCode::executableAddressAtOffset(size_t offset)
-{
-    RELEASE_ASSERT(m_ref);
</del><span class="cx">     return reinterpret_cast&lt;char*&gt;(m_ref.code().executableAddress()) + offset;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void* DirectJITCode::dataAddressAtOffset(size_t offset)
</del><ins>+void* JITCodeWithCodeRef::dataAddressAtOffset(size_t offset)
</ins><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(m_ref);
</span><span class="cx">     ASSERT(offset &lt;= size()); // use &lt;= instead of &lt; because it is valid to ask for an address at the exclusive end of the code.
</span><span class="cx">     return reinterpret_cast&lt;char*&gt;(m_ref.code().dataLocation()) + offset;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-unsigned DirectJITCode::offsetOf(void* pointerIntoCode)
</del><ins>+unsigned JITCodeWithCodeRef::offsetOf(void* pointerIntoCode)
</ins><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(m_ref);
</span><span class="cx">     intptr_t result = reinterpret_cast&lt;intptr_t&gt;(pointerIntoCode) - reinterpret_cast&lt;intptr_t&gt;(m_ref.code().executableAddress());
</span><span class="lines">@@ -124,18 +113,107 @@
</span><span class="cx">     return static_cast&lt;unsigned&gt;(result);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-size_t DirectJITCode::size()
</del><ins>+size_t JITCodeWithCodeRef::size()
</ins><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(m_ref);
</span><span class="cx">     return m_ref.size();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool DirectJITCode::contains(void* address)
</del><ins>+bool JITCodeWithCodeRef::contains(void* address)
</ins><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(m_ref);
</span><span class="cx">     return m_ref.executableMemory()-&gt;contains(address);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+DirectJITCode::DirectJITCode(JITType jitType)
+    : JITCodeWithCodeRef(jitType)
+{
+}
+
+DirectJITCode::DirectJITCode(
+    JITCode::CodeRef ref, JITCode::CodePtr withArityCheck, JITType jitType)
+    : JITCodeWithCodeRef(ref, jitType)
+    , m_withArityCheck(withArityCheck)
+{
+}
+
+DirectJITCode::~DirectJITCode()
+{
+}
+
+void DirectJITCode::initializeCodeRef(JITCode::CodeRef ref, JITCode::CodePtr withArityCheck)
+{
+    RELEASE_ASSERT(!m_ref);
+    m_ref = ref;
+    m_withArityCheck = withArityCheck;
+}
+
+DirectJITCode::RegisterPreservationWrappers* DirectJITCode::ensureWrappers()
+{
+    if (!m_wrappers)
+        m_wrappers = std::make_unique&lt;RegisterPreservationWrappers&gt;();
+    return m_wrappers.get();
+}
+
+JITCode::CodePtr DirectJITCode::addressForCall(
+    VM&amp; vm, ExecutableBase* executable, ArityCheckMode arity,
+    RegisterPreservationMode registers)
+{
+    switch (arity) {
+    case ArityCheckNotRequired:
+        switch (registers) {
+        case RegisterPreservationNotRequired:
+            RELEASE_ASSERT(m_ref);
+            return m_ref.code();
+        case MustPreserveRegisters: {
+            RegisterPreservationWrappers* wrappers = ensureWrappers();
+            if (!wrappers-&gt;withoutArityCheck)
+                wrappers-&gt;withoutArityCheck = generateRegisterPreservationWrapper(vm, executable, m_ref.code(), ArityCheckNotRequired);
+            return wrappers-&gt;withoutArityCheck.code();
+        } }
+    case MustCheckArity:
+        switch (registers) {
+        case RegisterPreservationNotRequired:
+            RELEASE_ASSERT(m_withArityCheck);
+            return m_withArityCheck;
+        case MustPreserveRegisters: {
+            RegisterPreservationWrappers* wrappers = ensureWrappers();
+            if (!wrappers-&gt;withArityCheck)
+                wrappers-&gt;withArityCheck = generateRegisterPreservationWrapper(vm, executable, m_withArityCheck, MustCheckArity);
+            return wrappers-&gt;withArityCheck.code();
+        } }
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return CodePtr();
+}
+
+NativeJITCode::NativeJITCode(JITType jitType)
+    : JITCodeWithCodeRef(jitType)
+{
+}
+
+NativeJITCode::NativeJITCode(CodeRef ref, JITType jitType)
+    : JITCodeWithCodeRef(ref, jitType)
+{
+}
+
+NativeJITCode::~NativeJITCode()
+{
+}
+
+void NativeJITCode::initializeCodeRef(CodeRef ref)
+{
+    ASSERT(!m_ref);
+    m_ref = ref;
+}
+
+JITCode::CodePtr NativeJITCode::addressForCall(
+    VM&amp;, ExecutableBase*, ArityCheckMode, RegisterPreservationMode)
+{
+    RELEASE_ASSERT(!!m_ref);
+    return m_ref.code();
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitJITCodeh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/jit/JITCode.h (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/JITCode.h        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/jit/JITCode.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -26,14 +26,14 @@
</span><span class="cx"> #ifndef JITCode_h
</span><span class="cx"> #define JITCode_h
</span><span class="cx"> 
</span><del>-#if ENABLE(JIT) || ENABLE(LLINT)
</del><ins>+#include &quot;ArityCheckMode.h&quot;
</ins><span class="cx"> #include &quot;CallFrame.h&quot;
</span><span class="cx"> #include &quot;Disassembler.h&quot;
</span><span class="cx"> #include &quot;JITStubs.h&quot;
</span><span class="cx"> #include &quot;JSCJSValue.h&quot;
</span><span class="cx"> #include &quot;LegacyProfiler.h&quot;
</span><span class="cx"> #include &quot;MacroAssemblerCodeRef.h&quot;
</span><del>-#endif
</del><ins>+#include &quot;RegisterPreservationMode.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -164,7 +164,7 @@
</span><span class="cx">         return jitCode-&gt;jitType();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    virtual CodePtr addressForCall() = 0;
</del><ins>+    virtual CodePtr addressForCall(VM&amp;, ExecutableBase*, ArityCheckMode, RegisterPreservationMode) = 0;
</ins><span class="cx">     virtual void* executableAddressAtOffset(size_t offset) = 0;
</span><span class="cx">     void* executableAddress() { return executableAddressAtOffset(0); }
</span><span class="cx">     virtual void* dataAddressAtOffset(size_t offset) = 0;
</span><span class="lines">@@ -189,25 +189,58 @@
</span><span class="cx">     JITType m_jitType;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-class DirectJITCode : public JITCode {
</del><ins>+class JITCodeWithCodeRef : public JITCode {
+protected:
+    JITCodeWithCodeRef(JITType);
+    JITCodeWithCodeRef(CodeRef, JITType);
+
</ins><span class="cx"> public:
</span><del>-    DirectJITCode(JITType);
-    DirectJITCode(const CodeRef, JITType);
-    virtual ~DirectJITCode();
-    
-    void initializeCodeRef(CodeRef ref);
</del><ins>+    virtual ~JITCodeWithCodeRef();
</ins><span class="cx"> 
</span><del>-    virtual CodePtr addressForCall() OVERRIDE;
</del><span class="cx">     virtual void* executableAddressAtOffset(size_t offset) OVERRIDE;
</span><span class="cx">     virtual void* dataAddressAtOffset(size_t offset) OVERRIDE;
</span><span class="cx">     virtual unsigned offsetOf(void* pointerIntoCode) OVERRIDE;
</span><span class="cx">     virtual size_t size() OVERRIDE;
</span><span class="cx">     virtual bool contains(void*) OVERRIDE;
</span><span class="cx"> 
</span><del>-private:
</del><ins>+protected:
</ins><span class="cx">     CodeRef m_ref;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+class DirectJITCode : public JITCodeWithCodeRef {
+public:
+    DirectJITCode(JITType);
+    DirectJITCode(CodeRef, CodePtr withArityCheck, JITType);
+    virtual ~DirectJITCode();
+    
+    void initializeCodeRef(CodeRef ref, CodePtr withArityCheck);
+
+    virtual CodePtr addressForCall(VM&amp;, ExecutableBase*, ArityCheckMode, RegisterPreservationMode) OVERRIDE;
+
+private:
+    struct RegisterPreservationWrappers {
+        CodeRef withoutArityCheck;
+        CodeRef withArityCheck;
+    };
+
+    RegisterPreservationWrappers* ensureWrappers();
+    
+    CodePtr m_withArityCheck;
+    
+    std::unique_ptr&lt;RegisterPreservationWrappers&gt; m_wrappers;
+};
+
+class NativeJITCode : public JITCodeWithCodeRef {
+public:
+    NativeJITCode(JITType);
+    NativeJITCode(CodeRef, JITType);
+    virtual ~NativeJITCode();
+    
+    void initializeCodeRef(CodeRef ref);
+
+    virtual CodePtr addressForCall(VM&amp;, ExecutableBase*, ArityCheckMode, RegisterPreservationMode) OVERRIDE;
+};
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/jit/JITOperations.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/JITOperations.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/jit/JITOperations.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -678,7 +678,8 @@
</span><span class="cx">     return vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline char* linkFor(ExecState* execCallee, CodeSpecializationKind kind)
</del><ins>+inline char* linkFor(
+    ExecState* execCallee, CodeSpecializationKind kind, RegisterPreservationMode registers)
</ins><span class="cx"> {
</span><span class="cx">     ExecState* exec = execCallee-&gt;callerFrame();
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="lines">@@ -696,9 +697,9 @@
</span><span class="cx">     MacroAssemblerCodePtr codePtr;
</span><span class="cx">     CodeBlock* codeBlock = 0;
</span><span class="cx">     CallLinkInfo&amp; callLinkInfo = exec-&gt;codeBlock()-&gt;getCallLinkInfo(execCallee-&gt;returnPC());
</span><del>-    if (executable-&gt;isHostFunction())
-        codePtr = executable-&gt;generatedJITCodeFor(kind)-&gt;addressForCall();
-    else {
</del><ins>+    if (executable-&gt;isHostFunction()) {
+        codePtr = executable-&gt;entrypointFor(*vm, kind, MustCheckArity, registers);
+    } else {
</ins><span class="cx">         FunctionExecutable* functionExecutable = static_cast&lt;FunctionExecutable*&gt;(executable);
</span><span class="cx">         JSObject* error = functionExecutable-&gt;prepareForExecution(execCallee, callee-&gt;scope(), kind);
</span><span class="cx">         if (error) {
</span><span class="lines">@@ -706,30 +707,44 @@
</span><span class="cx">             return reinterpret_cast&lt;char*&gt;(vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
</span><span class="cx">         }
</span><span class="cx">         codeBlock = functionExecutable-&gt;codeBlockFor(kind);
</span><ins>+        ArityCheckMode arity;
</ins><span class="cx">         if (execCallee-&gt;argumentCountIncludingThis() &lt; static_cast&lt;size_t&gt;(codeBlock-&gt;numParameters()) || callLinkInfo.callType == CallLinkInfo::CallVarargs)
</span><del>-            codePtr = functionExecutable-&gt;generatedJITCodeWithArityCheckFor(kind);
</del><ins>+            arity = MustCheckArity;
</ins><span class="cx">         else
</span><del>-            codePtr = functionExecutable-&gt;generatedJITCodeFor(kind)-&gt;addressForCall();
</del><ins>+            arity = ArityCheckNotRequired;
+        codePtr = functionExecutable-&gt;entrypointFor(*vm, kind, arity, registers);
</ins><span class="cx">     }
</span><span class="cx">     if (!callLinkInfo.seenOnce())
</span><span class="cx">         callLinkInfo.setSeen();
</span><span class="cx">     else
</span><del>-        linkFor(execCallee, callLinkInfo, codeBlock, callee, codePtr, kind);
</del><ins>+        linkFor(execCallee, callLinkInfo, codeBlock, callee, codePtr, kind, registers);
</ins><span class="cx">     return reinterpret_cast&lt;char*&gt;(codePtr.executableAddress());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> char* JIT_OPERATION operationLinkCall(ExecState* execCallee)
</span><span class="cx"> {
</span><del>-    return linkFor(execCallee, CodeForCall);
</del><ins>+    return linkFor(execCallee, CodeForCall, RegisterPreservationNotRequired);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> char* JIT_OPERATION operationLinkConstruct(ExecState* execCallee)
</span><span class="cx"> {
</span><del>-    return linkFor(execCallee, CodeForConstruct);
</del><ins>+    return linkFor(execCallee, CodeForConstruct, RegisterPreservationNotRequired);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline char* virtualForWithFunction(ExecState* execCallee, CodeSpecializationKind kind, JSCell*&amp; calleeAsFunctionCell)
</del><ins>+char* JIT_OPERATION operationLinkCallThatPreservesRegs(ExecState* execCallee)
</ins><span class="cx"> {
</span><ins>+    return linkFor(execCallee, CodeForCall, MustPreserveRegisters);
+}
+
+char* JIT_OPERATION operationLinkConstructThatPreservesRegs(ExecState* execCallee)
+{
+    return linkFor(execCallee, CodeForConstruct, MustPreserveRegisters);
+}
+
+inline char* virtualForWithFunction(
+    ExecState* execCallee, CodeSpecializationKind kind, RegisterPreservationMode registers,
+    JSCell*&amp; calleeAsFunctionCell)
+{
</ins><span class="cx">     ExecState* exec = execCallee-&gt;callerFrame();
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><span class="lines">@@ -750,16 +765,20 @@
</span><span class="cx">             return reinterpret_cast&lt;char*&gt;(vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-    return reinterpret_cast&lt;char*&gt;(executable-&gt;generatedJITCodeWithArityCheckFor(kind).executableAddress());
</del><ins>+    return reinterpret_cast&lt;char*&gt;(executable-&gt;entrypointFor(
+        *vm, kind, MustCheckArity, registers).executableAddress());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline char* virtualFor(ExecState* execCallee, CodeSpecializationKind kind)
</del><ins>+inline char* virtualFor(
+    ExecState* execCallee, CodeSpecializationKind kind, RegisterPreservationMode registers)
</ins><span class="cx"> {
</span><span class="cx">     JSCell* calleeAsFunctionCellIgnored;
</span><del>-    return virtualForWithFunction(execCallee, kind, calleeAsFunctionCellIgnored);
</del><ins>+    return virtualForWithFunction(execCallee, kind, registers, calleeAsFunctionCellIgnored);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool attemptToOptimizeClosureCall(ExecState* execCallee, JSCell* calleeAsFunctionCell, CallLinkInfo&amp; callLinkInfo)
</del><ins>+static bool attemptToOptimizeClosureCall(
+    ExecState* execCallee, RegisterPreservationMode registers, JSCell* calleeAsFunctionCell,
+    CallLinkInfo&amp; callLinkInfo)
</ins><span class="cx"> {
</span><span class="cx">     if (!calleeAsFunctionCell)
</span><span class="cx">         return false;
</span><span class="lines">@@ -773,7 +792,10 @@
</span><span class="cx">         return false;
</span><span class="cx">     
</span><span class="cx">     ASSERT(callee-&gt;executable()-&gt;hasJITCodeForCall());
</span><del>-    MacroAssemblerCodePtr codePtr = callee-&gt;executable()-&gt;generatedJITCodeForCall()-&gt;addressForCall();
</del><ins>+    MacroAssemblerCodePtr codePtr =
+        callee-&gt;executable()-&gt;generatedJITCodeForCall()-&gt;addressForCall(
+            *execCallee-&gt;callerFrame()-&gt;codeBlock()-&gt;vm(), callee-&gt;executable(),
+            ArityCheckNotRequired, registers);
</ins><span class="cx">     
</span><span class="cx">     CodeBlock* codeBlock;
</span><span class="cx">     if (callee-&gt;executable()-&gt;isHostFunction())
</span><span class="lines">@@ -786,7 +808,7 @@
</span><span class="cx">     
</span><span class="cx">     linkClosureCall(
</span><span class="cx">         execCallee, callLinkInfo, codeBlock,
</span><del>-        callee-&gt;structure(), callee-&gt;executable(), codePtr);
</del><ins>+        callee-&gt;structure(), callee-&gt;executable(), codePtr, registers);
</ins><span class="cx">     
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="lines">@@ -794,26 +816,47 @@
</span><span class="cx"> char* JIT_OPERATION operationLinkClosureCall(ExecState* execCallee)
</span><span class="cx"> {
</span><span class="cx">     JSCell* calleeAsFunctionCell;
</span><del>-    char* result = virtualForWithFunction(execCallee, CodeForCall, calleeAsFunctionCell);
</del><ins>+    char* result = virtualForWithFunction(execCallee, CodeForCall, RegisterPreservationNotRequired, calleeAsFunctionCell);
</ins><span class="cx">     CallLinkInfo&amp; callLinkInfo = execCallee-&gt;callerFrame()-&gt;codeBlock()-&gt;getCallLinkInfo(execCallee-&gt;returnPC());
</span><span class="cx"> 
</span><del>-    if (!attemptToOptimizeClosureCall(execCallee, calleeAsFunctionCell, callLinkInfo))
-        linkSlowFor(execCallee, callLinkInfo, CodeForCall);
</del><ins>+    if (!attemptToOptimizeClosureCall(execCallee, RegisterPreservationNotRequired, calleeAsFunctionCell, callLinkInfo))
+        linkSlowFor(execCallee, callLinkInfo, CodeForCall, RegisterPreservationNotRequired);
</ins><span class="cx">     
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> char* JIT_OPERATION operationVirtualCall(ExecState* execCallee)
</span><span class="cx"> {    
</span><del>-    return virtualFor(execCallee, CodeForCall);
</del><ins>+    return virtualFor(execCallee, CodeForCall, RegisterPreservationNotRequired);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> char* JIT_OPERATION operationVirtualConstruct(ExecState* execCallee)
</span><span class="cx"> {
</span><del>-    return virtualFor(execCallee, CodeForConstruct);
</del><ins>+    return virtualFor(execCallee, CodeForConstruct, RegisterPreservationNotRequired);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+char* JIT_OPERATION operationLinkClosureCallThatPreservesRegs(ExecState* execCallee)
+{
+    JSCell* calleeAsFunctionCell;
+    char* result = virtualForWithFunction(execCallee, CodeForCall, MustPreserveRegisters, calleeAsFunctionCell);
+    CallLinkInfo&amp; callLinkInfo = execCallee-&gt;callerFrame()-&gt;codeBlock()-&gt;getCallLinkInfo(execCallee-&gt;returnPC());
</ins><span class="cx"> 
</span><ins>+    if (!attemptToOptimizeClosureCall(execCallee, MustPreserveRegisters, calleeAsFunctionCell, callLinkInfo))
+        linkSlowFor(execCallee, callLinkInfo, CodeForCall, MustPreserveRegisters);
+    
+    return result;
+}
+
+char* JIT_OPERATION operationVirtualCallThatPreservesRegs(ExecState* execCallee)
+{    
+    return virtualFor(execCallee, CodeForCall, MustPreserveRegisters);
+}
+
+char* JIT_OPERATION operationVirtualConstructThatPreservesRegs(ExecState* execCallee)
+{
+    return virtualFor(execCallee, CodeForConstruct, MustPreserveRegisters);
+}
+
</ins><span class="cx"> size_t JIT_OPERATION operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
</span><span class="cx"> {
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/jit/JITOperations.h (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/JITOperations.h        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/jit/JITOperations.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -216,11 +216,17 @@
</span><span class="cx"> void JIT_OPERATION operationPutByValGeneric(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
</span><span class="cx"> void JIT_OPERATION operationDirectPutByValGeneric(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationCallEval(ExecState*, ExecState*) WTF_INTERNAL;
</span><del>-char* JIT_OPERATION operationVirtualCall(ExecState*) WTF_INTERNAL;
</del><span class="cx"> char* JIT_OPERATION operationLinkCall(ExecState*) WTF_INTERNAL;
</span><span class="cx"> char* JIT_OPERATION operationLinkClosureCall(ExecState*) WTF_INTERNAL;
</span><ins>+char* JIT_OPERATION operationVirtualCall(ExecState*) WTF_INTERNAL;
</ins><span class="cx"> char* JIT_OPERATION operationVirtualConstruct(ExecState*) WTF_INTERNAL;
</span><span class="cx"> char* JIT_OPERATION operationLinkConstruct(ExecState*) WTF_INTERNAL;
</span><ins>+char* JIT_OPERATION operationLinkCallThatPreservesRegs(ExecState*) WTF_INTERNAL;
+char* JIT_OPERATION operationLinkClosureCallThatPreservesRegs(ExecState*) WTF_INTERNAL;
+char* JIT_OPERATION operationVirtualCallThatPreservesRegs(ExecState*) WTF_INTERNAL;
+char* JIT_OPERATION operationVirtualConstructThatPreservesRegs(ExecState*) WTF_INTERNAL;
+char* JIT_OPERATION operationLinkConstructThatPreservesRegs(ExecState*) WTF_INTERNAL;
+
</ins><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 class="cx"> size_t JIT_OPERATION operationCompareGreater(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
</span><span class="lines">@@ -282,6 +288,68 @@
</span><span class="cx"> 
</span><span class="cx"> } // extern &quot;C&quot;
</span><span class="cx"> 
</span><ins>+inline P_JITOperation_E operationLinkFor(
+    CodeSpecializationKind kind, RegisterPreservationMode registers)
+{
+    switch (kind) {
+    case CodeForCall:
+        switch (registers) {
+        case RegisterPreservationNotRequired:
+            return operationLinkCall;
+        case MustPreserveRegisters:
+            return operationLinkCallThatPreservesRegs;
+        }
+        break;
+    case CodeForConstruct:
+        switch (registers) {
+        case RegisterPreservationNotRequired:
+            return operationLinkConstruct;
+        case MustPreserveRegisters:
+            return operationLinkConstructThatPreservesRegs;
+        }
+        break;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return 0;
+}
+
+inline P_JITOperation_E operationVirtualFor(
+    CodeSpecializationKind kind, RegisterPreservationMode registers)
+{
+    switch (kind) {
+    case CodeForCall:
+        switch (registers) {
+        case RegisterPreservationNotRequired:
+            return operationVirtualCall;
+        case MustPreserveRegisters:
+            return operationVirtualCallThatPreservesRegs;
+        }
+        break;
+    case CodeForConstruct:
+        switch (registers) {
+        case RegisterPreservationNotRequired:
+            return operationVirtualConstruct;
+        case MustPreserveRegisters:
+            return operationVirtualConstructThatPreservesRegs;
+        }
+        break;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return 0;
+}
+
+inline P_JITOperation_E operationLinkClosureCallFor(RegisterPreservationMode registers)
+{
+    switch (registers) {
+    case RegisterPreservationNotRequired:
+        return operationLinkClosureCall;
+    case MustPreserveRegisters:
+        return operationLinkClosureCallThatPreservesRegs;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return 0;
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(JIT)
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitRegisterPreservationWrapperGeneratorcpp"></a>
<div class="addfile"><h4>Added: branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp (0 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp                                (rev 0)
+++ branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -0,0 +1,215 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;RegisterPreservationWrapperGenerator.h&quot;
+
+#if ENABLE(JIT)
+
+#include &quot;AssemblyHelpers.h&quot;
+#include &quot;LinkBuffer.h&quot;
+#include &quot;StackAlignment.h&quot;
+
+namespace JSC {
+
+RegisterSet registersToPreserve()
+{
+    RegisterSet calleeSaves = RegisterSet::calleeSaveRegisters();
+    
+    // No need to preserve FP since that always gets preserved anyway.
+    calleeSaves.clear(GPRInfo::callFrameRegister);
+    
+    return calleeSaves;
+}
+
+ptrdiff_t registerPreservationOffset()
+{
+    unsigned numberOfCalleeSaves = registersToPreserve().numberOfSetRegisters();
+    
+    // Need to preserve the old return PC.
+    unsigned numberOfValuesToSave = numberOfCalleeSaves + 1;
+    
+    // Alignment. Preserve the same alignment invariants that the caller imposed.
+    unsigned numberOfNewStackSlots =
+        WTF::roundUpToMultipleOf(stackAlignmentRegisters(), numberOfValuesToSave);
+    
+    return sizeof(Register) * numberOfNewStackSlots;
+}
+
+MacroAssemblerCodeRef generateRegisterPreservationWrapper(VM&amp; vm, ExecutableBase* executable, MacroAssemblerCodePtr target, ArityCheckMode arity)
+{
+#if ENABLE(FTL_JIT)
+    // We shouldn't ever be generating wrappers for native functions.
+    ScriptExecutable* scriptExecutable = jsCast&lt;ScriptExecutable*&gt;(executable);
+    
+    RegisterSet toSave = registersToPreserve();
+    ptrdiff_t offset = registerPreservationOffset();
+    
+    AssemblyHelpers jit(&amp;vm, 0);
+    
+    jit.preserveReturnAddressAfterCall(GPRInfo::regT1);
+    jit.load32(
+        AssemblyHelpers::Address(
+            AssemblyHelpers::stackPointerRegister,
+            (JSStack::ArgumentCount - JSStack::CallerFrameAndPCSize) * sizeof(Register) + PayloadOffset),
+        GPRInfo::regT2);
+    
+    // Place the stack pointer where we want it to be.
+    jit.subPtr(AssemblyHelpers::TrustedImm32(offset), AssemblyHelpers::stackPointerRegister);
+    
+    // Compute the number of things we will be copying.
+    jit.add32(
+        AssemblyHelpers::TrustedImm32(
+            JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize),
+        GPRInfo::regT2);
+
+    ASSERT(!toSave.get(GPRInfo::regT4));
+    jit.move(AssemblyHelpers::stackPointerRegister, GPRInfo::regT4);
+    
+    AssemblyHelpers::Label loop = jit.label();
+    jit.sub32(AssemblyHelpers::TrustedImm32(1), GPRInfo::regT2);
+    jit.load64(AssemblyHelpers::Address(GPRInfo::regT4, offset), GPRInfo::regT0);
+    jit.store64(GPRInfo::regT0, GPRInfo::regT4);
+    jit.addPtr(AssemblyHelpers::TrustedImm32(sizeof(Register)), GPRInfo::regT4);
+    jit.branchTest32(AssemblyHelpers::NonZero, GPRInfo::regT2).linkTo(loop, &amp;jit);
+
+    // At this point regT4 + offset points to where we save things.
+    ptrdiff_t currentOffset = 0;
+    jit.storePtr(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT4, currentOffset));
+    
+    for (GPRReg gpr = AssemblyHelpers::firstRegister(); gpr &lt;= AssemblyHelpers::lastRegister(); gpr = static_cast&lt;GPRReg&gt;(gpr + 1)) {
+        if (!toSave.get(gpr))
+            continue;
+        currentOffset += sizeof(Register);
+        jit.store64(gpr, AssemblyHelpers::Address(GPRInfo::regT4, currentOffset));
+    }
+    
+    // Assume that there aren't any saved FP registers.
+    
+    // Restore the tag registers.
+    jit.move(AssemblyHelpers::TrustedImm64(TagTypeNumber), GPRInfo::tagTypeNumberRegister);
+    jit.add64(AssemblyHelpers::TrustedImm32(TagMask - TagTypeNumber), GPRInfo::tagTypeNumberRegister, GPRInfo::tagMaskRegister);
+    
+    AssemblyHelpers::Call call = jit.nearCall();
+    
+    generateRegisterRestoration(jit, executable, arity);
+    
+    LinkBuffer linkBuffer(vm, &amp;jit, GLOBAL_THUNK_ID);
+    linkBuffer.link(call, CodeLocationLabel(target));
+    
+    return FINALIZE_DFG_CODE(linkBuffer, (&quot;Register preservation wrapper for %s/%s, %p&quot;, toCString(scriptExecutable-&gt;hashFor(CodeForCall)).data(), toCString(scriptExecutable-&gt;hashFor(CodeForConstruct)).data(), target.executableAddress()));
+#else // ENABLE(FTL_JIT)
+    // We don't support non-FTL builds for two reasons:
+    // - It just so happens that currently only the FTL bottoms out in this code.
+    // - The code above uses 64-bit instructions. It doesn't necessarily have to; it would be
+    //   easy to change it so that it doesn't. But obviously making that change would be a
+    //   prerequisite to removing this #if.
+    UNREACHABLE_FOR_PLATFORM();
+#endif // ENABLE(FTL_JIT)
+}
+
+void generateRegisterRestoration(AssemblyHelpers&amp; jit, ExecutableBase* executable, ArityCheckMode arity)
+{
+    RegisterSet toSave = registersToPreserve();
+    ptrdiff_t offset = registerPreservationOffset();
+    
+    // We need to place the stack pointer back to where the caller thought they left it.
+    // But also, in order to recover the registers, we need to figure out how big the
+    // arguments area is.
+    
+    jit.load32(
+        AssemblyHelpers::Address(
+            AssemblyHelpers::stackPointerRegister,
+            (JSStack::ArgumentCount - JSStack::CallerFrameAndPCSize) * sizeof(Register) + PayloadOffset),
+        GPRInfo::regT2);
+    
+    if (arity == MustCheckArity) {
+        // It's possible that the arity checker had extended the stack. In that case, we need
+        // to adjust the argument count to be the max of what the frame claims and what the
+        // executable desired.
+        FunctionExecutable* functionExecutable = jsCast&lt;FunctionExecutable*&gt;(executable);
+        int parameterCount = functionExecutable-&gt;parameterCount() + 1;
+        AssemblyHelpers::Jump ok = jit.branch32(
+            AssemblyHelpers::AboveOrEqual, GPRInfo::regT2,
+            AssemblyHelpers::TrustedImm32(parameterCount));
+        jit.move(AssemblyHelpers::TrustedImm32(parameterCount), GPRInfo::regT2);
+        ok.link(&amp;jit);
+    }
+    
+    jit.lshift32(AssemblyHelpers::TrustedImm32(3), GPRInfo::regT2);
+    
+    jit.addPtr(AssemblyHelpers::TrustedImm32(offset), AssemblyHelpers::stackPointerRegister);
+    jit.addPtr(AssemblyHelpers::stackPointerRegister, GPRInfo::regT2);
+    
+    // We saved things at:
+    //
+    //     adjSP + (JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize + NumArgs) * 8
+    //
+    // Where:
+    //
+    //     adjSP = origSP - offset
+    //
+    // regT2 now points at:
+    //
+    //     origSP + NumArgs * 8
+    //   = adjSP + offset + NumArgs * 8
+    // 
+    // So if we subtract offset and then add JSStack::CallFrameHeaderSize and subtract
+    // JSStack::CallerFrameAndPCSize, we'll get the thing we want.
+    ptrdiff_t currentOffset = -offset + sizeof(Register) * (
+        JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize);
+    jit.loadPtr(AssemblyHelpers::Address(GPRInfo::regT2, currentOffset), GPRInfo::regT1);
+    
+    for (GPRReg gpr = AssemblyHelpers::firstRegister(); gpr &lt;= AssemblyHelpers::lastRegister(); gpr = static_cast&lt;GPRReg&gt;(gpr + 1)) {
+        if (!toSave.get(gpr))
+            continue;
+        currentOffset += sizeof(Register);
+        jit.load64(AssemblyHelpers::Address(GPRInfo::regT2, currentOffset), gpr);
+    }
+    
+    if (!ASSERT_DISABLED) {
+        AssemblyHelpers::Jump ok = jit.branchPtr(
+            AssemblyHelpers::Above, GPRInfo::regT1, AssemblyHelpers::TrustedImmPtr(static_cast&lt;size_t&gt;(0x1000)));
+        jit.breakpoint();
+        ok.link(&amp;jit);
+    }
+    
+    jit.jump(GPRInfo::regT1);
+}
+
+MacroAssemblerCodeRef generateRegisterRestoration(
+    VM&amp; vm, ExecutableBase* executable, ArityCheckMode arity)
+{
+    ScriptExecutable* scriptExecutable = jsCast&lt;ScriptExecutable*&gt;(executable);
+    AssemblyHelpers jit(&amp;vm, 0);
+    generateRegisterRestoration(jit, executable, arity);
+    LinkBuffer linkBuffer(vm, &amp;jit, GLOBAL_THUNK_ID);
+    return FINALIZE_DFG_CODE(linkBuffer, (&quot;Register restoration thunk for %s/%s&quot;, toCString(scriptExecutable-&gt;hashFor(CodeForCall)).data(), toCString(scriptExecutable-&gt;hashFor(CodeForConstruct)).data()));
+}
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
</ins></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitRegisterPreservationWrapperGeneratorh"></a>
<div class="addfile"><h4>Added: branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.h (0 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.h                                (rev 0)
+++ branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -0,0 +1,53 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef RegisterPreservationWrapperGenerator_h
+#define RegisterPreservationWrapperGenerator_h
+
+#if ENABLE(JIT)
+
+#include &quot;ArityCheckMode.h&quot;
+#include &quot;AssemblyHelpers.h&quot;
+#include &quot;MacroAssemblerCodeRef.h&quot;
+#include &quot;VM.h&quot;
+
+namespace JSC {
+
+RegisterSet registersToPreserve();
+
+ptrdiff_t registerPreservationOffset();
+
+MacroAssemblerCodeRef generateRegisterPreservationWrapper(VM&amp;, ExecutableBase*, MacroAssemblerCodePtr target, ArityCheckMode);
+
+void generateRegisterRestoration(AssemblyHelpers&amp;, ExecutableBase*, ArityCheckMode);
+
+MacroAssemblerCodeRef generateRegisterRestoration(VM&amp;, ExecutableBase*, ArityCheckMode);
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
+#endif // RegisterPreservationWrapperGenerator_h
+
</ins></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitRepatchcpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/jit/Repatch.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/Repatch.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/jit/Repatch.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -1270,17 +1270,19 @@
</span><span class="cx">     repatchCall(exec-&gt;codeBlock(), stubInfo.callReturnLocation, operationIn);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void linkSlowFor(RepatchBuffer&amp; repatchBuffer, VM* vm, CallLinkInfo&amp; callLinkInfo, CodeSpecializationKind kind)
</del><ins>+static void linkSlowFor(
+    RepatchBuffer&amp; repatchBuffer, VM* vm, CallLinkInfo&amp; callLinkInfo,
+    CodeSpecializationKind kind, RegisterPreservationMode registers)
</ins><span class="cx"> {
</span><del>-    if (kind == CodeForCall) {
-        repatchBuffer.relink(callLinkInfo.callReturnLocation, vm-&gt;getCTIStub(virtualCallThunkGenerator).code());
-        return;
-    }
-    ASSERT(kind == CodeForConstruct);
-    repatchBuffer.relink(callLinkInfo.callReturnLocation, vm-&gt;getCTIStub(virtualConstructThunkGenerator).code());
</del><ins>+    repatchBuffer.relink(
+        callLinkInfo.callReturnLocation,
+        vm-&gt;getCTIStub(virtualThunkGeneratorFor(kind, registers)).code());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void linkFor(ExecState* exec, CallLinkInfo&amp; callLinkInfo, CodeBlock* calleeCodeBlock, JSFunction* callee, MacroAssemblerCodePtr codePtr, CodeSpecializationKind kind)
</del><ins>+void linkFor(
+    ExecState* exec, CallLinkInfo&amp; callLinkInfo, CodeBlock* calleeCodeBlock,
+    JSFunction* callee, MacroAssemblerCodePtr codePtr, CodeSpecializationKind kind,
+    RegisterPreservationMode registers)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!callLinkInfo.stub);
</span><span class="cx">     
</span><span class="lines">@@ -1296,31 +1298,38 @@
</span><span class="cx">     ASSERT(!callLinkInfo.isLinked());
</span><span class="cx">     callLinkInfo.callee.set(exec-&gt;callerFrame()-&gt;vm(), callLinkInfo.hotPathBegin, callerCodeBlock-&gt;ownerExecutable(), callee);
</span><span class="cx">     callLinkInfo.lastSeenCallee.set(exec-&gt;callerFrame()-&gt;vm(), callerCodeBlock-&gt;ownerExecutable(), callee);
</span><ins>+    if (Options::showDisassembly())
+        dataLog(&quot;Linking call in &quot;, *callerCodeBlock, &quot; at &quot;, callLinkInfo.codeOrigin, &quot; to &quot;, pointerDump(calleeCodeBlock), &quot;, entrypoint at &quot;, codePtr, &quot;\n&quot;);
</ins><span class="cx">     repatchBuffer.relink(callLinkInfo.hotPathOther, codePtr);
</span><span class="cx">     
</span><span class="cx">     if (calleeCodeBlock)
</span><span class="cx">         calleeCodeBlock-&gt;linkIncomingCall(exec-&gt;callerFrame(), &amp;callLinkInfo);
</span><span class="cx">     
</span><span class="cx">     if (kind == CodeForCall) {
</span><del>-        repatchBuffer.relink(callLinkInfo.callReturnLocation, vm-&gt;getCTIStub(linkClosureCallThunkGenerator).code());
</del><ins>+        repatchBuffer.relink(callLinkInfo.callReturnLocation, vm-&gt;getCTIStub(linkClosureCallThunkGeneratorFor(registers)).code());
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     ASSERT(kind == CodeForConstruct);
</span><del>-    linkSlowFor(repatchBuffer, vm, callLinkInfo, CodeForConstruct);
</del><ins>+    linkSlowFor(repatchBuffer, vm, callLinkInfo, CodeForConstruct, registers);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void linkSlowFor(ExecState* exec, CallLinkInfo&amp; callLinkInfo, CodeSpecializationKind kind)
</del><ins>+void linkSlowFor(
+    ExecState* exec, CallLinkInfo&amp; callLinkInfo, CodeSpecializationKind kind,
+    RegisterPreservationMode registers)
</ins><span class="cx"> {
</span><span class="cx">     CodeBlock* callerCodeBlock = exec-&gt;callerFrame()-&gt;codeBlock();
</span><span class="cx">     VM* vm = callerCodeBlock-&gt;vm();
</span><span class="cx">     
</span><span class="cx">     RepatchBuffer repatchBuffer(callerCodeBlock);
</span><span class="cx">     
</span><del>-    linkSlowFor(repatchBuffer, vm, callLinkInfo, kind);
</del><ins>+    linkSlowFor(repatchBuffer, vm, callLinkInfo, kind, registers);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void linkClosureCall(ExecState* exec, CallLinkInfo&amp; callLinkInfo, CodeBlock* calleeCodeBlock, Structure* structure, ExecutableBase* executable, MacroAssemblerCodePtr codePtr)
</del><ins>+void linkClosureCall(
+    ExecState* exec, CallLinkInfo&amp; callLinkInfo, CodeBlock* calleeCodeBlock,
+    Structure* structure, ExecutableBase* executable, MacroAssemblerCodePtr codePtr,
+    RegisterPreservationMode registers)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!callLinkInfo.stub);
</span><span class="cx">     
</span><span class="lines">@@ -1380,18 +1389,18 @@
</span><span class="cx"> #if USE(JSVALUE32_64)
</span><span class="cx">     stubJit.move(CCallHelpers::TrustedImm32(JSValue::CellTag), GPRInfo::regT1);
</span><span class="cx"> #endif
</span><del>-    stubJit.move(CCallHelpers::TrustedImmPtr(callLinkInfo.callReturnLocation.executableAddress()), GPRInfo::nonArgGPR2);
</del><ins>+    stubJit.move(CCallHelpers::TrustedImmPtr(callLinkInfo.callReturnLocation.executableAddress()), GPRInfo::regT2);
</ins><span class="cx">     
</span><span class="cx">     // FIXME: CStack - Think the restoreReturnAddressBeforeReturn() instruction should be a poke
</span><span class="cx">     stubJit.breakpoint();
</span><del>-    stubJit.restoreReturnAddressBeforeReturn(GPRInfo::nonArgGPR2);
</del><ins>+    stubJit.restoreReturnAddressBeforeReturn(GPRInfo::regT2);
</ins><span class="cx">     AssemblyHelpers::Jump slow = stubJit.jump();
</span><span class="cx">     
</span><span class="cx">     LinkBuffer patchBuffer(*vm, &amp;stubJit, callerCodeBlock);
</span><span class="cx">     
</span><span class="cx">     patchBuffer.link(call, FunctionPtr(codePtr.executableAddress()));
</span><span class="cx">     patchBuffer.link(done, callLinkInfo.callReturnLocation.labelAtOffset(0));
</span><del>-    patchBuffer.link(slow, CodeLocationLabel(vm-&gt;getCTIStub(virtualCallThunkGenerator).code()));
</del><ins>+    patchBuffer.link(slow, CodeLocationLabel(vm-&gt;getCTIStub(virtualThunkGeneratorFor(CodeForCall, registers)).code()));
</ins><span class="cx">     
</span><span class="cx">     RefPtr&lt;ClosureCallStubRoutine&gt; stubRoutine = adoptRef(new ClosureCallStubRoutine(
</span><span class="cx">         FINALIZE_DFG_CODE(
</span><span class="lines">@@ -1406,7 +1415,7 @@
</span><span class="cx">     repatchBuffer.replaceWithJump(
</span><span class="cx">         RepatchBuffer::startOfBranchPtrWithPatchOnRegister(callLinkInfo.hotPathBegin),
</span><span class="cx">         CodeLocationLabel(stubRoutine-&gt;code().code()));
</span><del>-    linkSlowFor(repatchBuffer, vm, callLinkInfo, CodeForCall);
</del><ins>+    linkSlowFor(repatchBuffer, vm, callLinkInfo, CodeForCall, registers);
</ins><span class="cx">     
</span><span class="cx">     callLinkInfo.stub = stubRoutine.release();
</span><span class="cx">     
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitRepatchh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/jit/Repatch.h (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/Repatch.h        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/jit/Repatch.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -41,9 +41,9 @@
</span><span class="cx"> void repatchPutByID(ExecState*, JSValue, const Identifier&amp;, const PutPropertySlot&amp;, StructureStubInfo&amp;, PutKind);
</span><span class="cx"> void buildPutByIdList(ExecState*, JSValue, const Identifier&amp;, const PutPropertySlot&amp;, StructureStubInfo&amp;, PutKind);
</span><span class="cx"> void repatchIn(ExecState*, JSCell*, const Identifier&amp;, bool wasFound, const PropertySlot&amp;, StructureStubInfo&amp;);
</span><del>-void linkFor(ExecState*, CallLinkInfo&amp;, CodeBlock*, JSFunction* callee, MacroAssemblerCodePtr, CodeSpecializationKind);
-void linkSlowFor(ExecState*, CallLinkInfo&amp;, CodeSpecializationKind);
-void linkClosureCall(ExecState*, CallLinkInfo&amp;, CodeBlock*, Structure*, ExecutableBase*, MacroAssemblerCodePtr);
</del><ins>+void linkFor(ExecState*, CallLinkInfo&amp;, CodeBlock*, JSFunction* callee, MacroAssemblerCodePtr, CodeSpecializationKind, RegisterPreservationMode);
+void linkSlowFor(ExecState*, CallLinkInfo&amp;, CodeSpecializationKind, RegisterPreservationMode);
+void linkClosureCall(ExecState*, CallLinkInfo&amp;, CodeBlock*, Structure*, ExecutableBase*, MacroAssemblerCodePtr, RegisterPreservationMode);
</ins><span class="cx"> void resetGetByID(RepatchBuffer&amp;, StructureStubInfo&amp;);
</span><span class="cx"> void resetPutByID(RepatchBuffer&amp;, StructureStubInfo&amp;);
</span><span class="cx"> void resetIn(RepatchBuffer&amp;, StructureStubInfo&amp;);
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitThunkGeneratorscpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/jit/ThunkGenerators.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -99,7 +99,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static MacroAssemblerCodeRef linkForThunkGenerator(
</span><del>-    VM* vm, CodeSpecializationKind kind)
</del><ins>+    VM* vm, CodeSpecializationKind kind, RegisterPreservationMode registers)
</ins><span class="cx"> {
</span><span class="cx">     // The return address is on the stack or in the link register. We will hence
</span><span class="cx">     // save the return address to the call frame while we make a C++ function call
</span><span class="lines">@@ -109,38 +109,59 @@
</span><span class="cx">     
</span><span class="cx">     CCallHelpers jit(vm);
</span><span class="cx">     
</span><del>-    slowPathFor(jit, vm, kind == CodeForCall ? operationLinkCall : operationLinkConstruct);
</del><ins>+    slowPathFor(jit, vm, operationLinkFor(kind, registers));
</ins><span class="cx">     
</span><span class="cx">     LinkBuffer patchBuffer(*vm, &amp;jit, GLOBAL_THUNK_ID);
</span><span class="cx">     return FINALIZE_CODE(
</span><span class="cx">         patchBuffer,
</span><del>-        (&quot;Link %s slow path thunk&quot;, kind == CodeForCall ? &quot;call&quot; : &quot;construct&quot;));
</del><ins>+        (&quot;Link %s%s slow path thunk&quot;, kind == CodeForCall ? &quot;call&quot; : &quot;construct&quot;, registers == MustPreserveRegisters ? &quot; that preserves registers&quot; : &quot;&quot;));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MacroAssemblerCodeRef linkCallThunkGenerator(VM* vm)
</span><span class="cx"> {
</span><del>-    return linkForThunkGenerator(vm, CodeForCall);
</del><ins>+    return linkForThunkGenerator(vm, CodeForCall, RegisterPreservationNotRequired);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MacroAssemblerCodeRef linkConstructThunkGenerator(VM* vm)
</span><span class="cx"> {
</span><del>-    return linkForThunkGenerator(vm, CodeForConstruct);
</del><ins>+    return linkForThunkGenerator(vm, CodeForConstruct, RegisterPreservationNotRequired);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-// For closure optimizations, we only include calls, since if you're using closures for
-// object construction then you're going to lose big time anyway.
-MacroAssemblerCodeRef linkClosureCallThunkGenerator(VM* vm)
</del><ins>+MacroAssemblerCodeRef linkCallThatPreservesRegsThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><ins>+    return linkForThunkGenerator(vm, CodeForCall, MustPreserveRegisters);
+}
+
+MacroAssemblerCodeRef linkConstructThatPreservesRegsThunkGenerator(VM* vm)
+{
+    return linkForThunkGenerator(vm, CodeForConstruct, MustPreserveRegisters);
+}
+
+static MacroAssemblerCodeRef linkClosureCallForThunkGenerator(
+    VM* vm, RegisterPreservationMode registers)
+{
</ins><span class="cx">     CCallHelpers jit(vm);
</span><span class="cx">     
</span><del>-    slowPathFor(jit, vm, operationLinkClosureCall);
</del><ins>+    slowPathFor(jit, vm, operationLinkClosureCallFor(registers));
</ins><span class="cx">     
</span><span class="cx">     LinkBuffer patchBuffer(*vm, &amp;jit, GLOBAL_THUNK_ID);
</span><del>-    return FINALIZE_CODE(patchBuffer, (&quot;Link closure call slow path thunk&quot;));
</del><ins>+    return FINALIZE_CODE(patchBuffer, (&quot;Link closure call %s slow path thunk&quot;, registers == MustPreserveRegisters ? &quot; that preserves registers&quot; : &quot;&quot;));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// For closure optimizations, we only include calls, since if you're using closures for
+// object construction then you're going to lose big time anyway.
+MacroAssemblerCodeRef linkClosureCallThunkGenerator(VM* vm)
+{
+    return linkClosureCallForThunkGenerator(vm, RegisterPreservationNotRequired);
+}
+
+MacroAssemblerCodeRef linkClosureCallThatPreservesRegsThunkGenerator(VM* vm)
+{
+    return linkClosureCallForThunkGenerator(vm, MustPreserveRegisters);
+}
+
</ins><span class="cx"> static MacroAssemblerCodeRef virtualForThunkGenerator(
</span><del>-    VM* vm, CodeSpecializationKind kind)
</del><ins>+    VM* vm, CodeSpecializationKind kind, RegisterPreservationMode registers)
</ins><span class="cx"> {
</span><span class="cx">     // The callee is in regT0 (for JSVALUE32_64, the tag is in regT1).
</span><span class="cx">     // The return address is on the stack, or in the link register. We will hence
</span><span class="lines">@@ -155,33 +176,34 @@
</span><span class="cx">     // the DFG knows that the value is definitely a cell, or definitely a function.
</span><span class="cx">     
</span><span class="cx"> #if USE(JSVALUE64)
</span><ins>+    jit.move(CCallHelpers::TrustedImm64(TagMask), GPRInfo::regT2);
+    
</ins><span class="cx">     slowCase.append(
</span><span class="cx">         jit.branchTest64(
</span><del>-            CCallHelpers::NonZero, GPRInfo::regT0, GPRInfo::tagMaskRegister));
</del><ins>+            CCallHelpers::NonZero, GPRInfo::regT0, GPRInfo::regT2));
</ins><span class="cx"> #else
</span><span class="cx">     slowCase.append(
</span><span class="cx">         jit.branch32(
</span><span class="cx">             CCallHelpers::NotEqual, GPRInfo::regT1,
</span><span class="cx">             CCallHelpers::TrustedImm32(JSValue::CellTag)));
</span><span class="cx"> #endif
</span><del>-    jit.loadPtr(CCallHelpers::Address(GPRInfo::regT0, JSCell::structureOffset()), GPRInfo::nonArgGPR2);
</del><ins>+    jit.loadPtr(CCallHelpers::Address(GPRInfo::regT0, JSCell::structureOffset()), GPRInfo::regT2);
</ins><span class="cx">     slowCase.append(
</span><span class="cx">         jit.branchPtr(
</span><span class="cx">             CCallHelpers::NotEqual,
</span><del>-            CCallHelpers::Address(GPRInfo::nonArgGPR2, Structure::classInfoOffset()),
</del><ins>+            CCallHelpers::Address(GPRInfo::regT2, Structure::classInfoOffset()),
</ins><span class="cx">             CCallHelpers::TrustedImmPtr(JSFunction::info())));
</span><span class="cx">     
</span><span class="cx">     // Now we know we have a JSFunction.
</span><span class="cx">     
</span><span class="cx">     jit.loadPtr(
</span><span class="cx">         CCallHelpers::Address(GPRInfo::regT0, JSFunction::offsetOfExecutable()),
</span><del>-        GPRInfo::nonArgGPR2);
-    slowCase.append(
-        jit.branch32(
-            CCallHelpers::LessThan,
-            CCallHelpers::Address(
-                GPRInfo::nonArgGPR2, ExecutableBase::offsetOfNumParametersFor(kind)),
-            CCallHelpers::TrustedImm32(0)));
</del><ins>+        GPRInfo::regT2);
+    jit.loadPtr(
+        CCallHelpers::Address(
+            GPRInfo::regT2, ExecutableBase::offsetOfJITCodeWithArityCheckFor(kind, registers)),
+        GPRInfo::regT2);
+    slowCase.append(jit.branchTestPtr(CCallHelpers::Zero, GPRInfo::regT2));
</ins><span class="cx">     
</span><span class="cx">     // Now we know that we have a CodeBlock, and we're committed to making a fast
</span><span class="cx">     // call.
</span><span class="lines">@@ -197,36 +219,42 @@
</span><span class="cx">         JSStack::ScopeChain);
</span><span class="cx"> #endif
</span><span class="cx">     
</span><del>-    jit.loadPtr(
-        CCallHelpers::Address(GPRInfo::nonArgGPR2, ExecutableBase::offsetOfJITCodeWithArityCheckFor(kind)),
-        GPRInfo::regT0);
-    
</del><span class="cx">     // Make a tail call. This will return back to JIT code.
</span><del>-    emitPointerValidation(jit, GPRInfo::regT0);
-    jit.jump(GPRInfo::regT0);
</del><ins>+    emitPointerValidation(jit, GPRInfo::regT2);
+    jit.jump(GPRInfo::regT2);
</ins><span class="cx"> 
</span><span class="cx">     slowCase.link(&amp;jit);
</span><span class="cx">     
</span><span class="cx">     // Here we don't know anything, so revert to the full slow path.
</span><span class="cx">     
</span><del>-    slowPathFor(jit, vm, kind == CodeForCall ? operationVirtualCall : operationVirtualConstruct);
</del><ins>+    slowPathFor(jit, vm, operationVirtualFor(kind, registers));
</ins><span class="cx">     
</span><span class="cx">     LinkBuffer patchBuffer(*vm, &amp;jit, GLOBAL_THUNK_ID);
</span><span class="cx">     return FINALIZE_CODE(
</span><span class="cx">         patchBuffer,
</span><del>-        (&quot;Virtual %s slow path thunk&quot;, kind == CodeForCall ? &quot;call&quot; : &quot;construct&quot;));
</del><ins>+        (&quot;Virtual %s%s slow path thunk&quot;, kind == CodeForCall ? &quot;call&quot; : &quot;construct&quot;, registers == MustPreserveRegisters ? &quot; that preserves registers&quot; : &quot;&quot;));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MacroAssemblerCodeRef virtualCallThunkGenerator(VM* vm)
</span><span class="cx"> {
</span><del>-    return virtualForThunkGenerator(vm, CodeForCall);
</del><ins>+    return virtualForThunkGenerator(vm, CodeForCall, RegisterPreservationNotRequired);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MacroAssemblerCodeRef virtualConstructThunkGenerator(VM* vm)
</span><span class="cx"> {
</span><del>-    return virtualForThunkGenerator(vm, CodeForConstruct);
</del><ins>+    return virtualForThunkGenerator(vm, CodeForConstruct, RegisterPreservationNotRequired);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+MacroAssemblerCodeRef virtualCallThatPreservesRegsThunkGenerator(VM* vm)
+{
+    return virtualForThunkGenerator(vm, CodeForCall, MustPreserveRegisters);
+}
+
+MacroAssemblerCodeRef virtualConstructThatPreservesRegsThunkGenerator(VM* vm)
+{
+    return virtualForThunkGenerator(vm, CodeForConstruct, MustPreserveRegisters);
+}
+
</ins><span class="cx"> enum ThunkEntryType { EnterViaCall, EnterViaJump };
</span><span class="cx"> 
</span><span class="cx"> static MacroAssemblerCodeRef nativeForGenerator(VM* vm, CodeSpecializationKind kind, ThunkEntryType entryType = EnterViaCall)
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitThunkGeneratorsh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/jit/ThunkGenerators.h (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/ThunkGenerators.h        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/jit/ThunkGenerators.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -26,6 +26,8 @@
</span><span class="cx"> #ifndef ThunkGenerators_h
</span><span class="cx"> #define ThunkGenerators_h
</span><span class="cx"> 
</span><ins>+#include &quot;CodeSpecializationKind.h&quot;
+#include &quot;RegisterPreservationMode.h&quot;
</ins><span class="cx"> #include &quot;ThunkGenerator.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="lines">@@ -35,12 +37,79 @@
</span><span class="cx"> 
</span><span class="cx"> MacroAssemblerCodeRef linkCallThunkGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef linkConstructThunkGenerator(VM*);
</span><ins>+MacroAssemblerCodeRef linkCallThatPreservesRegsThunkGenerator(VM*);
+MacroAssemblerCodeRef linkConstructThatPreservesRegsThunkGenerator(VM*);
</ins><span class="cx"> 
</span><ins>+inline ThunkGenerator linkThunkGeneratorFor(
+    CodeSpecializationKind kind, RegisterPreservationMode registers)
+{
+    switch (kind) {
+    case CodeForCall:
+        switch (registers) {
+        case RegisterPreservationNotRequired:
+            return linkCallThunkGenerator;
+        case MustPreserveRegisters:
+            return linkCallThatPreservesRegsThunkGenerator;
+        }
+        break;
+    case CodeForConstruct:
+        switch (registers) {
+        case RegisterPreservationNotRequired:
+            return linkConstructThunkGenerator;
+        case MustPreserveRegisters:
+            return linkConstructThatPreservesRegsThunkGenerator;
+        }
+        break;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return 0;
+}
+
</ins><span class="cx"> MacroAssemblerCodeRef linkClosureCallThunkGenerator(VM*);
</span><ins>+MacroAssemblerCodeRef linkClosureCallThatPreservesRegsThunkGenerator(VM*);
</ins><span class="cx"> 
</span><ins>+inline ThunkGenerator linkClosureCallThunkGeneratorFor(RegisterPreservationMode registers)
+{
+    switch (registers) {
+    case RegisterPreservationNotRequired:
+        return linkClosureCallThunkGenerator;
+    case MustPreserveRegisters:
+        return linkClosureCallThatPreservesRegsThunkGenerator;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return 0;
+}
+
</ins><span class="cx"> MacroAssemblerCodeRef virtualCallThunkGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef virtualConstructThunkGenerator(VM*);
</span><ins>+MacroAssemblerCodeRef virtualCallThatPreservesRegsThunkGenerator(VM*);
+MacroAssemblerCodeRef virtualConstructThatPreservesRegsThunkGenerator(VM*);
</ins><span class="cx"> 
</span><ins>+inline ThunkGenerator virtualThunkGeneratorFor(
+    CodeSpecializationKind kind, RegisterPreservationMode registers)
+{
+    switch (kind) {
+    case CodeForCall:
+        switch (registers) {
+        case RegisterPreservationNotRequired:
+            return virtualCallThunkGenerator;
+        case MustPreserveRegisters:
+            return virtualCallThatPreservesRegsThunkGenerator;
+        }
+        break;
+    case CodeForConstruct:
+        switch (registers) {
+        case RegisterPreservationNotRequired:
+            return virtualConstructThunkGenerator;
+        case MustPreserveRegisters:
+            return virtualConstructThatPreservesRegsThunkGenerator;
+        }
+        break;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return 0;
+}
+
</ins><span class="cx"> MacroAssemblerCodeRef nativeCallGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef nativeConstructGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef nativeTailCallGenerator(VM*);
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorellintLLIntEntrypointcpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/llint/LLIntEntrypoint.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/llint/LLIntEntrypoint.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/llint/LLIntEntrypoint.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -47,14 +47,12 @@
</span><span class="cx">     if (vm.canUseJIT()) {
</span><span class="cx">         if (kind == CodeForCall) {
</span><span class="cx">             codeBlock-&gt;setJITCode(
</span><del>-                adoptRef(new DirectJITCode(vm.getCTIStub(functionForCallEntryThunkGenerator), JITCode::InterpreterThunk)),
-                vm.getCTIStub(functionForCallArityCheckThunkGenerator).code());
</del><ins>+                adoptRef(new DirectJITCode(vm.getCTIStub(functionForCallEntryThunkGenerator), vm.getCTIStub(functionForCallArityCheckThunkGenerator).code(), JITCode::InterpreterThunk)));
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">         ASSERT(kind == CodeForConstruct);
</span><span class="cx">         codeBlock-&gt;setJITCode(
</span><del>-            adoptRef(new DirectJITCode(vm.getCTIStub(functionForConstructEntryThunkGenerator), JITCode::InterpreterThunk)),
-            vm.getCTIStub(functionForConstructArityCheckThunkGenerator).code());
</del><ins>+            adoptRef(new DirectJITCode(vm.getCTIStub(functionForConstructEntryThunkGenerator), vm.getCTIStub(functionForConstructArityCheckThunkGenerator).code(), JITCode::InterpreterThunk)));
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> #endif // ENABLE(JIT)
</span><span class="lines">@@ -62,14 +60,12 @@
</span><span class="cx">     UNUSED_PARAM(vm);
</span><span class="cx">     if (kind == CodeForCall) {
</span><span class="cx">         codeBlock-&gt;setJITCode(
</span><del>-            adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_call_prologue), JITCode::InterpreterThunk)),
-            MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_call_arity_check));
</del><ins>+            adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_call_prologue), MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_call_arity_check), JITCode::InterpreterThunk)));
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     ASSERT(kind == CodeForConstruct);
</span><span class="cx">     codeBlock-&gt;setJITCode(
</span><del>-        adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_construct_prologue), JITCode::InterpreterThunk)),
-        MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_construct_arity_check));
</del><ins>+        adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_construct_prologue), MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_construct_arity_check), JITCode::InterpreterThunk)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void setEvalEntrypoint(VM&amp; vm, CodeBlock* codeBlock)
</span><span class="lines">@@ -77,16 +73,14 @@
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     if (vm.canUseJIT()) {
</span><span class="cx">         codeBlock-&gt;setJITCode(
</span><del>-            adoptRef(new DirectJITCode(vm.getCTIStub(evalEntryThunkGenerator), JITCode::InterpreterThunk)),
-            MacroAssemblerCodePtr());
</del><ins>+            adoptRef(new DirectJITCode(vm.getCTIStub(evalEntryThunkGenerator), MacroAssemblerCodePtr(), JITCode::InterpreterThunk)));
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> #endif // ENABLE(JIT)
</span><span class="cx"> 
</span><span class="cx">     UNUSED_PARAM(vm);
</span><span class="cx">     codeBlock-&gt;setJITCode(
</span><del>-        adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_eval_prologue), JITCode::InterpreterThunk)),
-        MacroAssemblerCodePtr());
</del><ins>+        adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_eval_prologue), MacroAssemblerCodePtr(), JITCode::InterpreterThunk)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void setProgramEntrypoint(VM&amp; vm, CodeBlock* codeBlock)
</span><span class="lines">@@ -94,16 +88,14 @@
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     if (vm.canUseJIT()) {
</span><span class="cx">         codeBlock-&gt;setJITCode(
</span><del>-            adoptRef(new DirectJITCode(vm.getCTIStub(programEntryThunkGenerator), JITCode::InterpreterThunk)),
-            MacroAssemblerCodePtr());
</del><ins>+            adoptRef(new DirectJITCode(vm.getCTIStub(programEntryThunkGenerator), MacroAssemblerCodePtr(), JITCode::InterpreterThunk)));
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> #endif // ENABLE(JIT)
</span><span class="cx"> 
</span><span class="cx">     UNUSED_PARAM(vm);
</span><span class="cx">     codeBlock-&gt;setJITCode(
</span><del>-        adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_program_prologue), JITCode::InterpreterThunk)),
-        MacroAssemblerCodePtr());
</del><ins>+        adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_program_prologue), MacroAssemblerCodePtr(), JITCode::InterpreterThunk)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void setEntrypoint(VM&amp; vm, CodeBlock* codeBlock)
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -346,7 +346,9 @@
</span><span class="cx">     if (kind == Prologue)
</span><span class="cx">         LLINT_RETURN_TWO(codeBlock-&gt;jitCode()-&gt;executableAddress(), 0);
</span><span class="cx">     ASSERT(kind == ArityCheck);
</span><del>-    LLINT_RETURN_TWO(codeBlock-&gt;jitCodeWithArityCheck().executableAddress(), 0);
</del><ins>+    LLINT_RETURN_TWO(codeBlock-&gt;jitCode()-&gt;addressForCall(
+        *codeBlock-&gt;vm(), codeBlock-&gt;ownerExecutable(), MustCheckArity,
+        RegisterPreservationNotRequired).executableAddress(), 0);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> LLINT_SLOW_PATH_DECL(entry_osr)
</span><span class="lines">@@ -1046,7 +1048,7 @@
</span><span class="cx">     MacroAssemblerCodePtr codePtr;
</span><span class="cx">     CodeBlock* codeBlock = 0;
</span><span class="cx">     if (executable-&gt;isHostFunction())
</span><del>-        codePtr = executable-&gt;hostCodeEntryFor(kind);
</del><ins>+        codePtr = executable-&gt;entrypointFor(vm, kind, MustCheckArity, RegisterPreservationNotRequired);
</ins><span class="cx">     else {
</span><span class="cx">         FunctionExecutable* functionExecutable = static_cast&lt;FunctionExecutable*&gt;(executable);
</span><span class="cx">         JSObject* error = functionExecutable-&gt;prepareForExecution(execCallee, callee-&gt;scope(), kind);
</span><span class="lines">@@ -1054,12 +1056,16 @@
</span><span class="cx">             LLINT_CALL_THROW(execCallee-&gt;callerFrame(), error);
</span><span class="cx">         codeBlock = functionExecutable-&gt;codeBlockFor(kind);
</span><span class="cx">         ASSERT(codeBlock);
</span><ins>+        ArityCheckMode arity;
</ins><span class="cx">         if (execCallee-&gt;argumentCountIncludingThis() &lt; static_cast&lt;size_t&gt;(codeBlock-&gt;numParameters()))
</span><del>-            codePtr = functionExecutable-&gt;jsCodeWithArityCheckEntryFor(kind);
</del><ins>+            arity = MustCheckArity;
</ins><span class="cx">         else
</span><del>-            codePtr = functionExecutable-&gt;jsCodeEntryFor(kind);
</del><ins>+            arity = ArityCheckNotRequired;
+        codePtr = functionExecutable-&gt;entrypointFor(vm, kind, arity, RegisterPreservationNotRequired);
</ins><span class="cx">     }
</span><span class="cx">     
</span><ins>+    ASSERT(!!codePtr);
+    
</ins><span class="cx">     if (!LLINT_ALWAYS_ACCESS_SLOW &amp;&amp; callLinkInfo) {
</span><span class="cx">         ExecState* execCaller = execCallee-&gt;callerFrame();
</span><span class="cx">         
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreruntimeArityCheckModeh"></a>
<div class="addfile"><h4>Added: branches/jsCStack/Source/JavaScriptCore/runtime/ArityCheckMode.h (0 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/runtime/ArityCheckMode.h                                (rev 0)
+++ branches/jsCStack/Source/JavaScriptCore/runtime/ArityCheckMode.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef ArityCheckMode_h
+#define ArityCheckMode_h
+
+namespace JSC {
+
+enum ArityCheckMode {
+    ArityCheckNotRequired,
+    MustCheckArity
+};
+
+} // namespace JSC
+
+#endif // ArityCheckMode_h
+
</ins></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreruntimeExecutablecpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/runtime/Executable.cpp (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/runtime/Executable.cpp        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/runtime/Executable.cpp        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -118,12 +118,14 @@
</span><span class="cx">     switch (kind) {
</span><span class="cx">     case CodeForCall:
</span><span class="cx">         m_jitCodeForCall = genericCodeBlock-&gt;jitCode();
</span><del>-        m_jitCodeForCallWithArityCheck = genericCodeBlock-&gt;jitCodeWithArityCheck();
</del><ins>+        m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
+        m_jitCodeForCallWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
</ins><span class="cx">         m_numParametersForCall = genericCodeBlock-&gt;numParameters();
</span><span class="cx">         break;
</span><span class="cx">     case CodeForConstruct:
</span><span class="cx">         m_jitCodeForConstruct = genericCodeBlock-&gt;jitCode();
</span><del>-        m_jitCodeForConstructWithArityCheck = genericCodeBlock-&gt;jitCodeWithArityCheck();
</del><ins>+        m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
+        m_jitCodeForConstructWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();
</ins><span class="cx">         m_numParametersForConstruct = genericCodeBlock-&gt;numParameters();
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="lines">@@ -133,7 +135,6 @@
</span><span class="cx">         ProgramExecutable* executable = jsCast&lt;ProgramExecutable*&gt;(this);
</span><span class="cx">         ProgramCodeBlock* codeBlock = static_cast&lt;ProgramCodeBlock*&gt;(genericCodeBlock);
</span><span class="cx">         
</span><del>-        ASSERT(!codeBlock-&gt;jitCodeWithArityCheck());
</del><span class="cx">         ASSERT(kind == CodeForCall);
</span><span class="cx">         
</span><span class="cx">         oldCodeBlock = executable-&gt;m_programCodeBlock;
</span><span class="lines">@@ -145,7 +146,6 @@
</span><span class="cx">         EvalExecutable* executable = jsCast&lt;EvalExecutable*&gt;(this);
</span><span class="cx">         EvalCodeBlock* codeBlock = static_cast&lt;EvalCodeBlock*&gt;(genericCodeBlock);
</span><span class="cx">         
</span><del>-        ASSERT(!codeBlock-&gt;jitCodeWithArityCheck());
</del><span class="cx">         ASSERT(kind == CodeForCall);
</span><span class="cx">         
</span><span class="cx">         oldCodeBlock = executable-&gt;m_evalCodeBlock;
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreruntimeExecutableh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/runtime/Executable.h (160892 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/runtime/Executable.h        2013-12-20 02:58:16 UTC (rev 160892)
+++ branches/jsCStack/Source/JavaScriptCore/runtime/Executable.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #ifndef Executable_h
</span><span class="cx"> #define Executable_h
</span><span class="cx"> 
</span><ins>+#include &quot;ArityCheckMode.h&quot;
</ins><span class="cx"> #include &quot;CallData.h&quot;
</span><span class="cx"> #include &quot;CodeBlockHash.h&quot;
</span><span class="cx"> #include &quot;CodeSpecializationKind.h&quot;
</span><span class="lines">@@ -36,6 +37,7 @@
</span><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="cx"> #include &quot;JITCode.h&quot;
</span><span class="cx"> #include &quot;JSGlobalObject.h&quot;
</span><ins>+#include &quot;RegisterPreservationMode.h&quot;
</ins><span class="cx"> #include &quot;SamplingTool.h&quot;
</span><span class="cx"> #include &quot;SourceCode.h&quot;
</span><span class="cx"> #include &quot;UnlinkedCodeBlock.h&quot;
</span><span class="lines">@@ -144,37 +146,94 @@
</span><span class="cx">         ASSERT(kind == CodeForConstruct);
</span><span class="cx">         return generatedJITCodeForConstruct();
</span><span class="cx">     }
</span><del>-
-    MacroAssemblerCodePtr generatedJITCodeForCallWithArityCheck()
</del><ins>+    
+    MacroAssemblerCodePtr entrypointFor(
+        VM&amp; vm, CodeSpecializationKind kind, ArityCheckMode arity, RegisterPreservationMode registers)
</ins><span class="cx">     {
</span><del>-        ASSERT(m_jitCodeForCall);
-        ASSERT(m_jitCodeForCallWithArityCheck);
-        return m_jitCodeForCallWithArityCheck;
</del><ins>+        // Check if we have a cached result. We only have it for arity check because we use the
+        // no-arity entrypoint in non-virtual calls, which will &quot;cache&quot; this value directly in
+        // machine code.
+        if (arity == MustCheckArity) {
+            switch (kind) {
+            case CodeForCall:
+                switch (registers) {
+                case RegisterPreservationNotRequired:
+                    if (MacroAssemblerCodePtr result = m_jitCodeForCallWithArityCheck)
+                        return result;
+                    break;
+                case MustPreserveRegisters:
+                    if (MacroAssemblerCodePtr result = m_jitCodeForCallWithArityCheckAndPreserveRegs)
+                        return result;
+                    break;
+                }
+                break;
+            case CodeForConstruct:
+                switch (registers) {
+                case RegisterPreservationNotRequired:
+                    if (MacroAssemblerCodePtr result = m_jitCodeForConstructWithArityCheck)
+                        return result;
+                    break;
+                case MustPreserveRegisters:
+                    if (MacroAssemblerCodePtr result = m_jitCodeForConstructWithArityCheckAndPreserveRegs)
+                        return result;
+                    break;
+                }
+                break;
+            }
+        }
+        MacroAssemblerCodePtr result =
+            generatedJITCodeFor(kind)-&gt;addressForCall(vm, this, arity, registers);
+        if (arity == MustCheckArity) {
+            // Cache the result; this is necessary for the JIT's virtual call optimizations.
+            switch (kind) {
+            case CodeForCall:
+                switch (registers) {
+                case RegisterPreservationNotRequired:
+                    m_jitCodeForCallWithArityCheck = result;
+                    break;
+                case MustPreserveRegisters:
+                    m_jitCodeForCallWithArityCheckAndPreserveRegs = result;
+                    break;
+                }
+                break;
+            case CodeForConstruct:
+                switch (registers) {
+                case RegisterPreservationNotRequired:
+                    m_jitCodeForConstructWithArityCheck = result;
+                    break;
+                case MustPreserveRegisters:
+                    m_jitCodeForConstructWithArityCheckAndPreserveRegs = result;
+                    break;
+                }
+                break;
+            }
+        }
+        return result;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    MacroAssemblerCodePtr generatedJITCodeForConstructWithArityCheck()
</del><ins>+    static ptrdiff_t offsetOfJITCodeWithArityCheckFor(
+        CodeSpecializationKind kind, RegisterPreservationMode registers)
</ins><span class="cx">     {
</span><del>-        ASSERT(m_jitCodeForConstruct);
-        ASSERT(m_jitCodeForConstructWithArityCheck);
-        return m_jitCodeForConstructWithArityCheck;
</del><ins>+        switch (kind) {
+        case CodeForCall:
+            switch (registers) {
+            case RegisterPreservationNotRequired:
+                return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
+            case MustPreserveRegisters:
+                return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheckAndPreserveRegs);
+            }
+        case CodeForConstruct:
+            switch (registers) {
+            case RegisterPreservationNotRequired:
+                return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
+            case MustPreserveRegisters:
+                return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheckAndPreserveRegs);
+            }
+        }
+        RELEASE_ASSERT_NOT_REACHED();
+        return 0;
</ins><span class="cx">     }
</span><del>-        
-    MacroAssemblerCodePtr generatedJITCodeWithArityCheckFor(CodeSpecializationKind kind)
-    {
-        if (kind == CodeForCall)
-            return generatedJITCodeForCallWithArityCheck();
-        ASSERT(kind == CodeForConstruct);
-        return generatedJITCodeForConstructWithArityCheck();
-    }
-        
-    static ptrdiff_t offsetOfJITCodeWithArityCheckFor(CodeSpecializationKind kind)
-    {
-        if (kind == CodeForCall)
-            return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
-        ASSERT(kind == CodeForConstruct);
-        return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
-    }
-        
</del><ins>+    
</ins><span class="cx">     static ptrdiff_t offsetOfNumParametersFor(CodeSpecializationKind kind)
</span><span class="cx">     {
</span><span class="cx">         if (kind == CodeForCall)
</span><span class="lines">@@ -211,21 +270,6 @@
</span><span class="cx">         return NoIntrinsic;
</span><span class="cx">     }
</span><span class="cx">         
</span><del>-    MacroAssemblerCodePtr hostCodeEntryFor(CodeSpecializationKind kind)
-    {
-        return generatedJITCodeFor(kind)-&gt;addressForCall();
-    }
-
-    MacroAssemblerCodePtr jsCodeEntryFor(CodeSpecializationKind kind)
-    {
-        return generatedJITCodeFor(kind)-&gt;addressForCall();
-    }
-
-    MacroAssemblerCodePtr jsCodeWithArityCheckEntryFor(CodeSpecializationKind kind)
-    {
-        return generatedJITCodeWithArityCheckFor(kind);
-    }
-
</del><span class="cx"> protected:
</span><span class="cx">     ExecutableBase* m_prev;
</span><span class="cx">     ExecutableBase* m_next;
</span><span class="lines">@@ -234,6 +278,8 @@
</span><span class="cx">     RefPtr&lt;JITCode&gt; m_jitCodeForConstruct;
</span><span class="cx">     MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
</span><span class="cx">     MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
</span><ins>+    MacroAssemblerCodePtr m_jitCodeForCallWithArityCheckAndPreserveRegs;
+    MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheckAndPreserveRegs;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class NativeExecutable : public ExecutableBase {
</span><span class="lines">@@ -288,8 +334,6 @@
</span><span class="cx">     void finishCreation(VM&amp; vm, PassRefPtr&lt;JITCode&gt; callThunk, PassRefPtr&lt;JITCode&gt; constructThunk, Intrinsic intrinsic)
</span><span class="cx">     {
</span><span class="cx">         Base::finishCreation(vm);
</span><del>-        m_jitCodeForCallWithArityCheck = callThunk ? callThunk-&gt;addressForCall() : MacroAssemblerCodePtr();
-        m_jitCodeForConstructWithArityCheck = constructThunk ? constructThunk-&gt;addressForCall() : MacroAssemblerCodePtr();
</del><span class="cx">         m_jitCodeForCall = callThunk;
</span><span class="cx">         m_jitCodeForConstruct = constructThunk;
</span><span class="cx">         m_intrinsic = intrinsic;
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreruntimeRegisterPreservationModeh"></a>
<div class="addfile"><h4>Added: branches/jsCStack/Source/JavaScriptCore/runtime/RegisterPreservationMode.h (0 => 160893)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/runtime/RegisterPreservationMode.h                                (rev 0)
+++ branches/jsCStack/Source/JavaScriptCore/runtime/RegisterPreservationMode.h        2013-12-20 03:33:24 UTC (rev 160893)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef RegisterPreservationMode_h
+#define RegisterPreservationMode_h
+
+namespace JSC {
+
+enum RegisterPreservationMode {
+    RegisterPreservationNotRequired,
+    MustPreserveRegisters
+};
+
+} // namespace JSC
+
+#endif // RegisterPreservationMode_h
+
</ins></span></pre>
</div>
</div>

</body>
</html>