<!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>[172940] 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/172940">172940</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-08-25 15:35:40 -0700 (Mon, 25 Aug 2014)</dd>
</dl>

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

Reviewed by Geoffrey Garen.
Source/JavaScriptCore:

        
Added a log-based high-fidelity call edge profiler that runs in DFG JIT (and optionally
baseline JIT) code. Used it to do precise polymorphic inlining in the FTL. Potential
inlining sites use the call edge profile if it is available, but they will still fall back
on the call inline cache and rare case counts if it's not. Polymorphic inlining means that
multiple possible callees can be inlined with a switch to guard them. The slow path may
either be an OSR exit or a virtual call.
        
The call edge profiling added in this patch is very precise - it will tell you about every
call that has ever happened. It took some effort to reduce the overhead of this profiling.
This mostly involved ensuring that we don't do it unnecessarily. For example, we avoid it
in the baseline JIT (you can conditionally enable it but it's off by default) and we only do
it in the DFG JIT if we know that the regular inline cache profiling wasn't precise enough.
I also experimented with reducing the precision of the profiling. This led to a significant
reduction in the speed-up, so I avoided this approach. I also explored making log processing
concurrent, but that didn't help. Also, I tested the overhead of the log processing and
found that most of the overhead of this profiling is actually in putting things into the log
rather than in processing the log - that part appears to be surprisingly cheap.
        
Polymorphic inlining could be enabled in the DFG if we enabled baseline call edge profiling,
and if we guarded such inlining sites with some profiling mechanism to detect
polyvariant monomorphisation opportunities (where the callsite being inlined reveals that
it's actually monomorphic).
        
This is a ~28% speed-up on deltablue and a ~7% speed-up on richards, with small speed-ups on
other programs as well. It's about a 2% speed-up on Octane version 2, and never a regression
on anything we care about. Some aggregates, like V8Spider, see a regression. This is
highlighting the increase in profiling overhead. But since this doesn't show up on any major
score (code-load or SunSpider), it's probably not relevant.
        
* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CallEdge.cpp: Added.
(JSC::CallEdge::dump):
* bytecode/CallEdge.h: Added.
(JSC::CallEdge::operator!):
(JSC::CallEdge::callee):
(JSC::CallEdge::count):
(JSC::CallEdge::despecifiedClosure):
(JSC::CallEdge::CallEdge):
* bytecode/CallEdgeProfile.cpp: Added.
(JSC::CallEdgeProfile::callEdges):
(JSC::CallEdgeProfile::numCallsToKnownCells):
(JSC::worthDespecifying):
(JSC::CallEdgeProfile::worthDespecifying):
(JSC::CallEdgeProfile::visitWeak):
(JSC::CallEdgeProfile::addSlow):
(JSC::CallEdgeProfile::mergeBack):
(JSC::CallEdgeProfile::fadeByHalf):
(JSC::CallEdgeLog::CallEdgeLog):
(JSC::CallEdgeLog::~CallEdgeLog):
(JSC::CallEdgeLog::isEnabled):
(JSC::operationProcessCallEdgeLog):
(JSC::CallEdgeLog::emitLogCode):
(JSC::CallEdgeLog::processLog):
* bytecode/CallEdgeProfile.h: Added.
(JSC::CallEdgeProfile::numCallsToNotCell):
(JSC::CallEdgeProfile::numCallsToUnknownCell):
(JSC::CallEdgeProfile::totalCalls):
* bytecode/CallEdgeProfileInlines.h: Added.
(JSC::CallEdgeProfile::CallEdgeProfile):
(JSC::CallEdgeProfile::add):
* bytecode/CallLinkInfo.cpp:
(JSC::CallLinkInfo::visitWeak):
* bytecode/CallLinkInfo.h:
* bytecode/CallLinkStatus.cpp:
(JSC::CallLinkStatus::CallLinkStatus):
(JSC::CallLinkStatus::computeFromLLInt):
(JSC::CallLinkStatus::computeFor):
(JSC::CallLinkStatus::computeExitSiteData):
(JSC::CallLinkStatus::computeFromCallLinkInfo):
(JSC::CallLinkStatus::computeFromCallEdgeProfile):
(JSC::CallLinkStatus::computeDFGStatuses):
(JSC::CallLinkStatus::isClosureCall):
(JSC::CallLinkStatus::makeClosureCall):
(JSC::CallLinkStatus::dump):
(JSC::CallLinkStatus::function): Deleted.
(JSC::CallLinkStatus::internalFunction): Deleted.
(JSC::CallLinkStatus::intrinsicFor): Deleted.
* bytecode/CallLinkStatus.h:
(JSC::CallLinkStatus::CallLinkStatus):
(JSC::CallLinkStatus::isSet):
(JSC::CallLinkStatus::couldTakeSlowPath):
(JSC::CallLinkStatus::edges):
(JSC::CallLinkStatus::size):
(JSC::CallLinkStatus::at):
(JSC::CallLinkStatus::operator[]):
(JSC::CallLinkStatus::canOptimize):
(JSC::CallLinkStatus::canTrustCounts):
(JSC::CallLinkStatus::isClosureCall): Deleted.
(JSC::CallLinkStatus::callTarget): Deleted.
(JSC::CallLinkStatus::executable): Deleted.
(JSC::CallLinkStatus::makeClosureCall): Deleted.
* bytecode/CallVariant.cpp: Added.
(JSC::CallVariant::dump):
* bytecode/CallVariant.h: Added.
(JSC::CallVariant::CallVariant):
(JSC::CallVariant::operator!):
(JSC::CallVariant::despecifiedClosure):
(JSC::CallVariant::rawCalleeCell):
(JSC::CallVariant::internalFunction):
(JSC::CallVariant::function):
(JSC::CallVariant::isClosureCall):
(JSC::CallVariant::executable):
(JSC::CallVariant::nonExecutableCallee):
(JSC::CallVariant::intrinsicFor):
(JSC::CallVariant::functionExecutable):
(JSC::CallVariant::isHashTableDeletedValue):
(JSC::CallVariant::operator==):
(JSC::CallVariant::operator!=):
(JSC::CallVariant::operator&lt;):
(JSC::CallVariant::operator&gt;):
(JSC::CallVariant::operator&lt;=):
(JSC::CallVariant::operator&gt;=):
(JSC::CallVariant::hash):
(JSC::CallVariant::deletedToken):
(JSC::CallVariantHash::hash):
(JSC::CallVariantHash::equal):
* bytecode/CodeOrigin.h:
(JSC::InlineCallFrame::isNormalCall):
* bytecode/ExitKind.cpp:
(JSC::exitKindToString):
* bytecode/ExitKind.h:
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeForStubInfo):
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeForStubInfo):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGBackwardsPropagationPhase.cpp:
(JSC::DFG::BackwardsPropagationPhase::propagate):
* dfg/DFGBasicBlock.cpp:
(JSC::DFG::BasicBlock::~BasicBlock):
* dfg/DFGBasicBlock.h:
(JSC::DFG::BasicBlock::takeLast):
(JSC::DFG::BasicBlock::didLink):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::processSetLocalQueue):
(JSC::DFG::ByteCodeParser::removeLastNodeFromGraph):
(JSC::DFG::ByteCodeParser::addCallWithoutSettingResult):
(JSC::DFG::ByteCodeParser::addCall):
(JSC::DFG::ByteCodeParser::handleCall):
(JSC::DFG::ByteCodeParser::emitFunctionChecks):
(JSC::DFG::ByteCodeParser::undoFunctionChecks):
(JSC::DFG::ByteCodeParser::inliningCost):
(JSC::DFG::ByteCodeParser::inlineCall):
(JSC::DFG::ByteCodeParser::cancelLinkingForBlock):
(JSC::DFG::ByteCodeParser::attemptToInlineCall):
(JSC::DFG::ByteCodeParser::handleInlining):
(JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
(JSC::DFG::ByteCodeParser::prepareToParseBlock):
(JSC::DFG::ByteCodeParser::clearCaches):
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::linkBlock):
(JSC::DFG::ByteCodeParser::linkBlocks):
(JSC::DFG::ByteCodeParser::parseCodeBlock):
* dfg/DFGCPSRethreadingPhase.cpp:
(JSC::DFG::CPSRethreadingPhase::freeUnnecessaryNodes):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGCommon.h:
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGDriver.cpp:
(JSC::DFG::compileImpl):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
(JSC::DFG::Graph::visitChildren):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
* dfg/DFGLazyJSValue.cpp:
(JSC::DFG::LazyJSValue::switchLookupValue):
* dfg/DFGLazyJSValue.h:
(JSC::DFG::LazyJSValue::switchLookupValue): Deleted.
* dfg/DFGNode.cpp:
(WTF::printInternal):
* dfg/DFGNode.h:
(JSC::DFG::OpInfo::OpInfo):
(JSC::DFG::Node::hasHeapPrediction):
(JSC::DFG::Node::hasCellOperand):
(JSC::DFG::Node::cellOperand):
(JSC::DFG::Node::setCellOperand):
(JSC::DFG::Node::canBeKnownFunction): Deleted.
(JSC::DFG::Node::hasKnownFunction): Deleted.
(JSC::DFG::Node::knownFunction): Deleted.
(JSC::DFG::Node::giveKnownFunction): Deleted.
(JSC::DFG::Node::hasFunction): Deleted.
(JSC::DFG::Node::function): Deleted.
(JSC::DFG::Node::hasExecutable): Deleted.
(JSC::DFG::Node::executable): Deleted.
* dfg/DFGNodeType.h:
* dfg/DFGPhantomCanonicalizationPhase.cpp:
(JSC::DFG::PhantomCanonicalizationPhase::run):
* dfg/DFGPhantomRemovalPhase.cpp:
(JSC::DFG::PhantomRemovalPhase::run):
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::emitSwitch):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStructureRegistrationPhase.cpp:
(JSC::DFG::StructureRegistrationPhase::run):
* dfg/DFGTierUpCheckInjectionPhase.cpp:
(JSC::DFG::TierUpCheckInjectionPhase::run):
(JSC::DFG::TierUpCheckInjectionPhase::removeFTLProfiling):
* dfg/DFGValidate.cpp:
(JSC::DFG::Validate::validate):
* dfg/DFGWatchpointCollectionPhase.cpp:
(JSC::DFG::WatchpointCollectionPhase::handle):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::ftlUnreachable):
(JSC::FTL::LowerDFGToLLVM::lower):
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileCheckCell):
(JSC::FTL::LowerDFGToLLVM::compileCheckBadCell):
(JSC::FTL::LowerDFGToLLVM::compileGetExecutable):
(JSC::FTL::LowerDFGToLLVM::compileNativeCallOrConstruct):
(JSC::FTL::LowerDFGToLLVM::compileSwitch):
(JSC::FTL::LowerDFGToLLVM::buildSwitch):
(JSC::FTL::LowerDFGToLLVM::compileCheckFunction): Deleted.
(JSC::FTL::LowerDFGToLLVM::compileCheckExecutable): Deleted.
* heap/Heap.cpp:
(JSC::Heap::collect):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::storeValue):
(JSC::AssemblyHelpers::loadValue):
* jit/CCallHelpers.h:
(JSC::CCallHelpers::setupArguments):
* jit/GPRInfo.h:
(JSC::JSValueRegs::uses):
* jit/JITCall.cpp:
(JSC::JIT::compileOpCall):
* jit/JITCall32_64.cpp:
(JSC::JIT::compileOpCall):
* runtime/Options.h:
* runtime/VM.cpp:
(JSC::VM::ensureCallEdgeLog):
* runtime/VM.h:
* tests/stress/new-array-then-exit.js: Added.
(foo):
* tests/stress/poly-call-exit-this.js: Added.
* tests/stress/poly-call-exit.js: Added.

Source/WTF:

        
Add some power that I need for call edge profiling.

* wtf/OwnPtr.h:
(WTF::OwnPtr&lt;T&gt;::createTransactionally):
* wtf/Spectrum.h:
(WTF::Spectrum::add):
(WTF::Spectrum::addAll):
(WTF::Spectrum::get):
(WTF::Spectrum::size):
(WTF::Spectrum::KeyAndCount::KeyAndCount):
(WTF::Spectrum::clear):
(WTF::Spectrum::removeIf):

LayoutTests:


* js/regress/script-tests/simple-poly-call-nested.js: Added.
* js/regress/script-tests/simple-poly-call.js: Added.
* js/regress/simple-poly-call-expected.txt: Added.
* js/regress/simple-poly-call-nested-expected.txt: Added.
* js/regress/simple-poly-call-nested.html: Added.
* js/regress/simple-poly-call.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</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="#trunkSourceJavaScriptCorebytecodeCallLinkStatuscpp">trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallLinkStatush">trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeOriginh">trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeExitKindcpp">trunk/Source/JavaScriptCore/bytecode/ExitKind.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeExitKindh">trunk/Source/JavaScriptCore/bytecode/ExitKind.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeGetByIdStatuscpp">trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePutByIdStatuscpp">trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGBackwardsPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGBasicBlockcpp">trunk/Source/JavaScriptCore/dfg/DFGBasicBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGBasicBlockh">trunk/Source/JavaScriptCore/dfg/DFGBasicBlock.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="#trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.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="#trunkSourceJavaScriptCoredfgDFGGraphcpp">trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCompilercpp">trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGLazyJSValuecpp">trunk/Source/JavaScriptCore/dfg/DFGLazyJSValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGLazyJSValueh">trunk/Source/JavaScriptCore/dfg/DFGLazyJSValue.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="#trunkSourceJavaScriptCoredfgDFGPhantomCanonicalizationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPhantomRemovalPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.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="#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="#trunkSourceJavaScriptCoredfgDFGStructureRegistrationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGTierUpCheckInjectionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGValidatecpp">trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGWatchpointCollectionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapcpp">trunk/Source/JavaScriptCore/heap/Heap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAssemblyHelpersh">trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitCCallHelpersh">trunk/Source/JavaScriptCore/jit/CCallHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitGPRInfoh">trunk/Source/JavaScriptCore/jit/GPRInfo.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="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</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="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfOwnPtrh">trunk/Source/WTF/wtf/OwnPtr.h</a></li>
<li><a href="#trunkSourceWTFwtfSpectrumh">trunk/Source/WTF/wtf/Spectrum.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsregressscripttestssimplepolycallnestedjs">trunk/LayoutTests/js/regress/script-tests/simple-poly-call-nested.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestssimplepolycalljs">trunk/LayoutTests/js/regress/script-tests/simple-poly-call.js</a></li>
<li><a href="#trunkLayoutTestsjsregresssimplepolycallexpectedtxt">trunk/LayoutTests/js/regress/simple-poly-call-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregresssimplepolycallnestedexpectedtxt">trunk/LayoutTests/js/regress/simple-poly-call-nested-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregresssimplepolycallnestedhtml">trunk/LayoutTests/js/regress/simple-poly-call-nested.html</a></li>
<li><a href="#trunkLayoutTestsjsregresssimplepolycallhtml">trunk/LayoutTests/js/regress/simple-poly-call.html</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallEdgecpp">trunk/Source/JavaScriptCore/bytecode/CallEdge.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallEdgeh">trunk/Source/JavaScriptCore/bytecode/CallEdge.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallEdgeProfilecpp">trunk/Source/JavaScriptCore/bytecode/CallEdgeProfile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallEdgeProfileh">trunk/Source/JavaScriptCore/bytecode/CallEdgeProfile.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallEdgeProfileInlinesh">trunk/Source/JavaScriptCore/bytecode/CallEdgeProfileInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallVariantcpp">trunk/Source/JavaScriptCore/bytecode/CallVariant.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallVarianth">trunk/Source/JavaScriptCore/bytecode/CallVariant.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressnewarraythenexitjs">trunk/Source/JavaScriptCore/tests/stress/new-array-then-exit.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresspolycallexitthisjs">trunk/Source/JavaScriptCore/tests/stress/poly-call-exit-this.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresspolycallexitjs">trunk/Source/JavaScriptCore/tests/stress/poly-call-exit.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/LayoutTests/ChangeLog        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2014-08-23  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        FTL should be able to do polymorphic call inlining
+        https://bugs.webkit.org/show_bug.cgi?id=135145
+
+        Reviewed by Geoffrey Garen.
+
+        * js/regress/script-tests/simple-poly-call-nested.js: Added.
+        * js/regress/script-tests/simple-poly-call.js: Added.
+        * js/regress/simple-poly-call-expected.txt: Added.
+        * js/regress/simple-poly-call-nested-expected.txt: Added.
+        * js/regress/simple-poly-call-nested.html: Added.
+        * js/regress/simple-poly-call.html: Added.
+
</ins><span class="cx"> 2014-08-25  Alexey Proskuryakov  &lt;ap@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         ASSERT(extractable()) when storing a non-extractable key in IndexedDB
</span></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestssimplepolycallnestedjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/simple-poly-call-nested.js (0 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/simple-poly-call-nested.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/simple-poly-call-nested.js        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+(function() {
+    function foo(x) { return 1; }
+    function bar(x) { return x; }
+    
+    var n = 1000000;
+    
+    var result = (function() {
+        var f = foo;
+        var g = bar;
+        
+        var result = 0;
+        for (var i = 0; i &lt; n; ++i) {
+            result += f(42);
+            
+            var tmp = f;
+            f = g;
+            g = tmp;
+        }
+        
+        return result;
+    })();
+    
+    if (result != n / 2 * 42 + n / 2 * 1)
+        throw &quot;Error: bad result: &quot; + result;
+})();
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestssimplepolycalljs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/simple-poly-call.js (0 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/simple-poly-call.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/simple-poly-call.js        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -0,0 +1,20 @@
</span><ins>+(function() {
+    function foo(x) { return 1; }
+    function bar(x) { return x; }
+    
+    var f = foo;
+    var g = bar;
+    
+    var result = 0;
+    var n = 100000;
+    for (var i = 0; i &lt; n; ++i) {
+        result += f(42);
+        
+        var tmp = f;
+        f = g;
+        g = tmp;
+    }
+    
+    if (result != n / 2 * 42 + n / 2 * 1)
+        throw &quot;Error: bad result: &quot; + result;
+})();
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregresssimplepolycallexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/simple-poly-call-expected.txt (0 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/simple-poly-call-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/simple-poly-call-expected.txt        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/simple-poly-call
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregresssimplepolycallnestedexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/simple-poly-call-nested-expected.txt (0 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/simple-poly-call-nested-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/simple-poly-call-nested-expected.txt        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/simple-poly-call-nested
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregresssimplepolycallnestedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/simple-poly-call-nested.html (0 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/simple-poly-call-nested.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/simple-poly-call-nested.html        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/simple-poly-call-nested.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregresssimplepolycallhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/simple-poly-call.html (0 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/simple-poly-call.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/simple-poly-call.html        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/simple-poly-call.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -65,8 +65,11 @@
</span><span class="cx">     bytecode/ArrayProfile.cpp
</span><span class="cx">     bytecode/BytecodeBasicBlock.cpp
</span><span class="cx">     bytecode/BytecodeLivenessAnalysis.cpp
</span><ins>+    bytecode/CallEdge.cpp
+    bytecode/CallEdgeProfile.cpp
</ins><span class="cx">     bytecode/CallLinkInfo.cpp
</span><span class="cx">     bytecode/CallLinkStatus.cpp
</span><ins>+    bytecode/CallVariant.cpp
</ins><span class="cx">     bytecode/CodeBlock.cpp
</span><span class="cx">     bytecode/CodeBlockHash.cpp
</span><span class="cx">     bytecode/CodeBlockJettisoningWatchpoint.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -1,3 +1,266 @@
</span><ins>+2014-08-24  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        FTL should be able to do polymorphic call inlining
+        https://bugs.webkit.org/show_bug.cgi?id=135145
+
+        Reviewed by Geoffrey Garen.
+        
+        Added a log-based high-fidelity call edge profiler that runs in DFG JIT (and optionally
+        baseline JIT) code. Used it to do precise polymorphic inlining in the FTL. Potential
+        inlining sites use the call edge profile if it is available, but they will still fall back
+        on the call inline cache and rare case counts if it's not. Polymorphic inlining means that
+        multiple possible callees can be inlined with a switch to guard them. The slow path may
+        either be an OSR exit or a virtual call.
+        
+        The call edge profiling added in this patch is very precise - it will tell you about every
+        call that has ever happened. It took some effort to reduce the overhead of this profiling.
+        This mostly involved ensuring that we don't do it unnecessarily. For example, we avoid it
+        in the baseline JIT (you can conditionally enable it but it's off by default) and we only do
+        it in the DFG JIT if we know that the regular inline cache profiling wasn't precise enough.
+        I also experimented with reducing the precision of the profiling. This led to a significant
+        reduction in the speed-up, so I avoided this approach. I also explored making log processing
+        concurrent, but that didn't help. Also, I tested the overhead of the log processing and
+        found that most of the overhead of this profiling is actually in putting things into the log
+        rather than in processing the log - that part appears to be surprisingly cheap.
+        
+        Polymorphic inlining could be enabled in the DFG if we enabled baseline call edge profiling,
+        and if we guarded such inlining sites with some profiling mechanism to detect
+        polyvariant monomorphisation opportunities (where the callsite being inlined reveals that
+        it's actually monomorphic).
+        
+        This is a ~28% speed-up on deltablue and a ~7% speed-up on richards, with small speed-ups on
+        other programs as well. It's about a 2% speed-up on Octane version 2, and never a regression
+        on anything we care about. Some aggregates, like V8Spider, see a regression. This is
+        highlighting the increase in profiling overhead. But since this doesn't show up on any major
+        score (code-load or SunSpider), it's probably not relevant.
+        
+        * CMakeLists.txt:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/CallEdge.cpp: Added.
+        (JSC::CallEdge::dump):
+        * bytecode/CallEdge.h: Added.
+        (JSC::CallEdge::operator!):
+        (JSC::CallEdge::callee):
+        (JSC::CallEdge::count):
+        (JSC::CallEdge::despecifiedClosure):
+        (JSC::CallEdge::CallEdge):
+        * bytecode/CallEdgeProfile.cpp: Added.
+        (JSC::CallEdgeProfile::callEdges):
+        (JSC::CallEdgeProfile::numCallsToKnownCells):
+        (JSC::worthDespecifying):
+        (JSC::CallEdgeProfile::worthDespecifying):
+        (JSC::CallEdgeProfile::visitWeak):
+        (JSC::CallEdgeProfile::addSlow):
+        (JSC::CallEdgeProfile::mergeBack):
+        (JSC::CallEdgeProfile::fadeByHalf):
+        (JSC::CallEdgeLog::CallEdgeLog):
+        (JSC::CallEdgeLog::~CallEdgeLog):
+        (JSC::CallEdgeLog::isEnabled):
+        (JSC::operationProcessCallEdgeLog):
+        (JSC::CallEdgeLog::emitLogCode):
+        (JSC::CallEdgeLog::processLog):
+        * bytecode/CallEdgeProfile.h: Added.
+        (JSC::CallEdgeProfile::numCallsToNotCell):
+        (JSC::CallEdgeProfile::numCallsToUnknownCell):
+        (JSC::CallEdgeProfile::totalCalls):
+        * bytecode/CallEdgeProfileInlines.h: Added.
+        (JSC::CallEdgeProfile::CallEdgeProfile):
+        (JSC::CallEdgeProfile::add):
+        * bytecode/CallLinkInfo.cpp:
+        (JSC::CallLinkInfo::visitWeak):
+        * bytecode/CallLinkInfo.h:
+        * bytecode/CallLinkStatus.cpp:
+        (JSC::CallLinkStatus::CallLinkStatus):
+        (JSC::CallLinkStatus::computeFromLLInt):
+        (JSC::CallLinkStatus::computeFor):
+        (JSC::CallLinkStatus::computeExitSiteData):
+        (JSC::CallLinkStatus::computeFromCallLinkInfo):
+        (JSC::CallLinkStatus::computeFromCallEdgeProfile):
+        (JSC::CallLinkStatus::computeDFGStatuses):
+        (JSC::CallLinkStatus::isClosureCall):
+        (JSC::CallLinkStatus::makeClosureCall):
+        (JSC::CallLinkStatus::dump):
+        (JSC::CallLinkStatus::function): Deleted.
+        (JSC::CallLinkStatus::internalFunction): Deleted.
+        (JSC::CallLinkStatus::intrinsicFor): Deleted.
+        * bytecode/CallLinkStatus.h:
+        (JSC::CallLinkStatus::CallLinkStatus):
+        (JSC::CallLinkStatus::isSet):
+        (JSC::CallLinkStatus::couldTakeSlowPath):
+        (JSC::CallLinkStatus::edges):
+        (JSC::CallLinkStatus::size):
+        (JSC::CallLinkStatus::at):
+        (JSC::CallLinkStatus::operator[]):
+        (JSC::CallLinkStatus::canOptimize):
+        (JSC::CallLinkStatus::canTrustCounts):
+        (JSC::CallLinkStatus::isClosureCall): Deleted.
+        (JSC::CallLinkStatus::callTarget): Deleted.
+        (JSC::CallLinkStatus::executable): Deleted.
+        (JSC::CallLinkStatus::makeClosureCall): Deleted.
+        * bytecode/CallVariant.cpp: Added.
+        (JSC::CallVariant::dump):
+        * bytecode/CallVariant.h: Added.
+        (JSC::CallVariant::CallVariant):
+        (JSC::CallVariant::operator!):
+        (JSC::CallVariant::despecifiedClosure):
+        (JSC::CallVariant::rawCalleeCell):
+        (JSC::CallVariant::internalFunction):
+        (JSC::CallVariant::function):
+        (JSC::CallVariant::isClosureCall):
+        (JSC::CallVariant::executable):
+        (JSC::CallVariant::nonExecutableCallee):
+        (JSC::CallVariant::intrinsicFor):
+        (JSC::CallVariant::functionExecutable):
+        (JSC::CallVariant::isHashTableDeletedValue):
+        (JSC::CallVariant::operator==):
+        (JSC::CallVariant::operator!=):
+        (JSC::CallVariant::operator&lt;):
+        (JSC::CallVariant::operator&gt;):
+        (JSC::CallVariant::operator&lt;=):
+        (JSC::CallVariant::operator&gt;=):
+        (JSC::CallVariant::hash):
+        (JSC::CallVariant::deletedToken):
+        (JSC::CallVariantHash::hash):
+        (JSC::CallVariantHash::equal):
+        * bytecode/CodeOrigin.h:
+        (JSC::InlineCallFrame::isNormalCall):
+        * bytecode/ExitKind.cpp:
+        (JSC::exitKindToString):
+        * bytecode/ExitKind.h:
+        * bytecode/GetByIdStatus.cpp:
+        (JSC::GetByIdStatus::computeForStubInfo):
+        * bytecode/PutByIdStatus.cpp:
+        (JSC::PutByIdStatus::computeForStubInfo):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGBackwardsPropagationPhase.cpp:
+        (JSC::DFG::BackwardsPropagationPhase::propagate):
+        * dfg/DFGBasicBlock.cpp:
+        (JSC::DFG::BasicBlock::~BasicBlock):
+        * dfg/DFGBasicBlock.h:
+        (JSC::DFG::BasicBlock::takeLast):
+        (JSC::DFG::BasicBlock::didLink):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::processSetLocalQueue):
+        (JSC::DFG::ByteCodeParser::removeLastNodeFromGraph):
+        (JSC::DFG::ByteCodeParser::addCallWithoutSettingResult):
+        (JSC::DFG::ByteCodeParser::addCall):
+        (JSC::DFG::ByteCodeParser::handleCall):
+        (JSC::DFG::ByteCodeParser::emitFunctionChecks):
+        (JSC::DFG::ByteCodeParser::undoFunctionChecks):
+        (JSC::DFG::ByteCodeParser::inliningCost):
+        (JSC::DFG::ByteCodeParser::inlineCall):
+        (JSC::DFG::ByteCodeParser::cancelLinkingForBlock):
+        (JSC::DFG::ByteCodeParser::attemptToInlineCall):
+        (JSC::DFG::ByteCodeParser::handleInlining):
+        (JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
+        (JSC::DFG::ByteCodeParser::prepareToParseBlock):
+        (JSC::DFG::ByteCodeParser::clearCaches):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        (JSC::DFG::ByteCodeParser::linkBlock):
+        (JSC::DFG::ByteCodeParser::linkBlocks):
+        (JSC::DFG::ByteCodeParser::parseCodeBlock):
+        * dfg/DFGCPSRethreadingPhase.cpp:
+        (JSC::DFG::CPSRethreadingPhase::freeUnnecessaryNodes):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGCommon.h:
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGDriver.cpp:
+        (JSC::DFG::compileImpl):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::dump):
+        (JSC::DFG::Graph::visitChildren):
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::link):
+        * dfg/DFGLazyJSValue.cpp:
+        (JSC::DFG::LazyJSValue::switchLookupValue):
+        * dfg/DFGLazyJSValue.h:
+        (JSC::DFG::LazyJSValue::switchLookupValue): Deleted.
+        * dfg/DFGNode.cpp:
+        (WTF::printInternal):
+        * dfg/DFGNode.h:
+        (JSC::DFG::OpInfo::OpInfo):
+        (JSC::DFG::Node::hasHeapPrediction):
+        (JSC::DFG::Node::hasCellOperand):
+        (JSC::DFG::Node::cellOperand):
+        (JSC::DFG::Node::setCellOperand):
+        (JSC::DFG::Node::canBeKnownFunction): Deleted.
+        (JSC::DFG::Node::hasKnownFunction): Deleted.
+        (JSC::DFG::Node::knownFunction): Deleted.
+        (JSC::DFG::Node::giveKnownFunction): Deleted.
+        (JSC::DFG::Node::hasFunction): Deleted.
+        (JSC::DFG::Node::function): Deleted.
+        (JSC::DFG::Node::hasExecutable): Deleted.
+        (JSC::DFG::Node::executable): Deleted.
+        * dfg/DFGNodeType.h:
+        * dfg/DFGPhantomCanonicalizationPhase.cpp:
+        (JSC::DFG::PhantomCanonicalizationPhase::run):
+        * dfg/DFGPhantomRemovalPhase.cpp:
+        (JSC::DFG::PhantomRemovalPhase::run):
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::emitSwitch):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::emitCall):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::emitCall):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGStructureRegistrationPhase.cpp:
+        (JSC::DFG::StructureRegistrationPhase::run):
+        * dfg/DFGTierUpCheckInjectionPhase.cpp:
+        (JSC::DFG::TierUpCheckInjectionPhase::run):
+        (JSC::DFG::TierUpCheckInjectionPhase::removeFTLProfiling):
+        * dfg/DFGValidate.cpp:
+        (JSC::DFG::Validate::validate):
+        * dfg/DFGWatchpointCollectionPhase.cpp:
+        (JSC::DFG::WatchpointCollectionPhase::handle):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::ftlUnreachable):
+        (JSC::FTL::LowerDFGToLLVM::lower):
+        (JSC::FTL::LowerDFGToLLVM::compileNode):
+        (JSC::FTL::LowerDFGToLLVM::compileCheckCell):
+        (JSC::FTL::LowerDFGToLLVM::compileCheckBadCell):
+        (JSC::FTL::LowerDFGToLLVM::compileGetExecutable):
+        (JSC::FTL::LowerDFGToLLVM::compileNativeCallOrConstruct):
+        (JSC::FTL::LowerDFGToLLVM::compileSwitch):
+        (JSC::FTL::LowerDFGToLLVM::buildSwitch):
+        (JSC::FTL::LowerDFGToLLVM::compileCheckFunction): Deleted.
+        (JSC::FTL::LowerDFGToLLVM::compileCheckExecutable): Deleted.
+        * heap/Heap.cpp:
+        (JSC::Heap::collect):
+        * jit/AssemblyHelpers.h:
+        (JSC::AssemblyHelpers::storeValue):
+        (JSC::AssemblyHelpers::loadValue):
+        * jit/CCallHelpers.h:
+        (JSC::CCallHelpers::setupArguments):
+        * jit/GPRInfo.h:
+        (JSC::JSValueRegs::uses):
+        * jit/JITCall.cpp:
+        (JSC::JIT::compileOpCall):
+        * jit/JITCall32_64.cpp:
+        (JSC::JIT::compileOpCall):
+        * runtime/Options.h:
+        * runtime/VM.cpp:
+        (JSC::VM::ensureCallEdgeLog):
+        * runtime/VM.h:
+        * tests/stress/new-array-then-exit.js: Added.
+        (foo):
+        * tests/stress/poly-call-exit-this.js: Added.
+        * tests/stress/poly-call-exit.js: Added.
+
</ins><span class="cx"> 2014-08-22  Michael Saboff  &lt;msaboff@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         After r172867 another crash in in js/dom/line-column-numbers.html
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -314,8 +314,11 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\ArrayProfile.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\BytecodeBasicBlock.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\BytecodeLivenessAnalysis.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\bytecode\CallEdge.cpp&quot; /&gt;
+    &lt;ClCompile Include=&quot;..\bytecode\CallEdgeProfile.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\CallLinkInfo.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\CallLinkStatus.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\bytecode\CallVariant.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\CodeBlock.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\CodeBlockHash.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\CodeBlockJettisoningWatchpoint.cpp&quot; /&gt;
</span><span class="lines">@@ -905,9 +908,13 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\BytecodeBasicBlock.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\BytecodeLivenessAnalysis.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\BytecodeUseDef.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\bytecode\CallEdge.h&quot; /&gt;
+    &lt;ClInclude Include=&quot;..\bytecode\CallEdgeProfile.h&quot; /&gt;
+    &lt;ClInclude Include=&quot;..\bytecode\CallEdgeProfileInlines.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\CallLinkInfo.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\CallLinkStatus.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\CallReturnOffsetToBytecodeOffset.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\bytecode\CallVariant.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\CodeBlock.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\CodeBlockHash.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\CodeBlockJettisoningWatchpoint.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -263,6 +263,13 @@
</span><span class="cx">                 0F3B3A281544C997003ED0FF /* DFGCFGSimplificationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B3A251544C991003ED0FF /* DFGCFGSimplificationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F3B3A2B15475000003ED0FF /* DFGValidate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3B3A2915474FF4003ED0FF /* DFGValidate.cpp */; };
</span><span class="cx">                 0F3B3A2C15475002003ED0FF /* DFGValidate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B3A2A15474FF4003ED0FF /* DFGValidate.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F3B7E2619A11B8000D9BC56 /* CallEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B7E2019A11B8000D9BC56 /* CallEdge.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F3B7E2719A11B8000D9BC56 /* CallEdgeProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3B7E2119A11B8000D9BC56 /* CallEdgeProfile.cpp */; };
+                0F3B7E2819A11B8000D9BC56 /* CallEdgeProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B7E2219A11B8000D9BC56 /* CallEdgeProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F3B7E2919A11B8000D9BC56 /* CallEdgeProfileInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B7E2319A11B8000D9BC56 /* CallEdgeProfileInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F3B7E2A19A11B8000D9BC56 /* CallVariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3B7E2419A11B8000D9BC56 /* CallVariant.cpp */; };
+                0F3B7E2B19A11B8000D9BC56 /* CallVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B7E2519A11B8000D9BC56 /* CallVariant.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0F3B7E2D19A12AAE00D9BC56 /* CallEdge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3B7E2C19A12AAE00D9BC56 /* CallEdge.cpp */; };
</ins><span class="cx">                 0F3D0BBC194A414300FC9CF9 /* ConstantStructureCheck.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3D0BBA194A414300FC9CF9 /* ConstantStructureCheck.cpp */; };
</span><span class="cx">                 0F3D0BBD194A414300FC9CF9 /* ConstantStructureCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3D0BBB194A414300FC9CF9 /* ConstantStructureCheck.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F426A481460CBB300131F8F /* ValueRecovery.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F426A451460CBAB00131F8F /* ValueRecovery.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -2169,6 +2176,13 @@
</span><span class="cx">                 0F3B3A251544C991003ED0FF /* DFGCFGSimplificationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCFGSimplificationPhase.h; path = dfg/DFGCFGSimplificationPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F3B3A2915474FF4003ED0FF /* DFGValidate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGValidate.cpp; path = dfg/DFGValidate.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F3B3A2A15474FF4003ED0FF /* DFGValidate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGValidate.h; path = dfg/DFGValidate.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F3B7E2019A11B8000D9BC56 /* CallEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallEdge.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F3B7E2119A11B8000D9BC56 /* CallEdgeProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallEdgeProfile.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F3B7E2219A11B8000D9BC56 /* CallEdgeProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallEdgeProfile.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F3B7E2319A11B8000D9BC56 /* CallEdgeProfileInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallEdgeProfileInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F3B7E2419A11B8000D9BC56 /* CallVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallVariant.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F3B7E2519A11B8000D9BC56 /* CallVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallVariant.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F3B7E2C19A12AAE00D9BC56 /* CallEdge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallEdge.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F3D0BBA194A414300FC9CF9 /* ConstantStructureCheck.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConstantStructureCheck.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F3D0BBB194A414300FC9CF9 /* ConstantStructureCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantStructureCheck.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F426A451460CBAB00131F8F /* ValueRecovery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueRecovery.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5146,11 +5160,18 @@
</span><span class="cx">                                 0F666EBE183566F900D017F1 /* BytecodeLivenessAnalysisInlines.h */,
</span><span class="cx">                                 0F885E101849A3BE00F1E3FA /* BytecodeUseDef.h */,
</span><span class="cx">                                 0F8023E91613832300A0BA45 /* ByValInfo.h */,
</span><ins>+                                0F3B7E2C19A12AAE00D9BC56 /* CallEdge.cpp */,
+                                0F3B7E2019A11B8000D9BC56 /* CallEdge.h */,
+                                0F3B7E2119A11B8000D9BC56 /* CallEdgeProfile.cpp */,
+                                0F3B7E2219A11B8000D9BC56 /* CallEdgeProfile.h */,
+                                0F3B7E2319A11B8000D9BC56 /* CallEdgeProfileInlines.h */,
</ins><span class="cx">                                 0F0B83AE14BCF71400885B4F /* CallLinkInfo.cpp */,
</span><span class="cx">                                 0F0B83AF14BCF71400885B4F /* CallLinkInfo.h */,
</span><span class="cx">                                 0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */,
</span><span class="cx">                                 0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */,
</span><span class="cx">                                 0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */,
</span><ins>+                                0F3B7E2419A11B8000D9BC56 /* CallVariant.cpp */,
+                                0F3B7E2519A11B8000D9BC56 /* CallVariant.h */,
</ins><span class="cx">                                 969A07900ED1D3AE00F1F681 /* CodeBlock.cpp */,
</span><span class="cx">                                 969A07910ED1D3AE00F1F681 /* CodeBlock.h */,
</span><span class="cx">                                 0F8F943D1667632D00D61971 /* CodeBlockHash.cpp */,
</span><span class="lines">@@ -5879,6 +5900,7 @@
</span><span class="cx">                                 0FFFC95A14EF90A900C72532 /* DFGCSEPhase.h in Headers */,
</span><span class="cx">                                 0F2FC77316E12F740038D976 /* DFGDCEPhase.h in Headers */,
</span><span class="cx">                                 0F8F2B9A172F0501007DBDA5 /* DFGDesiredIdentifiers.h in Headers */,
</span><ins>+                                0F3B7E2819A11B8000D9BC56 /* CallEdgeProfile.h in Headers */,
</ins><span class="cx">                                 C2C0F7CE17BBFC5B00464FE4 /* DFGDesiredTransitions.h in Headers */,
</span><span class="cx">                                 0FE8534C1723CDA500B618F5 /* DFGDesiredWatchpoints.h in Headers */,
</span><span class="cx">                                 C2981FD917BAEE4B00A3BC98 /* DFGDesiredWeakReferences.h in Headers */,
</span><span class="lines">@@ -6147,6 +6169,7 @@
</span><span class="cx">                                 0F766D3115AA8112008F363E /* JITStubRoutine.h in Headers */,
</span><span class="cx">                                 0F766D2C15A8CC3A008F363E /* JITStubRoutineSet.h in Headers */,
</span><span class="cx">                                 14C5242B0F5355E900BA3D04 /* JITStubs.h in Headers */,
</span><ins>+                                0F3B7E2B19A11B8000D9BC56 /* CallVariant.h in Headers */,
</ins><span class="cx">                                 FEF6835E174343CC00A32E25 /* JITStubsARM.h in Headers */,
</span><span class="cx">                                 FEF6835F174343CC00A32E25 /* JITStubsARMv7.h in Headers */,
</span><span class="cx">                                 FEF68361174343CC00A32E25 /* JITStubsX86.h in Headers */,
</span><span class="lines">@@ -6158,6 +6181,7 @@
</span><span class="cx">                                 A76F54A313B28AAB00EF2BCE /* JITWriteBarrier.h in Headers */,
</span><span class="cx">                                 BC18C4160E16F5CD00B34460 /* JSActivation.h in Headers */,
</span><span class="cx">                                 840480131021A1D9008E7F01 /* JSAPIValueWrapper.h in Headers */,
</span><ins>+                                0F3B7E2919A11B8000D9BC56 /* CallEdgeProfileInlines.h in Headers */,
</ins><span class="cx">                                 C2CF39C216E15A8100DD69BE /* JSAPIWrapperObject.h in Headers */,
</span><span class="cx">                                 A76140D2182982CB00750624 /* JSArgumentsIterator.h in Headers */,
</span><span class="cx">                                 BC18C4170E16F5CD00B34460 /* JSArray.h in Headers */,
</span><span class="lines">@@ -6473,6 +6497,7 @@
</span><span class="cx">                                 E49DC16C12EF294E00184A1F /* SourceProviderCache.h in Headers */,
</span><span class="cx">                                 E49DC16D12EF295300184A1F /* SourceProviderCacheItem.h in Headers */,
</span><span class="cx">                                 0FB7F39E15ED8E4600F167B2 /* SparseArrayValueMap.h in Headers */,
</span><ins>+                                0F3B7E2619A11B8000D9BC56 /* CallEdge.h in Headers */,
</ins><span class="cx">                                 A7386554118697B400540279 /* SpecializedThunkJIT.h in Headers */,
</span><span class="cx">                                 0F5541B21613C1FB00CE3E25 /* SpecialPointer.h in Headers */,
</span><span class="cx">                                 0FD82E54141DAEEE00179C94 /* SpeculatedType.h in Headers */,
</span><span class="lines">@@ -7327,6 +7352,7 @@
</span><span class="cx">                                 0F235BD517178E1C00690C7F /* FTLExitArgumentForOperand.cpp in Sources */,
</span><span class="cx">                                 0F235BD817178E1C00690C7F /* FTLExitThunkGenerator.cpp in Sources */,
</span><span class="cx">                                 0F235BDA17178E1C00690C7F /* FTLExitValue.cpp in Sources */,
</span><ins>+                                0F3B7E2719A11B8000D9BC56 /* CallEdgeProfile.cpp in Sources */,
</ins><span class="cx">                                 A7F2996B17A0BB670010417A /* FTLFail.cpp in Sources */,
</span><span class="cx">                                 0FD8A31917D51F2200CA2C40 /* FTLForOSREntryJITCode.cpp in Sources */,
</span><span class="cx">                                 0F25F1AF181635F300522F39 /* FTLInlineCacheSize.cpp in Sources */,
</span><span class="lines">@@ -7513,6 +7539,7 @@
</span><span class="cx">                                 0F4680D214BBD16500BFE272 /* LLIntData.cpp in Sources */,
</span><span class="cx">                                 0F38B01117CF078000B144D3 /* LLIntEntrypoint.cpp in Sources */,
</span><span class="cx">                                 0F4680A814BA7FAB00BFE272 /* LLIntExceptions.cpp in Sources */,
</span><ins>+                                0F3B7E2D19A12AAE00D9BC56 /* CallEdge.cpp in Sources */,
</ins><span class="cx">                                 0F4680A414BA7F8D00BFE272 /* LLIntSlowPaths.cpp in Sources */,
</span><span class="cx">                                 0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */,
</span><span class="cx">                                 0FCEFACD1805E75500472CE4 /* LLVMAPI.cpp in Sources */,
</span><span class="lines">@@ -7674,6 +7701,7 @@
</span><span class="cx">                                 14E84FA014EE1ACC00D6D5D4 /* WeakSet.cpp in Sources */,
</span><span class="cx">                                 2A4EC90B1860D6C20094F782 /* WriteBarrierBuffer.cpp in Sources */,
</span><span class="cx">                                 0FC8150B14043C0E00CFA603 /* WriteBarrierSupport.cpp in Sources */,
</span><ins>+                                0F3B7E2A19A11B8000D9BC56 /* CallVariant.cpp in Sources */,
</ins><span class="cx">                                 A7E5AB3A1799E4B200D2833D /* X86Disassembler.cpp in Sources */,
</span><span class="cx">                                 863C6D9C1521111A00585E4E /* YarrCanonicalizeUCS2.cpp in Sources */,
</span><span class="cx">                                 86704B8412DBA33700A9FE7B /* YarrInterpreter.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallEdgecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/CallEdge.cpp (0 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallEdge.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/CallEdge.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;CallEdge.h&quot;
+
+namespace JSC {
+
+void CallEdge::dump(PrintStream&amp; out) const
+{
+    out.print(&quot;&lt;&quot;, m_callee, &quot;, count: &quot;, m_count, &quot;&gt;&quot;);
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallEdgeh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/CallEdge.h (0 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallEdge.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/CallEdge.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -0,0 +1,73 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef CallEdge_h
+#define CallEdge_h
+
+#include &quot;CallVariant.h&quot;
+
+namespace JSC {
+
+typedef uint16_t CallEdgeCountType;
+
+class CallEdge {
+public:
+    CallEdge();
+    CallEdge(CallVariant, CallEdgeCountType);
+    
+    bool operator!() const { return !m_callee; }
+    
+    CallVariant callee() const { return m_callee; }
+    CallEdgeCountType count() const { return m_count; }
+    
+    CallEdge despecifiedClosure() const
+    {
+        return CallEdge(m_callee.despecifiedClosure(), m_count);
+    }
+    
+    void dump(PrintStream&amp;) const;
+    
+public:
+    CallVariant m_callee;
+    CallEdgeCountType m_count;
+};
+
+inline CallEdge::CallEdge(CallVariant callee, CallEdgeCountType count)
+    : m_callee(callee)
+    , m_count(count)
+{
+}
+
+inline CallEdge::CallEdge()
+    : CallEdge(CallVariant(), 0)
+{
+}
+
+typedef Vector&lt;CallEdge, 1&gt; CallEdgeList;
+
+} // namespace JSC
+
+#endif // CallEdge_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallEdgeProfilecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/CallEdgeProfile.cpp (0 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallEdgeProfile.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/CallEdgeProfile.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -0,0 +1,348 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;CallEdgeProfile.h&quot;
+
+#include &quot;CCallHelpers.h&quot;
+#include &quot;CallEdgeProfileInlines.h&quot;
+#include &quot;JITOperations.h&quot;
+#include &quot;JSCInlines.h&quot;
+
+namespace JSC {
+
+CallEdgeList CallEdgeProfile::callEdges() const
+{
+    ConcurrentJITLocker locker(m_lock);
+    
+    CallEdgeList result;
+    
+    CallVariant primaryCallee = m_primaryCallee;
+    CallEdgeCountType numCallsToPrimary = m_numCallsToPrimary;
+    // Defend against races. These fields are modified by the log processor without locking.
+    if (!!primaryCallee &amp;&amp; numCallsToPrimary)
+        result.append(CallEdge(primaryCallee, numCallsToPrimary));
+    
+    if (m_otherCallees) {
+        // Make sure that if the primary thread had just created a m_otherCalles while log
+        // processing, we see a consistently created one. The lock being held is insufficient for
+        // this, since the log processor will only grab the lock when merging the secondary
+        // spectrum into the primary one but may still create the data structure without holding
+        // locks.
+        WTF::loadLoadFence();
+        for (CallEdge&amp; entry : m_otherCallees-&gt;m_processed) {
+            // Defend against the possibility that the primary duplicates an entry in the secondary
+            // spectrum. That can happen when the GC removes the primary. We could have the GC fix
+            // the situation by changing the primary to be something from the secondary spectrum,
+            // but this fix seems simpler to implement and also cheaper.
+            if (entry.callee() == result[0].callee()) {
+                result[0] = CallEdge(result[0].callee(), entry.count() + result[0].count());
+                continue;
+            }
+            
+            result.append(entry);
+        }
+    }
+    
+    std::sort(result.begin(), result.end(), [] (const CallEdge&amp; a, const CallEdge&amp; b) -&gt; bool {
+            return a.count() &gt; b.count();
+        });
+    
+    if (result.size() &gt;= 2)
+        ASSERT(result[0].count() &gt;= result.last().count());
+    
+    return result;
+}
+
+CallEdgeCountType CallEdgeProfile::numCallsToKnownCells() const
+{
+    CallEdgeCountType result = 0;
+    for (CallEdge&amp; edge : callEdges())
+        result += edge.count();
+    return result;
+}
+
+static bool worthDespecifying(const CallVariant&amp; variant)
+{
+    return !Heap::isMarked(variant.rawCalleeCell())
+        &amp;&amp; Heap::isMarked(variant.despecifiedClosure().rawCalleeCell());
+}
+
+bool CallEdgeProfile::worthDespecifying()
+{
+    if (m_closuresAreDespecified)
+        return false;
+    
+    if (!!m_primaryCallee &amp;&amp; !JSC::worthDespecifying(m_primaryCallee))
+        return false;
+    
+    if (m_otherCallees) {
+        for (unsigned i = m_otherCallees-&gt;m_processed.size(); i--;) {
+            if (!JSC::worthDespecifying(m_otherCallees-&gt;m_processed[i].callee()))
+                return false;
+        }
+    }
+    
+    return true;
+}
+
+void CallEdgeProfile::visitWeak()
+{
+    if (!m_primaryCallee &amp;&amp; !m_otherCallees)
+        return;
+    
+    ConcurrentJITLocker locker(m_lock);
+    
+    // See if anything is dead and if that can be rectified by despecifying.
+    if (worthDespecifying()) {
+        CallSpectrum newSpectrum;
+        
+        if (!!m_primaryCallee)
+            newSpectrum.add(m_primaryCallee.despecifiedClosure(), m_numCallsToPrimary);
+        
+        if (m_otherCallees) {
+            for (unsigned i = m_otherCallees-&gt;m_processed.size(); i--;) {
+                newSpectrum.add(
+                    m_otherCallees-&gt;m_processed[i].callee().despecifiedClosure(),
+                    m_otherCallees-&gt;m_processed[i].count());
+            }
+        }
+        
+        Vector&lt;CallSpectrum::KeyAndCount&gt; list = newSpectrum.buildList();
+        ASSERT(list.size());
+        m_primaryCallee = list.last().key;
+        m_numCallsToPrimary = list.last().count;
+        
+        ASSERT(!!m_otherCallees == (list.size() &gt;= 2));
+        if (m_otherCallees) {
+            m_otherCallees-&gt;m_processed.clear();
+            for (unsigned i = list.size() - 1; i--;)
+                m_otherCallees-&gt;m_processed.append(CallEdge(list[i].key, list[i].count));
+        }
+        
+        m_closuresAreDespecified = true;
+        
+        return;
+    }
+    
+    if (!!m_primaryCallee &amp;&amp; !Heap::isMarked(m_primaryCallee.rawCalleeCell())) {
+        m_numCallsToUnknownCell += m_numCallsToPrimary;
+        
+        m_primaryCallee = CallVariant();
+        m_numCallsToPrimary = 0;
+    }
+    
+    if (m_otherCallees) {
+        for (unsigned i = 0; i &lt; m_otherCallees-&gt;m_processed.size(); i++) {
+            if (Heap::isMarked(m_otherCallees-&gt;m_processed[i].callee().rawCalleeCell()))
+                continue;
+            
+            m_numCallsToUnknownCell += m_otherCallees-&gt;m_processed[i].count();
+            m_otherCallees-&gt;m_processed[i--] = m_otherCallees-&gt;m_processed.last();
+            m_otherCallees-&gt;m_processed.removeLast();
+        }
+        
+        // Only exists while we are processing the log.
+        RELEASE_ASSERT(!m_otherCallees-&gt;m_temporarySpectrum);
+    }
+}
+
+void CallEdgeProfile::addSlow(CallVariant callee, CallEdgeProfileVector&amp; mergeBackLog)
+{
+    // This exists to handle cases where the spectrum wasn't created yet, or we're storing to a
+    // particular spectrum for the first time during a log processing iteration.
+    
+    if (!m_otherCallees) {
+        m_otherCallees = std::make_unique&lt;Secondary&gt;();
+        // If a compiler thread notices the m_otherCallees being non-null, we want to make sure
+        // that it sees a fully created one.
+        WTF::storeStoreFence();
+    }
+    
+    if (!m_otherCallees-&gt;m_temporarySpectrum) {
+        m_otherCallees-&gt;m_temporarySpectrum = std::make_unique&lt;CallSpectrum&gt;();
+        for (unsigned i = m_otherCallees-&gt;m_processed.size(); i--;) {
+            m_otherCallees-&gt;m_temporarySpectrum-&gt;add(
+                m_otherCallees-&gt;m_processed[i].callee(),
+                m_otherCallees-&gt;m_processed[i].count());
+        }
+        
+        // This means that this is the first time we're seeing this profile during this log
+        // processing iteration.
+        mergeBackLog.append(this);
+    }
+    
+    m_otherCallees-&gt;m_temporarySpectrum-&gt;add(callee);
+}
+
+void CallEdgeProfile::mergeBack()
+{
+    ConcurrentJITLocker locker(m_lock);
+    
+    ASSERT(m_otherCallees);
+    ASSERT(m_otherCallees-&gt;m_temporarySpectrum);
+    
+    if (!!m_primaryCallee)
+        m_otherCallees-&gt;m_temporarySpectrum-&gt;add(m_primaryCallee, m_numCallsToPrimary);
+    
+    if (!m_closuresAreDespecified) {
+        CallSpectrum newSpectrum;
+        for (auto&amp; entry : *m_otherCallees-&gt;m_temporarySpectrum)
+            newSpectrum.add(entry.key.despecifiedClosure(), entry.value);
+        
+        if (newSpectrum.size() &lt; m_otherCallees-&gt;m_temporarySpectrum-&gt;size()) {
+            *m_otherCallees-&gt;m_temporarySpectrum = newSpectrum;
+            m_closuresAreDespecified = true;
+        }
+    }
+    
+    Vector&lt;CallSpectrum::KeyAndCount&gt; list = m_otherCallees-&gt;m_temporarySpectrum-&gt;buildList();
+    m_otherCallees-&gt;m_temporarySpectrum = nullptr;
+    
+    m_primaryCallee = list.last().key;
+    m_numCallsToPrimary = list.last().count;
+    list.removeLast();
+    
+    m_otherCallees-&gt;m_processed.clear();
+    for (unsigned count = maxKnownCallees; count-- &amp;&amp; !list.isEmpty();) {
+        m_otherCallees-&gt;m_processed.append(CallEdge(list.last().key, list.last().count));
+        list.removeLast();
+    }
+    
+    for (unsigned i = list.size(); i--;)
+        m_numCallsToUnknownCell += list[i].count;
+}
+
+void CallEdgeProfile::fadeByHalf()
+{
+    m_numCallsToPrimary &gt;&gt;= 1;
+    m_numCallsToNotCell &gt;&gt;= 1;
+    m_numCallsToUnknownCell &gt;&gt;= 1;
+    m_totalCount &gt;&gt;= 1;
+    
+    if (m_otherCallees) {
+        for (unsigned i = m_otherCallees-&gt;m_processed.size(); i--;) {
+            m_otherCallees-&gt;m_processed[i] = CallEdge(
+                m_otherCallees-&gt;m_processed[i].callee(),
+                m_otherCallees-&gt;m_processed[i].count() &gt;&gt; 1);
+        }
+        
+        if (m_otherCallees-&gt;m_temporarySpectrum) {
+            for (auto&amp; entry : *m_otherCallees-&gt;m_temporarySpectrum)
+                entry.value &gt;&gt;= 1;
+        }
+    }
+}
+
+CallEdgeLog::CallEdgeLog()
+    : m_scaledLogIndex(logSize * sizeof(Entry))
+{
+    ASSERT(!(m_scaledLogIndex % sizeof(Entry)));
+}
+
+CallEdgeLog::~CallEdgeLog() { }
+
+bool CallEdgeLog::isEnabled()
+{
+    return Options::enableCallEdgeProfiling() &amp;&amp; Options::useFTLJIT();
+}
+
+#if ENABLE(JIT)
+
+extern &quot;C&quot; JIT_OPERATION void operationProcessCallEdgeLog(CallEdgeLog*) WTF_INTERNAL;
+extern &quot;C&quot; JIT_OPERATION void operationProcessCallEdgeLog(CallEdgeLog* log)
+{
+    log-&gt;processLog();
+}
+
+void CallEdgeLog::emitLogCode(CCallHelpers&amp; jit, CallEdgeProfile&amp; profile, JSValueRegs calleeRegs)
+{
+    const unsigned numberOfArguments = 1;
+    
+    GPRReg scratchGPR;
+    if (!calleeRegs.uses(GPRInfo::regT0))
+        scratchGPR = GPRInfo::regT0;
+    else if (!calleeRegs.uses(GPRInfo::regT1))
+        scratchGPR = GPRInfo::regT1;
+    else
+        scratchGPR = GPRInfo::regT2;
+    
+    jit.load32(&amp;m_scaledLogIndex, scratchGPR);
+    
+    CCallHelpers::Jump ok = jit.branchTest32(CCallHelpers::NonZero, scratchGPR);
+    
+    ASSERT_UNUSED(numberOfArguments, stackAlignmentRegisters() &gt;= 1 + numberOfArguments);
+    
+    jit.subPtr(CCallHelpers::TrustedImm32(stackAlignmentBytes()), CCallHelpers::stackPointerRegister);
+    
+    jit.storeValue(calleeRegs, CCallHelpers::Address(CCallHelpers::stackPointerRegister, sizeof(JSValue)));
+    jit.setupArguments(CCallHelpers::TrustedImmPtr(this));
+    jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast&lt;void*&gt;(operationProcessCallEdgeLog)), GPRInfo::nonArgGPR0);
+    jit.call(GPRInfo::nonArgGPR0);
+    jit.loadValue(CCallHelpers::Address(CCallHelpers::stackPointerRegister, sizeof(JSValue)), calleeRegs);
+    
+    jit.addPtr(CCallHelpers::TrustedImm32(stackAlignmentBytes()), CCallHelpers::stackPointerRegister);
+    
+    jit.move(CCallHelpers::TrustedImm32(logSize * sizeof(Entry)), scratchGPR);
+    ok.link(&amp;jit);
+
+    jit.sub32(CCallHelpers::TrustedImm32(sizeof(Entry)), scratchGPR);
+    jit.store32(scratchGPR, &amp;m_scaledLogIndex);
+    jit.addPtr(CCallHelpers::TrustedImmPtr(m_log), scratchGPR);
+    jit.storeValue(calleeRegs, CCallHelpers::Address(scratchGPR, OBJECT_OFFSETOF(Entry, m_value)));
+    jit.storePtr(CCallHelpers::TrustedImmPtr(&amp;profile), CCallHelpers::Address(scratchGPR, OBJECT_OFFSETOF(Entry, m_profile)));
+}
+
+void CallEdgeLog::emitLogCode(
+    CCallHelpers&amp; jit, OwnPtr&lt;CallEdgeProfile&gt;&amp; profilePointer, JSValueRegs calleeRegs)
+{
+    if (!isEnabled())
+        return;
+    
+    profilePointer.createTransactionally();
+    emitLogCode(jit, *profilePointer, calleeRegs);
+}
+
+#endif // ENABLE(JIT)
+
+void CallEdgeLog::processLog()
+{
+    ASSERT(!(m_scaledLogIndex % sizeof(Entry)));
+    
+    if (Options::callEdgeProfileReallyProcessesLog()) {
+        CallEdgeProfileVector mergeBackLog;
+        
+        for (unsigned i = m_scaledLogIndex / sizeof(Entry); i &lt; logSize; ++i)
+            m_log[i].m_profile-&gt;add(m_log[i].m_value, mergeBackLog);
+        
+        for (unsigned i = mergeBackLog.size(); i--;)
+            mergeBackLog[i]-&gt;mergeBack();
+    }
+    
+    m_scaledLogIndex = logSize * sizeof(Entry);
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallEdgeProfileh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/CallEdgeProfile.h (0 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallEdgeProfile.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/CallEdgeProfile.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -0,0 +1,130 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef CallEdgeProfile_h
+#define CallEdgeProfile_h
+
+#include &quot;CallEdge.h&quot;
+#include &quot;CallVariant.h&quot;
+#include &quot;ConcurrentJITLock.h&quot;
+#include &quot;JSCell.h&quot;
+#include &lt;wtf/OwnPtr.h&gt;
+
+namespace JSC {
+
+class CCallHelpers;
+class LLIntOffsetsExtractor;
+
+class CallEdgeLog;
+class CallEdgeProfile;
+typedef Vector&lt;CallEdgeProfile*, 10&gt; CallEdgeProfileVector;
+
+class CallEdgeProfile {
+public:
+    CallEdgeProfile();
+    
+    CallEdgeCountType numCallsToNotCell() const { return m_numCallsToNotCell; }
+    CallEdgeCountType numCallsToUnknownCell() const { return m_numCallsToUnknownCell; }
+    CallEdgeCountType numCallsToKnownCells() const;
+    
+    CallEdgeCountType totalCalls() const { return m_totalCount; }
+    
+    // Call while holding the owning CodeBlock's lock.
+    CallEdgeList callEdges() const;
+    
+    void visitWeak();
+    
+private:
+    friend class CallEdgeLog;
+    
+    static const unsigned maxKnownCallees = 5;
+    
+    void add(JSValue, CallEdgeProfileVector&amp; mergeBackLog);
+    
+    bool worthDespecifying();
+    void addSlow(CallVariant, CallEdgeProfileVector&amp; mergeBackLog);
+    void mergeBack();
+    void fadeByHalf();
+    
+    // It's cheaper to let this have its own lock. It needs to be able to find which lock to
+    // lock. Normally it would lock the owning CodeBlock's lock, but that would require a
+    // pointer-width word to point at the CodeBlock. Having the byte-sized lock here is
+    // cheaper. However, this means that the relationship with the CodeBlock lock is:
+    // acquire the CodeBlock lock before this one.
+    mutable ConcurrentJITLock m_lock;
+    
+    bool m_closuresAreDespecified;
+    
+    CallEdgeCountType m_numCallsToPrimary;
+    CallEdgeCountType m_numCallsToNotCell;
+    CallEdgeCountType m_numCallsToUnknownCell;
+    CallEdgeCountType m_totalCount;
+    CallVariant m_primaryCallee;
+    
+    typedef Spectrum&lt;CallVariant, CallEdgeCountType&gt; CallSpectrum;
+    
+    struct Secondary {
+        Vector&lt;CallEdge&gt; m_processed; // Processed but not necessarily sorted.
+        std::unique_ptr&lt;CallSpectrum&gt; m_temporarySpectrum;
+    };
+    
+    std::unique_ptr&lt;Secondary&gt; m_otherCallees;
+};
+
+class CallEdgeLog {
+public:
+    CallEdgeLog();
+    ~CallEdgeLog();
+
+    static bool isEnabled();
+    
+#if ENABLE(JIT)
+    void emitLogCode(CCallHelpers&amp;, CallEdgeProfile&amp;, JSValueRegs calleeRegs); // Assumes that stack is aligned, all volatile registers - other than calleeGPR - are clobberable, and the parameter space is in use.
+    
+    // Same as above but creates a CallEdgeProfile instance if one did not already exist. Does
+    // this in a thread-safe manner by calling OwnPtr::createTransactionally.
+    void emitLogCode(CCallHelpers&amp;, OwnPtr&lt;CallEdgeProfile&gt;&amp;, JSValueRegs calleeRegs);
+#endif // ENABLE(JIT)
+    
+    void processLog();
+    
+private:
+    friend class LLIntOffsetsExtractor;
+
+    static const unsigned logSize = 10000;
+    
+    struct Entry {
+        JSValue m_value;
+        CallEdgeProfile* m_profile;
+    };
+    
+    unsigned m_scaledLogIndex;
+    Entry m_log[logSize];
+};
+
+} // namespace JSC
+
+#endif // CallEdgeProfile_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallEdgeProfileInlinesh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/CallEdgeProfileInlines.h (0 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallEdgeProfileInlines.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/CallEdgeProfileInlines.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -0,0 +1,91 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef CallEdgeProfileInlines_h
+#define CallEdgeProfileInlines_h
+
+#include &quot;CallEdgeProfile.h&quot;
+
+namespace JSC {
+
+inline CallEdgeProfile::CallEdgeProfile()
+    : m_closuresAreDespecified(false)
+    , m_numCallsToPrimary(0)
+    , m_numCallsToNotCell(0)
+    , m_numCallsToUnknownCell(0)
+    , m_totalCount(0)
+    , m_primaryCallee(nullptr)
+{
+}
+
+ALWAYS_INLINE void CallEdgeProfile::add(JSValue value, CallEdgeProfileVector&amp; mergeBackLog)
+{
+    unsigned newTotalCount = m_totalCount + 1;
+    if (UNLIKELY(!newTotalCount)) {
+        fadeByHalf(); // Tackle overflows by dividing all counts by two.
+        newTotalCount = m_totalCount + 1;
+    }
+    ASSERT(newTotalCount);
+    m_totalCount = newTotalCount;
+    
+    if (UNLIKELY(!value.isCell())) {
+        m_numCallsToNotCell++;
+        return;
+    }
+
+    CallVariant callee = CallVariant(value.asCell());
+    
+    if (m_closuresAreDespecified)
+        callee = callee.despecifiedClosure();
+    
+    if (UNLIKELY(!m_primaryCallee)) {
+        m_primaryCallee = callee;
+        m_numCallsToPrimary = 1;
+        return;
+    }
+        
+    if (LIKELY(m_primaryCallee == callee)) {
+        m_numCallsToPrimary++;
+        return;
+    }
+        
+    if (UNLIKELY(!m_otherCallees)) {
+        addSlow(callee, mergeBackLog);
+        return;
+    }
+        
+    CallSpectrum* secondary = m_otherCallees-&gt;m_temporarySpectrum.get();
+    if (!secondary) {
+        addSlow(callee, mergeBackLog);
+        return;
+    }
+        
+    secondary-&gt;add(callee);
+}
+
+} // namespace JSC
+
+#endif // CallEdgeProfileInlines_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkInfocpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -83,6 +83,11 @@
</span><span class="cx">     }
</span><span class="cx">     if (!!lastSeenCallee &amp;&amp; !Heap::isMarked(lastSeenCallee.get()))
</span><span class="cx">         lastSeenCallee.clear();
</span><ins>+    
+    if (callEdgeProfile) {
+        WTF::loadLoadFence();
+        callEdgeProfile-&gt;visitWeak();
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> CallLinkInfo&amp; CallLinkInfo::dummy()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #ifndef CallLinkInfo_h
</span><span class="cx"> #define CallLinkInfo_h
</span><span class="cx"> 
</span><ins>+#include &quot;CallEdgeProfile.h&quot;
</ins><span class="cx"> #include &quot;ClosureCallStubRoutine.h&quot;
</span><span class="cx"> #include &quot;CodeLocation.h&quot;
</span><span class="cx"> #include &quot;CodeSpecializationKind.h&quot;
</span><span class="lines">@@ -33,6 +34,7 @@
</span><span class="cx"> #include &quot;JSFunction.h&quot;
</span><span class="cx"> #include &quot;Opcode.h&quot;
</span><span class="cx"> #include &quot;WriteBarrier.h&quot;
</span><ins>+#include &lt;wtf/OwnPtr.h&gt;
</ins><span class="cx"> #include &lt;wtf/SentinelLinkedList.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -88,6 +90,7 @@
</span><span class="cx">     unsigned calleeGPR : 8;
</span><span class="cx">     unsigned slowPathCount;
</span><span class="cx">     CodeOrigin codeOrigin;
</span><ins>+    OwnPtr&lt;CallEdgeProfile&gt; callEdgeProfile;
</ins><span class="cx"> 
</span><span class="cx">     bool isLinked() { return stub || callee; }
</span><span class="cx">     void unlink(RepatchBuffer&amp;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkStatuscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -32,62 +32,30 @@
</span><span class="cx"> #include &quot;LLIntCallLinkInfo.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &lt;wtf/CommaPrinter.h&gt;
</span><ins>+#include &lt;wtf/ListDump.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> static const bool verbose = false;
</span><span class="cx"> 
</span><span class="cx"> CallLinkStatus::CallLinkStatus(JSValue value)
</span><del>-    : m_callTarget(value)
-    , m_executable(0)
-    , m_couldTakeSlowPath(false)
</del><ins>+    : m_couldTakeSlowPath(false)
</ins><span class="cx">     , m_isProved(false)
</span><span class="cx"> {
</span><del>-    if (!value || !value.isCell())
</del><ins>+    if (!value || !value.isCell()) {
+        m_couldTakeSlowPath = true;
</ins><span class="cx">         return;
</span><ins>+    }
</ins><span class="cx">     
</span><del>-    if (!value.asCell()-&gt;inherits(JSFunction::info()))
-        return;
-    
-    m_executable = jsCast&lt;JSFunction*&gt;(value.asCell())-&gt;executable();
</del><ins>+    m_edges.append(CallEdge(CallVariant(value.asCell()), 1));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSFunction* CallLinkStatus::function() const
-{
-    if (!m_callTarget || !m_callTarget.isCell())
-        return 0;
-    
-    if (!m_callTarget.asCell()-&gt;inherits(JSFunction::info()))
-        return 0;
-    
-    return jsCast&lt;JSFunction*&gt;(m_callTarget.asCell());
-}
-
-InternalFunction* CallLinkStatus::internalFunction() const
-{
-    if (!m_callTarget || !m_callTarget.isCell())
-        return 0;
-    
-    if (!m_callTarget.asCell()-&gt;inherits(InternalFunction::info()))
-        return 0;
-    
-    return jsCast&lt;InternalFunction*&gt;(m_callTarget.asCell());
-}
-
-Intrinsic CallLinkStatus::intrinsicFor(CodeSpecializationKind kind) const
-{
-    if (!m_executable)
-        return NoIntrinsic;
-    
-    return m_executable-&gt;intrinsicFor(kind);
-}
-
</del><span class="cx"> CallLinkStatus CallLinkStatus::computeFromLLInt(const ConcurrentJITLocker&amp; locker, CodeBlock* profiledBlock, unsigned bytecodeIndex)
</span><span class="cx"> {
</span><span class="cx">     UNUSED_PARAM(profiledBlock);
</span><span class="cx">     UNUSED_PARAM(bytecodeIndex);
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><del>-    if (profiledBlock-&gt;hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadFunction))) {
</del><ins>+    if (profiledBlock-&gt;hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCell))) {
</ins><span class="cx">         // We could force this to be a closure call, but instead we'll just assume that it
</span><span class="cx">         // takes slow path.
</span><span class="cx">         return takesSlowPath();
</span><span class="lines">@@ -125,7 +93,7 @@
</span><span class="cx">     if (!callLinkInfo)
</span><span class="cx">         return computeFromLLInt(locker, profiledBlock, bytecodeIndex);
</span><span class="cx">     
</span><del>-    return computeFor(locker, *callLinkInfo, exitSiteData);
</del><ins>+    return computeFor(locker, profiledBlock, *callLinkInfo, exitSiteData);
</ins><span class="cx"> #else
</span><span class="cx">     return CallLinkStatus();
</span><span class="cx"> #endif
</span><span class="lines">@@ -139,10 +107,10 @@
</span><span class="cx">     
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     exitSiteData.m_takesSlowPath =
</span><del>-        profiledBlock-&gt;hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCache, exitingJITType))
</del><ins>+        profiledBlock-&gt;hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadType, exitingJITType))
</ins><span class="cx">         || profiledBlock-&gt;hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadExecutable, exitingJITType));
</span><span class="cx">     exitSiteData.m_badFunction =
</span><del>-        profiledBlock-&gt;hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadFunction, exitingJITType));
</del><ins>+        profiledBlock-&gt;hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCell, exitingJITType));
</ins><span class="cx"> #else
</span><span class="cx">     UNUSED_PARAM(locker);
</span><span class="cx">     UNUSED_PARAM(profiledBlock);
</span><span class="lines">@@ -154,8 +122,35 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(JIT)
</span><del>-CallLinkStatus CallLinkStatus::computeFor(const ConcurrentJITLocker&amp;, CallLinkInfo&amp; callLinkInfo)
</del><ins>+CallLinkStatus CallLinkStatus::computeFor(
+    const ConcurrentJITLocker&amp; locker, CodeBlock* profiledBlock, CallLinkInfo&amp; callLinkInfo)
</ins><span class="cx"> {
</span><ins>+    // We don't really need this, but anytime we have to debug this code, it becomes indispensable.
+    UNUSED_PARAM(profiledBlock);
+    
+    if (Options::callStatusShouldUseCallEdgeProfile()) {
+        // Always trust the call edge profile over anything else since this has precise counts.
+        // It can make the best possible decision because it never &quot;forgets&quot; what happened for any
+        // call, with the exception of fading out the counts of old calls (for example if the
+        // counter type is 16-bit then calls that happened more than 2^16 calls ago are given half
+        // weight, and this compounds for every 2^15 [sic] calls after that). The combination of
+        // high fidelity for recent calls and fading for older calls makes this the most useful
+        // mechamism of choosing how to optimize future calls.
+        CallEdgeProfile* edgeProfile = callLinkInfo.callEdgeProfile.get();
+        WTF::loadLoadFence();
+        if (edgeProfile) {
+            CallLinkStatus result = computeFromCallEdgeProfile(edgeProfile);
+            if (!!result)
+                return result;
+        }
+    }
+    
+    return computeFromCallLinkInfo(locker, callLinkInfo);
+}
+
+CallLinkStatus CallLinkStatus::computeFromCallLinkInfo(
+    const ConcurrentJITLocker&amp;, CallLinkInfo&amp; callLinkInfo)
+{
</ins><span class="cx">     // Note that despite requiring that the locker is held, this code is racy with respect
</span><span class="cx">     // to the CallLinkInfo: it may get cleared while this code runs! This is because
</span><span class="cx">     // CallLinkInfo::unlink() may be called from a different CodeBlock than the one that owns
</span><span class="lines">@@ -177,7 +172,7 @@
</span><span class="cx">     
</span><span class="cx">     JSFunction* target = callLinkInfo.lastSeenCallee.get();
</span><span class="cx">     if (!target)
</span><del>-        return CallLinkStatus();
</del><ins>+        return takesSlowPath();
</ins><span class="cx">     
</span><span class="cx">     if (callLinkInfo.hasSeenClosure)
</span><span class="cx">         return CallLinkStatus(target-&gt;executable());
</span><span class="lines">@@ -185,15 +180,43 @@
</span><span class="cx">     return CallLinkStatus(target);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-CallLinkStatus CallLinkStatus::computeFor(
-    const ConcurrentJITLocker&amp; locker, CallLinkInfo&amp; callLinkInfo, ExitSiteData exitSiteData)
</del><ins>+CallLinkStatus CallLinkStatus::computeFromCallEdgeProfile(CallEdgeProfile* edgeProfile)
</ins><span class="cx"> {
</span><del>-    if (exitSiteData.m_takesSlowPath)
</del><ins>+    // In cases where the call edge profile saw nothing, use the CallLinkInfo instead.
+    if (!edgeProfile-&gt;totalCalls())
+        return CallLinkStatus();
+    
+    // To do anything meaningful, we require that the majority of calls are to something we
+    // know how to handle.
+    unsigned numCallsToKnown = edgeProfile-&gt;numCallsToKnownCells();
+    unsigned numCallsToUnknown = edgeProfile-&gt;numCallsToNotCell() + edgeProfile-&gt;numCallsToUnknownCell();
+    
+    // We require that the majority of calls were to something that we could possibly inline.
+    if (numCallsToKnown &lt;= numCallsToUnknown)
</ins><span class="cx">         return takesSlowPath();
</span><span class="cx">     
</span><del>-    CallLinkStatus result = computeFor(locker, callLinkInfo);
</del><ins>+    // We require that the number of such calls is greater than some minimal threshold, so that we
+    // avoid inlining completely cold calls.
+    if (numCallsToKnown &lt; Options::frequentCallThreshold())
+        return takesSlowPath();
+    
+    CallLinkStatus result;
+    result.m_edges = edgeProfile-&gt;callEdges();
+    result.m_couldTakeSlowPath = !!numCallsToUnknown;
+    result.m_canTrustCounts = true;
+    
+    return result;
+}
+
+CallLinkStatus CallLinkStatus::computeFor(
+    const ConcurrentJITLocker&amp; locker, CodeBlock* profiledBlock, CallLinkInfo&amp; callLinkInfo,
+    ExitSiteData exitSiteData)
+{
+    CallLinkStatus result = computeFor(locker, profiledBlock, callLinkInfo);
</ins><span class="cx">     if (exitSiteData.m_badFunction)
</span><span class="cx">         result.makeClosureCall();
</span><ins>+    if (exitSiteData.m_takesSlowPath)
+        result.m_couldTakeSlowPath = true;
</ins><span class="cx">     
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="lines">@@ -227,7 +250,7 @@
</span><span class="cx">         
</span><span class="cx">         {
</span><span class="cx">             ConcurrentJITLocker locker(dfgCodeBlock-&gt;m_lock);
</span><del>-            map.add(info.codeOrigin, computeFor(locker, info, exitSiteData));
</del><ins>+            map.add(info.codeOrigin, computeFor(locker, dfgCodeBlock, info, exitSiteData));
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> #else
</span><span class="lines">@@ -256,6 +279,31 @@
</span><span class="cx">     return computeFor(profiledBlock, codeOrigin.bytecodeIndex, baselineMap);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool CallLinkStatus::isClosureCall() const
+{
+    for (unsigned i = m_edges.size(); i--;) {
+        if (m_edges[i].callee().isClosureCall())
+            return true;
+    }
+    return false;
+}
+
+void CallLinkStatus::makeClosureCall()
+{
+    ASSERT(!m_isProved);
+    for (unsigned i = m_edges.size(); i--;)
+        m_edges[i] = m_edges[i].despecifiedClosure();
+    
+    if (!ASSERT_DISABLED) {
+        // Doing this should not have created duplicates, because the CallEdgeProfile
+        // should despecify closures if doing so would reduce the number of known callees.
+        for (unsigned i = 0; i &lt; m_edges.size(); ++i) {
+            for (unsigned j = i + 1; j &lt; m_edges.size(); ++j)
+                ASSERT(m_edges[i].callee() != m_edges[j].callee());
+        }
+    }
+}
+
</ins><span class="cx"> void CallLinkStatus::dump(PrintStream&amp; out) const
</span><span class="cx"> {
</span><span class="cx">     if (!isSet()) {
</span><span class="lines">@@ -271,14 +319,7 @@
</span><span class="cx">     if (m_couldTakeSlowPath)
</span><span class="cx">         out.print(comma, &quot;Could Take Slow Path&quot;);
</span><span class="cx">     
</span><del>-    if (m_callTarget)
-        out.print(comma, &quot;Known target: &quot;, m_callTarget);
-    
-    if (m_executable) {
-        out.print(comma, &quot;Executable/CallHash: &quot;, RawPointer(m_executable));
-        if (!isCompilationThread())
-            out.print(&quot;/&quot;, m_executable-&gt;hashFor(CodeForCall));
-    }
</del><ins>+    out.print(listDump(m_edges));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkStatush"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -46,9 +46,9 @@
</span><span class="cx"> class CallLinkStatus {
</span><span class="cx"> public:
</span><span class="cx">     CallLinkStatus()
</span><del>-        : m_executable(0)
-        , m_couldTakeSlowPath(false)
</del><ins>+        : m_couldTakeSlowPath(false)
</ins><span class="cx">         , m_isProved(false)
</span><ins>+        , m_canTrustCounts(false)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -61,10 +61,11 @@
</span><span class="cx">     
</span><span class="cx">     explicit CallLinkStatus(JSValue);
</span><span class="cx">     
</span><del>-    CallLinkStatus(ExecutableBase* executable)
-        : m_executable(executable)
</del><ins>+    CallLinkStatus(CallVariant variant)
+        : m_edges(1, CallEdge(variant, 1))
</ins><span class="cx">         , m_couldTakeSlowPath(false)
</span><span class="cx">         , m_isProved(false)
</span><ins>+        , m_canTrustCounts(false)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -92,8 +93,9 @@
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     // Computes the status assuming that we never took slow path and never previously
</span><span class="cx">     // exited.
</span><del>-    static CallLinkStatus computeFor(const ConcurrentJITLocker&amp;, CallLinkInfo&amp;);
-    static CallLinkStatus computeFor(const ConcurrentJITLocker&amp;, CallLinkInfo&amp;, ExitSiteData);
</del><ins>+    static CallLinkStatus computeFor(const ConcurrentJITLocker&amp;, CodeBlock*, CallLinkInfo&amp;);
+    static CallLinkStatus computeFor(
+        const ConcurrentJITLocker&amp;, CodeBlock*, CallLinkInfo&amp;, ExitSiteData);
</ins><span class="cx"> #endif
</span><span class="cx">     
</span><span class="cx">     typedef HashMap&lt;CodeOrigin, CallLinkStatus, CodeOriginApproximateHash&gt; ContextMap;
</span><span class="lines">@@ -107,37 +109,38 @@
</span><span class="cx">     static CallLinkStatus computeFor(
</span><span class="cx">         CodeBlock*, CodeOrigin, const CallLinkInfoMap&amp;, const ContextMap&amp;);
</span><span class="cx">     
</span><del>-    bool isSet() const { return m_callTarget || m_executable || m_couldTakeSlowPath; }
</del><ins>+    bool isSet() const { return !m_edges.isEmpty() || m_couldTakeSlowPath; }
</ins><span class="cx">     
</span><span class="cx">     bool operator!() const { return !isSet(); }
</span><span class="cx">     
</span><span class="cx">     bool couldTakeSlowPath() const { return m_couldTakeSlowPath; }
</span><del>-    bool isClosureCall() const { return m_executable &amp;&amp; !m_callTarget; }
</del><span class="cx">     
</span><del>-    JSValue callTarget() const { return m_callTarget; }
-    JSFunction* function() const;
-    InternalFunction* internalFunction() const;
-    Intrinsic intrinsicFor(CodeSpecializationKind) const;
-    ExecutableBase* executable() const { return m_executable; }
</del><ins>+    CallEdgeList edges() const { return m_edges; }
+    unsigned size() const { return m_edges.size(); }
+    CallEdge at(unsigned i) const { return m_edges[i]; }
+    CallEdge operator[](unsigned i) const { return at(i); }
</ins><span class="cx">     bool isProved() const { return m_isProved; }
</span><del>-    bool canOptimize() const { return (m_callTarget || m_executable) &amp;&amp; !m_couldTakeSlowPath; }
</del><ins>+    bool canOptimize() const { return !m_edges.isEmpty(); }
+    bool canTrustCounts() const { return m_canTrustCounts; }
</ins><span class="cx">     
</span><ins>+    bool isClosureCall() const; // Returns true if any callee is a closure call.
+    
</ins><span class="cx">     void dump(PrintStream&amp;) const;
</span><span class="cx">     
</span><span class="cx"> private:
</span><del>-    void makeClosureCall()
-    {
-        ASSERT(!m_isProved);
-        // Turn this into a closure call.
-        m_callTarget = JSValue();
-    }
</del><ins>+    void makeClosureCall();
</ins><span class="cx">     
</span><span class="cx">     static CallLinkStatus computeFromLLInt(const ConcurrentJITLocker&amp;, CodeBlock*, unsigned bytecodeIndex);
</span><ins>+#if ENABLE(JIT)
+    static CallLinkStatus computeFromCallEdgeProfile(CallEdgeProfile*);
+    static CallLinkStatus computeFromCallLinkInfo(
+        const ConcurrentJITLocker&amp;, CallLinkInfo&amp;);
+#endif
</ins><span class="cx">     
</span><del>-    JSValue m_callTarget;
-    ExecutableBase* m_executable;
</del><ins>+    CallEdgeList m_edges;
</ins><span class="cx">     bool m_couldTakeSlowPath;
</span><span class="cx">     bool m_isProved;
</span><ins>+    bool m_canTrustCounts;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallVariantcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/CallVariant.cpp (0 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallVariant.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/CallVariant.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;CallVariant.h&quot;
+
+#include &quot;JSCInlines.h&quot;
+
+namespace JSC {
+
+void CallVariant::dump(PrintStream&amp; out) const
+{
+    if (!*this) {
+        out.print(&quot;null&quot;);
+        return;
+    }
+    
+    if (InternalFunction* internalFunction = this-&gt;internalFunction()) {
+        out.print(&quot;InternalFunction: &quot;, JSValue(internalFunction));
+        return;
+    }
+    
+    if (JSFunction* function = this-&gt;function()) {
+        out.print(&quot;(Function: &quot;, JSValue(function), &quot;; Executable: &quot;, *executable(), &quot;)&quot;);
+        return;
+    }
+    
+    out.print(&quot;Executable: &quot;, *executable());
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallVarianth"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/CallVariant.h (0 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallVariant.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/CallVariant.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -0,0 +1,198 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef CallVariant_h
+#define CallVariant_h
+
+#include &quot;Executable.h&quot;
+#include &quot;JSCell.h&quot;
+#include &quot;JSFunction.h&quot;
+
+namespace JSC {
+
+// The CallVariant class is meant to encapsulate a callee in a way that is useful for call linking
+// and inlining. Because JavaScript has closures, and because JSC implements the notion of internal
+// non-function objects that nevertheless provide call traps, the call machinery wants to see a
+// callee in one of the following four forms:
+//
+// JSFunction callee: This means that we expect the callsite to always call a particular function
+//     instance, that is associated with a particular activation. This pinpoints not just the code
+//     that will be called (i.e. the executable) but also the scope within which the code runs.
+//
+// Executable callee: This corresponds to a call to a closure. In this case, we know that the
+//     callsite will call a JSFunction, but we do not know which particular JSFunction. We do know
+//     what code will be called - i.e. we know the executable.
+//
+// InternalFunction callee: JSC supports a special kind of native functions that support bizarre
+//     semantics. These are always singletons. If we know that the callee is an InternalFunction
+//     then we know both the code that will be called and the scope; in fact the &quot;scope&quot; is really
+//     just the InternalFunction itself.
+//
+// Something else: It's possible call all manner of rubbish in JavaScript. This implicitly supports
+//     bizarre object callees, but it can't really tell you anything interesting about them other
+//     than the fact that they don't fall into any of the above categories.
+//
+// This class serves as a kind of union over these four things. It does so by just holding a
+// JSCell*. We determine which of the modes its in by doing type checks on the cell. Note that there
+// is no lifecycle management for the cell because this class is always used in contexts where we
+// either do custom weak reference logic over instances of this class (see CallEdgeProfile), or we
+// are inside the compiler and we assume that the compiler runs in between collections and so can
+// touch the heap without notifying anyone.
+
+class CallVariant {
+public:
+    explicit CallVariant(JSCell* callee = nullptr)
+        : m_callee(callee)
+    {
+    }
+    
+    CallVariant(WTF::HashTableDeletedValueType)
+        : m_callee(deletedToken())
+    {
+    }
+    
+    bool operator!() const { return !m_callee; }
+    
+    // If this variant refers to a function, change it to refer to its executable.
+    ALWAYS_INLINE CallVariant despecifiedClosure() const
+    {
+        if (m_callee-&gt;type() == JSFunctionType)
+            return CallVariant(jsCast&lt;JSFunction*&gt;(m_callee)-&gt;executable());
+        return *this;
+    }
+    
+    JSCell* rawCalleeCell() const { return m_callee; }
+    
+    InternalFunction* internalFunction() const
+    {
+        return jsDynamicCast&lt;InternalFunction*&gt;(m_callee);
+    }
+    
+    JSFunction* function() const
+    {
+        return jsDynamicCast&lt;JSFunction*&gt;(m_callee);
+    }
+    
+    bool isClosureCall() const { return !!jsDynamicCast&lt;ExecutableBase*&gt;(m_callee); }
+    
+    ExecutableBase* executable() const
+    {
+        if (JSFunction* function = this-&gt;function())
+            return function-&gt;executable();
+        return jsDynamicCast&lt;ExecutableBase*&gt;(m_callee);
+    }
+    
+    JSCell* nonExecutableCallee() const
+    {
+        RELEASE_ASSERT(!isClosureCall());
+        return m_callee;
+    }
+    
+    Intrinsic intrinsicFor(CodeSpecializationKind kind) const
+    {
+        if (ExecutableBase* executable = this-&gt;executable())
+            return executable-&gt;intrinsicFor(kind);
+        return NoIntrinsic;
+    }
+    
+    FunctionExecutable* functionExecutable() const
+    {
+        if (ExecutableBase* executable = this-&gt;executable())
+            return jsDynamicCast&lt;FunctionExecutable*&gt;(executable);
+        return nullptr;
+    }
+    
+    void dump(PrintStream&amp; out) const;
+    
+    bool isHashTableDeletedValue() const
+    {
+        return m_callee == deletedToken();
+    }
+    
+    bool operator==(const CallVariant&amp; other) const
+    {
+        return m_callee == other.m_callee;
+    }
+    
+    bool operator!=(const CallVariant&amp; other) const
+    {
+        return !(*this == other);
+    }
+    
+    bool operator&lt;(const CallVariant&amp; other) const
+    {
+        return m_callee &lt; other.m_callee;
+    }
+    
+    bool operator&gt;(const CallVariant&amp; other) const
+    {
+        return other &lt; *this;
+    }
+    
+    bool operator&lt;=(const CallVariant&amp; other) const
+    {
+        return !(*this &lt; other);
+    }
+    
+    bool operator&gt;=(const CallVariant&amp; other) const
+    {
+        return other &lt;= *this;
+    }
+    
+    unsigned hash() const
+    {
+        return WTF::PtrHash&lt;JSCell*&gt;::hash(m_callee);
+    }
+    
+private:
+    static JSCell* deletedToken() { return bitwise_cast&lt;JSCell*&gt;(static_cast&lt;uintptr_t&gt;(1)); }
+    
+    JSCell* m_callee;
+};
+
+struct CallVariantHash {
+    static unsigned hash(const CallVariant&amp; key) { return key.hash(); }
+    static bool equal(const CallVariant&amp; a, const CallVariant&amp; b) { return a == b; }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+typedef Vector&lt;CallVariant, 1&gt; CallVariantList;
+
+} // namespace JSC
+
+namespace WTF {
+
+template&lt;typename T&gt; struct DefaultHash;
+template&lt;&gt; struct DefaultHash&lt;JSC::CallVariant&gt; {
+    typedef JSC::CallVariantHash Hash;
+};
+
+template&lt;typename T&gt; struct HashTraits;
+template&lt;&gt; struct HashTraits&lt;JSC::CallVariant&gt; : SimpleClassHashTraits&lt;JSC::CallVariant&gt; { };
+
+} // namespace WTF
+
+#endif // CallVariant_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeOriginh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/bytecode/CodeOrigin.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -154,6 +154,17 @@
</span><span class="cx">         return CodeForCall;
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    static bool isNormalCall(Kind kind)
+    {
+        switch (kind) {
+        case Call:
+        case Construct:
+            return true;
+        default:
+            return false;
+        }
+    }
+    
</ins><span class="cx">     Vector&lt;ValueRecovery&gt; arguments; // Includes 'this'.
</span><span class="cx">     WriteBarrier&lt;ScriptExecutable&gt; executable;
</span><span class="cx">     ValueRecovery calleeRecovery;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeExitKindcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ExitKind.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ExitKind.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/bytecode/ExitKind.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -38,8 +38,8 @@
</span><span class="cx">         return &quot;Unset&quot;;
</span><span class="cx">     case BadType:
</span><span class="cx">         return &quot;BadType&quot;;
</span><del>-    case BadFunction:
-        return &quot;BadFunction&quot;;
</del><ins>+    case BadCell:
+        return &quot;BadCell&quot;;
</ins><span class="cx">     case BadExecutable:
</span><span class="cx">         return &quot;BadExecutable&quot;;
</span><span class="cx">     case BadCache:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeExitKindh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ExitKind.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ExitKind.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/bytecode/ExitKind.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -31,7 +31,7 @@
</span><span class="cx"> enum ExitKind : uint8_t {
</span><span class="cx">     ExitKindUnset,
</span><span class="cx">     BadType, // We exited because a type prediction was wrong.
</span><del>-    BadFunction, // We exited because we made an incorrect assumption about what function we would see.
</del><ins>+    BadCell, // We exited because we made an incorrect assumption about what cell we would see. Usually used for function checks.
</ins><span class="cx">     BadExecutable, // We exited because we made an incorrect assumption about what executable we would see.
</span><span class="cx">     BadCache, // We exited because an inline cache was wrong.
</span><span class="cx">     BadConstantCache, // We exited because a cache on a weak constant (usually a prototype) was wrong.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeGetByIdStatuscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -187,7 +187,8 @@
</span><span class="cx">                     AccessorCallJITStubRoutine* stub = static_cast&lt;AccessorCallJITStubRoutine*&gt;(
</span><span class="cx">                         list-&gt;at(listIndex).stubRoutine());
</span><span class="cx">                     callLinkStatus = std::make_unique&lt;CallLinkStatus&gt;(
</span><del>-                        CallLinkStatus::computeFor(locker, *stub-&gt;m_callLinkInfo, callExitSiteData));
</del><ins>+                        CallLinkStatus::computeFor(
+                            locker, profiledBlock, *stub-&gt;m_callLinkInfo, callExitSiteData));
</ins><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="cx">                 case GetByIdAccess::CustomGetter:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePutByIdStatuscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -247,7 +247,7 @@
</span><span class="cx">                     std::unique_ptr&lt;CallLinkStatus&gt; callLinkStatus =
</span><span class="cx">                         std::make_unique&lt;CallLinkStatus&gt;(
</span><span class="cx">                             CallLinkStatus::computeFor(
</span><del>-                                locker, *stub-&gt;m_callLinkInfo, callExitSiteData));
</del><ins>+                                locker, profiledBlock, *stub-&gt;m_callLinkInfo, callExitSiteData));
</ins><span class="cx">                     
</span><span class="cx">                     variant = PutByIdVariant::setter(
</span><span class="cx">                         structure, complexGetStatus.offset(), complexGetStatus.chain(),
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -1459,14 +1459,6 @@
</span><span class="cx">         forNode(node).setType(SpecInt32);
</span><span class="cx">         break;
</span><span class="cx">         
</span><del>-    case CheckExecutable: {
-        // FIXME: We could track executables in AbstractValue, which would allow us to get rid of these checks
-        // more thoroughly. https://bugs.webkit.org/show_bug.cgi?id=106200
-        // FIXME: We could eliminate these entirely if we know the exact value that flows into this.
-        // https://bugs.webkit.org/show_bug.cgi?id=106201
-        break;
-    }
-
</del><span class="cx">     case CheckStructure: {
</span><span class="cx">         // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
</span><span class="cx">         AbstractValue&amp; value = forNode(node-&gt;child1());
</span><span class="lines">@@ -1726,16 +1718,29 @@
</span><span class="cx">             m_state.setIsValid(false);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><ins>+        
+    case GetExecutable: {
+        JSValue value = forNode(node-&gt;child1()).value();
+        if (value) {
+            JSFunction* function = jsDynamicCast&lt;JSFunction*&gt;(value);
+            if (function) {
+                setConstant(node, *m_graph.freeze(function-&gt;executable()));
+                break;
+            }
+        }
+        forNode(node).setType(SpecCellOther);
+        break;
+    }
</ins><span class="cx">     
</span><del>-    case CheckFunction: {
</del><ins>+    case CheckCell: {
</ins><span class="cx">         JSValue value = forNode(node-&gt;child1()).value();
</span><del>-        if (value == node-&gt;function()-&gt;value()) {
</del><ins>+        if (value == node-&gt;cellOperand()-&gt;value()) {
</ins><span class="cx">             m_state.setFoundConstants(true);
</span><span class="cx">             ASSERT(value);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        filterByValue(node-&gt;child1(), *node-&gt;function());
</del><ins>+        filterByValue(node-&gt;child1(), *node-&gt;cellOperand());
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="lines">@@ -1859,8 +1864,6 @@
</span><span class="cx">         
</span><span class="cx">     case VariableWatchpoint:
</span><span class="cx">     case VarInjectionWatchpoint:
</span><del>-        break;
-            
</del><span class="cx">     case PutGlobalVar:
</span><span class="cx">     case NotifyWrite:
</span><span class="cx">         break;
</span><span class="lines">@@ -1900,7 +1903,16 @@
</span><span class="cx">         forNode(node).makeHeapTop();
</span><span class="cx">         break;
</span><span class="cx"> 
</span><ins>+    case ProfiledCall:
+    case ProfiledConstruct:
+        if (forNode(m_graph.varArgChild(node, 0)).m_value)
+            m_state.setFoundConstants(true);
+        clobberWorld(node-&gt;origin.semantic, clobberLimit);
+        forNode(node).makeHeapTop();
+        break;
+
</ins><span class="cx">     case ForceOSRExit:
</span><ins>+    case CheckBadCell:
</ins><span class="cx">         m_state.setIsValid(false);
</span><span class="cx">         break;
</span><span class="cx">         
</span><span class="lines">@@ -1955,7 +1967,8 @@
</span><span class="cx">     case LastNodeType:
</span><span class="cx">     case ArithIMul:
</span><span class="cx">     case FiatInt52:
</span><del>-        RELEASE_ASSERT_NOT_REACHED();
</del><ins>+    case BottomValue:
+        DFG_CRASH(m_graph, node, &quot;Unexpected node type&quot;);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGBackwardsPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -389,6 +389,11 @@
</span><span class="cx">                 // then -0 and 0 are treated the same.
</span><span class="cx">                 node-&gt;child1()-&gt;mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther);
</span><span class="cx">                 break;
</span><ins>+            case SwitchCell:
+                // There is currently no point to being clever here since this is used for switching
+                // on objects.
+                mergeDefaultFlags(node);
+                break;
</ins><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGBasicBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGBasicBlock.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGBasicBlock.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGBasicBlock.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -58,7 +58,9 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-BasicBlock::~BasicBlock() { }
</del><ins>+BasicBlock::~BasicBlock()
+{
+}
</ins><span class="cx"> 
</span><span class="cx"> void BasicBlock::ensureLocals(unsigned newNumLocals)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGBasicBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGBasicBlock.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGBasicBlock.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGBasicBlock.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -62,6 +62,7 @@
</span><span class="cx">     Node*&amp; operator[](size_t i) { return at(i); }
</span><span class="cx">     Node* operator[](size_t i) const { return at(i); }
</span><span class="cx">     Node* last() const { return at(size() - 1); }
</span><ins>+    Node* takeLast() { return m_nodes.takeLast(); }
</ins><span class="cx">     void resize(size_t size) { m_nodes.resize(size); }
</span><span class="cx">     void grow(size_t size) { m_nodes.grow(size); }
</span><span class="cx">     
</span><span class="lines">@@ -106,6 +107,13 @@
</span><span class="cx">     
</span><span class="cx">     void dump(PrintStream&amp; out) const;
</span><span class="cx">     
</span><ins>+    void didLink()
+    {
+#if !ASSERT_DISABLED
+        isLinked = true;
+#endif
+    }
+    
</ins><span class="cx">     // This value is used internally for block linking and OSR entry. It is mostly meaningless
</span><span class="cx">     // for other purposes due to inlining.
</span><span class="cx">     unsigned bytecodeBegin;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -50,6 +50,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="cx"> 
</span><ins>+static const bool verbose = false;
+
</ins><span class="cx"> class ConstantBufferKey {
</span><span class="cx"> public:
</span><span class="cx">     ConstantBufferKey()
</span><span class="lines">@@ -178,14 +180,20 @@
</span><span class="cx">         Node* callTarget, int argCount, int registerOffset, CallLinkStatus);
</span><span class="cx">     void handleCall(int result, NodeType op, CodeSpecializationKind, unsigned instructionSize, int callee, int argCount, int registerOffset);
</span><span class="cx">     void handleCall(Instruction* pc, NodeType op, CodeSpecializationKind);
</span><del>-    void emitFunctionChecks(const CallLinkStatus&amp;, Node* callTarget, int registerOffset, CodeSpecializationKind);
</del><ins>+    void emitFunctionChecks(CallVariant, Node* callTarget, int registerOffset, CodeSpecializationKind);
+    void undoFunctionChecks(CallVariant);
</ins><span class="cx">     void emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind);
</span><ins>+    unsigned inliningCost(CallVariant, int argumentCountIncludingThis, CodeSpecializationKind); // Return UINT_MAX if it's not an inlining candidate. By convention, intrinsics have a cost of 1.
</ins><span class="cx">     // Handle inlining. Return true if it succeeded, false if we need to plant a call.
</span><del>-    bool handleInlining(Node* callTargetNode, int resultOperand, const CallLinkStatus&amp;, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind);
</del><ins>+    bool handleInlining(Node* callTargetNode, int resultOperand, const CallLinkStatus&amp;, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, NodeType callOp, InlineCallFrame::Kind, SpeculatedType prediction);
+    enum CallerLinkability { CallerDoesNormalLinking, CallerLinksManually };
+    bool attemptToInlineCall(Node* callTargetNode, int resultOperand, CallVariant, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind, CallerLinkability, SpeculatedType prediction, unsigned&amp; inliningBalance);
+    void inlineCall(Node* callTargetNode, int resultOperand, CallVariant, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind, CallerLinkability);
+    void cancelLinkingForBlock(InlineStackEntry*, BasicBlock*); // Only works when the given block is the last one to have been added for that inline stack entry.
</ins><span class="cx">     // Handle intrinsic functions. Return true if it succeeded, false if we need to plant a call.
</span><span class="cx">     bool handleIntrinsic(int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction);
</span><span class="cx">     bool handleTypedArrayConstructor(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, TypedArrayType);
</span><del>-    bool handleConstantInternalFunction(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, CodeSpecializationKind);
</del><ins>+    bool handleConstantInternalFunction(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind);
</ins><span class="cx">     Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, Node* value);
</span><span class="cx">     Node* handleGetByOffset(SpeculatedType, Node* base, const StructureSet&amp;, unsigned identifierNumber, PropertyOffset, NodeType op = GetByOffset);
</span><span class="cx">     void handleGetById(
</span><span class="lines">@@ -200,8 +208,9 @@
</span><span class="cx"> 
</span><span class="cx">     Node* getScope(unsigned skipCount);
</span><span class="cx">     
</span><del>-    // Prepare to parse a block.
</del><span class="cx">     void prepareToParseBlock();
</span><ins>+    void clearCaches();
+
</ins><span class="cx">     // Parse a single basic block of bytecode instructions.
</span><span class="cx">     bool parseBlock(unsigned limit);
</span><span class="cx">     // Link block successors.
</span><span class="lines">@@ -296,6 +305,13 @@
</span><span class="cx">         
</span><span class="cx">         return delayed.execute(this, setMode);
</span><span class="cx">     }
</span><ins>+    
+    void processSetLocalQueue()
+    {
+        for (unsigned i = 0; i &lt; m_setLocalQueue.size(); ++i)
+            m_setLocalQueue[i].execute(this);
+        m_setLocalQueue.resize(0);
+    }
</ins><span class="cx"> 
</span><span class="cx">     Node* set(VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
</span><span class="cx">     {
</span><span class="lines">@@ -637,6 +653,13 @@
</span><span class="cx">         
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><ins>+    
+    void removeLastNodeFromGraph(NodeType expectedNodeType)
+    {
+        Node* node = m_currentBlock-&gt;takeLast();
+        RELEASE_ASSERT(node-&gt;op() == expectedNodeType);
+        m_graph.m_allocator.free(node);
+    }
</ins><span class="cx"> 
</span><span class="cx">     void addVarArgChild(Node* child)
</span><span class="cx">     {
</span><span class="lines">@@ -645,7 +668,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     Node* addCallWithoutSettingResult(
</span><del>-        NodeType op, Node* callee, int argCount, int registerOffset,
</del><ins>+        NodeType op, OpInfo opInfo, Node* callee, int argCount, int registerOffset,
</ins><span class="cx">         SpeculatedType prediction)
</span><span class="cx">     {
</span><span class="cx">         addVarArgChild(callee);
</span><span class="lines">@@ -653,19 +676,19 @@
</span><span class="cx">         if (parameterSlots &gt; m_parameterSlots)
</span><span class="cx">             m_parameterSlots = parameterSlots;
</span><span class="cx"> 
</span><del>-        int dummyThisArgument = op == Call || op == NativeCall ? 0 : 1;
</del><ins>+        int dummyThisArgument = op == Call || op == NativeCall || op == ProfiledCall ? 0 : 1;
</ins><span class="cx">         for (int i = 0 + dummyThisArgument; i &lt; argCount; ++i)
</span><span class="cx">             addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
</span><span class="cx"> 
</span><del>-        return addToGraph(Node::VarArg, op, OpInfo(0), OpInfo(prediction));
</del><ins>+        return addToGraph(Node::VarArg, op, opInfo, OpInfo(prediction));
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     Node* addCall(
</span><del>-        int result, NodeType op, Node* callee, int argCount, int registerOffset,
</del><ins>+        int result, NodeType op, OpInfo opInfo, Node* callee, int argCount, int registerOffset,
</ins><span class="cx">         SpeculatedType prediction)
</span><span class="cx">     {
</span><span class="cx">         Node* call = addCallWithoutSettingResult(
</span><del>-            op, callee, argCount, registerOffset, prediction);
</del><ins>+            op, opInfo, callee, argCount, registerOffset, prediction);
</ins><span class="cx">         VirtualRegister resultReg(result);
</span><span class="cx">         if (resultReg.isValid())
</span><span class="cx">             set(VirtualRegister(result), call);
</span><span class="lines">@@ -871,8 +894,7 @@
</span><span class="cx">         Vector&lt;UnlinkedBlock&gt; m_unlinkedBlocks;
</span><span class="cx">         
</span><span class="cx">         // Potential block linking targets. Must be sorted by bytecodeBegin, and
</span><del>-        // cannot have two blocks that have the same bytecodeBegin. For this very
-        // reason, this is not equivalent to 
</del><ins>+        // cannot have two blocks that have the same bytecodeBegin.
</ins><span class="cx">         Vector&lt;BasicBlock*&gt; m_blockLinkingTargets;
</span><span class="cx">         
</span><span class="cx">         // If the callsite's basic block was split into two, then this will be
</span><span class="lines">@@ -1019,77 +1041,63 @@
</span><span class="cx">     CallLinkStatus callLinkStatus, SpeculatedType prediction)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(registerOffset &lt;= 0);
</span><del>-    CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
</del><span class="cx">     
</span><span class="cx">     if (callTarget-&gt;hasConstant())
</span><span class="cx">         callLinkStatus = CallLinkStatus(callTarget-&gt;asJSValue()).setIsProved(true);
</span><span class="cx">     
</span><ins>+    if ((!callLinkStatus.canOptimize() || callLinkStatus.size() != 1)
+        &amp;&amp; !isFTL(m_graph.m_plan.mode) &amp;&amp; Options::useFTLJIT()
+        &amp;&amp; InlineCallFrame::isNormalCall(kind)
+        &amp;&amp; CallEdgeLog::isEnabled()
+        &amp;&amp; Options::dfgDoesCallEdgeProfiling()) {
+        ASSERT(op == Call || op == Construct);
+        if (op == Call)
+            op = ProfiledCall;
+        else
+            op = ProfiledConstruct;
+    }
+    
</ins><span class="cx">     if (!callLinkStatus.canOptimize()) {
</span><span class="cx">         // Oddly, this conflates calls that haven't executed with calls that behaved sufficiently polymorphically
</span><span class="cx">         // that we cannot optimize them.
</span><span class="cx">         
</span><del>-        addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset, prediction);
</del><ins>+        addCall(result, op, OpInfo(), callTarget, argumentCountIncludingThis, registerOffset, prediction);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     unsigned nextOffset = m_currentIndex + instructionSize;
</span><del>-
-    if (InternalFunction* function = callLinkStatus.internalFunction()) {
-        if (handleConstantInternalFunction(result, function, registerOffset, argumentCountIncludingThis, prediction, specializationKind)) {
-            // This phantoming has to be *after* the code for the intrinsic, to signify that
-            // the inputs must be kept alive whatever exits the intrinsic may do.
-            addToGraph(Phantom, callTarget);
-            emitArgumentPhantoms(registerOffset, argumentCountIncludingThis, specializationKind);
-            return;
-        }
-        
-        // Can only handle this using the generic call handler.
-        addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset, prediction);
-        return;
-    }
-        
-    Intrinsic intrinsic = callLinkStatus.intrinsicFor(specializationKind);
-
-    JSFunction* knownFunction = nullptr;
-    if (intrinsic != NoIntrinsic) {
-        emitFunctionChecks(callLinkStatus, callTarget, registerOffset, specializationKind);
-            
-        if (handleIntrinsic(result, intrinsic, registerOffset, argumentCountIncludingThis, prediction)) {
-            // This phantoming has to be *after* the code for the intrinsic, to signify that
-            // the inputs must be kept alive whatever exits the intrinsic may do.
-            addToGraph(Phantom, callTarget);
-            emitArgumentPhantoms(registerOffset, argumentCountIncludingThis, specializationKind);
-            if (m_graph.compilation())
-                m_graph.compilation()-&gt;noticeInlinedCall();
-            return;
-        }
-    } else if (handleInlining(callTarget, result, callLinkStatus, registerOffset, argumentCountIncludingThis, nextOffset, kind)) {
</del><ins>+    
+    OpInfo callOpInfo;
+    
+    if (handleInlining(callTarget, result, callLinkStatus, registerOffset, argumentCountIncludingThis, nextOffset, op, kind, prediction)) {
</ins><span class="cx">         if (m_graph.compilation())
</span><span class="cx">             m_graph.compilation()-&gt;noticeInlinedCall();
</span><span class="cx">         return;
</span><ins>+    }
+    
</ins><span class="cx"> #if ENABLE(FTL_NATIVE_CALL_INLINING)
</span><del>-    } else if (isFTL(m_graph.m_plan.mode) &amp;&amp; Options::optimizeNativeCalls()) {
-        JSFunction* function = callLinkStatus.function();
</del><ins>+    if (isFTL(m_graph.m_plan.mode) &amp;&amp; Options::optimizeNativeCalls() &amp;&amp; callLinkStatus.size() == 1 &amp;&amp; !callLinkStatus.couldTakeSlowPath()) {
+        CallVariant callee = callLinkStatus[0].callee();
+        JSFunction* function = callee.function();
+        CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
</ins><span class="cx">         if (function &amp;&amp; function-&gt;isHostFunction()) {
</span><del>-            emitFunctionChecks(callLinkStatus, callTarget, registerOffset, specializationKind);
-            knownFunction = function;
</del><ins>+            emitFunctionChecks(callee, callTarget, registerOffset, specializationKind);
+            callOpInfo = OpInfo(m_graph.freeze(function));
</ins><span class="cx"> 
</span><del>-            if (op == Call) 
</del><ins>+            if (op == Call || op == ProfiledCall)
</ins><span class="cx">                 op = NativeCall;
</span><span class="cx">             else {
</span><del>-                ASSERT(op == Construct);
</del><ins>+                ASSERT(op == Construct || op == ProfiledConstruct);
</ins><span class="cx">                 op = NativeConstruct;
</span><span class="cx">             }
</span><span class="cx">         }
</span><ins>+    }
</ins><span class="cx"> #endif
</span><del>-    }
-    Node* call = addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset, prediction);
-
-    if (knownFunction) 
-        call-&gt;giveKnownFunction(knownFunction);
</del><ins>+    
+    addCall(result, op, callOpInfo, callTarget, argumentCountIncludingThis, registerOffset, prediction);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ByteCodeParser::emitFunctionChecks(const CallLinkStatus&amp; callLinkStatus, Node* callTarget, int registerOffset, CodeSpecializationKind kind)
</del><ins>+void ByteCodeParser::emitFunctionChecks(CallVariant callee, Node* callTarget, int registerOffset, CodeSpecializationKind kind)
</ins><span class="cx"> {
</span><span class="cx">     Node* thisArgument;
</span><span class="cx">     if (kind == CodeForCall)
</span><span class="lines">@@ -1097,58 +1105,52 @@
</span><span class="cx">     else
</span><span class="cx">         thisArgument = 0;
</span><span class="cx"> 
</span><del>-    if (callLinkStatus.isProved()) {
-        addToGraph(Phantom, callTarget, thisArgument);
-        return;
</del><ins>+    JSCell* calleeCell;
+    Node* callTargetForCheck;
+    if (callee.isClosureCall()) {
+        calleeCell = callee.executable();
+        callTargetForCheck = addToGraph(GetExecutable, callTarget);
+    } else {
+        calleeCell = callee.nonExecutableCallee();
+        callTargetForCheck = callTarget;
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    ASSERT(callLinkStatus.canOptimize());
-    
-    if (JSFunction* function = callLinkStatus.function())
-        addToGraph(CheckFunction, OpInfo(m_graph.freeze(function)), callTarget, thisArgument);
-    else {
-        ASSERT(callLinkStatus.executable());
-        
-        addToGraph(CheckExecutable, OpInfo(callLinkStatus.executable()), callTarget, thisArgument);
-    }
</del><ins>+    ASSERT(calleeCell);
+    addToGraph(CheckCell, OpInfo(m_graph.freeze(calleeCell)), callTargetForCheck, thisArgument);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void ByteCodeParser::undoFunctionChecks(CallVariant callee)
+{
+    removeLastNodeFromGraph(CheckCell);
+    if (callee.isClosureCall())
+        removeLastNodeFromGraph(GetExecutable);
+}
+
</ins><span class="cx"> void ByteCodeParser::emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind kind)
</span><span class="cx"> {
</span><span class="cx">     for (int i = kind == CodeForCall ? 0 : 1; i &lt; argumentCountIncludingThis; ++i)
</span><span class="cx">         addToGraph(Phantom, get(virtualRegisterForArgument(i, registerOffset)));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool ByteCodeParser::handleInlining(Node* callTargetNode, int resultOperand, const CallLinkStatus&amp; callLinkStatus, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind kind)
</del><ins>+unsigned ByteCodeParser::inliningCost(CallVariant callee, int argumentCountIncludingThis, CodeSpecializationKind kind)
</ins><span class="cx"> {
</span><del>-    static const bool verbose = false;
-    
-    CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
-    
</del><span class="cx">     if (verbose)
</span><del>-        dataLog(&quot;Considering inlining &quot;, callLinkStatus, &quot; into &quot;, currentCodeOrigin(), &quot;\n&quot;);
</del><ins>+        dataLog(&quot;Considering inlining &quot;, callee, &quot; into &quot;, currentCodeOrigin(), &quot;\n&quot;);
</ins><span class="cx">     
</span><del>-    // First, the really simple checks: do we have an actual JS function?
-    if (!callLinkStatus.executable()) {
</del><ins>+    FunctionExecutable* executable = callee.functionExecutable();
+    if (!executable) {
</ins><span class="cx">         if (verbose)
</span><del>-            dataLog(&quot;    Failing because there is no executable.\n&quot;);
-        return false;
</del><ins>+            dataLog(&quot;    Failing because there is no function executable.&quot;);
+        return UINT_MAX;
</ins><span class="cx">     }
</span><del>-    if (callLinkStatus.executable()-&gt;isHostFunction()) {
-        if (verbose)
-            dataLog(&quot;    Failing because it's a host function.\n&quot;);
-        return false;
-    }
</del><span class="cx">     
</span><del>-    FunctionExecutable* executable = jsCast&lt;FunctionExecutable*&gt;(callLinkStatus.executable());
-    
</del><span class="cx">     // Does the number of arguments we're passing match the arity of the target? We currently
</span><span class="cx">     // inline only if the number of arguments passed is greater than or equal to the number
</span><span class="cx">     // arguments expected.
</span><span class="cx">     if (static_cast&lt;int&gt;(executable-&gt;parameterCount()) + 1 &gt; argumentCountIncludingThis) {
</span><span class="cx">         if (verbose)
</span><span class="cx">             dataLog(&quot;    Failing because of arity mismatch.\n&quot;);
</span><del>-        return false;
</del><ins>+        return UINT_MAX;
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // Do we have a code block, and does the code block's size match the heuristics/requirements for
</span><span class="lines">@@ -1157,18 +1159,18 @@
</span><span class="cx">     // if we had a static proof of what was being called; this might happen for example if you call a
</span><span class="cx">     // global function, where watchpointing gives us static information. Overall, it's a rare case
</span><span class="cx">     // because we expect that any hot callees would have already been compiled.
</span><del>-    CodeBlock* codeBlock = executable-&gt;baselineCodeBlockFor(specializationKind);
</del><ins>+    CodeBlock* codeBlock = executable-&gt;baselineCodeBlockFor(kind);
</ins><span class="cx">     if (!codeBlock) {
</span><span class="cx">         if (verbose)
</span><span class="cx">             dataLog(&quot;    Failing because no code block available.\n&quot;);
</span><del>-        return false;
</del><ins>+        return UINT_MAX;
</ins><span class="cx">     }
</span><span class="cx">     CapabilityLevel capabilityLevel = inlineFunctionForCapabilityLevel(
</span><del>-        codeBlock, specializationKind, callLinkStatus.isClosureCall());
</del><ins>+        codeBlock, kind, callee.isClosureCall());
</ins><span class="cx">     if (!canInline(capabilityLevel)) {
</span><span class="cx">         if (verbose)
</span><span class="cx">             dataLog(&quot;    Failing because the function is not inlineable.\n&quot;);
</span><del>-        return false;
</del><ins>+        return UINT_MAX;
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // Check if the caller is already too large. We do this check here because that's just
</span><span class="lines">@@ -1178,7 +1180,7 @@
</span><span class="cx">         codeBlock-&gt;m_shouldAlwaysBeInlined = false;
</span><span class="cx">         if (verbose)
</span><span class="cx">             dataLog(&quot;    Failing because the caller is too large.\n&quot;);
</span><del>-        return false;
</del><ins>+        return UINT_MAX;
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // FIXME: this should be better at predicting how much bloat we will introduce by inlining
</span><span class="lines">@@ -1197,7 +1199,7 @@
</span><span class="cx">         if (depth &gt;= Options::maximumInliningDepth()) {
</span><span class="cx">             if (verbose)
</span><span class="cx">                 dataLog(&quot;    Failing because depth exceeded.\n&quot;);
</span><del>-            return false;
</del><ins>+            return UINT_MAX;
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         if (entry-&gt;executable() == executable) {
</span><span class="lines">@@ -1205,19 +1207,26 @@
</span><span class="cx">             if (recursion &gt;= Options::maximumInliningRecursion()) {
</span><span class="cx">                 if (verbose)
</span><span class="cx">                     dataLog(&quot;    Failing because recursion detected.\n&quot;);
</span><del>-                return false;
</del><ins>+                return UINT_MAX;
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (verbose)
</span><del>-        dataLog(&quot;    Committing to inlining.\n&quot;);
</del><ins>+        dataLog(&quot;    Inlining should be possible.\n&quot;);
</ins><span class="cx">     
</span><del>-    // Now we know without a doubt that we are committed to inlining. So begin the process
-    // by checking the callee (if necessary) and making sure that arguments and the callee
-    // are flushed.
-    emitFunctionChecks(callLinkStatus, callTargetNode, registerOffset, specializationKind);
</del><ins>+    // It might be possible to inline.
+    return codeBlock-&gt;instructionCount();
+}
+
+void ByteCodeParser::inlineCall(Node* callTargetNode, int resultOperand, CallVariant callee, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind kind, CallerLinkability callerLinkability)
+{
+    CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
</ins><span class="cx">     
</span><ins>+    ASSERT(inliningCost(callee, argumentCountIncludingThis, specializationKind) != UINT_MAX);
+    
+    CodeBlock* codeBlock = callee.functionExecutable()-&gt;baselineCodeBlockFor(specializationKind);
+
</ins><span class="cx">     // FIXME: Don't flush constants!
</span><span class="cx">     
</span><span class="cx">     int inlineCallFrameStart = m_inlineStackTop-&gt;remapOperand(VirtualRegister(registerOffset)).offset() + JSStack::CallFrameHeaderSize;
</span><span class="lines">@@ -1233,7 +1242,7 @@
</span><span class="cx">         resultReg = m_inlineStackTop-&gt;remapOperand(resultReg);
</span><span class="cx">     
</span><span class="cx">     InlineStackEntry inlineStackEntry(
</span><del>-        this, codeBlock, codeBlock, m_graph.lastBlock(), callLinkStatus.function(), resultReg,
</del><ins>+        this, codeBlock, codeBlock, m_graph.lastBlock(), callee.function(), resultReg,
</ins><span class="cx">         (VirtualRegister)inlineCallFrameStart, argumentCountIncludingThis, kind);
</span><span class="cx">     
</span><span class="cx">     // This is where the actual inlining really happens.
</span><span class="lines">@@ -1247,8 +1256,8 @@
</span><span class="cx">     
</span><span class="cx">     RELEASE_ASSERT(
</span><span class="cx">         m_inlineStackTop-&gt;m_inlineCallFrame-&gt;isClosureCall
</span><del>-        == callLinkStatus.isClosureCall());
-    if (callLinkStatus.isClosureCall()) {
</del><ins>+        == callee.isClosureCall());
+    if (callee.isClosureCall()) {
</ins><span class="cx">         VariableAccessData* calleeVariable =
</span><span class="cx">             set(VirtualRegister(JSStack::Callee), callTargetNode, ImmediateNakedSet)-&gt;variableAccessData();
</span><span class="cx">         VariableAccessData* scopeVariable =
</span><span class="lines">@@ -1263,7 +1272,7 @@
</span><span class="cx">     m_graph.m_inlineVariableData.append(inlineVariableData);
</span><span class="cx">     
</span><span class="cx">     parseCodeBlock();
</span><del>-    prepareToParseBlock(); // Reset our state now that we're back to the outer code.
</del><ins>+    clearCaches(); // Reset our state now that we're back to the outer code.
</ins><span class="cx">     
</span><span class="cx">     m_currentIndex = oldIndex;
</span><span class="cx">     
</span><span class="lines">@@ -1276,20 +1285,8 @@
</span><span class="cx">         else
</span><span class="cx">             ASSERT(inlineStackEntry.m_callsiteBlockHead-&gt;isLinked);
</span><span class="cx">         
</span><del>-        // It's possible that the callsite block head is not owned by the caller.
-        if (!inlineStackEntry.m_caller-&gt;m_unlinkedBlocks.isEmpty()) {
-            // It's definitely owned by the caller, because the caller created new blocks.
-            // Assert that this all adds up.
-            ASSERT(inlineStackEntry.m_caller-&gt;m_unlinkedBlocks.last().m_block == inlineStackEntry.m_callsiteBlockHead);
-            ASSERT(inlineStackEntry.m_caller-&gt;m_unlinkedBlocks.last().m_needsNormalLinking);
-            inlineStackEntry.m_caller-&gt;m_unlinkedBlocks.last().m_needsNormalLinking = false;
-        } else {
-            // It's definitely not owned by the caller. Tell the caller that he does not
-            // need to link his callsite block head, because we did it for him.
-            ASSERT(inlineStackEntry.m_caller-&gt;m_callsiteBlockHeadNeedsLinking);
-            ASSERT(inlineStackEntry.m_caller-&gt;m_callsiteBlockHead == inlineStackEntry.m_callsiteBlockHead);
-            inlineStackEntry.m_caller-&gt;m_callsiteBlockHeadNeedsLinking = false;
-        }
</del><ins>+        if (callerLinkability == CallerDoesNormalLinking)
+            cancelLinkingForBlock(inlineStackEntry.m_caller, inlineStackEntry.m_callsiteBlockHead);
</ins><span class="cx">         
</span><span class="cx">         linkBlocks(inlineStackEntry.m_unlinkedBlocks, inlineStackEntry.m_blockLinkingTargets);
</span><span class="cx">     } else
</span><span class="lines">@@ -1308,16 +1305,19 @@
</span><span class="cx">             // for release builds because this block will never serve as a potential target
</span><span class="cx">             // in the linker's binary search.
</span><span class="cx">             lastBlock-&gt;bytecodeBegin = m_currentIndex;
</span><del>-            m_inlineStackTop-&gt;m_caller-&gt;m_unlinkedBlocks.append(UnlinkedBlock(m_graph.lastBlock()));
</del><ins>+            if (callerLinkability == CallerDoesNormalLinking) {
+                if (verbose)
+                    dataLog(&quot;Adding unlinked block &quot;, RawPointer(m_graph.lastBlock()), &quot; (one return)\n&quot;);
+                m_inlineStackTop-&gt;m_caller-&gt;m_unlinkedBlocks.append(UnlinkedBlock(m_graph.lastBlock()));
+            }
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         m_currentBlock = m_graph.lastBlock();
</span><del>-        return true;
</del><ins>+        return;
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // If we get to this point then all blocks must end in some sort of terminals.
</span><span class="cx">     ASSERT(lastBlock-&gt;last()-&gt;isTerminal());
</span><del>-    
</del><span class="cx"> 
</span><span class="cx">     // Need to create a new basic block for the continuation at the caller.
</span><span class="cx">     RefPtr&lt;BasicBlock&gt; block = adoptRef(new BasicBlock(nextOffset, m_numArguments, m_numLocals, PNaN));
</span><span class="lines">@@ -1333,23 +1333,296 @@
</span><span class="cx">         ASSERT(!node-&gt;targetBlock());
</span><span class="cx">         node-&gt;targetBlock() = block.get();
</span><span class="cx">         inlineStackEntry.m_unlinkedBlocks[i].m_needsEarlyReturnLinking = false;
</span><del>-#if !ASSERT_DISABLED
-        blockToLink-&gt;isLinked = true;
-#endif
</del><ins>+        if (verbose)
+            dataLog(&quot;Marking &quot;, RawPointer(blockToLink), &quot; as linked (jumps to return)\n&quot;);
+        blockToLink-&gt;didLink();
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     m_currentBlock = block.get();
</span><span class="cx">     ASSERT(m_inlineStackTop-&gt;m_caller-&gt;m_blockLinkingTargets.isEmpty() || m_inlineStackTop-&gt;m_caller-&gt;m_blockLinkingTargets.last()-&gt;bytecodeBegin &lt; nextOffset);
</span><del>-    m_inlineStackTop-&gt;m_caller-&gt;m_unlinkedBlocks.append(UnlinkedBlock(block.get()));
-    m_inlineStackTop-&gt;m_caller-&gt;m_blockLinkingTargets.append(block.get());
</del><ins>+    if (verbose)
+        dataLog(&quot;Adding unlinked block &quot;, RawPointer(block.get()), &quot; (many returns)\n&quot;);
+    if (callerLinkability == CallerDoesNormalLinking) {
+        m_inlineStackTop-&gt;m_caller-&gt;m_unlinkedBlocks.append(UnlinkedBlock(block.get()));
+        m_inlineStackTop-&gt;m_caller-&gt;m_blockLinkingTargets.append(block.get());
+    }
</ins><span class="cx">     m_graph.appendBlock(block);
</span><span class="cx">     prepareToParseBlock();
</span><ins>+}
+
+void ByteCodeParser::cancelLinkingForBlock(InlineStackEntry* inlineStackEntry, BasicBlock* block)
+{
+    // It's possible that the callsite block head is not owned by the caller.
+    if (!inlineStackEntry-&gt;m_unlinkedBlocks.isEmpty()) {
+        // It's definitely owned by the caller, because the caller created new blocks.
+        // Assert that this all adds up.
+        ASSERT_UNUSED(block, inlineStackEntry-&gt;m_unlinkedBlocks.last().m_block == block);
+        ASSERT(inlineStackEntry-&gt;m_unlinkedBlocks.last().m_needsNormalLinking);
+        inlineStackEntry-&gt;m_unlinkedBlocks.last().m_needsNormalLinking = false;
+    } else {
+        // It's definitely not owned by the caller. Tell the caller that he does not
+        // need to link his callsite block head, because we did it for him.
+        ASSERT(inlineStackEntry-&gt;m_callsiteBlockHeadNeedsLinking);
+        ASSERT_UNUSED(block, inlineStackEntry-&gt;m_callsiteBlockHead == block);
+        inlineStackEntry-&gt;m_callsiteBlockHeadNeedsLinking = false;
+    }
+}
+
+bool ByteCodeParser::attemptToInlineCall(Node* callTargetNode, int resultOperand, CallVariant callee, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind kind, CallerLinkability callerLinkability, SpeculatedType prediction, unsigned&amp; inliningBalance)
+{
+    CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
</ins><span class="cx">     
</span><del>-    // At this point we return and continue to generate code for the caller, but
-    // in the new basic block.
</del><ins>+    if (!inliningBalance)
+        return false;
+    
+    if (InternalFunction* function = callee.internalFunction()) {
+        if (handleConstantInternalFunction(resultOperand, function, registerOffset, argumentCountIncludingThis, specializationKind)) {
+            addToGraph(Phantom, callTargetNode);
+            emitArgumentPhantoms(registerOffset, argumentCountIncludingThis, specializationKind);
+            inliningBalance--;
+            return true;
+        }
+        return false;
+    }
+    
+    Intrinsic intrinsic = callee.intrinsicFor(specializationKind);
+    if (intrinsic != NoIntrinsic) {
+        if (handleIntrinsic(resultOperand, intrinsic, registerOffset, argumentCountIncludingThis, prediction)) {
+            addToGraph(Phantom, callTargetNode);
+            emitArgumentPhantoms(registerOffset, argumentCountIncludingThis, specializationKind);
+            inliningBalance--;
+            return true;
+        }
+        return false;
+    }
+    
+    unsigned myInliningCost = inliningCost(callee, argumentCountIncludingThis, specializationKind);
+    if (myInliningCost &gt; inliningBalance)
+        return false;
+    
+    inlineCall(callTargetNode, resultOperand, callee, registerOffset, argumentCountIncludingThis, nextOffset, kind, callerLinkability);
+    inliningBalance -= myInliningCost;
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool ByteCodeParser::handleInlining(Node* callTargetNode, int resultOperand, const CallLinkStatus&amp; callLinkStatus, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, NodeType callOp, InlineCallFrame::Kind kind, SpeculatedType prediction)
+{
+    if (verbose) {
+        dataLog(&quot;Handling inlining...\n&quot;);
+        dataLog(&quot;Stack: &quot;, currentCodeOrigin(), &quot;\n&quot;);
+    }
+    CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
+    
+    if (!callLinkStatus.size()) {
+        if (verbose)
+            dataLog(&quot;Bailing inlining.\n&quot;);
+        return false;
+    }
+    
+    unsigned inliningBalance = Options::maximumFunctionForCallInlineCandidateInstructionCount();
+    if (specializationKind == CodeForConstruct)
+        inliningBalance = std::min(inliningBalance, Options::maximumFunctionForConstructInlineCandidateInstructionCount());
+    if (callLinkStatus.isClosureCall())
+        inliningBalance = std::min(inliningBalance, Options::maximumFunctionForClosureCallInlineCandidateInstructionCount());
+    
+    // First check if we can avoid creating control flow. Our inliner does some CFG
+    // simplification on the fly and this helps reduce compile times, but we can only leverage
+    // this in cases where we don't need control flow diamonds to check the callee.
+    if (!callLinkStatus.couldTakeSlowPath() &amp;&amp; callLinkStatus.size() == 1) {
+        emitFunctionChecks(
+            callLinkStatus[0].callee(), callTargetNode, registerOffset, specializationKind);
+        bool result = attemptToInlineCall(
+            callTargetNode, resultOperand, callLinkStatus[0].callee(), registerOffset,
+            argumentCountIncludingThis, nextOffset, kind, CallerDoesNormalLinking, prediction,
+            inliningBalance);
+        if (!result &amp;&amp; !callLinkStatus.isProved())
+            undoFunctionChecks(callLinkStatus[0].callee());
+        if (verbose) {
+            dataLog(&quot;Done inlining (simple).\n&quot;);
+            dataLog(&quot;Stack: &quot;, currentCodeOrigin(), &quot;\n&quot;);
+        }
+        return result;
+    }
+    
+    // We need to create some kind of switch over callee. For now we only do this if we believe that
+    // we're in the top tier. We have two reasons for this: first, it provides us an opportunity to
+    // do more detailed polyvariant/polymorphic profiling; and second, it reduces compile times in
+    // the DFG. And by polyvariant profiling we mean polyvariant profiling of *this* call. Note that
+    // we could improve that aspect of this by doing polymorphic inlining but having the profiling
+    // also. Currently we opt against this, but it could be interesting. That would require having a
+    // separate node for call edge profiling.
+    // FIXME: Introduce the notion of a separate call edge profiling node.
+    // https://bugs.webkit.org/show_bug.cgi?id=136033
+    if (!isFTL(m_graph.m_plan.mode) || !Options::enablePolymorphicCallInlining()) {
+        if (verbose) {
+            dataLog(&quot;Bailing inlining (hard).\n&quot;);
+            dataLog(&quot;Stack: &quot;, currentCodeOrigin(), &quot;\n&quot;);
+        }
+        return false;
+    }
+    
+    unsigned oldOffset = m_currentIndex;
+    
+    bool allAreClosureCalls = true;
+    bool allAreDirectCalls = true;
+    for (unsigned i = callLinkStatus.size(); i--;) {
+        if (callLinkStatus[i].callee().isClosureCall())
+            allAreDirectCalls = false;
+        else
+            allAreClosureCalls = false;
+    }
+    
+    Node* thingToSwitchOn;
+    if (allAreDirectCalls)
+        thingToSwitchOn = callTargetNode;
+    else if (allAreClosureCalls)
+        thingToSwitchOn = addToGraph(GetExecutable, callTargetNode);
+    else {
+        // FIXME: We should be able to handle this case, but it's tricky and we don't know of cases
+        // where it would be beneficial. Also, CallLinkStatus would make all callees appear like
+        // closure calls if any calls were closure calls - except for calls to internal functions.
+        // So this will only arise if some callees are internal functions and others are closures.
+        // https://bugs.webkit.org/show_bug.cgi?id=136020
+        if (verbose) {
+            dataLog(&quot;Bailing inlining (mix).\n&quot;);
+            dataLog(&quot;Stack: &quot;, currentCodeOrigin(), &quot;\n&quot;);
+        }
+        return false;
+    }
+    
+    if (verbose) {
+        dataLog(&quot;Doing hard inlining...\n&quot;);
+        dataLog(&quot;Stack: &quot;, currentCodeOrigin(), &quot;\n&quot;);
+    }
+    
+    // This makes me wish that we were in SSA all the time. We need to pick a variable into which to
+    // store the callee so that it will be accessible to all of the blocks we're about to create. We
+    // get away with doing an immediate-set here because we wouldn't have performed any side effects
+    // yet.
+    if (verbose)
+        dataLog(&quot;Register offset: &quot;, registerOffset);
+    VirtualRegister calleeReg(registerOffset + JSStack::Callee);
+    calleeReg = m_inlineStackTop-&gt;remapOperand(calleeReg);
+    if (verbose)
+        dataLog(&quot;Callee is going to be &quot;, calleeReg, &quot;\n&quot;);
+    setDirect(calleeReg, callTargetNode, ImmediateSetWithFlush);
+    
+    SwitchData&amp; data = *m_graph.m_switchData.add();
+    data.kind = SwitchCell;
+    addToGraph(Switch, OpInfo(&amp;data), thingToSwitchOn);
+    
+    BasicBlock* originBlock = m_currentBlock;
+    if (verbose)
+        dataLog(&quot;Marking &quot;, RawPointer(originBlock), &quot; as linked (origin of poly inline)\n&quot;);
+    originBlock-&gt;didLink();
+    cancelLinkingForBlock(m_inlineStackTop, originBlock);
+    
+    // Each inlined callee will have a landing block that it returns at. They should all have jumps
+    // to the continuation block, which we create last.
+    Vector&lt;BasicBlock*&gt; landingBlocks;
+    
+    // We make force this true if we give up on inlining any of the edges.
+    bool couldTakeSlowPath = callLinkStatus.couldTakeSlowPath();
+    
+    if (verbose)
+        dataLog(&quot;About to loop over functions at &quot;, currentCodeOrigin(), &quot;.\n&quot;);
+    
+    for (unsigned i = 0; i &lt; callLinkStatus.size(); ++i) {
+        m_currentIndex = oldOffset;
+        RefPtr&lt;BasicBlock&gt; block = adoptRef(new BasicBlock(UINT_MAX, m_numArguments, m_numLocals, PNaN));
+        m_currentBlock = block.get();
+        m_graph.appendBlock(block);
+        prepareToParseBlock();
+        
+        Node* myCallTargetNode = getDirect(calleeReg);
+        
+        bool inliningResult = attemptToInlineCall(
+            myCallTargetNode, resultOperand, callLinkStatus[i].callee(), registerOffset,
+            argumentCountIncludingThis, nextOffset, kind, CallerLinksManually, prediction,
+            inliningBalance);
+        
+        if (!inliningResult) {
+            // That failed so we let the block die. Nothing interesting should have been added to
+            // the block. We also give up on inlining any of the (less frequent) callees.
+            ASSERT(m_currentBlock == block.get());
+            ASSERT(m_graph.m_blocks.last() == block);
+            m_graph.killBlockAndItsContents(block.get());
+            m_graph.m_blocks.removeLast();
+            
+            // The fact that inlining failed means we need a slow path.
+            couldTakeSlowPath = true;
+            break;
+        }
+        
+        JSCell* thingToCaseOn;
+        if (allAreDirectCalls)
+            thingToCaseOn = callLinkStatus[i].callee().nonExecutableCallee();
+        else {
+            ASSERT(allAreClosureCalls);
+            thingToCaseOn = callLinkStatus[i].callee().executable();
+        }
+        data.cases.append(SwitchCase(m_graph.freeze(thingToCaseOn), block.get()));
+        m_currentIndex = nextOffset;
+        processSetLocalQueue(); // This only comes into play for intrinsics, since normal inlined code will leave an empty queue.
+        addToGraph(Jump);
+        if (verbose)
+            dataLog(&quot;Marking &quot;, RawPointer(m_currentBlock), &quot; as linked (tail of poly inlinee)\n&quot;);
+        m_currentBlock-&gt;didLink();
+        landingBlocks.append(m_currentBlock);
+
+        if (verbose)
+            dataLog(&quot;Finished inlining &quot;, callLinkStatus[i].callee(), &quot; at &quot;, currentCodeOrigin(), &quot;.\n&quot;);
+    }
+    
+    RefPtr&lt;BasicBlock&gt; slowPathBlock = adoptRef(
+        new BasicBlock(UINT_MAX, m_numArguments, m_numLocals, PNaN));
+    m_currentIndex = oldOffset;
+    data.fallThrough = BranchTarget(slowPathBlock.get());
+    m_graph.appendBlock(slowPathBlock);
+    if (verbose)
+        dataLog(&quot;Marking &quot;, RawPointer(slowPathBlock.get()), &quot; as linked (slow path block)\n&quot;);
+    slowPathBlock-&gt;didLink();
+    prepareToParseBlock();
+    m_currentBlock = slowPathBlock.get();
+    Node* myCallTargetNode = getDirect(calleeReg);
+    if (couldTakeSlowPath) {
+        addCall(
+            resultOperand, callOp, OpInfo(), myCallTargetNode, argumentCountIncludingThis,
+            registerOffset, prediction);
+    } else {
+        addToGraph(CheckBadCell);
+        addToGraph(Phantom, myCallTargetNode);
+        emitArgumentPhantoms(registerOffset, argumentCountIncludingThis, specializationKind);
+        
+        set(VirtualRegister(resultOperand), addToGraph(BottomValue));
+    }
+
+    m_currentIndex = nextOffset;
+    processSetLocalQueue();
+    addToGraph(Jump);
+    landingBlocks.append(m_currentBlock);
+    
+    RefPtr&lt;BasicBlock&gt; continuationBlock = adoptRef(
+        new BasicBlock(UINT_MAX, m_numArguments, m_numLocals, PNaN));
+    m_graph.appendBlock(continuationBlock);
+    if (verbose)
+        dataLog(&quot;Adding unlinked block &quot;, RawPointer(continuationBlock.get()), &quot; (continuation)\n&quot;);
+    m_inlineStackTop-&gt;m_unlinkedBlocks.append(UnlinkedBlock(continuationBlock.get()));
+    prepareToParseBlock();
+    m_currentBlock = continuationBlock.get();
+    
+    for (unsigned i = landingBlocks.size(); i--;)
+        landingBlocks[i]-&gt;last()-&gt;targetBlock() = continuationBlock.get();
+    
+    m_currentIndex = oldOffset;
+    
+    if (verbose) {
+        dataLog(&quot;Done inlining (hard).\n&quot;);
+        dataLog(&quot;Stack: &quot;, currentCodeOrigin(), &quot;\n&quot;);
+    }
+    return true;
+}
+
</ins><span class="cx"> bool ByteCodeParser::handleMinMax(int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis)
</span><span class="cx"> {
</span><span class="cx">     if (argumentCountIncludingThis == 1) { // Math.min()
</span><span class="lines">@@ -1645,7 +1918,7 @@
</span><span class="cx"> 
</span><span class="cx"> bool ByteCodeParser::handleConstantInternalFunction(
</span><span class="cx">     int resultOperand, InternalFunction* function, int registerOffset,
</span><del>-    int argumentCountIncludingThis, SpeculatedType prediction, CodeSpecializationKind kind)
</del><ins>+    int argumentCountIncludingThis, CodeSpecializationKind kind)
</ins><span class="cx"> {
</span><span class="cx">     // If we ever find that we have a lot of internal functions that we specialize for,
</span><span class="cx">     // then we should probably have some sort of hashtable dispatch, or maybe even
</span><span class="lines">@@ -1654,8 +1927,6 @@
</span><span class="cx">     // we know about is small enough, that having just a linear cascade of if statements
</span><span class="cx">     // is good enough.
</span><span class="cx">     
</span><del>-    UNUSED_PARAM(prediction); // Remove this once we do more things.
-    
</del><span class="cx">     if (function-&gt;classInfo() == ArrayConstructor::info()) {
</span><span class="cx">         if (function-&gt;globalObject() != m_inlineStackTop-&gt;m_codeBlock-&gt;globalObject())
</span><span class="cx">             return false;
</span><span class="lines">@@ -2020,6 +2291,12 @@
</span><span class="cx"> 
</span><span class="cx"> void ByteCodeParser::prepareToParseBlock()
</span><span class="cx"> {
</span><ins>+    clearCaches();
+    ASSERT(m_setLocalQueue.isEmpty());
+}
+
+void ByteCodeParser::clearCaches()
+{
</ins><span class="cx">     m_constants.resize(0);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2059,9 +2336,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     while (true) {
</span><del>-        for (unsigned i = 0; i &lt; m_setLocalQueue.size(); ++i)
-            m_setLocalQueue[i].execute(this);
-        m_setLocalQueue.resize(0);
</del><ins>+        processSetLocalQueue();
</ins><span class="cx">         
</span><span class="cx">         // Don't extend over jump destinations.
</span><span class="cx">         if (m_currentIndex == limit) {
</span><span class="lines">@@ -2205,13 +2480,13 @@
</span><span class="cx">             JSCell* cachedFunction = currentInstruction[2].u.jsCell.get();
</span><span class="cx">             if (!cachedFunction 
</span><span class="cx">                 || m_inlineStackTop-&gt;m_profiledBlock-&gt;couldTakeSlowCase(m_currentIndex)
</span><del>-                || m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, BadFunction)) {
</del><ins>+                || m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, BadCell)) {
</ins><span class="cx">                 set(VirtualRegister(currentInstruction[1].u.operand), get(VirtualRegister(JSStack::Callee)));
</span><span class="cx">             } else {
</span><span class="cx">                 FrozenValue* frozen = m_graph.freeze(cachedFunction);
</span><span class="cx">                 ASSERT(cachedFunction-&gt;inherits(JSFunction::info()));
</span><span class="cx">                 Node* actualCallee = get(VirtualRegister(JSStack::Callee));
</span><del>-                addToGraph(CheckFunction, OpInfo(frozen), actualCallee);
</del><ins>+                addToGraph(CheckCell, OpInfo(frozen), actualCallee);
</ins><span class="cx">                 set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(JSConstant, OpInfo(frozen)));
</span><span class="cx">             }
</span><span class="cx">             NEXT_OPCODE(op_get_callee);
</span><span class="lines">@@ -2893,7 +3168,7 @@
</span><span class="cx">             // already gnarly enough as it is.
</span><span class="cx">             ASSERT(pointerIsFunction(currentInstruction[2].u.specialPointer));
</span><span class="cx">             addToGraph(
</span><del>-                CheckFunction,
</del><ins>+                CheckCell,
</ins><span class="cx">                 OpInfo(m_graph.freeze(static_cast&lt;JSCell*&gt;(actualPointerFor(
</span><span class="cx">                     m_inlineStackTop-&gt;m_codeBlock, currentInstruction[2].u.specialPointer)))),
</span><span class="cx">                 get(VirtualRegister(currentInstruction[1].u.operand)));
</span><span class="lines">@@ -3317,15 +3592,19 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-#if !ASSERT_DISABLED
-    block-&gt;isLinked = true;
-#endif
</del><ins>+    if (verbose)
+        dataLog(&quot;Marking &quot;, RawPointer(block), &quot; as linked (actually did linking)\n&quot;);
+    block-&gt;didLink();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ByteCodeParser::linkBlocks(Vector&lt;UnlinkedBlock&gt;&amp; unlinkedBlocks, Vector&lt;BasicBlock*&gt;&amp; possibleTargets)
</span><span class="cx"> {
</span><span class="cx">     for (size_t i = 0; i &lt; unlinkedBlocks.size(); ++i) {
</span><ins>+        if (verbose)
+            dataLog(&quot;Attempting to link &quot;, RawPointer(unlinkedBlocks[i].m_block), &quot;\n&quot;);
</ins><span class="cx">         if (unlinkedBlocks[i].m_needsNormalLinking) {
</span><ins>+            if (verbose)
+                dataLog(&quot;    Does need normal linking.\n&quot;);
</ins><span class="cx">             linkBlock(unlinkedBlocks[i].m_block, possibleTargets);
</span><span class="cx">             unlinkedBlocks[i].m_needsNormalLinking = false;
</span><span class="cx">         }
</span><span class="lines">@@ -3492,7 +3771,7 @@
</span><span class="cx"> 
</span><span class="cx"> void ByteCodeParser::parseCodeBlock()
</span><span class="cx"> {
</span><del>-    prepareToParseBlock();
</del><ins>+    clearCaches();
</ins><span class="cx">     
</span><span class="cx">     CodeBlock* codeBlock = m_inlineStackTop-&gt;m_codeBlock;
</span><span class="cx">     
</span><span class="lines">@@ -3558,7 +3837,12 @@
</span><span class="cx">                     // 2) If the bytecodeBegin is equal to the currentIndex, then we failed to do
</span><span class="cx">                     //    a peephole coalescing of this block in the if statement above. So, we're
</span><span class="cx">                     //    generating suboptimal code and leaving more work for the CFG simplifier.
</span><del>-                    ASSERT(m_inlineStackTop-&gt;m_unlinkedBlocks.isEmpty() || m_inlineStackTop-&gt;m_unlinkedBlocks.last().m_block-&gt;bytecodeBegin &lt; m_currentIndex);
</del><ins>+                    if (!m_inlineStackTop-&gt;m_unlinkedBlocks.isEmpty()) {
+                        unsigned lastBegin =
+                            m_inlineStackTop-&gt;m_unlinkedBlocks.last().m_block-&gt;bytecodeBegin;
+                        ASSERT_UNUSED(
+                            lastBegin, lastBegin == UINT_MAX || lastBegin &lt; m_currentIndex);
+                    }
</ins><span class="cx">                     m_inlineStackTop-&gt;m_unlinkedBlocks.append(UnlinkedBlock(block.get()));
</span><span class="cx">                     m_inlineStackTop-&gt;m_blockLinkingTargets.append(block.get());
</span><span class="cx">                     // The first block is definitely an OSR target.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCPSRethreadingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -90,8 +90,10 @@
</span><span class="cx">                     node-&gt;children.setChild1(Edge());
</span><span class="cx">                     break;
</span><span class="cx">                 case Phantom:
</span><del>-                    if (!node-&gt;child1())
</del><ins>+                    if (!node-&gt;child1()) {
+                        m_graph.m_allocator.free(node);
</ins><span class="cx">                         continue;
</span><ins>+                    }
</ins><span class="cx">                     switch (node-&gt;child1()-&gt;op()) {
</span><span class="cx">                     case Phi:
</span><span class="cx">                     case SetArgument:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -144,6 +144,8 @@
</span><span class="cx">     case FiatInt52:
</span><span class="cx">     case MakeRope:
</span><span class="cx">     case ValueToInt32:
</span><ins>+    case GetExecutable:
+    case BottomValue:
</ins><span class="cx">         def(PureValue(node));
</span><span class="cx">         return;
</span><span class="cx">         
</span><span class="lines">@@ -239,14 +241,10 @@
</span><span class="cx">         def(PureValue(node, node-&gt;arithMode()));
</span><span class="cx">         return;
</span><span class="cx">         
</span><del>-    case CheckFunction:
-        def(PureValue(CheckFunction, AdjacencyList(AdjacencyList::Fixed, node-&gt;child1()), node-&gt;function()));
</del><ins>+    case CheckCell:
+        def(PureValue(CheckCell, AdjacencyList(AdjacencyList::Fixed, node-&gt;child1()), node-&gt;cellOperand()));
</ins><span class="cx">         return;
</span><span class="cx">         
</span><del>-    case CheckExecutable:
-        def(PureValue(node, node-&gt;executable()));
-        return;
-        
</del><span class="cx">     case ConstantStoragePointer:
</span><span class="cx">         def(PureValue(node, node-&gt;storagePointer()));
</span><span class="cx">         return;
</span><span class="lines">@@ -263,6 +261,7 @@
</span><span class="cx">     case Switch:
</span><span class="cx">     case Throw:
</span><span class="cx">     case ForceOSRExit:
</span><ins>+    case CheckBadCell:
</ins><span class="cx">     case Return:
</span><span class="cx">     case Unreachable:
</span><span class="cx">     case CheckTierUpInLoop:
</span><span class="lines">@@ -358,6 +357,8 @@
</span><span class="cx">     case ArrayPop:
</span><span class="cx">     case Call:
</span><span class="cx">     case Construct:
</span><ins>+    case ProfiledCall:
+    case ProfiledConstruct:
</ins><span class="cx">     case NativeCall:
</span><span class="cx">     case NativeConstruct:
</span><span class="cx">     case ToPrimitive:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCommonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCommon.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCommon.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGCommon.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -63,6 +63,13 @@
</span><span class="cx">     DontRefNode
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+enum SwitchKind {
+    SwitchImm,
+    SwitchChar,
+    SwitchString,
+    SwitchCell
+};
+
</ins><span class="cx"> inline bool verboseCompilationEnabled(CompilationMode mode = DFGMode)
</span><span class="cx"> {
</span><span class="cx">     return Options::verboseCompilation() || Options::dumpGraphAtEachPhase() || (isFTL(mode) &amp;&amp; Options::verboseFTLCompilation());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -142,8 +142,8 @@
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">                 
</span><del>-            case CheckFunction: {
-                if (m_state.forNode(node-&gt;child1()).value() != node-&gt;function()-&gt;value())
</del><ins>+            case CheckCell: {
+                if (m_state.forNode(node-&gt;child1()).value() != node-&gt;cellOperand()-&gt;value())
</ins><span class="cx">                     break;
</span><span class="cx">                 node-&gt;convertToPhantom();
</span><span class="cx">                 eliminated = true;
</span><span class="lines">@@ -384,6 +384,19 @@
</span><span class="cx">                 }
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><ins>+                
+            case ProfiledCall:
+            case ProfiledConstruct: {
+                if (!m_state.forNode(m_graph.varArgChild(node, 0)).m_value)
+                    break;
+                
+                // If we were able to prove that the callee is a constant then the normal call
+                // inline cache will record this callee. This means that there is no need to do any
+                // additional profiling.
+                node-&gt;setOp(node-&gt;op() == ProfiledCall ? Call : Construct);
+                eliminated = true;
+                break;
+            }
</ins><span class="cx"> 
</span><span class="cx">             default:
</span><span class="cx">                 break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -91,7 +91,7 @@
</span><span class="cx">     case PutByIdFlush:
</span><span class="cx">     case PutByIdDirect:
</span><span class="cx">     case CheckStructure:
</span><del>-    case CheckExecutable:
</del><ins>+    case GetExecutable:
</ins><span class="cx">     case GetButterfly:
</span><span class="cx">     case CheckArray:
</span><span class="cx">     case GetScope:
</span><span class="lines">@@ -104,7 +104,7 @@
</span><span class="cx">     case PutGlobalVar:
</span><span class="cx">     case VariableWatchpoint:
</span><span class="cx">     case VarInjectionWatchpoint:
</span><del>-    case CheckFunction:
</del><ins>+    case CheckCell:
</ins><span class="cx">     case AllocationProfileWatchpoint:
</span><span class="cx">     case RegExpExec:
</span><span class="cx">     case RegExpTest:
</span><span class="lines">@@ -119,6 +119,8 @@
</span><span class="cx">     case Construct:
</span><span class="cx">     case NativeCall:
</span><span class="cx">     case NativeConstruct:
</span><ins>+    case ProfiledCall:
+    case ProfiledConstruct:
</ins><span class="cx">     case Breakpoint:
</span><span class="cx">     case ProfileWillCall:
</span><span class="cx">     case ProfileDidCall:
</span><span class="lines">@@ -195,6 +197,8 @@
</span><span class="cx">     case GetDirectPname:
</span><span class="cx">     case FiatInt52:
</span><span class="cx">     case BooleanToNumber:
</span><ins>+    case CheckBadCell:
+    case BottomValue:
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     case CreateActivation:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDrivercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -89,6 +89,9 @@
</span><span class="cx">         vm.getCTIStub(virtualConstructThatPreservesRegsThunkGenerator);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    if (CallEdgeLog::isEnabled())
+        vm.ensureCallEdgeLog().processLog();
+    
</ins><span class="cx">     RefPtr&lt;Plan&gt; plan = adoptRef(
</span><span class="cx">         new Plan(codeBlock, profiledDFGCodeBlock, mode, osrEntryBytecodeIndex, mustHandleValues));
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -736,6 +736,12 @@
</span><span class="cx">                 else if (node-&gt;child1()-&gt;shouldSpeculateString())
</span><span class="cx">                     fixEdge&lt;StringUse&gt;(node-&gt;child1());
</span><span class="cx">                 break;
</span><ins>+            case SwitchCell:
+                if (node-&gt;child1()-&gt;shouldSpeculateCell())
+                    fixEdge&lt;CellUse&gt;(node-&gt;child1());
+                // else it's fine for this to have UntypedUse; we will handle this by just making
+                // non-cells take the default case.
+                break;
</ins><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -897,13 +903,13 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case CheckExecutable: {
</del><ins>+        case GetExecutable: {
</ins><span class="cx">             fixEdge&lt;FunctionUse&gt;(node-&gt;child1());
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         case CheckStructure:
</span><del>-        case CheckFunction:
</del><ins>+        case CheckCell:
</ins><span class="cx">         case CheckHasInstance:
</span><span class="cx">         case CreateThis:
</span><span class="cx">         case GetButterfly: {
</span><span class="lines">@@ -1120,6 +1126,8 @@
</span><span class="cx">         case AllocationProfileWatchpoint:
</span><span class="cx">         case Call:
</span><span class="cx">         case Construct:
</span><ins>+        case ProfiledCall:
+        case ProfiledConstruct:
</ins><span class="cx">         case NativeCall:
</span><span class="cx">         case NativeConstruct:
</span><span class="cx">         case NewObject:
</span><span class="lines">@@ -1149,6 +1157,7 @@
</span><span class="cx">         case ThrowReferenceError:
</span><span class="cx">         case CountExecution:
</span><span class="cx">         case ForceOSRExit:
</span><ins>+        case CheckBadCell:
</ins><span class="cx">         case CheckWatchdogTimer:
</span><span class="cx">         case Unreachable:
</span><span class="cx">         case ExtractOSREntryLocal:
</span><span class="lines">@@ -1159,6 +1168,7 @@
</span><span class="cx">         case TypedArrayWatchpoint:
</span><span class="cx">         case MovHint:
</span><span class="cx">         case ZombieHint:
</span><ins>+        case BottomValue:
</ins><span class="cx">             break;
</span><span class="cx"> #else
</span><span class="cx">         default:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -222,25 +222,24 @@
</span><span class="cx">         out.print(comma, inContext(*node-&gt;structure(), context));
</span><span class="cx">     if (node-&gt;hasTransition())
</span><span class="cx">         out.print(comma, pointerDumpInContext(node-&gt;transition(), context));
</span><del>-    if (node-&gt;hasFunction()) {
-        out.print(comma, &quot;function(&quot;, pointerDump(node-&gt;function()), &quot;, &quot;);
-        if (node-&gt;function()-&gt;value().isCell()
-            &amp;&amp; node-&gt;function()-&gt;value().asCell()-&gt;inherits(JSFunction::info())) {
-            JSFunction* function = jsCast&lt;JSFunction*&gt;(node-&gt;function()-&gt;value().asCell());
-            if (function-&gt;isHostFunction())
-                out.print(&quot;&lt;host function&gt;&quot;);
-            else
-                out.print(FunctionExecutableDump(function-&gt;jsExecutable()));
-        } else
-            out.print(&quot;&lt;not JSFunction&gt;&quot;);
-        out.print(&quot;)&quot;);
</del><ins>+    if (node-&gt;hasCellOperand()) {
+        if (!node-&gt;cellOperand()-&gt;value() || !node-&gt;cellOperand()-&gt;value().isCell())
+            out.print(comma, &quot;invalid cell operand: &quot;, node-&gt;cellOperand()-&gt;value());
+        else {
+            out.print(comma, pointerDump(node-&gt;cellOperand()-&gt;value().asCell()));
+            if (node-&gt;cellOperand()-&gt;value().isCell()) {
+                CallVariant variant(node-&gt;cellOperand()-&gt;value().asCell());
+                if (ExecutableBase* executable = variant.executable()) {
+                    if (executable-&gt;isHostFunction())
+                        out.print(comma, &quot;&lt;host function&gt;&quot;);
+                    else if (FunctionExecutable* functionExecutable = jsDynamicCast&lt;FunctionExecutable*&gt;(executable))
+                        out.print(comma, FunctionExecutableDump(functionExecutable));
+                    else
+                        out.print(comma, &quot;&lt;non-function executable&gt;&quot;);
+                }
+            }
+        }
</ins><span class="cx">     }
</span><del>-    if (node-&gt;hasExecutable()) {
-        if (node-&gt;executable()-&gt;inherits(FunctionExecutable::info()))
-            out.print(comma, &quot;executable(&quot;, FunctionExecutableDump(jsCast&lt;FunctionExecutable*&gt;(node-&gt;executable())), &quot;)&quot;);
-        else
-            out.print(comma, &quot;executable(not function: &quot;, RawPointer(node-&gt;executable()), &quot;)&quot;);
-    }
</del><span class="cx">     if (node-&gt;hasFunctionDeclIndex()) {
</span><span class="cx">         FunctionExecutable* executable = m_codeBlock-&gt;functionDecl(node-&gt;functionDeclIndex());
</span><span class="cx">         out.print(comma, FunctionExecutableDump(executable));
</span><span class="lines">@@ -985,10 +984,6 @@
</span><span class="cx">             Node* node = block-&gt;at(nodeIndex);
</span><span class="cx">             
</span><span class="cx">             switch (node-&gt;op()) {
</span><del>-            case CheckExecutable:
-                visitor.appendUnbarrieredReadOnlyPointer(node-&gt;executable());
-                break;
-                
</del><span class="cx">             case CheckStructure:
</span><span class="cx">                 for (unsigned i = node-&gt;structureSet().size(); i--;)
</span><span class="cx">                     visitor.appendUnbarrieredReadOnlyPointer(node-&gt;structureSet()[i]);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -188,7 +188,7 @@
</span><span class="cx">             table.ctiOffsets[j] = table.ctiDefault;
</span><span class="cx">         for (unsigned j = data.cases.size(); j--;) {
</span><span class="cx">             SwitchCase&amp; myCase = data.cases[j];
</span><del>-            table.ctiOffsets[myCase.value.switchLookupValue() - table.min] =
</del><ins>+            table.ctiOffsets[myCase.value.switchLookupValue(data.kind) - table.min] =
</ins><span class="cx">                 linkBuffer.locationOf(m_blockHeads[myCase.target.block-&gt;index]);
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGLazyJSValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGLazyJSValue.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGLazyJSValue.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGLazyJSValue.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -113,6 +113,36 @@
</span><span class="cx">     return FalseTriState;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+uintptr_t LazyJSValue::switchLookupValue(SwitchKind kind) const
+{
+    // NB. Not every kind of JSValue will be able to give you a switch lookup
+    // value, and this method will assert, or do bad things, if you use it
+    // for a kind of value that can't.
+    switch (m_kind) {
+    case KnownValue:
+        switch (kind) {
+        case SwitchImm:
+            return value()-&gt;value().asInt32();
+        case SwitchCell:
+            return bitwise_cast&lt;uintptr_t&gt;(value()-&gt;value().asCell());
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return 0;
+        }
+    case SingleCharacterString:
+        switch (kind) {
+        case SwitchChar:
+            return character();
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return 0;
+        }
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+        return 0;
+    }
+}
+
</ins><span class="cx"> void LazyJSValue::dumpInContext(PrintStream&amp; out, DumpContext* context) const
</span><span class="cx"> {
</span><span class="cx">     switch (m_kind) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGLazyJSValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGLazyJSValue.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGLazyJSValue.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGLazyJSValue.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;DFGCommon.h&quot;
</ins><span class="cx"> #include &quot;DFGFrozenValue.h&quot;
</span><span class="cx"> #include &lt;wtf/text/StringImpl.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -95,21 +96,7 @@
</span><span class="cx">     
</span><span class="cx">     TriState strictEqual(const LazyJSValue&amp; other) const;
</span><span class="cx">     
</span><del>-    unsigned switchLookupValue() const
-    {
-        // NB. Not every kind of JSValue will be able to give you a switch lookup
-        // value, and this method will assert, or do bad things, if you use it
-        // for a kind of value that can't.
-        switch (m_kind) {
-        case KnownValue:
-            return value()-&gt;value().asInt32();
-        case SingleCharacterString:
-            return character();
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-            return 0;
-        }
-    }
</del><ins>+    uintptr_t switchLookupValue(SwitchKind) const;
</ins><span class="cx">     
</span><span class="cx">     void dump(PrintStream&amp;) const;
</span><span class="cx">     void dumpInContext(PrintStream&amp;, DumpContext*) const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -113,6 +113,9 @@
</span><span class="cx">     case SwitchString:
</span><span class="cx">         out.print(&quot;SwitchString&quot;);
</span><span class="cx">         return;
</span><ins>+    case SwitchCell:
+        out.print(&quot;SwitchCell&quot;);
+        return;
</ins><span class="cx">     }
</span><span class="cx">     RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -157,12 +157,6 @@
</span><span class="cx">     BranchTarget target;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-enum SwitchKind {
-    SwitchImm,
-    SwitchChar,
-    SwitchString
-};
-
</del><span class="cx"> struct SwitchData {
</span><span class="cx">     // Initializes most fields to obviously invalid values. Anyone
</span><span class="cx">     // constructing this should make sure to initialize everything they
</span><span class="lines">@@ -185,6 +179,7 @@
</span><span class="cx"> // distinguishes an immediate value (typically an index into a CodeBlock data structure - 
</span><span class="cx"> // a constant index, argument, or identifier) from a Node*.
</span><span class="cx"> struct OpInfo {
</span><ins>+    OpInfo() : m_value(0) { }
</ins><span class="cx">     explicit OpInfo(int32_t value) : m_value(static_cast&lt;uintptr_t&gt;(value)) { }
</span><span class="cx">     explicit OpInfo(uint32_t value) : m_value(static_cast&lt;uintptr_t&gt;(value)) { }
</span><span class="cx"> #if OS(DARWIN) || USE(JSVALUE64)
</span><span class="lines">@@ -1009,6 +1004,8 @@
</span><span class="cx">         case GetMyArgumentByValSafe:
</span><span class="cx">         case Call:
</span><span class="cx">         case Construct:
</span><ins>+        case ProfiledCall:
+        case ProfiledConstruct:
</ins><span class="cx">         case NativeCall:
</span><span class="cx">         case NativeConstruct:
</span><span class="cx">         case GetByOffset:
</span><span class="lines">@@ -1044,9 +1041,11 @@
</span><span class="cx">         m_opInfo2 = prediction;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    bool canBeKnownFunction()
</del><ins>+    bool hasCellOperand()
</ins><span class="cx">     {
</span><span class="cx">         switch (op()) {
</span><ins>+        case AllocationProfileWatchpoint:
+        case CheckCell:
</ins><span class="cx">         case NativeConstruct:
</span><span class="cx">         case NativeCall:
</span><span class="cx">             return true;
</span><span class="lines">@@ -1055,56 +1054,18 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool hasKnownFunction()
</del><ins>+    FrozenValue* cellOperand()
</ins><span class="cx">     {
</span><del>-        switch (op()) {
-        case NativeConstruct:
-        case NativeCall:
-            return (bool)m_opInfo;
-        default:
-            return false;
-        }
-    }
-    
-    JSFunction* knownFunction()
-    {
-        ASSERT(canBeKnownFunction());
-        return bitwise_cast&lt;JSFunction*&gt;(m_opInfo);
-    }
-
-    void giveKnownFunction(JSFunction* callData) 
-    {
-        ASSERT(canBeKnownFunction());
-        m_opInfo = bitwise_cast&lt;uintptr_t&gt;(callData);
-    }
-
-    bool hasFunction()
-    {
-        switch (op()) {
-        case CheckFunction:
-        case AllocationProfileWatchpoint:
-            return true;
-        default:
-            return false;
-        }
-    }
-
-    FrozenValue* function()
-    {
-        ASSERT(hasFunction());
</del><ins>+        ASSERT(hasCellOperand());
</ins><span class="cx">         return reinterpret_cast&lt;FrozenValue*&gt;(m_opInfo);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    bool hasExecutable()
</del><ins>+    void setCellOperand(FrozenValue* value)
</ins><span class="cx">     {
</span><del>-        return op() == CheckExecutable;
</del><ins>+        ASSERT(hasCellOperand());
+        m_opInfo = bitwise_cast&lt;uintptr_t&gt;(value);
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    ExecutableBase* executable()
-    {
-        return jsCast&lt;ExecutableBase*&gt;(reinterpret_cast&lt;JSCell*&gt;(m_opInfo));
-    }
-    
</del><span class="cx">     bool hasVariableWatchpointSet()
</span><span class="cx">     {
</span><span class="cx">         return op() == NotifyWrite || op() == VariableWatchpoint;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -153,7 +153,7 @@
</span><span class="cx">     macro(PutByIdFlush, NodeMustGenerate | NodeMustGenerate | NodeClobbersWorld) \
</span><span class="cx">     macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
</span><span class="cx">     macro(CheckStructure, NodeMustGenerate) \
</span><del>-    macro(CheckExecutable, NodeMustGenerate) \
</del><ins>+    macro(GetExecutable, NodeResultJS) \
</ins><span class="cx">     macro(PutStructure, NodeMustGenerate) \
</span><span class="cx">     macro(AllocatePropertyStorage, NodeMustGenerate | NodeResultStorage) \
</span><span class="cx">     macro(ReallocatePropertyStorage, NodeMustGenerate | NodeResultStorage) \
</span><span class="lines">@@ -185,7 +185,8 @@
</span><span class="cx">     macro(VariableWatchpoint, NodeMustGenerate) \
</span><span class="cx">     macro(VarInjectionWatchpoint, NodeMustGenerate) \
</span><span class="cx">     macro(FunctionReentryWatchpoint, NodeMustGenerate) \
</span><del>-    macro(CheckFunction, NodeMustGenerate) \
</del><ins>+    macro(CheckCell, NodeMustGenerate) \
+    macro(CheckBadCell, NodeMustGenerate) \
</ins><span class="cx">     macro(AllocationProfileWatchpoint, NodeMustGenerate) \
</span><span class="cx">     macro(CheckInBounds, NodeMustGenerate) \
</span><span class="cx">     \
</span><span class="lines">@@ -214,6 +215,8 @@
</span><span class="cx">     /* Calls. */\
</span><span class="cx">     macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
</span><span class="cx">     macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
</span><ins>+    macro(ProfiledCall, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
+    macro(ProfiledConstruct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
</ins><span class="cx">     macro(NativeCall, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
</span><span class="cx">     macro(NativeConstruct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
</span><span class="cx">     \
</span><span class="lines">@@ -286,6 +289,11 @@
</span><span class="cx">     /* different compiler. */\
</span><span class="cx">     macro(ForceOSRExit, NodeMustGenerate) \
</span><span class="cx">     \
</span><ins>+    /* Vends a bottom JS value. It is invalid to ever execute this. Useful for cases */\
+    /* where we know that we would have exited but we'd like to still track the control */\
+    /* flow. */\
+    macro(BottomValue, NodeResultJS) \
+    \
</ins><span class="cx">     /* Checks the watchdog timer. If the timer has fired, we OSR exit to the */ \
</span><span class="cx">     /* baseline JIT to redo the watchdog timer check, and service the timer. */ \
</span><span class="cx">     macro(CheckWatchdogTimer, NodeMustGenerate) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPhantomCanonicalizationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -92,8 +92,10 @@
</span><span class="cx">                         node-&gt;children.removeEdge(i--);
</span><span class="cx">                     }
</span><span class="cx">                     
</span><del>-                    if (node-&gt;children.isEmpty())
</del><ins>+                    if (node-&gt;children.isEmpty()) {
+                        m_graph.m_allocator.free(node);
</ins><span class="cx">                         continue;
</span><ins>+                    }
</ins><span class="cx">                     
</span><span class="cx">                     node-&gt;convertToCheck();
</span><span class="cx">                 }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPhantomRemovalPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -125,6 +125,7 @@
</span><span class="cx">                     }
</span><span class="cx">                     
</span><span class="cx">                     if (node-&gt;children.isEmpty()) {
</span><ins>+                        m_graph.m_allocator.free(node);
</ins><span class="cx">                         changed = true;
</span><span class="cx">                         continue;
</span><span class="cx">                     }
</span><span class="lines">@@ -142,6 +143,7 @@
</span><span class="cx">                         changed = true;
</span><span class="cx">                     }
</span><span class="cx">                     if (node-&gt;children.isEmpty()) {
</span><ins>+                        m_graph.m_allocator.free(node);
</ins><span class="cx">                         changed = true;
</span><span class="cx">                         continue;
</span><span class="cx">                     }
</span><span class="lines">@@ -149,8 +151,10 @@
</span><span class="cx">                 }
</span><span class="cx">                     
</span><span class="cx">                 case HardPhantom: {
</span><del>-                    if (node-&gt;children.isEmpty())
</del><ins>+                    if (node-&gt;children.isEmpty()) {
+                        m_graph.m_allocator.free(node);
</ins><span class="cx">                         continue;
</span><ins>+                    }
</ins><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="cx">                     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -188,6 +188,8 @@
</span><span class="cx">         case GetDirectPname:
</span><span class="cx">         case Call:
</span><span class="cx">         case Construct:
</span><ins>+        case ProfiledCall:
+        case ProfiledConstruct:
</ins><span class="cx">         case NativeCall:
</span><span class="cx">         case NativeConstruct:
</span><span class="cx">         case GetGlobalVar:
</span><span class="lines">@@ -196,7 +198,8 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><del>-        case GetGetterSetterByOffset: {
</del><ins>+        case GetGetterSetterByOffset:
+        case GetExecutable: {
</ins><span class="cx">             changed |= setPrediction(SpecCellOther);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -642,8 +645,8 @@
</span><span class="cx">         case ForceOSRExit:
</span><span class="cx">         case SetArgument:
</span><span class="cx">         case CheckStructure:
</span><del>-        case CheckExecutable:
-        case CheckFunction:
</del><ins>+        case CheckCell:
+        case CheckBadCell:
</ins><span class="cx">         case PutStructure:
</span><span class="cx">         case TearOffActivation:
</span><span class="cx">         case TearOffArguments:
</span><span class="lines">@@ -665,6 +668,10 @@
</span><span class="cx">         case ZombieHint:
</span><span class="cx">             break;
</span><span class="cx">             
</span><ins>+        // This gets ignored because it only pretends to produce a value.
+        case BottomValue:
+            break;
+            
</ins><span class="cx">         // This gets ignored because it already has a prediction.
</span><span class="cx">         case ExtractOSREntryLocal:
</span><span class="cx">             break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -159,7 +159,7 @@
</span><span class="cx">     case PutByIdFlush:
</span><span class="cx">     case PutByIdDirect:
</span><span class="cx">     case CheckStructure:
</span><del>-    case CheckExecutable:
</del><ins>+    case GetExecutable:
</ins><span class="cx">     case GetButterfly:
</span><span class="cx">     case CheckArray:
</span><span class="cx">     case Arrayify:
</span><span class="lines">@@ -174,7 +174,8 @@
</span><span class="cx">     case PutGlobalVar:
</span><span class="cx">     case VariableWatchpoint:
</span><span class="cx">     case VarInjectionWatchpoint:
</span><del>-    case CheckFunction:
</del><ins>+    case CheckCell:
+    case CheckBadCell:
</ins><span class="cx">     case AllocationProfileWatchpoint:
</span><span class="cx">     case RegExpExec:
</span><span class="cx">     case RegExpTest:
</span><span class="lines">@@ -187,6 +188,8 @@
</span><span class="cx">     case CompareStrictEq:
</span><span class="cx">     case Call:
</span><span class="cx">     case Construct:
</span><ins>+    case ProfiledCall:
+    case ProfiledConstruct:
</ins><span class="cx">     case NewObject:
</span><span class="cx">     case NewArray:
</span><span class="cx">     case NewArrayWithSize:
</span><span class="lines">@@ -273,6 +276,11 @@
</span><span class="cx">     case NativeConstruct:
</span><span class="cx">         return false; // TODO: add a check for already checked.  https://bugs.webkit.org/show_bug.cgi?id=133769
</span><span class="cx"> 
</span><ins>+    case BottomValue:
+        // If in doubt, assume that this isn't safe to execute, just because we have no way of
+        // compiling this node.
+        return false;
+
</ins><span class="cx">     case GetByVal:
</span><span class="cx">     case GetIndexedPropertyStorage:
</span><span class="cx">     case GetArrayLength:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -5354,6 +5354,10 @@
</span><span class="cx">     case SwitchString: {
</span><span class="cx">         emitSwitchString(node, data);
</span><span class="cx">         return;
</span><ins>+    }
+    case SwitchCell: {
+        DFG_CRASH(m_jit.graph(), node, &quot;Bad switch kind&quot;);
+        return;
</ins><span class="cx">     } }
</span><span class="cx">     RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -640,9 +640,9 @@
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::emitCall(Node* node)
</span><span class="cx"> {
</span><del>-    bool isCall = node-&gt;op() == Call;
</del><ins>+    bool isCall = node-&gt;op() == Call || node-&gt;op() == ProfiledCall;
</ins><span class="cx">     if (!isCall)
</span><del>-        ASSERT(node-&gt;op() == Construct);
</del><ins>+        ASSERT(node-&gt;op() == Construct || node-&gt;op() == ProfiledConstruct);
</ins><span class="cx"> 
</span><span class="cx">     // For constructors, the this argument is not passed but we have to make space
</span><span class="cx">     // for it.
</span><span class="lines">@@ -689,6 +689,13 @@
</span><span class="cx"> 
</span><span class="cx">     m_jit.emitStoreCodeOrigin(node-&gt;origin.semantic);
</span><span class="cx">     
</span><ins>+    CallLinkInfo* info = m_jit.codeBlock()-&gt;addCallLinkInfo();
+
+    if (node-&gt;op() == ProfiledCall || node-&gt;op() == ProfiledConstruct) {
+        m_jit.vm()-&gt;callEdgeLog-&gt;emitLogCode(
+            m_jit, info-&gt;callEdgeProfile, callee.jsValueRegs());
+    }
+    
</ins><span class="cx">     slowPath.append(branchNotCell(callee.jsValueRegs()));
</span><span class="cx">     slowPath.append(m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleePayloadGPR, targetToCheck));
</span><span class="cx">     m_jit.loadPtr(MacroAssembler::Address(calleePayloadGPR, OBJECT_OFFSETOF(JSFunction, m_scope)), resultPayloadGPR);
</span><span class="lines">@@ -713,7 +720,6 @@
</span><span class="cx">         m_jit.move(calleePayloadGPR, GPRInfo::regT0);
</span><span class="cx">         m_jit.move(calleeTagGPR, GPRInfo::regT1);
</span><span class="cx">     }
</span><del>-    CallLinkInfo* info = m_jit.codeBlock()-&gt;addCallLinkInfo();
</del><span class="cx">     m_jit.move(MacroAssembler::TrustedImmPtr(info), GPRInfo::regT2);
</span><span class="cx">     JITCompiler::Call slowCall = m_jit.nearCall();
</span><span class="cx"> 
</span><span class="lines">@@ -3675,18 +3681,21 @@
</span><span class="cx">         compileGetArrayLength(node);
</span><span class="cx">         break;
</span><span class="cx">         
</span><del>-    case CheckFunction: {
-        SpeculateCellOperand function(this, node-&gt;child1());
-        speculationCheck(BadFunction, JSValueSource::unboxedCell(function.gpr()), node-&gt;child1(), m_jit.branchWeakPtr(JITCompiler::NotEqual, function.gpr(), node-&gt;function()-&gt;value().asCell()));
</del><ins>+    case CheckCell: {
+        SpeculateCellOperand cell(this, node-&gt;child1());
+        speculationCheck(BadCell, JSValueSource::unboxedCell(cell.gpr()), node-&gt;child1(), m_jit.branchWeakPtr(JITCompiler::NotEqual, cell.gpr(), node-&gt;cellOperand()-&gt;value().asCell()));
</ins><span class="cx">         noResult(node);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    case CheckExecutable: {
</del><ins>+    case GetExecutable: {
</ins><span class="cx">         SpeculateCellOperand function(this, node-&gt;child1());
</span><del>-        speculateCellType(node-&gt;child1(), function.gpr(), SpecFunction, JSFunctionType);
-        speculationCheck(BadExecutable, JSValueSource::unboxedCell(function.gpr()), node-&gt;child1(), m_jit.branchWeakPtr(JITCompiler::NotEqual, JITCompiler::Address(function.gpr(), JSFunction::offsetOfExecutable()), node-&gt;executable()));
-        noResult(node);
</del><ins>+        GPRTemporary result(this, Reuse, function);
+        GPRReg functionGPR = function.gpr();
+        GPRReg resultGPR = result.gpr();
+        speculateCellType(node-&gt;child1(), functionGPR, SpecFunction, JSFunctionType);
+        m_jit.loadPtr(JITCompiler::Address(functionGPR, JSFunction::offsetOfExecutable()), resultGPR);
+        cellResult(resultGPR, node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="lines">@@ -4156,6 +4165,8 @@
</span><span class="cx"> 
</span><span class="cx">     case Call:
</span><span class="cx">     case Construct:
</span><ins>+    case ProfiledCall:
+    case ProfiledConstruct:
</ins><span class="cx">         emitCall(node);
</span><span class="cx">         break;
</span><span class="cx"> 
</span><span class="lines">@@ -4892,6 +4903,8 @@
</span><span class="cx">     case MultiPutByOffset:
</span><span class="cx">     case NativeCall:
</span><span class="cx">     case NativeConstruct:
</span><ins>+    case CheckBadCell:
+    case BottomValue:
</ins><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         break;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -626,10 +626,9 @@
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::emitCall(Node* node)
</span><span class="cx"> {
</span><del>-
-    bool isCall = node-&gt;op() == Call;
</del><ins>+    bool isCall = node-&gt;op() == Call || node-&gt;op() == ProfiledCall;
</ins><span class="cx">     if (!isCall)
</span><del>-        DFG_ASSERT(m_jit.graph(), node, node-&gt;op() == Construct);
</del><ins>+        DFG_ASSERT(m_jit.graph(), node, node-&gt;op() == Construct || node-&gt;op() == ProfiledConstruct);
</ins><span class="cx">     
</span><span class="cx">     // For constructors, the this argument is not passed but we have to make space
</span><span class="cx">     // for it.
</span><span class="lines">@@ -670,6 +669,13 @@
</span><span class="cx"> 
</span><span class="cx">     m_jit.emitStoreCodeOrigin(node-&gt;origin.semantic);
</span><span class="cx">     
</span><ins>+    CallLinkInfo* callLinkInfo = m_jit.codeBlock()-&gt;addCallLinkInfo();
+    
+    if (node-&gt;op() == ProfiledCall || node-&gt;op() == ProfiledConstruct) {
+        m_jit.vm()-&gt;callEdgeLog-&gt;emitLogCode(
+            m_jit, callLinkInfo-&gt;callEdgeProfile, JSValueRegs(calleeGPR));
+    }
+
</ins><span class="cx">     slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(0));
</span><span class="cx"> 
</span><span class="cx">     m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scope)), resultGPR);
</span><span class="lines">@@ -682,7 +688,6 @@
</span><span class="cx">     slowPath.link(&amp;m_jit);
</span><span class="cx">     
</span><span class="cx">     m_jit.move(calleeGPR, GPRInfo::regT0); // Callee needs to be in regT0
</span><del>-    CallLinkInfo* callLinkInfo = m_jit.codeBlock()-&gt;addCallLinkInfo();
</del><span class="cx">     m_jit.move(MacroAssembler::TrustedImmPtr(callLinkInfo), GPRInfo::regT2); // Link info needs to be in regT2
</span><span class="cx">     JITCompiler::Call slowCall = m_jit.nearCall();
</span><span class="cx">     
</span><span class="lines">@@ -3768,18 +3773,21 @@
</span><span class="cx">         compileGetArrayLength(node);
</span><span class="cx">         break;
</span><span class="cx">         
</span><del>-    case CheckFunction: {
-        SpeculateCellOperand function(this, node-&gt;child1());
-        speculationCheck(BadFunction, JSValueSource::unboxedCell(function.gpr()), node-&gt;child1(), m_jit.branchWeakPtr(JITCompiler::NotEqual, function.gpr(), node-&gt;function()-&gt;value().asCell()));
</del><ins>+    case CheckCell: {
+        SpeculateCellOperand cell(this, node-&gt;child1());
+        speculationCheck(BadCell, JSValueSource::unboxedCell(cell.gpr()), node-&gt;child1(), m_jit.branchWeakPtr(JITCompiler::NotEqual, cell.gpr(), node-&gt;cellOperand()-&gt;value().asCell()));
</ins><span class="cx">         noResult(node);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><del>-    case CheckExecutable: {
</del><ins>+    case GetExecutable: {
</ins><span class="cx">         SpeculateCellOperand function(this, node-&gt;child1());
</span><del>-        speculateCellType(node-&gt;child1(), function.gpr(), SpecFunction, JSFunctionType);
-        speculationCheck(BadExecutable, JSValueSource::unboxedCell(function.gpr()), node-&gt;child1(), m_jit.branchWeakPtr(JITCompiler::NotEqual, JITCompiler::Address(function.gpr(), JSFunction::offsetOfExecutable()), node-&gt;executable()));
-        noResult(node);
</del><ins>+        GPRTemporary result(this, Reuse, function);
+        GPRReg functionGPR = function.gpr();
+        GPRReg resultGPR = result.gpr();
+        speculateCellType(node-&gt;child1(), functionGPR, SpecFunction, JSFunctionType);
+        m_jit.loadPtr(JITCompiler::Address(functionGPR, JSFunction::offsetOfExecutable()), resultGPR);
+        cellResult(resultGPR, node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="lines">@@ -4219,9 +4227,11 @@
</span><span class="cx"> 
</span><span class="cx">     case Call:
</span><span class="cx">     case Construct:
</span><ins>+    case ProfiledCall:
+    case ProfiledConstruct:
</ins><span class="cx">         emitCall(node);
</span><span class="cx">         break;
</span><del>-
</del><ins>+        
</ins><span class="cx">     case CreateActivation: {
</span><span class="cx">         DFG_ASSERT(m_jit.graph(), node, !node-&gt;origin.semantic.inlineCallFrame);
</span><span class="cx">         
</span><span class="lines">@@ -4970,7 +4980,9 @@
</span><span class="cx">     case MultiGetByOffset:
</span><span class="cx">     case MultiPutByOffset:
</span><span class="cx">     case FiatInt52:
</span><del>-        DFG_CRASH(m_jit.graph(), node, &quot;Unexpected FTL node&quot;);
</del><ins>+    case CheckBadCell:
+    case BottomValue:
+        DFG_CRASH(m_jit.graph(), node, &quot;Unexpected node&quot;);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGStructureRegistrationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -62,10 +62,6 @@
</span><span class="cx">                 Node* node = block-&gt;at(nodeIndex);
</span><span class="cx">             
</span><span class="cx">                 switch (node-&gt;op()) {
</span><del>-                case CheckExecutable:
-                    registerStructure(node-&gt;executable()-&gt;structure());
-                    break;
-                
</del><span class="cx">                 case CheckStructure:
</span><span class="cx">                     registerStructures(node-&gt;structureSet());
</span><span class="cx">                     break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGTierUpCheckInjectionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -50,13 +50,17 @@
</span><span class="cx">         if (!Options::useFTLJIT())
</span><span class="cx">             return false;
</span><span class="cx">         
</span><del>-        if (m_graph.m_profiledBlock-&gt;m_didFailFTLCompilation)
</del><ins>+        if (m_graph.m_profiledBlock-&gt;m_didFailFTLCompilation) {
+            removeFTLProfiling();
</ins><span class="cx">             return false;
</span><ins>+        }
</ins><span class="cx">         
</span><span class="cx"> #if ENABLE(FTL_JIT)
</span><span class="cx">         FTL::CapabilityLevel level = FTL::canCompile(m_graph);
</span><del>-        if (level == FTL::CannotCompile)
</del><ins>+        if (level == FTL::CannotCompile) {
+            removeFTLProfiling();
</ins><span class="cx">             return false;
</span><ins>+        }
</ins><span class="cx">         
</span><span class="cx">         if (!Options::enableOSREntryToFTL())
</span><span class="cx">             level = FTL::CanCompile;
</span><span class="lines">@@ -118,6 +122,32 @@
</span><span class="cx">         return false;
</span><span class="cx"> #endif // ENABLE(FTL_JIT)
</span><span class="cx">     }
</span><ins>+
+private:
+    void removeFTLProfiling()
+    {
+        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
+                continue;
+            
+            for (unsigned nodeIndex = 0; nodeIndex &lt; block-&gt;size(); ++nodeIndex) {
+                Node* node = block-&gt;at(nodeIndex);
+                switch (node-&gt;op()) {
+                case ProfiledCall:
+                    node-&gt;setOp(Call);
+                    break;
+                    
+                case ProfiledConstruct:
+                    node-&gt;setOp(Construct);
+                    break;
+                    
+                default:
+                    break;
+                }
+            }
+        }
+    }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> bool performTierUpCheckInjection(Graph&amp; graph)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGValidatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -200,7 +200,8 @@
</span><span class="cx">                 
</span><span class="cx">                 VALIDATE((node), !mayExit(m_graph, node) || node-&gt;origin.forExit.isSet());
</span><span class="cx">                 VALIDATE((node), !node-&gt;hasStructure() || !!node-&gt;structure());
</span><del>-                VALIDATE((node), !node-&gt;hasFunction() || node-&gt;function()-&gt;value().isFunction());
</del><ins>+                VALIDATE((node), !node-&gt;hasCellOperand() || node-&gt;cellOperand()-&gt;value().isCell());
+                VALIDATE((node), !node-&gt;hasCellOperand() || !!node-&gt;cellOperand()-&gt;value());
</ins><span class="cx">                  
</span><span class="cx">                 if (!(node-&gt;flags() &amp; NodeHasVarArgs)) {
</span><span class="cx">                     if (!node-&gt;child2())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGWatchpointCollectionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2014 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">@@ -114,7 +114,7 @@
</span><span class="cx">             break;
</span><span class="cx">             
</span><span class="cx">         case AllocationProfileWatchpoint:
</span><del>-            addLazily(jsCast&lt;JSFunction*&gt;(m_node-&gt;function()-&gt;value())-&gt;allocationProfileWatchpointSet());
</del><ins>+            addLazily(jsCast&lt;JSFunction*&gt;(m_node-&gt;cellOperand()-&gt;value())-&gt;allocationProfileWatchpointSet());
</ins><span class="cx">             break;
</span><span class="cx">             
</span><span class="cx">         case VariableWatchpoint:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -104,7 +104,8 @@
</span><span class="cx">     case PutClosureVar:
</span><span class="cx">     case InvalidationPoint:
</span><span class="cx">     case StringCharAt:
</span><del>-    case CheckFunction:
</del><ins>+    case CheckCell:
+    case CheckBadCell:
</ins><span class="cx">     case StringCharCodeAt:
</span><span class="cx">     case AllocatePropertyStorage:
</span><span class="cx">     case ReallocatePropertyStorage:
</span><span class="lines">@@ -126,7 +127,7 @@
</span><span class="cx">     case ConstantStoragePointer:
</span><span class="cx">     case Check:
</span><span class="cx">     case CountExecution:
</span><del>-    case CheckExecutable:
</del><ins>+    case GetExecutable:
</ins><span class="cx">     case GetScope:
</span><span class="cx">     case AllocationProfileWatchpoint:
</span><span class="cx">     case CheckArgumentsNotCreated:
</span><span class="lines">@@ -166,8 +167,14 @@
</span><span class="cx">     case GetGenericPropertyEnumerator:
</span><span class="cx">     case GetEnumeratorPname:
</span><span class="cx">     case ToIndexString:
</span><ins>+    case BottomValue:
</ins><span class="cx">         // These are OK.
</span><span class="cx">         break;
</span><ins>+    case ProfiledCall:
+    case ProfiledConstruct:
+        // These are OK not because the FTL can support them, but because if the DFG sees one of
+        // these then the FTL will see a normal Call/Construct.
+        break;
</ins><span class="cx">     case Identity:
</span><span class="cx">         // No backend handles this because it will be optimized out. But we may check
</span><span class="cx">         // for capabilities before optimization. It would be a deep error to remove this
</span><span class="lines">@@ -326,6 +333,7 @@
</span><span class="cx">         switch (node-&gt;switchData()-&gt;kind) {
</span><span class="cx">         case SwitchImm:
</span><span class="cx">         case SwitchChar:
</span><ins>+        case SwitchCell:
</ins><span class="cx">             break;
</span><span class="cx">         default:
</span><span class="cx">             return CannotCompile;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -67,7 +67,6 @@
</span><span class="cx"> NO_RETURN_DUE_TO_CRASH static void ftlUnreachable(
</span><span class="cx">     CodeBlock* codeBlock, BlockIndex blockIndex, unsigned nodeIndex)
</span><span class="cx"> {
</span><del>-    
</del><span class="cx">     dataLog(&quot;Crashing in thought-to-be-unreachable FTL-generated code for &quot;, pointerDump(codeBlock), &quot; at basic block #&quot;, blockIndex);
</span><span class="cx">     if (nodeIndex != UINT_MAX)
</span><span class="cx">         dataLog(&quot;, node @&quot;, nodeIndex);
</span><span class="lines">@@ -153,12 +152,18 @@
</span><span class="cx">         for (unsigned blockIndex = depthFirst.size(); blockIndex--; ) {
</span><span class="cx">             BasicBlock* block = depthFirst[blockIndex];
</span><span class="cx">             for (unsigned nodeIndex = block-&gt;size(); nodeIndex--; ) {
</span><del>-                Node* m_node = block-&gt;at(nodeIndex);
-                if (m_node-&gt;hasKnownFunction()) {
</del><ins>+                Node* node = block-&gt;at(nodeIndex);
+                switch (node-&gt;op()) {
+                case NativeCall:
+                case NativeConstruct: {
</ins><span class="cx">                     int numArgs = m_node-&gt;numChildren();
</span><span class="cx">                     if (numArgs &gt; maxNumberOfArguments)
</span><span class="cx">                         maxNumberOfArguments = numArgs;
</span><ins>+                    break;
</ins><span class="cx">                 }
</span><ins>+                default:
+                    break;
+                }
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -468,12 +473,15 @@
</span><span class="cx">         case CheckStructure:
</span><span class="cx">             compileCheckStructure();
</span><span class="cx">             break;
</span><del>-        case CheckFunction:
-            compileCheckFunction();
</del><ins>+        case CheckCell:
+            compileCheckCell();
</ins><span class="cx">             break;
</span><del>-        case CheckExecutable:
-            compileCheckExecutable();
</del><ins>+        case CheckBadCell:
+            compileCheckBadCell();
</ins><span class="cx">             break;
</span><ins>+        case GetExecutable:
+            compileGetExecutable();
+            break;
</ins><span class="cx">         case ArrayifyToStructure:
</span><span class="cx">             compileArrayifyToStructure();
</span><span class="cx">             break;
</span><span class="lines">@@ -1743,26 +1751,25 @@
</span><span class="cx">         m_out.appendTo(continuation, lastNext);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void compileCheckFunction()
</del><ins>+    void compileCheckCell()
</ins><span class="cx">     {
</span><span class="cx">         LValue cell = lowCell(m_node-&gt;child1());
</span><span class="cx">         
</span><span class="cx">         speculate(
</span><del>-            BadFunction, jsValueValue(cell), m_node-&gt;child1().node(),
-            m_out.notEqual(cell, weakPointer(m_node-&gt;function()-&gt;value().asCell())));
</del><ins>+            BadCell, jsValueValue(cell), m_node-&gt;child1().node(),
+            m_out.notEqual(cell, weakPointer(m_node-&gt;cellOperand()-&gt;value().asCell())));
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    void compileCheckExecutable()
</del><ins>+    void compileCheckBadCell()
</ins><span class="cx">     {
</span><ins>+        terminate(BadCell);
+    }
+    
+    void compileGetExecutable()
+    {
</ins><span class="cx">         LValue cell = lowCell(m_node-&gt;child1());
</span><del>-        
</del><span class="cx">         speculateFunction(m_node-&gt;child1(), cell);
</span><del>-        
-        speculate(
-            BadExecutable, jsValueValue(cell), m_node-&gt;child1().node(),
-            m_out.notEqual(
-                m_out.loadPtr(cell, m_heaps.JSFunction_executable),
-                weakPointer(m_node-&gt;executable())));
</del><ins>+        setJSValue(m_out.loadPtr(cell, m_heaps.JSFunction_executable));
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void compileArrayifyToStructure()
</span><span class="lines">@@ -3673,9 +3680,7 @@
</span><span class="cx">         int numPassedArgs = m_node-&gt;numChildren() - 1;
</span><span class="cx">         int numArgs = numPassedArgs + dummyThisArgument;
</span><span class="cx"> 
</span><del>-        ASSERT(m_node-&gt;hasKnownFunction());
-
-        JSFunction* knownFunction = m_node-&gt;knownFunction();
</del><ins>+        JSFunction* knownFunction = jsCast&lt;JSFunction*&gt;(m_node-&gt;cellOperand()-&gt;value().asCell());
</ins><span class="cx">         NativeFunction function = knownFunction-&gt;nativeFunction();
</span><span class="cx"> 
</span><span class="cx">         Dl_info info;
</span><span class="lines">@@ -3918,10 +3923,37 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        case SwitchString:
</del><ins>+        case SwitchString: {
</ins><span class="cx">             DFG_CRASH(m_graph, m_node, &quot;Unimplemented&quot;);
</span><del>-            break;
</del><ins>+            return;
</ins><span class="cx">         }
</span><ins>+            
+        case SwitchCell: {
+            LValue cell;
+            switch (m_node-&gt;child1().useKind()) {
+            case CellUse: {
+                cell = lowCell(m_node-&gt;child1());
+                break;
+            }
+                
+            case UntypedUse: {
+                LValue value = lowJSValue(m_node-&gt;child1());
+                LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, (&quot;Switch/SwitchCell cell case&quot;));
+                m_out.branch(
+                    isCell(value), unsure(cellCase), unsure(lowBlock(data-&gt;fallThrough.block)));
+                m_out.appendTo(cellCase);
+                cell = value;
+                break;
+            }
+                
+            default:
+                DFG_CRASH(m_graph, m_node, &quot;Bad use kind&quot;);
+                return;
+            }
+            
+            buildSwitch(m_node-&gt;switchData(), m_out.intPtr, cell);
+            return;
+        } }
</ins><span class="cx">         
</span><span class="cx">         DFG_CRASH(m_graph, m_node, &quot;Bad switch kind&quot;);
</span><span class="cx">     }
</span><span class="lines">@@ -5186,7 +5218,7 @@
</span><span class="cx">         Vector&lt;SwitchCase&gt; cases;
</span><span class="cx">         for (unsigned i = 0; i &lt; data-&gt;cases.size(); ++i) {
</span><span class="cx">             cases.append(SwitchCase(
</span><del>-                constInt(type, data-&gt;cases[i].value.switchLookupValue()),
</del><ins>+                constInt(type, data-&gt;cases[i].value.switchLookupValue(data-&gt;kind)),
</ins><span class="cx">                 lowBlock(data-&gt;cases[i].target.block), Weight(data-&gt;cases[i].target.count)));
</span><span class="cx">         }
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -984,6 +984,11 @@
</span><span class="cx">         vm()-&gt;typeProfilerLog()-&gt;processLogEntries(ASCIILiteral(&quot;GC&quot;));
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    if (vm()-&gt;callEdgeLog) {
+        DeferGCForAWhile awhile(*this);
+        vm()-&gt;callEdgeLog-&gt;processLog();
+    }
+    
</ins><span class="cx">     RELEASE_ASSERT(!m_deferralDepth);
</span><span class="cx">     ASSERT(vm()-&gt;currentThreadIsHoldingAPILock());
</span><span class="cx">     RELEASE_ASSERT(vm()-&gt;atomicStringTable() == wtfThreadData().atomicStringTable());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -88,6 +88,31 @@
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void storeValue(JSValueRegs regs, void* address)
+    {
+#if USE(JSVALUE64)
+        store64(regs.gpr(), address);
+#else
+        store32(regs.payloadGPR(), bitwise_cast&lt;void*&gt;(bitwise_cast&lt;uintptr_t&gt;(address) + PayloadOffset));
+        store32(regs.tagGPR(), bitwise_cast&lt;void*&gt;(bitwise_cast&lt;uintptr_t&gt;(address) + TagOffset));
+#endif
+    }
+    
+    void loadValue(Address address, JSValueRegs regs)
+    {
+#if USE(JSVALUE64)
+        load64(address, regs.gpr());
+#else
+        if (address.base == regs.payloadGPR()) {
+            load32(address.withOffset(TagOffset), regs.tagGPR());
+            load32(address.withOffset(PayloadOffset), regs.payloadGPR());
+        } else {
+            load32(address.withOffset(PayloadOffset), regs.payloadGPR());
+            load32(address.withOffset(TagOffset), regs.tagGPR());
+        }
+#endif
+    }
+    
</ins><span class="cx">     void moveTrustedValue(JSValue value, JSValueRegs regs)
</span><span class="cx">     {
</span><span class="cx"> #if USE(JSVALUE64)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitCCallHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/CCallHelpers.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CCallHelpers.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/jit/CCallHelpers.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -1666,6 +1666,15 @@
</span><span class="cx">         move(arg4, GPRInfo::argumentGPR3);
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><ins>+    
+    void setupArguments(JSValueRegs arg1)
+    {
+#if USE(JSVALUE64)
+        setupArguments(arg1.gpr());
+#else
+        setupArguments(arg1.payloadGPR(), arg1.tagGPR());
+#endif
+    }
</ins><span class="cx"> 
</span><span class="cx">     void setupResults(GPRReg destA, GPRReg destB)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitGPRInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/GPRInfo.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/GPRInfo.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/jit/GPRInfo.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -60,6 +60,8 @@
</span><span class="cx">     GPRReg tagGPR() const { return InvalidGPRReg; }
</span><span class="cx">     GPRReg payloadGPR() const { return m_gpr; }
</span><span class="cx">     
</span><ins>+    bool uses(GPRReg gpr) const { return m_gpr == gpr; }
+    
</ins><span class="cx"> private:
</span><span class="cx">     GPRReg m_gpr;
</span><span class="cx"> };
</span><span class="lines">@@ -169,6 +171,8 @@
</span><span class="cx">         return tagGPR();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool uses(GPRReg gpr) const { return m_tagGPR == gpr || m_payloadGPR == gpr; }
+    
</ins><span class="cx"> private:
</span><span class="cx">     int8_t m_tagGPR;
</span><span class="cx">     int8_t m_payloadGPR;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCallcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCall.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/jit/JITCall.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -212,7 +212,13 @@
</span><span class="cx">     emitGetVirtualRegister(callee, regT0); // regT0 holds callee.
</span><span class="cx"> 
</span><span class="cx">     store64(regT0, Address(stackPointerRegister, JSStack::Callee * static_cast&lt;int&gt;(sizeof(Register)) - sizeof(CallerFrameAndPC)));
</span><ins>+    
+    CallLinkInfo* info = m_codeBlock-&gt;addCallLinkInfo();
</ins><span class="cx"> 
</span><ins>+    if (CallEdgeLog::isEnabled() &amp;&amp; shouldEmitProfiling()
+        &amp;&amp; Options::baselineDoesCallEdgeProfiling())
+        m_vm-&gt;ensureCallEdgeLog().emitLogCode(*this, info-&gt;callEdgeProfile, JSValueRegs(regT0));
+
</ins><span class="cx">     if (opcodeID == op_call_eval) {
</span><span class="cx">         compileCallEval(instruction);
</span><span class="cx">         return;
</span><span class="lines">@@ -223,7 +229,6 @@
</span><span class="cx">     addSlowCase(slowCase);
</span><span class="cx"> 
</span><span class="cx">     ASSERT(m_callCompilationInfo.size() == callLinkInfoIndex);
</span><del>-    CallLinkInfo* info = m_codeBlock-&gt;addCallLinkInfo();
</del><span class="cx">     info-&gt;callType = CallLinkInfo::callTypeFor(opcodeID);
</span><span class="cx">     info-&gt;codeOrigin = CodeOrigin(m_bytecodeOffset);
</span><span class="cx">     info-&gt;calleeGPR = regT0;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCall32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -300,6 +300,14 @@
</span><span class="cx">     store32(regT0, Address(stackPointerRegister, JSStack::Callee * static_cast&lt;int&gt;(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC)));
</span><span class="cx">     store32(regT1, Address(stackPointerRegister, JSStack::Callee * static_cast&lt;int&gt;(sizeof(Register)) + TagOffset - sizeof(CallerFrameAndPC)));
</span><span class="cx"> 
</span><ins>+    CallLinkInfo* info = m_codeBlock-&gt;addCallLinkInfo();
+
+    if (CallEdgeLog::isEnabled() &amp;&amp; shouldEmitProfiling()
+        &amp;&amp; Options::baselineDoesCallEdgeProfiling()) {
+        m_vm-&gt;ensureCallEdgeLog().emitLogCode(
+            *this, info-&gt;callEdgeProfile, JSValueRegs(regT1, regT0));
+    }
+
</ins><span class="cx">     if (opcodeID == op_call_eval) {
</span><span class="cx">         compileCallEval(instruction);
</span><span class="cx">         return;
</span><span class="lines">@@ -313,7 +321,6 @@
</span><span class="cx">     addSlowCase(slowCase);
</span><span class="cx"> 
</span><span class="cx">     ASSERT(m_callCompilationInfo.size() == callLinkInfoIndex);
</span><del>-    CallLinkInfo* info = m_codeBlock-&gt;addCallLinkInfo();
</del><span class="cx">     info-&gt;callType = CallLinkInfo::callTypeFor(opcodeID);
</span><span class="cx">     info-&gt;codeOrigin = CodeOrigin(m_bytecodeOffset);
</span><span class="cx">     info-&gt;calleeGPR = regT0;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -167,6 +167,13 @@
</span><span class="cx">     v(bool, enableAccessInlining, true) \
</span><span class="cx">     v(bool, enablePolyvariantDevirtualization, true) \
</span><span class="cx">     v(bool, enablePolymorphicAccessInlining, true) \
</span><ins>+    v(bool, enablePolymorphicCallInlining, true) \
+    v(bool, callStatusShouldUseCallEdgeProfile, true) \
+    v(bool, callEdgeProfileReallyProcessesLog, true) \
+    v(bool, baselineDoesCallEdgeProfiling, false) \
+    v(bool, dfgDoesCallEdgeProfiling, true) \
+    v(bool, enableCallEdgeProfiling, true) \
+    v(unsigned, frequentCallThreshold, 2) \
</ins><span class="cx">     v(bool, optimizeNativeCalls, false) \
</span><span class="cx">     \
</span><span class="cx">     v(bool, enableConcurrentJIT, true) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -373,6 +373,13 @@
</span><span class="cx">     return sharedInstance;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+CallEdgeLog&amp; VM::ensureCallEdgeLog()
+{
+    if (!callEdgeLog)
+        callEdgeLog = std::make_unique&lt;CallEdgeLog&gt;();
+    return *callEdgeLog;
+}
+
</ins><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> static ThunkGenerator thunkGeneratorForIntrinsic(Intrinsic intrinsic)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -72,6 +72,7 @@
</span><span class="cx"> 
</span><span class="cx">     class ArityCheckFailReturnThunks;
</span><span class="cx">     class BuiltinExecutables;
</span><ins>+    class CallEdgeLog;
</ins><span class="cx">     class CodeBlock;
</span><span class="cx">     class CodeCache;
</span><span class="cx">     class CommonIdentifiers;
</span><span class="lines">@@ -233,6 +234,9 @@
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">         OwnPtr&lt;DFG::LongLivedState&gt; dfgState;
</span><span class="cx"> #endif // ENABLE(DFG_JIT)
</span><ins>+        
+        std::unique_ptr&lt;CallEdgeLog&gt; callEdgeLog;
+        CallEdgeLog&amp; ensureCallEdgeLog();
</ins><span class="cx"> 
</span><span class="cx">         VMType vmType;
</span><span class="cx">         ClientData* clientData;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressnewarraythenexitjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/new-array-then-exit.js (0 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/new-array-then-exit.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/new-array-then-exit.js        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+function foo(f) {
+    return new f();
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 10000; ++i)
+    foo(Array);
+
+var didCall = false;
+foo(function() { didCall = true; });
+
+if (!didCall)
+    throw &quot;Error: didn't call my function.&quot;;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresspolycallexitthisjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/poly-call-exit-this.js (0 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/poly-call-exit-this.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/poly-call-exit-this.js        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -0,0 +1,29 @@
</span><ins>+(function() {
+    function foo(x) { return 1 + this.f; }
+    function bar(x) { return x + this.f; }
+    function baz(x) { return x + 1 + this.f; }
+    
+    var n = 1000000;
+    
+    var result = (function(o) {
+        var f = {fun:foo, f:1};
+        var g = {fun:bar, f:2};
+        var h = {fun:baz, f:3};
+        
+        var result = 0;
+        for (var i = 0; i &lt; n; ++i) {
+            if (i == n - 1)
+                f = h;
+            result += f.fun(o.f);
+            
+            var tmp = f;
+            f = g;
+            g = tmp;
+        }
+        
+        return result;
+    })({f:42});
+    
+    if (result != ((n / 2 - 1) * (42 + 2)) + (n / 2 * (1 + 1) + (42 + 1 + 3)))
+        throw &quot;Error: bad result: &quot; + result;
+})();
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresspolycallexitjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/poly-call-exit.js (0 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/poly-call-exit.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/poly-call-exit.js        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -0,0 +1,29 @@
</span><ins>+(function() {
+    function foo(x) { return 1; }
+    function bar(x) { return x; }
+    function baz(x) { return x + 1; }
+    
+    var n = 1000000;
+    
+    var result = (function(o) {
+        var f = foo;
+        var g = bar;
+        var h = baz;
+        
+        var result = 0;
+        for (var i = 0; i &lt; n; ++i) {
+            if (i == n - 1)
+                f = h;
+            result += f(o.f);
+            
+            var tmp = f;
+            f = g;
+            g = tmp;
+        }
+        
+        return result;
+    })({f:42});
+    
+    if (result != ((n / 2 - 1) * 42) + (n / 2 * 1) + (42 + 1))
+        throw &quot;Error: bad result: &quot; + result;
+})();
</ins></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/WTF/ChangeLog        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2014-08-23  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        FTL should be able to do polymorphic call inlining
+        https://bugs.webkit.org/show_bug.cgi?id=135145
+
+        Reviewed by Geoffrey Garen.
+        
+        Add some power that I need for call edge profiling.
+
+        * wtf/OwnPtr.h:
+        (WTF::OwnPtr&lt;T&gt;::createTransactionally):
+        * wtf/Spectrum.h:
+        (WTF::Spectrum::add):
+        (WTF::Spectrum::addAll):
+        (WTF::Spectrum::get):
+        (WTF::Spectrum::size):
+        (WTF::Spectrum::KeyAndCount::KeyAndCount):
+        (WTF::Spectrum::clear):
+        (WTF::Spectrum::removeIf):
+
</ins><span class="cx"> 2014-08-25  Tomas Popela  &lt;tpopela@redhat.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add support for little-endian PowerPC64
</span></span></pre></div>
<a id="trunkSourceWTFwtfOwnPtrh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/OwnPtr.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/OwnPtr.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/WTF/wtf/OwnPtr.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- *  Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2006, 2007, 2008, 2009, 2010, 2014 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Library General Public
</span><span class="lines">@@ -22,6 +22,7 @@
</span><span class="cx"> #define WTF_OwnPtr_h
</span><span class="cx"> 
</span><span class="cx"> #include &lt;wtf/Assertions.h&gt;
</span><ins>+#include &lt;wtf/Atomics.h&gt;
</ins><span class="cx"> #include &lt;wtf/Noncopyable.h&gt;
</span><span class="cx"> #include &lt;wtf/OwnPtrCommon.h&gt;
</span><span class="cx"> #include &lt;algorithm&gt;
</span><span class="lines">@@ -72,6 +73,17 @@
</span><span class="cx">         template&lt;typename U&gt; OwnPtr&amp; operator=(OwnPtr&lt;U&gt;&amp;&amp;);
</span><span class="cx"> 
</span><span class="cx">         void swap(OwnPtr&amp; o) { std::swap(m_ptr, o.m_ptr); }
</span><ins>+        
+        // Construct an object to store into this OwnPtr, but only so long as this OwnPtr
+        // doesn't already point to an object. This will ensure that after you call this,
+        // the OwnPtr will point to an instance of T, even if called concurrently. This
+        // instance may or may not have been created by this call. Moreover, this call uses
+        // an opportunistic transaction, in that we may create an instance of T and then
+        // immediately throw it away, if in the process of creating that instance some
+        // other thread was doing the same thing and stored its instance into this pointer
+        // before we had a chance to do so.
+        template&lt;typename... Args&gt;
+        void createTransactionally(Args...);
</ins><span class="cx"> 
</span><span class="cx">     private:
</span><span class="cx">         explicit OwnPtr(PtrType ptr) : m_ptr(ptr) { }
</span><span class="lines">@@ -186,6 +198,28 @@
</span><span class="cx">         return p.get();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    template&lt;typename T&gt; template&lt;typename... Args&gt; inline void OwnPtr&lt;T&gt;::createTransactionally(Args... args)
+    {
+        if (m_ptr) {
+            WTF::loadLoadFence();
+            return;
+        }
+        
+        T* newObject = new T(args...);
+        WTF::storeStoreFence();
+#if ENABLE(COMPARE_AND_SWAP)
+        do {
+            if (m_ptr) {
+                delete newObject;
+                WTF::loadLoadFence();
+                return;
+            }
+        } while (!WTF::weakCompareAndSwap(bitwise_cast&lt;void*volatile*&gt;(&amp;m_ptr), nullptr, newObject));
+#else
+        m_ptr = newObject;
+#endif
+    }
+
</ins><span class="cx"> } // namespace WTF
</span><span class="cx"> 
</span><span class="cx"> using WTF::OwnPtr;
</span></span></pre></div>
<a id="trunkSourceWTFwtfSpectrumh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Spectrum.h (172939 => 172940)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Spectrum.h        2014-08-25 22:31:04 UTC (rev 172939)
+++ trunk/Source/WTF/wtf/Spectrum.h        2014-08-25 22:35:40 UTC (rev 172940)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011, 2014 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">@@ -32,29 +32,40 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="cx"> 
</span><del>-template&lt;typename T&gt;
</del><ins>+template&lt;typename T, typename CounterType = unsigned&gt;
</ins><span class="cx"> class Spectrum {
</span><span class="cx"> public:
</span><del>-    typedef typename HashMap&lt;T, unsigned long&gt;::iterator iterator;
-    typedef typename HashMap&lt;T, unsigned long&gt;::const_iterator const_iterator;
</del><ins>+    typedef typename HashMap&lt;T, CounterType&gt;::iterator iterator;
+    typedef typename HashMap&lt;T, CounterType&gt;::const_iterator const_iterator;
</ins><span class="cx">     
</span><span class="cx">     Spectrum() { }
</span><span class="cx">     
</span><del>-    void add(const T&amp; key, unsigned long count = 1)
</del><ins>+    void add(const T&amp; key, CounterType count = 1)
</ins><span class="cx">     {
</span><del>-        typename HashMap&lt;T, unsigned long&gt;::AddResult result = m_map.add(key, count);
</del><ins>+        if (!count)
+            return;
+        typename HashMap&lt;T, CounterType&gt;::AddResult result = m_map.add(key, count);
</ins><span class="cx">         if (!result.isNewEntry)
</span><span class="cx">             result.iterator-&gt;value += count;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    unsigned long get(const T&amp; key) const
</del><ins>+    template&lt;typename U&gt;
+    void addAll(const Spectrum&lt;T, U&gt;&amp; otherSpectrum)
</ins><span class="cx">     {
</span><ins>+        for (auto&amp; entry : otherSpectrum)
+            add(entry.key, entry.count);
+    }
+    
+    CounterType get(const T&amp; key) const
+    {
</ins><span class="cx">         const_iterator iter = m_map.find(key);
</span><span class="cx">         if (iter == m_map.end())
</span><span class="cx">             return 0;
</span><span class="cx">         return iter-&gt;value;
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    size_t size() const { return m_map.size(); }
+    
</ins><span class="cx">     iterator begin() { return m_map.begin(); }
</span><span class="cx">     iterator end() { return m_map.end(); }
</span><span class="cx">     const_iterator begin() const { return m_map.begin(); }
</span><span class="lines">@@ -63,7 +74,7 @@
</span><span class="cx">     struct KeyAndCount {
</span><span class="cx">         KeyAndCount() { }
</span><span class="cx">         
</span><del>-        KeyAndCount(const T&amp; key, unsigned long count)
</del><ins>+        KeyAndCount(const T&amp; key, CounterType count)
</ins><span class="cx">             : key(key)
</span><span class="cx">             , count(count)
</span><span class="cx">         {
</span><span class="lines">@@ -80,7 +91,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         T key;
</span><del>-        unsigned long count;
</del><ins>+        CounterType count;
</ins><span class="cx">     };
</span><span class="cx">     
</span><span class="cx">     // Returns a list ordered from lowest-count to highest-count.
</span><span class="lines">@@ -94,8 +105,18 @@
</span><span class="cx">         return list;
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void clear() { m_map.clear(); }
+    
+    template&lt;typename Functor&gt;
+    void removeIf(const Functor&amp; functor)
+    {
+        m_map.removeIf([functor] (typename HashMap&lt;T, CounterType&gt;::KeyValuePairType&amp; pair) {
+                return functor(KeyAndCount(pair.key, pair.value));
+            });
+    }
+    
</ins><span class="cx"> private:
</span><del>-    HashMap&lt;T, unsigned long&gt; m_map;
</del><ins>+    HashMap&lt;T, CounterType&gt; m_map;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WTF
</span></span></pre>
</div>
</div>

</body>
</html>