<!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>[209725] trunk</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/209725">209725</a></dd>
<dt>Author</dt> <dd>msaboff@apple.com</dd>
<dt>Date</dt> <dd>2016-12-12 13:46:45 -0800 (Mon, 12 Dec 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>REGRESSION(<a href="http://trac.webkit.org/projects/webkit/changeset/209653">r209653</a>): speedometer crashes making virtual slow path tailcalls
https://bugs.webkit.org/show_bug.cgi?id=165748

Reviewed by Filip Pizlo.

JSTests:

New regression test.

* stress/regress-165748.js: Added.
(sum1):
(sum2):
(sum3):
(sum4):
(sum5):
(sum6):
(tailCaller):
(test):

Source/JavaScriptCore:

The virtual slow path for tailcalls always passes arguments on the stack.
The fix here is to link to the stack argument entrypoint instead of a register
argument entrypoint.

While fixing this bug, I found that we weren't clearing the code origin when
shuffling the call frame for a register argument tailcall.

Also rolling back in <a href="http://trac.webkit.org/projects/webkit/changeset/209653">r209653</a>, <a href="http://trac.webkit.org/projects/webkit/changeset/209654">r209654</a>, <a href="http://trac.webkit.org/projects/webkit/changeset/209663">r209663</a>, and <a href="http://trac.webkit.org/projects/webkit/changeset/209673">r209673</a>.

* jit/CallFrameShuffler.cpp:
(JSC::CallFrameShuffler::prepareAny):
* jit/ThunkGenerators.cpp:
(JSC::virtualThunkFor):

Source/WTF:

Rolling back in <a href="http://trac.webkit.org/projects/webkit/changeset/209653">r209653</a>, <a href="http://trac.webkit.org/projects/webkit/changeset/209654">r209654</a>, <a href="http://trac.webkit.org/projects/webkit/changeset/209663">r209663</a>, and <a href="http://trac.webkit.org/projects/webkit/changeset/209673">r209673</a>.

* wtf/Platform.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ArgumentRegValueh">trunk/Source/JavaScriptCore/b3/B3ArgumentRegValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Validatecpp">trunk/Source/JavaScriptCore/b3/B3Validate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallLinkInfocpp">trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallLinkInfoh">trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePolymorphicAccesscpp">trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCPSRethreadingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCommonh">trunk/Source/JavaScriptCore/dfg/DFGCommon.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDCEPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDoesGCcpp">trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDrivercpp">trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGenerationInfoh">trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGraphcpp">trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGraphh">trunk/Source/JavaScriptCore/dfg/DFGGraph.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGInPlaceAbstractStatecpp">trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCompilercpp">trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCompilerh">trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITFinalizercpp">trunk/Source/JavaScriptCore/dfg/DFGJITFinalizer.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITFinalizerh">trunk/Source/JavaScriptCore/dfg/DFGJITFinalizer.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGLiveCatchVariablePreservationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGLiveCatchVariablePreservationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGMaximalFlushInsertionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGMaximalFlushInsertionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGMayExitcpp">trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGMinifiedNodecpp">trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGMinifiedNodeh">trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodecpp">trunk/Source/JavaScriptCore/dfg/DFGNode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRAvailabilityAnalysisPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSREntrypointCreationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPlancpp">trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPreciseLocalClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionInjectionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionInjectionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPutStackSinkingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPutStackSinkingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGRegisterBankh">trunk/Source/JavaScriptCore/dfg/DFGRegisterBank.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSSAConversionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSafeToExecuteh">trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGStrengthReductionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGThunkscpp">trunk/Source/JavaScriptCore/dfg/DFGThunks.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGVariableEventStreamcpp">trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGVirtualRegisterAllocationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLJITCodecpp">trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLJITCodeh">trunk/Source/JavaScriptCore/ftl/FTLJITCode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLJITFinalizercpp">trunk/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLinkcpp">trunk/Source/JavaScriptCore/ftl/FTLLink.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOSREntrycpp">trunk/Source/JavaScriptCore/ftl/FTLOSREntry.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOutputcpp">trunk/Source/JavaScriptCore/ftl/FTLOutput.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOutputh">trunk/Source/JavaScriptCore/ftl/FTLOutput.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterShadowChickencpp">trunk/Source/JavaScriptCore/interpreter/ShadowChicken.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAssemblyHelperscpp">trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAssemblyHelpersh">trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitCachedRecoverycpp">trunk/Source/JavaScriptCore/jit/CachedRecovery.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitCachedRecoveryh">trunk/Source/JavaScriptCore/jit/CachedRecovery.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitCallFrameShuffleDatah">trunk/Source/JavaScriptCore/jit/CallFrameShuffleData.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitCallFrameShufflercpp">trunk/Source/JavaScriptCore/jit/CallFrameShuffler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitCallFrameShufflerh">trunk/Source/JavaScriptCore/jit/CallFrameShuffler.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitCallFrameShuffler64cpp">trunk/Source/JavaScriptCore/jit/CallFrameShuffler64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitGPRInfoh">trunk/Source/JavaScriptCore/jit/GPRInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITcpp">trunk/Source/JavaScriptCore/jit/JIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCallcpp">trunk/Source/JavaScriptCore/jit/JITCall.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCall32_64cpp">trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCodecpp">trunk/Source/JavaScriptCore/jit/JITCode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCodeh">trunk/Source/JavaScriptCore/jit/JITCode.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodescpp">trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodes32_64cpp">trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITThunkscpp">trunk/Source/JavaScriptCore/jit/JITThunks.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITThunksh">trunk/Source/JavaScriptCore/jit/JITThunks.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJSInterfaceJITh">trunk/Source/JavaScriptCore/jit/JSInterfaceJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRegisterSetcpp">trunk/Source/JavaScriptCore/jit/RegisterSet.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRegisterSeth">trunk/Source/JavaScriptCore/jit/RegisterSet.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRepatchcpp">trunk/Source/JavaScriptCore/jit/Repatch.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitSpecializedThunkJITh">trunk/Source/JavaScriptCore/jit/SpecializedThunkJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitThunkGeneratorh">trunk/Source/JavaScriptCore/jit/ThunkGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitThunkGeneratorscpp">trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitThunkGeneratorsh">trunk/Source/JavaScriptCore/jit/ThunkGenerators.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntEntrypointcpp">trunk/Source/JavaScriptCore/llint/LLIntEntrypoint.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntThunkscpp">trunk/Source/JavaScriptCore/llint/LLIntThunks.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntThunksh">trunk/Source/JavaScriptCore/llint/LLIntThunks.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeArityCheckModeh">trunk/Source/JavaScriptCore/runtime/ArityCheckMode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeExecutableBasecpp">trunk/Source/JavaScriptCore/runtime/ExecutableBase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeExecutableBaseh">trunk/Source/JavaScriptCore/runtime/ExecutableBase.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSBoundFunctioncpp">trunk/Source/JavaScriptCore/runtime/JSBoundFunction.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeNativeExecutablecpp">trunk/Source/JavaScriptCore/runtime/NativeExecutable.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeScriptExecutablecpp">trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMcpp">trunk/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmBindingcpp">trunk/Source/JavaScriptCore/wasm/WasmBinding.cpp</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfPlatformh">trunk/Source/WTF/wtf/Platform.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsmicrobenchmarkscallingcomputedargsjs">trunk/JSTests/microbenchmarks/calling-computed-args.js</a></li>
<li><a href="#trunkJSTestsmicrobenchmarkscallingmanycalleesjs">trunk/JSTests/microbenchmarks/calling-many-callees.js</a></li>
<li><a href="#trunkJSTestsmicrobenchmarkscallingonecalleefixedjs">trunk/JSTests/microbenchmarks/calling-one-callee-fixed.js</a></li>
<li><a href="#trunkJSTestsmicrobenchmarkscallingonecalleejs">trunk/JSTests/microbenchmarks/calling-one-callee.js</a></li>
<li><a href="#trunkJSTestsmicrobenchmarkscallingpolycalleesjs">trunk/JSTests/microbenchmarks/calling-poly-callees.js</a></li>
<li><a href="#trunkJSTestsmicrobenchmarkscallingpolyextraaritycalleesjs">trunk/JSTests/microbenchmarks/calling-poly-extra-arity-callees.js</a></li>
<li><a href="#trunkJSTestsmicrobenchmarkscallingtailcalljs">trunk/JSTests/microbenchmarks/calling-tailcall.js</a></li>
<li><a href="#trunkJSTestsmicrobenchmarkscallingvirtualarityfixupcalleesjs">trunk/JSTests/microbenchmarks/calling-virtual-arity-fixup-callees.js</a></li>
<li><a href="#trunkJSTestsmicrobenchmarkscallingvirtualarityfixupstackargsjs">trunk/JSTests/microbenchmarks/calling-virtual-arity-fixup-stackargs.js</a></li>
<li><a href="#trunkJSTestsmicrobenchmarkscallingvirtualcalleesjs">trunk/JSTests/microbenchmarks/calling-virtual-callees.js</a></li>
<li><a href="#trunkJSTestsmicrobenchmarkscallingvirtualextraaritycalleesjs">trunk/JSTests/microbenchmarks/calling-virtual-extra-arity-callees.js</a></li>
<li><a href="#trunkJSTestsstressregress165728js">trunk/JSTests/stress/regress-165728.js</a></li>
<li><a href="#trunkJSTestsstressregress165748js">trunk/JSTests/stress/regress-165748.js</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITEntryPointsh">trunk/Source/JavaScriptCore/jit/JITEntryPoints.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/JSTests/ChangeLog        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2016-12-12  Michael Saboff  &lt;msaboff@apple.com&gt;
+
+        REGRESSION(r209653): speedometer crashes making virtual slow path tailcalls
+        https://bugs.webkit.org/show_bug.cgi?id=165748
+
+        Reviewed by Filip Pizlo.
+
+        New regression test.
+
+        * stress/regress-165748.js: Added.
+        (sum1):
+        (sum2):
+        (sum3):
+        (sum4):
+        (sum5):
+        (sum6):
+        (tailCaller):
+        (test):
+
</ins><span class="cx"> 2016-12-12  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Debug JSC test timeout: stress/string-prototype-replace-should-throw-out-of-memory-error-when-using-too-much-memory.js.ftl-no-cjit.
</span></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkscallingcomputedargsjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/calling-computed-args.js (0 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/calling-computed-args.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/calling-computed-args.js        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -0,0 +1,53 @@
</span><ins>+function sum2(a, b)
+{
+    return a + b;
+}
+
+noInline(sum2);
+
+function sum2b(a, b)
+{
+    return a + b;
+}
+
+noInline(sum2b);
+
+function sum3(a, b, c)
+{
+    return a + b + c;
+}
+
+noInline(sum3);
+
+function sum3b(a, b, c)
+{
+    return a + b + c;
+}
+
+noInline(sum3b);
+
+function test()
+{
+    let o1 = {
+        one: 1,
+        two: 2
+    }
+    let o2 = {
+        three: 3,
+        five: 5
+    };
+    let o3 = {
+        four: 4,
+        six: 6
+    };
+    let result = 0;
+    for (let i = 0; i &lt; 2000000; i++)
+        result = sum2(o1.one, o2.five) + sum2b(o1.two, o1.one + o2.five)
+            + sum3(o2.three, o3.four, o2.five) + sum3b(o1.two, o2.three + o2.five, o3.six);
+
+    return result;
+}
+
+let result = test();
+if (result != 42)
+    throw &quot;Unexpected result: &quot; + result;
</ins></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkscallingmanycalleesjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/calling-many-callees.js (0 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/calling-many-callees.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/calling-many-callees.js        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+function sum2(a, b)
+{
+    return a + b;
+}
+
+noInline(sum2);
+
+function sum2b(a, b)
+{
+    return a + b + b;
+}
+
+noInline(sum2b);
+
+function sum3(a, b, c)
+{
+    return a + b + c;
+}
+
+noInline(sum3);
+
+function sum3b(a, b, c)
+{
+    return a + b + b + c;
+}
+
+noInline(sum3b);
+
+function test()
+{
+    let result = 0;
+    for (let i = 0; i &lt; 2000000; i++)
+        result = sum2(1, 2) + sum2b(2, 3) + sum3(5, 5, 5) + sum3b(2, 4, 6);
+
+    return result;
+}
+
+let result = test();
+if (result != 42)
+    throw &quot;Unexpected result: &quot; + result;
</ins></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkscallingonecalleefixedjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/calling-one-callee-fixed.js (0 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/calling-one-callee-fixed.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/calling-one-callee-fixed.js        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -0,0 +1,19 @@
</span><ins>+function sum(a, b, c)
+{
+    return a + b + c;
+}
+
+noInline(sum);
+
+function test()
+{
+    let result = 0;
+    for (let i = 0; i &lt; 4000000; i++)
+        result = sum(1, 2, 3);
+
+    return result;
+}
+
+let result = test();
+if (result != 6)
+    throw &quot;Unexpected result: &quot; + result;
</ins></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkscallingonecalleejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/calling-one-callee.js (0 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/calling-one-callee.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/calling-one-callee.js        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -0,0 +1,19 @@
</span><ins>+function sum(a, b, c)
+{
+    return a + b + c;
+}
+
+noInline(sum);
+
+function test(a, b, c)
+{
+    let result = 0;
+    for (let i = 0; i &lt; 4000000; i++)
+        result = sum(a, b, c);
+
+    return result;
+}
+
+let result = test(1, 2, 3);
+if (result != 6)
+    throw &quot;Unexpected result: &quot; + result;
</ins></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkscallingpolycalleesjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/calling-poly-callees.js (0 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/calling-poly-callees.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/calling-poly-callees.js        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -0,0 +1,35 @@
</span><ins>+function sum1(a, b, c)
+{
+    return a + b + c;
+}
+
+noInline(sum1);
+
+function sum2(a, b, c)
+{
+    return b + a + c;
+}
+
+noInline(sum2);
+
+function sum3(a, b, c)
+{
+    return c + a + b;
+}
+
+noInline(sum3);
+
+let functions = [ sum1, sum2, sum3 ];
+
+function test(a, b, c)
+{
+    let result = 0;
+    for (let i = 0; i &lt; 4000000; i++)
+        result = functions[i % 3](a, b, c);
+
+    return result;
+}
+
+let result = test(2, 10, 30);
+if (result != 42)
+    throw &quot;Unexpected result: &quot; + result;
</ins></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkscallingpolyextraaritycalleesjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/calling-poly-extra-arity-callees.js (0 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/calling-poly-extra-arity-callees.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/calling-poly-extra-arity-callees.js        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -0,0 +1,35 @@
</span><ins>+function sum1(a, b)
+{
+    return a + b;
+}
+
+noInline(sum1);
+
+function sum2(a, b)
+{
+    return b + a;
+}
+
+noInline(sum2);
+
+function sum3(a, b)
+{
+    return a + b;
+}
+
+noInline(sum3);
+
+let functions = [ sum1, sum2, sum3 ];
+
+function test(a, b, c)
+{
+    let result = 0;
+    for (let i = 0; i &lt; 4000000; i++)
+        result = functions[i % 3](a, b, c);
+
+    return result;
+}
+
+let result = test(2, 40, &quot;Test&quot;);
+if (result != 42)
+    throw &quot;Unexpected result: &quot; + result;
</ins></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkscallingtailcalljs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/calling-tailcall.js (0 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/calling-tailcall.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/calling-tailcall.js        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -0,0 +1,28 @@
</span><ins>+&quot;use strict&quot;;
+
+function sum(a, b, c)
+{
+    return a + b + c;
+}
+
+noInline(sum);
+
+function tailCaller(a, b, c)
+{
+    return sum(b, a, c);
+}
+
+noInline(tailCaller);
+
+function test(a, b, c)
+{
+    let result = 0;
+    for (let i = 0; i &lt; 4000000; i++)
+        result = tailCaller(a, b, c);
+
+    return result;
+}
+
+let result = test(1, 2, 3);
+if (result != 6)
+    throw &quot;Unexpected result: &quot; + result;
</ins></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkscallingvirtualarityfixupcalleesjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/calling-virtual-arity-fixup-callees.js (0 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/calling-virtual-arity-fixup-callees.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/calling-virtual-arity-fixup-callees.js        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -0,0 +1,56 @@
</span><ins>+function sum1(a, b, c)
+{
+    return a + b + (c | 0);
+}
+
+noInline(sum1);
+
+function sum2(a, b, c)
+{
+    return b + a + (c | 0);
+}
+
+noInline(sum2);
+
+function sum3(a, b, c)
+{
+    return (c | 0) + a + b;
+}
+
+noInline(sum3);
+
+function sum4(a, b, c)
+{
+    return (c | 0) + a + b;
+}
+
+noInline(sum4);
+
+function sum5(a, b, c)
+{
+    return (c | 0) + a + b;
+}
+
+noInline(sum5);
+
+function sum6(a, b, c)
+{
+    return (c | 0) + a + b;
+}
+
+noInline(sum6);
+
+let functions = [ sum1, sum2, sum3, sum4, sum5, sum6 ];
+
+function test(a, b)
+{
+    let result = 0;
+    for (let i = 0; i &lt; 4000000; i++)
+        result = functions[i % 6](a, b);
+
+    return result;
+}
+
+let result = test(2, 40);
+if (result != 42)
+    throw &quot;Unexpected result: &quot; + result;
</ins></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkscallingvirtualarityfixupstackargsjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/calling-virtual-arity-fixup-stackargs.js (0 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/calling-virtual-arity-fixup-stackargs.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/calling-virtual-arity-fixup-stackargs.js        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -0,0 +1,56 @@
</span><ins>+function sum1(a, b, c, d)
+{
+    return a + b + c + (d | 0);
+}
+
+noInline(sum1);
+
+function sum2(a, b, c, d)
+{
+    return b + a + c + (d | 0);
+}
+
+noInline(sum2);
+
+function sum3(a, b, c, d)
+{
+    return (d | 0) + a + b + c;
+}
+
+noInline(sum3);
+
+function sum4(a, b, c, d)
+{
+    return (d | 0) + a + b + c;
+}
+
+noInline(sum4);
+
+function sum5(a, b, c, d)
+{
+    return (d | 0) + a + b + c;
+}
+
+noInline(sum5);
+
+function sum6(a, b, c, d)
+{
+    return (d | 0) + a + b + c;
+}
+
+noInline(sum6);
+
+let functions = [ sum1, sum2, sum3, sum4, sum5, sum6 ];
+
+function test(a, b, c)
+{
+    let result = 0;
+    for (let i = 0; i &lt; 4000000; i++)
+        result = functions[i % 6](a, b, c);
+
+    return result;
+}
+
+let result = test(2, 10, 30);
+if (result != 42)
+    throw &quot;Unexpected result: &quot; + result;
</ins></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkscallingvirtualcalleesjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/calling-virtual-callees.js (0 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/calling-virtual-callees.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/calling-virtual-callees.js        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -0,0 +1,56 @@
</span><ins>+function sum1(a, b, c)
+{
+    return a + b + c;
+}
+
+noInline(sum1);
+
+function sum2(a, b, c)
+{
+    return b + a + c;
+}
+
+noInline(sum2);
+
+function sum3(a, b, c)
+{
+    return c + a + b;
+}
+
+noInline(sum3);
+
+function sum4(a, b, c)
+{
+    return c + a + b;
+}
+
+noInline(sum4);
+
+function sum5(a, b, c)
+{
+    return c + a + b;
+}
+
+noInline(sum5);
+
+function sum6(a, b, c)
+{
+    return c + a + b;
+}
+
+noInline(sum6);
+
+let functions = [ sum1, sum2, sum3, sum4, sum5, sum6 ];
+
+function test(a, b, c)
+{
+    let result = 0;
+    for (let i = 0; i &lt; 4000000; i++)
+        result = functions[i % 6](a, b, c);
+
+    return result;
+}
+
+let result = test(2, 10, 30);
+if (result != 42)
+    throw &quot;Unexpected result: &quot; + result;
</ins></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkscallingvirtualextraaritycalleesjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/calling-virtual-extra-arity-callees.js (0 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/calling-virtual-extra-arity-callees.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/calling-virtual-extra-arity-callees.js        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -0,0 +1,56 @@
</span><ins>+function sum1(a, b)
+{
+    return a + b;
+}
+
+noInline(sum1);
+
+function sum2(a, b)
+{
+    return b + a;
+}
+
+noInline(sum2);
+
+function sum3(a, b)
+{
+    return a + b;
+}
+
+noInline(sum3);
+
+function sum4(a, b)
+{
+    return a + b;
+}
+
+noInline(sum4);
+
+function sum5(a, b)
+{
+    return a + b;
+}
+
+noInline(sum5);
+
+function sum6(a, b)
+{
+    return a + b;
+}
+
+noInline(sum6);
+
+let functions = [ sum1, sum2, sum3, sum4, sum5, sum6 ];
+
+function test(a, b, c)
+{
+    let result = 0;
+    for (let i = 0; i &lt; 4000000; i++)
+        result = functions[i % 6](a, b, c);
+
+    return result;
+}
+
+let result = test(40, 2, &quot;Test&quot;);
+if (result != 42)
+    throw &quot;Unexpected result: &quot; + result;
</ins></span></pre></div>
<a id="trunkJSTestsstressregress165728js"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/regress-165728.js (0 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/regress-165728.js                                (rev 0)
+++ trunk/JSTests/stress/regress-165728.js        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -0,0 +1,36 @@
</span><ins>+// Test for REGRESSION(r209653) Crash in CallFrameShuffler::snapshot() - This test shouldn't crash.
+&quot;use strict&quot;;
+
+function sum1(a, b, c)
+{
+    return a + b + c;
+}
+
+noInline(sum1);
+
+function sum2(a, b, c)
+{
+    return a + b + c;
+}
+
+noInline(sum2);
+
+function tailCaller(f, a, b)
+{
+    return f(a, b, a)
+}
+
+noInline(tailCaller);
+
+function test(a, b)
+{
+    let result = 0;
+    for (let i = 0; i &lt; 4000000; i++)
+        result = tailCaller(i % 2 ? sum1 : sum2, a, b);
+
+    return result;
+}
+
+let result = test(20, 2);
+if (result != 42)
+    throw &quot;Unexpected result: &quot; + result;
</ins></span></pre></div>
<a id="trunkJSTestsstressregress165748js"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/regress-165748.js (0 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/regress-165748.js                                (rev 0)
+++ trunk/JSTests/stress/regress-165748.js        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -0,0 +1,75 @@
</span><ins>+&quot;use strict&quot;;
+
+function sum1(a, b, c)
+{
+    return a + b + c;
+}
+
+noInline(sum1);
+
+function sum2(a, b, c)
+{
+    return b + a + c;
+}
+
+noInline(sum2);
+
+function sum3(a, b, c)
+{
+    return c + a + b;
+}
+
+noInline(sum3);
+
+function sum4(a, b, c)
+{
+    return c + a + b;
+}
+
+noInline(sum4);
+
+function sum5(a, b, c)
+{
+    return c + a + b;
+}
+
+noInline(sum5);
+
+function sum6(a, b, c)
+{
+    return c + a + b;
+}
+
+noInline(sum6);
+
+let functions = [ sum1, sum2, sum3, sum4, sum5, sum6 ];
+
+function tailCaller(o)
+{
+    let a = o.a;
+    let b = o.b;
+    let c = o.c;
+    
+    return functions[o.i % 6](a, b, c);
+}
+
+noInline(tailCaller);
+
+function test(a, b, c)
+{
+    let obj = {};
+    obj.a = a;
+    obj.b = b;
+    obj.c = c;
+    let result = 0;
+    for (let i = 0; i &lt; 4000000; i++) {
+        obj.i = i;
+        obj.val = tailCaller(obj);
+    }
+
+    return obj;
+}
+
+let result = test(2, 10, 30);
+if (result.val != 42)
+    throw &quot;Unexpected result: &quot; + result.val;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2016-12-12  Michael Saboff  &lt;msaboff@apple.com&gt;
+
+        REGRESSION(r209653): speedometer crashes making virtual slow path tailcalls
+        https://bugs.webkit.org/show_bug.cgi?id=165748
+
+        Reviewed by Filip Pizlo.
+
+        The virtual slow path for tailcalls always passes arguments on the stack.
+        The fix here is to link to the stack argument entrypoint instead of a register
+        argument entrypoint.
+
+        While fixing this bug, I found that we weren't clearing the code origin when
+        shuffling the call frame for a register argument tailcall.
+
+        Also rolling back in r209653, r209654, r209663, and r209673.
+
+        * jit/CallFrameShuffler.cpp:
+        (JSC::CallFrameShuffler::prepareAny):
+        * jit/ThunkGenerators.cpp:
+        (JSC::virtualThunkFor):
+
</ins><span class="cx"> 2016-12-12  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Rename BytecodeGenerator's m_symbolTableStack to m_lexicalScopeStack.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -1351,6 +1351,7 @@
</span><span class="cx">                 65C02850171795E200351E35 /* ARMv7Disassembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65C0284F171795E200351E35 /* ARMv7Disassembler.cpp */; };
</span><span class="cx">                 65C0285C1717966800351E35 /* ARMv7DOpcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65C0285A1717966800351E35 /* ARMv7DOpcode.cpp */; };
</span><span class="cx">                 65C0285D1717966800351E35 /* ARMv7DOpcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 65C0285B1717966800351E35 /* ARMv7DOpcode.h */; };
</span><ins>+                65DBF3021D93392B003AF4B0 /* JITEntryPoints.h in Headers */ = {isa = PBXBuildFile; fileRef = 650300F21C50274600D786D7 /* JITEntryPoints.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 65FB5117184EEE7000C12B70 /* ProtoCallFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65FB5116184EE9BC00C12B70 /* ProtoCallFrame.cpp */; };
</span><span class="cx">                 65FB63A41C8EA09C0020719B /* YarrCanonicalizeUnicode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65A946141C8E9F6F00A7209A /* YarrCanonicalizeUnicode.cpp */; };
</span><span class="cx">                 6AD2CB4D19B9140100065719 /* DebuggerEvalEnabler.h in Headers */ = {isa = PBXBuildFile; fileRef = 6AD2CB4C19B9140100065719 /* DebuggerEvalEnabler.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -3722,6 +3723,7 @@
</span><span class="cx">                 62E3D5EF1B8D0B7300B868BB /* DataFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DataFormat.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 62EC9BB41B7EB07C00303AD1 /* CallFrameShuffleData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallFrameShuffleData.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 62EC9BB51B7EB07C00303AD1 /* CallFrameShuffleData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallFrameShuffleData.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                650300F21C50274600D786D7 /* JITEntryPoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITEntryPoints.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 6507D2970E871E4A00D7D896 /* JSTypeInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypeInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 651122E5140469BA002B101D /* testRegExp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = testRegExp.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 6511230514046A4C002B101D /* testRegExp */ = {isa = PBXFileReference; explicitFileType = &quot;compiled.mach-o.executable&quot;; includeInIndex = 0; path = testRegExp; sourceTree = BUILT_PRODUCTS_DIR; };
</span><span class="lines">@@ -5560,6 +5562,7 @@
</span><span class="cx">                                 0FAF7EFB165BA919000C8455 /* JITDisassembler.h */,
</span><span class="cx">                                 FE187A0A1C0229230038BBCA /* JITDivGenerator.cpp */,
</span><span class="cx">                                 FE187A0B1C0229230038BBCA /* JITDivGenerator.h */,
</span><ins>+                                650300F21C50274600D786D7 /* JITEntryPoints.h */,
</ins><span class="cx">                                 0F46807F14BA572700BFE272 /* JITExceptions.cpp */,
</span><span class="cx">                                 0F46808014BA572700BFE272 /* JITExceptions.h */,
</span><span class="cx">                                 0FB14E1C18124ACE009B6B4D /* JITInlineCacheGenerator.cpp */,
</span><span class="lines">@@ -7717,6 +7720,7 @@
</span><span class="cx">                                 79B00CBD1C6AB07E0088C65D /* ProxyConstructor.h in Headers */,
</span><span class="cx">                                 53D444DC1DAF08AB00B92784 /* B3WasmAddressValue.h in Headers */,
</span><span class="cx">                                 990DA67F1C8E316A00295159 /* generate_objc_protocol_type_conversions_implementation.py in Headers */,
</span><ins>+                                65DBF3021D93392B003AF4B0 /* JITEntryPoints.h in Headers */,
</ins><span class="cx">                                 DC17E8191C9C91DB008A6AB3 /* ShadowChickenInlines.h in Headers */,
</span><span class="cx">                                 DC17E8181C9C91D9008A6AB3 /* ShadowChicken.h in Headers */,
</span><span class="cx">                                 799EF7C41C56ED96002B0534 /* B3PCToOriginMap.h in Headers */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ArgumentRegValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ArgumentRegValue.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ArgumentRegValue.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/b3/B3ArgumentRegValue.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -55,6 +55,13 @@
</span><span class="cx">         ASSERT(reg.isSet());
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ArgumentRegValue(Origin origin, Reg reg, Type type)
+        : Value(CheckedOpcode, ArgumentReg, type, origin)
+        , m_reg(reg)
+    {
+        ASSERT(reg.isSet());
+    }
+
</ins><span class="cx">     Reg m_reg;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Validatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Validate.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Validate.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/b3/B3Validate.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -182,9 +182,12 @@
</span><span class="cx">             case ArgumentReg:
</span><span class="cx">                 VALIDATE(!value-&gt;kind().hasExtraBits(), (&quot;At &quot;, *value));
</span><span class="cx">                 VALIDATE(!value-&gt;numChildren(), (&quot;At &quot;, *value));
</span><del>-                VALIDATE(
-                    (value-&gt;as&lt;ArgumentRegValue&gt;()-&gt;argumentReg().isGPR() ? pointerType() : Double)
-                    == value-&gt;type(), (&quot;At &quot;, *value));
</del><ins>+                // FIXME: https://bugs.webkit.org/show_bug.cgi?id=165717
+                // We need to handle Int32 arguments and Int64 arguments
+                // for the same register distinctly.
+                VALIDATE((value-&gt;as&lt;ArgumentRegValue&gt;()-&gt;argumentReg().isGPR()
+                    ? (value-&gt;type() == pointerType() || value-&gt;type() == Int32)
+                    : value-&gt;type() == Double), (&quot;At &quot;, *value));
</ins><span class="cx">                 break;
</span><span class="cx">             case Add:
</span><span class="cx">             case Sub:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkInfocpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -60,6 +60,7 @@
</span><span class="cx">     , m_hasSeenClosure(false)
</span><span class="cx">     , m_clearedByGC(false)
</span><span class="cx">     , m_allowStubs(true)
</span><ins>+    , m_argumentsLocation(static_cast&lt;unsigned&gt;(ArgumentsLocation::StackArgs))
</ins><span class="cx">     , m_isLinked(false)
</span><span class="cx">     , m_callType(None)
</span><span class="cx">     , m_calleeGPR(255)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #include &quot;CallMode.h&quot;
</span><span class="cx"> #include &quot;CodeLocation.h&quot;
</span><span class="cx"> #include &quot;CodeSpecializationKind.h&quot;
</span><ins>+#include &quot;JITEntryPoints.h&quot;
</ins><span class="cx"> #include &quot;PolymorphicCallStubRoutine.h&quot;
</span><span class="cx"> #include &quot;WriteBarrier.h&quot;
</span><span class="cx"> #include &lt;wtf/SentinelLinkedList.h&gt;
</span><span class="lines">@@ -157,9 +158,12 @@
</span><span class="cx">     bool isLinked() { return m_stub || m_calleeOrCodeBlock; }
</span><span class="cx">     void unlink(VM&amp;);
</span><span class="cx"> 
</span><del>-    void setUpCall(CallType callType, CodeOrigin codeOrigin, unsigned calleeGPR)
</del><ins>+    void setUpCall(CallType callType, ArgumentsLocation argumentsLocation, CodeOrigin codeOrigin, unsigned calleeGPR)
</ins><span class="cx">     {
</span><ins>+        ASSERT(!isVarargsCallType(callType) || (argumentsLocation == StackArgs));
+
</ins><span class="cx">         m_callType = callType;
</span><ins>+        m_argumentsLocation = static_cast&lt;unsigned&gt;(argumentsLocation);
</ins><span class="cx">         m_codeOrigin = codeOrigin;
</span><span class="cx">         m_calleeGPR = calleeGPR;
</span><span class="cx">     }
</span><span class="lines">@@ -275,6 +279,16 @@
</span><span class="cx">         return static_cast&lt;CallType&gt;(m_callType);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ArgumentsLocation argumentsLocation()
+    {
+        return static_cast&lt;ArgumentsLocation&gt;(m_argumentsLocation);
+    }
+
+    bool argumentsInRegisters()
+    {
+        return m_argumentsLocation != StackArgs;
+    }
+
</ins><span class="cx">     uint32_t* addressOfMaxNumArguments()
</span><span class="cx">     {
</span><span class="cx">         return &amp;m_maxNumArguments;
</span><span class="lines">@@ -339,6 +353,7 @@
</span><span class="cx">     bool m_hasSeenClosure : 1;
</span><span class="cx">     bool m_clearedByGC : 1;
</span><span class="cx">     bool m_allowStubs : 1;
</span><ins>+    unsigned m_argumentsLocation : 4;
</ins><span class="cx">     bool m_isLinked : 1;
</span><span class="cx">     unsigned m_callType : 4; // CallType
</span><span class="cx">     unsigned m_calleeGPR : 8;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePolymorphicAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -1032,7 +1032,7 @@
</span><span class="cx">             m_rareData-&gt;callLinkInfo-&gt;disallowStubs();
</span><span class="cx">             
</span><span class="cx">             m_rareData-&gt;callLinkInfo-&gt;setUpCall(
</span><del>-                CallLinkInfo::Call, stubInfo.codeOrigin, loadedValueGPR);
</del><ins>+                CallLinkInfo::Call, StackArgs, stubInfo.codeOrigin, loadedValueGPR);
</ins><span class="cx"> 
</span><span class="cx">             CCallHelpers::JumpList done;
</span><span class="cx"> 
</span><span class="lines">@@ -1105,7 +1105,7 @@
</span><span class="cx">             // We *always* know that the getter/setter, if non-null, is a cell.
</span><span class="cx">             jit.move(CCallHelpers::TrustedImm32(JSValue::CellTag), GPRInfo::regT1);
</span><span class="cx"> #endif
</span><del>-            jit.move(CCallHelpers::TrustedImmPtr(m_rareData-&gt;callLinkInfo.get()), GPRInfo::regT2);
</del><ins>+            jit.move(CCallHelpers::TrustedImmPtr(m_rareData-&gt;callLinkInfo.get()), GPRInfo::nonArgGPR0);
</ins><span class="cx">             slowPathCall = jit.nearCall();
</span><span class="cx">             if (m_type == Getter)
</span><span class="cx">                 jit.setupResults(valueRegs);
</span><span class="lines">@@ -1131,7 +1131,7 @@
</span><span class="cx"> 
</span><span class="cx">                     linkBuffer.link(
</span><span class="cx">                         slowPathCall,
</span><del>-                        CodeLocationLabel(vm.getCTIStub(linkCallThunkGenerator).code()));
</del><ins>+                        CodeLocationLabel(vm.getJITCallThunkEntryStub(linkCallThunkGenerator).entryFor(StackArgs)));
</ins><span class="cx">                 });
</span><span class="cx">         } else {
</span><span class="cx">             ASSERT(m_type == CustomValueGetter || m_type == CustomAccessorGetter || m_type == CustomValueSetter || m_type == CustomAccessorSetter);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -271,7 +271,17 @@
</span><span class="cx">         // non-clear value.
</span><span class="cx">         ASSERT(!m_state.variables().operand(node-&gt;local()).isClear());
</span><span class="cx">         break;
</span><del>-        
</del><ins>+
+    case GetArgumentRegister:
+        ASSERT(!m_state.variables().operand(node-&gt;local()).isClear());
+        if (node-&gt;variableAccessData()-&gt;flushFormat() == FlushedJSValue) {
+            forNode(node).makeBytecodeTop();
+            break;
+        }
+
+        forNode(node).setType(m_graph, typeFilterFor(node-&gt;variableAccessData()-&gt;flushFormat()));
+        break;
+
</ins><span class="cx">     case LoadVarargs:
</span><span class="cx">     case ForwardVarargs: {
</span><span class="cx">         // FIXME: ForwardVarargs should check if the count becomes known, and if it does, it should turn
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -3697,11 +3697,59 @@
</span><span class="cx">     // us to track if a use of an argument may use the actual argument passed, as
</span><span class="cx">     // opposed to using a value we set explicitly.
</span><span class="cx">     if (m_currentBlock == m_graph.block(0) &amp;&amp; !inlineCallFrame()) {
</span><del>-        m_graph.m_arguments.resize(m_numArguments);
-        // We will emit SetArgument nodes. They don't exit, but we're at the top of an op_enter so
-        // exitOK = true.
</del><ins>+        m_graph.m_argumentsOnStack.resize(m_numArguments);
+        m_graph.m_argumentsForChecking.resize(m_numArguments);
+        // Create all GetArgumentRegister nodes first and then the corresponding MovHint nodes,
+        // followed by the corresponding SetLocal nodes and finally any SetArgument nodes for
+        // the remaining arguments.
+        // We do this to make the exit processing correct. We start with m_exitOK = true since
+        // GetArgumentRegister nodes can exit, even though they don't. The MovHint's technically could
+        // exit but won't. The SetLocals can exit and therefore we want all the MovHints
+        // before the first SetLocal so that the register state is consistent.
+        // We do all this processing before creating any SetArgument nodes since they are
+        // morally equivalent to the SetLocals for GetArgumentRegister nodes.
</ins><span class="cx">         m_exitOK = true;
</span><del>-        for (unsigned argument = 0; argument &lt; m_numArguments; ++argument) {
</del><ins>+        
+        unsigned numRegisterArguments = std::min(m_numArguments, NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS);
+
+        Vector&lt;Node*, NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS&gt; getArgumentRegisterNodes;
+
+        // First create GetArgumentRegister nodes.
+        for (unsigned argument = 0; argument &lt; numRegisterArguments; ++argument) {
+            getArgumentRegisterNodes.append(
+                addToGraph(GetArgumentRegister, OpInfo(0),
+                    OpInfo(argumentRegisterIndexForJSFunctionArgument(argument))));
+        }
+
+        // Create all the MovHint's for the GetArgumentRegister nodes created above.
+        for (unsigned i = 0; i &lt; getArgumentRegisterNodes.size(); ++i) {
+            Node* getArgumentRegister = getArgumentRegisterNodes[i];
+            addToGraph(MovHint, OpInfo(virtualRegisterForArgument(i).offset()), getArgumentRegister);
+            // We can't exit anymore.
+            m_exitOK = false;
+        }
+
+        // Exit is now okay, but we need to fence with an ExitOK node.
+        m_exitOK = true;
+        addToGraph(ExitOK);
+
+        // Create all the SetLocals's for the GetArgumentRegister nodes created above.
+        for (unsigned i = 0; i &lt; getArgumentRegisterNodes.size(); ++i) {
+            Node* getArgumentRegister = getArgumentRegisterNodes[i];
+            VariableAccessData* variableAccessData = newVariableAccessData(virtualRegisterForArgument(i));
+            variableAccessData-&gt;mergeStructureCheckHoistingFailed(
+                m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, BadCache));
+            variableAccessData-&gt;mergeCheckArrayHoistingFailed(
+                m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, BadIndexingType));
+            Node* setLocal = addToGraph(SetLocal, OpInfo(variableAccessData), getArgumentRegister);
+            m_currentBlock-&gt;variablesAtTail.argument(i) = setLocal;
+            getArgumentRegister-&gt;setVariableAccessData(setLocal-&gt;variableAccessData());
+            m_graph.m_argumentsOnStack[i] = setLocal;
+            m_graph.m_argumentsForChecking[i] = getArgumentRegister;
+        }
+
+        // Finally create any SetArgument nodes.
+        for (unsigned argument = NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argument &lt; m_numArguments; ++argument) {
</ins><span class="cx">             VariableAccessData* variable = newVariableAccessData(
</span><span class="cx">                 virtualRegisterForArgument(argument));
</span><span class="cx">             variable-&gt;mergeStructureCheckHoistingFailed(
</span><span class="lines">@@ -3710,7 +3758,8 @@
</span><span class="cx">                 m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, BadIndexingType));
</span><span class="cx">             
</span><span class="cx">             Node* setArgument = addToGraph(SetArgument, OpInfo(variable));
</span><del>-            m_graph.m_arguments[argument] = setArgument;
</del><ins>+            m_graph.m_argumentsOnStack[argument] = setArgument;
+            m_graph.m_argumentsForChecking[argument] = setArgument;
</ins><span class="cx">             m_currentBlock-&gt;variablesAtTail.setArgumentFirstTime(argument, setArgument);
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -4820,8 +4869,10 @@
</span><span class="cx">             // We need to make sure that we don't unbox our arguments here since that won't be
</span><span class="cx">             // done by the arguments object creation node as that node may not exist.
</span><span class="cx">             noticeArgumentsUse();
</span><ins>+            Terminality terminality = handleVarargsCall(currentInstruction, TailCallForwardVarargs, CallMode::Tail);
+            // We need to insert flush nodes for our arguments after the TailCallForwardVarargs
+            // node so that they will be flushed to the stack and kept alive.
</ins><span class="cx">             flushForReturn();
</span><del>-            Terminality terminality = handleVarargsCall(currentInstruction, TailCallForwardVarargs, CallMode::Tail);
</del><span class="cx">             ASSERT_WITH_MESSAGE(m_currentInstruction == currentInstruction, &quot;handleVarargsCall, which may have inlined the callee, trashed m_currentInstruction&quot;);
</span><span class="cx">             // If the call is terminal then we should not parse any further bytecodes as the TailCall will exit the function.
</span><span class="cx">             // If the call is not terminal, however, then we want the subsequent op_ret/op_jump to update metadata and clean
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCPSRethreadingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -299,14 +299,16 @@
</span><span class="cx">             // The rules for threaded CPS form:
</span><span class="cx">             // 
</span><span class="cx">             // Head variable: describes what is live at the head of the basic block.
</span><del>-            // Head variable links may refer to Flush, PhantomLocal, Phi, or SetArgument.
-            // SetArgument may only appear in the root block.
</del><ins>+            // Head variable links may refer to Flush, PhantomLocal, Phi, GetArgumentRegister
+            // or SetArgument.
+            // GetArgumentRegister and SetArgument may only appear in the root block.
</ins><span class="cx">             //
</span><span class="cx">             // Tail variable: the last thing that happened to the variable in the block.
</span><del>-            // It may be a Flush, PhantomLocal, GetLocal, SetLocal, SetArgument, or Phi.
-            // SetArgument may only appear in the root block. Note that if there ever
-            // was a GetLocal to the variable, and it was followed by PhantomLocals and
-            // Flushes but not SetLocals, then the tail variable will be the GetLocal.
</del><ins>+            // It may be a Flush, PhantomLocal, GetLocal, SetLocal, GetArgumentRegister,
+            // SetArgument, or Phi. GetArgumentRegister and SetArgument may only appear
+            // in the root block. Note that if there ever was a GetLocal to the variable,
+            // and it was followed by PhantomLocals and Flushes but not SetLocals, then
+            // the tail variable will be the GetLocal.
</ins><span class="cx">             // This reflects the fact that you only care that the tail variable is a
</span><span class="cx">             // Flush or PhantomLocal if nothing else interesting happened. Likewise, if
</span><span class="cx">             // there ever was a SetLocal and it was followed by Flushes, then the tail
</span><span class="lines">@@ -367,12 +369,13 @@
</span><span class="cx">     
</span><span class="cx">     void specialCaseArguments()
</span><span class="cx">     {
</span><del>-        // Normally, a SetArgument denotes the start of a live range for a local's value on the stack.
-        // But those SetArguments used for the actual arguments to the machine CodeBlock get
-        // special-cased. We could have instead used two different node types - one for the arguments
-        // at the prologue case, and another for the other uses. But this seemed like IR overkill.
-        for (unsigned i = m_graph.m_arguments.size(); i--;)
-            m_graph.block(0)-&gt;variablesAtHead.setArgumentFirstTime(i, m_graph.m_arguments[i]);
</del><ins>+        // Normally, a SetArgument or SetLocal denotes the start of a live range for
+        // a local's value on the stack. But those SetArguments and SetLocals used
+        // for the actual arguments to the machine CodeBlock get special-cased. We could have
+        // instead used two different node types - one for the arguments at the prologue case,
+        // and another for the other uses. But this seemed like IR overkill.
+        for (unsigned i = m_graph.m_argumentsOnStack.size(); i--;)
+            m_graph.block(0)-&gt;variablesAtHead.setArgumentFirstTime(i, m_graph.m_argumentsOnStack[i]);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     template&lt;OperandKind operandKind&gt;
</span><span class="lines">@@ -480,6 +483,7 @@
</span><span class="cx">             switch (node-&gt;op()) {
</span><span class="cx">             case SetLocal:
</span><span class="cx">             case SetArgument:
</span><ins>+            case GetArgumentRegister:
</ins><span class="cx">                 break;
</span><span class="cx">                 
</span><span class="cx">             case Flush:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -406,6 +406,7 @@
</span><span class="cx">     case Phi:
</span><span class="cx">     case PhantomLocal:
</span><span class="cx">     case SetArgument:
</span><ins>+    case GetArgumentRegister:
</ins><span class="cx">     case Jump:
</span><span class="cx">     case Branch:
</span><span class="cx">     case Switch:
</span><span class="lines">@@ -470,7 +471,7 @@
</span><span class="cx">     case PhantomClonedArguments:
</span><span class="cx">         // DFG backend requires that the locals that this reads are flushed. FTL backend can handle those
</span><span class="cx">         // locals being promoted.
</span><del>-        if (!isFTL(graph.m_plan.mode))
</del><ins>+        if (!isFTL(graph.m_plan.mode) &amp;&amp; !node-&gt;origin.semantic.inlineCallFrame)
</ins><span class="cx">             read(Stack);
</span><span class="cx">         
</span><span class="cx">         // Even though it's phantom, it still has the property that one can't be replaced with another.
</span><span class="lines">@@ -559,11 +560,18 @@
</span><span class="cx">     case TailCall:
</span><span class="cx">     case DirectTailCall:
</span><span class="cx">     case TailCallVarargs:
</span><ins>+        read(World);
+        write(SideState);
+        return;
+        
</ins><span class="cx">     case TailCallForwardVarargs:
</span><ins>+        // We read all arguments after &quot;this&quot;.
+        for (unsigned arg = 1; arg &lt; graph.m_argumentsOnStack.size(); arg++)
+            read(AbstractHeap(Stack, virtualRegisterForArgument(arg)));
</ins><span class="cx">         read(World);
</span><span class="cx">         write(SideState);
</span><span class="cx">         return;
</span><del>-        
</del><ins>+
</ins><span class="cx">     case GetGetter:
</span><span class="cx">         read(GetterSetter_getter);
</span><span class="cx">         def(HeapLocation(GetterLoc, GetterSetter_getter, node-&gt;child1()), LazyNode(node));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCommonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCommon.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCommon.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGCommon.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -152,6 +152,8 @@
</span><span class="cx"> 
</span><span class="cx"> enum OptimizationFixpointState { BeforeFixpoint, FixpointNotConverged, FixpointConverged };
</span><span class="cx"> 
</span><ins>+enum StrengthReduceArgumentFlushes { DontOptimizeArgumentFlushes, OptimizeArgumentFlushes };
+
</ins><span class="cx"> // Describes the form you can expect the entire graph to be in.
</span><span class="cx"> enum GraphForm {
</span><span class="cx">     // LoadStore form means that basic blocks may freely use GetLocal, SetLocal,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDCEPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -53,7 +53,8 @@
</span><span class="cx">         for (BasicBlock* block : m_graph.blocksInPreOrder())
</span><span class="cx">             fixupBlock(block);
</span><span class="cx">         
</span><del>-        cleanVariables(m_graph.m_arguments);
</del><ins>+        cleanVariables(m_graph.m_argumentsOnStack);
+        cleanVariables(m_graph.m_argumentsForChecking);
</ins><span class="cx"> 
</span><span class="cx">         // Just do a basic Phantom/Check clean-up.
</span><span class="cx">         for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -261,6 +261,7 @@
</span><span class="cx">     case GetStack:
</span><span class="cx">     case GetFromArguments:
</span><span class="cx">     case PutToArguments:
</span><ins>+    case GetArgumentRegister:
</ins><span class="cx">     case GetArgument:
</span><span class="cx">     case LogShadowChickenPrologue:
</span><span class="cx">     case LogShadowChickenTail:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDrivercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -90,8 +90,9 @@
</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(linkPolymorphicCallThunkGenerator);
</del><ins>+    vm.getJITCallThunkEntryStub(linkCallThunkGenerator);
+    vm.getJITCallThunkEntryStub(linkDirectCallThunkGenerator);
+    vm.getJITCallThunkEntryStub(linkPolymorphicCallThunkGenerator);
</ins><span class="cx">     
</span><span class="cx">     if (vm.typeProfiler())
</span><span class="cx">         vm.typeProfilerLog()-&gt;processLogEntries(ASCIILiteral(&quot;Preparing for DFG compilation.&quot;));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -1791,6 +1791,7 @@
</span><span class="cx">         case DoubleConstant:
</span><span class="cx">         case GetLocal:
</span><span class="cx">         case GetCallee:
</span><ins>+        case GetArgumentRegister:
</ins><span class="cx">         case GetArgumentCountIncludingThis:
</span><span class="cx">         case GetRestLength:
</span><span class="cx">         case GetArgument:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGenerationInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -104,6 +104,19 @@
</span><span class="cx">         ASSERT(format &amp; DataFormatJS);
</span><span class="cx">         initGPR(node, useCount, gpr, format);
</span><span class="cx">     }
</span><ins>+
+    void initArgumentRegisterValue(Node* node, uint32_t useCount, GPRReg gpr, DataFormat registerFormat =  DataFormatJS)
+    {
+        m_node = node;
+        m_useCount = useCount;
+        m_registerFormat = registerFormat;
+        m_spillFormat = DataFormatNone;
+        m_canFill = false;
+        u.gpr = gpr;
+        m_bornForOSR = false;
+        m_isConstant = false;
+        ASSERT(m_useCount);
+    }
</ins><span class="cx"> #elif USE(JSVALUE32_64)
</span><span class="cx">     void initJSValue(Node* node, uint32_t useCount, GPRReg tagGPR, GPRReg payloadGPR, DataFormat format = DataFormatJS)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -294,7 +294,6 @@
</span><span class="cx">         for (unsigned i = 0; i &lt; data.variants.size(); ++i)
</span><span class="cx">             out.print(comma, inContext(data.variants[i], context));
</span><span class="cx">     }
</span><del>-    ASSERT(node-&gt;hasVariableAccessData(*this) == node-&gt;accessesStack(*this));
</del><span class="cx">     if (node-&gt;hasVariableAccessData(*this)) {
</span><span class="cx">         VariableAccessData* variableAccessData = node-&gt;tryGetVariableAccessData();
</span><span class="cx">         if (variableAccessData) {
</span><span class="lines">@@ -373,6 +372,8 @@
</span><span class="cx">             out.print(comma, inContext(data-&gt;cases[i].value, context), &quot;:&quot;, data-&gt;cases[i].target);
</span><span class="cx">         out.print(comma, &quot;default:&quot;, data-&gt;fallThrough);
</span><span class="cx">     }
</span><ins>+    if (node-&gt;hasArgumentRegisterIndex())
+        out.print(comma, node-&gt;argumentRegisterIndex(), &quot;(&quot;, GPRInfo::toArgumentRegister(node-&gt;argumentRegisterIndex()), &quot;)&quot;);
</ins><span class="cx">     ClobberSet reads;
</span><span class="cx">     ClobberSet writes;
</span><span class="cx">     addReadsAndWrites(*this, node, reads, writes);
</span><span class="lines">@@ -396,7 +397,7 @@
</span><span class="cx">         out.print(comma, &quot;WasHoisted&quot;);
</span><span class="cx">     out.print(&quot;)&quot;);
</span><span class="cx"> 
</span><del>-    if (node-&gt;accessesStack(*this) &amp;&amp; node-&gt;tryGetVariableAccessData())
</del><ins>+    if ((node-&gt;accessesStack(*this) || node-&gt;op() == GetArgumentRegister) &amp;&amp; node-&gt;tryGetVariableAccessData())
</ins><span class="cx">         out.print(&quot;  predicting &quot;, SpeculationDump(node-&gt;tryGetVariableAccessData()-&gt;prediction()));
</span><span class="cx">     else if (node-&gt;hasHeapPrediction())
</span><span class="cx">         out.print(&quot;  predicting &quot;, SpeculationDump(node-&gt;getHeapPrediction()));
</span><span class="lines">@@ -506,8 +507,10 @@
</span><span class="cx">     out.print(&quot;  Fixpoint state: &quot;, m_fixpointState, &quot;; Form: &quot;, m_form, &quot;; Unification state: &quot;, m_unificationState, &quot;; Ref count state: &quot;, m_refCountState, &quot;\n&quot;);
</span><span class="cx">     if (m_form == SSA)
</span><span class="cx">         out.print(&quot;  Argument formats: &quot;, listDump(m_argumentFormats), &quot;\n&quot;);
</span><del>-    else
-        out.print(&quot;  Arguments: &quot;, listDump(m_arguments), &quot;\n&quot;);
</del><ins>+    else {
+        out.print(&quot;  Arguments for checking: &quot;, listDump(m_argumentsForChecking), &quot;\n&quot;);
+        out.print(&quot;  Arguments on stack: &quot;, listDump(m_argumentsOnStack), &quot;\n&quot;);
+    }
</ins><span class="cx">     out.print(&quot;\n&quot;);
</span><span class="cx">     
</span><span class="cx">     Node* lastNode = nullptr;
</span><span class="lines">@@ -1620,13 +1623,13 @@
</span><span class="cx">         if (!currentNode || node-&gt;origin != currentNode-&gt;origin) {
</span><span class="cx">             CodeBlock* profiledBlock = baselineCodeBlockFor(node-&gt;origin.semantic);
</span><span class="cx"> 
</span><del>-            if (node-&gt;accessesStack(*this)) {
</del><ins>+            if (node-&gt;accessesStack(*this) || node-&gt;op() == GetArgumentRegister) {
</ins><span class="cx">                 ValueProfile* result = [&amp;] () -&gt; ValueProfile* {
</span><span class="cx">                     if (!node-&gt;local().isArgument())
</span><span class="cx">                         return nullptr;
</span><span class="cx">                     int argument = node-&gt;local().toArgument();
</span><del>-                    Node* argumentNode = m_arguments[argument];
-                    if (!argumentNode)
</del><ins>+                    Node* argumentNode = m_argumentsOnStack[argument];
+                    if (!argumentNode || !argumentNode-&gt;accessesStack(*this))
</ins><span class="cx">                         return nullptr;
</span><span class="cx">                     if (node-&gt;variableAccessData() != argumentNode-&gt;variableAccessData())
</span><span class="cx">                         return nullptr;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -859,7 +859,7 @@
</span><span class="cx">     bool willCatchExceptionInMachineFrame(CodeOrigin, CodeOrigin&amp; opCatchOriginOut, HandlerInfo*&amp; catchHandlerOut);
</span><span class="cx">     
</span><span class="cx">     bool needsScopeRegister() const { return m_hasDebuggerEnabled || m_codeBlock-&gt;usesEval(); }
</span><del>-    bool needsFlushedThis() const { return m_codeBlock-&gt;usesEval(); }
</del><ins>+    bool needsFlushedThis() const { return m_hasDebuggerEnabled || m_codeBlock-&gt;usesEval(); }
</ins><span class="cx"> 
</span><span class="cx">     VM&amp; m_vm;
</span><span class="cx">     Plan&amp; m_plan;
</span><span class="lines">@@ -878,9 +878,9 @@
</span><span class="cx">     
</span><span class="cx">     Bag&lt;StorageAccessData&gt; m_storageAccessData;
</span><span class="cx">     
</span><del>-    // In CPS, this is all of the SetArgument nodes for the arguments in the machine code block
-    // that survived DCE. All of them except maybe &quot;this&quot; will survive DCE, because of the Flush
-    // nodes.
</del><ins>+    // In CPS, this is all of the GetArgumentRegister and SetArgument nodes for the arguments in
+    // the machine code block that survived DCE. All of them except maybe &quot;this&quot; will survive DCE,
+    // because of the Flush nodes.
</ins><span class="cx">     //
</span><span class="cx">     // In SSA, this is all of the GetStack nodes for the arguments in the machine code block that
</span><span class="cx">     // may have some speculation in the prologue and survived DCE. Note that to get the speculation
</span><span class="lines">@@ -903,7 +903,8 @@
</span><span class="cx">     //
</span><span class="cx">     // If we DCE the ArithAdd and we remove the int check on x, then this won't do the side
</span><span class="cx">     // effects.
</span><del>-    Vector&lt;Node*, 8&gt; m_arguments;
</del><ins>+    Vector&lt;Node*, 8&gt; m_argumentsOnStack;
+    Vector&lt;Node*, 8&gt; m_argumentsForChecking;
</ins><span class="cx">     
</span><span class="cx">     // In CPS, this is meaningless. In SSA, this is the argument speculation that we've locked in.
</span><span class="cx">     Vector&lt;FlushFormat&gt; m_argumentFormats;
</span><span class="lines">@@ -954,6 +955,7 @@
</span><span class="cx">     GraphForm m_form;
</span><span class="cx">     UnificationState m_unificationState;
</span><span class="cx">     PlanStage m_planStage { PlanStage::Initial };
</span><ins>+    StrengthReduceArgumentFlushes m_strengthReduceArguments = { StrengthReduceArgumentFlushes::DontOptimizeArgumentFlushes };
</ins><span class="cx">     RefCountState m_refCountState;
</span><span class="cx">     bool m_hasDebuggerEnabled;
</span><span class="cx">     bool m_hasExceptionHandlers { false };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGInPlaceAbstractStatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -106,11 +106,11 @@
</span><span class="cx">         if (m_graph.m_form == SSA)
</span><span class="cx">             format = m_graph.m_argumentFormats[i];
</span><span class="cx">         else {
</span><del>-            Node* node = m_graph.m_arguments[i];
</del><ins>+            Node* node = m_graph.m_argumentsOnStack[i];
</ins><span class="cx">             if (!node)
</span><span class="cx">                 format = FlushedJSValue;
</span><span class="cx">             else {
</span><del>-                ASSERT(node-&gt;op() == SetArgument);
</del><ins>+                ASSERT(node-&gt;op() == SetArgument || node-&gt;op() == SetLocal);
</ins><span class="cx">                 format = node-&gt;variableAccessData()-&gt;flushFormat();
</span><span class="cx">             }
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -99,18 +99,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JITCompiler::compileEntry()
-{
-    // This code currently matches the old JIT. In the function header we need to
-    // save return address and call frame via the prologue and perform a fast stack check.
-    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56292
-    // We'll need to convert the remaining cti_ style calls (specifically the stack
-    // check) which will be dependent on stack layout. (We'd need to account for this in
-    // both normal return code and when jumping to an exception handler).
-    emitFunctionPrologue();
-    emitPutToCallFrameHeader(m_codeBlock, CallFrameSlot::codeBlock);
-}
-
</del><span class="cx"> void JITCompiler::compileSetupRegistersForEntry()
</span><span class="cx"> {
</span><span class="cx">     emitSaveCalleeSaves();
</span><span class="lines">@@ -277,7 +265,7 @@
</span><span class="cx">     for (unsigned i = 0; i &lt; m_jsCalls.size(); ++i) {
</span><span class="cx">         JSCallRecord&amp; record = m_jsCalls[i];
</span><span class="cx">         CallLinkInfo&amp; info = *record.info;
</span><del>-        linkBuffer.link(record.slowCall, FunctionPtr(m_vm-&gt;getCTIStub(linkCallThunkGenerator).code().executableAddress()));
</del><ins>+        linkBuffer.link(record.slowCall, FunctionPtr(m_vm-&gt;getJITCallThunkEntryStub(linkCallThunkGenerator).entryFor(info.argumentsLocation()).executableAddress()));
</ins><span class="cx">         info.setCallLocations(
</span><span class="cx">             CodeLocationLabel(linkBuffer.locationOfNearCall(record.slowCall)),
</span><span class="cx">             CodeLocationLabel(linkBuffer.locationOf(record.targetToCheck)),
</span><span class="lines">@@ -287,6 +275,8 @@
</span><span class="cx">     for (JSDirectCallRecord&amp; record : m_jsDirectCalls) {
</span><span class="cx">         CallLinkInfo&amp; info = *record.info;
</span><span class="cx">         linkBuffer.link(record.call, linkBuffer.locationOf(record.slowPath));
</span><ins>+        if (record.hasSlowCall())
+            linkBuffer.link(record.slowCall, FunctionPtr(m_vm-&gt;getJITCallThunkEntryStub(linkDirectCallThunkGenerator).entryFor(info.argumentsLocation()).executableAddress()));
</ins><span class="cx">         info.setCallLocations(
</span><span class="cx">             CodeLocationLabel(),
</span><span class="cx">             linkBuffer.locationOf(record.slowPath),
</span><span class="lines">@@ -354,8 +344,14 @@
</span><span class="cx"> 
</span><span class="cx"> void JITCompiler::compile()
</span><span class="cx"> {
</span><ins>+    Label mainEntry(this);
+
</ins><span class="cx">     setStartOfCode();
</span><del>-    compileEntry();
</del><ins>+    emitFunctionPrologue();
+
+    Label entryPoint(this);
+    emitPutToCallFrameHeader(m_codeBlock, CallFrameSlot::codeBlock);
+
</ins><span class="cx">     m_speculative = std::make_unique&lt;SpeculativeJIT&gt;(*this);
</span><span class="cx"> 
</span><span class="cx">     // Plant a check that sufficient space is available in the JSStack.
</span><span class="lines">@@ -382,6 +378,20 @@
</span><span class="cx"> 
</span><span class="cx">     m_speculative-&gt;callOperationWithCallFrameRollbackOnException(operationThrowStackOverflowError, m_codeBlock);
</span><span class="cx"> 
</span><ins>+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    m_stackArgsArityOKEntry = label();
+    emitFunctionPrologue();
+
+    // Load argument values into argument registers
+    loadPtr(addressFor(CallFrameSlot::callee), argumentRegisterForCallee());
+    load32(payloadFor(CallFrameSlot::argumentCount), argumentRegisterForArgumentCount());
+    
+    for (unsigned argIndex = 0; argIndex &lt; static_cast&lt;unsigned&gt;(m_codeBlock-&gt;numParameters()) &amp;&amp; argIndex &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argIndex++)
+        load64(Address(GPRInfo::callFrameRegister, (CallFrameSlot::thisArgument + argIndex) * static_cast&lt;int&gt;(sizeof(Register))), argumentRegisterForFunctionArgument(argIndex));
+    
+    jump(entryPoint);
+#endif
+
</ins><span class="cx">     // Generate slow path code.
</span><span class="cx">     m_speculative-&gt;runSlowPathGenerators(m_pcToCodeOriginMapBuilder);
</span><span class="cx">     m_pcToCodeOriginMapBuilder.appendItem(labelIgnoringWatchpoints(), PCToCodeOriginMapBuilder::defaultCodeOrigin());
</span><span class="lines">@@ -406,24 +416,87 @@
</span><span class="cx">     codeBlock()-&gt;shrinkToFit(CodeBlock::LateShrink);
</span><span class="cx"> 
</span><span class="cx">     disassemble(*linkBuffer);
</span><del>-    
</del><ins>+
+    JITEntryPoints entrypoints;
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    entrypoints.setEntryFor(RegisterArgsArityCheckNotRequired, linkBuffer-&gt;locationOf(mainEntry));
+    entrypoints.setEntryFor(StackArgsArityCheckNotRequired, linkBuffer-&gt;locationOf(m_stackArgsArityOKEntry));
+#else
+    entrypoints.setEntryFor(StackArgsArityCheckNotRequired, linkBuffer-&gt;locationOf(mainEntry));
+#endif
+
</ins><span class="cx">     m_graph.m_plan.finalizer = std::make_unique&lt;JITFinalizer&gt;(
</span><del>-        m_graph.m_plan, WTFMove(m_jitCode), WTFMove(linkBuffer));
</del><ins>+        m_graph.m_plan, WTFMove(m_jitCode), WTFMove(linkBuffer), entrypoints);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JITCompiler::compileFunction()
</span><span class="cx"> {
</span><span class="cx">     setStartOfCode();
</span><del>-    compileEntry();
</del><span class="cx"> 
</span><ins>+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    unsigned numParameters = static_cast&lt;unsigned&gt;(m_codeBlock-&gt;numParameters());
+    GPRReg argCountReg = argumentRegisterForArgumentCount();
+    JumpList continueRegisterEntry;
+    Label registerArgumentsEntrypoints[NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS + 1];
+
+    if (numParameters &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS) {
+        // Spill any extra register arguments passed to function onto the stack.
+        for (unsigned extraRegisterArgumentIndex = NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS - 1;
+            extraRegisterArgumentIndex &gt;= numParameters; extraRegisterArgumentIndex--) {
+            registerArgumentsEntrypoints[extraRegisterArgumentIndex + 1] = label();
+            emitPutArgumentToCallFrameBeforePrologue(argumentRegisterForFunctionArgument(extraRegisterArgumentIndex), extraRegisterArgumentIndex);
+        }
+    }
+    incrementCounter(this, VM::RegArgsExtra);
+
+    continueRegisterEntry.append(jump());
+
+    m_registerArgsWithArityCheck = label();
+    incrementCounter(this, VM::RegArgsArity);
+
+    Label registerArgsCheckArity(this);
+
+    Jump registerCheckArity;
+
+    if (numParameters &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS)
+        registerCheckArity = branch32(NotEqual, argCountReg, TrustedImm32(numParameters));
+    else {
+        registerCheckArity = branch32(Below, argCountReg, TrustedImm32(numParameters));
+        m_registerArgsWithPossibleExtraArgs = label();
+    }
+    
+    Label registerEntryNoArity(this);
+
+    if (numParameters &lt;= NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS)
+        registerArgumentsEntrypoints[numParameters] = registerEntryNoArity;
+
+    incrementCounter(this, VM::RegArgsNoArity);
+
+    continueRegisterEntry.link(this);
+#endif // NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+
+    Label mainEntry(this);
+
+    emitFunctionPrologue();
+
</ins><span class="cx">     // === Function header code generation ===
</span><span class="cx">     // This is the main entry point, without performing an arity check.
</span><span class="cx">     // If we needed to perform an arity check we will already have moved the return address,
</span><span class="cx">     // so enter after this.
</span><span class="cx">     Label fromArityCheck(this);
</span><ins>+
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    storePtr(argumentRegisterForCallee(), addressFor(CallFrameSlot::callee));
+    store32(argCountReg, payloadFor(CallFrameSlot::argumentCount));
+
+    Label fromStackEntry(this);
+#endif
+    
+    emitPutToCallFrameHeader(m_codeBlock, CallFrameSlot::codeBlock);
+
</ins><span class="cx">     // Plant a check that sufficient space is available in the JSStack.
</span><del>-    addPtr(TrustedImm32(virtualRegisterForLocal(m_graph.requiredRegisterCountForExecutionAndExit() - 1).offset() * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::regT1);
-    Jump stackOverflow = branchPtr(Above, AbsoluteAddress(m_vm-&gt;addressOfSoftStackLimit()), GPRInfo::regT1);
</del><ins>+    addPtr(TrustedImm32(virtualRegisterForLocal(m_graph.requiredRegisterCountForExecutionAndExit() - 1).offset() * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::nonArgGPR0);
+    Jump stackOverflow = branchPtr(Above, AbsoluteAddress(m_vm-&gt;addressOfSoftStackLimit()), GPRInfo::nonArgGPR0);
</ins><span class="cx"> 
</span><span class="cx">     // Move the stack pointer down to accommodate locals
</span><span class="cx">     addPtr(TrustedImm32(m_graph.stackPointerOffset() * sizeof(Register)), GPRInfo::callFrameRegister, stackPointerRegister);
</span><span class="lines">@@ -452,17 +525,73 @@
</span><span class="cx">         addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
</span><span class="cx"> 
</span><span class="cx">     m_speculative-&gt;callOperationWithCallFrameRollbackOnException(operationThrowStackOverflowError, m_codeBlock);
</span><ins>+
+    JumpList arityOK;
</ins><span class="cx">     
</span><del>-    // The fast entry point into a function does not check the correct number of arguments
-    // have been passed to the call (we only use the fast entry point where we can statically
-    // determine the correct number of arguments have been passed, or have already checked).
-    // In cases where an arity check is necessary, we enter here.
-    // FIXME: change this from a cti call to a DFG style operation (normal C calling conventions).
-    m_arityCheck = label();
-    compileEntry();
</del><ins>+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    jump(registerArgsCheckArity);
</ins><span class="cx"> 
</span><ins>+    JumpList registerArityNeedsFixup;
+    if (numParameters &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS) {
+        registerCheckArity.link(this);
+        registerArityNeedsFixup.append(branch32(Below, argCountReg, TrustedImm32(m_codeBlock-&gt;numParameters())));
+
+        // We have extra register arguments.
+
+        // The fast entry point into a function does not check that the correct number of arguments
+        // have been passed to the call (we only use the fast entry point where we can statically
+        // determine the correct number of arguments have been passed, or have already checked).
+        // In cases where an arity check is necessary, we enter here.
+        m_registerArgsWithPossibleExtraArgs = label();
+
+        incrementCounter(this, VM::RegArgsExtra);
+
+        // Spill extra args passed to function
+        for (unsigned argIndex = static_cast&lt;unsigned&gt;(m_codeBlock-&gt;numParameters()); argIndex &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argIndex++) {
+            branch32(MacroAssembler::BelowOrEqual, argCountReg, MacroAssembler::TrustedImm32(argIndex)).linkTo(mainEntry, this);
+            emitPutArgumentToCallFrameBeforePrologue(argumentRegisterForFunctionArgument(argIndex), argIndex);
+        }
+        jump(mainEntry);
+    }
+
+    // Fall through
+    if (numParameters &gt; 0) {
+        // There should always be a &quot;this&quot; parameter.
+        unsigned registerArgumentFixupCount = std::min(numParameters - 1, NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS);
+        Label registerArgumentsNeedArityFixup = label();
+
+        for (unsigned argIndex = 1; argIndex &lt;= registerArgumentFixupCount; argIndex++)
+            registerArgumentsEntrypoints[argIndex] = registerArgumentsNeedArityFixup;
+    }
+
+    incrementCounter(this, VM::RegArgsArity);
+
+    registerArityNeedsFixup.link(this);
+
+    if (numParameters &gt;= NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS)
+        registerCheckArity.link(this);
+
+    spillArgumentRegistersToFrameBeforePrologue();
+
+#if ENABLE(VM_COUNTERS)
+    Jump continueToStackArityFixup = jump();
+#endif
+#endif // NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+
+    m_stackArgsWithArityCheck = label();
+    incrementCounter(this, VM::StackArgsArity);
+
+#if ENABLE(VM_COUNTERS)
+    continueToStackArityFixup.link(this);
+#endif
+
+    emitFunctionPrologue();
+
</ins><span class="cx">     load32(AssemblyHelpers::payloadFor((VirtualRegister)CallFrameSlot::argumentCount), GPRInfo::regT1);
</span><del>-    branch32(AboveOrEqual, GPRInfo::regT1, TrustedImm32(m_codeBlock-&gt;numParameters())).linkTo(fromArityCheck, this);
</del><ins>+    arityOK.append(branch32(AboveOrEqual, GPRInfo::regT1, TrustedImm32(m_codeBlock-&gt;numParameters())));
+
+    incrementCounter(this, VM::ArityFixupRequired);
+
</ins><span class="cx">     emitStoreCodeOrigin(CodeOrigin(0));
</span><span class="cx">     if (maxFrameExtentForSlowPathCall)
</span><span class="cx">         addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
</span><span class="lines">@@ -469,11 +598,32 @@
</span><span class="cx">     m_speculative-&gt;callOperationWithCallFrameRollbackOnException(m_codeBlock-&gt;m_isConstructor ? operationConstructArityCheck : operationCallArityCheck, GPRInfo::regT0);
</span><span class="cx">     if (maxFrameExtentForSlowPathCall)
</span><span class="cx">         addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
</span><del>-    branchTest32(Zero, GPRInfo::returnValueGPR).linkTo(fromArityCheck, this);
</del><ins>+    arityOK.append(branchTest32(Zero, GPRInfo::returnValueGPR));
+
</ins><span class="cx">     emitStoreCodeOrigin(CodeOrigin(0));
</span><span class="cx">     move(GPRInfo::returnValueGPR, GPRInfo::argumentGPR0);
</span><span class="cx">     m_callArityFixup = call();
</span><ins>+
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    Jump toFillRegisters = jump();
+
+    m_stackArgsArityOKEntry = label();
+
+    incrementCounter(this, VM::StackArgsNoArity);
+    emitFunctionPrologue();
+
+    arityOK.link(this);
+    toFillRegisters.link(this);
+
+    // Load argument values into argument registers
+    for (unsigned argIndex = 0; argIndex &lt; static_cast&lt;unsigned&gt;(m_codeBlock-&gt;numParameters()) &amp;&amp; argIndex &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argIndex++)
+        load64(Address(GPRInfo::callFrameRegister, (CallFrameSlot::thisArgument + argIndex) * static_cast&lt;int&gt;(sizeof(Register))), argumentRegisterForFunctionArgument(argIndex));
+
+    jump(fromStackEntry);
+#else
+    arityOK.linkTo(fromArityCheck, this);
</ins><span class="cx">     jump(fromArityCheck);
</span><ins>+#endif
</ins><span class="cx">     
</span><span class="cx">     // Generate slow path code.
</span><span class="cx">     m_speculative-&gt;runSlowPathGenerators(m_pcToCodeOriginMapBuilder);
</span><span class="lines">@@ -502,10 +652,35 @@
</span><span class="cx">     
</span><span class="cx">     disassemble(*linkBuffer);
</span><span class="cx"> 
</span><del>-    MacroAssemblerCodePtr withArityCheck = linkBuffer-&gt;locationOf(m_arityCheck);
</del><ins>+    JITEntryPoints entrypoints;
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+#if ENABLE(VM_COUNTERS)
+    MacroAssemblerCodePtr mainEntryCodePtr = linkBuffer-&gt;locationOf(registerEntryNoArity);
+#else
+    MacroAssemblerCodePtr mainEntryCodePtr = linkBuffer-&gt;locationOf(mainEntry);
+#endif
+    entrypoints.setEntryFor(RegisterArgsArityCheckNotRequired, mainEntryCodePtr);
+    entrypoints.setEntryFor(RegisterArgsPossibleExtraArgs, linkBuffer-&gt;locationOf(m_registerArgsWithPossibleExtraArgs));
+    entrypoints.setEntryFor(RegisterArgsMustCheckArity, linkBuffer-&gt;locationOf(m_registerArgsWithArityCheck));
</ins><span class="cx"> 
</span><ins>+    for (unsigned argCount = 1; argCount &lt;= NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argCount++) {
+        MacroAssemblerCodePtr entry;
+        if (argCount == numParameters)
+            entry = mainEntryCodePtr;
+        else if (registerArgumentsEntrypoints[argCount].isSet())
+            entry = linkBuffer-&gt;locationOf(registerArgumentsEntrypoints[argCount]);
+        else
+            entry = linkBuffer-&gt;locationOf(m_registerArgsWithArityCheck);
+        entrypoints.setEntryFor(JITEntryPoints::registerEntryTypeForArgumentCount(argCount), entry);
+    }
+    entrypoints.setEntryFor(StackArgsArityCheckNotRequired, linkBuffer-&gt;locationOf(m_stackArgsArityOKEntry));
+#else
+    entrypoints.setEntryFor(StackArgsArityCheckNotRequired, linkBuffer-&gt;locationOf(mainEntry));
+#endif
+    entrypoints.setEntryFor(StackArgsMustCheckArity, linkBuffer-&gt;locationOf(m_stackArgsWithArityCheck));
+
</ins><span class="cx">     m_graph.m_plan.finalizer = std::make_unique&lt;JITFinalizer&gt;(
</span><del>-        m_graph.m_plan, WTFMove(m_jitCode), WTFMove(linkBuffer), withArityCheck);
</del><ins>+        m_graph.m_plan, WTFMove(m_jitCode), WTFMove(linkBuffer), entrypoints);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JITCompiler::disassemble(LinkBuffer&amp; linkBuffer)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCompilerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -217,6 +217,11 @@
</span><span class="cx">         m_jsDirectCalls.append(JSDirectCallRecord(call, slowPath, info));
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void addJSDirectCall(Call call, Call slowCall, Label slowPath, CallLinkInfo* info)
+    {
+        m_jsDirectCalls.append(JSDirectCallRecord(call, slowCall, slowPath, info));
+    }
+    
</ins><span class="cx">     void addJSDirectTailCall(PatchableJump patchableJump, Call call, Label slowPath, CallLinkInfo* info)
</span><span class="cx">     {
</span><span class="cx">         m_jsDirectTailCalls.append(JSDirectTailCallRecord(patchableJump, call, slowPath, info));
</span><span class="lines">@@ -267,7 +272,6 @@
</span><span class="cx">     friend class OSRExitJumpPlaceholder;
</span><span class="cx">     
</span><span class="cx">     // Internal implementation to compile.
</span><del>-    void compileEntry();
</del><span class="cx">     void compileSetupRegistersForEntry();
</span><span class="cx">     void compileEntryExecutionFlag();
</span><span class="cx">     void compileBody();
</span><span class="lines">@@ -318,7 +322,18 @@
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx">         
</span><ins>+        JSDirectCallRecord(Call call, Call slowCall, Label slowPath, CallLinkInfo* info)
+            : call(call)
+            , slowCall(slowCall)
+            , slowPath(slowPath)
+            , info(info)
+        {
+        }
+
+        bool hasSlowCall() { return slowCall.m_label.isSet(); }
+
</ins><span class="cx">         Call call;
</span><ins>+        Call slowCall;
</ins><span class="cx">         Label slowPath;
</span><span class="cx">         CallLinkInfo* info;
</span><span class="cx">     };
</span><span class="lines">@@ -355,7 +370,12 @@
</span><span class="cx">     Vector&lt;ExceptionHandlingOSRExitInfo&gt; m_exceptionHandlerOSRExitCallSites;
</span><span class="cx">     
</span><span class="cx">     Call m_callArityFixup;
</span><del>-    Label m_arityCheck;
</del><ins>+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    Label m_registerArgsWithPossibleExtraArgs;
+    Label m_registerArgsWithArityCheck;
+    Label m_stackArgsArityOKEntry;
+#endif
+    Label m_stackArgsWithArityCheck;
</ins><span class="cx">     std::unique_ptr&lt;SpeculativeJIT&gt; m_speculative;
</span><span class="cx">     PCToCodeOriginMapBuilder m_pcToCodeOriginMapBuilder;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITFinalizercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITFinalizer.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITFinalizer.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITFinalizer.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -37,11 +37,12 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="cx"> 
</span><del>-JITFinalizer::JITFinalizer(Plan&amp; plan, PassRefPtr&lt;JITCode&gt; jitCode, std::unique_ptr&lt;LinkBuffer&gt; linkBuffer, MacroAssemblerCodePtr withArityCheck)
</del><ins>+JITFinalizer::JITFinalizer(Plan&amp; plan, PassRefPtr&lt;JITCode&gt; jitCode,
+    std::unique_ptr&lt;LinkBuffer&gt; linkBuffer, JITEntryPoints&amp; entrypoints)
</ins><span class="cx">     : Finalizer(plan)
</span><span class="cx">     , m_jitCode(jitCode)
</span><span class="cx">     , m_linkBuffer(WTFMove(linkBuffer))
</span><del>-    , m_withArityCheck(withArityCheck)
</del><ins>+    , m_entrypoints(entrypoints)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -56,9 +57,8 @@
</span><span class="cx"> 
</span><span class="cx"> bool JITFinalizer::finalize()
</span><span class="cx"> {
</span><del>-    m_jitCode-&gt;initializeCodeRef(
-        FINALIZE_DFG_CODE(*m_linkBuffer, (&quot;DFG JIT code for %s&quot;, toCString(CodeBlockWithJITType(m_plan.codeBlock, JITCode::DFGJIT)).data())),
-        MacroAssemblerCodePtr());
</del><ins>+    MacroAssemblerCodeRef codeRef = FINALIZE_DFG_CODE(*m_linkBuffer, (&quot;DFG JIT code for %s&quot;, toCString(CodeBlockWithJITType(m_plan.codeBlock, JITCode::DFGJIT)).data()));
+    m_jitCode-&gt;initializeEntryPoints(JITEntryPointsWithRef(codeRef, m_entrypoints));
</ins><span class="cx">     
</span><span class="cx">     m_plan.codeBlock-&gt;setJITCode(m_jitCode);
</span><span class="cx">     
</span><span class="lines">@@ -69,10 +69,11 @@
</span><span class="cx"> 
</span><span class="cx"> bool JITFinalizer::finalizeFunction()
</span><span class="cx"> {
</span><del>-    RELEASE_ASSERT(!m_withArityCheck.isEmptyValue());
-    m_jitCode-&gt;initializeCodeRef(
-        FINALIZE_DFG_CODE(*m_linkBuffer, (&quot;DFG JIT code for %s&quot;, toCString(CodeBlockWithJITType(m_plan.codeBlock, JITCode::DFGJIT)).data())),
-        m_withArityCheck);
</del><ins>+    RELEASE_ASSERT(!m_entrypoints.entryFor(StackArgsMustCheckArity).isEmptyValue());
+    MacroAssemblerCodeRef codeRef = FINALIZE_DFG_CODE(*m_linkBuffer, (&quot;DFG JIT code for %s&quot;, toCString(CodeBlockWithJITType(m_plan.codeBlock, JITCode::DFGJIT)).data()));
+
+    m_jitCode-&gt;initializeEntryPoints(JITEntryPointsWithRef(codeRef, m_entrypoints));
+
</ins><span class="cx">     m_plan.codeBlock-&gt;setJITCode(m_jitCode);
</span><span class="cx">     
</span><span class="cx">     finalizeCommon();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITFinalizerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITFinalizer.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITFinalizer.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITFinalizer.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -36,7 +36,7 @@
</span><span class="cx"> 
</span><span class="cx"> class JITFinalizer : public Finalizer {
</span><span class="cx"> public:
</span><del>-    JITFinalizer(Plan&amp;, PassRefPtr&lt;JITCode&gt;, std::unique_ptr&lt;LinkBuffer&gt;, MacroAssemblerCodePtr withArityCheck = MacroAssemblerCodePtr(MacroAssemblerCodePtr::EmptyValue));
</del><ins>+    JITFinalizer(Plan&amp;, PassRefPtr&lt;JITCode&gt;, std::unique_ptr&lt;LinkBuffer&gt;, JITEntryPoints&amp;);
</ins><span class="cx">     virtual ~JITFinalizer();
</span><span class="cx">     
</span><span class="cx">     size_t codeSize() override;
</span><span class="lines">@@ -48,7 +48,7 @@
</span><span class="cx">     
</span><span class="cx">     RefPtr&lt;JITCode&gt; m_jitCode;
</span><span class="cx">     std::unique_ptr&lt;LinkBuffer&gt; m_linkBuffer;
</span><del>-    MacroAssemblerCodePtr m_withArityCheck;
</del><ins>+    JITEntryPoints m_entrypoints;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGLiveCatchVariablePreservationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGLiveCatchVariablePreservationPhase.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGLiveCatchVariablePreservationPhase.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGLiveCatchVariablePreservationPhase.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -101,7 +101,7 @@
</span><span class="cx">         {
</span><span class="cx">             for (unsigned i = 0; i &lt; block-&gt;size(); i++) {
</span><span class="cx">                 Node* node = block-&gt;at(i);
</span><del>-                bool isPrimordialSetArgument = node-&gt;op() == SetArgument &amp;&amp; node-&gt;local().isArgument() &amp;&amp; node == m_graph.m_arguments[node-&gt;local().toArgument()];
</del><ins>+                bool isPrimordialSetArgument = node-&gt;op() == SetArgument &amp;&amp; node-&gt;local().isArgument() &amp;&amp; node == m_graph.m_argumentsOnStack[node-&gt;local().toArgument()];
</ins><span class="cx">                 InlineCallFrame* inlineCallFrame = node-&gt;origin.semantic.inlineCallFrame;
</span><span class="cx">                 if (inlineCallFrame)
</span><span class="cx">                     seenInlineCallFrames.add(inlineCallFrame);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGMaximalFlushInsertionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGMaximalFlushInsertionPhase.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGMaximalFlushInsertionPhase.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGMaximalFlushInsertionPhase.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -67,8 +67,8 @@
</span><span class="cx">         {
</span><span class="cx">             for (unsigned i = 0; i &lt; block-&gt;size(); i++) {
</span><span class="cx">                 Node* node = block-&gt;at(i);
</span><del>-                bool isPrimordialSetArgument = node-&gt;op() == SetArgument &amp;&amp; node-&gt;local().isArgument() &amp;&amp; node == m_graph.m_arguments[node-&gt;local().toArgument()];
-                if (node-&gt;op() == SetLocal || (node-&gt;op() == SetArgument &amp;&amp; !isPrimordialSetArgument)) {
</del><ins>+                if ((node-&gt;op() == SetArgument || node-&gt;op() == SetLocal)
+                    &amp;&amp; (!node-&gt;local().isArgument() || node != m_graph.m_argumentsOnStack[node-&gt;local().toArgument()])) {
</ins><span class="cx">                     VirtualRegister operand = node-&gt;local();
</span><span class="cx">                     VariableAccessData* flushAccessData = currentBlockAccessData.operand(operand);
</span><span class="cx">                     if (!flushAccessData)
</span><span class="lines">@@ -117,7 +117,6 @@
</span><span class="cx">             if (initialAccessData.operand(operand))
</span><span class="cx">                 continue;
</span><span class="cx"> 
</span><del>-            DFG_ASSERT(m_graph, node, node-&gt;op() != SetLocal); // We should have inserted a Flush before this!
</del><span class="cx">             initialAccessData.operand(operand) = node-&gt;variableAccessData();
</span><span class="cx">             initialAccessNodes.operand(operand) = node;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGMayExitcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -72,6 +72,7 @@
</span><span class="cx">     case GetStack:
</span><span class="cx">     case GetCallee:
</span><span class="cx">     case GetArgumentCountIncludingThis:
</span><ins>+    case GetArgumentRegister:
</ins><span class="cx">     case GetRestLength:
</span><span class="cx">     case GetScope:
</span><span class="cx">     case PhantomLocal:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGMinifiedNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012-2016 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">@@ -41,6 +41,8 @@
</span><span class="cx">     result.m_op = node-&gt;op();
</span><span class="cx">     if (hasConstant(node-&gt;op()))
</span><span class="cx">         result.m_info = JSValue::encode(node-&gt;asJSValue());
</span><ins>+    else if (node-&gt;op() == GetArgumentRegister)
+        result.m_info = jsFunctionArgumentForArgumentRegisterIndex(node-&gt;argumentRegisterIndex());
</ins><span class="cx">     else {
</span><span class="cx">         ASSERT(node-&gt;op() == PhantomDirectArguments || node-&gt;op() == PhantomClonedArguments);
</span><span class="cx">         result.m_info = bitwise_cast&lt;uintptr_t&gt;(node-&gt;origin.semantic.inlineCallFrame);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGMinifiedNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012, 2014, 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 2014-2016 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">@@ -43,6 +43,7 @@
</span><span class="cx">     case DoubleConstant:
</span><span class="cx">     case PhantomDirectArguments:
</span><span class="cx">     case PhantomClonedArguments:
</span><ins>+    case GetArgumentRegister:
</ins><span class="cx">         return true;
</span><span class="cx">     default:
</span><span class="cx">         return false;
</span><span class="lines">@@ -71,6 +72,10 @@
</span><span class="cx">     {
</span><span class="cx">         return bitwise_cast&lt;InlineCallFrame*&gt;(static_cast&lt;uintptr_t&gt;(m_info));
</span><span class="cx">     }
</span><ins>+
+    bool hasArgumentIndex() const { return hasArgumentIndex(m_op); }
+
+    unsigned argumentIndex() const { return static_cast&lt;unsigned&gt;(m_info); }
</ins><span class="cx">     
</span><span class="cx">     static MinifiedID getID(MinifiedNode* node) { return node-&gt;id(); }
</span><span class="cx">     static bool compareByNodeIndex(const MinifiedNode&amp; a, const MinifiedNode&amp; b)
</span><span class="lines">@@ -88,6 +93,11 @@
</span><span class="cx">     {
</span><span class="cx">         return type == PhantomDirectArguments || type == PhantomClonedArguments;
</span><span class="cx">     }
</span><ins>+
+    static bool hasArgumentIndex(NodeType type)
+    {
+        return type == GetArgumentRegister;
+    }
</ins><span class="cx">     
</span><span class="cx">     MinifiedID m_id;
</span><span class="cx">     uint64_t m_info;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -71,6 +71,7 @@
</span><span class="cx">     case GetLocal:
</span><span class="cx">     case SetLocal:
</span><span class="cx">     case SetArgument:
</span><ins>+    case GetArgumentRegister:
</ins><span class="cx">     case Flush:
</span><span class="cx">     case PhantomLocal:
</span><span class="cx">         return true;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -828,6 +828,9 @@
</span><span class="cx">     bool hasVariableAccessData(Graph&amp;);
</span><span class="cx">     bool accessesStack(Graph&amp; graph)
</span><span class="cx">     {
</span><ins>+        if (op() == GetArgumentRegister)
+            return false;
+
</ins><span class="cx">         return hasVariableAccessData(graph);
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -846,6 +849,11 @@
</span><span class="cx">         return m_opInfo.as&lt;VariableAccessData*&gt;()-&gt;find();
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void setVariableAccessData(VariableAccessData* variable)
+    {
+        m_opInfo = variable;
+    }
+    
</ins><span class="cx">     VirtualRegister local()
</span><span class="cx">     {
</span><span class="cx">         return variableAccessData()-&gt;local();
</span><span class="lines">@@ -1214,6 +1222,17 @@
</span><span class="cx">         return speculationFromJSType(queriedType());
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    bool hasArgumentRegisterIndex()
+    {
+        return op() == GetArgumentRegister;
+    }
+    
+    unsigned argumentRegisterIndex()
+    {
+        ASSERT(hasArgumentRegisterIndex());
+        return m_opInfo2.as&lt;unsigned&gt;();
+    }
+    
</ins><span class="cx">     bool hasResult()
</span><span class="cx">     {
</span><span class="cx">         return !!result();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -53,6 +53,7 @@
</span><span class="cx">     macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \
</span><span class="cx">     macro(GetCallee, NodeResultJS) \
</span><span class="cx">     macro(GetArgumentCountIncludingThis, NodeResultInt32) \
</span><ins>+    macro(GetArgumentRegister, NodeResultJS /* | NodeMustGenerate */) \
</ins><span class="cx">     \
</span><span class="cx">     /* Nodes for local variable access. These nodes are linked together using Phi nodes. */\
</span><span class="cx">     /* Any two nodes that are part of the same Phi graph will share the same */\
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRAvailabilityAnalysisPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -144,6 +144,11 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case GetArgumentRegister: {
+        m_availability.m_locals.operand(node-&gt;local()).setNode(node);
+        break;
+    }
+
</ins><span class="cx">     case MovHint: {
</span><span class="cx">         m_availability.m_locals.operand(node-&gt;unlinkedLocal()).setNode(node-&gt;child1().node());
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSREntrypointCreationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -112,16 +112,32 @@
</span><span class="cx">         // type checks to here.
</span><span class="cx">         origin = target-&gt;at(0)-&gt;origin;
</span><span class="cx">         
</span><del>-        for (int argument = 0; argument &lt; baseline-&gt;numParameters(); ++argument) {
</del><ins>+        for (unsigned argument = 0; argument &lt; static_cast&lt;unsigned&gt;(baseline-&gt;numParameters()); ++argument) {
</ins><span class="cx">             Node* oldNode = target-&gt;variablesAtHead.argument(argument);
</span><span class="cx">             if (!oldNode) {
</span><del>-                // Just for sanity, always have a SetArgument even if it's not needed.
-                oldNode = m_graph.m_arguments[argument];
</del><ins>+                // Just for sanity, always have an argument node even if it's not needed.
+                oldNode = m_graph.m_argumentsForChecking[argument];
</ins><span class="cx">             }
</span><del>-            Node* node = newRoot-&gt;appendNode(
-                m_graph, SpecNone, SetArgument, origin,
-                OpInfo(oldNode-&gt;variableAccessData()));
-            m_graph.m_arguments[argument] = node;
</del><ins>+            Node* node;
+            Node* stackNode;
+            if (argument &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS) {
+                node = newRoot-&gt;appendNode(
+                    m_graph, SpecNone, GetArgumentRegister, origin,
+                    OpInfo(oldNode-&gt;variableAccessData()),
+                    OpInfo(argumentRegisterIndexForJSFunctionArgument(argument)));
+                stackNode = newRoot-&gt;appendNode(
+                    m_graph, SpecNone, SetLocal, origin,
+                    OpInfo(oldNode-&gt;variableAccessData()),
+                    Edge(node));
+            } else {
+                node = newRoot-&gt;appendNode(
+                    m_graph, SpecNone, SetArgument, origin,
+                    OpInfo(oldNode-&gt;variableAccessData()));
+                stackNode = node;
+            }
+
+            m_graph.m_argumentsForChecking[argument] = node;
+            m_graph.m_argumentsOnStack[argument] = stackNode;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         for (int local = 0; local &lt; baseline-&gt;m_numCalleeLocals; ++local) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -314,7 +314,9 @@
</span><span class="cx">     performCFA(dfg);
</span><span class="cx">     performConstantFolding(dfg);
</span><span class="cx">     bool changed = false;
</span><ins>+    dfg.m_strengthReduceArguments = OptimizeArgumentFlushes;
</ins><span class="cx">     changed |= performCFGSimplification(dfg);
</span><ins>+    changed |= performStrengthReduction(dfg);
</ins><span class="cx">     changed |= performLocalCSE(dfg);
</span><span class="cx">     
</span><span class="cx">     if (validationEnabled())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPreciseLocalClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -197,7 +197,7 @@
</span><span class="cx"> 
</span><span class="cx">             
</span><span class="cx">         default: {
</span><del>-            // All of the outermost arguments, except this, are definitely read.
</del><ins>+            // All of the outermost stack arguments, except this, are definitely read.
</ins><span class="cx">             for (unsigned i = m_graph.m_codeBlock-&gt;numParameters(); i-- &gt; 1;)
</span><span class="cx">                 m_read(virtualRegisterForArgument(i));
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionInjectionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionInjectionPhase.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionInjectionPhase.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionInjectionPhase.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -56,7 +56,7 @@
</span><span class="cx">                 if (!profile)
</span><span class="cx">                     continue;
</span><span class="cx">             
</span><del>-                m_graph.m_arguments[arg]-&gt;variableAccessData()-&gt;predict(
</del><ins>+                m_graph.m_argumentsForChecking[arg]-&gt;variableAccessData()-&gt;predict(
</ins><span class="cx">                     profile-&gt;computeUpdatedPrediction(locker));
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="lines">@@ -74,7 +74,7 @@
</span><span class="cx">                 Node* node = block-&gt;variablesAtHead.operand(operand);
</span><span class="cx">                 if (!node)
</span><span class="cx">                     continue;
</span><del>-                ASSERT(node-&gt;accessesStack(m_graph));
</del><ins>+                ASSERT(node-&gt;accessesStack(m_graph) || node-&gt;op() == GetArgumentRegister);
</ins><span class="cx">                 node-&gt;variableAccessData()-&gt;predict(
</span><span class="cx">                     speculationFromValue(m_graph.m_plan.mustHandleValues[i]));
</span><span class="cx">             }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -168,6 +168,16 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        case GetArgumentRegister: {
+            VariableAccessData* variable = node-&gt;variableAccessData();
+            SpeculatedType prediction = variable-&gt;prediction();
+            if (!variable-&gt;couldRepresentInt52() &amp;&amp; (prediction &amp; SpecInt52Only))
+                prediction = (prediction | SpecAnyIntAsDouble) &amp; ~SpecInt52Only;
+            if (prediction)
+                changed |= mergePrediction(prediction);
+            break;
+        }
+            
</ins><span class="cx">         case UInt32ToNumber: {
</span><span class="cx">             if (node-&gt;canSpeculateInt32(m_pass))
</span><span class="cx">                 changed |= mergePrediction(SpecInt32Only);
</span><span class="lines">@@ -968,6 +978,7 @@
</span><span class="cx"> 
</span><span class="cx">         case GetLocal:
</span><span class="cx">         case SetLocal:
</span><ins>+        case GetArgumentRegister:
</ins><span class="cx">         case UInt32ToNumber:
</span><span class="cx">         case ValueAdd:
</span><span class="cx">         case ArithAdd:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPutStackSinkingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPutStackSinkingPhase.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPutStackSinkingPhase.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGPutStackSinkingPhase.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -147,7 +147,7 @@
</span><span class="cx">             
</span><span class="cx">         } while (changed);
</span><span class="cx">         
</span><del>-        // All of the arguments should be live at head of root. Note that we may find that some
</del><ins>+        // All of the stack arguments should be live at head of root. Note that we may find that some
</ins><span class="cx">         // locals are live at head of root. This seems wrong but isn't. This will happen for example
</span><span class="cx">         // if the function accesses closure variable #42 for some other function and we either don't
</span><span class="cx">         // have variable #42 at all or we haven't set it at root, for whatever reason. Basically this
</span><span class="lines">@@ -157,8 +157,12 @@
</span><span class="cx">         //
</span><span class="cx">         // For our purposes here, the imprecision in the aliasing is harmless. It just means that we
</span><span class="cx">         // may not do as much Phi pruning as we wanted.
</span><del>-        for (size_t i = liveAtHead.atIndex(0).numberOfArguments(); i--;)
-            DFG_ASSERT(m_graph, nullptr, liveAtHead.atIndex(0).argument(i));
</del><ins>+        for (size_t i = liveAtHead.atIndex(0).numberOfArguments(); i--;) {
+            if (i &gt;= NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS) {
+                // Stack arguments are live at the head of root.
+                DFG_ASSERT(m_graph, nullptr, liveAtHead.atIndex(0).argument(i));
+            }
+        }
</ins><span class="cx">         
</span><span class="cx">         // Next identify where we would want to sink PutStacks to. We say that there is a deferred
</span><span class="cx">         // flush if we had a PutStack with a given FlushFormat but it hasn't been materialized yet.
</span><span class="lines">@@ -358,7 +362,8 @@
</span><span class="cx">             for (Node* node : *block) {
</span><span class="cx">                 switch (node-&gt;op()) {
</span><span class="cx">                 case PutStack:
</span><del>-                    putStacksToSink.add(node);
</del><ins>+                    if (!m_graph.m_argumentsOnStack.contains(node))
+                        putStacksToSink.add(node);
</ins><span class="cx">                     ssaCalculator.newDef(
</span><span class="cx">                         operandToVariable.operand(node-&gt;stackAccessData()-&gt;local),
</span><span class="cx">                         block, node-&gt;child1().node());
</span><span class="lines">@@ -483,11 +488,15 @@
</span><span class="cx">                             return;
</span><span class="cx">                         }
</span><span class="cx">                     
</span><ins>+                        Node* incoming = mapping.operand(operand);
+                        // Since we don't delete argument PutStacks, no need to add one back.
+                        if (m_graph.m_argumentsOnStack.contains(incoming))
+                            return;
+
</ins><span class="cx">                         // Gotta insert a PutStack.
</span><span class="cx">                         if (verbose)
</span><span class="cx">                             dataLog(&quot;Inserting a PutStack for &quot;, operand, &quot; at &quot;, node, &quot;\n&quot;);
</span><span class="cx"> 
</span><del>-                        Node* incoming = mapping.operand(operand);
</del><span class="cx">                         DFG_ASSERT(m_graph, node, incoming);
</span><span class="cx">                     
</span><span class="cx">                         insertionSet.insertNode(
</span><span class="lines">@@ -538,6 +547,8 @@
</span><span class="cx">                     Node* incoming;
</span><span class="cx">                     if (isConcrete(deferred.operand(operand))) {
</span><span class="cx">                         incoming = mapping.operand(operand);
</span><ins>+                        if (m_graph.m_argumentsOnStack.contains(incoming))
+                            continue;
</ins><span class="cx">                         DFG_ASSERT(m_graph, phiNode, incoming);
</span><span class="cx">                     } else {
</span><span class="cx">                         // Issue a GetStack to get the value. This might introduce some redundancy
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGRegisterBankh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGRegisterBank.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGRegisterBank.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGRegisterBank.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -236,6 +236,11 @@
</span><span class="cx">             return m_bank-&gt;isLockedAtIndex(m_index);
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        void unlock() const
+        {
+            return m_bank-&gt;unlockAtIndex(m_index);
+        }
+        
</ins><span class="cx">         void release() const
</span><span class="cx">         {
</span><span class="cx">             m_bank-&gt;releaseAtIndex(m_index);
</span><span class="lines">@@ -298,6 +303,13 @@
</span><span class="cx">         return m_data[index].lockCount;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void unlockAtIndex(unsigned index)
+    {
+        ASSERT(index &lt; NUM_REGS);
+        ASSERT(m_data[index].lockCount);
+        --m_data[index].lockCount;
+    }
+
</ins><span class="cx">     VirtualRegister nameAtIndex(unsigned index) const
</span><span class="cx">     {
</span><span class="cx">         ASSERT(index &lt; NUM_REGS);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSSAConversionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -73,7 +73,8 @@
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         // Find all SetLocals and create Defs for them. We handle SetArgument by creating a
</span><del>-        // GetLocal, and recording the flush format.
</del><ins>+        // GetStack, and recording the flush format. We handle GetArgumentRegister by directly
+        // adding the node to m_argumentMapping hash map.
</ins><span class="cx">         for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
</span><span class="cx">             BasicBlock* block = m_graph.block(blockIndex);
</span><span class="cx">             if (!block)
</span><span class="lines">@@ -83,14 +84,16 @@
</span><span class="cx">             // assignment for every local.
</span><span class="cx">             for (unsigned nodeIndex = 0; nodeIndex &lt; block-&gt;size(); ++nodeIndex) {
</span><span class="cx">                 Node* node = block-&gt;at(nodeIndex);
</span><del>-                if (node-&gt;op() != SetLocal &amp;&amp; node-&gt;op() != SetArgument)
</del><ins>+                if (node-&gt;op() != SetLocal &amp;&amp; node-&gt;op() != SetArgument &amp;&amp; node-&gt;op() != GetArgumentRegister)
</ins><span class="cx">                     continue;
</span><span class="cx">                 
</span><span class="cx">                 VariableAccessData* variable = node-&gt;variableAccessData();
</span><span class="cx">                 
</span><del>-                Node* childNode;
</del><ins>+                Node* childNode = nullptr;
</ins><span class="cx">                 if (node-&gt;op() == SetLocal)
</span><span class="cx">                     childNode = node-&gt;child1().node();
</span><ins>+                else if (node-&gt;op() == GetArgumentRegister)
+                    m_argumentMapping.add(node, node);
</ins><span class="cx">                 else {
</span><span class="cx">                     ASSERT(node-&gt;op() == SetArgument);
</span><span class="cx">                     childNode = m_insertionSet.insertNode(
</span><span class="lines">@@ -101,9 +104,11 @@
</span><span class="cx">                         m_argumentGetters.add(childNode);
</span><span class="cx">                     m_argumentMapping.add(node, childNode);
</span><span class="cx">                 }
</span><del>-                
-                m_calculator.newDef(
-                    m_ssaVariableForVariable.get(variable), block, childNode);
</del><ins>+
+                if (childNode) {
+                    m_calculator.newDef(
+                        m_ssaVariableForVariable.get(variable), block, childNode);
+                }
</ins><span class="cx">             }
</span><span class="cx">             
</span><span class="cx">             m_insertionSet.execute(block);
</span><span class="lines">@@ -294,7 +299,13 @@
</span><span class="cx">                     valueForOperand.operand(variable-&gt;local()) = child;
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><del>-                    
</del><ins>+
+                case GetArgumentRegister: {
+                    VariableAccessData* variable = node-&gt;variableAccessData();
+                    valueForOperand.operand(variable-&gt;local()) = node;
+                    break;
+                }
+
</ins><span class="cx">                 case GetStack: {
</span><span class="cx">                     ASSERT(m_argumentGetters.contains(node));
</span><span class="cx">                     valueForOperand.operand(node-&gt;stackAccessData()-&gt;local) = node;
</span><span class="lines">@@ -382,17 +393,21 @@
</span><span class="cx">             block-&gt;ssa = std::make_unique&lt;BasicBlock::SSAData&gt;(block);
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        m_graph.m_argumentFormats.resize(m_graph.m_arguments.size());
-        for (unsigned i = m_graph.m_arguments.size(); i--;) {
</del><ins>+        m_graph.m_argumentFormats.resize(m_graph.m_argumentsForChecking.size());
+        for (unsigned i = m_graph.m_argumentsForChecking.size(); i--;) {
</ins><span class="cx">             FlushFormat format = FlushedJSValue;
</span><span class="cx"> 
</span><del>-            Node* node = m_argumentMapping.get(m_graph.m_arguments[i]);
</del><ins>+            Node* node = m_argumentMapping.get(m_graph.m_argumentsForChecking[i]);
</ins><span class="cx">             
</span><span class="cx">             RELEASE_ASSERT(node);
</span><del>-            format = node-&gt;stackAccessData()-&gt;format;
</del><ins>+            if (node-&gt;op() == GetArgumentRegister) {
+                VariableAccessData* variable = node-&gt;variableAccessData();
+                format = variable-&gt;flushFormat();
+            } else
+                format = node-&gt;stackAccessData()-&gt;format;
</ins><span class="cx">             
</span><span class="cx">             m_graph.m_argumentFormats[i] = format;
</span><del>-            m_graph.m_arguments[i] = node; // Record the load that loads the arguments for the benefit of exit profiling.
</del><ins>+            m_graph.m_argumentsForChecking[i] = node; // Record the load that loads the arguments for the benefit of exit profiling.
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         m_graph.m_form = SSA;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -147,6 +147,7 @@
</span><span class="cx">     case CreateThis:
</span><span class="cx">     case GetCallee:
</span><span class="cx">     case GetArgumentCountIncludingThis:
</span><ins>+    case GetArgumentRegister:
</ins><span class="cx">     case GetRestLength:
</span><span class="cx">     case GetLocal:
</span><span class="cx">     case SetLocal:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -74,6 +74,7 @@
</span><span class="cx">     , m_lastGeneratedNode(LastNodeType)
</span><span class="cx">     , m_indexInBlock(0)
</span><span class="cx">     , m_generationInfo(m_jit.graph().frameRegisterCount())
</span><ins>+    , m_argumentGenerationInfo(CallFrameSlot::callee + GPRInfo::numberOfArgumentRegisters)
</ins><span class="cx">     , m_state(m_jit.graph())
</span><span class="cx">     , m_interpreter(m_jit.graph(), m_state)
</span><span class="cx">     , m_stream(&amp;jit.jitCode()-&gt;variableEventStream)
</span><span class="lines">@@ -407,6 +408,8 @@
</span><span class="cx"> {
</span><span class="cx">     for (unsigned i = 0; i &lt; m_generationInfo.size(); ++i)
</span><span class="cx">         m_generationInfo[i] = GenerationInfo();
</span><ins>+    for (unsigned i = 0; i &lt; m_argumentGenerationInfo.size(); ++i)
+        m_argumentGenerationInfo[i] = GenerationInfo();
</ins><span class="cx">     m_gprs = RegisterBank&lt;GPRInfo&gt;();
</span><span class="cx">     m_fprs = RegisterBank&lt;FPRInfo&gt;();
</span><span class="cx"> }
</span><span class="lines">@@ -1199,6 +1202,25 @@
</span><span class="cx">     return strings[format];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void dumpRegisterInfo(GenerationInfo&amp; info, unsigned index)
+{
+    if (info.alive())
+        dataLogF(&quot;    % 3d:%s%s&quot;, index, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));
+    else
+        dataLogF(&quot;    % 3d:[__][__]&quot;, index);
+    if (info.registerFormat() == DataFormatDouble)
+        dataLogF(&quot;:fpr%d\n&quot;, info.fpr());
+    else if (info.registerFormat() != DataFormatNone
+#if USE(JSVALUE32_64)
+        &amp;&amp; !(info.registerFormat() &amp; DataFormatJS)
+#endif
+        ) {
+        ASSERT(info.gpr() != InvalidGPRReg);
+        dataLogF(&quot;:%s\n&quot;, GPRInfo::debugName(info.gpr()));
+    } else
+        dataLogF(&quot;\n&quot;);
+}
+
</ins><span class="cx"> void SpeculativeJIT::dump(const char* label)
</span><span class="cx"> {
</span><span class="cx">     if (label)
</span><span class="lines">@@ -1208,25 +1230,15 @@
</span><span class="cx">     m_gprs.dump();
</span><span class="cx">     dataLogF(&quot;  fprs:\n&quot;);
</span><span class="cx">     m_fprs.dump();
</span><del>-    dataLogF(&quot;  VirtualRegisters:\n&quot;);
-    for (unsigned i = 0; i &lt; m_generationInfo.size(); ++i) {
-        GenerationInfo&amp; info = m_generationInfo[i];
-        if (info.alive())
-            dataLogF(&quot;    % 3d:%s%s&quot;, i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));
-        else
-            dataLogF(&quot;    % 3d:[__][__]&quot;, i);
-        if (info.registerFormat() == DataFormatDouble)
-            dataLogF(&quot;:fpr%d\n&quot;, info.fpr());
-        else if (info.registerFormat() != DataFormatNone
-#if USE(JSVALUE32_64)
-            &amp;&amp; !(info.registerFormat() &amp; DataFormatJS)
-#endif
-            ) {
-            ASSERT(info.gpr() != InvalidGPRReg);
-            dataLogF(&quot;:%s\n&quot;, GPRInfo::debugName(info.gpr()));
-        } else
-            dataLogF(&quot;\n&quot;);
-    }
</del><ins>+
+    dataLogF(&quot;  Argument VirtualRegisters:\n&quot;);
+    for (unsigned i = 0; i &lt; m_argumentGenerationInfo.size(); ++i)
+        dumpRegisterInfo(m_argumentGenerationInfo[i], i);
+
+    dataLogF(&quot;  Local VirtualRegisters:\n&quot;);
+    for (unsigned i = 0; i &lt; m_generationInfo.size(); ++i)
+        dumpRegisterInfo(m_generationInfo[i], i);
+
</ins><span class="cx">     if (label)
</span><span class="cx">         dataLogF(&quot;&lt;/%s&gt;\n&quot;, label);
</span><span class="cx"> }
</span><span class="lines">@@ -1677,6 +1689,9 @@
</span><span class="cx">     
</span><span class="cx">     m_jit.blockHeads()[m_block-&gt;index] = m_jit.label();
</span><span class="cx"> 
</span><ins>+    if (!m_block-&gt;index)
+        checkArgumentTypes();
+
</ins><span class="cx">     if (!m_block-&gt;intersectionOfCFAHasVisited) {
</span><span class="cx">         // Don't generate code for basic blocks that are unreachable according to CFA.
</span><span class="cx">         // But to be sure that nobody has generated a jump to this block, drop in a
</span><span class="lines">@@ -1687,6 +1702,9 @@
</span><span class="cx"> 
</span><span class="cx">     m_stream-&gt;appendAndLog(VariableEvent::reset());
</span><span class="cx">     
</span><ins>+    if (!m_block-&gt;index)
+        setupArgumentRegistersForEntry();
+    
</ins><span class="cx">     m_jit.jitAssertHasValidCallFrame();
</span><span class="cx">     m_jit.jitAssertTagsInPlace();
</span><span class="cx">     m_jit.jitAssertArgumentCountSane();
</span><span class="lines">@@ -1696,6 +1714,21 @@
</span><span class="cx">     
</span><span class="cx">     for (size_t i = m_block-&gt;variablesAtHead.size(); i--;) {
</span><span class="cx">         int operand = m_block-&gt;variablesAtHead.operandForIndex(i);
</span><ins>+        if (!m_block-&gt;index &amp;&amp; operandIsArgument(operand)) {
+            unsigned argument = m_block-&gt;variablesAtHead.argumentForIndex(i);
+            Node* argumentNode = m_jit.graph().m_argumentsForChecking[argument];
+            
+            if (argumentNode &amp;&amp; argumentNode-&gt;op() == GetArgumentRegister) {
+                if (!argumentNode-&gt;refCount())
+                    continue; // No need to record dead GetArgumentRegisters's.
+                m_stream-&gt;appendAndLog(
+                    VariableEvent::movHint(
+                        MinifiedID(argumentNode),
+                        argumentNode-&gt;local()));
+                continue;
+            }
+        }
+
</ins><span class="cx">         Node* node = m_block-&gt;variablesAtHead[i];
</span><span class="cx">         if (!node)
</span><span class="cx">             continue; // No need to record dead SetLocal's.
</span><span class="lines">@@ -1782,13 +1815,15 @@
</span><span class="cx">     m_origin = NodeOrigin(CodeOrigin(0), CodeOrigin(0), true);
</span><span class="cx"> 
</span><span class="cx">     for (int i = 0; i &lt; m_jit.codeBlock()-&gt;numParameters(); ++i) {
</span><del>-        Node* node = m_jit.graph().m_arguments[i];
</del><ins>+        Node* node = m_jit.graph().m_argumentsForChecking[i];
</ins><span class="cx">         if (!node) {
</span><span class="cx">             // The argument is dead. We don't do any checks for such arguments.
</span><span class="cx">             continue;
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        ASSERT(node-&gt;op() == SetArgument);
</del><ins>+        ASSERT(node-&gt;op() == SetArgument
+            || (node-&gt;op() == SetLocal &amp;&amp; node-&gt;child1()-&gt;op() == GetArgumentRegister)
+            || node-&gt;op() == GetArgumentRegister);
</ins><span class="cx">         ASSERT(node-&gt;shouldGenerate());
</span><span class="cx"> 
</span><span class="cx">         VariableAccessData* variableAccessData = node-&gt;variableAccessData();
</span><span class="lines">@@ -1799,23 +1834,44 @@
</span><span class="cx">         
</span><span class="cx">         VirtualRegister virtualRegister = variableAccessData-&gt;local();
</span><span class="cx"> 
</span><del>-        JSValueSource valueSource = JSValueSource(JITCompiler::addressFor(virtualRegister));
-        
</del><ins>+        JSValueSource valueSource;
+
</ins><span class="cx"> #if USE(JSVALUE64)
</span><ins>+        GPRReg argumentRegister = InvalidGPRReg;
+
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+        if (static_cast&lt;unsigned&gt;(i) &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS) {
+            argumentRegister = argumentRegisterForFunctionArgument(i);
+            valueSource = JSValueSource(argumentRegister);
+        } else
+#endif
+#endif
+            valueSource = JSValueSource(JITCompiler::addressFor(virtualRegister));
+
+#if USE(JSVALUE64)
</ins><span class="cx">         switch (format) {
</span><span class="cx">         case FlushedInt32: {
</span><del>-            speculationCheck(BadType, valueSource, node, m_jit.branch64(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
</del><ins>+            if (argumentRegister != InvalidGPRReg)
+                speculationCheck(BadType, valueSource, node, m_jit.branch64(MacroAssembler::Below, argumentRegister, GPRInfo::tagTypeNumberRegister));
+            else
+                speculationCheck(BadType, valueSource, node, m_jit.branch64(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case FlushedBoolean: {
</span><span class="cx">             GPRTemporary temp(this);
</span><del>-            m_jit.load64(JITCompiler::addressFor(virtualRegister), temp.gpr());
</del><ins>+            if (argumentRegister != InvalidGPRReg)
+                m_jit.move(argumentRegister, temp.gpr());
+            else
+                m_jit.load64(JITCompiler::addressFor(virtualRegister), temp.gpr());
</ins><span class="cx">             m_jit.xor64(TrustedImm32(static_cast&lt;int32_t&gt;(ValueFalse)), temp.gpr());
</span><span class="cx">             speculationCheck(BadType, valueSource, node, m_jit.branchTest64(MacroAssembler::NonZero, temp.gpr(), TrustedImm32(static_cast&lt;int32_t&gt;(~1))));
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case FlushedCell: {
</span><del>-            speculationCheck(BadType, valueSource, node, m_jit.branchTest64(MacroAssembler::NonZero, JITCompiler::addressFor(virtualRegister), GPRInfo::tagMaskRegister));
</del><ins>+            if (argumentRegister != InvalidGPRReg)
+                speculationCheck(BadType, valueSource, node, m_jit.branchTest64(MacroAssembler::NonZero, argumentRegister, GPRInfo::tagMaskRegister));
+            else
+                speculationCheck(BadType, valueSource, node, m_jit.branchTest64(MacroAssembler::NonZero, JITCompiler::addressFor(virtualRegister), GPRInfo::tagMaskRegister));
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         default:
</span><span class="lines">@@ -1846,10 +1902,38 @@
</span><span class="cx">     m_origin = NodeOrigin();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::setupArgumentRegistersForEntry()
+{
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    BasicBlock* firstBlock = m_jit.graph().block(0);
+
+    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=165720
+    // We should scan m_arguemntsForChecking instead of looking for GetArgumentRegister
+    // nodes in the root block.
+    for (size_t indexInBlock = 0; indexInBlock &lt; firstBlock-&gt;size(); ++indexInBlock) {
+        Node* node = firstBlock-&gt;at(indexInBlock);
+
+        if (node-&gt;op() == GetArgumentRegister) {
+            VirtualRegister virtualRegister = node-&gt;virtualRegister();
+            GenerationInfo&amp; info = generationInfoFromVirtualRegister(virtualRegister);
+            GPRReg argumentReg = GPRInfo::toArgumentRegister(node-&gt;argumentRegisterIndex());
+            
+            ASSERT(argumentReg != InvalidGPRReg);
+            
+            ASSERT(!m_gprs.isLocked(argumentReg));
+            m_gprs.allocateSpecific(argumentReg);
+            m_gprs.retain(argumentReg, virtualRegister, SpillOrderJS);
+            info.initArgumentRegisterValue(node, node-&gt;refCount(), argumentReg, DataFormatJS);
+            info.noticeOSRBirth(*m_stream, node, virtualRegister);
+            // Don't leave argument registers locked.
+            m_gprs.unlock(argumentReg);
+        }
+    }
+#endif
+}
+
</ins><span class="cx"> bool SpeculativeJIT::compile()
</span><span class="cx"> {
</span><del>-    checkArgumentTypes();
-    
</del><span class="cx">     ASSERT(!m_currentNode);
</span><span class="cx">     for (BlockIndex blockIndex = 0; blockIndex &lt; m_jit.graph().numBlocks(); ++blockIndex) {
</span><span class="cx">         m_jit.setForBlockIndex(blockIndex);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -128,7 +128,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx"> #if USE(JSVALUE64)
</span><del>-    GPRReg fillJSValue(Edge);
</del><ins>+    GPRReg fillJSValue(Edge, GPRReg gprToUse = InvalidGPRReg);
</ins><span class="cx"> #elif USE(JSVALUE32_64)
</span><span class="cx">     bool fillJSValue(Edge, GPRReg&amp;, GPRReg&amp;, FPRReg&amp;);
</span><span class="cx"> #endif
</span><span class="lines">@@ -200,6 +200,9 @@
</span><span class="cx"> #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
</span><span class="cx">         m_jit.addRegisterAllocationAtOffset(m_jit.debugOffset());
</span><span class="cx"> #endif
</span><ins>+        if (specific == InvalidGPRReg)
+            return allocate();
+
</ins><span class="cx">         VirtualRegister spillMe = m_gprs.allocateSpecific(specific);
</span><span class="cx">         if (spillMe.isValid()) {
</span><span class="cx"> #if USE(JSVALUE32_64)
</span><span class="lines">@@ -315,6 +318,8 @@
</span><span class="cx"> 
</span><span class="cx">     void checkArgumentTypes();
</span><span class="cx"> 
</span><ins>+    void setupArgumentRegistersForEntry();
+
</ins><span class="cx">     void clearGenerationInfo();
</span><span class="cx"> 
</span><span class="cx">     // These methods are used when generating 'unexpected'
</span><span class="lines">@@ -485,6 +490,9 @@
</span><span class="cx">     // Spill a VirtualRegister to the JSStack.
</span><span class="cx">     void spill(VirtualRegister spillMe)
</span><span class="cx">     {
</span><ins>+        if (spillMe.isArgument() &amp;&amp; m_block-&gt;index &gt; 0)
+            return;
+
</ins><span class="cx">         GenerationInfo&amp; info = generationInfoFromVirtualRegister(spillMe);
</span><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE32_64)
</span><span class="lines">@@ -2873,7 +2881,10 @@
</span><span class="cx"> 
</span><span class="cx">     GenerationInfo&amp; generationInfoFromVirtualRegister(VirtualRegister virtualRegister)
</span><span class="cx">     {
</span><del>-        return m_generationInfo[virtualRegister.toLocal()];
</del><ins>+        if (virtualRegister.isLocal())
+            return m_generationInfo[virtualRegister.toLocal()];
+        ASSERT(virtualRegister.isArgument());
+        return m_argumentGenerationInfo[virtualRegister.offset()];
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     GenerationInfo&amp; generationInfo(Node* node)
</span><span class="lines">@@ -2896,6 +2907,7 @@
</span><span class="cx">     unsigned m_indexInBlock;
</span><span class="cx">     // Virtual and physical register maps.
</span><span class="cx">     Vector&lt;GenerationInfo, 32&gt; m_generationInfo;
</span><ins>+    Vector&lt;GenerationInfo, 8&gt; m_argumentGenerationInfo;
</ins><span class="cx">     RegisterBank&lt;GPRInfo&gt; m_gprs;
</span><span class="cx">     RegisterBank&lt;FPRInfo&gt; m_fprs;
</span><span class="cx"> 
</span><span class="lines">@@ -2994,6 +3006,20 @@
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+#if USE(JSVALUE64)
+    explicit JSValueOperand(SpeculativeJIT* jit, Edge edge, GPRReg regToUse)
+        : m_jit(jit)
+        , m_edge(edge)
+        , m_gprOrInvalid(InvalidGPRReg)
+    {
+        ASSERT(m_jit);
+        if (!edge)
+            return;
+        if (jit-&gt;isFilled(node()) || regToUse != InvalidGPRReg)
+            gprUseSpecific(regToUse);
+    }
+#endif
+    
</ins><span class="cx">     ~JSValueOperand()
</span><span class="cx">     {
</span><span class="cx">         if (!m_edge)
</span><span class="lines">@@ -3030,6 +3056,12 @@
</span><span class="cx">             m_gprOrInvalid = m_jit-&gt;fillJSValue(m_edge);
</span><span class="cx">         return m_gprOrInvalid;
</span><span class="cx">     }
</span><ins>+    GPRReg gprUseSpecific(GPRReg regToUse)
+    {
+        if (m_gprOrInvalid == InvalidGPRReg)
+            m_gprOrInvalid = m_jit-&gt;fillJSValue(m_edge, regToUse);
+        return m_gprOrInvalid;
+    }
</ins><span class="cx">     JSValueRegs jsValueRegs()
</span><span class="cx">     {
</span><span class="cx">         return JSValueRegs(gpr());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -932,7 +932,7 @@
</span><span class="cx">     CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(dynamicOrigin, m_stream-&gt;size());
</span><span class="cx">     
</span><span class="cx">     CallLinkInfo* info = m_jit.codeBlock()-&gt;addCallLinkInfo();
</span><del>-    info-&gt;setUpCall(callType, node-&gt;origin.semantic, calleePayloadGPR);
</del><ins>+    info-&gt;setUpCall(callType, StackArgs, node-&gt;origin.semantic, calleePayloadGPR);
</ins><span class="cx">     
</span><span class="cx">     auto setResultAndResetStack = [&amp;] () {
</span><span class="cx">         GPRFlushedCallResult resultPayload(this);
</span><span class="lines">@@ -1081,7 +1081,7 @@
</span><span class="cx">             m_jit.emitRestoreCalleeSaves();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_jit.move(MacroAssembler::TrustedImmPtr(info), GPRInfo::regT2);
</del><ins>+    m_jit.move(MacroAssembler::TrustedImmPtr(info), GPRInfo::nonArgGPR0);
</ins><span class="cx">     JITCompiler::Call slowCall = m_jit.nearCall();
</span><span class="cx"> 
</span><span class="cx">     done.link(&amp;m_jit);
</span><span class="lines">@@ -5624,6 +5624,7 @@
</span><span class="cx">     case KillStack:
</span><span class="cx">     case GetStack:
</span><span class="cx">     case GetMyArgumentByVal:
</span><ins>+    case GetArgumentRegister:
</ins><span class="cx">     case GetMyArgumentByValOutOfBounds:
</span><span class="cx">     case PhantomCreateRest:
</span><span class="cx">     case PhantomSpread:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -80,7 +80,7 @@
</span><span class="cx">     unlock(fpr);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-GPRReg SpeculativeJIT::fillJSValue(Edge edge)
</del><ins>+GPRReg SpeculativeJIT::fillJSValue(Edge edge, GPRReg gprToUse)
</ins><span class="cx"> {
</span><span class="cx">     VirtualRegister virtualRegister = edge-&gt;virtualRegister();
</span><span class="cx">     GenerationInfo&amp; info = generationInfoFromVirtualRegister(virtualRegister);
</span><span class="lines">@@ -87,7 +87,7 @@
</span><span class="cx">     
</span><span class="cx">     switch (info.registerFormat()) {
</span><span class="cx">     case DataFormatNone: {
</span><del>-        GPRReg gpr = allocate();
</del><ins>+        GPRReg gpr = allocate(gprToUse);
</ins><span class="cx"> 
</span><span class="cx">         if (edge-&gt;hasConstant()) {
</span><span class="cx">             JSValue jsValue = edge-&gt;asJSValue();
</span><span class="lines">@@ -120,10 +120,15 @@
</span><span class="cx">         // If the register has already been locked we need to take a copy.
</span><span class="cx">         // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInt32, not DataFormatJSInt32.
</span><span class="cx">         if (m_gprs.isLocked(gpr)) {
</span><del>-            GPRReg result = allocate();
</del><ins>+            GPRReg result = allocate(gprToUse);
</ins><span class="cx">             m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr, result);
</span><span class="cx">             return result;
</span><span class="cx">         }
</span><ins>+        if (gprToUse != InvalidGPRReg &amp;&amp; gpr != gprToUse) {
+            GPRReg result = allocate(gprToUse);
+            m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr, result);
+            return result;
+        }
</ins><span class="cx">         m_gprs.lock(gpr);
</span><span class="cx">         m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr);
</span><span class="cx">         info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
</span><span class="lines">@@ -138,6 +143,11 @@
</span><span class="cx">     case DataFormatJSCell:
</span><span class="cx">     case DataFormatJSBoolean: {
</span><span class="cx">         GPRReg gpr = info.gpr();
</span><ins>+        if (gprToUse != InvalidGPRReg &amp;&amp; gpr != gprToUse) {
+            GPRReg result = allocate(gprToUse);
+            m_jit.move(gpr, result);
+            return result;
+        }
</ins><span class="cx">         m_gprs.lock(gpr);
</span><span class="cx">         return gpr;
</span><span class="cx">     }
</span><span class="lines">@@ -632,6 +642,7 @@
</span><span class="cx"> void SpeculativeJIT::emitCall(Node* node)
</span><span class="cx"> {
</span><span class="cx">     CallLinkInfo::CallType callType;
</span><ins>+    ArgumentsLocation argumentsLocation = StackArgs;
</ins><span class="cx">     bool isVarargs = false;
</span><span class="cx">     bool isForwardVarargs = false;
</span><span class="cx">     bool isTail = false;
</span><span class="lines">@@ -714,7 +725,11 @@
</span><span class="cx"> 
</span><span class="cx">     GPRReg calleeGPR = InvalidGPRReg;
</span><span class="cx">     CallFrameShuffleData shuffleData;
</span><del>-    
</del><ins>+    std::optional&lt;JSValueOperand&gt; tailCallee;
+    std::optional&lt;GPRTemporary&gt; calleeGPRTemporary;
+
+    incrementCounter(&amp;m_jit, VM::DFGCaller);
+
</ins><span class="cx">     ExecutableBase* executable = nullptr;
</span><span class="cx">     FunctionExecutable* functionExecutable = nullptr;
</span><span class="cx">     if (isDirect) {
</span><span class="lines">@@ -733,6 +748,7 @@
</span><span class="cx">         GPRReg resultGPR;
</span><span class="cx">         unsigned numUsedStackSlots = m_jit.graph().m_nextMachineLocal;
</span><span class="cx">         
</span><ins>+        incrementCounter(&amp;m_jit, VM::CallVarargs);
</ins><span class="cx">         if (isForwardVarargs) {
</span><span class="cx">             flushRegisters();
</span><span class="cx">             if (node-&gt;child3())
</span><span class="lines">@@ -841,15 +857,25 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (isTail) {
</span><ins>+            incrementCounter(&amp;m_jit, VM::TailCall);
</ins><span class="cx">             Edge calleeEdge = m_jit.graph().child(node, 0);
</span><del>-            JSValueOperand callee(this, calleeEdge);
-            calleeGPR = callee.gpr();
</del><ins>+            // We can't get the a specific register for the callee, since that will just move
+            // from any current register.  When we silent fill in the slow path we'll fill
+            // the original register and won't have the callee in the right register.
+            // Therefore we allocate a temp register for the callee and move ourselves.
+            tailCallee.emplace(this, calleeEdge);
+            GPRReg tailCalleeGPR = tailCallee-&gt;gpr();
+            calleeGPR = argumentRegisterForCallee();
+            if (tailCalleeGPR != calleeGPR)
+                calleeGPRTemporary = GPRTemporary(this, calleeGPR);
</ins><span class="cx">             if (!isDirect)
</span><del>-                callee.use();
</del><ins>+                tailCallee-&gt;use();
</ins><span class="cx"> 
</span><ins>+            argumentsLocation = argumentsLocationFor(numAllocatedArgs);
+            shuffleData.argumentsInRegisters = argumentsLocation != StackArgs;
</ins><span class="cx">             shuffleData.tagTypeNumber = GPRInfo::tagTypeNumberRegister;
</span><span class="cx">             shuffleData.numLocals = m_jit.graph().frameRegisterCount();
</span><del>-            shuffleData.callee = ValueRecovery::inGPR(calleeGPR, DataFormatJS);
</del><ins>+            shuffleData.callee = ValueRecovery::inGPR(tailCalleeGPR, DataFormatJS);
</ins><span class="cx">             shuffleData.args.resize(numAllocatedArgs);
</span><span class="cx"> 
</span><span class="cx">             for (unsigned i = 0; i &lt; numPassedArgs; ++i) {
</span><span class="lines">@@ -864,7 +890,8 @@
</span><span class="cx">                 shuffleData.args[i] = ValueRecovery::constant(jsUndefined());
</span><span class="cx"> 
</span><span class="cx">             shuffleData.setupCalleeSaveRegisters(m_jit.codeBlock());
</span><del>-        } else {
</del><ins>+        } else if (node-&gt;op() == CallEval) {
+            // CallEval is handled with the arguments in the stack
</ins><span class="cx">             m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs), JITCompiler::calleeFramePayloadSlot(CallFrameSlot::argumentCount));
</span><span class="cx"> 
</span><span class="cx">             for (unsigned i = 0; i &lt; numPassedArgs; i++) {
</span><span class="lines">@@ -878,15 +905,60 @@
</span><span class="cx">             
</span><span class="cx">             for (unsigned i = numPassedArgs; i &lt; numAllocatedArgs; ++i)
</span><span class="cx">                 m_jit.storeTrustedValue(jsUndefined(), JITCompiler::calleeArgumentSlot(i));
</span><ins>+
+            incrementCounter(&amp;m_jit, VM::CallEval);
+        } else {
+            for (unsigned i = numPassedArgs; i-- &gt; 0;) {
+                GPRReg platformArgGPR = argumentRegisterForFunctionArgument(i);
+                Edge argEdge = m_jit.graph().m_varArgChildren[node-&gt;firstChild() + 1 + i];
+                JSValueOperand arg(this, argEdge, platformArgGPR);
+                GPRReg argGPR = arg.gpr();
+                ASSERT(argGPR == platformArgGPR || platformArgGPR == InvalidGPRReg);
+
+                // Only free the non-argument registers at this point.
+                if (platformArgGPR == InvalidGPRReg) {
+                    use(argEdge);
+                    m_jit.store64(argGPR, JITCompiler::calleeArgumentSlot(i));
+                }
+            }
+
+            // Use the argument edges for arguments passed in registers.
+            for (unsigned i = numPassedArgs; i-- &gt; 0;) {
+                GPRReg argGPR = argumentRegisterForFunctionArgument(i);
+                if (argGPR != InvalidGPRReg) {
+                    Edge argEdge = m_jit.graph().m_varArgChildren[node-&gt;firstChild() + 1 + i];
+                    use(argEdge);
+                }
+            }
+
+            GPRTemporary argCount(this, argumentRegisterForArgumentCount());
+            GPRReg argCountGPR = argCount.gpr();
+            m_jit.move(TrustedImm32(numPassedArgs), argCountGPR);
+            argumentsLocation = argumentsLocationFor(numAllocatedArgs);
+
+            for (unsigned i = numPassedArgs; i &lt; numAllocatedArgs; ++i) {
+                GPRReg platformArgGPR = argumentRegisterForFunctionArgument(i);
+
+                // FIXME: https://bugs.webkit.org/show_bug.cgi?id=165769
+                // Eliminate filling extra stack slots with undefined JSValues for register arguments.
+                // The LLInt thunks aren't smart enough to know what register arguments to spill therefore
+                // we put undefined in both the extra argument register and stack slot.
+                if (platformArgGPR != InvalidGPRReg) {
+                    GPRTemporary argumentTemp(this, platformArgGPR);
+                    m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), argumentTemp.gpr());
+                }
+                m_jit.storeTrustedValue(jsUndefined(), JITCompiler::calleeArgumentSlot(i));
+            }
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (!isTail || isVarargs || isForwardVarargs) {
</span><span class="cx">         Edge calleeEdge = m_jit.graph().child(node, 0);
</span><del>-        JSValueOperand callee(this, calleeEdge);
</del><ins>+        JSValueOperand callee(this, calleeEdge, argumentRegisterForCallee());
</ins><span class="cx">         calleeGPR = callee.gpr();
</span><span class="cx">         callee.use();
</span><del>-        m_jit.store64(calleeGPR, JITCompiler::calleeFrameSlot(CallFrameSlot::callee));
</del><ins>+        if (argumentsLocation == StackArgs)
+            m_jit.store64(calleeGPR, JITCompiler::calleeFrameSlot(CallFrameSlot::callee));
</ins><span class="cx"> 
</span><span class="cx">         flushRegisters();
</span><span class="cx">     }
</span><span class="lines">@@ -913,7 +985,7 @@
</span><span class="cx">     };
</span><span class="cx">     
</span><span class="cx">     CallLinkInfo* callLinkInfo = m_jit.codeBlock()-&gt;addCallLinkInfo();
</span><del>-    callLinkInfo-&gt;setUpCall(callType, m_currentNode-&gt;origin.semantic, calleeGPR);
</del><ins>+    callLinkInfo-&gt;setUpCall(callType, argumentsLocation, m_currentNode-&gt;origin.semantic, calleeGPR);
</ins><span class="cx"> 
</span><span class="cx">     if (node-&gt;op() == CallEval) {
</span><span class="cx">         // We want to call operationCallEval but we don't want to overwrite the parameter area in
</span><span class="lines">@@ -954,8 +1026,14 @@
</span><span class="cx">         if (isTail) {
</span><span class="cx">             RELEASE_ASSERT(node-&gt;op() == DirectTailCall);
</span><span class="cx">             
</span><ins>+            if (calleeGPRTemporary != std::nullopt)
+                m_jit.move(tailCallee-&gt;gpr(), calleeGPRTemporary-&gt;gpr());
+
</ins><span class="cx">             JITCompiler::PatchableJump patchableJump = m_jit.patchableJump();
</span><span class="cx">             JITCompiler::Label mainPath = m_jit.label();
</span><ins>+
+            incrementCounter(&amp;m_jit, VM::TailCall);
+            incrementCounter(&amp;m_jit, VM::DirectCall);
</ins><span class="cx">             
</span><span class="cx">             m_jit.emitStoreCallSiteIndex(callSite);
</span><span class="cx">             
</span><span class="lines">@@ -971,6 +1049,8 @@
</span><span class="cx">             callOperation(operationLinkDirectCall, callLinkInfo, calleeGPR);
</span><span class="cx">             silentFillAllRegisters(InvalidGPRReg);
</span><span class="cx">             m_jit.exceptionCheck();
</span><ins>+            if (calleeGPRTemporary != std::nullopt)
+                m_jit.move(tailCallee-&gt;gpr(), calleeGPRTemporary-&gt;gpr());
</ins><span class="cx">             m_jit.jump().linkTo(mainPath, &amp;m_jit);
</span><span class="cx">             
</span><span class="cx">             useChildren(node);
</span><span class="lines">@@ -981,6 +1061,8 @@
</span><span class="cx">         
</span><span class="cx">         JITCompiler::Label mainPath = m_jit.label();
</span><span class="cx">         
</span><ins>+        incrementCounter(&amp;m_jit, VM::DirectCall);
+
</ins><span class="cx">         m_jit.emitStoreCallSiteIndex(callSite);
</span><span class="cx">         
</span><span class="cx">         JITCompiler::Call call = m_jit.nearCall();
</span><span class="lines">@@ -988,9 +1070,11 @@
</span><span class="cx">         
</span><span class="cx">         JITCompiler::Label slowPath = m_jit.label();
</span><span class="cx">         if (isX86())
</span><del>-            m_jit.pop(JITCompiler::selectScratchGPR(calleeGPR));
</del><ins>+            m_jit.pop(GPRInfo::nonArgGPR0);
</ins><span class="cx"> 
</span><del>-        callOperation(operationLinkDirectCall, callLinkInfo, calleeGPR);
</del><ins>+        m_jit.move(MacroAssembler::TrustedImmPtr(callLinkInfo), GPRInfo::nonArgGPR0); // Link info needs to be in nonArgGPR0
+        JITCompiler::Call slowCall = m_jit.nearCall();
+
</ins><span class="cx">         m_jit.exceptionCheck();
</span><span class="cx">         m_jit.jump().linkTo(mainPath, &amp;m_jit);
</span><span class="cx">         
</span><span class="lines">@@ -997,11 +1081,14 @@
</span><span class="cx">         done.link(&amp;m_jit);
</span><span class="cx">         
</span><span class="cx">         setResultAndResetStack();
</span><del>-        
-        m_jit.addJSDirectCall(call, slowPath, callLinkInfo);
</del><ins>+
+        m_jit.addJSDirectCall(call, slowCall, slowPath, callLinkInfo);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><del>-    
</del><ins>+
+    if (isTail &amp;&amp; calleeGPRTemporary != std::nullopt)
+        m_jit.move(tailCallee-&gt;gpr(), calleeGPRTemporary-&gt;gpr());
+
</ins><span class="cx">     m_jit.emitStoreCallSiteIndex(callSite);
</span><span class="cx">     
</span><span class="cx">     JITCompiler::DataLabelPtr targetToCheck;
</span><span class="lines">@@ -1025,23 +1112,22 @@
</span><span class="cx"> 
</span><span class="cx">     if (node-&gt;op() == TailCall) {
</span><span class="cx">         CallFrameShuffler callFrameShuffler(m_jit, shuffleData);
</span><del>-        callFrameShuffler.setCalleeJSValueRegs(JSValueRegs(GPRInfo::regT0));
</del><ins>+        if (argumentsLocation == StackArgs)
+            callFrameShuffler.setCalleeJSValueRegs(JSValueRegs(argumentRegisterForCallee()));
</ins><span class="cx">         callFrameShuffler.prepareForSlowPath();
</span><del>-    } else {
-        m_jit.move(calleeGPR, GPRInfo::regT0); // Callee needs to be in regT0
</del><ins>+    } else if (isTail)
+        m_jit.emitRestoreCalleeSaves();
</ins><span class="cx"> 
</span><del>-        if (isTail)
-            m_jit.emitRestoreCalleeSaves(); // This needs to happen after we moved calleeGPR to regT0
-    }
-
-    m_jit.move(MacroAssembler::TrustedImmPtr(callLinkInfo), GPRInfo::regT2); // Link info needs to be in regT2
</del><ins>+    m_jit.move(MacroAssembler::TrustedImmPtr(callLinkInfo), GPRInfo::nonArgGPR0); // Link info needs to be in nonArgGPR0
</ins><span class="cx">     JITCompiler::Call slowCall = m_jit.nearCall();
</span><span class="cx"> 
</span><span class="cx">     done.link(&amp;m_jit);
</span><span class="cx"> 
</span><del>-    if (isTail)
</del><ins>+    if (isTail) {
+        tailCallee = std::nullopt;
+        calleeGPRTemporary = std::nullopt;
</ins><span class="cx">         m_jit.abortWithReason(JITDidReturnFromTailCall);
</span><del>-    else
</del><ins>+    } else
</ins><span class="cx">         setResultAndResetStack();
</span><span class="cx"> 
</span><span class="cx">     m_jit.addJSCall(fastCall, slowCall, targetToCheck, callLinkInfo);
</span><span class="lines">@@ -4166,6 +4252,9 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case GetArgumentRegister:
+        break;
+            
</ins><span class="cx">     case GetRestLength: {
</span><span class="cx">         compileGetRestLength(node);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGStrengthReductionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -276,6 +276,9 @@
</span><span class="cx">             Node* setLocal = nullptr;
</span><span class="cx">             VirtualRegister local = m_node-&gt;local();
</span><span class="cx">             
</span><ins>+            if (local.isArgument() &amp;&amp; m_graph.m_strengthReduceArguments != OptimizeArgumentFlushes)
+                break;
+
</ins><span class="cx">             for (unsigned i = m_nodeIndex; i--;) {
</span><span class="cx">                 Node* node = m_block-&gt;at(i);
</span><span class="cx">                 if (node-&gt;op() == SetLocal &amp;&amp; node-&gt;local() == local) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGThunkscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGThunks.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGThunks.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGThunks.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -130,15 +130,30 @@
</span><span class="cx">     jit.store32(GPRInfo::regT3, MacroAssembler::BaseIndex(GPRInfo::callFrameRegister, GPRInfo::regT4, MacroAssembler::TimesEight, -static_cast&lt;intptr_t&gt;(sizeof(Register)) + static_cast&lt;intptr_t&gt;(sizeof(int32_t))));
</span><span class="cx">     jit.branchPtr(MacroAssembler::NotEqual, GPRInfo::regT1, MacroAssembler::TrustedImmPtr(bitwise_cast&lt;void*&gt;(-static_cast&lt;intptr_t&gt;(CallFrame::headerSizeInRegisters)))).linkTo(loop, &amp;jit);
</span><span class="cx">     
</span><del>-    jit.loadPtr(MacroAssembler::Address(GPRInfo::regT0, offsetOfTargetPC), GPRInfo::regT1);
-    MacroAssembler::Jump ok = jit.branchPtr(MacroAssembler::Above, GPRInfo::regT1, MacroAssembler::TrustedImmPtr(bitwise_cast&lt;void*&gt;(static_cast&lt;intptr_t&gt;(1000))));
</del><ins>+    jit.loadPtr(MacroAssembler::Address(GPRInfo::regT0, offsetOfTargetPC), GPRInfo::nonArgGPR0);
+    MacroAssembler::Jump ok = jit.branchPtr(MacroAssembler::Above, GPRInfo::nonArgGPR0, MacroAssembler::TrustedImmPtr(bitwise_cast&lt;void*&gt;(static_cast&lt;intptr_t&gt;(1000))));
</ins><span class="cx">     jit.abortWithReason(DFGUnreasonableOSREntryJumpDestination);
</span><span class="cx"> 
</span><span class="cx">     ok.link(&amp;jit);
</span><ins>+
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    // Load argument values into argument registers
+    jit.loadPtr(MacroAssembler::Address(GPRInfo::callFrameRegister, CallFrameSlot::callee * static_cast&lt;int&gt;(sizeof(Register))), argumentRegisterForCallee());
+    GPRReg argCountReg = argumentRegisterForArgumentCount();
+    jit.load32(AssemblyHelpers::payloadFor(CallFrameSlot::argumentCount), argCountReg);
+    
+    MacroAssembler::JumpList doneLoadingArgs;
+    
+    for (unsigned argIndex = 0; argIndex &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argIndex++)
+        jit.load64(MacroAssembler::Address(GPRInfo::callFrameRegister, (CallFrameSlot::thisArgument + argIndex) * static_cast&lt;int&gt;(sizeof(Register))), argumentRegisterForFunctionArgument(argIndex));
+    
+    doneLoadingArgs.link(&amp;jit);
+#endif
+    
</ins><span class="cx">     jit.restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer();
</span><span class="cx">     jit.emitMaterializeTagCheckRegisters();
</span><span class="cx"> 
</span><del>-    jit.jump(GPRInfo::regT1);
</del><ins>+    jit.jump(GPRInfo::nonArgGPR0);
</ins><span class="cx">     
</span><span class="cx">     LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
</span><span class="cx">     return FINALIZE_CODE(patchBuffer, (&quot;DFG OSR entry thunk&quot;));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGVariableEventStreamcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -133,8 +133,13 @@
</span><span class="cx">     if (!index) {
</span><span class="cx">         valueRecoveries = Operands&lt;ValueRecovery&gt;(codeBlock-&gt;numParameters(), numVariables);
</span><span class="cx">         for (size_t i = 0; i &lt; valueRecoveries.size(); ++i) {
</span><del>-            valueRecoveries[i] = ValueRecovery::displacedInJSStack(
-                VirtualRegister(valueRecoveries.operandForIndex(i)), DataFormatJS);
</del><ins>+            if (i &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS) {
+                valueRecoveries[i] = ValueRecovery::inGPR(
+                    argumentRegisterForFunctionArgument(i), DataFormatJS);
+            } else {
+                valueRecoveries[i] = ValueRecovery::displacedInJSStack(
+                    VirtualRegister(valueRecoveries.operandForIndex(i)), DataFormatJS);
+            }
</ins><span class="cx">         }
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="lines">@@ -161,6 +166,12 @@
</span><span class="cx">             MinifiedGenerationInfo info;
</span><span class="cx">             info.update(event);
</span><span class="cx">             generationInfos.add(event.id(), info);
</span><ins>+            MinifiedNode* node = graph.at(event.id());
+            if (node &amp;&amp; node-&gt;hasArgumentIndex()) {
+                unsigned argument = node-&gt;argumentIndex();
+                VirtualRegister argumentReg = virtualRegisterForArgument(argument);
+                operandSources.setOperand(argumentReg, ValueSource(event.id()));
+            }
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case Fill:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGVirtualRegisterAllocationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -42,7 +42,33 @@
</span><span class="cx">         : Phase(graph, &quot;virtual register allocation&quot;)
</span><span class="cx">     {
</span><span class="cx">     }
</span><del>-    
</del><ins>+
+    void allocateRegister(ScoreBoard&amp; scoreBoard, Node* node)
+    {
+        // First, call use on all of the current node's children, then
+        // allocate a VirtualRegister for this node. We do so in this
+        // order so that if a child is on its last use, and a
+        // VirtualRegister is freed, then it may be reused for node.
+        if (node-&gt;flags() &amp; NodeHasVarArgs) {
+            for (unsigned childIdx = node-&gt;firstChild(); childIdx &lt; node-&gt;firstChild() + node-&gt;numChildren(); childIdx++)
+                scoreBoard.useIfHasResult(m_graph.m_varArgChildren[childIdx]);
+        } else {
+            scoreBoard.useIfHasResult(node-&gt;child1());
+            scoreBoard.useIfHasResult(node-&gt;child2());
+            scoreBoard.useIfHasResult(node-&gt;child3());
+        }
+
+        if (!node-&gt;hasResult())
+            return;
+
+        VirtualRegister virtualRegister = scoreBoard.allocate();
+        node-&gt;setVirtualRegister(virtualRegister);
+        // 'mustGenerate' nodes have their useCount artificially elevated,
+        // call use now to account for this.
+        if (node-&gt;mustGenerate())
+            scoreBoard.use(node);
+    }
+
</ins><span class="cx">     bool run()
</span><span class="cx">     {
</span><span class="cx">         DFG_ASSERT(m_graph, nullptr, m_graph.m_form == ThreadedCPS);
</span><span class="lines">@@ -59,6 +85,17 @@
</span><span class="cx">                 // Force usage of highest-numbered virtual registers.
</span><span class="cx">                 scoreBoard.sortFree();
</span><span class="cx">             }
</span><ins>+
+            // Handle GetArgumentRegister Nodes first as the register is alive on entry
+            // to the function and may need to be spilled before any use.
+            if (!blockIndex) {
+                for (size_t indexInBlock = 0; indexInBlock &lt; block-&gt;size(); ++indexInBlock) {
+                    Node* node = block-&gt;at(indexInBlock);
+                    if (node-&gt;op() == GetArgumentRegister)
+                        allocateRegister(scoreBoard, node);
+                }
+            }
+
</ins><span class="cx">             for (size_t indexInBlock = 0; indexInBlock &lt; block-&gt;size(); ++indexInBlock) {
</span><span class="cx">                 Node* node = block-&gt;at(indexInBlock);
</span><span class="cx">         
</span><span class="lines">@@ -73,32 +110,14 @@
</span><span class="cx">                 case GetLocal:
</span><span class="cx">                     ASSERT(!node-&gt;child1()-&gt;hasResult());
</span><span class="cx">                     break;
</span><ins>+                case GetArgumentRegister:
+                    ASSERT(!blockIndex);
+                    continue;
</ins><span class="cx">                 default:
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><del>-                
-                // First, call use on all of the current node's children, then
-                // allocate a VirtualRegister for this node. We do so in this
-                // order so that if a child is on its last use, and a
-                // VirtualRegister is freed, then it may be reused for node.
-                if (node-&gt;flags() &amp; NodeHasVarArgs) {
-                    for (unsigned childIdx = node-&gt;firstChild(); childIdx &lt; node-&gt;firstChild() + node-&gt;numChildren(); childIdx++)
-                        scoreBoard.useIfHasResult(m_graph.m_varArgChildren[childIdx]);
-                } else {
-                    scoreBoard.useIfHasResult(node-&gt;child1());
-                    scoreBoard.useIfHasResult(node-&gt;child2());
-                    scoreBoard.useIfHasResult(node-&gt;child3());
-                }
</del><span class="cx"> 
</span><del>-                if (!node-&gt;hasResult())
-                    continue;
-
-                VirtualRegister virtualRegister = scoreBoard.allocate();
-                node-&gt;setVirtualRegister(virtualRegister);
-                // 'mustGenerate' nodes have their useCount artificially elevated,
-                // call use now to account for this.
-                if (node-&gt;mustGenerate())
-                    scoreBoard.use(node);
</del><ins>+                allocateRegister(scoreBoard, node);
</ins><span class="cx">             }
</span><span class="cx">             scoreBoard.assertClear();
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -172,6 +172,7 @@
</span><span class="cx">     case GetExecutable:
</span><span class="cx">     case GetScope:
</span><span class="cx">     case GetCallee:
</span><ins>+    case GetArgumentRegister:
</ins><span class="cx">     case GetArgumentCountIncludingThis:
</span><span class="cx">     case ToNumber:
</span><span class="cx">     case ToString:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLJITCodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -45,7 +45,8 @@
</span><span class="cx">         dataLog(&quot;Destroying FTL JIT code at &quot;);
</span><span class="cx">         CommaPrinter comma;
</span><span class="cx">         dataLog(comma, m_b3Code);
</span><del>-        dataLog(comma, m_arityCheckEntrypoint);
</del><ins>+        dataLog(comma, m_registerArgsPossibleExtraArgsEntryPoint);
+        dataLog(comma, m_registerArgsCheckArityEntryPoint);
</ins><span class="cx">         dataLog(&quot;\n&quot;);
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="lines">@@ -60,31 +61,30 @@
</span><span class="cx">     m_b3Byproducts = WTFMove(byproducts);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JITCode::initializeAddressForCall(CodePtr address)
</del><ins>+void JITCode::initializeEntrypointThunk(CodeRef entrypointThunk)
</ins><span class="cx"> {
</span><del>-    m_addressForCall = address;
</del><ins>+    m_entrypointThunk = entrypointThunk;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JITCode::initializeArityCheckEntrypoint(CodeRef entrypoint)
</del><ins>+void JITCode::setEntryFor(EntryPointType type, CodePtr entry)
</ins><span class="cx"> {
</span><del>-    m_arityCheckEntrypoint = entrypoint;
</del><ins>+    m_entrypoints.setEntryFor(type, entry);
</ins><span class="cx"> }
</span><del>-
-JITCode::CodePtr JITCode::addressForCall(ArityCheckMode arityCheck)
</del><ins>+    
+JITCode::CodePtr JITCode::addressForCall(EntryPointType entryType)
</ins><span class="cx"> {
</span><del>-    switch (arityCheck) {
-    case ArityCheckNotRequired:
-        return m_addressForCall;
-    case MustCheckArity:
-        return m_arityCheckEntrypoint.code();
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-    return CodePtr();
</del><ins>+    CodePtr entry = m_entrypoints.entryFor(entryType);
+    RELEASE_ASSERT(entry);
+    return entry;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void* JITCode::executableAddressAtOffset(size_t offset)
</span><span class="cx"> {
</span><del>-    return reinterpret_cast&lt;char*&gt;(m_addressForCall.executableAddress()) + offset;
</del><ins>+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    return reinterpret_cast&lt;char*&gt;(addressForCall(RegisterArgsArityCheckNotRequired).executableAddress()) + offset;
+#else
+    return reinterpret_cast&lt;char*&gt;(addressForCall(StackArgsArityCheckNotRequired).executableAddress()) + offset;
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void* JITCode::dataAddressAtOffset(size_t)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLJITCodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLJITCode.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJITCode.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/ftl/FTLJITCode.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx">     JITCode();
</span><span class="cx">     ~JITCode();
</span><span class="cx"> 
</span><del>-    CodePtr addressForCall(ArityCheckMode) override;
</del><ins>+    CodePtr addressForCall(EntryPointType) override;
</ins><span class="cx">     void* executableAddressAtOffset(size_t offset) override;
</span><span class="cx">     void* dataAddressAtOffset(size_t offset) override;
</span><span class="cx">     unsigned offsetOf(void* pointerIntoCode) override;
</span><span class="lines">@@ -53,9 +53,9 @@
</span><span class="cx"> 
</span><span class="cx">     void initializeB3Code(CodeRef);
</span><span class="cx">     void initializeB3Byproducts(std::unique_ptr&lt;B3::OpaqueByproducts&gt;);
</span><del>-    void initializeAddressForCall(CodePtr);
-    void initializeArityCheckEntrypoint(CodeRef);
-    
</del><ins>+    void initializeEntrypointThunk(CodeRef);
+    void setEntryFor(EntryPointType, CodePtr);
+
</ins><span class="cx">     void validateReferences(const TrackedReferences&amp;) override;
</span><span class="cx"> 
</span><span class="cx">     RegisterSet liveRegistersToPreserveAtExceptionHandlingCallSite(CodeBlock*, CallSiteIndex) override;
</span><span class="lines">@@ -77,7 +77,12 @@
</span><span class="cx">     CodePtr m_addressForCall;
</span><span class="cx">     CodeRef m_b3Code;
</span><span class="cx">     std::unique_ptr&lt;B3::OpaqueByproducts&gt; m_b3Byproducts;
</span><del>-    CodeRef m_arityCheckEntrypoint;
</del><ins>+    CodeRef m_entrypointThunk;
+    JITEntryPoints m_entrypoints;
+    CodePtr m_registerArgsPossibleExtraArgsEntryPoint;
+    CodePtr m_registerArgsCheckArityEntryPoint;
+    CodePtr m_stackArgsArityOKEntryPoint;
+    CodePtr m_stackArgsCheckArityEntrypoint;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::FTL
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLJITFinalizercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -76,7 +76,7 @@
</span><span class="cx">             dumpDisassembly, *b3CodeLinkBuffer,
</span><span class="cx">             (&quot;FTL B3 code for %s&quot;, toCString(CodeBlockWithJITType(m_plan.codeBlock, JITCode::FTLJIT)).data())));
</span><span class="cx"> 
</span><del>-    jitCode-&gt;initializeArityCheckEntrypoint(
</del><ins>+    jitCode-&gt;initializeEntrypointThunk(
</ins><span class="cx">         FINALIZE_CODE_IF(
</span><span class="cx">             dumpDisassembly, *entrypointLinkBuffer,
</span><span class="cx">             (&quot;FTL entrypoint thunk for %s with B3 generated code at %p&quot;, toCString(CodeBlockWithJITType(m_plan.codeBlock, JITCode::FTLJIT)).data(), function)));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLinkcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLink.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLink.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/ftl/FTLLink.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -127,14 +127,110 @@
</span><span class="cx">     
</span><span class="cx">     switch (graph.m_plan.mode) {
</span><span class="cx">     case FTLMode: {
</span><del>-        CCallHelpers::JumpList mainPathJumps;
-    
-        jit.load32(
-            frame.withOffset(sizeof(Register) * CallFrameSlot::argumentCount),
-            GPRInfo::regT1);
-        mainPathJumps.append(jit.branch32(
-            CCallHelpers::AboveOrEqual, GPRInfo::regT1,
-            CCallHelpers::TrustedImm32(codeBlock-&gt;numParameters())));
</del><ins>+        CCallHelpers::JumpList fillRegistersAndContinueMainPath;
+        CCallHelpers::JumpList toMainPath;
+
+        unsigned numParameters = static_cast&lt;unsigned&gt;(codeBlock-&gt;numParameters());
+        unsigned maxRegisterArgumentCount = std::min(numParameters, NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS);
+
+        GPRReg argCountReg = argumentRegisterForArgumentCount();
+
+        CCallHelpers::Label registerArgumentsEntrypoints[NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS + 1];
+
+        if (numParameters &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS) {
+            // Spill any extra register arguments passed to function onto the stack.
+            for (unsigned argIndex = NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS - 1; argIndex &gt;= numParameters; argIndex--) {
+                registerArgumentsEntrypoints[argIndex + 1] = jit.label();
+                jit.emitPutArgumentToCallFrameBeforePrologue(argumentRegisterForFunctionArgument(argIndex), argIndex);
+            }
+            incrementCounter(&amp;jit, VM::RegArgsExtra);
+            toMainPath.append(jit.jump());
+        }
+
+        CCallHelpers::JumpList continueToArityFixup;
+
+        CCallHelpers::Label stackArgsCheckArityEntry = jit.label();
+        incrementCounter(&amp;jit, VM::StackArgsArity);
+        jit.load32(frame.withOffset(sizeof(Register) * CallFrameSlot::argumentCount), GPRInfo::regT1);
+        continueToArityFixup.append(jit.branch32(
+            CCallHelpers::Below, GPRInfo::regT1,
+            CCallHelpers::TrustedImm32(numParameters)));
+
+#if ENABLE(VM_COUNTERS)
+        CCallHelpers::Jump continueToStackArityOk = jit.jump();
+#endif
+
+        CCallHelpers::Label stackArgsArityOKEntry = jit.label();
+
+        incrementCounter(&amp;jit, VM::StackArgsArity);
+
+#if ENABLE(VM_COUNTERS)
+        continueToStackArityOk.link(&amp;jit);
+#endif
+
+        // Load argument values into argument registers
+
+        // FIXME: Would like to eliminate these to load, but we currently can't jump into
+        // the B3 compiled code at an arbitrary point from the slow entry where the
+        // registers are stored to the stack.
+        jit.emitGetFromCallFrameHeaderBeforePrologue(CallFrameSlot::callee, argumentRegisterForCallee());
+        jit.emitGetPayloadFromCallFrameHeaderBeforePrologue(CallFrameSlot::argumentCount, argumentRegisterForArgumentCount());
+
+        for (unsigned argIndex = 0; argIndex &lt; maxRegisterArgumentCount; argIndex++)
+            jit.emitGetFromCallFrameArgumentBeforePrologue(argIndex, argumentRegisterForFunctionArgument(argIndex));
+
+        toMainPath.append(jit.jump());
+
+        CCallHelpers::Label registerArgsCheckArityEntry = jit.label();
+        incrementCounter(&amp;jit, VM::RegArgsArity);
+
+        CCallHelpers::JumpList continueToRegisterArityFixup;
+        CCallHelpers::Label checkForExtraRegisterArguments;
+
+        if (numParameters &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS) {
+            toMainPath.append(jit.branch32(
+                CCallHelpers::Equal, argCountReg, CCallHelpers::TrustedImm32(numParameters)));
+            continueToRegisterArityFixup.append(jit.branch32(
+                CCallHelpers::Below, argCountReg, CCallHelpers::TrustedImm32(numParameters)));
+            //  Fall through to the &quot;extra register arity&quot; case.
+
+            checkForExtraRegisterArguments = jit.label();
+            // Spill any extra register arguments passed to function onto the stack.
+            for (unsigned argIndex = numParameters; argIndex &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argIndex++) {
+                toMainPath.append(jit.branch32(CCallHelpers::BelowOrEqual, argCountReg, CCallHelpers::TrustedImm32(argIndex)));
+                jit.emitPutArgumentToCallFrameBeforePrologue(argumentRegisterForFunctionArgument(argIndex), argIndex);
+            }
+
+            incrementCounter(&amp;jit, VM::RegArgsExtra);
+            toMainPath.append(jit.jump());
+        } else
+            toMainPath.append(jit.branch32(
+                CCallHelpers::AboveOrEqual, argCountReg, CCallHelpers::TrustedImm32(numParameters)));
+
+#if ENABLE(VM_COUNTERS)
+        continueToRegisterArityFixup.append(jit.jump());
+#endif
+
+        if (numParameters &gt; 0) {
+            //  There should always be a &quot;this&quot; parameter.
+            CCallHelpers::Label registerArgumentsNeedArityFixup = jit.label();
+
+            for (unsigned argIndex = 1; argIndex &lt; numParameters &amp;&amp; argIndex &lt;= maxRegisterArgumentCount; argIndex++)
+                registerArgumentsEntrypoints[argIndex] = registerArgumentsNeedArityFixup;
+        }
+
+#if ENABLE(VM_COUNTERS)
+        incrementCounter(&amp;jit, VM::RegArgsArity);
+#endif
+
+        continueToRegisterArityFixup.link(&amp;jit);
+
+        jit.spillArgumentRegistersToFrameBeforePrologue(maxRegisterArgumentCount);
+
+        continueToArityFixup.link(&amp;jit);
+
+        incrementCounter(&amp;jit, VM::ArityFixupRequired);
+
</ins><span class="cx">         jit.emitFunctionPrologue();
</span><span class="cx">         jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
</span><span class="cx">         jit.storePtr(GPRInfo::callFrameRegister, &amp;vm.topCallFrame);
</span><span class="lines">@@ -155,12 +251,21 @@
</span><span class="cx"> 
</span><span class="cx">         jit.move(GPRInfo::returnValueGPR, GPRInfo::argumentGPR0);
</span><span class="cx">         jit.emitFunctionEpilogue();
</span><del>-        mainPathJumps.append(jit.branchTest32(CCallHelpers::Zero, GPRInfo::argumentGPR0));
</del><ins>+        fillRegistersAndContinueMainPath.append(jit.branchTest32(CCallHelpers::Zero, GPRInfo::argumentGPR0));
</ins><span class="cx">         jit.emitFunctionPrologue();
</span><span class="cx">         CCallHelpers::Call callArityFixup = jit.call();
</span><span class="cx">         jit.emitFunctionEpilogue();
</span><del>-        mainPathJumps.append(jit.jump());
</del><span class="cx"> 
</span><ins>+        fillRegistersAndContinueMainPath.append(jit.jump());
+
+        fillRegistersAndContinueMainPath.linkTo(stackArgsArityOKEntry, &amp;jit);
+
+#if ENABLE(VM_COUNTERS)
+        CCallHelpers::Label registerEntryNoArity = jit.label();
+        incrementCounter(&amp;jit, VM::RegArgsNoArity);
+        toMainPath.append(jit.jump());
+#endif
+
</ins><span class="cx">         linkBuffer = std::make_unique&lt;LinkBuffer&gt;(vm, jit, codeBlock, JITCompilationCanFail);
</span><span class="cx">         if (linkBuffer-&gt;didFailToAllocate()) {
</span><span class="cx">             state.allocationFailed = true;
</span><span class="lines">@@ -169,9 +274,35 @@
</span><span class="cx">         linkBuffer-&gt;link(callArityCheck, codeBlock-&gt;m_isConstructor ? operationConstructArityCheck : operationCallArityCheck);
</span><span class="cx">         linkBuffer-&gt;link(callLookupExceptionHandlerFromCallerFrame, lookupExceptionHandlerFromCallerFrame);
</span><span class="cx">         linkBuffer-&gt;link(callArityFixup, FunctionPtr((vm.getCTIStub(arityFixupGenerator)).code().executableAddress()));
</span><del>-        linkBuffer-&gt;link(mainPathJumps, CodeLocationLabel(bitwise_cast&lt;void*&gt;(state.generatedFunction)));
</del><ins>+        linkBuffer-&gt;link(toMainPath, CodeLocationLabel(bitwise_cast&lt;void*&gt;(state.generatedFunction)));
</ins><span class="cx"> 
</span><del>-        state.jitCode-&gt;initializeAddressForCall(MacroAssemblerCodePtr(bitwise_cast&lt;void*&gt;(state.generatedFunction)));
</del><ins>+        state.jitCode-&gt;setEntryFor(StackArgsMustCheckArity, linkBuffer-&gt;locationOf(stackArgsCheckArityEntry));
+        state.jitCode-&gt;setEntryFor(StackArgsArityCheckNotRequired, linkBuffer-&gt;locationOf(stackArgsArityOKEntry));
+
+#if ENABLE(VM_COUNTERS)
+        MacroAssemblerCodePtr mainEntry = linkBuffer-&gt;locationOf(registerEntryNoArity);
+#else
+        MacroAssemblerCodePtr mainEntry = MacroAssemblerCodePtr(bitwise_cast&lt;void*&gt;(state.generatedFunction));
+#endif
+        state.jitCode-&gt;setEntryFor(RegisterArgsArityCheckNotRequired, mainEntry);
+
+        if (checkForExtraRegisterArguments.isSet())
+            state.jitCode-&gt;setEntryFor(RegisterArgsPossibleExtraArgs, linkBuffer-&gt;locationOf(checkForExtraRegisterArguments));
+        else
+            state.jitCode-&gt;setEntryFor(RegisterArgsPossibleExtraArgs, mainEntry);
+                                                                             
+        state.jitCode-&gt;setEntryFor(RegisterArgsMustCheckArity, linkBuffer-&gt;locationOf(registerArgsCheckArityEntry));
+
+        for (unsigned argCount = 1; argCount &lt;= NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argCount++) {
+            MacroAssemblerCodePtr entry;
+            if (argCount == numParameters)
+                entry = mainEntry;
+            else if (registerArgumentsEntrypoints[argCount].isSet())
+                entry = linkBuffer-&gt;locationOf(registerArgumentsEntrypoints[argCount]);
+            else
+                entry = linkBuffer-&gt;locationOf(registerArgsCheckArityEntry);
+            state.jitCode-&gt;setEntryFor(JITEntryPoints::registerEntryTypeForArgumentCount(argCount), entry);
+        }
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="lines">@@ -181,7 +312,20 @@
</span><span class="cx">         // point we've even done the stack check. Basically we just have to make the
</span><span class="cx">         // call to the B3-generated code.
</span><span class="cx">         CCallHelpers::Label start = jit.label();
</span><ins>+
</ins><span class="cx">         jit.emitFunctionEpilogue();
</span><ins>+
+        // Load argument values into argument registers
+
+        // FIXME: Would like to eliminate these to load, but we currently can't jump into
+        // the B3 compiled code at an arbitrary point from the slow entry where the
+        // registers are stored to the stack.
+        jit.emitGetFromCallFrameHeaderBeforePrologue(CallFrameSlot::callee, argumentRegisterForCallee());
+        jit.emitGetPayloadFromCallFrameHeaderBeforePrologue(CallFrameSlot::argumentCount, argumentRegisterForArgumentCount());
+
+        for (unsigned argIndex = 0; argIndex &lt; static_cast&lt;unsigned&gt;(codeBlock-&gt;numParameters()) &amp;&amp; argIndex &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argIndex++)
+            jit.emitGetFromCallFrameArgumentBeforePrologue(argIndex, argumentRegisterForFunctionArgument(argIndex));
+
</ins><span class="cx">         CCallHelpers::Jump mainPathJump = jit.jump();
</span><span class="cx">         
</span><span class="cx">         linkBuffer = std::make_unique&lt;LinkBuffer&gt;(vm, jit, codeBlock, JITCompilationCanFail);
</span><span class="lines">@@ -191,7 +335,7 @@
</span><span class="cx">         }
</span><span class="cx">         linkBuffer-&gt;link(mainPathJump, CodeLocationLabel(bitwise_cast&lt;void*&gt;(state.generatedFunction)));
</span><span class="cx"> 
</span><del>-        state.jitCode-&gt;initializeAddressForCall(linkBuffer-&gt;locationOf(start));
</del><ins>+        state.jitCode-&gt;setEntryFor(RegisterArgsArityCheckNotRequired, linkBuffer-&gt;locationOf(start));
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -196,6 +196,10 @@
</span><span class="cx">         m_proc.addFastConstant(m_tagTypeNumber-&gt;key());
</span><span class="cx">         m_proc.addFastConstant(m_tagMask-&gt;key());
</span><span class="cx">         
</span><ins>+        // Store out callee and argument count for possible OSR exit.
+        m_out.store64(m_out.argumentRegister(argumentRegisterForCallee()), addressFor(CallFrameSlot::callee));
+        m_out.store32(m_out.argumentRegisterInt32(argumentRegisterForArgumentCount()), payloadFor(CallFrameSlot::argumentCount));
+
</ins><span class="cx">         m_out.storePtr(m_out.constIntPtr(codeBlock()), addressFor(CallFrameSlot::codeBlock));
</span><span class="cx"> 
</span><span class="cx">         // Stack Overflow Check.
</span><span class="lines">@@ -247,20 +251,34 @@
</span><span class="cx">         // Check Arguments.
</span><span class="cx">         availabilityMap().clear();
</span><span class="cx">         availabilityMap().m_locals = Operands&lt;Availability&gt;(codeBlock()-&gt;numParameters(), 0);
</span><ins>+
+        Vector&lt;Node*, 8&gt; argumentNodes;
+        Vector&lt;LValue, 8&gt; argumentValues;
+
+        argumentNodes.resize(codeBlock()-&gt;numParameters());
+        argumentValues.resize(codeBlock()-&gt;numParameters());
+
+        m_highBlock = m_graph.block(0);
+
</ins><span class="cx">         for (unsigned i = codeBlock()-&gt;numParameters(); i--;) {
</span><del>-            availabilityMap().m_locals.argument(i) =
-                Availability(FlushedAt(FlushedJSValue, virtualRegisterForArgument(i)));
-        }
-        m_node = nullptr;
-        m_origin = NodeOrigin(CodeOrigin(0), CodeOrigin(0), true);
-        for (unsigned i = codeBlock()-&gt;numParameters(); i--;) {
-            Node* node = m_graph.m_arguments[i];
</del><ins>+            Node* node = m_graph.m_argumentsForChecking[i];
</ins><span class="cx">             VirtualRegister operand = virtualRegisterForArgument(i);
</span><span class="cx">             
</span><del>-            LValue jsValue = m_out.load64(addressFor(operand));
</del><ins>+            LValue jsValue = nullptr;
+
+            if (node) {
+                if (i &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS) {
+                    availabilityMap().m_locals.argument(i) = Availability(node);
+                    jsValue = m_out.argumentRegister(GPRInfo::toArgumentRegister(node-&gt;argumentRegisterIndex()));
+
+                    setJSValue(node, jsValue);
+                } else {
+                    availabilityMap().m_locals.argument(i) =
+                        Availability(FlushedAt(FlushedJSValue, operand));
+                    jsValue = m_out.load64(addressFor(virtualRegisterForArgument(i)));
+                }
</ins><span class="cx">             
</span><del>-            if (node) {
-                DFG_ASSERT(m_graph, node, operand == node-&gt;stackAccessData()-&gt;machineLocal);
</del><ins>+                DFG_ASSERT(m_graph, node, node-&gt;hasArgumentRegisterIndex() || operand == node-&gt;stackAccessData()-&gt;machineLocal);
</ins><span class="cx">                 
</span><span class="cx">                 // This is a hack, but it's an effective one. It allows us to do CSE on the
</span><span class="cx">                 // primordial load of arguments. This assumes that the GetLocal that got put in
</span><span class="lines">@@ -268,7 +286,21 @@
</span><span class="cx">                 // should hold true.
</span><span class="cx">                 m_loadedArgumentValues.add(node, jsValue);
</span><span class="cx">             }
</span><ins>+
+            argumentNodes[i] = node;
+            argumentValues[i] = jsValue;
+        }
+
+        m_node = nullptr;
+        m_origin = NodeOrigin(CodeOrigin(0), CodeOrigin(0), true);
+        for (unsigned i = codeBlock()-&gt;numParameters(); i--;) {
+            Node* node = argumentNodes[i];
</ins><span class="cx">             
</span><ins>+            if (!node)
+                continue;
+
+            LValue jsValue = argumentValues[i];
+
</ins><span class="cx">             switch (m_graph.m_argumentFormats[i]) {
</span><span class="cx">             case FlushedInt32:
</span><span class="cx">                 speculate(BadType, jsValueValue(jsValue), node, isNotInt32(jsValue));
</span><span class="lines">@@ -813,6 +845,9 @@
</span><span class="cx">         case GetArgumentCountIncludingThis:
</span><span class="cx">             compileGetArgumentCountIncludingThis();
</span><span class="cx">             break;
</span><ins>+        case GetArgumentRegister:
+            compileGetArgumentRegister();
+            break;
</ins><span class="cx">         case GetScope:
</span><span class="cx">             compileGetScope();
</span><span class="cx">             break;
</span><span class="lines">@@ -5402,6 +5437,16 @@
</span><span class="cx">         setInt32(m_out.load32(payloadFor(CallFrameSlot::argumentCount)));
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void compileGetArgumentRegister()
+    {
+        // We might have already have a value for this node.
+        if (LValue value = m_loadedArgumentValues.get(m_node)) {
+            setJSValue(value);
+            return;
+        }
+        setJSValue(m_out.argumentRegister(GPRInfo::toArgumentRegister(m_node-&gt;argumentRegisterIndex())));
+    }
+    
</ins><span class="cx">     void compileGetScope()
</span><span class="cx">     {
</span><span class="cx">         setJSValue(m_out.loadPtr(lowCell(m_node-&gt;child1()), m_heaps.JSFunction_scope));
</span><span class="lines">@@ -5814,9 +5859,10 @@
</span><span class="cx">         // the call.
</span><span class="cx">         Vector&lt;ConstrainedValue&gt; arguments;
</span><span class="cx"> 
</span><del>-        // Make sure that the callee goes into GPR0 because that's where the slow path thunks expect the
-        // callee to be.
-        arguments.append(ConstrainedValue(jsCallee, ValueRep::reg(GPRInfo::regT0)));
</del><ins>+        // Make sure that the callee goes into argumentRegisterForCallee() because that's where
+        // the slow path thunks expect the callee to be.
+        GPRReg calleeReg = argumentRegisterForCallee();
+        arguments.append(ConstrainedValue(jsCallee, ValueRep::reg(calleeReg)));
</ins><span class="cx"> 
</span><span class="cx">         auto addArgument = [&amp;] (LValue value, VirtualRegister reg, int offset) {
</span><span class="cx">             intptr_t offsetFromSP =
</span><span class="lines">@@ -5824,11 +5870,17 @@
</span><span class="cx">             arguments.append(ConstrainedValue(value, ValueRep::stackArgument(offsetFromSP)));
</span><span class="cx">         };
</span><span class="cx"> 
</span><del>-        addArgument(jsCallee, VirtualRegister(CallFrameSlot::callee), 0);
-        addArgument(m_out.constInt32(numArgs), VirtualRegister(CallFrameSlot::argumentCount), PayloadOffset);
-        for (unsigned i = 0; i &lt; numArgs; ++i)
-            addArgument(lowJSValue(m_graph.varArgChild(node, 1 + i)), virtualRegisterForArgument(i), 0);
</del><ins>+        ArgumentsLocation argLocation = argumentsLocationFor(numArgs);
+        arguments.append(ConstrainedValue(jsCallee, ValueRep::reg(calleeReg)));
+        arguments.append(ConstrainedValue(m_out.constInt32(numArgs), ValueRep::reg(argumentRegisterForArgumentCount())));
</ins><span class="cx"> 
</span><ins>+        for (unsigned i = 0; i &lt; numArgs; ++i) {
+            if (i &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS)
+                arguments.append(ConstrainedValue(lowJSValue(m_graph.varArgChild(node, 1 + i)), ValueRep::reg(argumentRegisterForFunctionArgument(i))));
+            else
+                addArgument(lowJSValue(m_graph.varArgChild(node, 1 + i)), virtualRegisterForArgument(i), 0);
+        }
+
</ins><span class="cx">         PatchpointValue* patchpoint = m_out.patchpoint(Int64);
</span><span class="cx">         patchpoint-&gt;appendVector(arguments);
</span><span class="cx"> 
</span><span class="lines">@@ -5856,9 +5908,11 @@
</span><span class="cx"> 
</span><span class="cx">                 CallLinkInfo* callLinkInfo = jit.codeBlock()-&gt;addCallLinkInfo();
</span><span class="cx"> 
</span><ins>+                incrementCounter(&amp;jit, VM::FTLCaller);
+
</ins><span class="cx">                 CCallHelpers::DataLabelPtr targetToCheck;
</span><span class="cx">                 CCallHelpers::Jump slowPath = jit.branchPtrWithPatch(
</span><del>-                    CCallHelpers::NotEqual, GPRInfo::regT0, targetToCheck,
</del><ins>+                    CCallHelpers::NotEqual, calleeReg, targetToCheck,
</ins><span class="cx">                     CCallHelpers::TrustedImmPtr(0));
</span><span class="cx"> 
</span><span class="cx">                 CCallHelpers::Call fastCall = jit.nearCall();
</span><span class="lines">@@ -5866,13 +5920,13 @@
</span><span class="cx"> 
</span><span class="cx">                 slowPath.link(&amp;jit);
</span><span class="cx"> 
</span><del>-                jit.move(CCallHelpers::TrustedImmPtr(callLinkInfo), GPRInfo::regT2);
</del><ins>+                jit.move(CCallHelpers::TrustedImmPtr(callLinkInfo), GPRInfo::nonArgGPR0);
</ins><span class="cx">                 CCallHelpers::Call slowCall = jit.nearCall();
</span><span class="cx">                 done.link(&amp;jit);
</span><span class="cx"> 
</span><span class="cx">                 callLinkInfo-&gt;setUpCall(
</span><span class="cx">                     node-&gt;op() == Construct ? CallLinkInfo::Construct : CallLinkInfo::Call,
</span><del>-                    node-&gt;origin.semantic, GPRInfo::regT0);
</del><ins>+                    argLocation, node-&gt;origin.semantic, argumentRegisterForCallee());
</ins><span class="cx"> 
</span><span class="cx">                 jit.addPtr(
</span><span class="cx">                     CCallHelpers::TrustedImm32(-params.proc().frameSize()),
</span><span class="lines">@@ -5881,7 +5935,7 @@
</span><span class="cx">                 jit.addLinkTask(
</span><span class="cx">                     [=] (LinkBuffer&amp; linkBuffer) {
</span><span class="cx">                         MacroAssemblerCodePtr linkCall =
</span><del>-                            linkBuffer.vm().getCTIStub(linkCallThunkGenerator).code();
</del><ins>+                            linkBuffer.vm().getJITCallThunkEntryStub(linkCallThunkGenerator).entryFor(callLinkInfo-&gt;argumentsLocation());
</ins><span class="cx">                         linkBuffer.link(slowCall, FunctionPtr(linkCall.executableAddress()));
</span><span class="cx"> 
</span><span class="cx">                         callLinkInfo-&gt;setCallLocations(
</span><span class="lines">@@ -5925,7 +5979,10 @@
</span><span class="cx">         
</span><span class="cx">         Vector&lt;ConstrainedValue&gt; arguments;
</span><span class="cx">         
</span><del>-        arguments.append(ConstrainedValue(jsCallee, ValueRep::SomeRegister));
</del><ins>+        // Make sure that the callee goes into argumentRegisterForCallee() because that's where
+        // the slow path thunks expect the callee to be.
+        GPRReg calleeReg = argumentRegisterForCallee();
+        arguments.append(ConstrainedValue(jsCallee, ValueRep::reg(calleeReg)));
</ins><span class="cx">         if (!isTail) {
</span><span class="cx">             auto addArgument = [&amp;] (LValue value, VirtualRegister reg, int offset) {
</span><span class="cx">                 intptr_t offsetFromSP =
</span><span class="lines">@@ -5932,13 +5989,28 @@
</span><span class="cx">                     (reg.offset() - CallerFrameAndPC::sizeInRegisters) * sizeof(EncodedJSValue) + offset;
</span><span class="cx">                 arguments.append(ConstrainedValue(value, ValueRep::stackArgument(offsetFromSP)));
</span><span class="cx">             };
</span><del>-            
</del><ins>+
+            arguments.append(ConstrainedValue(jsCallee, ValueRep::reg(calleeReg)));
+#if ENABLE(CALLER_SPILLS_CALLEE)
</ins><span class="cx">             addArgument(jsCallee, VirtualRegister(CallFrameSlot::callee), 0);
</span><ins>+#endif
+            arguments.append(ConstrainedValue(m_out.constInt32(numPassedArgs), ValueRep::reg(argumentRegisterForArgumentCount())));
+#if ENABLE(CALLER_SPILLS_ARGCOUNT)
</ins><span class="cx">             addArgument(m_out.constInt32(numPassedArgs), VirtualRegister(CallFrameSlot::argumentCount), PayloadOffset);
</span><del>-            for (unsigned i = 0; i &lt; numPassedArgs; ++i)
-                addArgument(lowJSValue(m_graph.varArgChild(node, 1 + i)), virtualRegisterForArgument(i), 0);
-            for (unsigned i = numPassedArgs; i &lt; numAllocatedArgs; ++i)
-                addArgument(m_out.constInt64(JSValue::encode(jsUndefined())), virtualRegisterForArgument(i), 0);
</del><ins>+#endif
+            
+            for (unsigned i = 0; i &lt; numPassedArgs; ++i) {
+                if (i &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS)
+                    arguments.append(ConstrainedValue(lowJSValue(m_graph.varArgChild(node, 1 + i)), ValueRep::reg(argumentRegisterForFunctionArgument(i))));
+                else
+                    addArgument(lowJSValue(m_graph.varArgChild(node, 1 + i)), virtualRegisterForArgument(i), 0);
+            }
+            for (unsigned i = numPassedArgs; i &lt; numAllocatedArgs; ++i) {
+                if (i &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS)
+                    arguments.append(ConstrainedValue(m_out.constInt64(JSValue::encode(jsUndefined())), ValueRep::reg(argumentRegisterForFunctionArgument(i))));
+                else
+                    addArgument(m_out.constInt64(JSValue::encode(jsUndefined())), virtualRegisterForArgument(i), 0);
+            }
</ins><span class="cx">         } else {
</span><span class="cx">             for (unsigned i = 0; i &lt; numPassedArgs; ++i)
</span><span class="cx">                 arguments.append(ConstrainedValue(lowJSValue(m_graph.varArgChild(node, 1 + i)), ValueRep::WarmAny));
</span><span class="lines">@@ -5980,6 +6052,7 @@
</span><span class="cx">                     shuffleData.numLocals = state-&gt;jitCode-&gt;common.frameRegisterCount;
</span><span class="cx">                     
</span><span class="cx">                     RegisterSet toSave = params.unavailableRegisters();
</span><ins>+                    shuffleData.argumentsInRegisters = true;
</ins><span class="cx">                     shuffleData.callee = ValueRecovery::inGPR(calleeGPR, DataFormatCell);
</span><span class="cx">                     toSave.set(calleeGPR);
</span><span class="cx">                     for (unsigned i = 0; i &lt; numPassedArgs; ++i) {
</span><span class="lines">@@ -5998,7 +6071,11 @@
</span><span class="cx">                     
</span><span class="cx">                     CCallHelpers::PatchableJump patchableJump = jit.patchableJump();
</span><span class="cx">                     CCallHelpers::Label mainPath = jit.label();
</span><del>-                    
</del><ins>+
+                    incrementCounter(&amp;jit, VM::FTLCaller);
+                    incrementCounter(&amp;jit, VM::TailCall);
+                    incrementCounter(&amp;jit, VM::DirectCall);
+
</ins><span class="cx">                     jit.store32(
</span><span class="cx">                         CCallHelpers::TrustedImm32(callSiteIndex.bits()),
</span><span class="cx">                         CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount)));
</span><span class="lines">@@ -6019,7 +6096,7 @@
</span><span class="cx">                     jit.jump().linkTo(mainPath, &amp;jit);
</span><span class="cx">                     
</span><span class="cx">                     callLinkInfo-&gt;setUpCall(
</span><del>-                        CallLinkInfo::DirectTailCall, node-&gt;origin.semantic, InvalidGPRReg);
</del><ins>+                        CallLinkInfo::DirectTailCall, argumentsLocationFor(numPassedArgs), node-&gt;origin.semantic, InvalidGPRReg);
</ins><span class="cx">                     callLinkInfo-&gt;setExecutableDuringCompilation(executable);
</span><span class="cx">                     if (numAllocatedArgs &gt; numPassedArgs)
</span><span class="cx">                         callLinkInfo-&gt;setMaxNumArguments(numAllocatedArgs);
</span><span class="lines">@@ -6042,6 +6119,9 @@
</span><span class="cx">                 
</span><span class="cx">                 CCallHelpers::Label mainPath = jit.label();
</span><span class="cx"> 
</span><ins>+                incrementCounter(&amp;jit, VM::FTLCaller);
+                incrementCounter(&amp;jit, VM::DirectCall);
+
</ins><span class="cx">                 jit.store32(
</span><span class="cx">                     CCallHelpers::TrustedImm32(callSiteIndex.bits()),
</span><span class="cx">                     CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount)));
</span><span class="lines">@@ -6053,7 +6133,7 @@
</span><span class="cx">                 
</span><span class="cx">                 callLinkInfo-&gt;setUpCall(
</span><span class="cx">                     isConstruct ? CallLinkInfo::DirectConstruct : CallLinkInfo::DirectCall,
</span><del>-                    node-&gt;origin.semantic, InvalidGPRReg);
</del><ins>+                    argumentsLocationFor(numPassedArgs), node-&gt;origin.semantic, InvalidGPRReg);
</ins><span class="cx">                 callLinkInfo-&gt;setExecutableDuringCompilation(executable);
</span><span class="cx">                 if (numAllocatedArgs &gt; numPassedArgs)
</span><span class="cx">                     callLinkInfo-&gt;setMaxNumArguments(numAllocatedArgs);
</span><span class="lines">@@ -6064,13 +6144,11 @@
</span><span class="cx">                         
</span><span class="cx">                         CCallHelpers::Label slowPath = jit.label();
</span><span class="cx">                         if (isX86())
</span><del>-                            jit.pop(CCallHelpers::selectScratchGPR(calleeGPR));
-                        
-                        callOperation(
-                            *state, params.unavailableRegisters(), jit,
-                            node-&gt;origin.semantic, exceptions.get(), operationLinkDirectCall,
-                            InvalidGPRReg, CCallHelpers::TrustedImmPtr(callLinkInfo),
-                            calleeGPR).call();
</del><ins>+                            jit.pop(GPRInfo::nonArgGPR0);
+
+                        jit.move(CCallHelpers::TrustedImmPtr(callLinkInfo), GPRInfo::nonArgGPR0); // Link info needs to be in nonArgGPR0
+                        CCallHelpers::Call slowCall = jit.nearCall();
+                        exceptions-&gt;append(jit.emitExceptionCheck(AssemblyHelpers::NormalExceptionCheck, AssemblyHelpers::FarJumpWidth));
</ins><span class="cx">                         jit.jump().linkTo(mainPath, &amp;jit);
</span><span class="cx">                         
</span><span class="cx">                         jit.addLinkTask(
</span><span class="lines">@@ -6079,6 +6157,9 @@
</span><span class="cx">                                 CodeLocationLabel slowPathLocation = linkBuffer.locationOf(slowPath);
</span><span class="cx">                                 
</span><span class="cx">                                 linkBuffer.link(call, slowPathLocation);
</span><ins>+                                MacroAssemblerCodePtr linkCall =
+                                    linkBuffer.vm().getJITCallThunkEntryStub(linkDirectCallThunkGenerator).entryFor(callLinkInfo-&gt;argumentsLocation());
+                                linkBuffer.link(slowCall, FunctionPtr(linkCall.executableAddress()));
</ins><span class="cx">                                 
</span><span class="cx">                                 callLinkInfo-&gt;setCallLocations(
</span><span class="cx">                                     CodeLocationLabel(),
</span><span class="lines">@@ -6110,7 +6191,8 @@
</span><span class="cx"> 
</span><span class="cx">         Vector&lt;ConstrainedValue&gt; arguments;
</span><span class="cx"> 
</span><del>-        arguments.append(ConstrainedValue(jsCallee, ValueRep::reg(GPRInfo::regT0)));
</del><ins>+        GPRReg calleeReg = argumentRegisterForCallee();
+        arguments.append(ConstrainedValue(jsCallee, ValueRep::reg(calleeReg)));
</ins><span class="cx"> 
</span><span class="cx">         for (unsigned i = 0; i &lt; numArgs; ++i) {
</span><span class="cx">             // Note: we could let the shuffler do boxing for us, but it's not super clear that this
</span><span class="lines">@@ -6144,6 +6226,9 @@
</span><span class="cx">                 AllowMacroScratchRegisterUsage allowScratch(jit);
</span><span class="cx">                 CallSiteIndex callSiteIndex = state-&gt;jitCode-&gt;common.addUniqueCallSiteIndex(codeOrigin);
</span><span class="cx"> 
</span><ins>+                incrementCounter(&amp;jit, VM::FTLCaller);
+                incrementCounter(&amp;jit, VM::TailCall);
+
</ins><span class="cx">                 // Yes, this is really necessary. You could throw an exception in a host call on the
</span><span class="cx">                 // slow path. That'll route us to lookupExceptionHandler(), which unwinds starting
</span><span class="cx">                 // with the call site index of our frame. Bad things happen if it's not set.
</span><span class="lines">@@ -6152,8 +6237,9 @@
</span><span class="cx">                     CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount)));
</span><span class="cx"> 
</span><span class="cx">                 CallFrameShuffleData shuffleData;
</span><ins>+                shuffleData.argumentsInRegisters = true;
</ins><span class="cx">                 shuffleData.numLocals = state-&gt;jitCode-&gt;common.frameRegisterCount;
</span><del>-                shuffleData.callee = ValueRecovery::inGPR(GPRInfo::regT0, DataFormatJS);
</del><ins>+                shuffleData.callee = ValueRecovery::inGPR(calleeReg, DataFormatJS);
</ins><span class="cx"> 
</span><span class="cx">                 for (unsigned i = 0; i &lt; numArgs; ++i)
</span><span class="cx">                     shuffleData.args.append(params[1 + i].recoveryForJSValue());
</span><span class="lines">@@ -6164,7 +6250,7 @@
</span><span class="cx"> 
</span><span class="cx">                 CCallHelpers::DataLabelPtr targetToCheck;
</span><span class="cx">                 CCallHelpers::Jump slowPath = jit.branchPtrWithPatch(
</span><del>-                    CCallHelpers::NotEqual, GPRInfo::regT0, targetToCheck,
</del><ins>+                    CCallHelpers::NotEqual, calleeReg, targetToCheck,
</ins><span class="cx">                     CCallHelpers::TrustedImmPtr(0));
</span><span class="cx"> 
</span><span class="cx">                 callLinkInfo-&gt;setFrameShuffleData(shuffleData);
</span><span class="lines">@@ -6175,20 +6261,19 @@
</span><span class="cx">                 slowPath.link(&amp;jit);
</span><span class="cx"> 
</span><span class="cx">                 CallFrameShuffler slowPathShuffler(jit, shuffleData);
</span><del>-                slowPathShuffler.setCalleeJSValueRegs(JSValueRegs(GPRInfo::regT0));
</del><span class="cx">                 slowPathShuffler.prepareForSlowPath();
</span><span class="cx"> 
</span><del>-                jit.move(CCallHelpers::TrustedImmPtr(callLinkInfo), GPRInfo::regT2);
</del><ins>+                jit.move(CCallHelpers::TrustedImmPtr(callLinkInfo), GPRInfo::nonArgGPR0);
</ins><span class="cx">                 CCallHelpers::Call slowCall = jit.nearCall();
</span><span class="cx"> 
</span><span class="cx">                 jit.abortWithReason(JITDidReturnFromTailCall);
</span><span class="cx"> 
</span><del>-                callLinkInfo-&gt;setUpCall(CallLinkInfo::TailCall, codeOrigin, GPRInfo::regT0);
</del><ins>+                callLinkInfo-&gt;setUpCall(CallLinkInfo::TailCall, argumentsLocationFor(numArgs), codeOrigin, calleeReg);
</ins><span class="cx"> 
</span><span class="cx">                 jit.addLinkTask(
</span><span class="cx">                     [=] (LinkBuffer&amp; linkBuffer) {
</span><span class="cx">                         MacroAssemblerCodePtr linkCall =
</span><del>-                            linkBuffer.vm().getCTIStub(linkCallThunkGenerator).code();
</del><ins>+                            linkBuffer.vm().getJITCallThunkEntryStub(linkCallThunkGenerator).entryFor(callLinkInfo-&gt;argumentsLocation());
</ins><span class="cx">                         linkBuffer.link(slowCall, FunctionPtr(linkCall.executableAddress()));
</span><span class="cx"> 
</span><span class="cx">                         callLinkInfo-&gt;setCallLocations(
</span><span class="lines">@@ -6278,6 +6363,7 @@
</span><span class="cx">                     CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount)));
</span><span class="cx"> 
</span><span class="cx">                 CallLinkInfo* callLinkInfo = jit.codeBlock()-&gt;addCallLinkInfo();
</span><ins>+                ArgumentsLocation argumentsLocation = StackArgs;
</ins><span class="cx"> 
</span><span class="cx">                 RegisterSet usedRegisters = RegisterSet::allRegisters();
</span><span class="cx">                 usedRegisters.exclude(RegisterSet::volatileRegistersForJSCall());
</span><span class="lines">@@ -6427,7 +6513,7 @@
</span><span class="cx">                 if (isTailCall)
</span><span class="cx">                     jit.emitRestoreCalleeSaves();
</span><span class="cx">                 ASSERT(!usedRegisters.get(GPRInfo::regT2));
</span><del>-                jit.move(CCallHelpers::TrustedImmPtr(callLinkInfo), GPRInfo::regT2);
</del><ins>+                jit.move(CCallHelpers::TrustedImmPtr(callLinkInfo), GPRInfo::nonArgGPR0);
</ins><span class="cx">                 CCallHelpers::Call slowCall = jit.nearCall();
</span><span class="cx">                 
</span><span class="cx">                 if (isTailCall)
</span><span class="lines">@@ -6435,7 +6521,7 @@
</span><span class="cx">                 else
</span><span class="cx">                     done.link(&amp;jit);
</span><span class="cx">                 
</span><del>-                callLinkInfo-&gt;setUpCall(callType, node-&gt;origin.semantic, GPRInfo::regT0);
</del><ins>+                callLinkInfo-&gt;setUpCall(callType, argumentsLocation, node-&gt;origin.semantic, GPRInfo::regT0);
</ins><span class="cx"> 
</span><span class="cx">                 jit.addPtr(
</span><span class="cx">                     CCallHelpers::TrustedImm32(-originalStackHeight),
</span><span class="lines">@@ -6444,7 +6530,7 @@
</span><span class="cx">                 jit.addLinkTask(
</span><span class="cx">                     [=] (LinkBuffer&amp; linkBuffer) {
</span><span class="cx">                         MacroAssemblerCodePtr linkCall =
</span><del>-                            linkBuffer.vm().getCTIStub(linkCallThunkGenerator).code();
</del><ins>+                            linkBuffer.vm().getJITCallThunkEntryStub(linkCallThunkGenerator).entryFor(StackArgs);
</ins><span class="cx">                         linkBuffer.link(slowCall, FunctionPtr(linkCall.executableAddress()));
</span><span class="cx">                         
</span><span class="cx">                         callLinkInfo-&gt;setCallLocations(
</span><span class="lines">@@ -6545,11 +6631,15 @@
</span><span class="cx"> 
</span><span class="cx">                 exceptionHandle-&gt;scheduleExitCreationForUnwind(params, callSiteIndex);
</span><span class="cx"> 
</span><ins>+                incrementCounter(&amp;jit, VM::FTLCaller);
+                incrementCounter(&amp;jit, VM::CallVarargs);
+                
</ins><span class="cx">                 jit.store32(
</span><span class="cx">                     CCallHelpers::TrustedImm32(callSiteIndex.bits()),
</span><span class="cx">                     CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount)));
</span><span class="cx"> 
</span><span class="cx">                 CallLinkInfo* callLinkInfo = jit.codeBlock()-&gt;addCallLinkInfo();
</span><ins>+                ArgumentsLocation argumentsLocation = StackArgs;
</ins><span class="cx">                 CallVarargsData* data = node-&gt;callVarargsData();
</span><span class="cx"> 
</span><span class="cx">                 unsigned argIndex = 1;
</span><span class="lines">@@ -6710,7 +6800,7 @@
</span><span class="cx"> 
</span><span class="cx">                 if (isTailCall)
</span><span class="cx">                     jit.emitRestoreCalleeSaves();
</span><del>-                jit.move(CCallHelpers::TrustedImmPtr(callLinkInfo), GPRInfo::regT2);
</del><ins>+                jit.move(CCallHelpers::TrustedImmPtr(callLinkInfo), GPRInfo::nonArgGPR0);
</ins><span class="cx">                 CCallHelpers::Call slowCall = jit.nearCall();
</span><span class="cx">                 
</span><span class="cx">                 if (isTailCall)
</span><span class="lines">@@ -6718,7 +6808,7 @@
</span><span class="cx">                 else
</span><span class="cx">                     done.link(&amp;jit);
</span><span class="cx">                 
</span><del>-                callLinkInfo-&gt;setUpCall(callType, node-&gt;origin.semantic, GPRInfo::regT0);
</del><ins>+                callLinkInfo-&gt;setUpCall(callType, argumentsLocation, node-&gt;origin.semantic, GPRInfo::regT0);
</ins><span class="cx">                 
</span><span class="cx">                 jit.addPtr(
</span><span class="cx">                     CCallHelpers::TrustedImm32(-originalStackHeight),
</span><span class="lines">@@ -6727,7 +6817,7 @@
</span><span class="cx">                 jit.addLinkTask(
</span><span class="cx">                     [=] (LinkBuffer&amp; linkBuffer) {
</span><span class="cx">                         MacroAssemblerCodePtr linkCall =
</span><del>-                            linkBuffer.vm().getCTIStub(linkCallThunkGenerator).code();
</del><ins>+                            linkBuffer.vm().getJITCallThunkEntryStub(linkCallThunkGenerator).entryFor(StackArgs);
</ins><span class="cx">                         linkBuffer.link(slowCall, FunctionPtr(linkCall.executableAddress()));
</span><span class="cx">                         
</span><span class="cx">                         callLinkInfo-&gt;setCallLocations(
</span><span class="lines">@@ -6796,13 +6886,16 @@
</span><span class="cx">                 Box&lt;CCallHelpers::JumpList&gt; exceptions = exceptionHandle-&gt;scheduleExitCreation(params)-&gt;jumps(jit);
</span><span class="cx">                 
</span><span class="cx">                 exceptionHandle-&gt;scheduleExitCreationForUnwind(params, callSiteIndex);
</span><del>-                
</del><ins>+
+                incrementCounter(&amp;jit, VM::FTLCaller);
+                incrementCounter(&amp;jit, VM::CallEval);
+
</ins><span class="cx">                 jit.store32(
</span><span class="cx">                     CCallHelpers::TrustedImm32(callSiteIndex.bits()),
</span><span class="cx">                     CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount)));
</span><span class="cx">                 
</span><span class="cx">                 CallLinkInfo* callLinkInfo = jit.codeBlock()-&gt;addCallLinkInfo();
</span><del>-                callLinkInfo-&gt;setUpCall(CallLinkInfo::Call, node-&gt;origin.semantic, GPRInfo::regT0);
</del><ins>+                callLinkInfo-&gt;setUpCall(CallLinkInfo::Call, StackArgs, node-&gt;origin.semantic, GPRInfo::regT0);
</ins><span class="cx">                 
</span><span class="cx">                 jit.addPtr(CCallHelpers::TrustedImm32(-static_cast&lt;ptrdiff_t&gt;(sizeof(CallerFrameAndPC))), CCallHelpers::stackPointerRegister, GPRInfo::regT1);
</span><span class="cx">                 jit.storePtr(GPRInfo::callFrameRegister, CCallHelpers::Address(GPRInfo::regT1, CallFrame::callerFrameOffset()));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOSREntrycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOSREntry.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOSREntry.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/ftl/FTLOSREntry.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -71,7 +71,11 @@
</span><span class="cx">     if (Options::verboseOSR())
</span><span class="cx">         dataLog(&quot;    Values at entry: &quot;, values, &quot;\n&quot;);
</span><span class="cx">     
</span><del>-    for (int argument = values.numberOfArguments(); argument--;) {
</del><ins>+    for (unsigned argument = values.numberOfArguments(); argument--;) {
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+        if (argument &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS)
+            break;
+#endif
</ins><span class="cx">         JSValue valueOnStack = exec-&gt;r(virtualRegisterForArgument(argument).offset()).asanUnsafeJSValue();
</span><span class="cx">         JSValue reconstructedValue = values.argument(argument);
</span><span class="cx">         if (valueOnStack == reconstructedValue || !argument)
</span><span class="lines">@@ -99,8 +103,12 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     exec-&gt;setCodeBlock(entryCodeBlock);
</span><del>-    
-    void* result = entryCode-&gt;addressForCall(ArityCheckNotRequired).executableAddress();
</del><ins>+
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    void* result = entryCode-&gt;addressForCall(RegisterArgsArityCheckNotRequired).executableAddress();
+#else
+    void* result = entryCode-&gt;addressForCall(StackArgsArityCheckNotRequired).executableAddress();
+#endif
</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="trunkSourceJavaScriptCoreftlFTLOutputcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOutput.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOutput.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/ftl/FTLOutput.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -89,6 +89,16 @@
</span><span class="cx">     m_block = block;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+LValue Output::argumentRegister(Reg reg)
+{
+    return m_block-&gt;appendNew&lt;ArgumentRegValue&gt;(m_proc, origin(), reg);
+}
+
+LValue Output::argumentRegisterInt32(Reg reg)
+{
+    return m_block-&gt;appendNew&lt;ArgumentRegValue&gt;(m_proc, origin(), reg, Int32);
+}
+
</ins><span class="cx"> LValue Output::framePointer()
</span><span class="cx"> {
</span><span class="cx">     return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::FramePointer, origin());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOutputh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOutput.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOutput.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/ftl/FTLOutput.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -98,6 +98,8 @@
</span><span class="cx">     void setOrigin(DFG::Node* node) { m_origin = node; }
</span><span class="cx">     B3::Origin origin() { return B3::Origin(m_origin); }
</span><span class="cx"> 
</span><ins>+    LValue argumentRegister(Reg reg);
+    LValue argumentRegisterInt32(Reg reg);
</ins><span class="cx">     LValue framePointer();
</span><span class="cx"> 
</span><span class="cx">     B3::SlotBaseValue* lockedStackSlot(size_t bytes);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterShadowChickencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/ShadowChicken.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/ShadowChicken.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/interpreter/ShadowChicken.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -297,16 +297,24 @@
</span><span class="cx">             bool foundFrame = advanceIndexInLogTo(callFrame, callFrame-&gt;jsCallee(), callFrame-&gt;callerFrame());
</span><span class="cx">             bool isTailDeleted = false;
</span><span class="cx">             JSScope* scope = nullptr;
</span><ins>+            JSValue thisValue = jsUndefined();
</ins><span class="cx">             CodeBlock* codeBlock = callFrame-&gt;codeBlock();
</span><del>-            if (codeBlock &amp;&amp; codeBlock-&gt;wasCompiledWithDebuggingOpcodes() &amp;&amp; codeBlock-&gt;scopeRegister().isValid()) {
-                scope = callFrame-&gt;scope(codeBlock-&gt;scopeRegister().offset());
-                RELEASE_ASSERT(scope-&gt;inherits(JSScope::info()));
</del><ins>+            if (codeBlock &amp;&amp; codeBlock-&gt;wasCompiledWithDebuggingOpcodes()) {
+                if (codeBlock-&gt;scopeRegister().isValid()) {
+                    scope = callFrame-&gt;scope(codeBlock-&gt;scopeRegister().offset());
+                    RELEASE_ASSERT(scope-&gt;inherits(JSScope::info()));
+                }
+                thisValue = callFrame-&gt;thisValue();
</ins><span class="cx">             } else if (foundFrame) {
</span><del>-                scope = m_log[indexInLog].scope;
-                if (scope)
-                    RELEASE_ASSERT(scope-&gt;inherits(JSScope::info()));
</del><ins>+                if (!scope) {
+                    scope = m_log[indexInLog].scope;
+                    if (scope)
+                        RELEASE_ASSERT(scope-&gt;inherits(JSScope::info()));
+                }
+                if (thisValue.isUndefined())
+                    thisValue = m_log[indexInLog].thisValue;
</ins><span class="cx">             }
</span><del>-            toPush.append(Frame(jsCast&lt;JSObject*&gt;(visitor-&gt;callee()), callFrame, isTailDeleted, callFrame-&gt;thisValue(), scope, codeBlock, callFrame-&gt;callSiteIndex()));
</del><ins>+            toPush.append(Frame(jsCast&lt;JSObject*&gt;(visitor-&gt;callee()), callFrame, isTailDeleted, thisValue, scope, codeBlock, callFrame-&gt;callSiteIndex()));
</ins><span class="cx"> 
</span><span class="cx">             if (indexInLog &lt; logCursorIndex
</span><span class="cx">                 // This condition protects us from the case where advanceIndexInLogTo didn't find
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelperscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -616,13 +616,13 @@
</span><span class="cx"> 
</span><span class="cx"> void AssemblyHelpers::emitDumbVirtualCall(CallLinkInfo* info)
</span><span class="cx"> {
</span><del>-    move(TrustedImmPtr(info), GPRInfo::regT2);
</del><ins>+    move(TrustedImmPtr(info), GPRInfo::nonArgGPR0);
</ins><span class="cx">     Call call = nearCall();
</span><span class="cx">     addLinkTask(
</span><span class="cx">         [=] (LinkBuffer&amp; linkBuffer) {
</span><del>-            MacroAssemblerCodeRef virtualThunk = virtualThunkFor(&amp;linkBuffer.vm(), *info);
-            info-&gt;setSlowStub(createJITStubRoutine(virtualThunk, linkBuffer.vm(), nullptr, true));
-            linkBuffer.link(call, CodeLocationLabel(virtualThunk.code()));
</del><ins>+            JITJSCallThunkEntryPointsWithRef virtualThunk = virtualThunkFor(&amp;linkBuffer.vm(), *info);
+            info-&gt;setSlowStub(createJITStubRoutine(virtualThunk.codeRef(), linkBuffer.vm(), nullptr, true));
+            linkBuffer.link(call, CodeLocationLabel(virtualThunk.entryFor(StackArgs)));
</ins><span class="cx">         });
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -414,6 +414,89 @@
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    enum SpillRegisterType { SpillAll, SpillExactly };
+
+    void spillArgumentRegistersToFrameBeforePrologue(unsigned minimumArgsToSpill = 0, SpillRegisterType spillType = SpillAll)
+    {
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+        JumpList doneStoringArgs;
+
+        emitPutToCallFrameHeaderBeforePrologue(argumentRegisterForCallee(), CallFrameSlot::callee);
+        GPRReg argCountReg = argumentRegisterForArgumentCount();
+        emitPutToCallFrameHeaderBeforePrologue(argCountReg, CallFrameSlot::argumentCount);
+
+        unsigned argIndex = 0;
+        // Always spill &quot;this&quot;
+        minimumArgsToSpill = std::max(minimumArgsToSpill, 1U);
+
+        for (; argIndex &lt; minimumArgsToSpill &amp;&amp; argIndex &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argIndex++)
+            emitPutArgumentToCallFrameBeforePrologue(argumentRegisterForFunctionArgument(argIndex), argIndex);
+
+        if (spillType == SpillAll) {
+            // Spill extra args passed to function
+            for (; argIndex &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argIndex++) {
+                doneStoringArgs.append(branch32(MacroAssembler::BelowOrEqual, argCountReg, MacroAssembler::TrustedImm32(argIndex)));
+                emitPutArgumentToCallFrameBeforePrologue(argumentRegisterForFunctionArgument(argIndex), argIndex);
+            }
+        }
+
+        doneStoringArgs.link(this);
+#else
+        UNUSED_PARAM(minimumArgsToSpill);
+        UNUSED_PARAM(spillType);
+#endif
+    }
+
+    void spillArgumentRegistersToFrame(unsigned minimumArgsToSpill = 0, SpillRegisterType spillType = SpillAll)
+    {
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+        JumpList doneStoringArgs;
+
+        emitPutToCallFrameHeader(argumentRegisterForCallee(), CallFrameSlot::callee);
+        GPRReg argCountReg = argumentRegisterForArgumentCount();
+        emitPutToCallFrameHeader(argCountReg, CallFrameSlot::argumentCount);
+        
+        unsigned argIndex = 0;
+        // Always spill &quot;this&quot;
+        minimumArgsToSpill = std::max(minimumArgsToSpill, 1U);
+        
+        for (; argIndex &lt; minimumArgsToSpill &amp;&amp; argIndex &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argIndex++)
+            emitPutArgumentToCallFrame(argumentRegisterForFunctionArgument(argIndex), argIndex);
+        
+        if (spillType == SpillAll) {
+            // Spill extra args passed to function
+            for (; argIndex &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argIndex++) {
+                doneStoringArgs.append(branch32(MacroAssembler::BelowOrEqual, argCountReg, MacroAssembler::TrustedImm32(argIndex)));
+                emitPutArgumentToCallFrame(argumentRegisterForFunctionArgument(argIndex), argIndex);
+            }
+        }
+        
+        doneStoringArgs.link(this);
+#else
+        UNUSED_PARAM(minimumArgsToSpill);
+        UNUSED_PARAM(spillType);
+#endif
+    }
+    
+    void fillArgumentRegistersFromFrameBeforePrologue()
+    {
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+        JumpList doneLoadingArgs;
+
+        emitGetFromCallFrameHeaderBeforePrologue(CallFrameSlot::callee, argumentRegisterForCallee());
+        GPRReg argCountReg = argumentRegisterForArgumentCount();
+        emitGetPayloadFromCallFrameHeaderBeforePrologue(CallFrameSlot::argumentCount, argCountReg);
+        
+        for (unsigned argIndex = 0; argIndex &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argIndex++) {
+            if (argIndex) // Always load &quot;this&quot;
+                doneLoadingArgs.append(branch32(MacroAssembler::BelowOrEqual, argCountReg, MacroAssembler::TrustedImm32(argIndex)));
+            emitGetFromCallFrameArgumentBeforePrologue(argIndex, argumentRegisterForFunctionArgument(argIndex));
+        }
+        
+        doneLoadingArgs.link(this);
+#endif
+    }
+
</ins><span class="cx"> #if CPU(X86_64) || CPU(X86)
</span><span class="cx">     static size_t prologueStackPointerDelta()
</span><span class="cx">     {
</span><span class="lines">@@ -624,6 +707,31 @@
</span><span class="cx">     {
</span><span class="cx">         storePtr(from, Address(stackPointerRegister, entry * static_cast&lt;ptrdiff_t&gt;(sizeof(Register)) - prologueStackPointerDelta()));
</span><span class="cx">     }
</span><ins>+
+    void emitPutArgumentToCallFrameBeforePrologue(GPRReg from, unsigned argument)
+    {
+        storePtr(from, Address(stackPointerRegister, (CallFrameSlot::thisArgument + argument) * static_cast&lt;ptrdiff_t&gt;(sizeof(Register)) - prologueStackPointerDelta()));
+    }
+
+    void emitPutArgumentToCallFrame(GPRReg from, unsigned argument)
+    {
+        emitPutToCallFrameHeader(from, CallFrameSlot::thisArgument + argument);
+    }
+
+    void emitGetFromCallFrameHeaderBeforePrologue(const int entry, GPRReg to)
+    {
+        loadPtr(Address(stackPointerRegister, entry * static_cast&lt;ptrdiff_t&gt;(sizeof(Register)) - prologueStackPointerDelta()), to);
+    }
+    
+    void emitGetFromCallFrameArgumentBeforePrologue(unsigned argument, GPRReg to)
+    {
+        loadPtr(Address(stackPointerRegister, (CallFrameSlot::thisArgument + argument) * static_cast&lt;ptrdiff_t&gt;(sizeof(Register)) - prologueStackPointerDelta()), to);
+    }
+    
+    void emitGetPayloadFromCallFrameHeaderBeforePrologue(const int entry, GPRReg to)
+    {
+        load32(Address(stackPointerRegister, entry * static_cast&lt;ptrdiff_t&gt;(sizeof(Register)) - prologueStackPointerDelta() + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), to);
+    }
</ins><span class="cx"> #else
</span><span class="cx">     void emitPutPayloadToCallFrameHeaderBeforePrologue(GPRReg from, int entry)
</span><span class="cx">     {
</span><span class="lines">@@ -1660,7 +1768,14 @@
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">     void wangsInt64Hash(GPRReg inputAndResult, GPRReg scratch);
</span><span class="cx"> #endif
</span><del>-    
</del><ins>+
+#if ENABLE(VM_COUNTERS)
+    void incrementCounter(VM::VMCounterType counterType)
+    {
+        addPtr(TrustedImm32(1), AbsoluteAddress(vm()-&gt;addressOfCounter(counterType)));
+    }
+#endif
+
</ins><span class="cx"> protected:
</span><span class="cx">     VM* m_vm;
</span><span class="cx">     CodeBlock* m_codeBlock;
</span><span class="lines">@@ -1669,6 +1784,12 @@
</span><span class="cx">     HashMap&lt;CodeBlock*, Vector&lt;BytecodeAndMachineOffset&gt;&gt; m_decodedCodeMaps;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+#if ENABLE(VM_COUNTERS)
+#define incrementCounter(jit, counterType) (jit)-&gt;incrementCounter(counterType)
+#else
+#define incrementCounter(jit, counterType) ((void)0)
+#endif
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitCachedRecoverycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/CachedRecovery.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CachedRecovery.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/CachedRecovery.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -30,6 +30,26 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+void CachedRecovery::addTargetJSValueRegs(JSValueRegs jsValueRegs)
+{
+    ASSERT(m_wantedFPR == InvalidFPRReg);
+    size_t existing = m_gprTargets.find(jsValueRegs);
+    if (existing == WTF::notFound) {
+#if USE(JSVALUE64)
+        if (m_gprTargets.size() &gt; 0 &amp;&amp; m_recovery.isSet() &amp;&amp; m_recovery.isInGPR()) {
+            // If we are recovering to the same GPR, make that GPR the first target.
+            GPRReg sourceGPR = m_recovery.gpr();
+            if (jsValueRegs.gpr() == sourceGPR) {
+                // Append the current first GPR below.
+                jsValueRegs = JSValueRegs(m_gprTargets[0].gpr());
+                m_gprTargets[0] = JSValueRegs(sourceGPR);
+            }
+        }
+#endif
+        m_gprTargets.append(jsValueRegs);
+    }
+}
+
</ins><span class="cx"> // We prefer loading doubles and undetermined JSValues into FPRs
</span><span class="cx"> // because it would otherwise use up GPRs.  Two in JSVALUE32_64.
</span><span class="cx"> bool CachedRecovery::loadsIntoFPR() const
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitCachedRecoveryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/CachedRecovery.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CachedRecovery.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/CachedRecovery.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -50,6 +50,7 @@
</span><span class="cx">     CachedRecovery&amp; operator=(CachedRecovery&amp;&amp;) = delete;
</span><span class="cx"> 
</span><span class="cx">     const Vector&lt;VirtualRegister, 1&gt;&amp; targets() const { return m_targets; }
</span><ins>+    const Vector&lt;JSValueRegs, 1&gt;&amp; gprTargets() const { return m_gprTargets; }
</ins><span class="cx"> 
</span><span class="cx">     void addTarget(VirtualRegister reg)
</span><span class="cx">     {
</span><span class="lines">@@ -68,15 +69,11 @@
</span><span class="cx">         m_targets.clear();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void setWantedJSValueRegs(JSValueRegs jsValueRegs)
-    {
-        ASSERT(m_wantedFPR == InvalidFPRReg);
-        m_wantedJSValueRegs = jsValueRegs;
-    }
</del><ins>+    void addTargetJSValueRegs(JSValueRegs);
</ins><span class="cx"> 
</span><span class="cx">     void setWantedFPR(FPRReg fpr)
</span><span class="cx">     {
</span><del>-        ASSERT(!m_wantedJSValueRegs);
</del><ins>+        ASSERT(m_gprTargets.isEmpty());
</ins><span class="cx">         m_wantedFPR = fpr;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -119,14 +116,20 @@
</span><span class="cx"> 
</span><span class="cx">     void setRecovery(ValueRecovery recovery) { m_recovery = recovery; }
</span><span class="cx"> 
</span><del>-    JSValueRegs wantedJSValueRegs() const { return m_wantedJSValueRegs; }
</del><ins>+    JSValueRegs wantedJSValueRegs() const
+    {
+        if (m_gprTargets.isEmpty())
+            return JSValueRegs();
</ins><span class="cx"> 
</span><ins>+        return m_gprTargets[0];
+    }
+
</ins><span class="cx">     FPRReg wantedFPR() const { return m_wantedFPR; }
</span><span class="cx"> private:
</span><span class="cx">     ValueRecovery m_recovery;
</span><del>-    JSValueRegs m_wantedJSValueRegs;
</del><span class="cx">     FPRReg m_wantedFPR { InvalidFPRReg };
</span><span class="cx">     Vector&lt;VirtualRegister, 1&gt; m_targets;
</span><ins>+    Vector&lt;JSValueRegs, 1&gt; m_gprTargets;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitCallFrameShuffleDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/CallFrameShuffleData.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CallFrameShuffleData.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/CallFrameShuffleData.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx">     ValueRecovery callee;
</span><span class="cx">     Vector&lt;ValueRecovery&gt; args;
</span><span class="cx"> #if USE(JSVALUE64)
</span><ins>+    bool argumentsInRegisters { false };
</ins><span class="cx">     RegisterMap&lt;ValueRecovery&gt; registers;
</span><span class="cx">     GPRReg tagTypeNumber { InvalidGPRReg };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitCallFrameShufflercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/CallFrameShuffler.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CallFrameShuffler.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/CallFrameShuffler.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -42,6 +42,9 @@
</span><span class="cx">         + roundArgumentCountToAlignFrame(jit.codeBlock()-&gt;numParameters()))
</span><span class="cx">     , m_alignedNewFrameSize(CallFrame::headerSizeInRegisters
</span><span class="cx">         + roundArgumentCountToAlignFrame(data.args.size()))
</span><ins>+#if USE(JSVALUE64)
+    , m_argumentsInRegisters(data.argumentsInRegisters)
+#endif
</ins><span class="cx">     , m_frameDelta(m_alignedNewFrameSize - m_alignedOldFrameSize)
</span><span class="cx">     , m_lockedRegisters(RegisterSet::allRegisters())
</span><span class="cx"> {
</span><span class="lines">@@ -54,11 +57,21 @@
</span><span class="cx">     m_lockedRegisters.exclude(RegisterSet::vmCalleeSaveRegisters());
</span><span class="cx"> 
</span><span class="cx">     ASSERT(!data.callee.isInJSStack() || data.callee.virtualRegister().isLocal());
</span><del>-    addNew(VirtualRegister(CallFrameSlot::callee), data.callee);
-
</del><ins>+#if USE(JSVALUE64)
+    if (data.argumentsInRegisters)
+        addNew(JSValueRegs(argumentRegisterForCallee()), data.callee);
+    else
+#endif
+        addNew(VirtualRegister(CallFrameSlot::callee), data.callee);
+    
</ins><span class="cx">     for (size_t i = 0; i &lt; data.args.size(); ++i) {
</span><span class="cx">         ASSERT(!data.args[i].isInJSStack() || data.args[i].virtualRegister().isLocal());
</span><del>-        addNew(virtualRegisterForArgument(i), data.args[i]);
</del><ins>+#if USE(JSVALUE64)
+        if (data.argumentsInRegisters &amp;&amp; i &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS)
+            addNew(JSValueRegs(argumentRegisterForFunctionArgument(i)), data.args[i]);
+        else
+#endif
+            addNew(virtualRegisterForArgument(i), data.args[i]);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="lines">@@ -185,8 +198,13 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> #else
</span><del>-        if (newCachedRecovery)
</del><ins>+        if (newCachedRecovery) {
</ins><span class="cx">             out.print(&quot;         &quot;, reg, &quot; &lt;- &quot;, newCachedRecovery-&gt;recovery());
</span><ins>+            if (newCachedRecovery-&gt;gprTargets().size() &gt; 1) {
+                for (size_t i = 1; i &lt; newCachedRecovery-&gt;gprTargets().size(); i++)
+                    out.print(&quot;, &quot;, newCachedRecovery-&gt;gprTargets()[i].gpr(), &quot; &lt;- &quot;, newCachedRecovery-&gt;recovery());
+            }
+        }
</ins><span class="cx"> #endif
</span><span class="cx">         out.print(&quot;\n&quot;);
</span><span class="cx">     }
</span><span class="lines">@@ -496,7 +514,7 @@
</span><span class="cx">     ASSERT(cachedRecovery.recovery().isInRegisters()
</span><span class="cx">         || cachedRecovery.recovery().isConstant());
</span><span class="cx"> 
</span><del>-    if (verbose)
</del><ins>+    if (verbose &amp;&amp; cachedRecovery.targets().size())
</ins><span class="cx">         dataLog(&quot;   * Storing &quot;, cachedRecovery.recovery());
</span><span class="cx">     for (size_t i = 0; i &lt; cachedRecovery.targets().size(); ++i) {
</span><span class="cx">         VirtualRegister target { cachedRecovery.targets()[i] };
</span><span class="lines">@@ -505,9 +523,9 @@
</span><span class="cx">             dataLog(!i ? &quot; into &quot; : &quot;, and &quot;, &quot;NEW &quot;, target);
</span><span class="cx">         emitStore(cachedRecovery, addressForNew(target));
</span><span class="cx">         setNew(target, nullptr);
</span><ins>+        if (verbose)
+            dataLog(&quot;\n&quot;);
</ins><span class="cx">     }
</span><del>-    if (verbose)
-        dataLog(&quot;\n&quot;);
</del><span class="cx">     cachedRecovery.clearTargets();
</span><span class="cx">     if (!cachedRecovery.wantedJSValueRegs() &amp;&amp; cachedRecovery.wantedFPR() == InvalidFPRReg)
</span><span class="cx">         clearCachedRecovery(cachedRecovery.recovery());
</span><span class="lines">@@ -606,7 +624,7 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!isUndecided());
</span><span class="cx"> 
</span><del>-    updateDangerFrontier();
</del><ins>+    initDangerFrontier();
</ins><span class="cx"> 
</span><span class="cx">     // First, we try to store any value that goes above the danger
</span><span class="cx">     // frontier. This will never use more registers since we are only
</span><span class="lines">@@ -702,13 +720,9 @@
</span><span class="cx">         ASSERT_UNUSED(writesOK, writesOK);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-#if USE(JSVALUE64)
-    if (m_tagTypeNumber != InvalidGPRReg &amp;&amp; m_newRegisters[m_tagTypeNumber])
-        releaseGPR(m_tagTypeNumber);
-#endif
-
</del><span class="cx">     // Handle 2) by loading all registers. We don't have to do any
</span><span class="cx">     // writes, since they have been taken care of above.
</span><ins>+    // Note that we need m_tagTypeNumber to remain locked to box wanted registers.
</ins><span class="cx">     if (verbose)
</span><span class="cx">         dataLog(&quot;  Loading wanted registers into registers\n&quot;);
</span><span class="cx">     for (Reg reg = Reg::first(); reg &lt;= Reg::last(); reg = reg.next()) {
</span><span class="lines">@@ -742,13 +756,22 @@
</span><span class="cx"> 
</span><span class="cx">     // We need to handle 4) first because it implies releasing
</span><span class="cx">     // m_newFrameBase, which could be a wanted register.
</span><ins>+    // Note that we delay setting the argument count register as it needs to be released in step 3.
</ins><span class="cx">     if (verbose)
</span><span class="cx">         dataLog(&quot;   * Storing the argument count into &quot;, VirtualRegister { CallFrameSlot::argumentCount }, &quot;\n&quot;);
</span><ins>+
</ins><span class="cx">     m_jit.store32(MacroAssembler::TrustedImm32(0),
</span><span class="cx">         addressForNew(VirtualRegister { CallFrameSlot::argumentCount }).withOffset(TagOffset));
</span><del>-    m_jit.store32(MacroAssembler::TrustedImm32(argCount()),
-        addressForNew(VirtualRegister { CallFrameSlot::argumentCount }).withOffset(PayloadOffset));
</del><span class="cx"> 
</span><ins>+#if USE(JSVALUE64)
+    if (!m_argumentsInRegisters) {
+#endif
+        m_jit.store32(MacroAssembler::TrustedImm32(argCount()),
+            addressForNew(VirtualRegister { CallFrameSlot::argumentCount }).withOffset(PayloadOffset));
+#if USE(JSVALUE64)
+    }
+#endif
+
</ins><span class="cx">     if (!isSlowPath()) {
</span><span class="cx">         ASSERT(m_newFrameBase != MacroAssembler::stackPointerRegister);
</span><span class="cx">         if (verbose)
</span><span class="lines">@@ -767,6 +790,23 @@
</span><span class="cx"> 
</span><span class="cx">         emitDisplace(*cachedRecovery);
</span><span class="cx">     }
</span><ins>+
+#if USE(JSVALUE64)
+    // For recoveries with multiple register targets, copy the contents of the first target to the
+    // remaining targets.
+    for (Reg reg = Reg::first(); reg &lt;= Reg::last(); reg = reg.next()) {
+        CachedRecovery* cachedRecovery { m_newRegisters[reg] };
+        if (!cachedRecovery || cachedRecovery-&gt;gprTargets().size() &lt; 2)
+            continue;
+
+        GPRReg sourceGPR = cachedRecovery-&gt;gprTargets()[0].gpr();
+        for (size_t i = 1; i &lt; cachedRecovery-&gt;gprTargets().size(); i++)
+            m_jit.move(sourceGPR, cachedRecovery-&gt;gprTargets()[i].gpr());
+    }
+
+    if (m_argumentsInRegisters)
+        m_jit.move(MacroAssembler::TrustedImm32(argCount()), argumentRegisterForArgumentCount());
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitCallFrameShufflerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/CallFrameShuffler.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CallFrameShuffler.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/CallFrameShuffler.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -96,17 +96,57 @@
</span><span class="cx">     // contains information about where the
</span><span class="cx">     // arguments/callee/callee-save registers are by taking into
</span><span class="cx">     // account any spilling that acquireGPR() could have done.
</span><del>-    CallFrameShuffleData snapshot() const
</del><ins>+    CallFrameShuffleData snapshot(ArgumentsLocation argumentsLocation) const
</ins><span class="cx">     {
</span><span class="cx">         ASSERT(isUndecided());
</span><span class="cx"> 
</span><span class="cx">         CallFrameShuffleData data;
</span><span class="cx">         data.numLocals = numLocals();
</span><del>-        data.callee = getNew(VirtualRegister { CallFrameSlot::callee })-&gt;recovery();
</del><ins>+#if USE(JSVALUE64)
+        data.argumentsInRegisters = argumentsLocation != StackArgs;
+#endif
+        if (argumentsLocation == StackArgs)
+            data.callee = getNew(VirtualRegister { CallFrameSlot::callee })-&gt;recovery();
+        else {
+            Reg reg { argumentRegisterForCallee() };
+            CachedRecovery* cachedRecovery { m_newRegisters[reg] };
+            data.callee = cachedRecovery-&gt;recovery();
+        }
</ins><span class="cx">         data.args.resize(argCount());
</span><del>-        for (size_t i = 0; i &lt; argCount(); ++i)
-            data.args[i] = getNew(virtualRegisterForArgument(i))-&gt;recovery();
</del><ins>+
+        Vector&lt;ValueRecovery&gt; registerArgRecoveries;
+#if USE(JSVALUE64)
+        // Find cached recoveries for all argument registers.
+        // We do this here, because a cached recovery may be the source for multiple
+        // argument registers, but it is only stored in one m_newRegister index.
+        if (data.argumentsInRegisters) {
+            unsigned maxArgumentRegister = std::min(static_cast&lt;unsigned&gt;(argCount()), NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS);
+            registerArgRecoveries.resize(maxArgumentRegister);
+            for (size_t i = 0; i &lt; maxArgumentRegister; ++i) {
+                Reg reg { argumentRegisterForFunctionArgument(i) };
+                CachedRecovery* cachedRecovery { m_newRegisters[reg] };
+                if (cachedRecovery) {
+                    for (auto jsValueReg : cachedRecovery-&gt;gprTargets())
+                        registerArgRecoveries[jsFunctionArgumentForArgumentRegister(jsValueReg.gpr())] = cachedRecovery-&gt;recovery();
+                }
+            }
+        }
+#endif
+        
+        for (size_t i = 0; i &lt; argCount(); ++i) {
+            if (argumentsLocation == StackArgs || i &gt;= NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS)
+                data.args[i] = getNew(virtualRegisterForArgument(i))-&gt;recovery();
+            else {
+                Reg reg { argumentRegisterForFunctionArgument(i) };
+                ASSERT(registerArgRecoveries[i]);
+                data.args[i] = registerArgRecoveries[i];
+            }
+        }
</ins><span class="cx">         for (Reg reg = Reg::first(); reg &lt;= Reg::last(); reg = reg.next()) {
</span><ins>+            if (reg.isGPR() &amp;&amp; argumentsLocation != StackArgs
+                &amp;&amp; GPRInfo::toArgumentIndex(reg.gpr()) &lt; argumentRegisterIndexForJSFunctionArgument(argCount()))
+                continue;
+
</ins><span class="cx">             CachedRecovery* cachedRecovery { m_newRegisters[reg] };
</span><span class="cx">             if (!cachedRecovery)
</span><span class="cx">                 continue;
</span><span class="lines">@@ -376,6 +416,9 @@
</span><span class="cx"> 
</span><span class="cx">     int m_alignedOldFrameSize;
</span><span class="cx">     int m_alignedNewFrameSize;
</span><ins>+#if USE(JSVALUE64)
+    bool m_argumentsInRegisters;
+#endif
</ins><span class="cx"> 
</span><span class="cx">     // This is the distance, in slots, between the base of the new
</span><span class="cx">     // frame and the base of the old frame. It could be negative when
</span><span class="lines">@@ -417,15 +460,22 @@
</span><span class="cx">     bool tryAcquireTagTypeNumber();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    // This stores, for each register, information about the recovery
-    // for the value that should eventually go into that register. The
-    // only registers that have a target recovery will be callee-save
-    // registers, as well as possibly one JSValueRegs for holding the
-    // callee.
</del><ins>+    // This stores information about the recovery for the value that
+    // should eventually go into that register. In some cases there
+    // are recoveries that have multiple targets. For those recoveries,
+    // only the first target register in the map has the recovery.
+    // We optimize the case where there are multiple targets for one
+    // recovery where one of those targets is also the source register.
+    // Restoring the first target becomes a nop and simplifies the logic
+    // of restoring the remaining targets.
</ins><span class="cx">     //
</span><span class="cx">     // Once the correct value has been put into the registers, and
</span><span class="cx">     // contrary to what we do with m_newFrame, we keep the entry in
</span><span class="cx">     // m_newRegisters to simplify spilling.
</span><ins>+    //
+    // If a recovery has multiple target registers, we copy the value
+    // from the first target register to the remaining target registers
+    // at the end of the shuffling process.
</ins><span class="cx">     RegisterMap&lt;CachedRecovery*&gt; m_newRegisters;
</span><span class="cx"> 
</span><span class="cx">     template&lt;typename CheckFunctor&gt;
</span><span class="lines">@@ -641,9 +691,13 @@
</span><span class="cx">         ASSERT(jsValueRegs &amp;&amp; !getNew(jsValueRegs));
</span><span class="cx">         CachedRecovery* cachedRecovery = addCachedRecovery(recovery);
</span><span class="cx"> #if USE(JSVALUE64)
</span><del>-        if (cachedRecovery-&gt;wantedJSValueRegs())
-            m_newRegisters[cachedRecovery-&gt;wantedJSValueRegs().gpr()] = nullptr;
-        m_newRegisters[jsValueRegs.gpr()] = cachedRecovery;
</del><ins>+        if (cachedRecovery-&gt;wantedJSValueRegs()) {
+            if (recovery.isInGPR() &amp;&amp; jsValueRegs.gpr() == recovery.gpr()) {
+                m_newRegisters[cachedRecovery-&gt;wantedJSValueRegs().gpr()] = nullptr;
+                m_newRegisters[jsValueRegs.gpr()] = cachedRecovery;
+            }
+        } else
+            m_newRegisters[jsValueRegs.gpr()] = cachedRecovery;
</ins><span class="cx"> #else
</span><span class="cx">         if (JSValueRegs oldRegs { cachedRecovery-&gt;wantedJSValueRegs() }) {
</span><span class="cx">             if (oldRegs.payloadGPR())
</span><span class="lines">@@ -656,8 +710,7 @@
</span><span class="cx">         if (jsValueRegs.tagGPR() != InvalidGPRReg)
</span><span class="cx">             m_newRegisters[jsValueRegs.tagGPR()] = cachedRecovery;
</span><span class="cx"> #endif
</span><del>-        ASSERT(!cachedRecovery-&gt;wantedJSValueRegs());
-        cachedRecovery-&gt;setWantedJSValueRegs(jsValueRegs);
</del><ins>+        cachedRecovery-&gt;addTargetJSValueRegs(jsValueRegs);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void addNew(FPRReg fpr, ValueRecovery recovery)
</span><span class="lines">@@ -755,13 +808,23 @@
</span><span class="cx">         return reg &lt;= dangerFrontier();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void initDangerFrontier()
+    {
+        findDangerFrontierFrom(lastNew());
+    }
+
</ins><span class="cx">     void updateDangerFrontier()
</span><span class="cx">     {
</span><ins>+        findDangerFrontierFrom(m_dangerFrontier - 1);
+    }
+
+    void findDangerFrontierFrom(VirtualRegister nextReg)
+    {
</ins><span class="cx">         ASSERT(!isUndecided());
</span><span class="cx"> 
</span><span class="cx">         m_dangerFrontier = firstNew() - 1;
</span><del>-        for (VirtualRegister reg = lastNew(); reg &gt;= firstNew(); reg -= 1) {
-            if (!getNew(reg) || !isValidOld(newAsOld(reg)) || !getOld(newAsOld(reg)))
</del><ins>+        for (VirtualRegister reg = nextReg; reg &gt;= firstNew(); reg -= 1) {
+            if (!isValidOld(newAsOld(reg)) || !getOld(newAsOld(reg)))
</ins><span class="cx">                 continue;
</span><span class="cx"> 
</span><span class="cx">             m_dangerFrontier = reg;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitCallFrameShuffler64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/CallFrameShuffler64.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CallFrameShuffler64.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/CallFrameShuffler64.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -323,7 +323,8 @@
</span><span class="cx">             m_jit.move(cachedRecovery.recovery().gpr(), wantedReg.gpr());
</span><span class="cx">         else
</span><span class="cx">             m_jit.move64ToDouble(cachedRecovery.recovery().gpr(), wantedReg.fpr());
</span><del>-        RELEASE_ASSERT(cachedRecovery.recovery().dataFormat() == DataFormatJS);
</del><ins>+        DataFormat format = cachedRecovery.recovery().dataFormat();
+        RELEASE_ASSERT(format == DataFormatJS || format == DataFormatCell);
</ins><span class="cx">         updateRecovery(cachedRecovery,
</span><span class="cx">             ValueRecovery::inRegister(wantedReg, DataFormatJS));
</span><span class="cx">     } else {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitGPRInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/GPRInfo.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/GPRInfo.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/GPRInfo.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -69,8 +69,8 @@
</span><span class="cx">     bool operator!() const { return m_gpr == InvalidGPRReg; }
</span><span class="cx">     explicit operator bool() const { return m_gpr != InvalidGPRReg; }
</span><span class="cx"> 
</span><del>-    bool operator==(JSValueRegs other) { return m_gpr == other.m_gpr; }
-    bool operator!=(JSValueRegs other) { return !(*this == other); }
</del><ins>+    bool operator==(JSValueRegs other) const { return m_gpr == other.m_gpr; }
+    bool operator!=(JSValueRegs other) const { return !(*this == other); }
</ins><span class="cx">     
</span><span class="cx">     GPRReg gpr() const { return m_gpr; }
</span><span class="cx">     GPRReg tagGPR() const { return InvalidGPRReg; }
</span><span class="lines">@@ -331,6 +331,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if CPU(X86)
</span><span class="cx"> #define NUMBER_OF_ARGUMENT_REGISTERS 0u
</span><ins>+#define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS 0u
</ins><span class="cx"> #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
</span><span class="cx"> 
</span><span class="cx"> class GPRInfo {
</span><span class="lines">@@ -353,6 +354,7 @@
</span><span class="cx">     static const GPRReg argumentGPR2 = X86Registers::eax; // regT0
</span><span class="cx">     static const GPRReg argumentGPR3 = X86Registers::ebx; // regT3
</span><span class="cx">     static const GPRReg nonArgGPR0 = X86Registers::esi; // regT4
</span><ins>+    static const GPRReg nonArgGPR1 = X86Registers::edi; // regT5
</ins><span class="cx">     static const GPRReg returnValueGPR = X86Registers::eax; // regT0
</span><span class="cx">     static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
</span><span class="cx">     static const GPRReg nonPreservedNonReturnGPR = X86Registers::ecx;
</span><span class="lines">@@ -379,6 +381,14 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static unsigned toArgumentIndex(GPRReg reg)
+    {
+        ASSERT(reg != InvalidGPRReg);
+        ASSERT(static_cast&lt;int&gt;(reg) &lt; 8);
+        static const unsigned indexForArgumentRegister[8] = { 2, 0, 1, 3, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
+        return indexForArgumentRegister[reg];
+    }
+
</ins><span class="cx">     static const char* debugName(GPRReg reg)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(reg != InvalidGPRReg);
</span><span class="lines">@@ -399,9 +409,11 @@
</span><span class="cx"> #if !OS(WINDOWS)
</span><span class="cx"> #define NUMBER_OF_ARGUMENT_REGISTERS 6u
</span><span class="cx"> #define NUMBER_OF_CALLEE_SAVES_REGISTERS 5u
</span><ins>+#define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS (NUMBER_OF_ARGUMENT_REGISTERS - 2u)
</ins><span class="cx"> #else
</span><span class="cx"> #define NUMBER_OF_ARGUMENT_REGISTERS 4u
</span><span class="cx"> #define NUMBER_OF_CALLEE_SAVES_REGISTERS 7u
</span><ins>+#define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS 0u
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> class GPRInfo {
</span><span class="lines">@@ -464,6 +476,7 @@
</span><span class="cx">     static const GPRReg argumentGPR3 = X86Registers::r9; // regT3
</span><span class="cx"> #endif
</span><span class="cx">     static const GPRReg nonArgGPR0 = X86Registers::r10; // regT5 (regT4 on Windows)
</span><ins>+    static const GPRReg nonArgGPR1 = X86Registers::eax; // regT0
</ins><span class="cx">     static const GPRReg returnValueGPR = X86Registers::eax; // regT0
</span><span class="cx">     static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1 or regT2
</span><span class="cx">     static const GPRReg nonPreservedNonReturnGPR = X86Registers::r10; // regT5 (regT4 on Windows)
</span><span class="lines">@@ -508,6 +521,18 @@
</span><span class="cx">         return indexForRegister[reg];
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static unsigned toArgumentIndex(GPRReg reg)
+    {
+        ASSERT(reg != InvalidGPRReg);
+        ASSERT(static_cast&lt;int&gt;(reg) &lt; 16);
+#if !OS(WINDOWS)
+        static const unsigned indexForArgumentRegister[16] = { InvalidIndex, 3, 2, InvalidIndex, InvalidIndex, InvalidIndex, 1, 0, 4, 5, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
+#else
+        static const unsigned indexForArgumentRegister[16] = { InvalidIndex, 0, 1, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, 2, 3, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
+#endif
+        return indexForArgumentRegister[reg];
+    }
+    
</ins><span class="cx">     static const char* debugName(GPRReg reg)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(reg != InvalidGPRReg);
</span><span class="lines">@@ -538,6 +563,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if CPU(ARM)
</span><span class="cx"> #define NUMBER_OF_ARGUMENT_REGISTERS 4u
</span><ins>+#define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS 0u
</ins><span class="cx"> #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
</span><span class="cx"> 
</span><span class="cx"> class GPRInfo {
</span><span class="lines">@@ -601,6 +627,15 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static unsigned toArgumentIndex(GPRReg reg)
+    {
+        ASSERT(reg != InvalidGPRReg);
+        ASSERT(static_cast&lt;int&gt;(reg) &lt; 16);
+        if (reg &gt; argumentGPR3)
+            return InvalidIndex;
+        return (unsigned)reg;
+    }
+    
</ins><span class="cx">     static const char* debugName(GPRReg reg)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(reg != InvalidGPRReg);
</span><span class="lines">@@ -621,6 +656,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if CPU(ARM64)
</span><span class="cx"> #define NUMBER_OF_ARGUMENT_REGISTERS 8u
</span><ins>+#define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS (NUMBER_OF_ARGUMENT_REGISTERS - 2u)
</ins><span class="cx"> // Callee Saves includes x19..x28 and FP registers q8..q15
</span><span class="cx"> #define NUMBER_OF_CALLEE_SAVES_REGISTERS 18u
</span><span class="cx"> 
</span><span class="lines">@@ -698,6 +734,7 @@
</span><span class="cx">     COMPILE_ASSERT(ARM64Registers::q13 == 13, q13_is_13);
</span><span class="cx">     COMPILE_ASSERT(ARM64Registers::q14 == 14, q14_is_14);
</span><span class="cx">     COMPILE_ASSERT(ARM64Registers::q15 == 15, q15_is_15);
</span><ins>+
</ins><span class="cx">     static GPRReg toRegister(unsigned index)
</span><span class="cx">     {
</span><span class="cx">         return (GPRReg)index;
</span><span class="lines">@@ -715,6 +752,14 @@
</span><span class="cx">         return toRegister(index);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static unsigned toArgumentIndex(GPRReg reg)
+    {
+        ASSERT(reg != InvalidGPRReg);
+        if (reg &gt; argumentGPR7)
+            return InvalidIndex;
+        return (unsigned)reg;
+    }
+
</ins><span class="cx">     static const char* debugName(GPRReg reg)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(reg != InvalidGPRReg);
</span><span class="lines">@@ -746,6 +791,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if CPU(MIPS)
</span><span class="cx"> #define NUMBER_OF_ARGUMENT_REGISTERS 4u
</span><ins>+#define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS 0u
</ins><span class="cx"> #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
</span><span class="cx"> 
</span><span class="cx"> class GPRInfo {
</span><span class="lines">@@ -773,6 +819,7 @@
</span><span class="cx">     static const GPRReg argumentGPR2 = MIPSRegisters::a2;
</span><span class="cx">     static const GPRReg argumentGPR3 = MIPSRegisters::a3;
</span><span class="cx">     static const GPRReg nonArgGPR0 = regT4;
</span><ins>+    static const GPRReg nonArgGPR1 = regT5;
</ins><span class="cx">     static const GPRReg returnValueGPR = regT0;
</span><span class="cx">     static const GPRReg returnValueGPR2 = regT1;
</span><span class="cx">     static const GPRReg nonPreservedNonReturnGPR = regT2;
</span><span class="lines">@@ -825,6 +872,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if CPU(SH4)
</span><span class="cx"> #define NUMBER_OF_ARGUMENT_REGISTERS 4u
</span><ins>+#define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS 0u
</ins><span class="cx"> #define NUMBER_OF_CALLEE_SAVES_REGISTERS 0u
</span><span class="cx"> 
</span><span class="cx"> class GPRInfo {
</span><span class="lines">@@ -855,6 +903,7 @@
</span><span class="cx">     static const GPRReg argumentGPR2 = SH4Registers::r6; // regT2
</span><span class="cx">     static const GPRReg argumentGPR3 = SH4Registers::r7; // regT3
</span><span class="cx">     static const GPRReg nonArgGPR0 = regT4;
</span><ins>+    static const GPRReg nonArgGPR1 = regT5;
</ins><span class="cx">     static const GPRReg returnValueGPR = regT0;
</span><span class="cx">     static const GPRReg returnValueGPR2 = regT1;
</span><span class="cx">     static const GPRReg nonPreservedNonReturnGPR = regT2;
</span><span class="lines">@@ -891,6 +940,73 @@
</span><span class="cx"> 
</span><span class="cx"> #endif // CPU(SH4)
</span><span class="cx"> 
</span><ins>+inline GPRReg argumentRegisterFor(unsigned argumentIndex)
+{
+#if NUMBER_OF_ARGUMENT_REGISTERS
+    if (argumentIndex &gt;= NUMBER_OF_ARGUMENT_REGISTERS)
+        return InvalidGPRReg;
+    return GPRInfo::toArgumentRegister(argumentIndex);
+#else
+    UNUSED_PARAM(argumentIndex);
+    RELEASE_ASSERT_NOT_REACHED();
+    return InvalidGPRReg;
+#endif
+}
+
+inline GPRReg argumentRegisterForCallee()
+{
+#if NUMBER_OF_ARGUMENT_REGISTERS
+    return argumentRegisterFor(0);
+#else
+    return GPRInfo::regT0;
+#endif
+}
+
+inline GPRReg argumentRegisterForArgumentCount()
+{
+    return argumentRegisterFor(1);
+}
+
+inline unsigned argumentRegisterIndexForJSFunctionArgument(unsigned argument)
+{
+    return argument + 2;
+}
+
+inline unsigned jsFunctionArgumentForArgumentRegisterIndex(unsigned index)
+{
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS &gt; 0
+    ASSERT(index &gt;= 2);
+    return index - 2;
+#else
+    UNUSED_PARAM(index);
+    RELEASE_ASSERT_NOT_REACHED();
+    return 0;
+#endif
+}
+
+inline unsigned jsFunctionArgumentForArgumentRegister(GPRReg gpr)
+{
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS &gt; 0
+    unsigned argumentRegisterIndex = GPRInfo::toArgumentIndex(gpr);
+    ASSERT(argumentRegisterIndex != GPRInfo::InvalidIndex);
+    return jsFunctionArgumentForArgumentRegisterIndex(argumentRegisterIndex);
+#else
+    UNUSED_PARAM(gpr);
+    RELEASE_ASSERT_NOT_REACHED();
+    return 0;
+#endif
+}
+
+inline GPRReg argumentRegisterForFunctionArgument(unsigned argumentIndex)
+{
+    return argumentRegisterFor(argumentRegisterIndexForJSFunctionArgument(argumentIndex));
+}
+
+inline unsigned numberOfRegisterArgumentsFor(unsigned argumentCount)
+{
+    return std::min(argumentCount, NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS);
+}
+
</ins><span class="cx"> // The baseline JIT uses &quot;accumulator&quot; style execution with regT0 (for 64-bit)
</span><span class="cx"> // and regT0 + regT1 (for 32-bit) serving as the accumulator register(s) for
</span><span class="cx"> // passing results of one opcode to the next. Hence:
</span><span class="lines">@@ -907,6 +1023,8 @@
</span><span class="cx"> #endif
</span><span class="cx"> inline NoResultTag extractResult(NoResultTag) { return NoResult; }
</span><span class="cx"> 
</span><ins>+#else // CLOOP
+#define NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS 0u
</ins><span class="cx"> #endif // ENABLE(JIT)
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -66,14 +66,6 @@
</span><span class="cx">         newCalleeFunction);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JIT::CodeRef JIT::compileCTINativeCall(VM* vm, NativeFunction func)
-{
-    if (!vm-&gt;canUseJIT())
-        return CodeRef::createLLIntCodeRef(llint_native_call_trampoline);
-    JIT jit(vm, 0);
-    return jit.privateCompileCTINativeCall(vm, func);
-}
-
</del><span class="cx"> JIT::JIT(VM* vm, CodeBlock* codeBlock)
</span><span class="cx">     : JSInterfaceJIT(vm, codeBlock)
</span><span class="cx">     , m_interpreter(vm-&gt;interpreter)
</span><span class="lines">@@ -579,6 +571,20 @@
</span><span class="cx">     if (m_randomGenerator.getUint32() &amp; 1)
</span><span class="cx">         nop();
</span><span class="cx"> 
</span><ins>+#if USE(JSVALUE64)
+    spillArgumentRegistersToFrameBeforePrologue(static_cast&lt;unsigned&gt;(m_codeBlock-&gt;numParameters()));
+    incrementCounter(this, VM::RegArgsNoArity);
+#if ENABLE(VM_COUNTERS)
+    Jump continueStackEntry = jump();
+#endif
+#endif
+    m_stackArgsArityOKEntry = label();
+    incrementCounter(this, VM::StackArgsNoArity);
+
+#if USE(JSVALUE64) &amp;&amp; ENABLE(VM_COUNTERS)
+    continueStackEntry.link(this);
+#endif
+
</ins><span class="cx">     emitFunctionPrologue();
</span><span class="cx">     emitPutToCallFrameHeader(m_codeBlock, CallFrameSlot::codeBlock);
</span><span class="cx"> 
</span><span class="lines">@@ -635,7 +641,21 @@
</span><span class="cx">     callOperationWithCallFrameRollbackOnException(operationThrowStackOverflowError, m_codeBlock);
</span><span class="cx"> 
</span><span class="cx">     if (m_codeBlock-&gt;codeType() == FunctionCode) {
</span><del>-        m_arityCheck = label();
</del><ins>+        m_registerArgsWithArityCheck = label();
+
+        incrementCounter(this, VM::RegArgsArity);
+
+        spillArgumentRegistersToFrameBeforePrologue();
+
+#if ENABLE(VM_COUNTERS)
+        Jump continueStackArityEntry = jump();
+#endif
+
+        m_stackArgsWithArityCheck = label();
+        incrementCounter(this, VM::StackArgsArity);
+#if ENABLE(VM_COUNTERS)
+        continueStackArityEntry.link(this);
+#endif
</ins><span class="cx">         store8(TrustedImm32(0), &amp;m_codeBlock-&gt;m_shouldAlwaysBeInlined);
</span><span class="cx">         emitFunctionPrologue();
</span><span class="cx">         emitPutToCallFrameHeader(m_codeBlock, CallFrameSlot::codeBlock);
</span><span class="lines">@@ -643,6 +663,8 @@
</span><span class="cx">         load32(payloadFor(CallFrameSlot::argumentCount), regT1);
</span><span class="cx">         branch32(AboveOrEqual, regT1, TrustedImm32(m_codeBlock-&gt;m_numParameters)).linkTo(beginLabel, this);
</span><span class="cx"> 
</span><ins>+        incrementCounter(this, VM::ArityFixupRequired);
+
</ins><span class="cx">         m_bytecodeOffset = 0;
</span><span class="cx"> 
</span><span class="cx">         if (maxFrameExtentForSlowPathCall)
</span><span class="lines">@@ -778,9 +800,14 @@
</span><span class="cx">     }
</span><span class="cx">     m_codeBlock-&gt;setJITCodeMap(jitCodeMapEncoder.finish());
</span><span class="cx"> 
</span><del>-    MacroAssemblerCodePtr withArityCheck;
-    if (m_codeBlock-&gt;codeType() == FunctionCode)
-        withArityCheck = patchBuffer.locationOf(m_arityCheck);
</del><ins>+    MacroAssemblerCodePtr stackEntryArityOKPtr = patchBuffer.locationOf(m_stackArgsArityOKEntry);
+    
+    MacroAssemblerCodePtr registerEntryWithArityCheckPtr;
+    MacroAssemblerCodePtr stackEntryWithArityCheckPtr;
+    if (m_codeBlock-&gt;codeType() == FunctionCode) {
+        registerEntryWithArityCheckPtr = patchBuffer.locationOf(m_registerArgsWithArityCheck);
+        stackEntryWithArityCheckPtr = patchBuffer.locationOf(m_stackArgsWithArityCheck);
+    }
</ins><span class="cx"> 
</span><span class="cx">     if (Options::dumpDisassembly()) {
</span><span class="cx">         m_disassembler-&gt;dump(patchBuffer);
</span><span class="lines">@@ -804,8 +831,20 @@
</span><span class="cx">         static_cast&lt;double&gt;(m_instructions.size()));
</span><span class="cx"> 
</span><span class="cx">     m_codeBlock-&gt;shrinkToFit(CodeBlock::LateShrink);
</span><ins>+    JITEntryPoints entrypoints(result.code(), registerEntryWithArityCheckPtr, registerEntryWithArityCheckPtr, stackEntryArityOKPtr, stackEntryWithArityCheckPtr);
+
+    unsigned numParameters = static_cast&lt;unsigned&gt;(m_codeBlock-&gt;numParameters());
+    for (unsigned argCount = 1; argCount &lt;= NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argCount++) {
+        MacroAssemblerCodePtr entry;
+        if (argCount == numParameters)
+            entry = result.code();
+        else
+            entry = registerEntryWithArityCheckPtr;
+        entrypoints.setEntryFor(JITEntryPoints::registerEntryTypeForArgumentCount(argCount), entry);
+    }
+
</ins><span class="cx">     m_codeBlock-&gt;setJITCode(
</span><del>-        adoptRef(new DirectJITCode(result, withArityCheck, JITCode::BaselineJIT)));
</del><ins>+        adoptRef(new DirectJITCode(JITEntryPointsWithRef(result, entrypoints), 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></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -43,6 +43,7 @@
</span><span class="cx"> #include &quot;JITInlineCacheGenerator.h&quot;
</span><span class="cx"> #include &quot;JITMathIC.h&quot;
</span><span class="cx"> #include &quot;JSInterfaceJIT.h&quot;
</span><ins>+#include &quot;LowLevelInterpreter.h&quot;
</ins><span class="cx"> #include &quot;PCToCodeOriginMap.h&quot;
</span><span class="cx"> #include &quot;UnusedPointer.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -246,7 +247,15 @@
</span><span class="cx">             jit.privateCompileHasIndexedProperty(byValInfo, returnAddress, arrayMode);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        static CodeRef compileCTINativeCall(VM*, NativeFunction);
</del><ins>+        static JITEntryPointsWithRef compileNativeCallEntryPoints(VM* vm, NativeFunction func)
+        {
+            if (!vm-&gt;canUseJIT()) {
+                CodeRef nativeCallRef = CodeRef::createLLIntCodeRef(llint_native_call_trampoline);
+                return JITEntryPointsWithRef(nativeCallRef, nativeCallRef.code(), nativeCallRef.code());
+            }
+            JIT jit(vm, 0);
+            return jit.privateCompileJITEntryNativeCall(vm, func);
+        }
</ins><span class="cx"> 
</span><span class="cx">         static unsigned frameRegisterCountFor(CodeBlock*);
</span><span class="cx">         static int stackPointerOffsetFor(CodeBlock*);
</span><span class="lines">@@ -266,8 +275,7 @@
</span><span class="cx"> 
</span><span class="cx">         void privateCompileHasIndexedProperty(ByValInfo*, ReturnAddressPtr, JITArrayMode);
</span><span class="cx"> 
</span><del>-        Label privateCompileCTINativeCall(VM*, bool isConstruct = false);
-        CodeRef privateCompileCTINativeCall(VM*, NativeFunction);
</del><ins>+        JITEntryPointsWithRef privateCompileJITEntryNativeCall(VM*, NativeFunction);
</ins><span class="cx">         void privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress);
</span><span class="cx"> 
</span><span class="cx">         // Add a call out from JIT code, without an exception check.
</span><span class="lines">@@ -949,8 +957,10 @@
</span><span class="cx">         unsigned m_putByIdIndex;
</span><span class="cx">         unsigned m_byValInstructionIndex;
</span><span class="cx">         unsigned m_callLinkInfoIndex;
</span><del>-        
-        Label m_arityCheck;
</del><ins>+
+        Label m_stackArgsArityOKEntry;
+        Label m_stackArgsWithArityCheck;
+        Label m_registerArgsWithArityCheck;
</ins><span class="cx">         std::unique_ptr&lt;LinkBuffer&gt; m_linkBuffer;
</span><span class="cx"> 
</span><span class="cx">         std::unique_ptr&lt;JITDisassembler&gt; m_disassembler;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCallcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCall.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/JITCall.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -91,6 +91,8 @@
</span><span class="cx">     store64(regT0, Address(regT1, CallFrame::thisArgumentOffset() * static_cast&lt;int&gt;(sizeof(Register))));
</span><span class="cx"> 
</span><span class="cx">     addPtr(TrustedImm32(sizeof(CallerFrameAndPC)), regT1, stackPointerRegister);
</span><ins>+    incrementCounter(this, VM::BaselineCaller);
+    incrementCounter(this, VM::CallVarargs);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT::compileCallEval(Instruction* instruction)
</span><span class="lines">@@ -98,6 +100,9 @@
</span><span class="cx">     addPtr(TrustedImm32(-static_cast&lt;ptrdiff_t&gt;(sizeof(CallerFrameAndPC))), stackPointerRegister, regT1);
</span><span class="cx">     storePtr(callFrameRegister, Address(regT1, CallFrame::callerFrameOffset()));
</span><span class="cx"> 
</span><ins>+    incrementCounter(this, VM::BaselineCaller);
+    incrementCounter(this, VM::CallEval);
+
</ins><span class="cx">     addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
</span><span class="cx">     checkStackPointerAlignment();
</span><span class="cx"> 
</span><span class="lines">@@ -113,7 +118,7 @@
</span><span class="cx"> void JIT::compileCallEvalSlowCase(Instruction* instruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
</span><span class="cx"> {
</span><span class="cx">     CallLinkInfo* info = m_codeBlock-&gt;addCallLinkInfo();
</span><del>-    info-&gt;setUpCall(CallLinkInfo::Call, CodeOrigin(m_bytecodeOffset), regT0);
</del><ins>+    info-&gt;setUpCall(CallLinkInfo::Call, StackArgs, CodeOrigin(m_bytecodeOffset), regT0);
</ins><span class="cx"> 
</span><span class="cx">     linkSlowCase(iter);
</span><span class="cx">     int registerOffset = -instruction[4].u.operand;
</span><span class="lines">@@ -154,12 +159,14 @@
</span><span class="cx">     COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_tail_call_forward_arguments), call_and_tail_call_forward_arguments_opcodes_must_be_same_length);
</span><span class="cx"> 
</span><span class="cx">     CallLinkInfo* info = nullptr;
</span><ins>+    ArgumentsLocation argumentsLocation = StackArgs;
+
</ins><span class="cx">     if (opcodeID != op_call_eval)
</span><span class="cx">         info = m_codeBlock-&gt;addCallLinkInfo();
</span><span class="cx">     if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs || opcodeID == op_tail_call_varargs || opcodeID == op_tail_call_forward_arguments)
</span><span class="cx">         compileSetupVarargsFrame(opcodeID, instruction, info);
</span><span class="cx">     else {
</span><del>-        int argCount = instruction[3].u.operand;
</del><ins>+        unsigned argCount = instruction[3].u.unsignedValue;
</ins><span class="cx">         int registerOffset = -instruction[4].u.operand;
</span><span class="cx"> 
</span><span class="cx">         if (opcodeID == op_call &amp;&amp; shouldEmitProfiling()) {
</span><span class="lines">@@ -171,16 +178,26 @@
</span><span class="cx">         }
</span><span class="cx">     
</span><span class="cx">         addPtr(TrustedImm32(registerOffset * sizeof(Register) + sizeof(CallerFrameAndPC)), callFrameRegister, stackPointerRegister);
</span><ins>+        if (argumentsLocation != StackArgs) {
+            move(TrustedImm32(argCount), argumentRegisterForArgumentCount());
+            unsigned registerArgs = std::min(argCount, NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS);
+            for (unsigned arg = 0; arg &lt; registerArgs; arg++)
+                load64(Address(stackPointerRegister, (CallFrameSlot::thisArgument + arg) * static_cast&lt;int&gt;(sizeof(Register)) - sizeof(CallerFrameAndPC)), argumentRegisterForFunctionArgument(arg));
+        }
</ins><span class="cx">         store32(TrustedImm32(argCount), Address(stackPointerRegister, CallFrameSlot::argumentCount * static_cast&lt;int&gt;(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC)));
</span><span class="cx">     } // SP holds newCallFrame + sizeof(CallerFrameAndPC), with ArgumentCount initialized.
</span><ins>+
+    incrementCounter(this, VM::BaselineCaller);
</ins><span class="cx">     
</span><span class="cx">     uint32_t bytecodeOffset = instruction - m_codeBlock-&gt;instructions().begin();
</span><span class="cx">     uint32_t locationBits = CallSiteIndex(bytecodeOffset).bits();
</span><span class="cx">     store32(TrustedImm32(locationBits), Address(callFrameRegister, CallFrameSlot::argumentCount * static_cast&lt;int&gt;(sizeof(Register)) + TagOffset));
</span><span class="cx"> 
</span><del>-    emitGetVirtualRegister(callee, regT0); // regT0 holds callee.
-    store64(regT0, Address(stackPointerRegister, CallFrameSlot::callee * static_cast&lt;int&gt;(sizeof(Register)) - sizeof(CallerFrameAndPC)));
</del><ins>+    GPRReg calleeRegister = argumentRegisterForCallee();
</ins><span class="cx"> 
</span><ins>+    emitGetVirtualRegister(callee, calleeRegister);
+    store64(calleeRegister, Address(stackPointerRegister, CallFrameSlot::callee * static_cast&lt;int&gt;(sizeof(Register)) - sizeof(CallerFrameAndPC)));
+
</ins><span class="cx">     if (opcodeID == op_call_eval) {
</span><span class="cx">         compileCallEval(instruction);
</span><span class="cx">         return;
</span><span class="lines">@@ -187,16 +204,18 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     DataLabelPtr addressOfLinkedFunctionCheck;
</span><del>-    Jump slowCase = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, TrustedImmPtr(0));
</del><ins>+    Jump slowCase = branchPtrWithPatch(NotEqual, calleeRegister, addressOfLinkedFunctionCheck, TrustedImmPtr(0));
</ins><span class="cx">     addSlowCase(slowCase);
</span><span class="cx"> 
</span><span class="cx">     ASSERT(m_callCompilationInfo.size() == callLinkInfoIndex);
</span><del>-    info-&gt;setUpCall(CallLinkInfo::callTypeFor(opcodeID), CodeOrigin(m_bytecodeOffset), regT0);
</del><ins>+    info-&gt;setUpCall(CallLinkInfo::callTypeFor(opcodeID), argumentsLocation, CodeOrigin(m_bytecodeOffset), calleeRegister);
</ins><span class="cx">     m_callCompilationInfo.append(CallCompilationInfo());
</span><span class="cx">     m_callCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
</span><span class="cx">     m_callCompilationInfo[callLinkInfoIndex].callLinkInfo = info;
</span><span class="cx"> 
</span><span class="cx">     if (opcodeID == op_tail_call) {
</span><ins>+        incrementCounter(this, VM::TailCall);
+
</ins><span class="cx">         CallFrameShuffleData shuffleData;
</span><span class="cx">         shuffleData.tagTypeNumber = GPRInfo::tagTypeNumberRegister;
</span><span class="cx">         shuffleData.numLocals =
</span><span class="lines">@@ -209,7 +228,7 @@
</span><span class="cx">                     DataFormatJS);
</span><span class="cx">         }
</span><span class="cx">         shuffleData.callee =
</span><del>-            ValueRecovery::inGPR(regT0, DataFormatJS);
</del><ins>+            ValueRecovery::inGPR(calleeRegister, DataFormatJS);
</ins><span class="cx">         shuffleData.setupCalleeSaveRegisters(m_codeBlock);
</span><span class="cx">         info-&gt;setFrameShuffleData(shuffleData);
</span><span class="cx">         CallFrameShuffler(*this, shuffleData).prepareForTailCall();
</span><span class="lines">@@ -246,9 +265,10 @@
</span><span class="cx">     if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs || opcodeID == op_tail_call_forward_arguments)
</span><span class="cx">         emitRestoreCalleeSaves();
</span><span class="cx"> 
</span><del>-    move(TrustedImmPtr(m_callCompilationInfo[callLinkInfoIndex].callLinkInfo), regT2);
</del><ins>+    CallLinkInfo* callLinkInfo = m_callCompilationInfo[callLinkInfoIndex].callLinkInfo;
+    move(TrustedImmPtr(callLinkInfo), nonArgGPR0);
</ins><span class="cx"> 
</span><del>-    m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm-&gt;getCTIStub(linkCallThunkGenerator).code());
</del><ins>+    m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm-&gt;getJITCallThunkEntryStub(linkCallThunkGenerator).entryFor(callLinkInfo-&gt;argumentsLocation()));
</ins><span class="cx"> 
</span><span class="cx">     if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs) {
</span><span class="cx">         abortWithReason(JITDidReturnFromTailCall);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCall32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -203,7 +203,7 @@
</span><span class="cx"> void JIT::compileCallEvalSlowCase(Instruction* instruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
</span><span class="cx"> {
</span><span class="cx">     CallLinkInfo* info = m_codeBlock-&gt;addCallLinkInfo();
</span><del>-    info-&gt;setUpCall(CallLinkInfo::Call, CodeOrigin(m_bytecodeOffset), regT0);
</del><ins>+    info-&gt;setUpCall(CallLinkInfo::Call, StackArgs, CodeOrigin(m_bytecodeOffset), regT0);
</ins><span class="cx"> 
</span><span class="cx">     linkSlowCase(iter);
</span><span class="cx"> 
</span><span class="lines">@@ -211,12 +211,12 @@
</span><span class="cx"> 
</span><span class="cx">     addPtr(TrustedImm32(registerOffset * sizeof(Register) + sizeof(CallerFrameAndPC)), callFrameRegister, stackPointerRegister);
</span><span class="cx"> 
</span><del>-    move(TrustedImmPtr(info), regT2);
</del><ins>+    move(TrustedImmPtr(info), nonArgGPR0);
</ins><span class="cx"> 
</span><span class="cx">     emitLoad(CallFrameSlot::callee, regT1, regT0);
</span><del>-    MacroAssemblerCodeRef virtualThunk = virtualThunkFor(m_vm, *info);
-    info-&gt;setSlowStub(createJITStubRoutine(virtualThunk, *m_vm, nullptr, true));
-    emitNakedCall(virtualThunk.code());
</del><ins>+    JITJSCallThunkEntryPointsWithRef virtualThunk = virtualThunkFor(m_vm, *info);
+    info-&gt;setSlowStub(createJITStubRoutine(virtualThunk.codeRef(), *m_vm, nullptr, true));
+    emitNakedCall(virtualThunk.entryFor(StackArgs));
</ins><span class="cx">     addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
</span><span class="cx">     checkStackPointerAlignment();
</span><span class="cx"> 
</span><span class="lines">@@ -286,7 +286,7 @@
</span><span class="cx">     addSlowCase(slowCase);
</span><span class="cx"> 
</span><span class="cx">     ASSERT(m_callCompilationInfo.size() == callLinkInfoIndex);
</span><del>-    info-&gt;setUpCall(CallLinkInfo::callTypeFor(opcodeID), CodeOrigin(m_bytecodeOffset), regT0);
</del><ins>+    info-&gt;setUpCall(CallLinkInfo::callTypeFor(opcodeID), StackArgs, CodeOrigin(m_bytecodeOffset), regT0);
</ins><span class="cx">     m_callCompilationInfo.append(CallCompilationInfo());
</span><span class="cx">     m_callCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
</span><span class="cx">     m_callCompilationInfo[callLinkInfoIndex].callLinkInfo = info;
</span><span class="lines">@@ -317,12 +317,13 @@
</span><span class="cx">     linkSlowCase(iter);
</span><span class="cx">     linkSlowCase(iter);
</span><span class="cx"> 
</span><del>-    move(TrustedImmPtr(m_callCompilationInfo[callLinkInfoIndex].callLinkInfo), regT2);
</del><ins>+    CallLinkInfo* callLinkInfo = m_callCompilationInfo[callLinkInfoIndex].callLinkInfo;
+    move(TrustedImmPtr(callLinkInfo), nonArgGPR0);
</ins><span class="cx"> 
</span><span class="cx">     if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs)
</span><span class="cx">         emitRestoreCalleeSaves();
</span><span class="cx"> 
</span><del>-    m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm-&gt;getCTIStub(linkCallThunkGenerator).code());
</del><ins>+    m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm-&gt;getJITCallThunkEntryStub(linkCallThunkGenerator).entryFor(callLinkInfo-&gt;argumentsLocation()));
</ins><span class="cx"> 
</span><span class="cx">     if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs) {
</span><span class="cx">         abortWithReason(JITDidReturnFromTailCall);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCode.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCode.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/JITCode.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -75,9 +75,9 @@
</span><span class="cx"> 
</span><span class="cx">     if (!function || !protoCallFrame-&gt;needArityCheck()) {
</span><span class="cx">         ASSERT(!protoCallFrame-&gt;needArityCheck());
</span><del>-        entryAddress = executableAddress();
</del><ins>+        entryAddress = addressForCall(StackArgsArityCheckNotRequired).executableAddress();
</ins><span class="cx">     } else
</span><del>-        entryAddress = addressForCall(MustCheckArity).executableAddress();
</del><ins>+        entryAddress = addressForCall(StackArgsMustCheckArity).executableAddress();
</ins><span class="cx">     JSValue result = JSValue::decode(vmEntryToJavaScript(entryAddress, vm, protoCallFrame));
</span><span class="cx">     return scope.exception() ? jsNull() : result;
</span><span class="cx"> }
</span><span class="lines">@@ -162,9 +162,9 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-DirectJITCode::DirectJITCode(JITCode::CodeRef ref, JITCode::CodePtr withArityCheck, JITType jitType)
-    : JITCodeWithCodeRef(ref, jitType)
-    , m_withArityCheck(withArityCheck)
</del><ins>+DirectJITCode::DirectJITCode(JITEntryPointsWithRef entries, JITType jitType)
+    : JITCodeWithCodeRef(entries.codeRef(), jitType)
+    , m_entryPoints(entries)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -172,25 +172,16 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void DirectJITCode::initializeCodeRef(JITCode::CodeRef ref, JITCode::CodePtr withArityCheck)
</del><ins>+void DirectJITCode::initializeEntryPoints(JITEntryPointsWithRef entries)
</ins><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(!m_ref);
</span><del>-    m_ref = ref;
-    m_withArityCheck = withArityCheck;
</del><ins>+    m_ref = entries.codeRef();
+    m_entryPoints = entries;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-JITCode::CodePtr DirectJITCode::addressForCall(ArityCheckMode arity)
</del><ins>+JITCode::CodePtr DirectJITCode::addressForCall(EntryPointType type)
</ins><span class="cx"> {
</span><del>-    switch (arity) {
-    case ArityCheckNotRequired:
-        RELEASE_ASSERT(m_ref);
-        return m_ref.code();
-    case MustCheckArity:
-        RELEASE_ASSERT(m_withArityCheck);
-        return m_withArityCheck;
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-    return CodePtr();
</del><ins>+    return m_entryPoints.entryFor(type);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> NativeJITCode::NativeJITCode(JITType jitType)
</span><span class="lines">@@ -213,7 +204,7 @@
</span><span class="cx">     m_ref = ref;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JITCode::CodePtr NativeJITCode::addressForCall(ArityCheckMode)
</del><ins>+JITCode::CodePtr NativeJITCode::addressForCall(EntryPointType)
</ins><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(!!m_ref);
</span><span class="cx">     return m_ref.code();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCode.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCode.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/JITCode.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -25,10 +25,10 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><del>-#include &quot;ArityCheckMode.h&quot;
</del><span class="cx"> #include &quot;CallFrame.h&quot;
</span><span class="cx"> #include &quot;CodeOrigin.h&quot;
</span><span class="cx"> #include &quot;Disassembler.h&quot;
</span><ins>+#include &quot;JITEntryPoints.h&quot;
</ins><span class="cx"> #include &quot;JSCJSValue.h&quot;
</span><span class="cx"> #include &quot;MacroAssemblerCodeRef.h&quot;
</span><span class="cx"> #include &quot;RegisterSet.h&quot;
</span><span class="lines">@@ -173,9 +173,8 @@
</span><span class="cx">         return jitCode-&gt;jitType();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    virtual CodePtr addressForCall(ArityCheckMode) = 0;
</del><ins>+    virtual CodePtr addressForCall(EntryPointType) = 0;
</ins><span class="cx">     virtual void* executableAddressAtOffset(size_t offset) = 0;
</span><del>-    void* executableAddress() { return executableAddressAtOffset(0); }
</del><span class="cx">     virtual void* dataAddressAtOffset(size_t offset) = 0;
</span><span class="cx">     virtual unsigned offsetOf(void* pointerIntoCode) = 0;
</span><span class="cx">     
</span><span class="lines">@@ -224,15 +223,15 @@
</span><span class="cx"> class DirectJITCode : public JITCodeWithCodeRef {
</span><span class="cx"> public:
</span><span class="cx">     DirectJITCode(JITType);
</span><del>-    DirectJITCode(CodeRef, CodePtr withArityCheck, JITType);
</del><ins>+    DirectJITCode(JITEntryPointsWithRef, JITType);
</ins><span class="cx">     virtual ~DirectJITCode();
</span><span class="cx">     
</span><del>-    void initializeCodeRef(CodeRef, CodePtr withArityCheck);
</del><ins>+    void initializeEntryPoints(JITEntryPointsWithRef);
</ins><span class="cx"> 
</span><del>-    CodePtr addressForCall(ArityCheckMode) override;
</del><ins>+    CodePtr addressForCall(EntryPointType) override;
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    CodePtr m_withArityCheck;
</del><ins>+    JITEntryPoints m_entryPoints;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class NativeJITCode : public JITCodeWithCodeRef {
</span><span class="lines">@@ -243,7 +242,7 @@
</span><span class="cx">     
</span><span class="cx">     void initializeCodeRef(CodeRef);
</span><span class="cx"> 
</span><del>-    CodePtr addressForCall(ArityCheckMode) override;
</del><ins>+    CodePtr addressForCall(EntryPointType) override;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITEntryPointsh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/jit/JITEntryPoints.h (0 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITEntryPoints.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/jit/JITEntryPoints.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -0,0 +1,359 @@
</span><ins>+/*
+ * Copyright (C) 2016 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. 
+ */
+
+#pragma once
+
+#include &quot;GPRInfo.h&quot;
+#include &quot;MacroAssemblerCodeRef.h&quot;
+
+namespace JSC {
+class VM;
+class MacroAssemblerCodeRef;
+
+enum ArgumentsLocation : unsigned {
+    StackArgs = 0,
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS &gt;= 4
+    RegisterArgs1InRegisters,
+    RegisterArgs2InRegisters,
+    RegisterArgs3InRegisters,
+    RegisterArgs4InRegisters,
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS == 6
+    RegisterArgs5InRegisters,
+    RegisterArgs6InRegisters,
+#endif
+    RegisterArgsWithExtraOnStack
+#endif
+};
+
+// This enum needs to have the same enumerator ordering as ArgumentsLocation.
+enum ThunkEntryPointType : unsigned {
+    StackArgsEntry = 0,
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS &gt;= 4
+    Register1ArgEntry,
+    Register2ArgsEntry,
+    Register3ArgsEntry,
+    Register4ArgsEntry,
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS == 6
+    Register5ArgsEntry,
+    Register6ArgsEntry,
+#endif
+#endif
+    ThunkEntryPointTypeCount
+};
+
+enum EntryPointType {
+    StackArgsArityCheckNotRequired,
+    StackArgsMustCheckArity,
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    RegisterArgsArityCheckNotRequired,
+    RegisterArgsPossibleExtraArgs,
+    RegisterArgsMustCheckArity,
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS &gt;= 4
+    RegisterArgs1,
+    RegisterArgs2,
+    RegisterArgs3,
+    RegisterArgs4,
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS == 6
+    RegisterArgs5,
+    RegisterArgs6,
+#endif
+#endif
+#endif
+    NumberOfEntryPointTypes
+};
+
+class JITEntryPoints {
+public:
+    typedef MacroAssemblerCodePtr CodePtr;
+    static const unsigned numberOfEntryTypes = EntryPointType::NumberOfEntryPointTypes;
+
+    JITEntryPoints()
+    {
+        clearEntries();
+    }
+
+    JITEntryPoints(CodePtr registerArgsNoCheckRequiredEntry, CodePtr registerArgsPossibleExtraArgsEntry,
+        CodePtr registerArgsCheckArityEntry, CodePtr stackArgsArityCheckNotRequiredEntry,
+        CodePtr stackArgsCheckArityEntry)
+    {
+        m_entryPoints[StackArgsArityCheckNotRequired] = stackArgsArityCheckNotRequiredEntry;
+        m_entryPoints[StackArgsMustCheckArity] = stackArgsCheckArityEntry;
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+        m_entryPoints[RegisterArgsArityCheckNotRequired] = registerArgsNoCheckRequiredEntry;
+        m_entryPoints[RegisterArgsPossibleExtraArgs] = registerArgsPossibleExtraArgsEntry;
+        m_entryPoints[RegisterArgsMustCheckArity] = registerArgsCheckArityEntry;
+        for (unsigned i = 1; i &lt;= NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; i ++)
+            m_entryPoints[registerEntryTypeForArgumentCount(i)] = registerArgsCheckArityEntry;
+#else
+        UNUSED_PARAM(registerArgsNoCheckRequiredEntry);
+        UNUSED_PARAM(registerArgsPossibleExtraArgsEntry);
+        UNUSED_PARAM(registerArgsCheckArityEntry);
+#endif
+
+    }
+
+    CodePtr entryFor(EntryPointType type)
+    {
+        return m_entryPoints[type];
+    }
+
+    void setEntryFor(EntryPointType type, CodePtr entry)
+    {
+        ASSERT(type &lt; NumberOfEntryPointTypes);
+        m_entryPoints[type] = entry;
+    }
+
+    static ptrdiff_t offsetOfEntryFor(EntryPointType type)
+    {
+        return offsetof(JITEntryPoints, m_entryPoints[type]);
+    }
+
+    static EntryPointType registerEntryTypeForArgumentCount(unsigned argCount)
+    {
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+        ASSERT(argCount);
+        unsigned registerArgCount = numberOfRegisterArgumentsFor(argCount);
+        if (!registerArgCount || registerArgCount != argCount)
+            return RegisterArgsMustCheckArity;
+
+        return static_cast&lt;EntryPointType&gt;(RegisterArgs1 + registerArgCount - 1);
+#else
+        UNUSED_PARAM(argCount);
+        RELEASE_ASSERT_NOT_REACHED();
+        return StackArgsMustCheckArity;
+#endif
+    }
+
+    static EntryPointType registerEntryTypeForArgumentType(ArgumentsLocation type)
+    {
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+        ASSERT(type != StackArgs);
+        if (type == RegisterArgsWithExtraOnStack)
+            return RegisterArgsMustCheckArity;
+        
+        return static_cast&lt;EntryPointType&gt;(RegisterArgs1 + type - RegisterArgs1InRegisters);
+#else
+        UNUSED_PARAM(type);
+        RELEASE_ASSERT_NOT_REACHED();
+        return StackArgsMustCheckArity;
+#endif
+    }
+
+    void clearEntries()
+    {
+        for (unsigned i = numberOfEntryTypes; i--;)
+            m_entryPoints[i] = MacroAssemblerCodePtr();
+    }
+
+    JITEntryPoints&amp; operator=(const JITEntryPoints&amp; other)
+    {
+        for (unsigned i = numberOfEntryTypes; i--;)
+            m_entryPoints[i] = other.m_entryPoints[i];
+
+        return *this;
+    }
+
+private:
+
+    CodePtr m_entryPoints[numberOfEntryTypes];
+};
+
+class JITEntryPointsWithRef : public JITEntryPoints {
+public:
+    typedef MacroAssemblerCodeRef CodeRef;
+
+    JITEntryPointsWithRef()
+    {
+    }
+
+    JITEntryPointsWithRef(const JITEntryPointsWithRef&amp; other)
+        : JITEntryPoints(other)
+        , m_codeRef(other.m_codeRef)
+    {
+    }
+
+    JITEntryPointsWithRef(CodeRef codeRef, const JITEntryPoints&amp; other)
+        : JITEntryPoints(other)
+        , m_codeRef(codeRef)
+    {
+    }
+    
+    JITEntryPointsWithRef(CodeRef codeRef, CodePtr stackArgsArityCheckNotRequiredEntry,
+        CodePtr stackArgsCheckArityEntry)
+        : JITEntryPoints(CodePtr(), CodePtr(), CodePtr(), stackArgsArityCheckNotRequiredEntry, stackArgsCheckArityEntry)
+        , m_codeRef(codeRef)
+    {
+    }
+
+    JITEntryPointsWithRef(CodeRef codeRef, CodePtr registerArgsNoChecksRequiredEntry,
+        CodePtr registerArgsPossibleExtraArgsEntry, CodePtr registerArgsCheckArityEntry,
+        CodePtr stackArgsArityCheckNotRequiredEntry, CodePtr stackArgsCheckArityEntry)
+        : JITEntryPoints(registerArgsNoChecksRequiredEntry, registerArgsPossibleExtraArgsEntry,
+            registerArgsCheckArityEntry, stackArgsArityCheckNotRequiredEntry,
+            stackArgsCheckArityEntry)
+        , m_codeRef(codeRef)
+    {
+    }
+
+    CodeRef codeRef() { return m_codeRef; }
+
+private:
+    CodeRef m_codeRef;
+};
+
+inline ArgumentsLocation argumentsLocationFor(unsigned argumentCount)
+{
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    if (!argumentCount)
+        return StackArgs;
+    
+    argumentCount = std::min(NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS + 1, argumentCount);
+    
+    return static_cast&lt;ArgumentsLocation&gt;(ArgumentsLocation::RegisterArgs1InRegisters + argumentCount - 1);
+#else
+    UNUSED_PARAM(argumentCount);
+    return StackArgs;
+#endif
+}
+
+inline EntryPointType registerEntryPointTypeFor(unsigned argumentCount)
+{
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    if (!argumentCount || argumentCount &gt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS)
+        return RegisterArgsMustCheckArity;
+    
+    return static_cast&lt;EntryPointType&gt;(EntryPointType::RegisterArgs1 + argumentCount - 1);
+#else
+    RELEASE_ASSERT_NOT_REACHED();
+    UNUSED_PARAM(argumentCount);
+    return StackArgsMustCheckArity;
+#endif
+}
+
+inline EntryPointType entryPointTypeFor(ArgumentsLocation argumentLocation)
+{
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    if (argumentLocation == StackArgs)
+        return StackArgsMustCheckArity;
+    
+    if (argumentLocation == RegisterArgsWithExtraOnStack)
+        return RegisterArgsMustCheckArity;
+    
+    return static_cast&lt;EntryPointType&gt;(EntryPointType::RegisterArgs1 + static_cast&lt;unsigned&gt;(argumentLocation - RegisterArgs1InRegisters));
+#else
+    UNUSED_PARAM(argumentLocation);
+    return StackArgsMustCheckArity;
+#endif
+}
+
+inline ThunkEntryPointType thunkEntryPointTypeFor(ArgumentsLocation argumentLocation)
+{
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    unsigned argumentLocationIndex = std::min(RegisterArgsWithExtraOnStack - 1, static_cast&lt;unsigned&gt;(argumentLocation));
+    return static_cast&lt;ThunkEntryPointType&gt;(argumentLocationIndex);
+#else
+    UNUSED_PARAM(argumentLocation);
+    return StackArgsEntry;
+#endif
+}
+
+inline ThunkEntryPointType thunkEntryPointTypeFor(unsigned argumentCount)
+{
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    argumentCount = numberOfRegisterArgumentsFor(argumentCount);
+    
+    return static_cast&lt;ThunkEntryPointType&gt;(ThunkEntryPointType::Register1ArgEntry + argumentCount - 1);
+#else
+    UNUSED_PARAM(argumentCount);
+    return StackArgsEntry;
+#endif
+}
+
+class JITJSCallThunkEntryPointsWithRef {
+public:
+    typedef MacroAssemblerCodePtr CodePtr;
+    typedef MacroAssemblerCodeRef CodeRef;
+    static const unsigned numberOfEntryTypes = ThunkEntryPointType::ThunkEntryPointTypeCount;
+
+    JITJSCallThunkEntryPointsWithRef()
+    {
+    }
+
+    JITJSCallThunkEntryPointsWithRef(CodeRef codeRef)
+        : m_codeRef(codeRef)
+    {
+    }
+
+    JITJSCallThunkEntryPointsWithRef(const JITJSCallThunkEntryPointsWithRef&amp; other)
+        : m_codeRef(other.m_codeRef)
+    {
+        for (unsigned i = 0; i &lt; numberOfEntryTypes; i++)
+            m_entryPoints[i] = other.m_entryPoints[i];
+    }
+
+    CodePtr entryFor(ThunkEntryPointType type)
+    {
+        return m_entryPoints[type];
+    }
+
+    CodePtr entryFor(ArgumentsLocation argumentsLocation)
+    {
+        return entryFor(thunkEntryPointTypeFor(argumentsLocation));
+    }
+
+    void setEntryFor(ThunkEntryPointType type, CodePtr entry)
+    {
+        m_entryPoints[type] = entry;
+    }
+
+    static ptrdiff_t offsetOfEntryFor(ThunkEntryPointType type)
+    {
+        return offsetof(JITJSCallThunkEntryPointsWithRef, m_entryPoints[type]);
+    }
+
+    void clearEntries()
+    {
+        for (unsigned i = numberOfEntryTypes; i--;)
+            m_entryPoints[i] = MacroAssemblerCodePtr();
+    }
+
+    CodeRef codeRef() { return m_codeRef; }
+
+    JITJSCallThunkEntryPointsWithRef&amp; operator=(const JITJSCallThunkEntryPointsWithRef&amp; other)
+    {
+        m_codeRef = other.m_codeRef;
+        for (unsigned i = numberOfEntryTypes; i--;)
+            m_entryPoints[i] = other.m_entryPoints[i];
+        
+        return *this;
+    }
+
+private:
+    CodeRef m_codeRef;
+    CodePtr m_entryPoints[numberOfEntryTypes];
+};
+
+
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -49,9 +49,9 @@
</span><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx"> 
</span><del>-JIT::CodeRef JIT::privateCompileCTINativeCall(VM* vm, NativeFunction)
</del><ins>+JITEntryPointsWithRef JIT::privateCompileJITEntryNativeCall(VM* vm, NativeFunction)
</ins><span class="cx"> {
</span><del>-    return vm-&gt;getCTIStub(nativeCallGenerator);
</del><ins>+    return vm-&gt;getJITEntryStub(nativeCallGenerator);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT::emit_op_mov(Instruction* currentInstruction)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodes32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -46,7 +46,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-JIT::CodeRef JIT::privateCompileCTINativeCall(VM* vm, NativeFunction func)
</del><ins>+JITEntryPointsWithRef JIT::privateCompileJITEntryNativeCall(VM* vm, NativeFunction func)
</ins><span class="cx"> {
</span><span class="cx">     // FIXME: This should be able to log ShadowChicken prologue packets.
</span><span class="cx">     // https://bugs.webkit.org/show_bug.cgi?id=155689
</span><span class="lines">@@ -129,7 +129,9 @@
</span><span class="cx">     LinkBuffer patchBuffer(*m_vm, *this, GLOBAL_THUNK_ID);
</span><span class="cx"> 
</span><span class="cx">     patchBuffer.link(nativeCall, FunctionPtr(func));
</span><del>-    return FINALIZE_CODE(patchBuffer, (&quot;JIT CTI native call&quot;));
</del><ins>+    JIT::CodeRef codeRef = FINALIZE_CODE(patchBuffer, (&quot;JIT CTI native call&quot;));
+    
+    return JITEntryPointsWithRef(codeRef, codeRef.code(), codeRef.code());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT::emit_op_mov(Instruction* currentInstruction)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -890,10 +890,14 @@
</span><span class="cx">     JSScope* scope = callee-&gt;scopeUnchecked();
</span><span class="cx">     ExecutableBase* executable = callee-&gt;executable();
</span><span class="cx"> 
</span><del>-    MacroAssemblerCodePtr codePtr;
</del><ins>+    MacroAssemblerCodePtr codePtr, codePtrForLinking;
</ins><span class="cx">     CodeBlock* codeBlock = 0;
</span><span class="cx">     if (executable-&gt;isHostFunction()) {
</span><del>-        codePtr = executable-&gt;entrypointFor(kind, MustCheckArity);
</del><ins>+        codePtr = executable-&gt;entrypointFor(kind, StackArgsMustCheckArity);
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+        if (callLinkInfo-&gt;argumentsInRegisters())
+            codePtrForLinking = executable-&gt;entrypointFor(kind, RegisterArgsMustCheckArity);
+#endif
</ins><span class="cx">     } else {
</span><span class="cx">         FunctionExecutable* functionExecutable = static_cast&lt;FunctionExecutable*&gt;(executable);
</span><span class="cx"> 
</span><span class="lines">@@ -914,17 +918,41 @@
</span><span class="cx">                 reinterpret_cast&lt;void*&gt;(KeepTheFrame));
</span><span class="cx">         }
</span><span class="cx">         codeBlock = *codeBlockSlot;
</span><del>-        ArityCheckMode arity;
-        if (execCallee-&gt;argumentCountIncludingThis() &lt; static_cast&lt;size_t&gt;(codeBlock-&gt;numParameters()) || callLinkInfo-&gt;isVarargs())
-            arity = MustCheckArity;
-        else
-            arity = ArityCheckNotRequired;
-        codePtr = functionExecutable-&gt;entrypointFor(kind, arity);
</del><ins>+        EntryPointType entryType;
+        size_t callerArgumentCount = execCallee-&gt;argumentCountIncludingThis();
+        size_t calleeArgumentCount = static_cast&lt;size_t&gt;(codeBlock-&gt;numParameters());
+        if (callerArgumentCount &lt; calleeArgumentCount || callLinkInfo-&gt;isVarargs()) {
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+            if (callLinkInfo-&gt;argumentsInRegisters()) {
+                codePtrForLinking = functionExecutable-&gt;entrypointFor(kind, JITEntryPoints::registerEntryTypeForArgumentCount(callerArgumentCount));
+                if (!codePtrForLinking)
+                    codePtrForLinking = functionExecutable-&gt;entrypointFor(kind, RegisterArgsMustCheckArity);
+            }
+#endif
+            entryType = StackArgsMustCheckArity;
+            (void) functionExecutable-&gt;entrypointFor(kind, entryPointTypeFor(callLinkInfo-&gt;argumentsLocation()));
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+        } else if (callLinkInfo-&gt;argumentsInRegisters()) {
+            if (callerArgumentCount == calleeArgumentCount || calleeArgumentCount &gt;= NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS)
+                codePtrForLinking = functionExecutable-&gt;entrypointFor(kind, RegisterArgsArityCheckNotRequired);
+            else {
+                codePtrForLinking = functionExecutable-&gt;entrypointFor(kind, JITEntryPoints::registerEntryTypeForArgumentCount(callerArgumentCount));
+                if (!codePtrForLinking)
+                    codePtrForLinking = functionExecutable-&gt;entrypointFor(kind, RegisterArgsPossibleExtraArgs);
+            }
+            //  Prepopulate the entry points the virtual thunk might use.
+            (void) functionExecutable-&gt;entrypointFor(kind, entryPointTypeFor(callLinkInfo-&gt;argumentsLocation()));
+
+            entryType = StackArgsArityCheckNotRequired;
+#endif
+        } else
+            entryType = StackArgsArityCheckNotRequired;
+        codePtr = functionExecutable-&gt;entrypointFor(kind, entryType);
</ins><span class="cx">     }
</span><span class="cx">     if (!callLinkInfo-&gt;seenOnce())
</span><span class="cx">         callLinkInfo-&gt;setSeen();
</span><span class="cx">     else
</span><del>-        linkFor(execCallee, *callLinkInfo, codeBlock, callee, codePtr);
</del><ins>+        linkFor(execCallee, *callLinkInfo, codeBlock, callee, codePtrForLinking ? codePtrForLinking : codePtr);
</ins><span class="cx">     
</span><span class="cx">     return encodeResult(codePtr.executableAddress(), reinterpret_cast&lt;void*&gt;(callLinkInfo-&gt;callMode() == CallMode::Tail ? ReuseTheFrame : KeepTheFrame));
</span><span class="cx"> }
</span><span class="lines">@@ -959,7 +987,11 @@
</span><span class="cx">     MacroAssemblerCodePtr codePtr;
</span><span class="cx">     CodeBlock* codeBlock = nullptr;
</span><span class="cx">     if (executable-&gt;isHostFunction())
</span><del>-        codePtr = executable-&gt;entrypointFor(kind, MustCheckArity);
</del><ins>+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+        codePtr = executable-&gt;entrypointFor(kind, callLinkInfo-&gt;argumentsInRegisters() ? RegisterArgsMustCheckArity : StackArgsMustCheckArity);
+#else
+    codePtr = executable-&gt;entrypointFor(kind, StackArgsMustCheckArity);
+#endif
</ins><span class="cx">     else {
</span><span class="cx">         FunctionExecutable* functionExecutable = static_cast&lt;FunctionExecutable*&gt;(executable);
</span><span class="cx"> 
</span><span class="lines">@@ -971,13 +1003,29 @@
</span><span class="cx">             throwException(exec, throwScope, error);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><del>-        ArityCheckMode arity;
</del><ins>+        EntryPointType entryType;
</ins><span class="cx">         unsigned argumentStackSlots = callLinkInfo-&gt;maxNumArguments();
</span><del>-        if (argumentStackSlots &lt; static_cast&lt;size_t&gt;(codeBlock-&gt;numParameters()))
-            arity = MustCheckArity;
</del><ins>+        size_t codeBlockParameterCount = static_cast&lt;size_t&gt;(codeBlock-&gt;numParameters());
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+        if (callLinkInfo-&gt;argumentsInRegisters()) {
+            // This logic could probably be simplified!
+            if (argumentStackSlots &lt; codeBlockParameterCount)
+                entryType = entryPointTypeFor(callLinkInfo-&gt;argumentsLocation());
+            else if (argumentStackSlots &gt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS) {
+                if (codeBlockParameterCount &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS)
+                    entryType = RegisterArgsPossibleExtraArgs;
+                else
+                    entryType = RegisterArgsArityCheckNotRequired;
+            } else
+                entryType = registerEntryPointTypeFor(argumentStackSlots);
+        } else if (argumentStackSlots &lt; codeBlockParameterCount)
+#else
+        if (argumentStackSlots &lt; codeBlockParameterCount)
+#endif
+            entryType = StackArgsMustCheckArity;
</ins><span class="cx">         else
</span><del>-            arity = ArityCheckNotRequired;
-        codePtr = functionExecutable-&gt;entrypointFor(kind, arity);
</del><ins>+            entryType = StackArgsArityCheckNotRequired;
+        codePtr = functionExecutable-&gt;entrypointFor(kind, entryType);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     linkDirectFor(exec, *callLinkInfo, codeBlock, codePtr);
</span><span class="lines">@@ -1020,8 +1068,17 @@
</span><span class="cx">                 reinterpret_cast&lt;void*&gt;(KeepTheFrame));
</span><span class="cx">         }
</span><span class="cx">     }
</span><ins>+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    if (callLinkInfo-&gt;argumentsInRegisters()) {
+        // Pull into the cache the arity check register entry if the caller wants a register entry.
+        // This will be used by the generic virtual call thunk.
+        (void) executable-&gt;entrypointFor(kind, RegisterArgsMustCheckArity);
+        (void) executable-&gt;entrypointFor(kind, entryPointTypeFor(callLinkInfo-&gt;argumentsLocation()));
+
+    }
+#endif
</ins><span class="cx">     return encodeResult(executable-&gt;entrypointFor(
</span><del>-        kind, MustCheckArity).executableAddress(),
</del><ins>+        kind, StackArgsMustCheckArity).executableAddress(),
</ins><span class="cx">         reinterpret_cast&lt;void*&gt;(callLinkInfo-&gt;callMode() == CallMode::Tail ? ReuseTheFrame : KeepTheFrame));
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITThunkscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITThunks.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITThunks.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/JITThunks.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -44,18 +44,22 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodePtr JITThunks::ctiNativeCall(VM* vm)
</del><ins>+JITEntryPointsWithRef JITThunks::jitEntryNativeCall(VM* vm)
</ins><span class="cx"> {
</span><del>-    if (!vm-&gt;canUseJIT())
-        return MacroAssemblerCodePtr::createLLIntCodePtr(llint_native_call_trampoline);
-    return ctiStub(vm, nativeCallGenerator).code();
</del><ins>+    if (!vm-&gt;canUseJIT()) {
+        MacroAssemblerCodePtr nativeCallStub = MacroAssemblerCodePtr::createLLIntCodePtr(llint_native_call_trampoline);
+        return JITEntryPointsWithRef(MacroAssemblerCodeRef::createSelfManagedCodeRef(nativeCallStub), nativeCallStub, nativeCallStub);
+    }
+    return jitEntryStub(vm, nativeCallGenerator);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodePtr JITThunks::ctiNativeConstruct(VM* vm)
</del><ins>+JITEntryPointsWithRef JITThunks::jitEntryNativeConstruct(VM* vm)
</ins><span class="cx"> {
</span><del>-    if (!vm-&gt;canUseJIT())
-        return MacroAssemblerCodePtr::createLLIntCodePtr(llint_native_construct_trampoline);
-    return ctiStub(vm, nativeConstructGenerator).code();
</del><ins>+    if (!vm-&gt;canUseJIT()) {
+        MacroAssemblerCodePtr nativeConstructStub = MacroAssemblerCodePtr::createLLIntCodePtr(llint_native_construct_trampoline);
+        return JITEntryPointsWithRef(MacroAssemblerCodeRef::createSelfManagedCodeRef(nativeConstructStub), nativeConstructStub, nativeConstructStub);
+    }
+    return jitEntryStub(vm, nativeConstructGenerator);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MacroAssemblerCodePtr JITThunks::ctiNativeTailCall(VM* vm)
</span><span class="lines">@@ -82,6 +86,30 @@
</span><span class="cx">     return entry.iterator-&gt;value;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JITEntryPointsWithRef JITThunks::jitEntryStub(VM* vm, JITEntryGenerator generator)
+{
+    LockHolder locker(m_lock);
+    JITEntryStubMap::AddResult entry = m_jitEntryStubMap.add(generator, JITEntryPointsWithRef());
+    if (entry.isNewEntry) {
+        // Compilation thread can only retrieve existing entries.
+        ASSERT(!isCompilationThread());
+        entry.iterator-&gt;value = generator(vm);
+    }
+    return entry.iterator-&gt;value;
+}
+
+JITJSCallThunkEntryPointsWithRef JITThunks::jitCallThunkEntryStub(VM* vm, JITCallThunkEntryGenerator generator)
+{
+    LockHolder locker(m_lock);
+    JITCallThunkEntryStubMap::AddResult entry = m_jitCallThunkEntryStubMap.add(generator, JITJSCallThunkEntryPointsWithRef());
+    if (entry.isNewEntry) {
+        // Compilation thread can only retrieve existing entries.
+        ASSERT(!isCompilationThread());
+        entry.iterator-&gt;value = generator(vm);
+    }
+    return entry.iterator-&gt;value;
+}
+
</ins><span class="cx"> void JITThunks::finalize(Handle&lt;Unknown&gt; handle, void*)
</span><span class="cx"> {
</span><span class="cx">     auto* nativeExecutable = jsCast&lt;NativeExecutable*&gt;(handle.get().asCell());
</span><span class="lines">@@ -93,7 +121,7 @@
</span><span class="cx">     return hostFunctionStub(vm, function, constructor, nullptr, NoIntrinsic, nullptr, name);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-NativeExecutable* JITThunks::hostFunctionStub(VM* vm, NativeFunction function, NativeFunction constructor, ThunkGenerator generator, Intrinsic intrinsic, const DOMJIT::Signature* signature, const String&amp; name)
</del><ins>+NativeExecutable* JITThunks::hostFunctionStub(VM* vm, NativeFunction function, NativeFunction constructor, JITEntryGenerator generator, Intrinsic intrinsic, const DOMJIT::Signature* signature, const String&amp; name)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!isCompilationThread());    
</span><span class="cx">     ASSERT(vm-&gt;canUseJIT());
</span><span class="lines">@@ -103,12 +131,12 @@
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;JITCode&gt; forCall;
</span><span class="cx">     if (generator) {
</span><del>-        MacroAssemblerCodeRef entry = generator(vm);
-        forCall = adoptRef(new DirectJITCode(entry, entry.code(), JITCode::HostCallThunk));
</del><ins>+        JITEntryPointsWithRef entry = generator(vm);
+        forCall = adoptRef(new DirectJITCode(entry, JITCode::HostCallThunk));
</ins><span class="cx">     } else
</span><del>-        forCall = adoptRef(new NativeJITCode(JIT::compileCTINativeCall(vm, function), JITCode::HostCallThunk));
</del><ins>+        forCall = adoptRef(new DirectJITCode(JIT::compileNativeCallEntryPoints(vm, function), JITCode::HostCallThunk));
</ins><span class="cx">     
</span><del>-    RefPtr&lt;JITCode&gt; forConstruct = adoptRef(new NativeJITCode(MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct(vm)), JITCode::HostCallThunk));
</del><ins>+    RefPtr&lt;JITCode&gt; forConstruct = adoptRef(new DirectJITCode(jitEntryNativeConstruct(vm), JITCode::HostCallThunk));
</ins><span class="cx">     
</span><span class="cx">     NativeExecutable* nativeExecutable = NativeExecutable::create(*vm, forCall, function, forConstruct, constructor, intrinsic, signature, name);
</span><span class="cx">     weakAdd(*m_hostFunctionStubMap, std::make_tuple(function, constructor, name), Weak&lt;NativeExecutable&gt;(nativeExecutable, this));
</span><span class="lines">@@ -115,7 +143,7 @@
</span><span class="cx">     return nativeExecutable;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-NativeExecutable* JITThunks::hostFunctionStub(VM* vm, NativeFunction function, ThunkGenerator generator, Intrinsic intrinsic, const String&amp; name)
</del><ins>+NativeExecutable* JITThunks::hostFunctionStub(VM* vm, NativeFunction function, JITEntryGenerator generator, Intrinsic intrinsic, const String&amp; name)
</ins><span class="cx"> {
</span><span class="cx">     return hostFunctionStub(vm, function, callHostFunctionAsConstructor, generator, intrinsic, nullptr, name);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITThunksh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITThunks.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITThunks.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/JITThunks.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CallData.h&quot;
</span><span class="cx"> #include &quot;Intrinsic.h&quot;
</span><ins>+#include &quot;JITEntryPoints.h&quot;
</ins><span class="cx"> #include &quot;MacroAssemblerCodeRef.h&quot;
</span><span class="cx"> #include &quot;ThunkGenerator.h&quot;
</span><span class="cx"> #include &quot;Weak.h&quot;
</span><span class="lines">@@ -52,16 +53,18 @@
</span><span class="cx">     JITThunks();
</span><span class="cx">     virtual ~JITThunks();
</span><span class="cx"> 
</span><del>-    MacroAssemblerCodePtr ctiNativeCall(VM*);
-    MacroAssemblerCodePtr ctiNativeConstruct(VM*);
</del><ins>+    JITEntryPointsWithRef jitEntryNativeCall(VM*);
+    JITEntryPointsWithRef jitEntryNativeConstruct(VM*);
</ins><span class="cx">     MacroAssemblerCodePtr ctiNativeTailCall(VM*);    
</span><span class="cx">     MacroAssemblerCodePtr ctiNativeTailCallWithoutSavedTags(VM*);    
</span><span class="cx"> 
</span><span class="cx">     MacroAssemblerCodeRef ctiStub(VM*, ThunkGenerator);
</span><ins>+    JITEntryPointsWithRef jitEntryStub(VM*, JITEntryGenerator);
+    JITJSCallThunkEntryPointsWithRef jitCallThunkEntryStub(VM*, JITCallThunkEntryGenerator);
</ins><span class="cx"> 
</span><span class="cx">     NativeExecutable* hostFunctionStub(VM*, NativeFunction, NativeFunction constructor, const String&amp; name);
</span><del>-    NativeExecutable* hostFunctionStub(VM*, NativeFunction, NativeFunction constructor, ThunkGenerator, Intrinsic, const DOMJIT::Signature*, const String&amp; name);
-    NativeExecutable* hostFunctionStub(VM*, NativeFunction, ThunkGenerator, Intrinsic, const String&amp; name);
</del><ins>+    NativeExecutable* hostFunctionStub(VM*, NativeFunction, NativeFunction constructor, JITEntryGenerator, Intrinsic, const DOMJIT::Signature*, const String&amp; name);
+    NativeExecutable* hostFunctionStub(VM*, NativeFunction, JITEntryGenerator, Intrinsic, const String&amp; name);
</ins><span class="cx"> 
</span><span class="cx">     void clearHostFunctionStubs();
</span><span class="cx"> 
</span><span class="lines">@@ -70,6 +73,10 @@
</span><span class="cx">     
</span><span class="cx">     typedef HashMap&lt;ThunkGenerator, MacroAssemblerCodeRef&gt; CTIStubMap;
</span><span class="cx">     CTIStubMap m_ctiStubMap;
</span><ins>+    typedef HashMap&lt;JITEntryGenerator, JITEntryPointsWithRef&gt; JITEntryStubMap;
+    JITEntryStubMap m_jitEntryStubMap;
+    typedef HashMap&lt;JITCallThunkEntryGenerator, JITJSCallThunkEntryPointsWithRef&gt; JITCallThunkEntryStubMap;
+    JITCallThunkEntryStubMap m_jitCallThunkEntryStubMap;
</ins><span class="cx"> 
</span><span class="cx">     typedef std::tuple&lt;NativeFunction, NativeFunction, String&gt; HostFunctionKey;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJSInterfaceJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JSInterfaceJIT.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JSInterfaceJIT.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/JSInterfaceJIT.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -63,6 +63,7 @@
</span><span class="cx">         Jump emitJumpIfNotJSCell(RegisterID);
</span><span class="cx">         Jump emitJumpIfNumber(RegisterID);
</span><span class="cx">         Jump emitJumpIfNotNumber(RegisterID);
</span><ins>+        Jump emitJumpIfNotInt32(RegisterID reg);
</ins><span class="cx">         void emitTagInt(RegisterID src, RegisterID dest);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -163,12 +164,17 @@
</span><span class="cx">         return branchTest64(NonZero, dst, tagMaskRegister);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    inline JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotInt32(RegisterID reg)
+    {
+        Jump result = branch64(Below, reg, tagTypeNumberRegister);
+        zeroExtend32ToPtr(reg, reg);
+        return result;
+    }
+
</ins><span class="cx">     inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst)
</span><span class="cx">     {
</span><span class="cx">         load64(addressFor(virtualRegisterIndex), dst);
</span><del>-        Jump result = branch64(Below, dst, tagTypeNumberRegister);
-        zeroExtend32ToPtr(dst, dst);
-        return result;
</del><ins>+        return emitJumpIfNotInt32(dst);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRegisterSetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/RegisterSet.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/RegisterSet.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/RegisterSet.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -159,6 +159,20 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RegisterSet RegisterSet::argumentRegisters()
+{
+    RegisterSet result;
+#if USE(JSVALUE64)
+    for (unsigned argumentIndex = 0; argumentIndex &lt; NUMBER_OF_ARGUMENT_REGISTERS; argumentIndex++) {
+        GPRReg argumentReg = argumentRegisterFor(argumentIndex);
+
+        if (argumentReg != InvalidGPRReg)
+            result.set(argumentReg);
+    }
+#endif
+    return result;
+}
+
</ins><span class="cx"> RegisterSet RegisterSet::vmCalleeSaveRegisters()
</span><span class="cx"> {
</span><span class="cx">     RegisterSet result;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRegisterSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/RegisterSet.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/RegisterSet.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/RegisterSet.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -49,6 +49,7 @@
</span><span class="cx">     static RegisterSet runtimeRegisters();
</span><span class="cx">     static RegisterSet specialRegisters(); // The union of stack, reserved hardware, and runtime registers.
</span><span class="cx">     JS_EXPORT_PRIVATE static RegisterSet calleeSaveRegisters();
</span><ins>+    static RegisterSet argumentRegisters(); // Registers used to pass arguments when making JS Calls
</ins><span class="cx">     static RegisterSet vmCalleeSaveRegisters(); // Callee save registers that might be saved and used by any tier.
</span><span class="cx">     static RegisterSet llintBaselineCalleeSaveRegisters(); // Registers saved and used by the LLInt.
</span><span class="cx">     static RegisterSet dfgCalleeSaveRegisters(); // Registers saved and used by the DFG JIT.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/Repatch.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -540,21 +540,21 @@
</span><span class="cx">         ftlThunkAwareRepatchCall(exec-&gt;codeBlock(), stubInfo.slowPathCallLocation(), operationIn);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void linkSlowFor(VM*, CallLinkInfo&amp; callLinkInfo, MacroAssemblerCodeRef codeRef)
</del><ins>+static void linkSlowFor(VM*, CallLinkInfo&amp; callLinkInfo, JITJSCallThunkEntryPointsWithRef thunkEntryPoints)
</ins><span class="cx"> {
</span><del>-    MacroAssembler::repatchNearCall(callLinkInfo.callReturnLocation(), CodeLocationLabel(codeRef.code()));
</del><ins>+    MacroAssembler::repatchNearCall(callLinkInfo.callReturnLocation(), CodeLocationLabel(thunkEntryPoints.entryFor(callLinkInfo.argumentsLocation())));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void linkSlowFor(VM* vm, CallLinkInfo&amp; callLinkInfo, ThunkGenerator generator)
</del><ins>+static void linkSlowFor(VM* vm, CallLinkInfo&amp; callLinkInfo, JITCallThunkEntryGenerator generator)
</ins><span class="cx"> {
</span><del>-    linkSlowFor(vm, callLinkInfo, vm-&gt;getCTIStub(generator));
</del><ins>+    linkSlowFor(vm, callLinkInfo, vm-&gt;getJITCallThunkEntryStub(generator));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void linkSlowFor(VM* vm, CallLinkInfo&amp; callLinkInfo)
</span><span class="cx"> {
</span><del>-    MacroAssemblerCodeRef virtualThunk = virtualThunkFor(vm, callLinkInfo);
</del><ins>+    JITJSCallThunkEntryPointsWithRef virtualThunk = virtualThunkFor(vm, callLinkInfo);
</ins><span class="cx">     linkSlowFor(vm, callLinkInfo, virtualThunk);
</span><del>-    callLinkInfo.setSlowStub(createJITStubRoutine(virtualThunk, *vm, nullptr, true));
</del><ins>+    callLinkInfo.setSlowStub(createJITStubRoutine(virtualThunk.codeRef(), *vm, nullptr, true));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static bool isWebAssemblyToJSCallee(VM&amp; vm, JSCell* callee)
</span><span class="lines">@@ -644,7 +644,7 @@
</span><span class="cx">     linkSlowFor(vm, callLinkInfo);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void revertCall(VM* vm, CallLinkInfo&amp; callLinkInfo, MacroAssemblerCodeRef codeRef)
</del><ins>+static void revertCall(VM* vm, CallLinkInfo&amp; callLinkInfo, JITJSCallThunkEntryPointsWithRef codeRef)
</ins><span class="cx"> {
</span><span class="cx">     if (callLinkInfo.isDirect()) {
</span><span class="cx">         callLinkInfo.clearCodeBlock();
</span><span class="lines">@@ -671,7 +671,7 @@
</span><span class="cx">     if (Options::dumpDisassembly())
</span><span class="cx">         dataLog(&quot;Unlinking call at &quot;, callLinkInfo.hotPathOther(), &quot;\n&quot;);
</span><span class="cx">     
</span><del>-    revertCall(&amp;vm, callLinkInfo, vm.getCTIStub(linkCallThunkGenerator));
</del><ins>+    revertCall(&amp;vm, callLinkInfo, vm.getJITCallThunkEntryStub(linkCallThunkGenerator));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void linkVirtualFor(ExecState* exec, CallLinkInfo&amp; callLinkInfo)
</span><span class="lines">@@ -683,9 +683,9 @@
</span><span class="cx">     if (shouldDumpDisassemblyFor(callerCodeBlock))
</span><span class="cx">         dataLog(&quot;Linking virtual call at &quot;, *callerCodeBlock, &quot; &quot;, callerFrame-&gt;codeOrigin(), &quot;\n&quot;);
</span><span class="cx"> 
</span><del>-    MacroAssemblerCodeRef virtualThunk = virtualThunkFor(&amp;vm, callLinkInfo);
</del><ins>+    JITJSCallThunkEntryPointsWithRef virtualThunk = virtualThunkFor(&amp;vm, callLinkInfo);
</ins><span class="cx">     revertCall(&amp;vm, callLinkInfo, virtualThunk);
</span><del>-    callLinkInfo.setSlowStub(createJITStubRoutine(virtualThunk, vm, nullptr, true));
</del><ins>+    callLinkInfo.setSlowStub(createJITStubRoutine(virtualThunk.codeRef(), vm, nullptr, true));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> namespace {
</span><span class="lines">@@ -740,6 +740,7 @@
</span><span class="cx">         callLinkInfo.setHasSeenClosure();
</span><span class="cx">     
</span><span class="cx">     Vector&lt;PolymorphicCallCase&gt; callCases;
</span><ins>+    size_t callerArgumentCount = exec-&gt;argumentCountIncludingThis();
</ins><span class="cx">     
</span><span class="cx">     // Figure out what our cases are.
</span><span class="cx">     for (CallVariant variant : list) {
</span><span class="lines">@@ -751,7 +752,7 @@
</span><span class="cx">             codeBlock = jsCast&lt;FunctionExecutable*&gt;(executable)-&gt;codeBlockForCall();
</span><span class="cx">             // If we cannot handle a callee, either because we don't have a CodeBlock or because arity mismatch,
</span><span class="cx">             // assume that it's better for this whole thing to be a virtual call.
</span><del>-            if (!codeBlock || exec-&gt;argumentCountIncludingThis() &lt; static_cast&lt;size_t&gt;(codeBlock-&gt;numParameters()) || callLinkInfo.isVarargs()) {
</del><ins>+            if (!codeBlock || callerArgumentCount &lt; static_cast&lt;size_t&gt;(codeBlock-&gt;numParameters()) || callLinkInfo.isVarargs()) {
</ins><span class="cx">                 linkVirtualFor(exec, callLinkInfo);
</span><span class="cx">                 return;
</span><span class="cx">             }
</span><span class="lines">@@ -775,7 +776,10 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     GPRReg calleeGPR = static_cast&lt;GPRReg&gt;(callLinkInfo.calleeGPR());
</span><del>-    
</del><ins>+
+    if (callLinkInfo.argumentsInRegisters())
+        ASSERT(calleeGPR == argumentRegisterForCallee());
+
</ins><span class="cx">     CCallHelpers stubJit(&amp;vm, callerCodeBlock);
</span><span class="cx">     
</span><span class="cx">     CCallHelpers::JumpList slowPath;
</span><span class="lines">@@ -797,6 +801,8 @@
</span><span class="cx">         GPRReg scratchGPR;
</span><span class="cx">         if (frameShuffler)
</span><span class="cx">             scratchGPR = frameShuffler-&gt;acquireGPR();
</span><ins>+        else if (callLinkInfo.argumentsInRegisters())
+            scratchGPR = GPRInfo::nonArgGPR0;
</ins><span class="cx">         else
</span><span class="cx">             scratchGPR = AssemblyHelpers::selectScratchGPR(calleeGPR);
</span><span class="cx">         // Verify that we have a function and stash the executable in scratchGPR.
</span><span class="lines">@@ -862,13 +868,23 @@
</span><span class="cx">     GPRReg fastCountsBaseGPR;
</span><span class="cx">     if (frameShuffler)
</span><span class="cx">         fastCountsBaseGPR = frameShuffler-&gt;acquireGPR();
</span><ins>+    else if (callLinkInfo.argumentsInRegisters())
+#if CPU(ARM64)
+        fastCountsBaseGPR = GPRInfo::nonArgGPR1;
+#else
+        fastCountsBaseGPR = GPRInfo::regT0;
+#endif
</ins><span class="cx">     else {
</span><span class="cx">         fastCountsBaseGPR =
</span><span class="cx">             AssemblyHelpers::selectScratchGPR(calleeGPR, comparisonValueGPR, GPRInfo::regT3);
</span><span class="cx">     }
</span><del>-    stubJit.move(CCallHelpers::TrustedImmPtr(fastCounts.get()), fastCountsBaseGPR);
</del><ins>+    if (fastCounts)
+        stubJit.move(CCallHelpers::TrustedImmPtr(fastCounts.get()), fastCountsBaseGPR);
</ins><span class="cx">     if (!frameShuffler &amp;&amp; callLinkInfo.isTailCall())
</span><span class="cx">         stubJit.emitRestoreCalleeSaves();
</span><ins>+
+    incrementCounter(&amp;stubJit, VM::PolymorphicCall);
+
</ins><span class="cx">     BinarySwitch binarySwitch(comparisonValueGPR, caseValues, BinarySwitch::IntPtr);
</span><span class="cx">     CCallHelpers::JumpList done;
</span><span class="cx">     while (binarySwitch.advance(stubJit)) {
</span><span class="lines">@@ -877,8 +893,32 @@
</span><span class="cx">         CallVariant variant = callCases[caseIndex].variant();
</span><span class="cx">         
</span><span class="cx">         ASSERT(variant.executable()-&gt;hasJITCodeForCall());
</span><ins>+
+        EntryPointType entryType = StackArgsArityCheckNotRequired;
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+        if (callLinkInfo.argumentsInRegisters()) {
+            CodeBlock* codeBlock = callCases[caseIndex].codeBlock();
+            if (codeBlock) {
+                size_t calleeArgumentCount = static_cast&lt;size_t&gt;(codeBlock-&gt;numParameters());
+                if (calleeArgumentCount == callerArgumentCount || calleeArgumentCount &gt;= NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS)
+                    entryType = RegisterArgsArityCheckNotRequired;
+                else {
+                    EntryPointType entryForArgCount = JITEntryPoints::registerEntryTypeForArgumentCount(callerArgumentCount);
+                    MacroAssemblerCodePtr codePtr =
+                        variant.executable()-&gt;generatedJITCodeForCall()-&gt;addressForCall(entryForArgCount);
+                    if (codePtr)
+                        entryType = entryForArgCount;
+                    else
+                        entryType = RegisterArgsPossibleExtraArgs;
+                }
+            } else
+                entryType = RegisterArgsPossibleExtraArgs;
+        }
+#endif
+
</ins><span class="cx">         MacroAssemblerCodePtr codePtr =
</span><del>-            variant.executable()-&gt;generatedJITCodeForCall()-&gt;addressForCall(ArityCheckNotRequired);
</del><ins>+            variant.executable()-&gt;generatedJITCodeForCall()-&gt;addressForCall(entryType);
+        ASSERT(codePtr);
</ins><span class="cx">         
</span><span class="cx">         if (fastCounts) {
</span><span class="cx">             stubJit.add32(
</span><span class="lines">@@ -886,7 +926,7 @@
</span><span class="cx">                 CCallHelpers::Address(fastCountsBaseGPR, caseIndex * sizeof(uint32_t)));
</span><span class="cx">         }
</span><span class="cx">         if (frameShuffler) {
</span><del>-            CallFrameShuffler(stubJit, frameShuffler-&gt;snapshot()).prepareForTailCall();
</del><ins>+            CallFrameShuffler(stubJit, frameShuffler-&gt;snapshot(callLinkInfo.argumentsLocation())).prepareForTailCall();
</ins><span class="cx">             calls[caseIndex].call = stubJit.nearTailCall();
</span><span class="cx">         } else if (callLinkInfo.isTailCall()) {
</span><span class="cx">             stubJit.prepareForTailCallSlow();
</span><span class="lines">@@ -907,19 +947,19 @@
</span><span class="cx"> #if USE(JSVALUE32_64)
</span><span class="cx">         frameShuffler-&gt;setCalleeJSValueRegs(JSValueRegs(GPRInfo::regT1, GPRInfo::regT0));
</span><span class="cx"> #else
</span><del>-        frameShuffler-&gt;setCalleeJSValueRegs(JSValueRegs(GPRInfo::regT0));
</del><ins>+        if (callLinkInfo.argumentsLocation() == StackArgs)
+            frameShuffler-&gt;setCalleeJSValueRegs(JSValueRegs(argumentRegisterForCallee()));
</ins><span class="cx"> #endif
</span><span class="cx">         frameShuffler-&gt;prepareForSlowPath();
</span><span class="cx">     } else {
</span><del>-        stubJit.move(calleeGPR, GPRInfo::regT0);
</del><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><span class="cx">     }
</span><del>-    stubJit.move(CCallHelpers::TrustedImmPtr(&amp;callLinkInfo), GPRInfo::regT2);
-    stubJit.move(CCallHelpers::TrustedImmPtr(callLinkInfo.callReturnLocation().executableAddress()), GPRInfo::regT4);
-    
-    stubJit.restoreReturnAddressBeforeReturn(GPRInfo::regT4);
</del><ins>+    stubJit.move(CCallHelpers::TrustedImmPtr(callLinkInfo.callReturnLocation().executableAddress()), GPRInfo::nonArgGPR1);
+    stubJit.restoreReturnAddressBeforeReturn(GPRInfo::nonArgGPR1);
+
+    stubJit.move(CCallHelpers::TrustedImmPtr(&amp;callLinkInfo), GPRInfo::nonArgGPR0);
</ins><span class="cx">     AssemblyHelpers::Jump slow = stubJit.jump();
</span><span class="cx">         
</span><span class="cx">     LinkBuffer patchBuffer(vm, stubJit, owner, JITCompilationCanFail);
</span><span class="lines">@@ -940,7 +980,7 @@
</span><span class="cx">         patchBuffer.link(done, callLinkInfo.callReturnLocation().labelAtOffset(0));
</span><span class="cx">     else
</span><span class="cx">         patchBuffer.link(done, callLinkInfo.hotPathOther().labelAtOffset(0));
</span><del>-    patchBuffer.link(slow, CodeLocationLabel(vm.getCTIStub(linkPolymorphicCallThunkGenerator).code()));
</del><ins>+    patchBuffer.link(slow, CodeLocationLabel(vm.getJITCallThunkEntryStub(linkPolymorphicCallThunkGenerator).entryFor(callLinkInfo.argumentsLocation())));
</ins><span class="cx">     
</span><span class="cx">     auto stubRoutine = adoptRef(*new PolymorphicCallStubRoutine(
</span><span class="cx">         FINALIZE_CODE_FOR(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitSpecializedThunkJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/SpecializedThunkJIT.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/SpecializedThunkJIT.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/SpecializedThunkJIT.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;JIT.h&quot;
</span><ins>+#include &quot;JITEntryPoints.h&quot;
</ins><span class="cx"> #include &quot;JITInlines.h&quot;
</span><span class="cx"> #include &quot;JSInterfaceJIT.h&quot;
</span><span class="cx"> #include &quot;LinkBuffer.h&quot;
</span><span class="lines">@@ -37,18 +38,43 @@
</span><span class="cx">     class SpecializedThunkJIT : public JSInterfaceJIT {
</span><span class="cx">     public:
</span><span class="cx">         static const int ThisArgument = -1;
</span><del>-        SpecializedThunkJIT(VM* vm, int expectedArgCount)
</del><ins>+        enum ArgLocation { OnStack, InRegisters };
+
+        SpecializedThunkJIT(VM* vm, int expectedArgCount, AssemblyHelpers::SpillRegisterType spillType = AssemblyHelpers::SpillExactly, ArgLocation argLocation = OnStack)
</ins><span class="cx">             : JSInterfaceJIT(vm)
</span><span class="cx">         {
</span><del>-            emitFunctionPrologue();
-            emitSaveThenMaterializeTagRegisters();
-            // Check that we have the expected number of arguments
-            m_failures.append(branch32(NotEqual, payloadFor(CallFrameSlot::argumentCount), TrustedImm32(expectedArgCount + 1)));
</del><ins>+#if !NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+            UNUSED_PARAM(spillType);
+            UNUSED_PARAM(argLocation);
+#else
+            if (argLocation == InRegisters) {
+                m_stackArgumentsEntry = label();
+                fillArgumentRegistersFromFrameBeforePrologue();
+                m_registerArgumentsEntry = label();
+                emitFunctionPrologue();
+                emitSaveThenMaterializeTagRegisters();
+                // Check that we have the expected number of arguments
+                m_failures.append(branch32(NotEqual, argumentRegisterForArgumentCount(), TrustedImm32(expectedArgCount + 1)));
+            } else {
+                spillArgumentRegistersToFrameBeforePrologue(expectedArgCount + 1, spillType);
+                m_stackArgumentsEntry = label();
+#endif
+                emitFunctionPrologue();
+                emitSaveThenMaterializeTagRegisters();
+                // Check that we have the expected number of arguments
+                m_failures.append(branch32(NotEqual, payloadFor(CallFrameSlot::argumentCount), TrustedImm32(expectedArgCount + 1)));
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+                }
+#endif
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         explicit SpecializedThunkJIT(VM* vm)
</span><span class="cx">             : JSInterfaceJIT(vm)
</span><span class="cx">         {
</span><ins>+#if USE(JSVALUE64)
+            spillArgumentRegistersToFrameBeforePrologue();
+            m_stackArgumentsEntry = Label();
+#endif
</ins><span class="cx">             emitFunctionPrologue();
</span><span class="cx">             emitSaveThenMaterializeTagRegisters();
</span><span class="cx">         }
</span><span class="lines">@@ -94,11 +120,26 @@
</span><span class="cx">             loadInt32Argument(argument, dst, conversionFailed);
</span><span class="cx">             m_failures.append(conversionFailed);
</span><span class="cx">         }
</span><ins>+
+        void checkJSStringArgument(VM&amp; vm, RegisterID argument)
+        {
+            m_failures.append(emitJumpIfNotJSCell(argument));
+            m_failures.append(branchStructure(NotEqual,
+                Address(argument, JSCell::structureIDOffset()),
+                vm.stringStructure.get()));
+        }
</ins><span class="cx">         
</span><span class="cx">         void appendFailure(const Jump&amp; failure)
</span><span class="cx">         {
</span><span class="cx">             m_failures.append(failure);
</span><span class="cx">         }
</span><ins>+
+        void linkFailureHere()
+        {
+            m_failures.link(this);
+            m_failures.clear();
+        }
+
</ins><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">         void returnJSValue(RegisterID src)
</span><span class="cx">         {
</span><span class="lines">@@ -164,13 +205,29 @@
</span><span class="cx">             ret();
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        MacroAssemblerCodeRef finalize(MacroAssemblerCodePtr fallback, const char* thunkKind)
</del><ins>+        JITEntryPointsWithRef finalize(MacroAssemblerCodePtr fallback, const char* thunkKind)
</ins><span class="cx">         {
</span><span class="cx">             LinkBuffer patchBuffer(*m_vm, *this, GLOBAL_THUNK_ID);
</span><span class="cx">             patchBuffer.link(m_failures, CodeLocationLabel(fallback));
</span><span class="cx">             for (unsigned i = 0; i &lt; m_calls.size(); i++)
</span><span class="cx">                 patchBuffer.link(m_calls[i].first, m_calls[i].second);
</span><del>-            return FINALIZE_CODE(patchBuffer, (&quot;Specialized thunk for %s&quot;, thunkKind));
</del><ins>+
+            MacroAssemblerCodePtr stackEntry;
+            if (m_stackArgumentsEntry.isSet())
+                stackEntry = patchBuffer.locationOf(m_stackArgumentsEntry);
+            MacroAssemblerCodePtr registerEntry;
+            if (m_registerArgumentsEntry.isSet())
+                registerEntry = patchBuffer.locationOf(m_registerArgumentsEntry);
+
+            MacroAssemblerCodeRef entry = FINALIZE_CODE(patchBuffer, (&quot;Specialized thunk for %s&quot;, thunkKind));
+
+            if (m_stackArgumentsEntry.isSet()) {
+                if (m_registerArgumentsEntry.isSet())
+                    return JITEntryPointsWithRef(entry, registerEntry, registerEntry, registerEntry, stackEntry, stackEntry);
+                return JITEntryPointsWithRef(entry, entry.code(), entry.code(), entry.code(), stackEntry, stackEntry);
+            }
+
+            return JITEntryPointsWithRef(entry, entry.code(), entry.code());
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Assumes that the target function uses fpRegister0 as the first argument
</span><span class="lines">@@ -207,6 +264,8 @@
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         MacroAssembler::JumpList m_failures;
</span><ins>+        MacroAssembler::Label m_registerArgumentsEntry;
+        MacroAssembler::Label m_stackArgumentsEntry;
</ins><span class="cx">         Vector&lt;std::pair&lt;Call, FunctionPtr&gt;&gt; m_calls;
</span><span class="cx">     };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitThunkGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ThunkGenerator.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerator.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerator.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -30,8 +30,12 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> class VM;
</span><span class="cx"> class MacroAssemblerCodeRef;
</span><ins>+class JITEntryPointsWithRef;
+class JITJSCallThunkEntryPointsWithRef;
</ins><span class="cx"> 
</span><span class="cx"> typedef MacroAssemblerCodeRef (*ThunkGenerator)(VM*);
</span><ins>+typedef JITEntryPointsWithRef (*JITEntryGenerator)(VM*);
+typedef JITJSCallThunkEntryPointsWithRef (*JITCallThunkEntryGenerator)(VM*);
</ins><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitThunkGeneratorscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -77,6 +77,23 @@
</span><span class="cx">     return FINALIZE_CODE(patchBuffer, (&quot;Throw exception from call slow path thunk&quot;));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void createRegisterArgumentsSpillEntry(CCallHelpers&amp; jit, MacroAssembler::Label entryPoints[ThunkEntryPointTypeCount])
+{
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    for (unsigned argIndex = NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argIndex-- &gt; 0;) {
+        entryPoints[thunkEntryPointTypeFor(argIndex + 1)] = jit.label();
+        jit.emitPutArgumentToCallFrameBeforePrologue(argumentRegisterForFunctionArgument(argIndex), argIndex);
+    }
+
+    jit.emitPutToCallFrameHeaderBeforePrologue(argumentRegisterForCallee(), CallFrameSlot::callee);
+    jit.emitPutToCallFrameHeaderBeforePrologue(argumentRegisterForArgumentCount(), CallFrameSlot::argumentCount);
+#else
+    UNUSED_PARAM(jit);
+    UNUSED_PARAM(entryPoints);
+#endif
+    entryPoints[StackArgs] = jit.label();
+}
+
</ins><span class="cx"> static void slowPathFor(
</span><span class="cx">     CCallHelpers&amp; jit, VM* vm, Sprt_JITOperation_ECli slowPathFunction)
</span><span class="cx"> {
</span><span class="lines">@@ -88,7 +105,7 @@
</span><span class="cx">     // Moving the stack down maxFrameExtentForSlowPathCall bytes gives us room for our 3 arguments
</span><span class="cx">     // and space for the 16 byte return area.
</span><span class="cx">     jit.addPtr(CCallHelpers::TrustedImm32(-maxFrameExtentForSlowPathCall), CCallHelpers::stackPointerRegister);
</span><del>-    jit.move(GPRInfo::regT2, GPRInfo::argumentGPR2);
</del><ins>+    jit.move(GPRInfo::nonArgGPR0, GPRInfo::argumentGPR2);
</ins><span class="cx">     jit.addPtr(CCallHelpers::TrustedImm32(32), CCallHelpers::stackPointerRegister, GPRInfo::argumentGPR0);
</span><span class="cx">     jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
</span><span class="cx">     jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast&lt;void*&gt;(slowPathFunction)), GPRInfo::nonArgGPR0);
</span><span class="lines">@@ -100,7 +117,7 @@
</span><span class="cx"> #else
</span><span class="cx">     if (maxFrameExtentForSlowPathCall)
</span><span class="cx">         jit.addPtr(CCallHelpers::TrustedImm32(-maxFrameExtentForSlowPathCall), CCallHelpers::stackPointerRegister);
</span><del>-    jit.setupArgumentsWithExecState(GPRInfo::regT2);
</del><ins>+    jit.setupArgumentsWithExecState(GPRInfo::nonArgGPR0);
</ins><span class="cx">     jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast&lt;void*&gt;(slowPathFunction)), GPRInfo::nonArgGPR0);
</span><span class="cx">     emitPointerValidation(jit, GPRInfo::nonArgGPR0);
</span><span class="cx">     jit.call(GPRInfo::nonArgGPR0);
</span><span class="lines">@@ -127,7 +144,7 @@
</span><span class="cx">     jit.jump(GPRInfo::returnValueGPR);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef linkCallThunkGenerator(VM* vm)
</del><ins>+JITJSCallThunkEntryPointsWithRef linkCallThunkGenerator(VM* vm)
</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">@@ -135,23 +152,115 @@
</span><span class="cx">     // to be in regT0/regT1 (payload/tag), the CallFrame to have already
</span><span class="cx">     // been adjusted, and all other registers to be available for use.
</span><span class="cx">     CCallHelpers jit(vm);
</span><del>-    
</del><ins>+
+    MacroAssembler::Label entryPoints[ThunkEntryPointTypeCount];
+
+    createRegisterArgumentsSpillEntry(jit, entryPoints);
</ins><span class="cx">     slowPathFor(jit, vm, operationLinkCall);
</span><span class="cx">     
</span><span class="cx">     LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
</span><del>-    return FINALIZE_CODE(patchBuffer, (&quot;Link call slow path thunk&quot;));
</del><ins>+    MacroAssemblerCodeRef codeRef FINALIZE_CODE(patchBuffer, (&quot;Link call slow path thunk&quot;));
+    JITJSCallThunkEntryPointsWithRef callEntryPoints = JITJSCallThunkEntryPointsWithRef(codeRef);
+
+    for (unsigned entryIndex = StackArgs; entryIndex &lt;  ThunkEntryPointTypeCount; entryIndex++) {
+        callEntryPoints.setEntryFor(static_cast&lt;ThunkEntryPointType&gt;(entryIndex),
+            patchBuffer.locationOf(entryPoints[entryIndex]));
+    }
+
+    return callEntryPoints;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JITJSCallThunkEntryPointsWithRef linkDirectCallThunkGenerator(VM* vm)
+{
+    // The return address is on the stack or in the link register. We will hence
+    // save the return address to the call frame while we make a C++ function call
+    // to perform linking and lazy compilation if necessary. We expect the CallLinkInfo
+    // to be in GPRInfo::nonArgGPR0, the callee to be in argumentRegisterForCallee(),
+    // the CallFrame to have already been adjusted, and arguments in argument registers
+    // and/or in the stack as appropriate.
+    CCallHelpers jit(vm);
+    
+    MacroAssembler::Label entryPoints[ThunkEntryPointTypeCount];
+
+    createRegisterArgumentsSpillEntry(jit, entryPoints);
+
+    jit.move(GPRInfo::callFrameRegister, GPRInfo::nonArgGPR1); // Save callee's frame pointer
+    jit.emitFunctionPrologue();
+    jit.storePtr(GPRInfo::callFrameRegister, &amp;vm-&gt;topCallFrame);
+
+    if (maxFrameExtentForSlowPathCall)
+        jit.addPtr(CCallHelpers::TrustedImm32(-maxFrameExtentForSlowPathCall), CCallHelpers::stackPointerRegister);
+    jit.setupArguments(GPRInfo::nonArgGPR1, GPRInfo::nonArgGPR0, argumentRegisterForCallee());
+    jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast&lt;void*&gt;(operationLinkDirectCall)), GPRInfo::nonArgGPR0);
+    emitPointerValidation(jit, GPRInfo::nonArgGPR0);
+    jit.call(GPRInfo::nonArgGPR0);
+    if (maxFrameExtentForSlowPathCall)
+        jit.addPtr(CCallHelpers::TrustedImm32(maxFrameExtentForSlowPathCall), CCallHelpers::stackPointerRegister);
+    
+    jit.emitFunctionEpilogue();
+
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    jit.emitGetFromCallFrameHeaderBeforePrologue(CallFrameSlot::callee, argumentRegisterForCallee());
+    GPRReg argCountReg = argumentRegisterForArgumentCount();
+    jit.emitGetPayloadFromCallFrameHeaderBeforePrologue(CallFrameSlot::argumentCount, argCountReg);
+
+    // load &quot;this&quot;
+    jit.emitGetFromCallFrameArgumentBeforePrologue(0, argumentRegisterForFunctionArgument(0));
+
+    CCallHelpers::Jump fillUndefined[NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS];
+    
+    for (unsigned argIndex = 1; argIndex &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argIndex++) {
+        fillUndefined[argIndex] = jit.branch32(MacroAssembler::BelowOrEqual, argCountReg, MacroAssembler::TrustedImm32(argIndex));
+        jit.emitGetFromCallFrameArgumentBeforePrologue(argIndex, argumentRegisterForFunctionArgument(argIndex));
+    }
+
+    CCallHelpers::Jump doneFilling = jit.jump();
+
+    for (unsigned argIndex = 1; argIndex &lt; NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS; argIndex++) {
+        fillUndefined[argIndex].link(&amp;jit);
+        jit.move(CCallHelpers::TrustedImm64(JSValue::encode(jsUndefined())), argumentRegisterForFunctionArgument(argIndex));
+    }
+
+    doneFilling.link(&amp;jit);
+#endif
+
+
+    jit.ret();
+
+    LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
+    MacroAssemblerCodeRef codeRef FINALIZE_CODE(patchBuffer, (&quot;Link direct call thunk&quot;));
+    JITJSCallThunkEntryPointsWithRef callEntryPoints = JITJSCallThunkEntryPointsWithRef(codeRef);
+    
+    for (unsigned entryIndex = StackArgs; entryIndex &lt;  ThunkEntryPointTypeCount; entryIndex++) {
+        callEntryPoints.setEntryFor(static_cast&lt;ThunkEntryPointType&gt;(entryIndex),
+            patchBuffer.locationOf(entryPoints[entryIndex]));
+    }
+    
+    return callEntryPoints;
+}
+
</ins><span class="cx"> // For closure optimizations, we only include calls, since if you're using closures for
</span><span class="cx"> // object construction then you're going to lose big time anyway.
</span><del>-MacroAssemblerCodeRef linkPolymorphicCallThunkGenerator(VM* vm)
</del><ins>+JITJSCallThunkEntryPointsWithRef linkPolymorphicCallThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><span class="cx">     CCallHelpers jit(vm);
</span><span class="cx">     
</span><ins>+    MacroAssembler::Label entryPoints[ThunkEntryPointTypeCount];
+
+    createRegisterArgumentsSpillEntry(jit, entryPoints);
+
</ins><span class="cx">     slowPathFor(jit, vm, operationLinkPolymorphicCall);
</span><span class="cx">     
</span><span class="cx">     LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
</span><del>-    return FINALIZE_CODE(patchBuffer, (&quot;Link polymorphic call slow path thunk&quot;));
</del><ins>+    MacroAssemblerCodeRef codeRef FINALIZE_CODE(patchBuffer, (&quot;Link polymorphic call slow path thunk&quot;));
+    JITJSCallThunkEntryPointsWithRef callEntryPoints = JITJSCallThunkEntryPointsWithRef(codeRef);
+    
+    for (unsigned entryIndex = StackArgs; entryIndex &lt;  ThunkEntryPointTypeCount; entryIndex++) {
+        callEntryPoints.setEntryFor(static_cast&lt;ThunkEntryPointType&gt;(entryIndex),
+            patchBuffer.locationOf(entryPoints[entryIndex]));
+    }
+    
+    return callEntryPoints;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // FIXME: We should distinguish between a megamorphic virtual call vs. a slow
</span><span class="lines">@@ -158,22 +267,38 @@
</span><span class="cx"> // path virtual call so that we can enable fast tail calls for megamorphic
</span><span class="cx"> // virtual calls by using the shuffler.
</span><span class="cx"> // https://bugs.webkit.org/show_bug.cgi?id=148831
</span><del>-MacroAssemblerCodeRef virtualThunkFor(VM* vm, CallLinkInfo&amp; callLinkInfo)
</del><ins>+JITJSCallThunkEntryPointsWithRef virtualThunkFor(VM* vm, CallLinkInfo&amp; callLinkInfo)
</ins><span class="cx"> {
</span><del>-    // The callee is in regT0 (for JSVALUE32_64, the tag is in regT1).
-    // The return address is on the stack, or in the link register. We will hence
-    // jump to the callee, or save the return address to the call frame while we
-    // make a C++ function call to the appropriate JIT operation.
</del><ins>+    // The callee is in argumentRegisterForCallee() (for JSVALUE32_64, it is in regT1:regT0).
+    // The CallLinkInfo is in GPRInfo::nonArgGPR0.
+    // The return address is on the stack, or in the link register.
+    /// We will hence jump to the callee, or save the return address to the call
+    // frame while we make a C++ function call to the appropriate JIT operation.
</ins><span class="cx"> 
</span><span class="cx">     CCallHelpers jit(vm);
</span><span class="cx">     
</span><span class="cx">     CCallHelpers::JumpList slowCase;
</span><del>-    
-    // This is a slow path execution, and regT2 contains the CallLinkInfo. Count the
-    // slow path execution for the profiler.
</del><ins>+
+    GPRReg calleeReg = argumentRegisterForCallee();
+#if USE(JSVALUE32_64)
+    GPRReg calleeTagReg = GPRInfo::regT1;
+#endif
+    GPRReg targetReg = GPRInfo::nonArgGPR1;
+    // This is the CallLinkInfo* on entry and used later as a temp.
+    GPRReg callLinkInfoAndTempReg = GPRInfo::nonArgGPR0;
+
+    jit.fillArgumentRegistersFromFrameBeforePrologue();
+
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    MacroAssembler::Label registerEntry = jit.label();
+#endif
+
+    incrementCounter(&amp;jit, VM::VirtualCall);
+
+    // This is a slow path execution. Count the slow path execution for the profiler.
</ins><span class="cx">     jit.add32(
</span><span class="cx">         CCallHelpers::TrustedImm32(1),
</span><del>-        CCallHelpers::Address(GPRInfo::regT2, CallLinkInfo::offsetOfSlowPathCount()));
</del><ins>+        CCallHelpers::Address(callLinkInfoAndTempReg, CallLinkInfo::offsetOfSlowPathCount()));
</ins><span class="cx"> 
</span><span class="cx">     // FIXME: we should have a story for eliminating these checks. In many cases,
</span><span class="cx">     // the DFG knows that the value is definitely a cell, or definitely a function.
</span><span class="lines">@@ -181,54 +306,72 @@
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">     slowCase.append(
</span><span class="cx">         jit.branchTest64(
</span><del>-            CCallHelpers::NonZero, GPRInfo::regT0, GPRInfo::tagMaskRegister));
</del><ins>+            CCallHelpers::NonZero, calleeReg, GPRInfo::tagMaskRegister));
</ins><span class="cx"> #else
</span><span class="cx">     slowCase.append(
</span><span class="cx">         jit.branch32(
</span><del>-            CCallHelpers::NotEqual, GPRInfo::regT1,
</del><ins>+            CCallHelpers::NotEqual, calleeTagReg,
</ins><span class="cx">             CCallHelpers::TrustedImm32(JSValue::CellTag)));
</span><span class="cx"> #endif
</span><del>-    slowCase.append(jit.branchIfNotType(GPRInfo::regT0, JSFunctionType));
</del><ins>+    slowCase.append(jit.branchIfNotType(calleeReg, JSFunctionType));
</ins><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><del>-        CCallHelpers::Address(GPRInfo::regT0, JSFunction::offsetOfExecutable()),
-        GPRInfo::regT4);
</del><ins>+        CCallHelpers::Address(calleeReg, JSFunction::offsetOfExecutable()),
+        targetReg);
+    
+    ArgumentsLocation argumentsLocation = callLinkInfo.isTailCall() ? StackArgs : callLinkInfo.argumentsLocation();
+
</ins><span class="cx">     jit.loadPtr(
</span><span class="cx">         CCallHelpers::Address(
</span><del>-            GPRInfo::regT4, ExecutableBase::offsetOfJITCodeWithArityCheckFor(
-                callLinkInfo.specializationKind())),
-        GPRInfo::regT4);
-    slowCase.append(jit.branchTestPtr(CCallHelpers::Zero, GPRInfo::regT4));
</del><ins>+            targetReg, ExecutableBase::offsetOfEntryFor(
+                callLinkInfo.specializationKind(),
+                entryPointTypeFor(argumentsLocation))),
+        targetReg);
+    slowCase.append(jit.branchTestPtr(CCallHelpers::Zero, targetReg));
</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="cx">     
</span><span class="cx">     // Make a tail call. This will return back to JIT code.
</span><del>-    emitPointerValidation(jit, GPRInfo::regT4);
</del><ins>+    emitPointerValidation(jit, targetReg);
</ins><span class="cx">     if (callLinkInfo.isTailCall()) {
</span><del>-        jit.preserveReturnAddressAfterCall(GPRInfo::regT0);
-        jit.prepareForTailCallSlow(GPRInfo::regT4);
</del><ins>+        jit.spillArgumentRegistersToFrameBeforePrologue();
+        jit.preserveReturnAddressAfterCall(callLinkInfoAndTempReg);
+        jit.prepareForTailCallSlow(targetReg);
</ins><span class="cx">     }
</span><del>-    jit.jump(GPRInfo::regT4);
</del><ins>+    jit.jump(targetReg);
+    slowCase.link(&amp;jit);
</ins><span class="cx"> 
</span><del>-    slowCase.link(&amp;jit);
-    
</del><ins>+    incrementCounter(&amp;jit, VM::VirtualSlowCall);
+
</ins><span class="cx">     // Here we don't know anything, so revert to the full slow path.
</span><ins>+    jit.spillArgumentRegistersToFrameBeforePrologue();
</ins><span class="cx">     
</span><span class="cx">     slowPathFor(jit, vm, operationVirtualCall);
</span><span class="cx">     
</span><span class="cx">     LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
</span><del>-    return FINALIZE_CODE(
-        patchBuffer,
</del><ins>+    MacroAssemblerCodeRef codeRef FINALIZE_CODE(patchBuffer,
</ins><span class="cx">         (&quot;Virtual %s slow path thunk&quot;,
</span><span class="cx">         callLinkInfo.callMode() == CallMode::Regular ? &quot;call&quot; : callLinkInfo.callMode() == CallMode::Tail ? &quot;tail call&quot; : &quot;construct&quot;));
</span><ins>+    JITJSCallThunkEntryPointsWithRef callEntryPoints = JITJSCallThunkEntryPointsWithRef(codeRef);
+
+    callEntryPoints.setEntryFor(StackArgsEntry, codeRef.code());
+
+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    MacroAssemblerCodePtr registerEntryPtr = patchBuffer.locationOf(registerEntry);
+
+    for (unsigned entryIndex = Register1ArgEntry; entryIndex &lt;  ThunkEntryPointTypeCount; entryIndex++)
+        callEntryPoints.setEntryFor(static_cast&lt;ThunkEntryPointType&gt;(entryIndex), registerEntryPtr);
+#endif
+
+    return callEntryPoints;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> enum ThunkEntryType { EnterViaCall, EnterViaJumpWithSavedTags, EnterViaJumpWithoutSavedTags };
</span><span class="cx"> 
</span><del>-static MacroAssemblerCodeRef nativeForGenerator(VM* vm, CodeSpecializationKind kind, ThunkEntryType entryType = EnterViaCall)
</del><ins>+static JITEntryPointsWithRef nativeForGenerator(VM* vm, CodeSpecializationKind kind, ThunkEntryType entryType = EnterViaCall)
</ins><span class="cx"> {
</span><span class="cx">     // FIXME: This should be able to log ShadowChicken prologue packets.
</span><span class="cx">     // https://bugs.webkit.org/show_bug.cgi?id=155689
</span><span class="lines">@@ -237,8 +380,14 @@
</span><span class="cx">     
</span><span class="cx">     JSInterfaceJIT jit(vm);
</span><span class="cx"> 
</span><ins>+    MacroAssembler::Label stackArgsEntry;
+
</ins><span class="cx">     switch (entryType) {
</span><span class="cx">     case EnterViaCall:
</span><ins>+        jit.spillArgumentRegistersToFrameBeforePrologue();
+
+        stackArgsEntry = jit.label();
+
</ins><span class="cx">         jit.emitFunctionPrologue();
</span><span class="cx">         break;
</span><span class="cx">     case EnterViaJumpWithSavedTags:
</span><span class="lines">@@ -379,10 +528,18 @@
</span><span class="cx">     jit.jumpToExceptionHandler();
</span><span class="cx"> 
</span><span class="cx">     LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
</span><del>-    return FINALIZE_CODE(patchBuffer, (&quot;native %s%s trampoline&quot;, entryType == EnterViaJumpWithSavedTags ? &quot;Tail With Saved Tags &quot; : entryType == EnterViaJumpWithoutSavedTags ? &quot;Tail Without Saved Tags &quot; : &quot;&quot;, toCString(kind).data()));
</del><ins>+    MacroAssemblerCodeRef codeRef FINALIZE_CODE(patchBuffer, (&quot;native %s%s trampoline&quot;, entryType == EnterViaJumpWithSavedTags ? &quot;Tail With Saved Tags &quot; : entryType == EnterViaJumpWithoutSavedTags ? &quot;Tail Without Saved Tags &quot; : &quot;&quot;, toCString(kind).data()));
+    if (entryType == EnterViaCall) {
+        MacroAssemblerCodePtr stackEntryPtr = patchBuffer.locationOf(stackArgsEntry);
+
+        return JITEntryPointsWithRef(codeRef, codeRef.code(), codeRef.code(), codeRef.code(), stackEntryPtr, stackEntryPtr);
+    }
+
+    return JITEntryPointsWithRef(codeRef, codeRef.code(), codeRef.code());
+
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef nativeCallGenerator(VM* vm)
</del><ins>+JITEntryPointsWithRef nativeCallGenerator(VM* vm)
</ins><span class="cx"> {
</span><span class="cx">     return nativeForGenerator(vm, CodeForCall);
</span><span class="cx"> }
</span><span class="lines">@@ -389,15 +546,15 @@
</span><span class="cx"> 
</span><span class="cx"> MacroAssemblerCodeRef nativeTailCallGenerator(VM* vm)
</span><span class="cx"> {
</span><del>-    return nativeForGenerator(vm, CodeForCall, EnterViaJumpWithSavedTags);
</del><ins>+    return nativeForGenerator(vm, CodeForCall, EnterViaJumpWithSavedTags).codeRef();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MacroAssemblerCodeRef nativeTailCallWithoutSavedTagsGenerator(VM* vm)
</span><span class="cx"> {
</span><del>-    return nativeForGenerator(vm, CodeForCall, EnterViaJumpWithoutSavedTags);
</del><ins>+    return nativeForGenerator(vm, CodeForCall, EnterViaJumpWithoutSavedTags).codeRef();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef nativeConstructGenerator(VM* vm)
</del><ins>+JITEntryPointsWithRef nativeConstructGenerator(VM* vm)
</ins><span class="cx"> {
</span><span class="cx">     return nativeForGenerator(vm, CodeForConstruct);
</span><span class="cx"> }
</span><span class="lines">@@ -536,6 +693,43 @@
</span><span class="cx">     return FINALIZE_CODE(patchBuffer, (&quot;unreachable thunk&quot;));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+static void stringCharLoadRegCall(SpecializedThunkJIT&amp; jit, VM* vm)
+{
+    // load string
+    GPRReg thisReg = argumentRegisterForFunctionArgument(0);
+    GPRReg indexReg = argumentRegisterForFunctionArgument(2);
+    GPRReg lengthReg = argumentRegisterForFunctionArgument(3);
+    GPRReg tempReg = SpecializedThunkJIT::nonArgGPR0;
+
+    jit.checkJSStringArgument(*vm, thisReg);
+
+    // Load string length to regT2, and start the process of loading the data pointer into regT0
+    jit.load32(MacroAssembler::Address(thisReg, ThunkHelpers::jsStringLengthOffset()), lengthReg);
+    jit.loadPtr(MacroAssembler::Address(thisReg, ThunkHelpers::jsStringValueOffset()), tempReg);
+    jit.appendFailure(jit.branchTest32(MacroAssembler::Zero, tempReg));
+
+    // load index
+    jit.move(argumentRegisterForFunctionArgument(1), indexReg);
+    jit.appendFailure(jit.emitJumpIfNotInt32(indexReg));
+
+    // Do an unsigned compare to simultaneously filter negative indices as well as indices that are too large
+    jit.appendFailure(jit.branch32(MacroAssembler::AboveOrEqual, indexReg, lengthReg));
+
+    // Load the character
+    SpecializedThunkJIT::JumpList is16Bit;
+    SpecializedThunkJIT::JumpList cont8Bit;
+    // Load the string flags
+    jit.loadPtr(MacroAssembler::Address(tempReg, StringImpl::flagsOffset()), lengthReg);
+    jit.loadPtr(MacroAssembler::Address(tempReg, StringImpl::dataOffset()), tempReg);
+    is16Bit.append(jit.branchTest32(MacroAssembler::Zero, lengthReg, MacroAssembler::TrustedImm32(StringImpl::flagIs8Bit())));
+    jit.load8(MacroAssembler::BaseIndex(tempReg, indexReg, MacroAssembler::TimesOne, 0), tempReg);
+    cont8Bit.append(jit.jump());
+    is16Bit.link(&amp;jit);
+    jit.load16(MacroAssembler::BaseIndex(tempReg, indexReg, MacroAssembler::TimesTwo, 0), tempReg);
+    cont8Bit.link(&amp;jit);
+}
+#else
</ins><span class="cx"> static void stringCharLoad(SpecializedThunkJIT&amp; jit, VM* vm)
</span><span class="cx"> {
</span><span class="cx">     // load string
</span><span class="lines">@@ -565,6 +759,7 @@
</span><span class="cx">     jit.load16(MacroAssembler::BaseIndex(SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1, MacroAssembler::TimesTwo, 0), SpecializedThunkJIT::regT0);
</span><span class="cx">     cont8Bit.link(&amp;jit);
</span><span class="cx"> }
</span><ins>+#endif
</ins><span class="cx"> 
</span><span class="cx"> static void charToString(SpecializedThunkJIT&amp; jit, VM* vm, MacroAssembler::RegisterID src, MacroAssembler::RegisterID dst, MacroAssembler::RegisterID scratch)
</span><span class="cx"> {
</span><span class="lines">@@ -574,34 +769,69 @@
</span><span class="cx">     jit.appendFailure(jit.branchTestPtr(MacroAssembler::Zero, dst));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef charCodeAtThunkGenerator(VM* vm)
</del><ins>+JITEntryPointsWithRef charCodeAtThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><ins>+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    SpecializedThunkJIT jit(vm, 1, AssemblyHelpers::SpillExactly, SpecializedThunkJIT::InRegisters);
+    stringCharLoadRegCall(jit, vm);
+    jit.returnInt32(SpecializedThunkJIT::nonArgGPR0);
+    jit.linkFailureHere();
+    jit.spillArgumentRegistersToFrame(2, AssemblyHelpers::SpillExactly);
+    jit.appendFailure(jit.jump());
+    return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;charCodeAt&quot;);
+#else
</ins><span class="cx">     SpecializedThunkJIT jit(vm, 1);
</span><span class="cx">     stringCharLoad(jit, vm);
</span><span class="cx">     jit.returnInt32(SpecializedThunkJIT::regT0);
</span><span class="cx">     return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;charCodeAt&quot;);
</span><ins>+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef charAtThunkGenerator(VM* vm)
</del><ins>+JITEntryPointsWithRef charAtThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><ins>+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    SpecializedThunkJIT jit(vm, 1, AssemblyHelpers::SpillExactly, SpecializedThunkJIT::InRegisters);
+    stringCharLoadRegCall(jit, vm);
+    charToString(jit, vm, SpecializedThunkJIT::nonArgGPR0, SpecializedThunkJIT::returnValueGPR, argumentRegisterForFunctionArgument(3));
+    jit.returnJSCell(SpecializedThunkJIT::returnValueGPR);
+    jit.linkFailureHere();
+    jit.spillArgumentRegistersToFrame(2, AssemblyHelpers::SpillExactly);
+    jit.appendFailure(jit.jump());
+    return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;charAt&quot;);
+#else
</ins><span class="cx">     SpecializedThunkJIT jit(vm, 1);
</span><span class="cx">     stringCharLoad(jit, vm);
</span><span class="cx">     charToString(jit, vm, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1);
</span><span class="cx">     jit.returnJSCell(SpecializedThunkJIT::regT0);
</span><span class="cx">     return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;charAt&quot;);
</span><ins>+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef fromCharCodeThunkGenerator(VM* vm)
</del><ins>+JITEntryPointsWithRef fromCharCodeThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><del>-    SpecializedThunkJIT jit(vm, 1);
</del><ins>+#if NUMBER_OF_JS_FUNCTION_ARGUMENT_REGISTERS
+    SpecializedThunkJIT jit(vm, 1, AssemblyHelpers::SpillExactly, SpecializedThunkJIT::InRegisters);
</ins><span class="cx">     // load char code
</span><ins>+    jit.move(argumentRegisterForFunctionArgument(1), SpecializedThunkJIT::nonArgGPR0);
+    jit.appendFailure(jit.emitJumpIfNotInt32(SpecializedThunkJIT::nonArgGPR0));
+
+    charToString(jit, vm, SpecializedThunkJIT::nonArgGPR0, SpecializedThunkJIT::returnValueGPR, argumentRegisterForFunctionArgument(3));
+    jit.returnJSCell(SpecializedThunkJIT::returnValueGPR);
+    jit.linkFailureHere();
+    jit.spillArgumentRegistersToFrame(2, AssemblyHelpers::SpillAll);
+    jit.appendFailure(jit.jump());
+    return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;fromCharCode&quot;);
+#else
+    SpecializedThunkJIT jit(vm, 1, AssemblyHelpers::SpillAll);
+    // load char code
</ins><span class="cx">     jit.loadInt32Argument(0, SpecializedThunkJIT::regT0);
</span><span class="cx">     charToString(jit, vm, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1);
</span><span class="cx">     jit.returnJSCell(SpecializedThunkJIT::regT0);
</span><span class="cx">     return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;fromCharCode&quot;);
</span><ins>+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef clz32ThunkGenerator(VM* vm)
</del><ins>+JITEntryPointsWithRef clz32ThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><span class="cx">     SpecializedThunkJIT jit(vm, 1);
</span><span class="cx">     MacroAssembler::Jump nonIntArgJump;
</span><span class="lines">@@ -622,11 +852,11 @@
</span><span class="cx">     return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;clz32&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef sqrtThunkGenerator(VM* vm)
</del><ins>+JITEntryPointsWithRef sqrtThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><span class="cx">     SpecializedThunkJIT jit(vm, 1);
</span><span class="cx">     if (!jit.supportsFloatingPointSqrt())
</span><del>-        return MacroAssemblerCodeRef::createSelfManagedCodeRef(vm-&gt;jitStubs-&gt;ctiNativeCall(vm));
</del><ins>+        return vm-&gt;jitStubs-&gt;jitEntryNativeCall(vm);
</ins><span class="cx"> 
</span><span class="cx">     jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
</span><span class="cx">     jit.sqrtDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0);
</span><span class="lines">@@ -782,12 +1012,12 @@
</span><span class="cx"> 
</span><span class="cx"> static const double halfConstant = 0.5;
</span><span class="cx">     
</span><del>-MacroAssemblerCodeRef floorThunkGenerator(VM* vm)
</del><ins>+JITEntryPointsWithRef floorThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><span class="cx">     SpecializedThunkJIT jit(vm, 1);
</span><span class="cx">     MacroAssembler::Jump nonIntJump;
</span><span class="cx">     if (!UnaryDoubleOpWrapper(floor) || !jit.supportsFloatingPoint())
</span><del>-        return MacroAssemblerCodeRef::createSelfManagedCodeRef(vm-&gt;jitStubs-&gt;ctiNativeCall(vm));
</del><ins>+        return vm-&gt;jitStubs-&gt;jitEntryNativeCall(vm);
</ins><span class="cx">     jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump);
</span><span class="cx">     jit.returnInt32(SpecializedThunkJIT::regT0);
</span><span class="cx">     nonIntJump.link(&amp;jit);
</span><span class="lines">@@ -825,11 +1055,11 @@
</span><span class="cx">     return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;floor&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef ceilThunkGenerator(VM* vm)
</del><ins>+JITEntryPointsWithRef ceilThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><span class="cx">     SpecializedThunkJIT jit(vm, 1);
</span><span class="cx">     if (!UnaryDoubleOpWrapper(ceil) || !jit.supportsFloatingPoint())
</span><del>-        return MacroAssemblerCodeRef::createSelfManagedCodeRef(vm-&gt;jitStubs-&gt;ctiNativeCall(vm));
</del><ins>+        return vm-&gt;jitStubs-&gt;jitEntryNativeCall(vm);
</ins><span class="cx">     MacroAssembler::Jump nonIntJump;
</span><span class="cx">     jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump);
</span><span class="cx">     jit.returnInt32(SpecializedThunkJIT::regT0);
</span><span class="lines">@@ -848,11 +1078,11 @@
</span><span class="cx">     return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;ceil&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef truncThunkGenerator(VM* vm)
</del><ins>+JITEntryPointsWithRef truncThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><span class="cx">     SpecializedThunkJIT jit(vm, 1);
</span><span class="cx">     if (!UnaryDoubleOpWrapper(trunc) || !jit.supportsFloatingPoint())
</span><del>-        return MacroAssemblerCodeRef::createSelfManagedCodeRef(vm-&gt;jitStubs-&gt;ctiNativeCall(vm));
</del><ins>+        return vm-&gt;jitStubs-&gt;jitEntryNativeCall(vm);
</ins><span class="cx">     MacroAssembler::Jump nonIntJump;
</span><span class="cx">     jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump);
</span><span class="cx">     jit.returnInt32(SpecializedThunkJIT::regT0);
</span><span class="lines">@@ -871,11 +1101,11 @@
</span><span class="cx">     return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;trunc&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef roundThunkGenerator(VM* vm)
</del><ins>+JITEntryPointsWithRef roundThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><span class="cx">     SpecializedThunkJIT jit(vm, 1);
</span><span class="cx">     if (!UnaryDoubleOpWrapper(jsRound) || !jit.supportsFloatingPoint())
</span><del>-        return MacroAssemblerCodeRef::createSelfManagedCodeRef(vm-&gt;jitStubs-&gt;ctiNativeCall(vm));
</del><ins>+        return vm-&gt;jitStubs-&gt;jitEntryNativeCall(vm);
</ins><span class="cx">     MacroAssembler::Jump nonIntJump;
</span><span class="cx">     jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump);
</span><span class="cx">     jit.returnInt32(SpecializedThunkJIT::regT0);
</span><span class="lines">@@ -905,13 +1135,13 @@
</span><span class="cx">     return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;round&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef expThunkGenerator(VM* vm)
</del><ins>+JITEntryPointsWithRef expThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><span class="cx">     if (!UnaryDoubleOpWrapper(exp))
</span><del>-        return MacroAssemblerCodeRef::createSelfManagedCodeRef(vm-&gt;jitStubs-&gt;ctiNativeCall(vm));
</del><ins>+        return vm-&gt;jitStubs-&gt;jitEntryNativeCall(vm);
</ins><span class="cx">     SpecializedThunkJIT jit(vm, 1);
</span><span class="cx">     if (!jit.supportsFloatingPoint())
</span><del>-        return MacroAssemblerCodeRef::createSelfManagedCodeRef(vm-&gt;jitStubs-&gt;ctiNativeCall(vm));
</del><ins>+        return vm-&gt;jitStubs-&gt;jitEntryNativeCall(vm);
</ins><span class="cx">     jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
</span><span class="cx">     jit.callDoubleToDoublePreservingReturn(UnaryDoubleOpWrapper(exp));
</span><span class="cx">     jit.returnDouble(SpecializedThunkJIT::fpRegT0);
</span><span class="lines">@@ -918,13 +1148,13 @@
</span><span class="cx">     return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;exp&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef logThunkGenerator(VM* vm)
</del><ins>+JITEntryPointsWithRef logThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><span class="cx">     if (!UnaryDoubleOpWrapper(log))
</span><del>-        return MacroAssemblerCodeRef::createSelfManagedCodeRef(vm-&gt;jitStubs-&gt;ctiNativeCall(vm));
</del><ins>+        return vm-&gt;jitStubs-&gt;jitEntryNativeCall(vm);
</ins><span class="cx">     SpecializedThunkJIT jit(vm, 1);
</span><span class="cx">     if (!jit.supportsFloatingPoint())
</span><del>-        return MacroAssemblerCodeRef::createSelfManagedCodeRef(vm-&gt;jitStubs-&gt;ctiNativeCall(vm));
</del><ins>+        return vm-&gt;jitStubs-&gt;jitEntryNativeCall(vm);
</ins><span class="cx">     jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
</span><span class="cx">     jit.callDoubleToDoublePreservingReturn(UnaryDoubleOpWrapper(log));
</span><span class="cx">     jit.returnDouble(SpecializedThunkJIT::fpRegT0);
</span><span class="lines">@@ -931,11 +1161,11 @@
</span><span class="cx">     return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;log&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef absThunkGenerator(VM* vm)
</del><ins>+JITEntryPointsWithRef absThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><span class="cx">     SpecializedThunkJIT jit(vm, 1);
</span><span class="cx">     if (!jit.supportsFloatingPointAbs())
</span><del>-        return MacroAssemblerCodeRef::createSelfManagedCodeRef(vm-&gt;jitStubs-&gt;ctiNativeCall(vm));
</del><ins>+        return vm-&gt;jitStubs-&gt;jitEntryNativeCall(vm);
</ins><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">     unsigned virtualRegisterIndex = CallFrame::argumentOffset(0);
</span><span class="lines">@@ -988,7 +1218,7 @@
</span><span class="cx">     return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;abs&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef imulThunkGenerator(VM* vm)
</del><ins>+JITEntryPointsWithRef imulThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><span class="cx">     SpecializedThunkJIT jit(vm, 2);
</span><span class="cx">     MacroAssembler::Jump nonIntArg0Jump;
</span><span class="lines">@@ -1019,11 +1249,11 @@
</span><span class="cx">     return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;imul&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef randomThunkGenerator(VM* vm)
</del><ins>+JITEntryPointsWithRef randomThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><span class="cx">     SpecializedThunkJIT jit(vm, 0);
</span><span class="cx">     if (!jit.supportsFloatingPoint())
</span><del>-        return MacroAssemblerCodeRef::createSelfManagedCodeRef(vm-&gt;jitStubs-&gt;ctiNativeCall(vm));
</del><ins>+        return vm-&gt;jitStubs-&gt;jitEntryNativeCall(vm);
</ins><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">     jit.emitRandomThunk(SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1, SpecializedThunkJIT::regT2, SpecializedThunkJIT::regT3, SpecializedThunkJIT::fpRegT0);
</span><span class="lines">@@ -1031,16 +1261,22 @@
</span><span class="cx"> 
</span><span class="cx">     return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;random&quot;);
</span><span class="cx"> #else
</span><del>-    return MacroAssemblerCodeRef::createSelfManagedCodeRef(vm-&gt;jitStubs-&gt;ctiNativeCall(vm));
</del><ins>+    return vm-&gt;jitStubs-&gt;jitEntryNativeCall(vm);
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef boundThisNoArgsFunctionCallGenerator(VM* vm)
</del><ins>+JITEntryPointsWithRef boundThisNoArgsFunctionCallGenerator(VM* vm)
</ins><span class="cx"> {
</span><del>-    CCallHelpers jit(vm);
</del><ins>+    JSInterfaceJIT jit(vm);
+
+    MacroAssembler::JumpList failures;
+
+    jit.spillArgumentRegistersToFrameBeforePrologue();
</ins><span class="cx">     
</span><ins>+    SpecializedThunkJIT::Label stackArgsEntry(&amp;jit);
+    
</ins><span class="cx">     jit.emitFunctionPrologue();
</span><del>-    
</del><ins>+
</ins><span class="cx">     // Set up our call frame.
</span><span class="cx">     jit.storePtr(CCallHelpers::TrustedImmPtr(nullptr), CCallHelpers::addressFor(CallFrameSlot::codeBlock));
</span><span class="cx">     jit.store32(CCallHelpers::TrustedImm32(0), CCallHelpers::tagFor(CallFrameSlot::argumentCount));
</span><span class="lines">@@ -1110,9 +1346,9 @@
</span><span class="cx">         GPRInfo::regT0);
</span><span class="cx">     jit.loadPtr(
</span><span class="cx">         CCallHelpers::Address(
</span><del>-            GPRInfo::regT0, ExecutableBase::offsetOfJITCodeWithArityCheckFor(CodeForCall)),
</del><ins>+            GPRInfo::regT0, ExecutableBase::offsetOfEntryFor(CodeForCall, StackArgsMustCheckArity)),
</ins><span class="cx">         GPRInfo::regT0);
</span><del>-    CCallHelpers::Jump noCode = jit.branchTestPtr(CCallHelpers::Zero, GPRInfo::regT0);
</del><ins>+    failures.append(jit.branchTestPtr(CCallHelpers::Zero, GPRInfo::regT0));
</ins><span class="cx">     
</span><span class="cx">     emitPointerValidation(jit, GPRInfo::regT0);
</span><span class="cx">     jit.call(GPRInfo::regT0);
</span><span class="lines">@@ -1119,11 +1355,14 @@
</span><span class="cx">     
</span><span class="cx">     jit.emitFunctionEpilogue();
</span><span class="cx">     jit.ret();
</span><del>-    
-    LinkBuffer linkBuffer(*vm, jit, GLOBAL_THUNK_ID);
-    linkBuffer.link(noCode, CodeLocationLabel(vm-&gt;jitStubs-&gt;ctiNativeTailCallWithoutSavedTags(vm)));
-    return FINALIZE_CODE(
-        linkBuffer, (&quot;Specialized thunk for bound function calls with no arguments&quot;));
</del><ins>+
+    LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
+    patchBuffer.link(failures, CodeLocationLabel(vm-&gt;jitStubs-&gt;ctiNativeTailCallWithoutSavedTags(vm)));
+
+    MacroAssemblerCodeRef codeRef FINALIZE_CODE(patchBuffer, (&quot;Specialized thunk for bound function calls with no arguments&quot;));
+    MacroAssemblerCodePtr stackEntryPtr = patchBuffer.locationOf(stackArgsEntry);
+
+    return JITEntryPointsWithRef(codeRef, codeRef.code(), codeRef.code(), codeRef.code(), stackEntryPtr, stackEntryPtr);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitThunkGeneratorsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ThunkGenerators.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CodeSpecializationKind.h&quot;
</span><ins>+#include &quot;JITEntryPoints.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">@@ -36,34 +37,35 @@
</span><span class="cx"> MacroAssemblerCodeRef throwExceptionFromCallSlowPathGenerator(VM*);
</span><span class="cx"> 
</span><span class="cx"> MacroAssemblerCodeRef linkCallThunk(VM*, CallLinkInfo&amp;, CodeSpecializationKind);
</span><del>-MacroAssemblerCodeRef linkCallThunkGenerator(VM*);
-MacroAssemblerCodeRef linkPolymorphicCallThunkGenerator(VM*);
</del><ins>+JITJSCallThunkEntryPointsWithRef linkCallThunkGenerator(VM*);
+JITJSCallThunkEntryPointsWithRef linkDirectCallThunkGenerator(VM*);
+JITJSCallThunkEntryPointsWithRef linkPolymorphicCallThunkGenerator(VM*);
</ins><span class="cx"> 
</span><del>-MacroAssemblerCodeRef virtualThunkFor(VM*, CallLinkInfo&amp;);
</del><ins>+JITJSCallThunkEntryPointsWithRef virtualThunkFor(VM*, CallLinkInfo&amp;);
</ins><span class="cx"> 
</span><del>-MacroAssemblerCodeRef nativeCallGenerator(VM*);
-MacroAssemblerCodeRef nativeConstructGenerator(VM*);
</del><ins>+JITEntryPointsWithRef nativeCallGenerator(VM*);
+JITEntryPointsWithRef nativeConstructGenerator(VM*);
</ins><span class="cx"> MacroAssemblerCodeRef nativeTailCallGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef nativeTailCallWithoutSavedTagsGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef arityFixupGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef unreachableGenerator(VM*);
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef charCodeAtThunkGenerator(VM*);
-MacroAssemblerCodeRef charAtThunkGenerator(VM*);
-MacroAssemblerCodeRef clz32ThunkGenerator(VM*);
-MacroAssemblerCodeRef fromCharCodeThunkGenerator(VM*);
-MacroAssemblerCodeRef absThunkGenerator(VM*);
-MacroAssemblerCodeRef ceilThunkGenerator(VM*);
-MacroAssemblerCodeRef expThunkGenerator(VM*);
-MacroAssemblerCodeRef floorThunkGenerator(VM*);
-MacroAssemblerCodeRef logThunkGenerator(VM*);
-MacroAssemblerCodeRef roundThunkGenerator(VM*);
-MacroAssemblerCodeRef sqrtThunkGenerator(VM*);
-MacroAssemblerCodeRef imulThunkGenerator(VM*);
-MacroAssemblerCodeRef randomThunkGenerator(VM*);
-MacroAssemblerCodeRef truncThunkGenerator(VM*);
</del><ins>+JITEntryPointsWithRef charCodeAtThunkGenerator(VM*);
+JITEntryPointsWithRef charAtThunkGenerator(VM*);
+JITEntryPointsWithRef clz32ThunkGenerator(VM*);
+JITEntryPointsWithRef fromCharCodeThunkGenerator(VM*);
+JITEntryPointsWithRef absThunkGenerator(VM*);
+JITEntryPointsWithRef ceilThunkGenerator(VM*);
+JITEntryPointsWithRef expThunkGenerator(VM*);
+JITEntryPointsWithRef floorThunkGenerator(VM*);
+JITEntryPointsWithRef logThunkGenerator(VM*);
+JITEntryPointsWithRef roundThunkGenerator(VM*);
+JITEntryPointsWithRef sqrtThunkGenerator(VM*);
+JITEntryPointsWithRef imulThunkGenerator(VM*);
+JITEntryPointsWithRef randomThunkGenerator(VM*);
+JITEntryPointsWithRef truncThunkGenerator(VM*);
</ins><span class="cx"> 
</span><del>-MacroAssemblerCodeRef boundThisNoArgsFunctionCallGenerator(VM* vm);
</del><ins>+JITEntryPointsWithRef boundThisNoArgsFunctionCallGenerator(VM*);
</ins><span class="cx"> 
</span><span class="cx"> }
</span><span class="cx"> #endif // ENABLE(JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -3259,6 +3259,9 @@
</span><span class="cx">     int result;
</span><span class="cx">     result = runJSC(vm, options);
</span><span class="cx"> 
</span><ins>+#if ENABLE(VM_COUNTERS)
+    vm-&gt;dumpCounters();
+#endif
</ins><span class="cx">     if (Options::gcAtEnd()) {
</span><span class="cx">         // We need to hold the API lock to do a GC.
</span><span class="cx">         JSLockHolder locker(vm);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntEntrypointcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntEntrypoint.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntEntrypoint.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/llint/LLIntEntrypoint.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -46,12 +46,26 @@
</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), vm.getCTIStub(functionForCallArityCheckThunkGenerator).code(), JITCode::InterpreterThunk)));
</del><ins>+                adoptRef(new DirectJITCode(
+                    JITEntryPointsWithRef(vm.getCTIStub(functionForRegisterCallEntryThunkGenerator),
+                        vm.getCTIStub(functionForRegisterCallEntryThunkGenerator).code(),
+                        vm.getCTIStub(functionForRegisterCallEntryThunkGenerator).code(),
+                        vm.getCTIStub(functionForRegisterCallArityCheckThunkGenerator).code(),
+                        vm.getCTIStub(functionForStackCallEntryThunkGenerator).code(),
+                        vm.getCTIStub(functionForStackCallArityCheckThunkGenerator).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), vm.getCTIStub(functionForConstructArityCheckThunkGenerator).code(), JITCode::InterpreterThunk)));
</del><ins>+            adoptRef(new DirectJITCode(
+                JITEntryPointsWithRef(vm.getCTIStub(functionForRegisterCallEntryThunkGenerator),
+                    vm.getCTIStub(functionForRegisterConstructEntryThunkGenerator).code(),
+                    vm.getCTIStub(functionForRegisterConstructEntryThunkGenerator).code(),
+                    vm.getCTIStub(functionForRegisterConstructArityCheckThunkGenerator).code(),
+                    vm.getCTIStub(functionForStackConstructEntryThunkGenerator).code(),
+                    vm.getCTIStub(functionForStackConstructArityCheckThunkGenerator).code()),
+                JITCode::InterpreterThunk)));
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> #endif // ENABLE(JIT)
</span><span class="lines">@@ -59,12 +73,26 @@
</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), MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_call_arity_check), JITCode::InterpreterThunk)));
</del><ins>+            adoptRef(new DirectJITCode(
+                JITEntryPointsWithRef(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_call_prologue),
+                    MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_call_prologue),
+                    MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_call_prologue),
+                    MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_call_prologue),
+                    MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_call_arity_check),
+                    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), MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_construct_arity_check), JITCode::InterpreterThunk)));
</del><ins>+        adoptRef(new DirectJITCode(
+            JITEntryPointsWithRef(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_construct_prologue),
+                MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_construct_prologue),
+                MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_construct_prologue),
+                MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_construct_prologue),
+                MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_construct_arity_check),
+                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">@@ -72,7 +100,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), MacroAssemblerCodePtr(), JITCode::InterpreterThunk)));
</del><ins>+            adoptRef(new DirectJITCode(
+                JITEntryPointsWithRef(vm.getCTIStub(evalEntryThunkGenerator),
+                    MacroAssemblerCodePtr(),
+                    MacroAssemblerCodePtr(),
+                    MacroAssemblerCodePtr(),
+                    vm.getCTIStub(evalEntryThunkGenerator).code(),
+                    vm.getCTIStub(evalEntryThunkGenerator).code()),
+                JITCode::InterpreterThunk)));
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> #endif // ENABLE(JIT)
</span><span class="lines">@@ -79,7 +114,14 @@
</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), MacroAssemblerCodePtr(), JITCode::InterpreterThunk)));
</del><ins>+        adoptRef(new DirectJITCode(
+            JITEntryPointsWithRef(MacroAssemblerCodeRef::createLLIntCodeRef(llint_eval_prologue),
+                MacroAssemblerCodePtr(),
+                MacroAssemblerCodePtr(),
+                MacroAssemblerCodePtr(),
+                MacroAssemblerCodeRef::createLLIntCodeRef(llint_eval_prologue).code(),
+                MacroAssemblerCodeRef::createLLIntCodeRef(llint_eval_prologue).code()),
+            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">@@ -87,7 +129,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), MacroAssemblerCodePtr(), JITCode::InterpreterThunk)));
</del><ins>+            adoptRef(new DirectJITCode(
+                JITEntryPointsWithRef(vm.getCTIStub(programEntryThunkGenerator),
+                MacroAssemblerCodePtr(),
+                MacroAssemblerCodePtr(),
+                MacroAssemblerCodePtr(),
+                vm.getCTIStub(programEntryThunkGenerator).code(),
+                vm.getCTIStub(programEntryThunkGenerator).code()),
+                JITCode::InterpreterThunk)));
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> #endif // ENABLE(JIT)
</span><span class="lines">@@ -94,7 +143,14 @@
</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), MacroAssemblerCodePtr(), JITCode::InterpreterThunk)));
</del><ins>+        adoptRef(new DirectJITCode(
+            JITEntryPointsWithRef(MacroAssemblerCodeRef::createLLIntCodeRef(llint_program_prologue),
+                MacroAssemblerCodePtr(),
+                MacroAssemblerCodePtr(),
+                MacroAssemblerCodePtr(),
+                MacroAssemblerCodePtr::createLLIntCodePtr(llint_program_prologue),
+                MacroAssemblerCodePtr::createLLIntCodePtr(llint_program_prologue)),
+            JITCode::InterpreterThunk)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void setModuleProgramEntrypoint(VM&amp; vm, CodeBlock* codeBlock)
</span><span class="lines">@@ -102,7 +158,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(moduleProgramEntryThunkGenerator), MacroAssemblerCodePtr(), JITCode::InterpreterThunk)));
</del><ins>+            adoptRef(new DirectJITCode(
+                JITEntryPointsWithRef(vm.getCTIStub(moduleProgramEntryThunkGenerator),
+                    MacroAssemblerCodePtr(),
+                    MacroAssemblerCodePtr(),
+                    MacroAssemblerCodePtr(),
+                    vm.getCTIStub(moduleProgramEntryThunkGenerator).code(),
+                    vm.getCTIStub(moduleProgramEntryThunkGenerator).code()),
+                JITCode::InterpreterThunk)));
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> #endif // ENABLE(JIT)
</span><span class="lines">@@ -109,7 +172,14 @@
</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_module_program_prologue), MacroAssemblerCodePtr(), JITCode::InterpreterThunk)));
</del><ins>+        adoptRef(new DirectJITCode(
+            JITEntryPointsWithRef(MacroAssemblerCodeRef::createLLIntCodeRef(llint_module_program_prologue),
+                MacroAssemblerCodePtr(),
+                MacroAssemblerCodePtr(),
+                MacroAssemblerCodePtr(),
+                MacroAssemblerCodePtr::createLLIntCodePtr(llint_module_program_prologue),
+                MacroAssemblerCodePtr::createLLIntCodePtr(llint_module_program_prologue)),
+            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="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -373,9 +373,9 @@
</span><span class="cx">     CODEBLOCK_LOG_EVENT(codeBlock, &quot;OSR entry&quot;, (&quot;in prologue&quot;));
</span><span class="cx">     
</span><span class="cx">     if (kind == Prologue)
</span><del>-        LLINT_RETURN_TWO(codeBlock-&gt;jitCode()-&gt;executableAddress(), 0);
</del><ins>+        LLINT_RETURN_TWO(codeBlock-&gt;jitCode()-&gt;addressForCall(StackArgsArityCheckNotRequired).executableAddress(), 0);
</ins><span class="cx">     ASSERT(kind == ArityCheck);
</span><del>-    LLINT_RETURN_TWO(codeBlock-&gt;jitCode()-&gt;addressForCall(MustCheckArity).executableAddress(), 0);
</del><ins>+    LLINT_RETURN_TWO(codeBlock-&gt;jitCode()-&gt;addressForCall(StackArgsMustCheckArity).executableAddress(), 0);
</ins><span class="cx"> }
</span><span class="cx"> #else // ENABLE(JIT)
</span><span class="cx"> static SlowPathReturnType entryOSR(ExecState* exec, Instruction*, CodeBlock* codeBlock, const char*, EntryKind)
</span><span class="lines">@@ -1292,7 +1292,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;entrypointFor(kind, MustCheckArity);
</del><ins>+        codePtr = executable-&gt;entrypointFor(kind, StackArgsMustCheckArity);
</ins><span class="cx">     } else {
</span><span class="cx">         FunctionExecutable* functionExecutable = static_cast&lt;FunctionExecutable*&gt;(executable);
</span><span class="cx"> 
</span><span class="lines">@@ -1306,12 +1306,12 @@
</span><span class="cx">             LLINT_CALL_THROW(exec, error);
</span><span class="cx">         codeBlock = *codeBlockSlot;
</span><span class="cx">         ASSERT(codeBlock);
</span><del>-        ArityCheckMode arity;
</del><ins>+        EntryPointType entryType;
</ins><span class="cx">         if (execCallee-&gt;argumentCountIncludingThis() &lt; static_cast&lt;size_t&gt;(codeBlock-&gt;numParameters()))
</span><del>-            arity = MustCheckArity;
</del><ins>+            entryType = StackArgsMustCheckArity;
</ins><span class="cx">         else
</span><del>-            arity = ArityCheckNotRequired;
-        codePtr = functionExecutable-&gt;entrypointFor(kind, arity);
</del><ins>+            entryType = StackArgsArityCheckNotRequired;
+        codePtr = functionExecutable-&gt;entrypointFor(kind, entryType);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ASSERT(!!codePtr);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntThunkscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntThunks.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntThunks.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/llint/LLIntThunks.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -51,10 +51,19 @@
</span><span class="cx"> 
</span><span class="cx"> namespace LLInt {
</span><span class="cx"> 
</span><del>-static MacroAssemblerCodeRef generateThunkWithJumpTo(VM* vm, void (*target)(), const char *thunkKind)
</del><ins>+enum ShouldCreateRegisterEntry { CreateRegisterEntry, DontCreateRegisterEntry };
+
+static MacroAssemblerCodeRef generateThunkWithJumpTo(VM* vm, void (*target)(), const char *thunkKind, ShouldCreateRegisterEntry shouldCreateRegisterEntry = DontCreateRegisterEntry)
</ins><span class="cx"> {
</span><span class="cx">     JSInterfaceJIT jit(vm);
</span><del>-    
</del><ins>+
+#if USE(JSVALUE64)
+    if (shouldCreateRegisterEntry == CreateRegisterEntry)
+        jit.spillArgumentRegistersToFrameBeforePrologue();
+#else
+    UNUSED_PARAM(shouldCreateRegisterEntry);
+#endif
+
</ins><span class="cx">     // FIXME: there's probably a better way to do it on X86, but I'm not sure I care.
</span><span class="cx">     jit.move(JSInterfaceJIT::TrustedImmPtr(bitwise_cast&lt;void*&gt;(target)), JSInterfaceJIT::regT0);
</span><span class="cx">     jit.jump(JSInterfaceJIT::regT0);
</span><span class="lines">@@ -63,26 +72,46 @@
</span><span class="cx">     return FINALIZE_CODE(patchBuffer, (&quot;LLInt %s prologue thunk&quot;, thunkKind));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef functionForCallEntryThunkGenerator(VM* vm)
</del><ins>+MacroAssemblerCodeRef functionForRegisterCallEntryThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><del>-    return generateThunkWithJumpTo(vm, LLInt::getCodeFunctionPtr(llint_function_for_call_prologue), &quot;function for call&quot;);
</del><ins>+    return generateThunkWithJumpTo(vm, LLInt::getCodeFunctionPtr(llint_function_for_call_prologue), &quot;function for register args call&quot;, CreateRegisterEntry);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef functionForConstructEntryThunkGenerator(VM* vm)
</del><ins>+MacroAssemblerCodeRef functionForStackCallEntryThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><del>-    return generateThunkWithJumpTo(vm, LLInt::getCodeFunctionPtr(llint_function_for_construct_prologue), &quot;function for construct&quot;);
</del><ins>+    return generateThunkWithJumpTo(vm, LLInt::getCodeFunctionPtr(llint_function_for_call_prologue), &quot;function for stack args call&quot;);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef functionForCallArityCheckThunkGenerator(VM* vm)
</del><ins>+MacroAssemblerCodeRef functionForRegisterConstructEntryThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><del>-    return generateThunkWithJumpTo(vm, LLInt::getCodeFunctionPtr(llint_function_for_call_arity_check), &quot;function for call with arity check&quot;);
</del><ins>+    return generateThunkWithJumpTo(vm, LLInt::getCodeFunctionPtr(llint_function_for_construct_prologue), &quot;function for register args construct&quot;, CreateRegisterEntry);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef functionForConstructArityCheckThunkGenerator(VM* vm)
</del><ins>+MacroAssemblerCodeRef functionForStackConstructEntryThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><del>-    return generateThunkWithJumpTo(vm, LLInt::getCodeFunctionPtr(llint_function_for_construct_arity_check), &quot;function for construct with arity check&quot;);
</del><ins>+    return generateThunkWithJumpTo(vm, LLInt::getCodeFunctionPtr(llint_function_for_construct_prologue), &quot;function for stack args construct&quot;);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+MacroAssemblerCodeRef functionForRegisterCallArityCheckThunkGenerator(VM* vm)
+{
+    return generateThunkWithJumpTo(vm, LLInt::getCodeFunctionPtr(llint_function_for_call_arity_check), &quot;function for register args call with arity check&quot;, CreateRegisterEntry);
+}
+
+MacroAssemblerCodeRef functionForStackCallArityCheckThunkGenerator(VM* vm)
+{
+    return generateThunkWithJumpTo(vm, LLInt::getCodeFunctionPtr(llint_function_for_call_arity_check), &quot;function for stack args call with arity check&quot;);
+}
+
+MacroAssemblerCodeRef functionForRegisterConstructArityCheckThunkGenerator(VM* vm)
+{
+    return generateThunkWithJumpTo(vm, LLInt::getCodeFunctionPtr(llint_function_for_construct_arity_check), &quot;function for register args construct with arity check&quot;, CreateRegisterEntry);
+}
+
+MacroAssemblerCodeRef functionForStackConstructArityCheckThunkGenerator(VM* vm)
+{
+    return generateThunkWithJumpTo(vm, LLInt::getCodeFunctionPtr(llint_function_for_construct_arity_check), &quot;function for stack args construct with arity check&quot;);
+}
+
</ins><span class="cx"> MacroAssemblerCodeRef evalEntryThunkGenerator(VM* vm)
</span><span class="cx"> {
</span><span class="cx">     return generateThunkWithJumpTo(vm, LLInt::getCodeFunctionPtr(llint_eval_prologue), &quot;eval&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntThunksh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntThunks.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntThunks.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/llint/LLIntThunks.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -42,10 +42,14 @@
</span><span class="cx"> 
</span><span class="cx"> namespace LLInt {
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef functionForCallEntryThunkGenerator(VM*);
-MacroAssemblerCodeRef functionForConstructEntryThunkGenerator(VM*);
-MacroAssemblerCodeRef functionForCallArityCheckThunkGenerator(VM*);
-MacroAssemblerCodeRef functionForConstructArityCheckThunkGenerator(VM*);
</del><ins>+MacroAssemblerCodeRef functionForRegisterCallEntryThunkGenerator(VM*);
+MacroAssemblerCodeRef functionForStackCallEntryThunkGenerator(VM*);
+MacroAssemblerCodeRef functionForRegisterConstructEntryThunkGenerator(VM*);
+MacroAssemblerCodeRef functionForStackConstructEntryThunkGenerator(VM*);
+MacroAssemblerCodeRef functionForRegisterCallArityCheckThunkGenerator(VM*);
+MacroAssemblerCodeRef functionForStackCallArityCheckThunkGenerator(VM*);
+MacroAssemblerCodeRef functionForRegisterConstructArityCheckThunkGenerator(VM*);
+MacroAssemblerCodeRef functionForStackConstructArityCheckThunkGenerator(VM*);
</ins><span class="cx"> MacroAssemblerCodeRef evalEntryThunkGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef programEntryThunkGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef moduleProgramEntryThunkGenerator(VM*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArityCheckModeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ArityCheckMode.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ArityCheckMode.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/runtime/ArityCheckMode.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> enum ArityCheckMode {
</span><ins>+    RegisterEntry,
</ins><span class="cx">     ArityCheckNotRequired,
</span><span class="cx">     MustCheckArity
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeExecutableBasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ExecutableBase.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ExecutableBase.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/runtime/ExecutableBase.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -54,8 +54,8 @@
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     m_jitCodeForCall = nullptr;
</span><span class="cx">     m_jitCodeForConstruct = nullptr;
</span><del>-    m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
-    m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
</del><ins>+    m_jitEntriesForCall.clearEntries();
+    m_jitEntriesForConstruct.clearEntries();
</ins><span class="cx"> #endif
</span><span class="cx">     m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
</span><span class="cx">     m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeExecutableBaseh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ExecutableBase.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ExecutableBase.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/runtime/ExecutableBase.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -25,7 +25,6 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><del>-#include &quot;ArityCheckMode.h&quot;
</del><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">@@ -34,6 +33,7 @@
</span><span class="cx"> #include &quot;HandlerInfo.h&quot;
</span><span class="cx"> #include &quot;InferredValue.h&quot;
</span><span class="cx"> #include &quot;JITCode.h&quot;
</span><ins>+#include &quot;JITEntryPoints.h&quot;
</ins><span class="cx"> #include &quot;JSGlobalObject.h&quot;
</span><span class="cx"> #include &quot;SourceCode.h&quot;
</span><span class="cx"> #include &quot;TypeSet.h&quot;
</span><span class="lines">@@ -145,47 +145,42 @@
</span><span class="cx">         return generatedJITCodeForConstruct();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    MacroAssemblerCodePtr entrypointFor(CodeSpecializationKind kind, ArityCheckMode arity)
</del><ins>+    MacroAssemblerCodePtr entrypointFor(CodeSpecializationKind kind, EntryPointType entryType)
</ins><span class="cx">     {
</span><span class="cx">         // Check if we have a cached result. We only have it for arity check because we use the
</span><span class="cx">         // no-arity entrypoint in non-virtual calls, which will &quot;cache&quot; this value directly in
</span><span class="cx">         // machine code.
</span><del>-        if (arity == MustCheckArity) {
-            switch (kind) {
-            case CodeForCall:
-                if (MacroAssemblerCodePtr result = m_jitCodeForCallWithArityCheck)
-                    return result;
-                break;
-            case CodeForConstruct:
-                if (MacroAssemblerCodePtr result = m_jitCodeForConstructWithArityCheck)
-                    return result;
-                break;
-            }
</del><ins>+        switch (kind) {
+        case CodeForCall:
+            if (MacroAssemblerCodePtr result = m_jitEntriesForCall.entryFor(entryType))
+                return result;
+            break;
+        case CodeForConstruct:
+            if (MacroAssemblerCodePtr result = m_jitEntriesForConstruct.entryFor(entryType))
+                return result;
+            break;
</ins><span class="cx">         }
</span><span class="cx">         MacroAssemblerCodePtr result =
</span><del>-            generatedJITCodeFor(kind)-&gt;addressForCall(arity);
-        if (arity == MustCheckArity) {
-            // Cache the result; this is necessary for the JIT's virtual call optimizations.
-            switch (kind) {
-            case CodeForCall:
-                m_jitCodeForCallWithArityCheck = result;
-                break;
-            case CodeForConstruct:
-                m_jitCodeForConstructWithArityCheck = result;
-                break;
-            }
</del><ins>+            generatedJITCodeFor(kind)-&gt;addressForCall(entryType);
+        // Cache the result; this is necessary for the JIT's virtual call optimizations.
+        switch (kind) {
+        case CodeForCall:
+            m_jitEntriesForCall.setEntryFor(entryType, result);
+            break;
+        case CodeForConstruct:
+            m_jitEntriesForConstruct.setEntryFor(entryType, result);
+            break;
</ins><span class="cx">         }
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    static ptrdiff_t offsetOfJITCodeWithArityCheckFor(
-        CodeSpecializationKind kind)
</del><ins>+    static ptrdiff_t offsetOfEntryFor(CodeSpecializationKind kind, EntryPointType entryPointType)
</ins><span class="cx">     {
</span><span class="cx">         switch (kind) {
</span><span class="cx">         case CodeForCall:
</span><del>-            return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
</del><ins>+            return OBJECT_OFFSETOF(ExecutableBase, m_jitEntriesForCall) + JITEntryPoints::offsetOfEntryFor(entryPointType);
</ins><span class="cx">         case CodeForConstruct:
</span><del>-            return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
</del><ins>+            return OBJECT_OFFSETOF(ExecutableBase, m_jitEntriesForConstruct) + JITEntryPoints::offsetOfEntryFor(entryPointType);
</ins><span class="cx">         }
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         return 0;
</span><span class="lines">@@ -233,8 +228,8 @@
</span><span class="cx">     Intrinsic m_intrinsic;
</span><span class="cx">     RefPtr&lt;JITCode&gt; m_jitCodeForCall;
</span><span class="cx">     RefPtr&lt;JITCode&gt; m_jitCodeForConstruct;
</span><del>-    MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
-    MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
</del><ins>+    JITEntryPoints m_jitEntriesForCall;
+    JITEntryPoints m_jitEntriesForConstruct;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSBoundFunctioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSBoundFunction.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSBoundFunction.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/runtime/JSBoundFunction.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -46,7 +46,7 @@
</span><span class="cx">     ExecutableBase* executable = targetFunction-&gt;executable();
</span><span class="cx">     if (executable-&gt;hasJITCodeForCall()) {
</span><span class="cx">         // Force the executable to cache its arity entrypoint.
</span><del>-        executable-&gt;entrypointFor(CodeForCall, MustCheckArity);
</del><ins>+        executable-&gt;entrypointFor(CodeForCall, StackArgsMustCheckArity);
</ins><span class="cx">     }
</span><span class="cx">     CallData callData;
</span><span class="cx">     CallType callType = getCallData(targetFunction, callData);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeNativeExecutablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/NativeExecutable.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/NativeExecutable.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/runtime/NativeExecutable.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -63,8 +63,8 @@
</span><span class="cx">     Base::finishCreation(vm);
</span><span class="cx">     m_jitCodeForCall = callThunk;
</span><span class="cx">     m_jitCodeForConstruct = constructThunk;
</span><del>-    m_jitCodeForCallWithArityCheck = m_jitCodeForCall-&gt;addressForCall(MustCheckArity);
-    m_jitCodeForConstructWithArityCheck = m_jitCodeForConstruct-&gt;addressForCall(MustCheckArity);
</del><ins>+    m_jitEntriesForCall.setEntryFor(StackArgsMustCheckArity, m_jitCodeForCall-&gt;addressForCall(StackArgsMustCheckArity));
+    m_jitEntriesForConstruct.setEntryFor(StackArgsMustCheckArity, m_jitCodeForConstruct-&gt;addressForCall(StackArgsMustCheckArity));
</ins><span class="cx">     m_name = name;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeScriptExecutablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -139,12 +139,12 @@
</span><span class="cx">     switch (kind) {
</span><span class="cx">     case CodeForCall:
</span><span class="cx">         m_jitCodeForCall = genericCodeBlock ? genericCodeBlock-&gt;jitCode() : nullptr;
</span><del>-        m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
</del><ins>+        m_jitEntriesForCall.clearEntries();
</ins><span class="cx">         m_numParametersForCall = genericCodeBlock ? genericCodeBlock-&gt;numParameters() : NUM_PARAMETERS_NOT_COMPILED;
</span><span class="cx">         break;
</span><span class="cx">     case CodeForConstruct:
</span><span class="cx">         m_jitCodeForConstruct = genericCodeBlock ? genericCodeBlock-&gt;jitCode() : nullptr;
</span><del>-        m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
</del><ins>+        m_jitEntriesForConstruct.clearEntries();
</ins><span class="cx">         m_numParametersForConstruct = genericCodeBlock ? genericCodeBlock-&gt;numParameters() : NUM_PARAMETERS_NOT_COMPILED;
</span><span class="cx">         break;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -210,6 +210,10 @@
</span><span class="cx">     updateSoftReservedZoneSize(Options::softReservedZoneSize());
</span><span class="cx">     setLastStackTop(stack.origin());
</span><span class="cx"> 
</span><ins>+#if ENABLE(VM_COUNTERS)
+    clearCounters();
+#endif
+
</ins><span class="cx">     // Need to be careful to keep everything consistent here
</span><span class="cx">     JSLockHolder lock(this);
</span><span class="cx">     AtomicStringTable* existingEntryAtomicStringTable = wtfThreadData().setCurrentAtomicStringTable(m_atomicStringTable);
</span><span class="lines">@@ -476,7 +480,7 @@
</span><span class="cx"> #endif // ENABLE(SAMPLING_PROFILER)
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(JIT)
</span><del>-static ThunkGenerator thunkGeneratorForIntrinsic(Intrinsic intrinsic)
</del><ins>+static JITEntryGenerator thunkGeneratorForIntrinsic(Intrinsic intrinsic)
</ins><span class="cx"> {
</span><span class="cx">     switch (intrinsic) {
</span><span class="cx">     case CharCodeAtIntrinsic:
</span><span class="lines">@@ -923,4 +927,35 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(VM_COUNTERS)
+void VM::clearCounters()
+{
+    for (unsigned i = 0; i &lt; NumberVMCounter; i++)
+        m_counters[i] = 0;
+}
+
+void VM::dumpCounters()
+{
+    size_t totalCalls = counterFor(BaselineCaller) + counterFor(DFGCaller) + counterFor(FTLCaller);
+    dataLog(&quot;#### VM Call counters ####\n&quot;);
+    dataLogF(&quot;%10zu Total calls\n&quot;, totalCalls);
+    dataLogF(&quot;%10zu Baseline calls\n&quot;, counterFor(BaselineCaller));
+    dataLogF(&quot;%10zu DFG calls\n&quot;, counterFor(DFGCaller));
+    dataLogF(&quot;%10zu FTL calls\n&quot;, counterFor(FTLCaller));
+    dataLogF(&quot;%10zu Vararg calls\n&quot;, counterFor(CallVarargs));
+    dataLogF(&quot;%10zu Tail calls\n&quot;, counterFor(TailCall));
+    dataLogF(&quot;%10zu Eval calls\n&quot;, counterFor(CallEval));
+    dataLogF(&quot;%10zu Direct calls\n&quot;, counterFor(DirectCall));
+    dataLogF(&quot;%10zu Polymorphic calls\n&quot;, counterFor(PolymorphicCall));
+    dataLogF(&quot;%10zu Virtual calls\n&quot;, counterFor(VirtualCall));
+    dataLogF(&quot;%10zu Virtual slow calls\n&quot;, counterFor(VirtualSlowCall));
+    dataLogF(&quot;%10zu Register args no arity\n&quot;, counterFor(RegArgsNoArity));
+    dataLogF(&quot;%10zu Stack args no arity\n&quot;, counterFor(StackArgsNoArity));
+    dataLogF(&quot;%10zu Register args extra arity\n&quot;, counterFor(RegArgsExtra));
+    dataLogF(&quot;%10zu Register args arity check\n&quot;, counterFor(RegArgsArity));
+    dataLogF(&quot;%10zu Stack args arity check\n&quot;, counterFor(StackArgsArity));
+    dataLogF(&quot;%10zu Arity fixups required\n&quot;, counterFor(ArityFixupRequired));
+}
+#endif
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -432,6 +432,16 @@
</span><span class="cx">     {
</span><span class="cx">         return jitStubs-&gt;ctiStub(this, generator);
</span><span class="cx">     }
</span><ins>+
+    JITEntryPointsWithRef getJITEntryStub(JITEntryGenerator generator)
+    {
+        return jitStubs-&gt;jitEntryStub(this, generator);
+    }
+
+    JITJSCallThunkEntryPointsWithRef getJITCallThunkEntryStub(JITCallThunkEntryGenerator generator)
+    {
+        return jitStubs-&gt;jitCallThunkEntryStub(this, generator);
+    }
</ins><span class="cx">     
</span><span class="cx">     std::unique_ptr&lt;RegisterAtOffsetList&gt; allCalleeSaveRegisterOffsets;
</span><span class="cx">     
</span><span class="lines">@@ -574,6 +584,50 @@
</span><span class="cx">     BumpPointerAllocator m_regExpAllocator;
</span><span class="cx">     ConcurrentJSLock m_regExpAllocatorLock;
</span><span class="cx"> 
</span><ins>+    enum VMCounterType {
+        BaselineCaller,
+        DFGCaller,
+        FTLCaller,
+        CallVarargs,
+        TailCall,
+        CallEval,
+        DirectCall,
+        PolymorphicCall,
+        VirtualCall,
+        VirtualSlowCall,
+        RegArgsNoArity,
+        StackArgsNoArity,
+        RegArgsExtra,
+        RegArgsArity,
+        StackArgsArity,
+        ArityFixupRequired,
+        NumberVMCounter
+    };
+
+#if ENABLE(VM_COUNTERS)
+    size_t m_counters[NumberVMCounter];
+
+    void clearCounters();
+
+    size_t* addressOfCounter(VMCounterType counterType)
+    {
+        if (counterType &gt;= NumberVMCounter)
+            return nullptr;
+
+        return &amp;m_counters[counterType];
+    }
+
+    size_t counterFor(VMCounterType counterType)
+    {
+        if (counterType &gt;= NumberVMCounter)
+            return 0;
+        
+        return m_counters[counterType];
+    }
+
+    JS_EXPORT_PRIVATE void dumpCounters();
+#endif
+
</ins><span class="cx">     std::unique_ptr&lt;HasOwnPropertyCache&gt; m_hasOwnPropertyCache;
</span><span class="cx">     ALWAYS_INLINE HasOwnPropertyCache* hasOwnPropertyCache() { return m_hasOwnPropertyCache.get(); }
</span><span class="cx">     HasOwnPropertyCache* ensureHasOwnPropertyCache();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmBindingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmBinding.cpp (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmBinding.cpp        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/JavaScriptCore/wasm/WasmBinding.cpp        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -133,7 +133,7 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    GPRReg importJSCellGPRReg = GPRInfo::regT0; // Callee needs to be in regT0 for slow path below.
</del><ins>+    GPRReg importJSCellGPRReg = argumentRegisterForCallee();
</ins><span class="cx">     ASSERT(!wasmCC.m_calleeSaveRegisters.get(importJSCellGPRReg));
</span><span class="cx"> 
</span><span class="cx">     // Each JS -&gt; wasm entry sets the WebAssembly.Instance whose export is being called. We're calling out of this Instance, and can therefore figure out the import being called.
</span><span class="lines">@@ -148,7 +148,7 @@
</span><span class="cx">     // FIXME Tail call if the wasm return type is void and no registers were spilled. https://bugs.webkit.org/show_bug.cgi?id=165488
</span><span class="cx"> 
</span><span class="cx">     CallLinkInfo* callLinkInfo = callLinkInfos.add();
</span><del>-    callLinkInfo-&gt;setUpCall(CallLinkInfo::Call, CodeOrigin(), importJSCellGPRReg);
</del><ins>+    callLinkInfo-&gt;setUpCall(CallLinkInfo::Call, StackArgs, CodeOrigin(), importJSCellGPRReg);
</ins><span class="cx">     JIT::DataLabelPtr targetToCheck;
</span><span class="cx">     JIT::TrustedImmPtr initialRightValue(0);
</span><span class="cx">     JIT::Jump slowPath = jit.branchPtrWithPatch(MacroAssembler::NotEqual, importJSCellGPRReg, targetToCheck, initialRightValue);
</span><span class="lines">@@ -155,8 +155,7 @@
</span><span class="cx">     JIT::Call fastCall = jit.nearCall();
</span><span class="cx">     JIT::Jump done = jit.jump();
</span><span class="cx">     slowPath.link(&amp;jit);
</span><del>-    // Callee needs to be in regT0 here.
-    jit.move(MacroAssembler::TrustedImmPtr(callLinkInfo), GPRInfo::regT2); // Link info needs to be in regT2.
</del><ins>+    jit.move(MacroAssembler::TrustedImmPtr(callLinkInfo), GPRInfo::nonArgGPR0); // Link info needs to be in nonArgGPR0
</ins><span class="cx">     JIT::Call slowCall = jit.nearCall();
</span><span class="cx">     done.link(&amp;jit);
</span><span class="cx"> 
</span><span class="lines">@@ -224,7 +223,7 @@
</span><span class="cx">     jit.ret();
</span><span class="cx"> 
</span><span class="cx">     LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
</span><del>-    patchBuffer.link(slowCall, FunctionPtr(vm-&gt;getCTIStub(linkCallThunkGenerator).code().executableAddress()));
</del><ins>+    patchBuffer.link(slowCall, FunctionPtr(vm-&gt;getJITCallThunkEntryStub(linkCallThunkGenerator).entryFor(StackArgs).executableAddress()));
</ins><span class="cx">     CodeLocationLabel callReturnLocation(patchBuffer.locationOfNearCall(slowCall));
</span><span class="cx">     CodeLocationLabel hotPathBegin(patchBuffer.locationOf(targetToCheck));
</span><span class="cx">     CodeLocationNearCall hotPathOther = patchBuffer.locationOfNearCall(fastCall);
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/WTF/ChangeLog        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2016-12-12  Michael Saboff  &lt;msaboff@apple.com&gt;
+
+        REGRESSION(r209653): speedometer crashes making virtual slow path tailcalls
+        https://bugs.webkit.org/show_bug.cgi?id=165748
+
+        Reviewed by Filip Pizlo.
+
+        Rolling back in r209653, r209654, r209663, and r209673.
+
+        * wtf/Platform.h:
+
</ins><span class="cx"> 2016-12-12  Commit Queue  &lt;commit-queue@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r209703.
</span></span></pre></div>
<a id="trunkSourceWTFwtfPlatformh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Platform.h (209724 => 209725)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Platform.h        2016-12-12 21:26:23 UTC (rev 209724)
+++ trunk/Source/WTF/wtf/Platform.h        2016-12-12 21:46:45 UTC (rev 209725)
</span><span class="lines">@@ -689,6 +689,9 @@
</span><span class="cx"> #define ENABLE_JIT 1
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+/* This enables per VM counters available for use by JIT'ed code. */
+#define ENABLE_VM_COUNTERS 0
+
</ins><span class="cx"> /* The FTL *does not* work on 32-bit platforms. Disable it even if someone asked us to enable it. */
</span><span class="cx"> #if USE(JSVALUE32_64)
</span><span class="cx"> #undef ENABLE_FTL_JIT
</span></span></pre>
</div>
</div>

</body>
</html>