<!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>[164207] 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/164207">164207</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-02-16 22:35:32 -0800 (Sun, 16 Feb 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>FTL should inline polymorphic heap accesses
https://bugs.webkit.org/show_bug.cgi?id=128795

Source/JavaScriptCore: 

Reviewed by Oliver Hunt.
        
We now inline GetByIds that we know are pure but polymorphic. They manifest in DFG IR
as MultiGetByOffset, and in LLVM IR as a switch with a basic block for each kind of
read.
        
2% speed-up on Octane mostly due to a 18% speed-up on deltablue.

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
* bytecode/ExitingJITType.cpp: Added.
(WTF::printInternal):
* bytecode/ExitingJITType.h:
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeFromLLInt):
(JSC::GetByIdStatus::computeForChain):
(JSC::GetByIdStatus::computeForStubInfo):
(JSC::GetByIdStatus::computeFor):
(JSC::GetByIdStatus::dump):
* bytecode/GetByIdStatus.h:
(JSC::GetByIdStatus::GetByIdStatus):
(JSC::GetByIdStatus::numVariants):
(JSC::GetByIdStatus::variants):
(JSC::GetByIdStatus::at):
(JSC::GetByIdStatus::operator[]):
* bytecode/GetByIdVariant.cpp: Added.
(JSC::GetByIdVariant::dump):
(JSC::GetByIdVariant::dumpInContext):
* bytecode/GetByIdVariant.h: Added.
(JSC::GetByIdVariant::GetByIdVariant):
(JSC::GetByIdVariant::isSet):
(JSC::GetByIdVariant::operator!):
(JSC::GetByIdVariant::structureSet):
(JSC::GetByIdVariant::chain):
(JSC::GetByIdVariant::specificValue):
(JSC::GetByIdVariant::offset):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::emitPrototypeChecks):
(JSC::DFG::ByteCodeParser::handleGetById):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::getByOffsetLoadElimination):
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGCommon.h:
(JSC::DFG::verboseCompilationEnabled):
(JSC::DFG::logCompilationChanges):
(JSC::DFG::shouldShowDisassembly):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
(JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
* dfg/DFGDriver.cpp:
(JSC::DFG::compileImpl):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::convertToConstant):
* dfg/DFGNode.h:
(JSC::DFG::Node::convertToGetByOffset):
(JSC::DFG::Node::hasHeapPrediction):
(JSC::DFG::Node::hasMultiGetByOffsetData):
(JSC::DFG::Node::multiGetByOffsetData):
* dfg/DFGNodeType.h:
* dfg/DFGPhase.h:
(JSC::DFG::Phase::graph):
(JSC::DFG::runAndLog):
* dfg/DFGPlan.cpp:
(JSC::DFG::dumpAndVerifyGraph):
(JSC::DFG::Plan::compileInThread):
(JSC::DFG::Plan::compileInThreadImpl):
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGTypeCheckHoistingPhase.cpp:
(JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks):
(JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLCompile.cpp:
(JSC::FTL::fixFunctionBasedOnStackMaps):
(JSC::FTL::compile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset):
* ftl/FTLState.h:
(JSC::FTL::verboseCompilationEnabled):
(JSC::FTL::showDisassembly):
* jsc.cpp:
(GlobalObject::finishCreation):
(functionEffectful42):
* runtime/IntendedStructureChain.cpp:
(JSC::IntendedStructureChain::dump):
(JSC::IntendedStructureChain::dumpInContext):
* runtime/IntendedStructureChain.h:
* runtime/Options.cpp:
(JSC::recomputeDependentOptions):
* runtime/Options.h:
* tests/stress/fold-multi-get-by-offset-to-get-by-offset-with-watchpoint.js: Added.
(foo):
(bar):
* tests/stress/fold-multi-get-by-offset-to-get-by-offset.js: Added.
(foo):
(bar):
* tests/stress/multi-get-by-offset-proto-and-self.js: Added.
(foo):
(Foo):

Source/WTF: 

Reviewed by Oliver Hunt.

* wtf/PrintStream.h:
(WTF::PointerDumpInContext::PointerDumpInContext):
(WTF::PointerDumpInContext::dump):
(WTF::pointerDumpInContext):

LayoutTests: 

Reviewed by Oliver Hunt.

* js/regress/polymorphic-get-by-id-expected.txt: Added.
* js/regress/polymorphic-get-by-id.html: Added.
* js/regress/script-tests/polymorphic-get-by-id.js: Added.
(foo):</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="#trunkSourceJavaScriptCoreGNUmakefilelistam">trunk/Source/JavaScriptCore/GNUmakefile.list.am</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="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeExitingJITTypeh">trunk/Source/JavaScriptCore/bytecode/ExitingJITType.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeGetByIdStatuscpp">trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeGetByIdStatush">trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCSEPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.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="#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="#trunkSourceJavaScriptCoredfgDFGGraphh">trunk/Source/JavaScriptCore/dfg/DFGGraph.h</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="#trunkSourceJavaScriptCoredfgDFGPhaseh">trunk/Source/JavaScriptCore/dfg/DFGPhase.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPlancpp">trunk/Source/JavaScriptCore/dfg/DFGPlan.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="#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="#trunkSourceJavaScriptCoredfgDFGTypeCheckHoistingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCompilecpp">trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLStateh">trunk/Source/JavaScriptCore/ftl/FTLState.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeIntendedStructureChaincpp">trunk/Source/JavaScriptCore/runtime/IntendedStructureChain.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeIntendedStructureChainh">trunk/Source/JavaScriptCore/runtime/IntendedStructureChain.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionscpp">trunk/Source/JavaScriptCore/runtime/Options.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfPrintStreamh">trunk/Source/WTF/wtf/PrintStream.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsregresspolymorphicgetbyidexpectedtxt">trunk/LayoutTests/js/regress/polymorphic-get-by-id-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregresspolymorphicgetbyidhtml">trunk/LayoutTests/js/regress/polymorphic-get-by-id.html</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestspolymorphicgetbyidjs">trunk/LayoutTests/js/regress/script-tests/polymorphic-get-by-id.js</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeExitingJITTypecpp">trunk/Source/JavaScriptCore/bytecode/ExitingJITType.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeGetByIdVariantcpp">trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeGetByIdVarianth">trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressfoldmultigetbyoffsettogetbyoffsetwithwatchpointjs">trunk/Source/JavaScriptCore/tests/stress/fold-multi-get-by-offset-to-get-by-offset-with-watchpoint.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressfoldmultigetbyoffsettogetbyoffsetjs">trunk/Source/JavaScriptCore/tests/stress/fold-multi-get-by-offset-to-get-by-offset.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressmultigetbyoffsetprotoandselfjs">trunk/Source/JavaScriptCore/tests/stress/multi-get-by-offset-proto-and-self.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/LayoutTests/ChangeLog        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2014-02-15  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        FTL should inline polymorphic heap accesses
+        https://bugs.webkit.org/show_bug.cgi?id=128795
+
+        Reviewed by Oliver Hunt.
+
+        * js/regress/polymorphic-get-by-id-expected.txt: Added.
+        * js/regress/polymorphic-get-by-id.html: Added.
+        * js/regress/script-tests/polymorphic-get-by-id.js: Added.
+        (foo):
+
</ins><span class="cx"> 2014-02-16  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, add a useful comment for this test.
</span></span></pre></div>
<a id="trunkLayoutTestsjsregresspolymorphicgetbyidexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/polymorphic-get-by-id-expected.txt (0 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/polymorphic-get-by-id-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/polymorphic-get-by-id-expected.txt        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/polymorphic-get-by-id
+
+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="trunkLayoutTestsjsregresspolymorphicgetbyidhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/polymorphic-get-by-id.html (0 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/polymorphic-get-by-id.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/polymorphic-get-by-id.html        2014-02-17 06:35:32 UTC (rev 164207)
</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/polymorphic-get-by-id.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="trunkLayoutTestsjsregressscripttestspolymorphicgetbyidjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/polymorphic-get-by-id.js (0 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/polymorphic-get-by-id.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/polymorphic-get-by-id.js        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -0,0 +1,21 @@
</span><ins>+function foo(o) {
+    var result = 0;
+    for (var i = 0; i &lt; 100; ++i)
+        result += o.f;
+    return result;
+}
+
+noInline(foo);
+
+var o = {f:1, g:2};
+var p = {g:1, f:2};
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo((i &amp; 1) ? o : p);
+    if (result != ((i &amp; 1) ? 100 : 200))
+        throw &quot;Error: bad result for i = &quot; + i + &quot;: &quot; + result;
+}
+
+var q = {g:3, h:4, f:5};
+var result = foo(q);
+if (result != 500)
+    throw &quot;Error: bad result at end: &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -70,7 +70,9 @@
</span><span class="cx">     bytecode/DeferredCompilationCallback.cpp
</span><span class="cx">     bytecode/ExecutionCounter.cpp
</span><span class="cx">     bytecode/ExitKind.cpp
</span><ins>+    bytecode/ExitingJITType.cpp
</ins><span class="cx">     bytecode/GetByIdStatus.cpp
</span><ins>+    bytecode/GetByIdVariant.cpp
</ins><span class="cx">     bytecode/InlineCallFrameSet.cpp
</span><span class="cx">     bytecode/JumpTable.cpp
</span><span class="cx">     bytecode/LazyOperandValueProfile.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -1,3 +1,129 @@
</span><ins>+2014-02-15  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        FTL should inline polymorphic heap accesses
+        https://bugs.webkit.org/show_bug.cgi?id=128795
+
+        Reviewed by Oliver Hunt.
+        
+        We now inline GetByIds that we know are pure but polymorphic. They manifest in DFG IR
+        as MultiGetByOffset, and in LLVM IR as a switch with a basic block for each kind of
+        read.
+        
+        2% speed-up on Octane mostly due to a 18% speed-up on deltablue.
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpBytecode):
+        * bytecode/ExitingJITType.cpp: Added.
+        (WTF::printInternal):
+        * bytecode/ExitingJITType.h:
+        * bytecode/GetByIdStatus.cpp:
+        (JSC::GetByIdStatus::computeFromLLInt):
+        (JSC::GetByIdStatus::computeForChain):
+        (JSC::GetByIdStatus::computeForStubInfo):
+        (JSC::GetByIdStatus::computeFor):
+        (JSC::GetByIdStatus::dump):
+        * bytecode/GetByIdStatus.h:
+        (JSC::GetByIdStatus::GetByIdStatus):
+        (JSC::GetByIdStatus::numVariants):
+        (JSC::GetByIdStatus::variants):
+        (JSC::GetByIdStatus::at):
+        (JSC::GetByIdStatus::operator[]):
+        * bytecode/GetByIdVariant.cpp: Added.
+        (JSC::GetByIdVariant::dump):
+        (JSC::GetByIdVariant::dumpInContext):
+        * bytecode/GetByIdVariant.h: Added.
+        (JSC::GetByIdVariant::GetByIdVariant):
+        (JSC::GetByIdVariant::isSet):
+        (JSC::GetByIdVariant::operator!):
+        (JSC::GetByIdVariant::structureSet):
+        (JSC::GetByIdVariant::chain):
+        (JSC::GetByIdVariant::specificValue):
+        (JSC::GetByIdVariant::offset):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::emitPrototypeChecks):
+        (JSC::DFG::ByteCodeParser::handleGetById):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCSEPhase.cpp:
+        (JSC::DFG::CSEPhase::getByOffsetLoadElimination):
+        (JSC::DFG::CSEPhase::performNodeCSE):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGCommon.h:
+        (JSC::DFG::verboseCompilationEnabled):
+        (JSC::DFG::logCompilationChanges):
+        (JSC::DFG::shouldShowDisassembly):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        (JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
+        * dfg/DFGDriver.cpp:
+        (JSC::DFG::compileImpl):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::dump):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::convertToConstant):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::convertToGetByOffset):
+        (JSC::DFG::Node::hasHeapPrediction):
+        (JSC::DFG::Node::hasMultiGetByOffsetData):
+        (JSC::DFG::Node::multiGetByOffsetData):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGPhase.h:
+        (JSC::DFG::Phase::graph):
+        (JSC::DFG::runAndLog):
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::dumpAndVerifyGraph):
+        (JSC::DFG::Plan::compileInThread):
+        (JSC::DFG::Plan::compileInThreadImpl):
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGTypeCheckHoistingPhase.cpp:
+        (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks):
+        (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLCompile.cpp:
+        (JSC::FTL::fixFunctionBasedOnStackMaps):
+        (JSC::FTL::compile):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileNode):
+        (JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset):
+        * ftl/FTLState.h:
+        (JSC::FTL::verboseCompilationEnabled):
+        (JSC::FTL::showDisassembly):
+        * jsc.cpp:
+        (GlobalObject::finishCreation):
+        (functionEffectful42):
+        * runtime/IntendedStructureChain.cpp:
+        (JSC::IntendedStructureChain::dump):
+        (JSC::IntendedStructureChain::dumpInContext):
+        * runtime/IntendedStructureChain.h:
+        * runtime/Options.cpp:
+        (JSC::recomputeDependentOptions):
+        * runtime/Options.h:
+        * tests/stress/fold-multi-get-by-offset-to-get-by-offset-with-watchpoint.js: Added.
+        (foo):
+        (bar):
+        * tests/stress/fold-multi-get-by-offset-to-get-by-offset.js: Added.
+        (foo):
+        (bar):
+        * tests/stress/multi-get-by-offset-proto-and-self.js: Added.
+        (foo):
+        (Foo):
+
</ins><span class="cx"> 2014-02-16  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         DFG::prepareOSREntry should be nice to the stack
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreGNUmakefilelistam"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/GNUmakefile.list.am (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/GNUmakefile.list.am        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/GNUmakefile.list.am        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -147,10 +147,14 @@
</span><span class="cx">         Source/JavaScriptCore/bytecode/ExecutionCounter.h \
</span><span class="cx">         Source/JavaScriptCore/bytecode/ExitKind.cpp \
</span><span class="cx">         Source/JavaScriptCore/bytecode/ExitKind.h \
</span><ins>+        Source/JavaScriptCore/bytecode/ExitingJITType.cpp \
+        Source/JavaScriptCore/bytecode/ExitingJITType.h \
</ins><span class="cx">         Source/JavaScriptCore/bytecode/ExpressionRangeInfo.h \
</span><span class="cx">         Source/JavaScriptCore/bytecode/FullBytecodeLiveness.h \
</span><span class="cx">         Source/JavaScriptCore/bytecode/GetByIdStatus.cpp \
</span><span class="cx">         Source/JavaScriptCore/bytecode/GetByIdStatus.h \
</span><ins>+        Source/JavaScriptCore/bytecode/GetByIdVariant.cpp \
+        Source/JavaScriptCore/bytecode/GetByIdVariant.h \
</ins><span class="cx">         Source/JavaScriptCore/bytecode/HandlerInfo.h \
</span><span class="cx">         Source/JavaScriptCore/bytecode/InlineCallFrameSet.cpp \
</span><span class="cx">         Source/JavaScriptCore/bytecode/InlineCallFrameSet.h \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -325,7 +325,9 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\DFGExitProfile.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\ExecutionCounter.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\ExitKind.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\bytecode\ExitingJITType.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\GetByIdStatus.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\bytecode\GetByIdVariant.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\InlineCallFrameSet.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\JumpTable.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\LazyOperandValueProfile.cpp&quot; /&gt;
</span><span class="lines">@@ -840,6 +842,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\ExitKind.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\ExpressionRangeInfo.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\GetByIdStatus.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\bytecode\GetByIdVariant.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\HandlerInfo.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\InlineCallFrameSet.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\Instruction.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -59,6 +59,9 @@
</span><span class="cx"> /* End PBXAggregateTarget section */
</span><span class="cx"> 
</span><span class="cx"> /* Begin PBXBuildFile section */
</span><ins>+                0F0332C018ADFAE1005F979A /* ExitingJITType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0332BF18ADFAE1005F979A /* ExitingJITType.cpp */; };
+                0F0332C318B01763005F979A /* GetByIdVariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0332C118B01763005F979A /* GetByIdVariant.cpp */; };
+                0F0332C418B01763005F979A /* GetByIdVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0332C218B01763005F979A /* GetByIdVariant.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F05C3B41683CF9200BAF45B /* DFGArrayifySlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0776BD14FF002800102332 /* JITCompilationEffort.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */; };
</span><span class="lines">@@ -210,9 +213,9 @@
</span><span class="cx">                 0F2FCCFD18A60070001A27F8 /* DFGScannable.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2FCCF618A60070001A27F8 /* DFGScannable.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F2FCCFE18A60070001A27F8 /* DFGThreadData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2FCCF718A60070001A27F8 /* DFGThreadData.cpp */; };
</span><span class="cx">                 0F2FCCFF18A60070001A27F8 /* DFGThreadData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2FCCF818A60070001A27F8 /* DFGThreadData.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F300B7818AB051100A6D72E /* DFGNodeOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F300B7B18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F300B7918AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp */; };
</span><span class="cx">                 0F300B7C18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F300B7A18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><del>-                0F300B7818AB051100A6D72E /* DFGNodeOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; };
</del><span class="cx">                 0F34B14916D42010001CDA5A /* DFGUseKind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */; };
</span><span class="cx">                 0F34B14A16D42013001CDA5A /* DFGUseKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F34B14816D4200E001CDA5A /* DFGUseKind.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F34B14C16D43E0D001CDA5A /* PolymorphicAccessStructureList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F34B14B16D43E0C001CDA5A /* PolymorphicAccessStructureList.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -1524,6 +1527,9 @@
</span><span class="cx"> /* End PBXCopyFilesBuildPhase section */
</span><span class="cx"> 
</span><span class="cx"> /* Begin PBXFileReference section */
</span><ins>+                0F0332BF18ADFAE1005F979A /* ExitingJITType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExitingJITType.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F0332C118B01763005F979A /* GetByIdVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetByIdVariant.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F0332C218B01763005F979A /* GetByIdVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetByIdVariant.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -1674,9 +1680,9 @@
</span><span class="cx">                 0F2FCCF618A60070001A27F8 /* DFGScannable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGScannable.h; path = dfg/DFGScannable.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F2FCCF718A60070001A27F8 /* DFGThreadData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGThreadData.cpp; path = dfg/DFGThreadData.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F2FCCF818A60070001A27F8 /* DFGThreadData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGThreadData.h; path = dfg/DFGThreadData.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeOrigin.h; path = dfg/DFGNodeOrigin.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F300B7918AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGIntegerCheckCombiningPhase.cpp; path = dfg/DFGIntegerCheckCombiningPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F300B7A18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGIntegerCheckCombiningPhase.h; path = dfg/DFGIntegerCheckCombiningPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeOrigin.h; path = dfg/DFGNodeOrigin.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGUseKind.cpp; path = dfg/DFGUseKind.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F34B14816D4200E001CDA5A /* DFGUseKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGUseKind.h; path = dfg/DFGUseKind.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F34B14B16D43E0C001CDA5A /* PolymorphicAccessStructureList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolymorphicAccessStructureList.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4519,6 +4525,7 @@
</span><span class="cx">                                 969A07920ED1D3AE00F1F681 /* EvalCodeCache.h */,
</span><span class="cx">                                 0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */,
</span><span class="cx">                                 0F56A1D115000F31002992B1 /* ExecutionCounter.h */,
</span><ins>+                                0F0332BF18ADFAE1005F979A /* ExitingJITType.cpp */,
</ins><span class="cx">                                 0F3AC753188E5EC80032029F /* ExitingJITType.h */,
</span><span class="cx">                                 0FB105821675480C00F8AB6E /* ExitKind.cpp */,
</span><span class="cx">                                 0FB105831675480C00F8AB6E /* ExitKind.h */,
</span><span class="lines">@@ -4526,6 +4533,8 @@
</span><span class="cx">                                 0F666EBF183566F900D017F1 /* FullBytecodeLiveness.h */,
</span><span class="cx">                                 0F93329514CA7DC10085F3C6 /* GetByIdStatus.cpp */,
</span><span class="cx">                                 0F93329614CA7DC10085F3C6 /* GetByIdStatus.h */,
</span><ins>+                                0F0332C118B01763005F979A /* GetByIdVariant.cpp */,
+                                0F0332C218B01763005F979A /* GetByIdVariant.h */,
</ins><span class="cx">                                 0F0B83A814BCF55E00885B4F /* HandlerInfo.h */,
</span><span class="cx">                                 0F24E55317F0B71C00ABB217 /* InlineCallFrameSet.cpp */,
</span><span class="cx">                                 0F24E55417F0B71C00ABB217 /* InlineCallFrameSet.h */,
</span><span class="lines">@@ -4822,6 +4831,7 @@
</span><span class="cx">                                 0F63945515D07057006A597C /* ArrayProfile.h in Headers */,
</span><span class="cx">                                 BC18C3E70E16F5CD00B34460 /* ArrayPrototype.h in Headers */,
</span><span class="cx">                                 BC18C5240E16FC8A00B34460 /* ArrayPrototype.lut.h in Headers */,
</span><ins>+                                0F0332C418B01763005F979A /* GetByIdVariant.h in Headers */,
</ins><span class="cx">                                 0FB7F39615ED8E4600F167B2 /* ArrayStorage.h in Headers */,
</span><span class="cx">                                 9688CB150ED12B4E001D649F /* AssemblerBuffer.h in Headers */,
</span><span class="cx">                                 86D3B2C510156BDE002865E7 /* AssemblerBufferWithConstantPool.h in Headers */,
</span><span class="lines">@@ -6093,6 +6103,7 @@
</span><span class="cx">                                 86EC9DC71328DF82002B2AD7 /* DFGGraph.cpp in Sources */,
</span><span class="cx">                                 A704D90517A0BAA8006BA554 /* DFGInPlaceAbstractState.cpp in Sources */,
</span><span class="cx">                                 0FC97F3D18202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp in Sources */,
</span><ins>+                                0F0332C018ADFAE1005F979A /* ExitingJITType.cpp in Sources */,
</ins><span class="cx">                                 0FEA0A33170D40BF00BB722C /* DFGJITCode.cpp in Sources */,
</span><span class="cx">                                 86EC9DCB1328DF82002B2AD7 /* DFGJITCompiler.cpp in Sources */,
</span><span class="cx">                                 A78A9778179738B8009DF744 /* DFGJITFinalizer.cpp in Sources */,
</span><span class="lines">@@ -6376,6 +6387,7 @@
</span><span class="cx">                                 A513E5CA185F9624007E95AD /* InjectedScriptManager.cpp in Sources */,
</span><span class="cx">                                 148F21B7107EC5470042EC2C /* Nodes.cpp in Sources */,
</span><span class="cx">                                 655EB29B10CE2581001A990E /* NodesCodegen.cpp in Sources */,
</span><ins>+                                0F0332C318B01763005F979A /* GetByIdVariant.cpp in Sources */,
</ins><span class="cx">                                 14469DE2107EC7E700650446 /* NumberConstructor.cpp in Sources */,
</span><span class="cx">                                 14469DE3107EC7E700650446 /* NumberObject.cpp in Sources */,
</span><span class="cx">                                 14469DE4107EC7E700650446 /* NumberPrototype.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -1377,7 +1377,7 @@
</span><span class="cx">         out.print(&quot; !! frequent exits: &quot;);
</span><span class="cx">         CommaPrinter comma;
</span><span class="cx">         for (unsigned i = 0; i &lt; exitSites.size(); ++i)
</span><del>-            out.print(comma, exitSites[i].kind());
</del><ins>+            out.print(comma, exitSites[i].kind(), &quot; &quot;, exitSites[i].jitType());
</ins><span class="cx">     }
</span><span class="cx"> #else // ENABLE(DFG_JIT)
</span><span class="cx">     UNUSED_PARAM(location);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeExitingJITTypecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/ExitingJITType.cpp (0 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ExitingJITType.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/ExitingJITType.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -0,0 +1,52 @@
</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;ExitingJITType.h&quot;
+
+#include &lt;wtf/PrintStream.h&gt;
+
+namespace WTF {
+
+using namespace JSC;
+
+void printInternal(PrintStream&amp; out, ExitingJITType type)
+{
+    switch (type) {
+    case ExitFromAnything:
+        out.print(&quot;FromAnything&quot;);
+        return;
+    case ExitFromDFG:
+        out.print(&quot;FromDFG&quot;);
+        return;
+    case ExitFromFTL:
+        out.print(&quot;FromFTL&quot;);
+        return;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+} // namespace WTF
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeExitingJITTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ExitingJITType.h (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ExitingJITType.h        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/bytecode/ExitingJITType.h        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -51,5 +51,12 @@
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><ins>+namespace WTF {
+
+class PrintStream;
+void printInternal(PrintStream&amp;, JSC::ExitingJITType);
+
+} // namespace WTF
+
</ins><span class="cx"> #endif // ExitingJITType_h
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeGetByIdStatuscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include &quot;LLIntData.h&quot;
</span><span class="cx"> #include &quot;LowLevelInterpreter.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</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="lines">@@ -71,15 +72,17 @@
</span><span class="cx">     if (!isValidOffset(offset))
</span><span class="cx">         return GetByIdStatus(NoInformation, false);
</span><span class="cx">     
</span><del>-    return GetByIdStatus(Simple, false, StructureSet(structure), offset, specificValue);
</del><ins>+    return GetByIdStatus(Simple, false, GetByIdVariant(StructureSet(structure), offset, specificValue));
</ins><span class="cx"> #else
</span><span class="cx">     return GetByIdStatus(NoInformation, false);
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void GetByIdStatus::computeForChain(GetByIdStatus&amp; result, CodeBlock* profiledBlock, StringImpl* uid)
</del><ins>+bool GetByIdStatus::computeForChain(CodeBlock* profiledBlock, StringImpl* uid, PassRefPtr&lt;IntendedStructureChain&gt; passedChain)
</ins><span class="cx"> {
</span><span class="cx"> #if ENABLE(JIT)
</span><ins>+    RefPtr&lt;IntendedStructureChain&gt; chain = passedChain;
+    
</ins><span class="cx">     // Validate the chain. If the chain is invalid, then currently the best thing
</span><span class="cx">     // we can do is to assume that TakesSlow is true. In the future, it might be
</span><span class="cx">     // worth exploring reifying the structure chain from the structure we've got
</span><span class="lines">@@ -90,40 +93,42 @@
</span><span class="cx">     // have now is that if the structure chain has changed between when it was
</span><span class="cx">     // cached on in the baseline JIT and when the DFG tried to inline the access,
</span><span class="cx">     // then we fall back on a polymorphic access.
</span><del>-    if (!result.m_chain-&gt;isStillValid())
-        return;
</del><ins>+    if (!chain-&gt;isStillValid())
+        return false;
</ins><span class="cx"> 
</span><del>-    if (result.m_chain-&gt;head()-&gt;takesSlowPathInDFGForImpureProperty())
-        return;
-    size_t chainSize = result.m_chain-&gt;size();
</del><ins>+    if (chain-&gt;head()-&gt;takesSlowPathInDFGForImpureProperty())
+        return false;
+    size_t chainSize = chain-&gt;size();
</ins><span class="cx">     for (size_t i = 0; i &lt; chainSize; i++) {
</span><del>-        if (result.m_chain-&gt;at(i)-&gt;takesSlowPathInDFGForImpureProperty())
-            return;
</del><ins>+        if (chain-&gt;at(i)-&gt;takesSlowPathInDFGForImpureProperty())
+            return false;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    JSObject* currentObject = result.m_chain-&gt;terminalPrototype();
-    Structure* currentStructure = result.m_chain-&gt;last();
</del><ins>+    JSObject* currentObject = chain-&gt;terminalPrototype();
+    Structure* currentStructure = chain-&gt;last();
</ins><span class="cx">     
</span><span class="cx">     ASSERT_UNUSED(currentObject, currentObject);
</span><del>-        
</del><ins>+    
</ins><span class="cx">     unsigned attributesIgnored;
</span><span class="cx">     JSCell* specificValue;
</span><del>-        
-    result.m_offset = currentStructure-&gt;getConcurrently(
</del><ins>+    
+    PropertyOffset offset = currentStructure-&gt;getConcurrently(
</ins><span class="cx">         *profiledBlock-&gt;vm(), uid, attributesIgnored, specificValue);
</span><span class="cx">     if (currentStructure-&gt;isDictionary())
</span><span class="cx">         specificValue = 0;
</span><del>-    if (!isValidOffset(result.m_offset))
-        return;
-        
-    result.m_structureSet.add(result.m_chain-&gt;head());
-    result.m_specificValue = JSValue(specificValue);
-#else
-    UNUSED_PARAM(result);
</del><ins>+    if (!isValidOffset(offset))
+        return false;
+    
+    m_variants.append(
+        GetByIdVariant(StructureSet(chain-&gt;head()), offset, specificValue, chain));
+    return true;
+#else // ENABLE(JIT)
</ins><span class="cx">     UNUSED_PARAM(profiledBlock);
</span><span class="cx">     UNUSED_PARAM(uid);
</span><ins>+    UNUSED_PARAM(passedChain);
</ins><span class="cx">     UNREACHABLE_FOR_PLATFORM();
</span><del>-#endif
</del><ins>+    return false;
+#endif // ENABLE(JIT)
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, StubInfoMap&amp; map, unsigned bytecodeIndex, StringImpl* uid)
</span><span class="lines">@@ -174,6 +179,7 @@
</span><span class="cx">     
</span><span class="cx">     // Finally figure out if we can derive an access strategy.
</span><span class="cx">     GetByIdStatus result;
</span><ins>+    result.m_state = Simple;
</ins><span class="cx">     result.m_wasSeenInJIT = true; // This is interesting for bytecode dumping only.
</span><span class="cx">     switch (stubInfo-&gt;accessType) {
</span><span class="cx">     case access_unset:
</span><span class="lines">@@ -185,31 +191,37 @@
</span><span class="cx">             return GetByIdStatus(TakesSlowPath, true);
</span><span class="cx">         unsigned attributesIgnored;
</span><span class="cx">         JSCell* specificValue;
</span><del>-        result.m_offset = structure-&gt;getConcurrently(
</del><ins>+        GetByIdVariant variant;
+        variant.m_offset = structure-&gt;getConcurrently(
</ins><span class="cx">             *profiledBlock-&gt;vm(), uid, attributesIgnored, specificValue);
</span><ins>+        if (!isValidOffset(variant.m_offset))
+            return GetByIdStatus(TakesSlowPath, true);
+        
</ins><span class="cx">         if (structure-&gt;isDictionary())
</span><span class="cx">             specificValue = 0;
</span><span class="cx">         
</span><del>-        if (isValidOffset(result.m_offset)) {
-            result.m_structureSet.add(structure);
-            result.m_specificValue = JSValue(specificValue);
-        }
-        
-        if (isValidOffset(result.m_offset))
-            ASSERT(result.m_structureSet.size());
-        break;
</del><ins>+        variant.m_structureSet.add(structure);
+        variant.m_specificValue = JSValue(specificValue);
+        result.m_variants.append(variant);
+        return result;
</ins><span class="cx">     }
</span><span class="cx">         
</span><span class="cx">     case access_get_by_id_self_list: {
</span><del>-        for (int i = 0; i &lt; listSize; ++i) {
-            ASSERT(list-&gt;list[i].isDirect);
</del><ins>+        for (int listIndex = 0; listIndex &lt; listSize; ++listIndex) {
+            ASSERT(list-&gt;list[listIndex].isDirect);
</ins><span class="cx">             
</span><del>-            Structure* structure = list-&gt;list[i].base.get();
</del><ins>+            Structure* structure = list-&gt;list[listIndex].base.get();
</ins><span class="cx">             if (structure-&gt;takesSlowPathInDFGForImpureProperty())
</span><span class="cx">                 return GetByIdStatus(TakesSlowPath, true);
</span><del>-
-            if (result.m_structureSet.contains(structure))
</del><ins>+            
+            if (list-&gt;list[listIndex].chain.get()) {
+                RefPtr&lt;IntendedStructureChain&gt; chain = adoptRef(new IntendedStructureChain(
+                    profiledBlock, structure, list-&gt;list[listIndex].chain.get(),
+                    list-&gt;list[listIndex].count));
+                if (!result.computeForChain(profiledBlock, uid, chain))
+                    return GetByIdStatus(TakesSlowPath, true);
</ins><span class="cx">                 continue;
</span><ins>+            }
</ins><span class="cx">             
</span><span class="cx">             unsigned attributesIgnored;
</span><span class="cx">             JSCell* specificValue;
</span><span class="lines">@@ -218,54 +230,58 @@
</span><span class="cx">             if (structure-&gt;isDictionary())
</span><span class="cx">                 specificValue = 0;
</span><span class="cx">             
</span><del>-            if (!isValidOffset(myOffset)) {
-                result.m_offset = invalidOffset;
</del><ins>+            if (!isValidOffset(myOffset))
+                return GetByIdStatus(TakesSlowPath, true);
+
+            bool found = false;
+            for (unsigned variantIndex = 0; variantIndex &lt; result.m_variants.size(); ++variantIndex) {
+                GetByIdVariant&amp; variant = result.m_variants[variantIndex];
+                if (variant.m_chain)
+                    continue;
+                
+                if (variant.m_offset != myOffset)
+                    continue;
+
+                found = true;
+                if (variant.m_structureSet.contains(structure))
+                    break;
+                
+                if (variant.m_specificValue != JSValue(specificValue))
+                    variant.m_specificValue = JSValue();
+                
+                variant.m_structureSet.add(structure);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-                    
-            if (!i) {
-                result.m_offset = myOffset;
-                result.m_specificValue = JSValue(specificValue);
-            } else if (result.m_offset != myOffset) {
-                result.m_offset = invalidOffset;
-                break;
-            } else if (result.m_specificValue != JSValue(specificValue))
-                result.m_specificValue = JSValue();
</del><span class="cx">             
</span><del>-            result.m_structureSet.add(structure);
</del><ins>+            if (found)
+                continue;
+            
+            result.m_variants.append(
+                GetByIdVariant(StructureSet(structure), myOffset, specificValue));
</ins><span class="cx">         }
</span><del>-                    
-        if (isValidOffset(result.m_offset))
-            ASSERT(result.m_structureSet.size());
-        break;
</del><ins>+        
+        return result;
</ins><span class="cx">     }
</span><span class="cx">         
</span><span class="cx">     case access_get_by_id_chain: {
</span><span class="cx">         if (!stubInfo-&gt;u.getByIdChain.isDirect)
</span><span class="cx">             return GetByIdStatus(MakesCalls, true);
</span><del>-        result.m_chain = adoptRef(new IntendedStructureChain(
</del><ins>+        RefPtr&lt;IntendedStructureChain&gt; chain = adoptRef(new IntendedStructureChain(
</ins><span class="cx">             profiledBlock,
</span><span class="cx">             stubInfo-&gt;u.getByIdChain.baseObjectStructure.get(),
</span><span class="cx">             stubInfo-&gt;u.getByIdChain.chain.get(),
</span><span class="cx">             stubInfo-&gt;u.getByIdChain.count));
</span><del>-        computeForChain(result, profiledBlock, uid);
-        break;
</del><ins>+        if (result.computeForChain(profiledBlock, uid, chain))
+            return result;
+        return GetByIdStatus(TakesSlowPath, true);
</ins><span class="cx">     }
</span><span class="cx">         
</span><span class="cx">     default:
</span><del>-        ASSERT(!isValidOffset(result.m_offset));
-        break;
</del><ins>+        return GetByIdStatus(TakesSlowPath, true);
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    if (!isValidOffset(result.m_offset)) {
-        result.m_state = TakesSlowPath;
-        result.m_structureSet.clear();
-        result.m_chain.clear();
-        result.m_specificValue = JSValue();
-    } else
-        result.m_state = Simple;
-    
-    return result;
</del><ins>+    RELEASE_ASSERT_NOT_REACHED();
+    return GetByIdStatus();
</ins><span class="cx"> }
</span><span class="cx"> #endif // ENABLE(JIT)
</span><span class="cx"> 
</span><span class="lines">@@ -280,7 +296,7 @@
</span><span class="cx">             ConcurrentJITLocker locker(dfgBlock-&gt;m_lock);
</span><span class="cx">             result = computeForStubInfo(locker, dfgBlock, dfgMap.get(codeOrigin), uid);
</span><span class="cx">         }
</span><del>-    
</del><ins>+        
</ins><span class="cx">         if (result.takesSlowPath())
</span><span class="cx">             return result;
</span><span class="cx">     
</span><span class="lines">@@ -318,22 +334,38 @@
</span><span class="cx">     if (!structure-&gt;propertyAccessesAreCacheable())
</span><span class="cx">         return GetByIdStatus(TakesSlowPath);
</span><span class="cx"> 
</span><del>-    GetByIdStatus result;
-    result.m_wasSeenInJIT = false; // To my knowledge nobody that uses computeFor(VM&amp;, Structure*, StringImpl*) reads this field, but I might as well be honest: no, it wasn't seen in the JIT, since I computed it statically.
</del><span class="cx">     unsigned attributes;
</span><span class="cx">     JSCell* specificValue;
</span><del>-    result.m_offset = structure-&gt;getConcurrently(vm, uid, attributes, specificValue);
-    if (!isValidOffset(result.m_offset))
</del><ins>+    PropertyOffset offset = structure-&gt;getConcurrently(vm, uid, attributes, specificValue);
+    if (!isValidOffset(offset))
</ins><span class="cx">         return GetByIdStatus(TakesSlowPath); // It's probably a prototype lookup. Give up on life for now, even though we could totally be way smarter about it.
</span><span class="cx">     if (attributes &amp; Accessor)
</span><span class="cx">         return GetByIdStatus(MakesCalls);
</span><span class="cx">     if (structure-&gt;isDictionary())
</span><span class="cx">         specificValue = 0;
</span><del>-    result.m_structureSet.add(structure);
-    result.m_specificValue = JSValue(specificValue);
-    result.m_state = Simple;
-    return result;
</del><ins>+    return GetByIdStatus(
+        Simple, false, GetByIdVariant(StructureSet(structure), offset, specificValue));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void GetByIdStatus::dump(PrintStream&amp; out) const
+{
+    out.print(&quot;(&quot;);
+    switch (m_state) {
+    case NoInformation:
+        out.print(&quot;NoInformation&quot;);
+        break;
+    case Simple:
+        out.print(&quot;Simple&quot;);
+        break;
+    case TakesSlowPath:
+        out.print(&quot;TakesSlowPath&quot;);
+        break;
+    case MakesCalls:
+        out.print(&quot;MakesCalls&quot;);
+        break;
+    }
+    out.print(&quot;, &quot;, listDump(m_variants), &quot;, seenInJIT = &quot;, m_wasSeenInJIT, &quot;)&quot;);
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeGetByIdStatush"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.h (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.h        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.h        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -29,9 +29,7 @@
</span><span class="cx"> #include &quot;CodeOrigin.h&quot;
</span><span class="cx"> #include &quot;ConcurrentJITLock.h&quot;
</span><span class="cx"> #include &quot;ExitingJITType.h&quot;
</span><del>-#include &quot;IntendedStructureChain.h&quot;
-#include &quot;PropertyOffset.h&quot;
-#include &quot;StructureSet.h&quot;
</del><ins>+#include &quot;GetByIdVariant.h&quot;
</ins><span class="cx"> #include &quot;StructureStubInfo.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -50,28 +48,22 @@
</span><span class="cx"> 
</span><span class="cx">     GetByIdStatus()
</span><span class="cx">         : m_state(NoInformation)
</span><del>-        , m_offset(invalidOffset)
</del><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     explicit GetByIdStatus(State state)
</span><span class="cx">         : m_state(state)
</span><del>-        , m_offset(invalidOffset)
</del><span class="cx">     {
</span><span class="cx">         ASSERT(state == NoInformation || state == TakesSlowPath || state == MakesCalls);
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     GetByIdStatus(
</span><del>-        State state, bool wasSeenInJIT, const StructureSet&amp; structureSet = StructureSet(),
-        PropertyOffset offset = invalidOffset, JSValue specificValue = JSValue(), PassRefPtr&lt;IntendedStructureChain&gt; chain = nullptr)
</del><ins>+        State state, bool wasSeenInJIT, const GetByIdVariant&amp; variant = GetByIdVariant())
</ins><span class="cx">         : m_state(state)
</span><del>-        , m_structureSet(structureSet)
-        , m_chain(chain)
-        , m_specificValue(specificValue)
-        , m_offset(offset)
</del><span class="cx">         , m_wasSeenInJIT(wasSeenInJIT)
</span><span class="cx">     {
</span><del>-        ASSERT((state == Simple) == (offset != invalidOffset));
</del><ins>+        ASSERT((state == Simple) == variant.isSet());
+        m_variants.append(variant);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     static GetByIdStatus computeFor(CodeBlock*, StubInfoMap&amp;, unsigned bytecodeIndex, StringImpl* uid);
</span><span class="lines">@@ -84,16 +76,19 @@
</span><span class="cx">     bool isSet() const { return m_state != NoInformation; }
</span><span class="cx">     bool operator!() const { return !isSet(); }
</span><span class="cx">     bool isSimple() const { return m_state == Simple; }
</span><ins>+
+    size_t numVariants() const { return m_variants.size(); }
+    const Vector&lt;GetByIdVariant, 1&gt;&amp; variants() const { return m_variants; }
+    const GetByIdVariant&amp; at(size_t index) const { return m_variants[index]; }
+    const GetByIdVariant&amp; operator[](size_t index) const { return at(index); }
+
</ins><span class="cx">     bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls; }
</span><span class="cx">     bool makesCalls() const { return m_state == MakesCalls; }
</span><span class="cx">     
</span><del>-    const StructureSet&amp; structureSet() const { return m_structureSet; }
-    IntendedStructureChain* chain() const { return const_cast&lt;IntendedStructureChain*&gt;(m_chain.get()); } // Returns null if this is a direct access.
-    JSValue specificValue() const { return m_specificValue; } // Returns JSValue() if there is no specific value.
-    PropertyOffset offset() const { return m_offset; }
-    
</del><span class="cx">     bool wasSeenInJIT() const { return m_wasSeenInJIT; }
</span><span class="cx">     
</span><ins>+    void dump(PrintStream&amp;) const;
+    
</ins><span class="cx"> private:
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     static bool hasExitSite(const ConcurrentJITLocker&amp;, CodeBlock*, unsigned bytecodeIndex, ExitingJITType = ExitFromAnything);
</span><span class="lines">@@ -101,14 +96,11 @@
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     static GetByIdStatus computeForStubInfo(const ConcurrentJITLocker&amp;, CodeBlock*, StructureStubInfo*, StringImpl* uid);
</span><span class="cx"> #endif
</span><del>-    static void computeForChain(GetByIdStatus&amp; result, CodeBlock*, StringImpl* uid);
</del><ins>+    bool computeForChain(CodeBlock*, StringImpl* uid, PassRefPtr&lt;IntendedStructureChain&gt;);
</ins><span class="cx">     static GetByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, StringImpl* uid);
</span><span class="cx">     
</span><span class="cx">     State m_state;
</span><del>-    StructureSet m_structureSet;
-    RefPtr&lt;IntendedStructureChain&gt; m_chain;
-    JSValue m_specificValue;
-    PropertyOffset m_offset;
</del><ins>+    Vector&lt;GetByIdVariant, 1&gt; m_variants;
</ins><span class="cx">     bool m_wasSeenInJIT;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeGetByIdVariantcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp (0 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -0,0 +1,52 @@
</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;GetByIdVariant.h&quot;
+
+#include &quot;JSCInlines.h&quot;
+
+namespace JSC {
+
+void GetByIdVariant::dump(PrintStream&amp; out) const
+{
+    dumpInContext(out, 0);
+}
+
+void GetByIdVariant::dumpInContext(PrintStream&amp; out, DumpContext* context) const
+{
+    if (!isSet()) {
+        out.print(&quot;&lt;empty&gt;&quot;);
+        return;
+    }
+    
+    out.print(
+        &quot;&lt;&quot;, inContext(structureSet(), context), &quot;, &quot;,
+        pointerDumpInContext(chain(), context), &quot;, &quot;,
+        inContext(specificValue(), context), &quot;, &quot;, offset(), &quot;&gt;&quot;);
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeGetByIdVarianth"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.h (0 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.h        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -0,0 +1,79 @@
</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 GetByIdVariant_h
+#define GetByIdVariant_h
+
+#include &quot;IntendedStructureChain.h&quot;
+#include &quot;JSCJSValue.h&quot;
+#include &quot;PropertyOffset.h&quot;
+#include &quot;StructureSet.h&quot;
+
+namespace JSC {
+
+class GetByIdStatus;
+struct DumpContext;
+
+class GetByIdVariant {
+public:
+    GetByIdVariant(
+        const StructureSet&amp; structureSet = StructureSet(),
+        PropertyOffset offset = invalidOffset, JSValue specificValue = JSValue(),
+        PassRefPtr&lt;IntendedStructureChain&gt; chain = nullptr)
+        : m_structureSet(structureSet)
+        , m_chain(chain)
+        , m_specificValue(specificValue)
+        , m_offset(offset)
+    {
+        if (!structureSet.size()) {
+            ASSERT(offset == invalidOffset);
+            ASSERT(!specificValue);
+            ASSERT(!chain);
+        }
+    }
+    
+    bool isSet() const { return !!m_structureSet.size(); }
+    bool operator!() const { return !isSet(); }
+    const StructureSet&amp; structureSet() const { return m_structureSet; }
+    IntendedStructureChain* chain() const { return const_cast&lt;IntendedStructureChain*&gt;(m_chain.get()); }
+    JSValue specificValue() const { return m_specificValue; }
+    PropertyOffset offset() const { return m_offset; }
+    
+    void dump(PrintStream&amp;) const;
+    void dumpInContext(PrintStream&amp;, DumpContext*) const;
+    
+private:
+    friend class GetByIdStatus;
+    
+    StructureSet m_structureSet;
+    RefPtr&lt;IntendedStructureChain&gt; m_chain;
+    JSValue m_specificValue;
+    PropertyOffset m_offset;
+};
+
+} // namespace JSC
+
+#endif // GetByIdVariant_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -1451,17 +1451,17 @@
</span><span class="cx">                 GetByIdStatus status = GetByIdStatus::computeFor(
</span><span class="cx">                     m_graph.m_vm, structure,
</span><span class="cx">                     m_graph.identifiers()[node-&gt;identifierNumber()]);
</span><del>-                if (status.isSimple()) {
</del><ins>+                if (status.isSimple() &amp;&amp; status.numVariants() == 1) {
</ins><span class="cx">                     // Assert things that we can't handle and that the computeFor() method
</span><span class="cx">                     // above won't be able to return.
</span><del>-                    ASSERT(status.structureSet().size() == 1);
-                    ASSERT(!status.chain());
</del><ins>+                    ASSERT(status[0].structureSet().size() == 1);
+                    ASSERT(!status[0].chain());
</ins><span class="cx">                     
</span><del>-                    if (status.specificValue())
-                        setConstant(node, status.specificValue());
</del><ins>+                    if (status[0].specificValue())
+                        setConstant(node, status[0].specificValue());
</ins><span class="cx">                     else
</span><span class="cx">                         forNode(node).makeHeapTop();
</span><del>-                    filter(node-&gt;child1(), status.structureSet());
</del><ins>+                    filter(node-&gt;child1(), status[0].structureSet());
</ins><span class="cx">                     
</span><span class="cx">                     m_state.setFoundConstants(true);
</span><span class="cx">                     m_state.setHaveStructures(true);
</span><span class="lines">@@ -1632,6 +1632,39 @@
</span><span class="cx">         forNode(node).makeHeapTop();
</span><span class="cx">         break;
</span><span class="cx">     }
</span><ins>+        
+    case MultiGetByOffset: {
+        AbstractValue&amp; value = forNode(node-&gt;child1());
+        ASSERT(!(value.m_type &amp; ~SpecCell)); // Edge filtering should have already ensured this.
+
+        if (Structure* structure = value.bestProvenStructure()) {
+            bool done = false;
+            for (unsigned i = node-&gt;multiGetByOffsetData().variants.size(); i--;) {
+                const GetByIdVariant&amp; variant = node-&gt;multiGetByOffsetData().variants[i];
+                if (!variant.structureSet().contains(structure))
+                    continue;
+                
+                if (variant.chain())
+                    break;
+                
+                filter(value, structure);
+                forNode(node).makeHeapTop();
+                m_state.setFoundConstants(true);
+                done = true;
+                break;
+            }
+            if (done)
+                break;
+        }
+        
+        StructureSet set;
+        for (unsigned i = node-&gt;multiGetByOffsetData().variants.size(); i--;)
+            set.addAll(node-&gt;multiGetByOffsetData().variants[i].structureSet());
+        
+        filter(value, set);
+        forNode(node).makeHeapTop();
+        break;
+    }
</ins><span class="cx">             
</span><span class="cx">     case PutByOffset: {
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -180,6 +180,7 @@
</span><span class="cx">     void handleGetById(
</span><span class="cx">         int destinationOperand, SpeculatedType, Node* base, unsigned identifierNumber,
</span><span class="cx">         const GetByIdStatus&amp;);
</span><ins>+    Node* emitPrototypeChecks(const GetByIdVariant&amp;);
</ins><span class="cx"> 
</span><span class="cx">     Node* getScope(bool skipTop, unsigned skipCount);
</span><span class="cx">     
</span><span class="lines">@@ -1827,6 +1828,21 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Node* ByteCodeParser::emitPrototypeChecks(const GetByIdVariant&amp; variant)
+{
+    Node* base = 0;
+    m_graph.chains().addLazily(variant.chain());
+    Structure* currentStructure = variant.structureSet().singletonStructure();
+    JSObject* currentObject = 0;
+    for (unsigned i = 0; i &lt; variant.chain()-&gt;size(); ++i) {
+        currentObject = asObject(currentStructure-&gt;prototypeForLookup(m_inlineStackTop-&gt;m_codeBlock));
+        currentStructure = variant.chain()-&gt;at(i);
+        base = cellConstantWithStructureCheck(currentObject, currentStructure);
+    }
+    RELEASE_ASSERT(base);
+    return base;
+}
+
</ins><span class="cx"> void ByteCodeParser::handleGetById(
</span><span class="cx">     int destinationOperand, SpeculatedType prediction, Node* base, unsigned identifierNumber,
</span><span class="cx">     const GetByIdStatus&amp; getByIdStatus)
</span><span class="lines">@@ -1839,25 +1855,42 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    ASSERT(getByIdStatus.structureSet().size());
</del><ins>+    if (getByIdStatus.numVariants() &gt; 1) {
+        if (!isFTL(m_graph.m_plan.mode)) {
+            set(VirtualRegister(destinationOperand),
+                addToGraph(GetById, OpInfo(identifierNumber), OpInfo(prediction), base));
+            return;
+        }
+        
+        // 1) Emit prototype structure checks for all chains. This could sort of maybe not be
+        //    optimal, if there is some rarely executed case in the chain that requires a lot
+        //    of checks and those checks are not watchpointable.
+        for (unsigned variantIndex = getByIdStatus.numVariants(); variantIndex--;) {
+            if (getByIdStatus[variantIndex].chain())
+                emitPrototypeChecks(getByIdStatus[variantIndex]);
+        }
+        
+        // 2) Emit a MultiGetByOffset
+        MultiGetByOffsetData* data = m_graph.m_multiGetByOffsetData.add();
+        data-&gt;variants = getByIdStatus.variants();
+        data-&gt;identifierNumber = identifierNumber;
+        set(VirtualRegister(destinationOperand),
+            addToGraph(MultiGetByOffset, OpInfo(data), OpInfo(prediction), base));
+        return;
+    }
+    
+    ASSERT(getByIdStatus.numVariants() == 1);
+    GetByIdVariant variant = getByIdStatus[0];
</ins><span class="cx">                 
</span><span class="cx">     if (m_graph.compilation())
</span><span class="cx">         m_graph.compilation()-&gt;noticeInlinedGetById();
</span><span class="cx">     
</span><span class="cx">     Node* originalBaseForBaselineJIT = base;
</span><span class="cx">                 
</span><del>-    addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(getByIdStatus.structureSet())), base);
</del><ins>+    addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), base);
</ins><span class="cx">     
</span><del>-    if (getByIdStatus.chain()) {
-        m_graph.chains().addLazily(getByIdStatus.chain());
-        Structure* currentStructure = getByIdStatus.structureSet().singletonStructure();
-        JSObject* currentObject = 0;
-        for (unsigned i = 0; i &lt; getByIdStatus.chain()-&gt;size(); ++i) {
-            currentObject = asObject(currentStructure-&gt;prototypeForLookup(m_inlineStackTop-&gt;m_codeBlock));
-            currentStructure = getByIdStatus.chain()-&gt;at(i);
-            base = cellConstantWithStructureCheck(currentObject, currentStructure);
-        }
-    }
</del><ins>+    if (variant.chain())
+        base = emitPrototypeChecks(variant);
</ins><span class="cx">     
</span><span class="cx">     // Unless we want bugs like https://bugs.webkit.org/show_bug.cgi?id=88783, we need to
</span><span class="cx">     // ensure that the base of the original get_by_id is kept alive until we're done with
</span><span class="lines">@@ -1865,18 +1898,18 @@
</span><span class="cx">     // on something other than the base following the CheckStructure on base, or if the
</span><span class="cx">     // access was compiled to a WeakJSConstant specific value, in which case we might not
</span><span class="cx">     // have any explicit use of the base at all.
</span><del>-    if (getByIdStatus.specificValue() || originalBaseForBaselineJIT != base)
</del><ins>+    if (variant.specificValue() || originalBaseForBaselineJIT != base)
</ins><span class="cx">         addToGraph(Phantom, originalBaseForBaselineJIT);
</span><span class="cx">     
</span><del>-    if (getByIdStatus.specificValue()) {
-        ASSERT(getByIdStatus.specificValue().isCell());
</del><ins>+    if (variant.specificValue()) {
+        ASSERT(variant.specificValue().isCell());
</ins><span class="cx">         
</span><del>-        set(VirtualRegister(destinationOperand), cellConstant(getByIdStatus.specificValue().asCell()));
</del><ins>+        set(VirtualRegister(destinationOperand), cellConstant(variant.specificValue().asCell()));
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     handleGetByOffset(
</span><del>-        destinationOperand, prediction, base, identifierNumber, getByIdStatus.offset());
</del><ins>+        destinationOperand, prediction, base, identifierNumber, variant.offset());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ByteCodeParser::prepareToParseBlock()
</span><span class="lines">@@ -3140,13 +3173,13 @@
</span><span class="cx">             case GlobalProperty:
</span><span class="cx">             case GlobalPropertyWithVarInjectionChecks: {
</span><span class="cx">                 GetByIdStatus status = GetByIdStatus::computeFor(*m_vm, structure, uid);
</span><del>-                if (status.takesSlowPath()) {
</del><ins>+                if (status.state() != GetByIdStatus::Simple || status.numVariants() != 1) {
</ins><span class="cx">                     set(VirtualRegister(dst), addToGraph(GetByIdFlush, OpInfo(identifierNumber), OpInfo(prediction), get(VirtualRegister(scope))));
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><del>-                Node* base = cellConstantWithStructureCheck(globalObject, status.structureSet().singletonStructure());
</del><ins>+                Node* base = cellConstantWithStructureCheck(globalObject, status[0].structureSet().singletonStructure());
</ins><span class="cx">                 addToGraph(Phantom, get(VirtualRegister(scope)));
</span><del>-                if (JSValue specificValue = status.specificValue())
</del><ins>+                if (JSValue specificValue = status[0].specificValue())
</ins><span class="cx">                     set(VirtualRegister(dst), cellConstant(specificValue.asCell()));
</span><span class="cx">                 else
</span><span class="cx">                     set(VirtualRegister(dst), handleGetByOffset(prediction, base, identifierNumber, operand));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCSEPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -642,23 +642,29 @@
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    Node* getByOffsetLoadElimination(unsigned identifierNumber, Node* child1)
</del><ins>+    Node* getByOffsetLoadElimination(unsigned identifierNumber, Node* base)
</ins><span class="cx">     {
</span><span class="cx">         for (unsigned i = m_indexInBlock; i--;) {
</span><span class="cx">             Node* node = m_currentBlock-&gt;at(i);
</span><del>-            if (node == child1)
</del><ins>+            if (node == base)
</ins><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="cx">             switch (node-&gt;op()) {
</span><span class="cx">             case GetByOffset:
</span><del>-                if (node-&gt;child1() == child1
</del><ins>+                if (node-&gt;child2() == base
</ins><span class="cx">                     &amp;&amp; m_graph.m_storageAccessData[node-&gt;storageAccessDataIndex()].identifierNumber == identifierNumber)
</span><span class="cx">                     return node;
</span><span class="cx">                 break;
</span><span class="cx">                 
</span><ins>+            case MultiGetByOffset:
+                if (node-&gt;child1() == base
+                    &amp;&amp; node-&gt;multiGetByOffsetData().identifierNumber == identifierNumber)
+                    return node;
+                break;
+                
</ins><span class="cx">             case PutByOffset:
</span><span class="cx">                 if (m_graph.m_storageAccessData[node-&gt;storageAccessDataIndex()].identifierNumber == identifierNumber) {
</span><del>-                    if (node-&gt;child1() == child1) // Must be same property storage.
</del><ins>+                    if (node-&gt;child2() == base) // Must be same property storage.
</ins><span class="cx">                         return node-&gt;child3().node();
</span><span class="cx">                     return 0;
</span><span class="cx">                 }
</span><span class="lines">@@ -1401,9 +1407,15 @@
</span><span class="cx">         case GetByOffset:
</span><span class="cx">             if (cseMode == StoreElimination)
</span><span class="cx">                 break;
</span><del>-            setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node-&gt;storageAccessDataIndex()].identifierNumber, node-&gt;child1().node()));
</del><ins>+            setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node-&gt;storageAccessDataIndex()].identifierNumber, node-&gt;child2().node()));
</ins><span class="cx">             break;
</span><span class="cx">             
</span><ins>+        case MultiGetByOffset:
+            if (cseMode == StoreElimination)
+                break;
+            setReplacement(getByOffsetLoadElimination(node-&gt;multiGetByOffsetData().identifierNumber, node-&gt;child1().node()));
+            break;
+            
</ins><span class="cx">         case PutByOffset:
</span><span class="cx">             if (cseMode == NormalCSE)
</span><span class="cx">                 break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -470,6 +470,10 @@
</span><span class="cx">         read(AbstractHeap(NamedProperties, graph.m_storageAccessData[node-&gt;storageAccessDataIndex()].identifierNumber));
</span><span class="cx">         return;
</span><span class="cx">         
</span><ins>+    case MultiGetByOffset:
+        read(AbstractHeap(NamedProperties, node-&gt;multiGetByOffsetData().identifierNumber));
+        return;
+        
</ins><span class="cx">     case PutByOffset:
</span><span class="cx">         write(AbstractHeap(NamedProperties, graph.m_storageAccessData[node-&gt;storageAccessDataIndex()].identifierNumber));
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCommonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCommon.h (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCommon.h        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGCommon.h        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -28,6 +28,8 @@
</span><span class="cx"> 
</span><span class="cx"> #include &lt;wtf/Platform.h&gt;
</span><span class="cx"> 
</span><ins>+#include &quot;DFGCompilationMode.h&quot;
+
</ins><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CodeOrigin.h&quot;
</span><span class="lines">@@ -63,14 +65,14 @@
</span><span class="cx">     DontRefNode
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-inline bool verboseCompilationEnabled()
</del><ins>+inline bool verboseCompilationEnabled(CompilationMode mode = DFGMode)
</ins><span class="cx"> {
</span><del>-    return Options::verboseCompilation() || Options::dumpGraphAtEachPhase();
</del><ins>+    return Options::verboseCompilation() || Options::dumpGraphAtEachPhase() || (isFTL(mode) &amp;&amp; Options::verboseFTLCompilation());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline bool logCompilationChanges()
</del><ins>+inline bool logCompilationChanges(CompilationMode mode = DFGMode)
</ins><span class="cx"> {
</span><del>-    return verboseCompilationEnabled() || Options::logCompilationChanges();
</del><ins>+    return verboseCompilationEnabled(mode) || Options::logCompilationChanges();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline bool shouldDumpGraphAtEachPhase()
</span><span class="lines">@@ -288,10 +290,10 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // Unconditionally disable DFG disassembly support if the DFG is not compiled in.
</span><del>-inline bool shouldShowDisassembly()
</del><ins>+inline bool shouldShowDisassembly(CompilationMode mode = DFGMode)
</ins><span class="cx"> {
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><del>-    return Options::showDisassembly() || Options::showDFGDisassembly();
</del><ins>+    return Options::showDisassembly() || Options::showDFGDisassembly() || (isFTL(mode) &amp;&amp; Options::showFTLDisassembly());
</ins><span class="cx"> #else
</span><span class="cx">     return false;
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -151,10 +151,33 @@
</span><span class="cx">                 
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><ins>+                
+            case MultiGetByOffset: {
+                Edge childEdge = node-&gt;child1();
+                Node* child = childEdge.node();
+                MultiGetByOffsetData&amp; data = node-&gt;multiGetByOffsetData();
+
+                Structure* structure = m_state.forNode(child).bestProvenStructure();
+                if (!structure)
+                    break;
+                
+                for (unsigned i = data.variants.size(); i--;) {
+                    const GetByIdVariant&amp; variant = data.variants[i];
+                    if (!variant.structureSet().contains(structure))
+                        continue;
+                    
+                    if (variant.chain())
+                        break;
+                    
+                    emitGetByOffset(indexInBlock, node, structure, variant, data.identifierNumber);
+                    eliminated = true;
+                    break;
+                }
+                break;
+            }
</ins><span class="cx">         
</span><span class="cx">             case GetById:
</span><span class="cx">             case GetByIdFlush: {
</span><del>-                NodeOrigin origin = node-&gt;origin;
</del><span class="cx">                 Edge childEdge = node-&gt;child1();
</span><span class="cx">                 Node* child = childEdge.node();
</span><span class="cx">                 unsigned identifierNumber = node-&gt;identifierNumber();
</span><span class="lines">@@ -166,54 +189,17 @@
</span><span class="cx">                 if (!structure)
</span><span class="cx">                     break;
</span><span class="cx">                 
</span><del>-                bool needsWatchpoint = !m_state.forNode(child).m_currentKnownStructure.hasSingleton();
-                bool needsCellCheck = m_state.forNode(child).m_type &amp; ~SpecCell;
-                
</del><span class="cx">                 GetByIdStatus status = GetByIdStatus::computeFor(
</span><span class="cx">                     vm(), structure, m_graph.identifiers()[identifierNumber]);
</span><span class="cx">                 
</span><del>-                if (!status.isSimple()) {
</del><ins>+                if (!status.isSimple() || status.numVariants() != 1) {
</ins><span class="cx">                     // FIXME: We could handle prototype cases.
</span><span class="cx">                     // https://bugs.webkit.org/show_bug.cgi?id=110386
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="cx">                 
</span><del>-                ASSERT(status.structureSet().size() == 1);
-                ASSERT(!status.chain());
-                ASSERT(status.structureSet().singletonStructure() == structure);
-                
-                // Now before we do anything else, push the CFA forward over the GetById
-                // and make sure we signal to the loop that it should continue and not
-                // do any eliminations.
-                m_interpreter.execute(indexInBlock);
</del><ins>+                emitGetByOffset(indexInBlock, node, structure, status[0], identifierNumber);
</ins><span class="cx">                 eliminated = true;
</span><del>-                
-                if (needsWatchpoint) {
-                    m_insertionSet.insertNode(
-                        indexInBlock, SpecNone, StructureTransitionWatchpoint, origin,
-                        OpInfo(structure), childEdge);
-                } else if (needsCellCheck) {
-                    m_insertionSet.insertNode(
-                        indexInBlock, SpecNone, Phantom, origin, childEdge);
-                }
-                
-                childEdge.setUseKind(KnownCellUse);
-                
-                Edge propertyStorage;
-                
-                if (isInlineOffset(status.offset()))
-                    propertyStorage = childEdge;
-                else {
-                    propertyStorage = Edge(m_insertionSet.insertNode(
-                        indexInBlock, SpecNone, GetButterfly, origin, childEdge));
-                }
-                
-                node-&gt;convertToGetByOffset(m_graph.m_storageAccessData.size(), propertyStorage);
-                
-                StorageAccessData storageAccessData;
-                storageAccessData.offset = status.offset();
-                storageAccessData.identifierNumber = identifierNumber;
-                m_graph.m_storageAccessData.append(storageAccessData);
</del><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">                 
</span><span class="lines">@@ -406,7 +392,57 @@
</span><span class="cx">         
</span><span class="cx">         return changed;
</span><span class="cx">     }
</span><ins>+        
+    void emitGetByOffset(unsigned indexInBlock, Node* node, Structure* structure, const GetByIdVariant&amp; variant, unsigned identifierNumber)
+    {
+        NodeOrigin origin = node-&gt;origin;
+        Edge childEdge = node-&gt;child1();
+        Node* child = childEdge.node();
</ins><span class="cx"> 
</span><ins>+        bool needsWatchpoint = !m_state.forNode(child).m_currentKnownStructure.hasSingleton();
+        bool needsCellCheck = m_state.forNode(child).m_type &amp; ~SpecCell;
+        
+        ASSERT(!variant.chain());
+        ASSERT(variant.structureSet().contains(structure));
+        
+        // Now before we do anything else, push the CFA forward over the GetById
+        // and make sure we signal to the loop that it should continue and not
+        // do any eliminations.
+        m_interpreter.execute(indexInBlock);
+        
+        if (needsWatchpoint) {
+            m_insertionSet.insertNode(
+                indexInBlock, SpecNone, StructureTransitionWatchpoint, origin,
+                OpInfo(structure), childEdge);
+        } else if (needsCellCheck) {
+            m_insertionSet.insertNode(
+                indexInBlock, SpecNone, Phantom, origin, childEdge);
+        }
+        
+        if (variant.specificValue()) {
+            m_graph.convertToConstant(node, variant.specificValue());
+            return;
+        }
+        
+        childEdge.setUseKind(KnownCellUse);
+        
+        Edge propertyStorage;
+        
+        if (isInlineOffset(variant.offset()))
+            propertyStorage = childEdge;
+        else {
+            propertyStorage = Edge(m_insertionSet.insertNode(
+                indexInBlock, SpecNone, GetButterfly, origin, childEdge));
+        }
+        
+        node-&gt;convertToGetByOffset(m_graph.m_storageAccessData.size(), propertyStorage);
+        
+        StorageAccessData storageAccessData;
+        storageAccessData.offset = variant.offset();
+        storageAccessData.identifierNumber = identifierNumber;
+        m_graph.m_storageAccessData.append(storageAccessData);
+    }
+
</ins><span class="cx">     void addStructureTransitionCheck(NodeOrigin origin, unsigned indexInBlock, JSCell* cell)
</span><span class="cx">     {
</span><span class="cx">         Node* weakConstant = m_insertionSet.insertNode(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDrivercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -82,7 +82,7 @@
</span><span class="cx">     if (debugger &amp;&amp; (debugger-&gt;isStepping() || codeBlock-&gt;baselineAlternative()-&gt;hasDebuggerRequests()))
</span><span class="cx">         return CompilationInvalidated;
</span><span class="cx"> 
</span><del>-    if (logCompilationChanges())
</del><ins>+    if (logCompilationChanges(mode))
</ins><span class="cx">         dataLog(&quot;DFG(Driver) compiling &quot;, *codeBlock, &quot; with &quot;, mode, &quot;, number of instructions = &quot;, codeBlock-&gt;instructionCount(), &quot;\n&quot;);
</span><span class="cx">     
</span><span class="cx">     // Make sure that any stubs that the DFG is going to use are initialized. We want to
</span><span class="lines">@@ -115,7 +115,7 @@
</span><span class="cx">     if (enableConcurrentJIT) {
</span><span class="cx">         Worklist* worklist = ensureGlobalWorklistFor(mode);
</span><span class="cx">         plan-&gt;callback = callback;
</span><del>-        if (logCompilationChanges())
</del><ins>+        if (logCompilationChanges(mode))
</ins><span class="cx">             dataLog(&quot;Deferring DFG compilation of &quot;, *codeBlock, &quot; with queue length &quot;, worklist-&gt;queueLength(), &quot;.\n&quot;);
</span><span class="cx">         worklist-&gt;enqueue(plan);
</span><span class="cx">         return CompilationDeferred;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -881,6 +881,11 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><ins>+        case MultiGetByOffset: {
+            fixEdge&lt;CellUse&gt;(node-&gt;child1());
+            break;
+        }
+            
</ins><span class="cx">         case PutByOffset: {
</span><span class="cx">             if (!node-&gt;child1()-&gt;hasStorageResult())
</span><span class="cx">                 fixEdge&lt;KnownCellUse&gt;(node-&gt;child1());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -246,6 +246,12 @@
</span><span class="cx">         out.print(comma, &quot;id&quot;, storageAccessData.identifierNumber, &quot;{&quot;, identifiers()[storageAccessData.identifierNumber], &quot;}&quot;);
</span><span class="cx">         out.print(&quot;, &quot;, static_cast&lt;ptrdiff_t&gt;(storageAccessData.offset));
</span><span class="cx">     }
</span><ins>+    if (node-&gt;hasMultiGetByOffsetData()) {
+        MultiGetByOffsetData&amp; data = node-&gt;multiGetByOffsetData();
+        out.print(comma, &quot;id&quot;, data.identifierNumber, &quot;{&quot;, identifiers()[data.identifierNumber], &quot;}&quot;);
+        for (unsigned i = 0; i &lt; data.variants.size(); ++i)
+            out.print(comma, inContext(data.variants[i], context));
+    }
</ins><span class="cx">     ASSERT(node-&gt;hasVariableAccessData(*this) == node-&gt;hasLocal(*this));
</span><span class="cx">     if (node-&gt;hasVariableAccessData(*this)) {
</span><span class="cx">         VariableAccessData* variableAccessData = node-&gt;tryGetVariableAccessData();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.h (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -177,7 +177,10 @@
</span><span class="cx">     
</span><span class="cx">     void convertToConstant(Node* node, JSValue value)
</span><span class="cx">     {
</span><del>-        convertToConstant(node, constantRegisterForConstant(value));
</del><ins>+        if (value.isObject())
+            node-&gt;convertToWeakConstant(value.asCell());
+        else
+            convertToConstant(node, constantRegisterForConstant(value));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // CodeBlock is optional, but may allow additional information to be dumped (e.g. Identifier names).
</span><span class="lines">@@ -827,6 +830,7 @@
</span><span class="cx">     SegmentedVector&lt;StructureTransitionData, 8&gt; m_structureTransitionData;
</span><span class="cx">     SegmentedVector&lt;NewArrayBufferData, 4&gt; m_newArrayBufferData;
</span><span class="cx">     SegmentedVector&lt;SwitchData, 4&gt; m_switchData;
</span><ins>+    Bag&lt;MultiGetByOffsetData&gt; m_multiGetByOffsetData;
</ins><span class="cx">     Vector&lt;InlineVariableData, 4&gt; m_inlineVariableData;
</span><span class="cx">     OwnPtr&lt;InlineCallFrameSet&gt; m_inlineCallFrames;
</span><span class="cx">     HashMap&lt;CodeBlock*, std::unique_ptr&lt;FullBytecodeLiveness&gt;&gt; m_bytecodeLiveness;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx"> #include &quot;DFGNodeOrigin.h&quot;
</span><span class="cx"> #include &quot;DFGNodeType.h&quot;
</span><span class="cx"> #include &quot;DFGVariableAccessData.h&quot;
</span><ins>+#include &quot;GetByIdVariant.h&quot;
</ins><span class="cx"> #include &quot;JSCJSValue.h&quot;
</span><span class="cx"> #include &quot;Operands.h&quot;
</span><span class="cx"> #include &quot;SpeculatedType.h&quot;
</span><span class="lines">@@ -53,6 +54,11 @@
</span><span class="cx"> class Graph;
</span><span class="cx"> struct BasicBlock;
</span><span class="cx"> 
</span><ins>+struct MultiGetByOffsetData {
+    unsigned identifierNumber;
+    Vector&lt;GetByIdVariant, 2&gt; variants;
+};
+
</ins><span class="cx"> struct StructureTransitionData {
</span><span class="cx">     Structure* previousStructure;
</span><span class="cx">     Structure* newStructure;
</span><span class="lines">@@ -406,7 +412,7 @@
</span><span class="cx">     
</span><span class="cx">     void convertToGetByOffset(unsigned storageAccessDataIndex, Edge storage)
</span><span class="cx">     {
</span><del>-        ASSERT(m_op == GetById || m_op == GetByIdFlush);
</del><ins>+        ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == MultiGetByOffset);
</ins><span class="cx">         m_opInfo = storageAccessDataIndex;
</span><span class="cx">         children.setChild2(children.child1());
</span><span class="cx">         children.child2().setUseKind(KnownCellUse);
</span><span class="lines">@@ -905,6 +911,7 @@
</span><span class="cx">         case Call:
</span><span class="cx">         case Construct:
</span><span class="cx">         case GetByOffset:
</span><ins>+        case MultiGetByOffset:
</ins><span class="cx">         case GetClosureVar:
</span><span class="cx">         case ArrayPop:
</span><span class="cx">         case ArrayPush:
</span><span class="lines">@@ -1054,6 +1061,16 @@
</span><span class="cx">         return m_opInfo;
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    bool hasMultiGetByOffsetData()
+    {
+        return op() == MultiGetByOffset;
+    }
+    
+    MultiGetByOffsetData&amp; multiGetByOffsetData()
+    {
+        return *reinterpret_cast&lt;MultiGetByOffsetData*&gt;(m_opInfo);
+    }
+    
</ins><span class="cx">     bool hasFunctionDeclIndex()
</span><span class="cx">     {
</span><span class="cx">         return op() == NewFunction
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -175,6 +175,7 @@
</span><span class="cx">     macro(ConstantStoragePointer, NodeResultStorage) \
</span><span class="cx">     macro(TypedArrayWatchpoint, NodeMustGenerate) \
</span><span class="cx">     macro(GetByOffset, NodeResultJS) \
</span><ins>+    macro(MultiGetByOffset, NodeResultJS) \
</ins><span class="cx">     macro(PutByOffset, NodeMustGenerate) \
</span><span class="cx">     macro(GetArrayLength, NodeResultInt32) \
</span><span class="cx">     macro(GetTypedArrayByteOffset, NodeResultInt32) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPhaseh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPhase.h (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPhase.h        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGPhase.h        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -51,6 +51,8 @@
</span><span class="cx">     
</span><span class="cx">     const char* name() const { return m_name; }
</span><span class="cx">     
</span><ins>+    Graph&amp; graph() { return m_graph; }
+    
</ins><span class="cx">     // Each phase must have a run() method.
</span><span class="cx">     
</span><span class="cx"> protected:
</span><span class="lines">@@ -73,7 +75,7 @@
</span><span class="cx"> bool runAndLog(PhaseType&amp; phase)
</span><span class="cx"> {
</span><span class="cx">     bool result = phase.run();
</span><del>-    if (result &amp;&amp; logCompilationChanges())
</del><ins>+    if (result &amp;&amp; logCompilationChanges(phase.graph().m_plan.mode))
</ins><span class="cx">         dataLogF(&quot;Phase %s changed the IR.\n&quot;, phase.name());
</span><span class="cx">     return result;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -85,7 +85,7 @@
</span><span class="cx"> static void dumpAndVerifyGraph(Graph&amp; graph, const char* text)
</span><span class="cx"> {
</span><span class="cx">     GraphDumpMode modeForFinalValidate = DumpGraph;
</span><del>-    if (verboseCompilationEnabled()) {
</del><ins>+    if (verboseCompilationEnabled(graph.m_plan.mode)) {
</ins><span class="cx">         dataLog(text, &quot;\n&quot;);
</span><span class="cx">         graph.dump();
</span><span class="cx">         modeForFinalValidate = DontDumpGraph;
</span><span class="lines">@@ -149,7 +149,7 @@
</span><span class="cx">     SamplingRegion samplingRegion(&quot;DFG Compilation (Plan)&quot;);
</span><span class="cx">     CompilationScope compilationScope;
</span><span class="cx"> 
</span><del>-    if (logCompilationChanges())
</del><ins>+    if (logCompilationChanges(mode))
</ins><span class="cx">         dataLog(&quot;DFG(Plan) compiling &quot;, *codeBlock, &quot; with &quot;, mode, &quot;, number of instructions = &quot;, codeBlock-&gt;instructionCount(), &quot;\n&quot;);
</span><span class="cx"> 
</span><span class="cx">     CompilationPath path = compileInThreadImpl(longLivedState);
</span><span class="lines">@@ -183,7 +183,7 @@
</span><span class="cx"> 
</span><span class="cx"> Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState&amp; longLivedState)
</span><span class="cx"> {
</span><del>-    if (verboseCompilationEnabled() &amp;&amp; osrEntryBytecodeIndex != UINT_MAX) {
</del><ins>+    if (verboseCompilationEnabled(mode) &amp;&amp; osrEntryBytecodeIndex != UINT_MAX) {
</ins><span class="cx">         dataLog(&quot;\n&quot;);
</span><span class="cx">         dataLog(&quot;Compiler must handle OSR entry from bc#&quot;, osrEntryBytecodeIndex, &quot; with values: &quot;, mustHandleValues, &quot;\n&quot;);
</span><span class="cx">         dataLog(&quot;\n&quot;);
</span><span class="lines">@@ -230,7 +230,7 @@
</span><span class="cx">     unsigned count = 1;
</span><span class="cx">     dfg.m_fixpointState = FixpointNotConverged;
</span><span class="cx">     for (;; ++count) {
</span><del>-        if (logCompilationChanges())
</del><ins>+        if (logCompilationChanges(mode))
</ins><span class="cx">             dataLogF(&quot;DFG beginning optimization fixpoint iteration #%u.\n&quot;, count);
</span><span class="cx">         bool changed = false;
</span><span class="cx">         
</span><span class="lines">@@ -250,7 +250,7 @@
</span><span class="cx">         performCPSRethreading(dfg);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    if (logCompilationChanges())
</del><ins>+    if (logCompilationChanges(mode))
</ins><span class="cx">         dataLogF(&quot;DFG optimization fixpoint converged in %u iterations.\n&quot;, count);
</span><span class="cx"> 
</span><span class="cx">     dfg.m_fixpointState = FixpointConverged;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -177,6 +177,7 @@
</span><span class="cx">         case GetByIdFlush:
</span><span class="cx">         case GetMyArgumentByValSafe:
</span><span class="cx">         case GetByOffset:
</span><ins>+        case MultiGetByOffset:
</ins><span class="cx">         case Call:
</span><span class="cx">         case Construct:
</span><span class="cx">         case GetGlobalVar:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -253,6 +253,7 @@
</span><span class="cx">     case CheckInBounds:
</span><span class="cx">     case ConstantStoragePointer:
</span><span class="cx">     case Check:
</span><ins>+    case MultiGetByOffset:
</ins><span class="cx">         return true;
</span><span class="cx">         
</span><span class="cx">     case GetByVal:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -4689,6 +4689,7 @@
</span><span class="cx">     case Int52ToValue:
</span><span class="cx">     case CheckInBounds:
</span><span class="cx">     case ArithIMul:
</span><ins>+    case MultiGetByOffset:
</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 (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -5010,6 +5010,7 @@
</span><span class="cx">     case ExtractOSREntryLocal:
</span><span class="cx">     case CheckInBounds:
</span><span class="cx">     case ArithIMul:
</span><ins>+    case MultiGetByOffset:
</ins><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         break;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGTypeCheckHoistingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -246,6 +246,7 @@
</span><span class="cx">                 case Phantom:
</span><span class="cx">                 case HardPhantom:
</span><span class="cx">                 case MovHint:
</span><ins>+                case MultiGetByOffset:
</ins><span class="cx">                     // Don't count these uses.
</span><span class="cx">                     break;
</span><span class="cx">                     
</span><span class="lines">@@ -345,6 +346,7 @@
</span><span class="cx">                 case Phantom:
</span><span class="cx">                 case HardPhantom:
</span><span class="cx">                 case MovHint:
</span><ins>+                case MultiGetByOffset:
</ins><span class="cx">                     // Don't count these uses.
</span><span class="cx">                     break;
</span><span class="cx">                     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -137,6 +137,7 @@
</span><span class="cx">     case NewArrayWithSize:
</span><span class="cx">     case GetById:
</span><span class="cx">     case ToThis:
</span><ins>+    case MultiGetByOffset:
</ins><span class="cx">         // These are OK.
</span><span class="cx">         break;
</span><span class="cx">     case PutByIdDirect:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCompilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -247,7 +247,7 @@
</span><span class="cx">             OSRExitCompilationInfo&amp; info = state.finalizer-&gt;osrExit[i];
</span><span class="cx">             OSRExit&amp; exit = jitCode-&gt;osrExit[i];
</span><span class="cx">             
</span><del>-            if (Options::verboseCompilation())
</del><ins>+            if (verboseCompilationEnabled())
</ins><span class="cx">                 dataLog(&quot;Handling OSR stackmap #&quot;, exit.m_stackmapID, &quot; for &quot;, exit.m_codeOrigin, &quot;\n&quot;);
</span><span class="cx"> 
</span><span class="cx">             iter = recordMap.find(exit.m_stackmapID);
</span><span class="lines">@@ -269,7 +269,7 @@
</span><span class="cx">                     VirtualRegister(value.virtualRegister().offset() + localsOffset));
</span><span class="cx">             }
</span><span class="cx">             
</span><del>-            if (Options::verboseCompilation()) {
</del><ins>+            if (verboseCompilationEnabled()) {
</ins><span class="cx">                 DumpContext context;
</span><span class="cx">                 dataLog(&quot;    Exit values: &quot;, inContext(exit.m_values, &amp;context), &quot;\n&quot;);
</span><span class="cx">             }
</span><span class="lines">@@ -286,7 +286,7 @@
</span><span class="cx">         for (unsigned i = state.getByIds.size(); i--;) {
</span><span class="cx">             GetByIdDescriptor&amp; getById = state.getByIds[i];
</span><span class="cx">             
</span><del>-            if (Options::verboseCompilation())
</del><ins>+            if (verboseCompilationEnabled())
</ins><span class="cx">                 dataLog(&quot;Handling GetById stackmap #&quot;, getById.stackmapID(), &quot;\n&quot;);
</span><span class="cx">             
</span><span class="cx">             iter = recordMap.find(getById.stackmapID());
</span><span class="lines">@@ -324,7 +324,7 @@
</span><span class="cx">         for (unsigned i = state.putByIds.size(); i--;) {
</span><span class="cx">             PutByIdDescriptor&amp; putById = state.putByIds[i];
</span><span class="cx">             
</span><del>-            if (Options::verboseCompilation())
</del><ins>+            if (verboseCompilationEnabled())
</ins><span class="cx">                 dataLog(&quot;Handling PutById stackmap #&quot;, putById.stackmapID(), &quot;\n&quot;);
</span><span class="cx">             
</span><span class="cx">             iter = recordMap.find(putById.stackmapID());
</span><span class="lines">@@ -541,7 +541,7 @@
</span><span class="cx">             llvm-&gt;RunPassManager(modulePasses, state.module);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (DFG::shouldShowDisassembly() || DFG::verboseCompilationEnabled())
</del><ins>+        if (shouldShowDisassembly() || verboseCompilationEnabled())
</ins><span class="cx">             state.dumpState(&quot;after optimization&quot;);
</span><span class="cx">     
</span><span class="cx">         // FIXME: Need to add support for the case where JIT memory allocation failed.
</span><span class="lines">@@ -577,7 +577,7 @@
</span><span class="cx">     
</span><span class="cx">     state.jitCode-&gt;unwindInfo.parse(
</span><span class="cx">         state.compactUnwind, state.compactUnwindSize, state.generatedFunction);
</span><del>-    if (DFG::shouldShowDisassembly())
</del><ins>+    if (shouldShowDisassembly())
</ins><span class="cx">         dataLog(&quot;Unwind info for &quot;, CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT), &quot;:\n    &quot;, state.jitCode-&gt;unwindInfo, &quot;\n&quot;);
</span><span class="cx">     
</span><span class="cx">     if (state.stackmapsSection.size()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -464,6 +464,9 @@
</span><span class="cx">         case GetByOffset:
</span><span class="cx">             compileGetByOffset();
</span><span class="cx">             break;
</span><ins>+        case MultiGetByOffset:
+            compileMultiGetByOffset();
+            break;
</ins><span class="cx">         case PutByOffset:
</span><span class="cx">             compilePutByOffset();
</span><span class="cx">             break;
</span><span class="lines">@@ -3075,6 +3078,63 @@
</span><span class="cx">                     offsetRelativeToBase(data.offset))));
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void compileMultiGetByOffset()
+    {
+        LValue base = lowCell(m_node-&gt;child1());
+        
+        MultiGetByOffsetData&amp; data = m_node-&gt;multiGetByOffsetData();
+        
+        Vector&lt;LBasicBlock, 2&gt; blocks(data.variants.size());
+        for (unsigned i = data.variants.size(); i--;)
+            blocks[i] = FTL_NEW_BLOCK(m_out, (&quot;MultiGetByOffset case &quot;, i));
+        LBasicBlock exit = FTL_NEW_BLOCK(m_out, (&quot;MultiGetByOffset fail&quot;));
+        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;MultiGetByOffset continuation&quot;));
+        
+        Vector&lt;SwitchCase, 2&gt; cases;
+        for (unsigned i = data.variants.size(); i--;) {
+            GetByIdVariant variant = data.variants[i];
+            for (unsigned j = variant.structureSet().size(); j--;)
+                cases.append(SwitchCase(weakPointer(variant.structureSet()[j]), blocks[i]));
+        }
+        m_out.switchInstruction(m_out.loadPtr(base, m_heaps.JSCell_structure), cases, exit);
+        
+        LBasicBlock lastNext = m_out.m_nextBlock;
+        
+        Vector&lt;ValueFromBlock, 2&gt; results;
+        for (unsigned i = data.variants.size(); i--;) {
+            m_out.appendTo(blocks[i], i + 1 &lt; data.variants.size() ? blocks[i + 1] : exit);
+            
+            GetByIdVariant variant = data.variants[i];
+            LValue result;
+            if (variant.specificValue())
+                result = m_out.constInt64(JSValue::encode(variant.specificValue()));
+            else {
+                LValue propertyBase;
+                if (variant.chain())
+                    propertyBase = weakPointer(variant.chain()-&gt;terminalPrototype());
+                else
+                    propertyBase = base;
+                if (!isInlineOffset(variant.offset()))
+                    propertyBase = m_out.loadPtr(propertyBase, m_heaps.JSObject_butterfly);
+                result = m_out.load64(
+                    m_out.address(
+                        m_heaps.properties[data.identifierNumber],
+                        propertyBase,
+                        offsetRelativeToBase(variant.offset())));
+            }
+            
+            results.append(m_out.anchor(result));
+            m_out.jump(continuation);
+        }
+        
+        m_out.appendTo(exit, continuation);
+        terminate(BadCache);
+        m_out.unreachable();
+        
+        m_out.appendTo(continuation, lastNext);
+        setJSValue(m_out.phi(m_out.int64, results));
+    }
+    
</ins><span class="cx">     void compilePutByOffset()
</span><span class="cx">     {
</span><span class="cx">         StorageAccessData&amp; data =
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLStateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLState.h (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLState.h        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/ftl/FTLState.h        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(FTL_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;DFGCommon.h&quot;
</ins><span class="cx"> #include &quot;DFGGraph.h&quot;
</span><span class="cx"> #include &quot;FTLAbbreviations.h&quot;
</span><span class="cx"> #include &quot;FTLGeneratedFunction.h&quot;
</span><span class="lines">@@ -42,6 +43,16 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace FTL {
</span><span class="cx"> 
</span><ins>+inline bool verboseCompilationEnabled()
+{
+    return DFG::verboseCompilationEnabled(DFG::FTLMode);
+}
+
+inline bool showDisassembly()
+{
+    return DFG::shouldShowDisassembly(DFG::FTLMode);
+}
+
</ins><span class="cx"> class State {
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(State);
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -238,6 +238,7 @@
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*);
</span><span class="cx"> static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionFalse(ExecState*);
</span><ins>+static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*);
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(SAMPLING_FLAGS)
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
</span><span class="lines">@@ -373,6 +374,8 @@
</span><span class="cx">         
</span><span class="cx">         putDirectNativeFunction(vm, this, Identifier(&amp;vm, &quot;DFGTrue&quot;), 0, functionFalse, DFGTrue, DontEnum | JSC::Function);
</span><span class="cx">         
</span><ins>+        addFunction(vm, &quot;effectful42&quot;, functionEffectful42, 0);
+        
</ins><span class="cx">         JSArray* array = constructEmptyArray(globalExec(), 0);
</span><span class="cx">         for (size_t i = 0; i &lt; arguments.size(); ++i)
</span><span class="cx">             array-&gt;putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]));
</span><span class="lines">@@ -727,6 +730,11 @@
</span><span class="cx">     return JSValue::encode(jsBoolean(false));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*)
+{
+    return JSValue::encode(jsNumber(42));
+}
+
</ins><span class="cx"> // Use SEH for Release builds only to get rid of the crash report dialog
</span><span class="cx"> // (luckily the same tests fail in Release and Debug builds so far). Need to
</span><span class="cx"> // be in a separate main function because the jscmain function requires object
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeIntendedStructureChaincpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/IntendedStructureChain.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/IntendedStructureChain.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/runtime/IntendedStructureChain.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;StructureChain.h&quot;
</span><ins>+#include &lt;wtf/CommaPrinter.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -145,5 +146,21 @@
</span><span class="cx">         visitor.appendUnbarrieredPointer(&amp;m_vector[i]);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void IntendedStructureChain::dump(PrintStream&amp; out) const
+{
+    dumpInContext(out, 0);
+}
+
+void IntendedStructureChain::dumpInContext(PrintStream&amp; out, DumpContext* context) const
+{
+    out.print(
+        &quot;(global = &quot;, RawPointer(m_globalObject), &quot;, head = &quot;,
+        pointerDumpInContext(m_head, context), &quot;, vector = [&quot;);
+    CommaPrinter comma;
+    for (unsigned i = 0; i &lt; m_vector.size(); ++i)
+        out.print(comma, pointerDumpInContext(m_vector[i], context));
+    out.print(&quot;])&quot;);
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeIntendedStructureChainh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/IntendedStructureChain.h (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/IntendedStructureChain.h        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/runtime/IntendedStructureChain.h        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx"> class JSGlobalObject;
</span><span class="cx"> class StructureChain;
</span><span class="cx"> class VM;
</span><ins>+struct DumpContext;
</ins><span class="cx"> 
</span><span class="cx"> class IntendedStructureChain : public RefCounted&lt;IntendedStructureChain&gt; {
</span><span class="cx"> public:
</span><span class="lines">@@ -61,6 +62,8 @@
</span><span class="cx">     Structure* last() const { return m_vector.last(); }
</span><span class="cx">     
</span><span class="cx">     void visitChildren(SlotVisitor&amp;);
</span><ins>+    void dump(PrintStream&amp;) const;
+    void dumpInContext(PrintStream&amp;, DumpContext*) const;
</ins><span class="cx">     
</span><span class="cx"> private:
</span><span class="cx">     JSGlobalObject* m_globalObject;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.cpp (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.cpp        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/runtime/Options.cpp        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -189,9 +189,11 @@
</span><span class="cx">     
</span><span class="cx">     if (Options::showDisassembly()
</span><span class="cx">         || Options::showDFGDisassembly()
</span><ins>+        || Options::showFTLDisassembly()
</ins><span class="cx">         || Options::dumpBytecodeAtDFGTime()
</span><span class="cx">         || Options::dumpGraphAtEachPhase()
</span><span class="cx">         || Options::verboseCompilation()
</span><ins>+        || Options::verboseFTLCompilation()
</ins><span class="cx">         || Options::logCompilationChanges()
</span><span class="cx">         || Options::validateGraph()
</span><span class="cx">         || Options::validateGraphAtEachPhase()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -112,11 +112,13 @@
</span><span class="cx">     /* showDisassembly implies showDFGDisassembly. */ \
</span><span class="cx">     v(bool, showDisassembly, false) \
</span><span class="cx">     v(bool, showDFGDisassembly, false) \
</span><ins>+    v(bool, showFTLDisassembly, false) \
</ins><span class="cx">     v(bool, showAllDFGNodes, false) \
</span><span class="cx">     v(optionRange, bytecodeRangeToDFGCompile, 0) \
</span><span class="cx">     v(bool, dumpBytecodeAtDFGTime, false) \
</span><span class="cx">     v(bool, dumpGraphAtEachPhase, false) \
</span><span class="cx">     v(bool, verboseCompilation, false) \
</span><ins>+    v(bool, verboseFTLCompilation, false) \
</ins><span class="cx">     v(bool, logCompilationChanges, false) \
</span><span class="cx">     v(bool, printEachOSRExit, false) \
</span><span class="cx">     v(bool, validateGraph, false) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressfoldmultigetbyoffsettogetbyoffsetwithwatchpointjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/fold-multi-get-by-offset-to-get-by-offset-with-watchpoint.js (0 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/fold-multi-get-by-offset-to-get-by-offset-with-watchpoint.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/fold-multi-get-by-offset-to-get-by-offset-with-watchpoint.js        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -0,0 +1,26 @@
</span><ins>+//@ defaultNoEagerRun
+
+function foo(o) {
+    return o.f;
+}
+
+for (var i = 0; i &lt; 100; ++i) {
+    var result = foo((i &amp; 1) ? {f:1, g:2} : {g:1, f:2});
+    if (result != 2 - (i &amp; 1))
+        throw &quot;Error: bad result in warm-up loop for i = &quot; + i + &quot;: &quot; + result;
+}
+
+function bar(o) {
+    return o.g + effectful42() + foo(o);
+}
+
+noInline(bar);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = bar({f:i, g:i * 3});
+    if (result != i * 4 + 42)
+        throw &quot;Error: bad result for i = &quot; + i + &quot;: &quot; + result;
+}
+
+if (reoptimizationRetryCount(bar))
+    throw &quot;Error: reoptimized bar unexpectedly: &quot; + reoptimizationRetryCount(bar);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressfoldmultigetbyoffsettogetbyoffsetjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/fold-multi-get-by-offset-to-get-by-offset.js (0 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/fold-multi-get-by-offset-to-get-by-offset.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/fold-multi-get-by-offset-to-get-by-offset.js        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -0,0 +1,26 @@
</span><ins>+//@ defaultNoEagerRun
+
+function foo(o) {
+    return o.f;
+}
+
+for (var i = 0; i &lt; 100; ++i) {
+    var result = foo((i &amp; 1) ? {f:1, g:2} : {g:1, f:2});
+    if (result != 2 - (i &amp; 1))
+        throw &quot;Error: bad result in warm-up loop for i = &quot; + i + &quot;: &quot; + result;
+}
+
+function bar(o) {
+    return o.g + foo(o);
+}
+
+noInline(bar);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = bar({f:i, g:i * 3});
+    if (result != i * 4)
+        throw &quot;Error: bad result for i = &quot; + i + &quot;: &quot; + result;
+}
+
+if (reoptimizationRetryCount(bar))
+    throw &quot;Error: reoptimized bar unexpectedly: &quot; + reoptimizationRetryCount(bar);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressmultigetbyoffsetprotoandselfjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/multi-get-by-offset-proto-and-self.js (0 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/multi-get-by-offset-proto-and-self.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/multi-get-by-offset-proto-and-self.js        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -0,0 +1,20 @@
</span><ins>+function foo(o) {
+    return o.f;
+}
+
+noInline(foo);
+
+function Foo() { }
+Foo.prototype.f = 42;
+
+for (var i = 0; i &lt; 100000; ++i) {
+    if (i &amp; 1) {
+        var result = foo(new Foo());
+        if (result != 42)
+            throw &quot;Error: bad result for new Foo(): &quot; + result;
+    } else {
+        var result = foo({f:24});
+        if (result != 24)
+            throw &quot;Error: bad result for {f:24}: &quot; + result;
+    }
+}
</ins></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/WTF/ChangeLog        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2014-02-15  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        FTL should inline polymorphic heap accesses
+        https://bugs.webkit.org/show_bug.cgi?id=128795
+
+        Reviewed by Oliver Hunt.
+
+        * wtf/PrintStream.h:
+        (WTF::PointerDumpInContext::PointerDumpInContext):
+        (WTF::PointerDumpInContext::dump):
+        (WTF::pointerDumpInContext):
+
</ins><span class="cx"> 2014-02-16  Zan Dobersek  &lt;zdobersek@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Reintroduce const qualifiers for return types of (Filter|Transform)Iterator::operator*()
</span></span></pre></div>
<a id="trunkSourceWTFwtfPrintStreamh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/PrintStream.h (164206 => 164207)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/PrintStream.h        2014-02-17 06:26:56 UTC (rev 164206)
+++ trunk/Source/WTF/wtf/PrintStream.h        2014-02-17 06:35:32 UTC (rev 164207)
</span><span class="lines">@@ -365,6 +365,34 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename T, typename U&gt;
</span><ins>+class PointerDumpInContext {
+public:
+    PointerDumpInContext(const T* ptr, U* context)
+        : m_ptr(ptr)
+        , m_context(context)
+    {
+    }
+    
+    void dump(PrintStream&amp; out) const
+    {
+        if (m_ptr)
+            m_ptr-&gt;dumpInContext(out, m_context);
+        else
+            out.print(&quot;(null)&quot;);
+    }
+
+private:
+    const T* m_ptr;
+    U* m_context;
+};
+
+template&lt;typename T, typename U&gt;
+PointerDumpInContext&lt;T, U&gt; pointerDumpInContext(const T* ptr, U* context)
+{
+    return PointerDumpInContext&lt;T, U&gt;(ptr, context);
+}
+
+template&lt;typename T, typename U&gt;
</ins><span class="cx"> class ValueIgnoringContext {
</span><span class="cx"> public:
</span><span class="cx">     ValueIgnoringContext(const U&amp; value)
</span><span class="lines">@@ -396,6 +424,7 @@
</span><span class="cx"> using WTF::ignoringContext;
</span><span class="cx"> using WTF::inContext;
</span><span class="cx"> using WTF::pointerDump;
</span><ins>+using WTF::pointerDumpInContext;
</ins><span class="cx"> 
</span><span class="cx"> #endif // PrintStream_h
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>