<!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>[209653] 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/209653">209653</a></dd>
<dt>Author</dt> <dd>msaboff@apple.com</dd>
<dt>Date</dt> <dd>2016-12-09 23:32:38 -0800 (Fri, 09 Dec 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>JSVALUE64: Pass arguments in platform argument registers when making JavaScript calls
https://bugs.webkit.org/show_bug.cgi?id=160355

Reviewed by Filip Pizlo.

JSTests:

New microbenchmarks to measure call type performance.

* microbenchmarks/calling-computed-args.js: Added.
* microbenchmarks/calling-many-callees.js: Added.
* microbenchmarks/calling-one-callee-fixed.js: Added.
* microbenchmarks/calling-one-callee.js: Added.
* microbenchmarks/calling-poly-callees.js: Added.
* microbenchmarks/calling-poly-extra-arity-callees.js: Added.
* microbenchmarks/calling-tailcall.js: Added.
* microbenchmarks/calling-virtual-arity-fixup-callees.js: Added.
* microbenchmarks/calling-virtual-arity-fixup-stackargs.js: Added.
* microbenchmarks/calling-virtual-callees.js: Added.
* microbenchmarks/calling-virtual-extra-arity-callees.js: Added.

Source/JavaScriptCore:

This patch implements passing JavaScript function arguments in registers for 64 bit platforms.

The implemented convention follows the ABI conventions for the associated platform.
The first two arguments are the callee and argument count, the rest of the argument registers
contain &quot;this&quot; and following argument until all platform argument registers are exhausted.
Arguments beyond what fit in registers are placed on the stack in the same location as
before this patch.

For X86-64 non-Windows platforms, there are 6 argument registers specified in the related ABI.
ARM64 has had argument registers.  This allows for 4 or 6 parameter values to be placed in
registers on these respective platforms.  This patch doesn't implement passing arguments in
registers for 32 bit platform, since most platforms have at most 4 argument registers
specified and 32 bit platforms use two 32 bit registers/memory locations to store one JSValue.

The call frame on the stack in unchanged in format and the arguments that are passed in
registers use the corresponding call frame location as a spill location. Arguments can
also be passed on the stack. The LLInt, baseline JIT'ed code as well as the initial entry
from C++ code base arguments on the stack. DFG s and FTL generated code pass arguments
via registers. All callees can accept arguments either in registers or on the stack.
The callee is responsible for moving argument to its preferred location.

The multiple entry points to JavaSCript code is now handled via the JITEntryPoints class and
related code.  That class now has entries for StackArgsArityCheckNotRequired,
StackArgsMustCheckArity and for platforms that support registers arguments,
RegisterArgsArityCheckNotRequired, RegisterArgsMustCheckArity as well as and additional
RegisterArgsPossibleExtraArgs entry point when extra registers argument are passed.
This last case is needed to spill those extra arguments to the corresponding call frame
slots.

* JavaScriptCore.xcodeproj/project.pbxproj:
* b3/B3ArgumentRegValue.h:
* b3/B3Validate.cpp:
* bytecode/CallLinkInfo.cpp:
(JSC::CallLinkInfo::CallLinkInfo):
* bytecode/CallLinkInfo.h:
(JSC::CallLinkInfo::setUpCall):
(JSC::CallLinkInfo::argumentsLocation):
(JSC::CallLinkInfo::argumentsInRegisters):
* bytecode/PolymorphicAccess.cpp:
(JSC::AccessCase::generateImpl):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCPSRethreadingPhase.cpp:
(JSC::DFG::CPSRethreadingPhase::canonicalizeLocalsInBlock):
(JSC::DFG::CPSRethreadingPhase::specialCaseArguments):
(JSC::DFG::CPSRethreadingPhase::computeIsFlushed):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGCommon.h:
* dfg/DFGDCEPhase.cpp:
(JSC::DFG::DCEPhase::run):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGDriver.cpp:
(JSC::DFG::compileImpl):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGenerationInfo.h:
(JSC::DFG::GenerationInfo::initArgumentRegisterValue):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
(JSC::DFG::Graph::methodOfGettingAValueProfileFor):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::needsFlushedThis):
(JSC::DFG::Graph::addImmediateShouldSpeculateInt32):
* dfg/DFGInPlaceAbstractState.cpp:
(JSC::DFG::InPlaceAbstractState::initialize):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::compileFunction):
(JSC::DFG::JITCompiler::compileEntry): Deleted.
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::addJSDirectCall):
(JSC::DFG::JITCompiler::JSDirectCallRecord::JSDirectCallRecord):
(JSC::DFG::JITCompiler::JSDirectCallRecord::hasSlowCall):
* dfg/DFGJITFinalizer.cpp:
(JSC::DFG::JITFinalizer::JITFinalizer):
(JSC::DFG::JITFinalizer::finalize):
(JSC::DFG::JITFinalizer::finalizeFunction):
* dfg/DFGJITFinalizer.h:
* dfg/DFGLiveCatchVariablePreservationPhase.cpp:
(JSC::DFG::LiveCatchVariablePreservationPhase::handleBlock):
* dfg/DFGMaximalFlushInsertionPhase.cpp:
(JSC::DFG::MaximalFlushInsertionPhase::treatRegularBlock):
(JSC::DFG::MaximalFlushInsertionPhase::treatRootBlock):
* dfg/DFGMayExit.cpp:
* dfg/DFGMinifiedNode.cpp:
(JSC::DFG::MinifiedNode::fromNode):
* dfg/DFGMinifiedNode.h:
(JSC::DFG::belongsInMinifiedGraph):
* dfg/DFGNode.cpp:
(JSC::DFG::Node::hasVariableAccessData):
* dfg/DFGNode.h:
(JSC::DFG::Node::accessesStack):
(JSC::DFG::Node::setVariableAccessData):
(JSC::DFG::Node::hasArgumentRegisterIndex):
(JSC::DFG::Node::argumentRegisterIndex):
* dfg/DFGNodeType.h:
* dfg/DFGOSRAvailabilityAnalysisPhase.cpp:
(JSC::DFG::LocalOSRAvailabilityCalculator::executeNode):
* dfg/DFGOSREntrypointCreationPhase.cpp:
(JSC::DFG::OSREntrypointCreationPhase::run):
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
* dfg/DFGPreciseLocalClobberize.h:
(JSC::DFG::PreciseLocalClobberizeAdaptor::readTop):
* dfg/DFGPredictionInjectionPhase.cpp:
(JSC::DFG::PredictionInjectionPhase::run):
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGPutStackSinkingPhase.cpp:
* dfg/DFGRegisterBank.h:
(JSC::DFG::RegisterBank::iterator::unlock):
(JSC::DFG::RegisterBank::unlockAtIndex):
* dfg/DFGSSAConversionPhase.cpp:
(JSC::DFG::SSAConversionPhase::run):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::SpeculativeJIT):
(JSC::DFG::SpeculativeJIT::clearGenerationInfo):
(JSC::DFG::dumpRegisterInfo):
(JSC::DFG::SpeculativeJIT::dump):
(JSC::DFG::SpeculativeJIT::compileCurrentBlock):
(JSC::DFG::SpeculativeJIT::checkArgumentTypes):
(JSC::DFG::SpeculativeJIT::setupArgumentRegistersForEntry):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::allocate):
(JSC::DFG::SpeculativeJIT::spill):
(JSC::DFG::SpeculativeJIT::generationInfoFromVirtualRegister):
(JSC::DFG::JSValueOperand::JSValueOperand):
(JSC::DFG::JSValueOperand::gprUseSpecific):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::fillJSValue):
(JSC::DFG::SpeculativeJIT::emitCall):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::handleNode):
* dfg/DFGThunks.cpp:
(JSC::DFG::osrEntryThunkGenerator):
* dfg/DFGVariableEventStream.cpp:
(JSC::DFG::VariableEventStream::reconstruct):
* dfg/DFGVirtualRegisterAllocationPhase.cpp:
(JSC::DFG::VirtualRegisterAllocationPhase::allocateRegister):
(JSC::DFG::VirtualRegisterAllocationPhase::run):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLJITCode.cpp:
(JSC::FTL::JITCode::~JITCode):
(JSC::FTL::JITCode::initializeEntrypointThunk):
(JSC::FTL::JITCode::setEntryFor):
(JSC::FTL::JITCode::addressForCall):
(JSC::FTL::JITCode::executableAddressAtOffset):
(JSC::FTL::JITCode::initializeAddressForCall): Deleted.
(JSC::FTL::JITCode::initializeArityCheckEntrypoint): Deleted.
* ftl/FTLJITCode.h:
* ftl/FTLJITFinalizer.cpp:
(JSC::FTL::JITFinalizer::finalizeFunction):
* ftl/FTLLink.cpp:
(JSC::FTL::link):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::lower):
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileGetArgumentRegister):
(JSC::FTL::DFG::LowerDFGToB3::compileCallOrConstruct):
(JSC::FTL::DFG::LowerDFGToB3::compileDirectCallOrConstruct):
(JSC::FTL::DFG::LowerDFGToB3::compileTailCall):
(JSC::FTL::DFG::LowerDFGToB3::compileCallOrConstructVarargsSpread):
(JSC::FTL::DFG::LowerDFGToB3::compileCallOrConstructVarargs):
(JSC::FTL::DFG::LowerDFGToB3::compileCallEval):
* ftl/FTLOSREntry.cpp:
(JSC::FTL::prepareOSREntry):
* ftl/FTLOutput.cpp:
(JSC::FTL::Output::argumentRegister):
(JSC::FTL::Output::argumentRegisterInt32):
* ftl/FTLOutput.h:
* interpreter/ShadowChicken.cpp:
(JSC::ShadowChicken::update):
* jit/AssemblyHelpers.cpp:
(JSC::AssemblyHelpers::emitDumbVirtualCall):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::spillArgumentRegistersToFrameBeforePrologue):
(JSC::AssemblyHelpers::spillArgumentRegistersToFrame):
(JSC::AssemblyHelpers::fillArgumentRegistersFromFrameBeforePrologue):
(JSC::AssemblyHelpers::emitPutArgumentToCallFrameBeforePrologue):
(JSC::AssemblyHelpers::emitPutArgumentToCallFrame):
(JSC::AssemblyHelpers::emitGetFromCallFrameHeaderBeforePrologue):
(JSC::AssemblyHelpers::emitGetFromCallFrameArgumentBeforePrologue):
(JSC::AssemblyHelpers::emitGetPayloadFromCallFrameHeaderBeforePrologue):
(JSC::AssemblyHelpers::incrementCounter):
* jit/CachedRecovery.cpp:
(JSC::CachedRecovery::addTargetJSValueRegs):
* jit/CachedRecovery.h:
(JSC::CachedRecovery::gprTargets):
(JSC::CachedRecovery::setWantedFPR):
(JSC::CachedRecovery::wantedJSValueRegs):
(JSC::CachedRecovery::setWantedJSValueRegs): Deleted.
* jit/CallFrameShuffleData.h:
* jit/CallFrameShuffler.cpp:
(JSC::CallFrameShuffler::CallFrameShuffler):
(JSC::CallFrameShuffler::dump):
(JSC::CallFrameShuffler::tryWrites):
(JSC::CallFrameShuffler::prepareAny):
* jit/CallFrameShuffler.h:
(JSC::CallFrameShuffler::snapshot):
(JSC::CallFrameShuffler::addNew):
(JSC::CallFrameShuffler::initDangerFrontier):
(JSC::CallFrameShuffler::updateDangerFrontier):
(JSC::CallFrameShuffler::findDangerFrontierFrom):
* jit/CallFrameShuffler64.cpp:
(JSC::CallFrameShuffler::emitDisplace):
* jit/GPRInfo.h:
(JSC::JSValueRegs::operator==):
(JSC::JSValueRegs::operator!=):
(JSC::GPRInfo::toArgumentIndex):
(JSC::argumentRegisterFor):
(JSC::argumentRegisterForCallee):
(JSC::argumentRegisterForArgumentCount):
(JSC::argumentRegisterIndexForJSFunctionArgument):
(JSC::jsFunctionArgumentForArgumentRegister):
(JSC::argumentRegisterForFunctionArgument):
(JSC::numberOfRegisterArgumentsFor):
* jit/JIT.cpp:
(JSC::JIT::compileWithoutLinking):
(JSC::JIT::link):
(JSC::JIT::compileCTINativeCall): Deleted.
* jit/JIT.h:
(JSC::JIT::compileNativeCallEntryPoints):
* jit/JITCall.cpp:
(JSC::JIT::compileSetupVarargsFrame):
(JSC::JIT::compileCallEval):
(JSC::JIT::compileCallEvalSlowCase):
(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):
* jit/JITCall32_64.cpp:
(JSC::JIT::compileCallEvalSlowCase):
(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):
* jit/JITCode.cpp:
(JSC::JITCode::execute):
(JSC::DirectJITCode::DirectJITCode):
(JSC::DirectJITCode::initializeEntryPoints):
(JSC::DirectJITCode::addressForCall):
(JSC::NativeJITCode::addressForCall):
(JSC::DirectJITCode::initializeCodeRef): Deleted.
* jit/JITCode.h:
(JSC::JITCode::executableAddress): Deleted.
* jit/JITEntryPoints.h: Added.
(JSC::JITEntryPoints::JITEntryPoints):
(JSC::JITEntryPoints::entryFor):
(JSC::JITEntryPoints::setEntryFor):
(JSC::JITEntryPoints::offsetOfEntryFor):
(JSC::JITEntryPoints::registerEntryTypeForArgumentCount):
(JSC::JITEntryPoints::registerEntryTypeForArgumentType):
(JSC::JITEntryPoints::clearEntries):
(JSC::JITEntryPoints::operator=):
(JSC::JITEntryPointsWithRef::JITEntryPointsWithRef):
(JSC::JITEntryPointsWithRef::codeRef):
(JSC::argumentsLocationFor):
(JSC::registerEntryPointTypeFor):
(JSC::entryPointTypeFor):
(JSC::thunkEntryPointTypeFor):
(JSC::JITJSCallThunkEntryPointsWithRef::JITJSCallThunkEntryPointsWithRef):
(JSC::JITJSCallThunkEntryPointsWithRef::entryFor):
(JSC::JITJSCallThunkEntryPointsWithRef::setEntryFor):
(JSC::JITJSCallThunkEntryPointsWithRef::offsetOfEntryFor):
(JSC::JITJSCallThunkEntryPointsWithRef::clearEntries):
(JSC::JITJSCallThunkEntryPointsWithRef::codeRef):
(JSC::JITJSCallThunkEntryPointsWithRef::operator=):
* jit/JITOpcodes.cpp:
(JSC::JIT::privateCompileJITEntryNativeCall):
(JSC::JIT::privateCompileCTINativeCall): Deleted.
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::privateCompileJITEntryNativeCall):
(JSC::JIT::privateCompileCTINativeCall): Deleted.
* jit/JITOperations.cpp:
* jit/JITThunks.cpp:
(JSC::JITThunks::jitEntryNativeCall):
(JSC::JITThunks::jitEntryNativeConstruct):
(JSC::JITThunks::jitEntryStub):
(JSC::JITThunks::jitCallThunkEntryStub):
(JSC::JITThunks::hostFunctionStub):
(JSC::JITThunks::ctiNativeCall): Deleted.
(JSC::JITThunks::ctiNativeConstruct): Deleted.
* jit/JITThunks.h:
* jit/JSInterfaceJIT.h:
(JSC::JSInterfaceJIT::emitJumpIfNotInt32):
(JSC::JSInterfaceJIT::emitLoadInt32):
* jit/RegisterSet.cpp:
(JSC::RegisterSet::argumentRegisters):
* jit/RegisterSet.h:
* jit/Repatch.cpp:
(JSC::linkSlowFor):
(JSC::revertCall):
(JSC::unlinkFor):
(JSC::linkVirtualFor):
(JSC::linkPolymorphicCall):
* jit/SpecializedThunkJIT.h:
(JSC::SpecializedThunkJIT::SpecializedThunkJIT):
(JSC::SpecializedThunkJIT::checkJSStringArgument):
(JSC::SpecializedThunkJIT::linkFailureHere):
(JSC::SpecializedThunkJIT::finalize):
* jit/ThunkGenerator.h:
* jit/ThunkGenerators.cpp:
(JSC::createRegisterArgumentsSpillEntry):
(JSC::slowPathFor):
(JSC::linkCallThunkGenerator):
(JSC::linkDirectCallThunkGenerator):
(JSC::linkPolymorphicCallThunkGenerator):
(JSC::virtualThunkFor):
(JSC::nativeForGenerator):
(JSC::nativeCallGenerator):
(JSC::nativeTailCallGenerator):
(JSC::nativeTailCallWithoutSavedTagsGenerator):
(JSC::nativeConstructGenerator):
(JSC::stringCharLoadRegCall):
(JSC::charCodeAtThunkGenerator):
(JSC::charAtThunkGenerator):
(JSC::fromCharCodeThunkGenerator):
(JSC::clz32ThunkGenerator):
(JSC::sqrtThunkGenerator):
(JSC::floorThunkGenerator):
(JSC::ceilThunkGenerator):
(JSC::truncThunkGenerator):
(JSC::roundThunkGenerator):
(JSC::expThunkGenerator):
(JSC::logThunkGenerator):
(JSC::absThunkGenerator):
(JSC::imulThunkGenerator):
(JSC::randomThunkGenerator):
(JSC::boundThisNoArgsFunctionCallGenerator):
* jit/ThunkGenerators.h:
* jsc.cpp:
(jscmain):
* llint/LLIntEntrypoint.cpp:
(JSC::LLInt::setFunctionEntrypoint):
(JSC::LLInt::setEvalEntrypoint):
(JSC::LLInt::setProgramEntrypoint):
(JSC::LLInt::setModuleProgramEntrypoint):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::entryOSR):
(JSC::LLInt::setUpCall):
* llint/LLIntThunks.cpp:
(JSC::LLInt::generateThunkWithJumpTo):
(JSC::LLInt::functionForRegisterCallEntryThunkGenerator):
(JSC::LLInt::functionForStackCallEntryThunkGenerator):
(JSC::LLInt::functionForRegisterConstructEntryThunkGenerator):
(JSC::LLInt::functionForStackConstructEntryThunkGenerator):
(JSC::LLInt::functionForRegisterCallArityCheckThunkGenerator):
(JSC::LLInt::functionForStackCallArityCheckThunkGenerator):
(JSC::LLInt::functionForRegisterConstructArityCheckThunkGenerator):
(JSC::LLInt::functionForStackConstructArityCheckThunkGenerator):
(JSC::LLInt::functionForCallEntryThunkGenerator): Deleted.
(JSC::LLInt::functionForConstructEntryThunkGenerator): Deleted.
(JSC::LLInt::functionForCallArityCheckThunkGenerator): Deleted.
(JSC::LLInt::functionForConstructArityCheckThunkGenerator): Deleted.
* llint/LLIntThunks.h:
* runtime/ArityCheckMode.h:
* runtime/ExecutableBase.cpp:
(JSC::ExecutableBase::clearCode):
* runtime/ExecutableBase.h:
(JSC::ExecutableBase::entrypointFor):
(JSC::ExecutableBase::offsetOfEntryFor):
(JSC::ExecutableBase::offsetOfJITCodeWithArityCheckFor): Deleted.
* runtime/JSBoundFunction.cpp:
(JSC::boundThisNoArgsFunctionCall):
* runtime/NativeExecutable.cpp:
(JSC::NativeExecutable::finishCreation):
* runtime/ScriptExecutable.cpp:
(JSC::ScriptExecutable::installCode):
* runtime/VM.cpp:
(JSC::VM::VM):
(JSC::thunkGeneratorForIntrinsic):
(JSC::VM::clearCounters):
(JSC::VM::dumpCounters):
* runtime/VM.h:
(JSC::VM::getJITEntryStub):
(JSC::VM::getJITCallThunkEntryStub):
(JSC::VM::addressOfCounter):
(JSC::VM::counterFor):
* wasm/WasmBinding.cpp:
(JSC::Wasm::importStubGenerator):

Source/WTF:

Added a new build option ENABLE_VM_COUNTERS to enable JIT'able counters.
The default is for the option to be off.

* wtf/Platform.h:
Added ENABLE_VM_COUNTERS</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="#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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/JSTests/ChangeLog        2016-12-10 07:32:38 UTC (rev 209653)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2016-12-09  Michael Saboff  &lt;msaboff@apple.com&gt;
+
+        JSVALUE64: Pass arguments in platform argument registers when making JavaScript calls
+        https://bugs.webkit.org/show_bug.cgi?id=160355
+
+        Reviewed by Filip Pizlo.
+
+        New microbenchmarks to measure call type performance.
+
+        * microbenchmarks/calling-computed-args.js: Added.
+        * microbenchmarks/calling-many-callees.js: Added.
+        * microbenchmarks/calling-one-callee-fixed.js: Added.
+        * microbenchmarks/calling-one-callee.js: Added.
+        * microbenchmarks/calling-poly-callees.js: Added.
+        * microbenchmarks/calling-poly-extra-arity-callees.js: Added.
+        * microbenchmarks/calling-tailcall.js: Added.
+        * microbenchmarks/calling-virtual-arity-fixup-callees.js: Added.
+        * microbenchmarks/calling-virtual-arity-fixup-stackargs.js: Added.
+        * microbenchmarks/calling-virtual-callees.js: Added.
+        * microbenchmarks/calling-virtual-extra-arity-callees.js: Added.
+
</ins><span class="cx"> 2016-12-09  Keith Miller  &lt;keith_miller@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Wasm should support call_indirect
</span></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkscallingcomputedargsjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/calling-computed-args.js (0 => 209653)</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-10 07:32:38 UTC (rev 209653)
</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 => 209653)</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-10 07:32:38 UTC (rev 209653)
</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 => 209653)</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-10 07:32:38 UTC (rev 209653)
</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 => 209653)</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-10 07:32:38 UTC (rev 209653)
</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 => 209653)</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-10 07:32:38 UTC (rev 209653)
</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 => 209653)</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-10 07:32:38 UTC (rev 209653)
</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 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/calling-tailcall.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/calling-tailcall.js        2016-12-10 07:32:38 UTC (rev 209653)
</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 => 209653)</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-10 07:32:38 UTC (rev 209653)
</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 => 209653)</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-10 07:32:38 UTC (rev 209653)
</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 => 209653)</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-10 07:32:38 UTC (rev 209653)
</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 => 209653)</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-10 07:32:38 UTC (rev 209653)
</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="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-12-10 07:32:38 UTC (rev 209653)
</span><span class="lines">@@ -1,3 +1,399 @@
</span><ins>+2016-12-09  Michael Saboff  &lt;msaboff@apple.com&gt;
+
+        JSVALUE64: Pass arguments in platform argument registers when making JavaScript calls
+        https://bugs.webkit.org/show_bug.cgi?id=160355
+
+        Reviewed by Filip Pizlo.
+
+        This patch implements passing JavaScript function arguments in registers for 64 bit platforms.
+
+        The implemented convention follows the ABI conventions for the associated platform.
+        The first two arguments are the callee and argument count, the rest of the argument registers
+        contain &quot;this&quot; and following argument until all platform argument registers are exhausted.
+        Arguments beyond what fit in registers are placed on the stack in the same location as
+        before this patch.
+
+        For X86-64 non-Windows platforms, there are 6 argument registers specified in the related ABI.
+        ARM64 has had argument registers.  This allows for 4 or 6 parameter values to be placed in
+        registers on these respective platforms.  This patch doesn't implement passing arguments in
+        registers for 32 bit platform, since most platforms have at most 4 argument registers
+        specified and 32 bit platforms use two 32 bit registers/memory locations to store one JSValue.
+
+        The call frame on the stack in unchanged in format and the arguments that are passed in
+        registers use the corresponding call frame location as a spill location. Arguments can
+        also be passed on the stack. The LLInt, baseline JIT'ed code as well as the initial entry
+        from C++ code base arguments on the stack. DFG s and FTL generated code pass arguments
+        via registers. All callees can accept arguments either in registers or on the stack.
+        The callee is responsible for moving argument to its preferred location.
+
+        The multiple entry points to JavaSCript code is now handled via the JITEntryPoints class and
+        related code.  That class now has entries for StackArgsArityCheckNotRequired,
+        StackArgsMustCheckArity and for platforms that support registers arguments,
+        RegisterArgsArityCheckNotRequired, RegisterArgsMustCheckArity as well as and additional
+        RegisterArgsPossibleExtraArgs entry point when extra registers argument are passed.
+        This last case is needed to spill those extra arguments to the corresponding call frame
+        slots.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * b3/B3ArgumentRegValue.h:
+        * b3/B3Validate.cpp:
+        * bytecode/CallLinkInfo.cpp:
+        (JSC::CallLinkInfo::CallLinkInfo):
+        * bytecode/CallLinkInfo.h:
+        (JSC::CallLinkInfo::setUpCall):
+        (JSC::CallLinkInfo::argumentsLocation):
+        (JSC::CallLinkInfo::argumentsInRegisters):
+        * bytecode/PolymorphicAccess.cpp:
+        (JSC::AccessCase::generateImpl):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCPSRethreadingPhase.cpp:
+        (JSC::DFG::CPSRethreadingPhase::canonicalizeLocalsInBlock):
+        (JSC::DFG::CPSRethreadingPhase::specialCaseArguments):
+        (JSC::DFG::CPSRethreadingPhase::computeIsFlushed):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGCommon.h:
+        * dfg/DFGDCEPhase.cpp:
+        (JSC::DFG::DCEPhase::run):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGDriver.cpp:
+        (JSC::DFG::compileImpl):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGGenerationInfo.h:
+        (JSC::DFG::GenerationInfo::initArgumentRegisterValue):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::dump):
+        (JSC::DFG::Graph::methodOfGettingAValueProfileFor):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::needsFlushedThis):
+        (JSC::DFG::Graph::addImmediateShouldSpeculateInt32):
+        * dfg/DFGInPlaceAbstractState.cpp:
+        (JSC::DFG::InPlaceAbstractState::initialize):
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::link):
+        (JSC::DFG::JITCompiler::compile):
+        (JSC::DFG::JITCompiler::compileFunction):
+        (JSC::DFG::JITCompiler::compileEntry): Deleted.
+        * dfg/DFGJITCompiler.h:
+        (JSC::DFG::JITCompiler::addJSDirectCall):
+        (JSC::DFG::JITCompiler::JSDirectCallRecord::JSDirectCallRecord):
+        (JSC::DFG::JITCompiler::JSDirectCallRecord::hasSlowCall):
+        * dfg/DFGJITFinalizer.cpp:
+        (JSC::DFG::JITFinalizer::JITFinalizer):
+        (JSC::DFG::JITFinalizer::finalize):
+        (JSC::DFG::JITFinalizer::finalizeFunction):
+        * dfg/DFGJITFinalizer.h:
+        * dfg/DFGLiveCatchVariablePreservationPhase.cpp:
+        (JSC::DFG::LiveCatchVariablePreservationPhase::handleBlock):
+        * dfg/DFGMaximalFlushInsertionPhase.cpp:
+        (JSC::DFG::MaximalFlushInsertionPhase::treatRegularBlock):
+        (JSC::DFG::MaximalFlushInsertionPhase::treatRootBlock):
+        * dfg/DFGMayExit.cpp:
+        * dfg/DFGMinifiedNode.cpp:
+        (JSC::DFG::MinifiedNode::fromNode):
+        * dfg/DFGMinifiedNode.h:
+        (JSC::DFG::belongsInMinifiedGraph):
+        * dfg/DFGNode.cpp:
+        (JSC::DFG::Node::hasVariableAccessData):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::accessesStack):
+        (JSC::DFG::Node::setVariableAccessData):
+        (JSC::DFG::Node::hasArgumentRegisterIndex):
+        (JSC::DFG::Node::argumentRegisterIndex):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOSRAvailabilityAnalysisPhase.cpp:
+        (JSC::DFG::LocalOSRAvailabilityCalculator::executeNode):
+        * dfg/DFGOSREntrypointCreationPhase.cpp:
+        (JSC::DFG::OSREntrypointCreationPhase::run):
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::compileInThreadImpl):
+        * dfg/DFGPreciseLocalClobberize.h:
+        (JSC::DFG::PreciseLocalClobberizeAdaptor::readTop):
+        * dfg/DFGPredictionInjectionPhase.cpp:
+        (JSC::DFG::PredictionInjectionPhase::run):
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGPutStackSinkingPhase.cpp:
+        * dfg/DFGRegisterBank.h:
+        (JSC::DFG::RegisterBank::iterator::unlock):
+        (JSC::DFG::RegisterBank::unlockAtIndex):
+        * dfg/DFGSSAConversionPhase.cpp:
+        (JSC::DFG::SSAConversionPhase::run):
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::SpeculativeJIT):
+        (JSC::DFG::SpeculativeJIT::clearGenerationInfo):
+        (JSC::DFG::dumpRegisterInfo):
+        (JSC::DFG::SpeculativeJIT::dump):
+        (JSC::DFG::SpeculativeJIT::compileCurrentBlock):
+        (JSC::DFG::SpeculativeJIT::checkArgumentTypes):
+        (JSC::DFG::SpeculativeJIT::setupArgumentRegistersForEntry):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::allocate):
+        (JSC::DFG::SpeculativeJIT::spill):
+        (JSC::DFG::SpeculativeJIT::generationInfoFromVirtualRegister):
+        (JSC::DFG::JSValueOperand::JSValueOperand):
+        (JSC::DFG::JSValueOperand::gprUseSpecific):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::emitCall):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::fillJSValue):
+        (JSC::DFG::SpeculativeJIT::emitCall):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGStrengthReductionPhase.cpp:
+        (JSC::DFG::StrengthReductionPhase::handleNode):
+        * dfg/DFGThunks.cpp:
+        (JSC::DFG::osrEntryThunkGenerator):
+        * dfg/DFGVariableEventStream.cpp:
+        (JSC::DFG::VariableEventStream::reconstruct):
+        * dfg/DFGVirtualRegisterAllocationPhase.cpp:
+        (JSC::DFG::VirtualRegisterAllocationPhase::allocateRegister):
+        (JSC::DFG::VirtualRegisterAllocationPhase::run):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLJITCode.cpp:
+        (JSC::FTL::JITCode::~JITCode):
+        (JSC::FTL::JITCode::initializeEntrypointThunk):
+        (JSC::FTL::JITCode::setEntryFor):
+        (JSC::FTL::JITCode::addressForCall):
+        (JSC::FTL::JITCode::executableAddressAtOffset):
+        (JSC::FTL::JITCode::initializeAddressForCall): Deleted.
+        (JSC::FTL::JITCode::initializeArityCheckEntrypoint): Deleted.
+        * ftl/FTLJITCode.h:
+        * ftl/FTLJITFinalizer.cpp:
+        (JSC::FTL::JITFinalizer::finalizeFunction):
+        * ftl/FTLLink.cpp:
+        (JSC::FTL::link):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::lower):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileGetArgumentRegister):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCallOrConstruct):
+        (JSC::FTL::DFG::LowerDFGToB3::compileDirectCallOrConstruct):
+        (JSC::FTL::DFG::LowerDFGToB3::compileTailCall):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCallOrConstructVarargsSpread):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCallOrConstructVarargs):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCallEval):
+        * ftl/FTLOSREntry.cpp:
+        (JSC::FTL::prepareOSREntry):
+        * ftl/FTLOutput.cpp:
+        (JSC::FTL::Output::argumentRegister):
+        (JSC::FTL::Output::argumentRegisterInt32):
+        * ftl/FTLOutput.h:
+        * interpreter/ShadowChicken.cpp:
+        (JSC::ShadowChicken::update):
+        * jit/AssemblyHelpers.cpp:
+        (JSC::AssemblyHelpers::emitDumbVirtualCall):
+        * jit/AssemblyHelpers.h:
+        (JSC::AssemblyHelpers::spillArgumentRegistersToFrameBeforePrologue):
+        (JSC::AssemblyHelpers::spillArgumentRegistersToFrame):
+        (JSC::AssemblyHelpers::fillArgumentRegistersFromFrameBeforePrologue):
+        (JSC::AssemblyHelpers::emitPutArgumentToCallFrameBeforePrologue):
+        (JSC::AssemblyHelpers::emitPutArgumentToCallFrame):
+        (JSC::AssemblyHelpers::emitGetFromCallFrameHeaderBeforePrologue):
+        (JSC::AssemblyHelpers::emitGetFromCallFrameArgumentBeforePrologue):
+        (JSC::AssemblyHelpers::emitGetPayloadFromCallFrameHeaderBeforePrologue):
+        (JSC::AssemblyHelpers::incrementCounter):
+        * jit/CachedRecovery.cpp:
+        (JSC::CachedRecovery::addTargetJSValueRegs):
+        * jit/CachedRecovery.h:
+        (JSC::CachedRecovery::gprTargets):
+        (JSC::CachedRecovery::setWantedFPR):
+        (JSC::CachedRecovery::wantedJSValueRegs):
+        (JSC::CachedRecovery::setWantedJSValueRegs): Deleted.
+        * jit/CallFrameShuffleData.h:
+        * jit/CallFrameShuffler.cpp:
+        (JSC::CallFrameShuffler::CallFrameShuffler):
+        (JSC::CallFrameShuffler::dump):
+        (JSC::CallFrameShuffler::tryWrites):
+        (JSC::CallFrameShuffler::prepareAny):
+        * jit/CallFrameShuffler.h:
+        (JSC::CallFrameShuffler::snapshot):
+        (JSC::CallFrameShuffler::addNew):
+        (JSC::CallFrameShuffler::initDangerFrontier):
+        (JSC::CallFrameShuffler::updateDangerFrontier):
+        (JSC::CallFrameShuffler::findDangerFrontierFrom):
+        * jit/CallFrameShuffler64.cpp:
+        (JSC::CallFrameShuffler::emitDisplace):
+        * jit/GPRInfo.h:
+        (JSC::JSValueRegs::operator==):
+        (JSC::JSValueRegs::operator!=):
+        (JSC::GPRInfo::toArgumentIndex):
+        (JSC::argumentRegisterFor):
+        (JSC::argumentRegisterForCallee):
+        (JSC::argumentRegisterForArgumentCount):
+        (JSC::argumentRegisterIndexForJSFunctionArgument):
+        (JSC::jsFunctionArgumentForArgumentRegister):
+        (JSC::argumentRegisterForFunctionArgument):
+        (JSC::numberOfRegisterArgumentsFor):
+        * jit/JIT.cpp:
+        (JSC::JIT::compileWithoutLinking):
+        (JSC::JIT::link):
+        (JSC::JIT::compileCTINativeCall): Deleted.
+        * jit/JIT.h:
+        (JSC::JIT::compileNativeCallEntryPoints):
+        * jit/JITCall.cpp:
+        (JSC::JIT::compileSetupVarargsFrame):
+        (JSC::JIT::compileCallEval):
+        (JSC::JIT::compileCallEvalSlowCase):
+        (JSC::JIT::compileOpCall):
+        (JSC::JIT::compileOpCallSlowCase):
+        * jit/JITCall32_64.cpp:
+        (JSC::JIT::compileCallEvalSlowCase):
+        (JSC::JIT::compileOpCall):
+        (JSC::JIT::compileOpCallSlowCase):
+        * jit/JITCode.cpp:
+        (JSC::JITCode::execute):
+        (JSC::DirectJITCode::DirectJITCode):
+        (JSC::DirectJITCode::initializeEntryPoints):
+        (JSC::DirectJITCode::addressForCall):
+        (JSC::NativeJITCode::addressForCall):
+        (JSC::DirectJITCode::initializeCodeRef): Deleted.
+        * jit/JITCode.h:
+        (JSC::JITCode::executableAddress): Deleted.
+        * jit/JITEntryPoints.h: Added.
+        (JSC::JITEntryPoints::JITEntryPoints):
+        (JSC::JITEntryPoints::entryFor):
+        (JSC::JITEntryPoints::setEntryFor):
+        (JSC::JITEntryPoints::offsetOfEntryFor):
+        (JSC::JITEntryPoints::registerEntryTypeForArgumentCount):
+        (JSC::JITEntryPoints::registerEntryTypeForArgumentType):
+        (JSC::JITEntryPoints::clearEntries):
+        (JSC::JITEntryPoints::operator=):
+        (JSC::JITEntryPointsWithRef::JITEntryPointsWithRef):
+        (JSC::JITEntryPointsWithRef::codeRef):
+        (JSC::argumentsLocationFor):
+        (JSC::registerEntryPointTypeFor):
+        (JSC::entryPointTypeFor):
+        (JSC::thunkEntryPointTypeFor):
+        (JSC::JITJSCallThunkEntryPointsWithRef::JITJSCallThunkEntryPointsWithRef):
+        (JSC::JITJSCallThunkEntryPointsWithRef::entryFor):
+        (JSC::JITJSCallThunkEntryPointsWithRef::setEntryFor):
+        (JSC::JITJSCallThunkEntryPointsWithRef::offsetOfEntryFor):
+        (JSC::JITJSCallThunkEntryPointsWithRef::clearEntries):
+        (JSC::JITJSCallThunkEntryPointsWithRef::codeRef):
+        (JSC::JITJSCallThunkEntryPointsWithRef::operator=):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::privateCompileJITEntryNativeCall):
+        (JSC::JIT::privateCompileCTINativeCall): Deleted.
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::privateCompileJITEntryNativeCall):
+        (JSC::JIT::privateCompileCTINativeCall): Deleted.
+        * jit/JITOperations.cpp:
+        * jit/JITThunks.cpp:
+        (JSC::JITThunks::jitEntryNativeCall):
+        (JSC::JITThunks::jitEntryNativeConstruct):
+        (JSC::JITThunks::jitEntryStub):
+        (JSC::JITThunks::jitCallThunkEntryStub):
+        (JSC::JITThunks::hostFunctionStub):
+        (JSC::JITThunks::ctiNativeCall): Deleted.
+        (JSC::JITThunks::ctiNativeConstruct): Deleted.
+        * jit/JITThunks.h:
+        * jit/JSInterfaceJIT.h:
+        (JSC::JSInterfaceJIT::emitJumpIfNotInt32):
+        (JSC::JSInterfaceJIT::emitLoadInt32):
+        * jit/RegisterSet.cpp:
+        (JSC::RegisterSet::argumentRegisters):
+        * jit/RegisterSet.h:
+        * jit/Repatch.cpp:
+        (JSC::linkSlowFor):
+        (JSC::revertCall):
+        (JSC::unlinkFor):
+        (JSC::linkVirtualFor):
+        (JSC::linkPolymorphicCall):
+        * jit/SpecializedThunkJIT.h:
+        (JSC::SpecializedThunkJIT::SpecializedThunkJIT):
+        (JSC::SpecializedThunkJIT::checkJSStringArgument):
+        (JSC::SpecializedThunkJIT::linkFailureHere):
+        (JSC::SpecializedThunkJIT::finalize):
+        * jit/ThunkGenerator.h:
+        * jit/ThunkGenerators.cpp:
+        (JSC::createRegisterArgumentsSpillEntry):
+        (JSC::slowPathFor):
+        (JSC::linkCallThunkGenerator):
+        (JSC::linkDirectCallThunkGenerator):
+        (JSC::linkPolymorphicCallThunkGenerator):
+        (JSC::virtualThunkFor):
+        (JSC::nativeForGenerator):
+        (JSC::nativeCallGenerator):
+        (JSC::nativeTailCallGenerator):
+        (JSC::nativeTailCallWithoutSavedTagsGenerator):
+        (JSC::nativeConstructGenerator):
+        (JSC::stringCharLoadRegCall):
+        (JSC::charCodeAtThunkGenerator):
+        (JSC::charAtThunkGenerator):
+        (JSC::fromCharCodeThunkGenerator):
+        (JSC::clz32ThunkGenerator):
+        (JSC::sqrtThunkGenerator):
+        (JSC::floorThunkGenerator):
+        (JSC::ceilThunkGenerator):
+        (JSC::truncThunkGenerator):
+        (JSC::roundThunkGenerator):
+        (JSC::expThunkGenerator):
+        (JSC::logThunkGenerator):
+        (JSC::absThunkGenerator):
+        (JSC::imulThunkGenerator):
+        (JSC::randomThunkGenerator):
+        (JSC::boundThisNoArgsFunctionCallGenerator):
+        * jit/ThunkGenerators.h:
+        * jsc.cpp:
+        (jscmain):
+        * llint/LLIntEntrypoint.cpp:
+        (JSC::LLInt::setFunctionEntrypoint):
+        (JSC::LLInt::setEvalEntrypoint):
+        (JSC::LLInt::setProgramEntrypoint):
+        (JSC::LLInt::setModuleProgramEntrypoint):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::entryOSR):
+        (JSC::LLInt::setUpCall):
+        * llint/LLIntThunks.cpp:
+        (JSC::LLInt::generateThunkWithJumpTo):
+        (JSC::LLInt::functionForRegisterCallEntryThunkGenerator):
+        (JSC::LLInt::functionForStackCallEntryThunkGenerator):
+        (JSC::LLInt::functionForRegisterConstructEntryThunkGenerator):
+        (JSC::LLInt::functionForStackConstructEntryThunkGenerator):
+        (JSC::LLInt::functionForRegisterCallArityCheckThunkGenerator):
+        (JSC::LLInt::functionForStackCallArityCheckThunkGenerator):
+        (JSC::LLInt::functionForRegisterConstructArityCheckThunkGenerator):
+        (JSC::LLInt::functionForStackConstructArityCheckThunkGenerator):
+        (JSC::LLInt::functionForCallEntryThunkGenerator): Deleted.
+        (JSC::LLInt::functionForConstructEntryThunkGenerator): Deleted.
+        (JSC::LLInt::functionForCallArityCheckThunkGenerator): Deleted.
+        (JSC::LLInt::functionForConstructArityCheckThunkGenerator): Deleted.
+        * llint/LLIntThunks.h:
+        * runtime/ArityCheckMode.h:
+        * runtime/ExecutableBase.cpp:
+        (JSC::ExecutableBase::clearCode):
+        * runtime/ExecutableBase.h:
+        (JSC::ExecutableBase::entrypointFor):
+        (JSC::ExecutableBase::offsetOfEntryFor):
+        (JSC::ExecutableBase::offsetOfJITCodeWithArityCheckFor): Deleted.
+        * runtime/JSBoundFunction.cpp:
+        (JSC::boundThisNoArgsFunctionCall):
+        * runtime/NativeExecutable.cpp:
+        (JSC::NativeExecutable::finishCreation):
+        * runtime/ScriptExecutable.cpp:
+        (JSC::ScriptExecutable::installCode):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        (JSC::thunkGeneratorForIntrinsic):
+        (JSC::VM::clearCounters):
+        (JSC::VM::dumpCounters):
+        * runtime/VM.h:
+        (JSC::VM::getJITEntryStub):
+        (JSC::VM::getJITCallThunkEntryStub):
+        (JSC::VM::addressOfCounter):
+        (JSC::VM::counterFor):
+        * wasm/WasmBinding.cpp:
+        (JSC::Wasm::importStubGenerator):
+
</ins><span class="cx"> 2016-12-09  Keith Miller  &lt;keith_miller@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Wasm should support call_indirect
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-12-10 07:32:38 UTC (rev 209653)
</span><span class="lines">@@ -1350,6 +1350,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">@@ -3720,6 +3721,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">@@ -5558,6 +5560,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">@@ -7714,6 +7717,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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ArgumentRegValue.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/b3/B3ArgumentRegValue.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Validate.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/b3/B3Validate.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCommon.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGCommon.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITFinalizer.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITFinalizer.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITFinalizer.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITFinalizer.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGLiveCatchVariablePreservationPhase.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGLiveCatchVariablePreservationPhase.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGMaximalFlushInsertionPhase.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGMaximalFlushInsertionPhase.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionInjectionPhase.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionInjectionPhase.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPutStackSinkingPhase.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGPutStackSinkingPhase.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGRegisterBank.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGRegisterBank.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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,57 @@
</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);
+
+                if (platformArgGPR == InvalidGPRReg)
+                    m_jit.storeTrustedValue(jsUndefined(), JITCompiler::calleeArgumentSlot(i));
+                else {
+                    GPRTemporary argumentTemp(this, platformArgGPR);
+                    m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), argumentTemp.gpr());
+                }
+            }
</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 +982,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 +1023,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 +1046,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 +1058,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 +1067,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 +1078,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 +1109,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 +4249,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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGThunks.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGThunks.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/ftl/FTLJITCode.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJITCode.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/ftl/FTLJITCode.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLink.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/ftl/FTLLink.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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,9 +6226,13 @@
</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">                 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">@@ -6157,7 +6243,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">                     CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount)));
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOSREntry.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/ftl/FTLOSREntry.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOutput.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/ftl/FTLOutput.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOutput.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/ftl/FTLOutput.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/ShadowChicken.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/interpreter/ShadowChicken.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</span><span class="lines">@@ -284,16 +284,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(visitor-&gt;callee(), callFrame, isTailDeleted, callFrame-&gt;thisValue(), scope, codeBlock, callFrame-&gt;callSiteIndex()));
</del><ins>+            toPush.append(Frame(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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CachedRecovery.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/CachedRecovery.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CachedRecovery.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/CachedRecovery.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CallFrameShuffleData.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/CallFrameShuffleData.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CallFrameShuffler.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/CallFrameShuffler.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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,12 +756,19 @@
</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><del>-    m_jit.store32(MacroAssembler::TrustedImm32(0),
-        addressForNew(VirtualRegister { CallFrameSlot::argumentCount }).withOffset(TagOffset));
-    m_jit.store32(MacroAssembler::TrustedImm32(argCount()),
-        addressForNew(VirtualRegister { CallFrameSlot::argumentCount }).withOffset(PayloadOffset));
</del><ins>+#if USE(JSVALUE64)
+    if (!m_argumentsInRegisters) {
+#endif
+        m_jit.store32(MacroAssembler::TrustedImm32(0),
+            addressForNew(VirtualRegister { CallFrameSlot::argumentCount }).withOffset(TagOffset));
+        m_jit.store32(MacroAssembler::TrustedImm32(argCount()),
+            addressForNew(VirtualRegister { CallFrameSlot::argumentCount }).withOffset(PayloadOffset));
+#if USE(JSVALUE64)
+    }
+#endif
</ins><span class="cx"> 
</span><span class="cx">     if (!isSlowPath()) {
</span><span class="cx">         ASSERT(m_newFrameBase != MacroAssembler::stackPointerRegister);
</span><span class="lines">@@ -767,6 +788,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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CallFrameShuffler.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/CallFrameShuffler.h        2016-12-10 07:32:38 UTC (rev 209653)
</span><span class="lines">@@ -96,17 +96,37 @@
</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>+        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) };
+                CachedRecovery* cachedRecovery { m_newRegisters[reg] };
+                data.args[i] = cachedRecovery-&gt;recovery();
+            }
+        }
</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 +396,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">@@ -641,9 +664,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 +683,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 +781,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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CallFrameShuffler64.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/CallFrameShuffler64.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/GPRInfo.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/GPRInfo.h        2016-12-10 07:32:38 UTC (rev 209653)
</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></pre></div>
<a id="trunkSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.cpp (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/JITCall.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCode.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/JITCode.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCode.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/JITCode.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITEntryPoints.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/jit/JITEntryPoints.h        2016-12-10 07:32:38 UTC (rev 209653)
</span><span class="lines">@@ -0,0 +1,363 @@
</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
+
+#if ENABLE(JIT)
+
+#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
+
+#endif // ENABLE(JIT)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITThunks.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/JITThunks.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITThunks.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/JITThunks.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JSInterfaceJIT.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/JSInterfaceJIT.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/RegisterSet.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/RegisterSet.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/RegisterSet.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/RegisterSet.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/Repatch.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/SpecializedThunkJIT.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/SpecializedThunkJIT.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerator.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerator.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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,69 @@
</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);
</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(callLinkInfo.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 +377,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 +525,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 +543,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 +690,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 +756,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 +766,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 +849,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 +1009,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 +1052,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 +1075,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 +1098,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 +1132,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 +1145,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 +1158,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 +1215,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 +1246,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 +1258,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 +1343,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 +1352,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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</span><span class="lines">@@ -3251,6 +3251,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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntEntrypoint.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/llint/LLIntEntrypoint.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntThunks.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/llint/LLIntThunks.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntThunks.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/llint/LLIntThunks.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ArityCheckMode.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/runtime/ArityCheckMode.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ExecutableBase.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/runtime/ExecutableBase.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ExecutableBase.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/runtime/ExecutableBase.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSBoundFunction.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/runtime/JSBoundFunction.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/NativeExecutable.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/runtime/NativeExecutable.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmBinding.cpp        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/JavaScriptCore/wasm/WasmBinding.cpp        2016-12-10 07:32:38 UTC (rev 209653)
</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 (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/WTF/ChangeLog        2016-12-10 07:32:38 UTC (rev 209653)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-12-09  Michael Saboff  &lt;msaboff@apple.com&gt;
+
+        JSVALUE64: Pass arguments in platform argument registers when making JavaScript calls
+        https://bugs.webkit.org/show_bug.cgi?id=160355
+
+        Reviewed by Filip Pizlo.
+
+        Added a new build option ENABLE_VM_COUNTERS to enable JIT'able counters.
+        The default is for the option to be off.
+
+        * wtf/Platform.h:
+        Added ENABLE_VM_COUNTERS
+
</ins><span class="cx"> 2016-12-09  Geoffrey Garen  &lt;ggaren@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Deploy OrdinalNumber in JSC::SourceCode
</span></span></pre></div>
<a id="trunkSourceWTFwtfPlatformh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Platform.h (209652 => 209653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Platform.h        2016-12-10 07:12:53 UTC (rev 209652)
+++ trunk/Source/WTF/wtf/Platform.h        2016-12-10 07:32:38 UTC (rev 209653)
</span><span class="lines">@@ -695,6 +695,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>