<!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<AbstractStateType>::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 <fpizlo@apple.com>
+
+ 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 <fpizlo@apple.com>
</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 "PASS" messages, followed by "TEST COMPLETE".
+
+
+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>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="resources/regress-pre.js"></script>
+<script src="script-tests/polymorphic-get-by-id.js"></script>
+<script src="resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</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 < 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 < 10000; ++i) {
+ var result = foo((i & 1) ? o : p);
+ if (result != ((i & 1) ? 100 : 200))
+ throw "Error: bad result for i = " + i + ": " + result;
+}
+
+var q = {g:3, h:4, f:5};
+var result = foo(q);
+if (result != 500)
+ throw "Error: bad result at end: " + 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 <fpizlo@apple.com>
+
+ 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<AbstractStateType>::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 <fpizlo@apple.com>
</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"> <ClCompile Include="..\bytecode\DFGExitProfile.cpp" />
</span><span class="cx"> <ClCompile Include="..\bytecode\ExecutionCounter.cpp" />
</span><span class="cx"> <ClCompile Include="..\bytecode\ExitKind.cpp" />
</span><ins>+ <ClCompile Include="..\bytecode\ExitingJITType.cpp" />
</ins><span class="cx"> <ClCompile Include="..\bytecode\GetByIdStatus.cpp" />
</span><ins>+ <ClCompile Include="..\bytecode\GetByIdVariant.cpp" />
</ins><span class="cx"> <ClCompile Include="..\bytecode\InlineCallFrameSet.cpp" />
</span><span class="cx"> <ClCompile Include="..\bytecode\JumpTable.cpp" />
</span><span class="cx"> <ClCompile Include="..\bytecode\LazyOperandValueProfile.cpp" />
</span><span class="lines">@@ -840,6 +842,7 @@
</span><span class="cx"> <ClInclude Include="..\bytecode\ExitKind.h" />
</span><span class="cx"> <ClInclude Include="..\bytecode\ExpressionRangeInfo.h" />
</span><span class="cx"> <ClInclude Include="..\bytecode\GetByIdStatus.h" />
</span><ins>+ <ClInclude Include="..\bytecode\GetByIdVariant.h" />
</ins><span class="cx"> <ClInclude Include="..\bytecode\HandlerInfo.h" />
</span><span class="cx"> <ClInclude Include="..\bytecode\InlineCallFrameSet.h" />
</span><span class="cx"> <ClInclude Include="..\bytecode\Instruction.h" />
</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 = "<group>"; };
+                0F0332C118B01763005F979A /* GetByIdVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetByIdVariant.cpp; sourceTree = "<group>"; };
+                0F0332C218B01763005F979A /* GetByIdVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetByIdVariant.h; sourceTree = "<group>"; };
</ins><span class="cx">                 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = "<group>"; };
</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 = "<group>"; };
</span><span class="cx">                 0F2FCCF718A60070001A27F8 /* DFGThreadData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGThreadData.cpp; path = dfg/DFGThreadData.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0F2FCCF818A60070001A27F8 /* DFGThreadData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGThreadData.h; path = dfg/DFGThreadData.h; sourceTree = "<group>"; };
</span><ins>+                0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeOrigin.h; path = dfg/DFGNodeOrigin.h; sourceTree = "<group>"; };
</ins><span class="cx">                 0F300B7918AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGIntegerCheckCombiningPhase.cpp; path = dfg/DFGIntegerCheckCombiningPhase.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0F300B7A18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGIntegerCheckCombiningPhase.h; path = dfg/DFGIntegerCheckCombiningPhase.h; sourceTree = "<group>"; };
</span><del>-                0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeOrigin.h; path = dfg/DFGNodeOrigin.h; sourceTree = "<group>"; };
</del><span class="cx">                 0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGUseKind.cpp; path = dfg/DFGUseKind.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0F34B14816D4200E001CDA5A /* DFGUseKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGUseKind.h; path = dfg/DFGUseKind.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F34B14B16D43E0C001CDA5A /* PolymorphicAccessStructureList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolymorphicAccessStructureList.h; sourceTree = "<group>"; };
</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(" !! frequent exits: ");
</span><span class="cx"> CommaPrinter comma;
</span><span class="cx"> for (unsigned i = 0; i < exitSites.size(); ++i)
</span><del>- out.print(comma, exitSites[i].kind());
</del><ins>+ out.print(comma, exitSites[i].kind(), " ", 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 "config.h"
+#include "ExitingJITType.h"
+
+#include <wtf/PrintStream.h>
+
+namespace WTF {
+
+using namespace JSC;
+
+void printInternal(PrintStream& out, ExitingJITType type)
+{
+ switch (type) {
+ case ExitFromAnything:
+ out.print("FromAnything");
+ return;
+ case ExitFromDFG:
+ out.print("FromDFG");
+ return;
+ case ExitFromFTL:
+ out.print("FromFTL");
+ 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&, 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 "LLIntData.h"
</span><span class="cx"> #include "LowLevelInterpreter.h"
</span><span class="cx"> #include "JSCInlines.h"
</span><ins>+#include <wtf/ListDump.h>
</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& result, CodeBlock* profiledBlock, StringImpl* uid)
</del><ins>+bool GetByIdStatus::computeForChain(CodeBlock* profiledBlock, StringImpl* uid, PassRefPtr<IntendedStructureChain> passedChain)
</ins><span class="cx"> {
</span><span class="cx"> #if ENABLE(JIT)
</span><ins>+ RefPtr<IntendedStructureChain> 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->isStillValid())
- return;
</del><ins>+ if (!chain->isStillValid())
+ return false;
</ins><span class="cx">
</span><del>- if (result.m_chain->head()->takesSlowPathInDFGForImpureProperty())
- return;
- size_t chainSize = result.m_chain->size();
</del><ins>+ if (chain->head()->takesSlowPathInDFGForImpureProperty())
+ return false;
+ size_t chainSize = chain->size();
</ins><span class="cx"> for (size_t i = 0; i < chainSize; i++) {
</span><del>- if (result.m_chain->at(i)->takesSlowPathInDFGForImpureProperty())
- return;
</del><ins>+ if (chain->at(i)->takesSlowPathInDFGForImpureProperty())
+ return false;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- JSObject* currentObject = result.m_chain->terminalPrototype();
- Structure* currentStructure = result.m_chain->last();
</del><ins>+ JSObject* currentObject = chain->terminalPrototype();
+ Structure* currentStructure = chain->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->getConcurrently(
</del><ins>+
+ PropertyOffset offset = currentStructure->getConcurrently(
</ins><span class="cx"> *profiledBlock->vm(), uid, attributesIgnored, specificValue);
</span><span class="cx"> if (currentStructure->isDictionary())
</span><span class="cx"> specificValue = 0;
</span><del>- if (!isValidOffset(result.m_offset))
- return;
-
- result.m_structureSet.add(result.m_chain->head());
- result.m_specificValue = JSValue(specificValue);
-#else
- UNUSED_PARAM(result);
</del><ins>+ if (!isValidOffset(offset))
+ return false;
+
+ m_variants.append(
+ GetByIdVariant(StructureSet(chain->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& 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->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->getConcurrently(
</del><ins>+ GetByIdVariant variant;
+ variant.m_offset = structure->getConcurrently(
</ins><span class="cx"> *profiledBlock->vm(), uid, attributesIgnored, specificValue);
</span><ins>+ if (!isValidOffset(variant.m_offset))
+ return GetByIdStatus(TakesSlowPath, true);
+
</ins><span class="cx"> if (structure->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 < listSize; ++i) {
- ASSERT(list->list[i].isDirect);
</del><ins>+ for (int listIndex = 0; listIndex < listSize; ++listIndex) {
+ ASSERT(list->list[listIndex].isDirect);
</ins><span class="cx">
</span><del>- Structure* structure = list->list[i].base.get();
</del><ins>+ Structure* structure = list->list[listIndex].base.get();
</ins><span class="cx"> if (structure->takesSlowPathInDFGForImpureProperty())
</span><span class="cx"> return GetByIdStatus(TakesSlowPath, true);
</span><del>-
- if (result.m_structureSet.contains(structure))
</del><ins>+
+ if (list->list[listIndex].chain.get()) {
+ RefPtr<IntendedStructureChain> chain = adoptRef(new IntendedStructureChain(
+ profiledBlock, structure, list->list[listIndex].chain.get(),
+ list->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->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 < result.m_variants.size(); ++variantIndex) {
+ GetByIdVariant& 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->u.getByIdChain.isDirect)
</span><span class="cx"> return GetByIdStatus(MakesCalls, true);
</span><del>- result.m_chain = adoptRef(new IntendedStructureChain(
</del><ins>+ RefPtr<IntendedStructureChain> chain = adoptRef(new IntendedStructureChain(
</ins><span class="cx"> profiledBlock,
</span><span class="cx"> stubInfo->u.getByIdChain.baseObjectStructure.get(),
</span><span class="cx"> stubInfo->u.getByIdChain.chain.get(),
</span><span class="cx"> stubInfo->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->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->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&, 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->getConcurrently(vm, uid, attributes, specificValue);
- if (!isValidOffset(result.m_offset))
</del><ins>+ PropertyOffset offset = structure->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 & Accessor)
</span><span class="cx"> return GetByIdStatus(MakesCalls);
</span><span class="cx"> if (structure->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& out) const
+{
+ out.print("(");
+ switch (m_state) {
+ case NoInformation:
+ out.print("NoInformation");
+ break;
+ case Simple:
+ out.print("Simple");
+ break;
+ case TakesSlowPath:
+ out.print("TakesSlowPath");
+ break;
+ case MakesCalls:
+ out.print("MakesCalls");
+ break;
+ }
+ out.print(", ", listDump(m_variants), ", seenInJIT = ", m_wasSeenInJIT, ")");
+}
+
</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 "CodeOrigin.h"
</span><span class="cx"> #include "ConcurrentJITLock.h"
</span><span class="cx"> #include "ExitingJITType.h"
</span><del>-#include "IntendedStructureChain.h"
-#include "PropertyOffset.h"
-#include "StructureSet.h"
</del><ins>+#include "GetByIdVariant.h"
</ins><span class="cx"> #include "StructureStubInfo.h"
</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& structureSet = StructureSet(),
- PropertyOffset offset = invalidOffset, JSValue specificValue = JSValue(), PassRefPtr<IntendedStructureChain> chain = nullptr)
</del><ins>+ State state, bool wasSeenInJIT, const GetByIdVariant& 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&, 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<GetByIdVariant, 1>& variants() const { return m_variants; }
+ const GetByIdVariant& at(size_t index) const { return m_variants[index]; }
+ const GetByIdVariant& 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& structureSet() const { return m_structureSet; }
- IntendedStructureChain* chain() const { return const_cast<IntendedStructureChain*>(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&) const;
+
</ins><span class="cx"> private:
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx"> static bool hasExitSite(const ConcurrentJITLocker&, 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&, CodeBlock*, StructureStubInfo*, StringImpl* uid);
</span><span class="cx"> #endif
</span><del>- static void computeForChain(GetByIdStatus& result, CodeBlock*, StringImpl* uid);
</del><ins>+ bool computeForChain(CodeBlock*, StringImpl* uid, PassRefPtr<IntendedStructureChain>);
</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<IntendedStructureChain> m_chain;
- JSValue m_specificValue;
- PropertyOffset m_offset;
</del><ins>+ Vector<GetByIdVariant, 1> 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 "config.h"
+#include "GetByIdVariant.h"
+
+#include "JSCInlines.h"
+
+namespace JSC {
+
+void GetByIdVariant::dump(PrintStream& out) const
+{
+ dumpInContext(out, 0);
+}
+
+void GetByIdVariant::dumpInContext(PrintStream& out, DumpContext* context) const
+{
+ if (!isSet()) {
+ out.print("<empty>");
+ return;
+ }
+
+ out.print(
+ "<", inContext(structureSet(), context), ", ",
+ pointerDumpInContext(chain(), context), ", ",
+ inContext(specificValue(), context), ", ", offset(), ">");
+}
+
+} // 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 "IntendedStructureChain.h"
+#include "JSCJSValue.h"
+#include "PropertyOffset.h"
+#include "StructureSet.h"
+
+namespace JSC {
+
+class GetByIdStatus;
+struct DumpContext;
+
+class GetByIdVariant {
+public:
+ GetByIdVariant(
+ const StructureSet& structureSet = StructureSet(),
+ PropertyOffset offset = invalidOffset, JSValue specificValue = JSValue(),
+ PassRefPtr<IntendedStructureChain> 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& structureSet() const { return m_structureSet; }
+ IntendedStructureChain* chain() const { return const_cast<IntendedStructureChain*>(m_chain.get()); }
+ JSValue specificValue() const { return m_specificValue; }
+ PropertyOffset offset() const { return m_offset; }
+
+ void dump(PrintStream&) const;
+ void dumpInContext(PrintStream&, DumpContext*) const;
+
+private:
+ friend class GetByIdStatus;
+
+ StructureSet m_structureSet;
+ RefPtr<IntendedStructureChain> 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->identifierNumber()]);
</span><del>- if (status.isSimple()) {
</del><ins>+ if (status.isSimple() && 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->child1(), status.structureSet());
</del><ins>+ filter(node->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& value = forNode(node->child1());
+ ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
+
+ if (Structure* structure = value.bestProvenStructure()) {
+ bool done = false;
+ for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) {
+ const GetByIdVariant& variant = node->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->multiGetByOffsetData().variants.size(); i--;)
+ set.addAll(node->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&);
</span><ins>+ Node* emitPrototypeChecks(const GetByIdVariant&);
</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& variant)
+{
+ Node* base = 0;
+ m_graph.chains().addLazily(variant.chain());
+ Structure* currentStructure = variant.structureSet().singletonStructure();
+ JSObject* currentObject = 0;
+ for (unsigned i = 0; i < variant.chain()->size(); ++i) {
+ currentObject = asObject(currentStructure->prototypeForLookup(m_inlineStackTop->m_codeBlock));
+ currentStructure = variant.chain()->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& 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() > 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->variants = getByIdStatus.variants();
+ data->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()->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 < getByIdStatus.chain()->size(); ++i) {
- currentObject = asObject(currentStructure->prototypeForLookup(m_inlineStackTop->m_codeBlock));
- currentStructure = getByIdStatus.chain()->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->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->op()) {
</span><span class="cx"> case GetByOffset:
</span><del>- if (node->child1() == child1
</del><ins>+ if (node->child2() == base
</ins><span class="cx"> && m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber == identifierNumber)
</span><span class="cx"> return node;
</span><span class="cx"> break;
</span><span class="cx">
</span><ins>+ case MultiGetByOffset:
+ if (node->child1() == base
+ && node->multiGetByOffsetData().identifierNumber == identifierNumber)
+ return node;
+ break;
+
</ins><span class="cx"> case PutByOffset:
</span><span class="cx"> if (m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber == identifierNumber) {
</span><del>- if (node->child1() == child1) // Must be same property storage.
</del><ins>+ if (node->child2() == base) // Must be same property storage.
</ins><span class="cx"> return node->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->storageAccessDataIndex()].identifierNumber, node->child1().node()));
</del><ins>+ setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber, node->child2().node()));
</ins><span class="cx"> break;
</span><span class="cx">
</span><ins>+ case MultiGetByOffset:
+ if (cseMode == StoreElimination)
+ break;
+ setReplacement(getByOffsetLoadElimination(node->multiGetByOffsetData().identifierNumber, node->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->storageAccessDataIndex()].identifierNumber));
</span><span class="cx"> return;
</span><span class="cx">
</span><ins>+ case MultiGetByOffset:
+ read(AbstractHeap(NamedProperties, node->multiGetByOffsetData().identifierNumber));
+ return;
+
</ins><span class="cx"> case PutByOffset:
</span><span class="cx"> write(AbstractHeap(NamedProperties, graph.m_storageAccessData[node->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 <wtf/Platform.h>
</span><span class="cx">
</span><ins>+#include "DFGCompilationMode.h"
+
</ins><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">
</span><span class="cx"> #include "CodeOrigin.h"
</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) && 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) && 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->child1();
+ Node* child = childEdge.node();
+ MultiGetByOffsetData& data = node->multiGetByOffsetData();
+
+ Structure* structure = m_state.forNode(child).bestProvenStructure();
+ if (!structure)
+ break;
+
+ for (unsigned i = data.variants.size(); i--;) {
+ const GetByIdVariant& 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->origin;
</del><span class="cx"> Edge childEdge = node->child1();
</span><span class="cx"> Node* child = childEdge.node();
</span><span class="cx"> unsigned identifierNumber = node->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 & ~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->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& variant, unsigned identifierNumber)
+ {
+ NodeOrigin origin = node->origin;
+ Edge childEdge = node->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 & ~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->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 && (debugger->isStepping() || codeBlock->baselineAlternative()->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("DFG(Driver) compiling ", *codeBlock, " with ", mode, ", number of instructions = ", codeBlock->instructionCount(), "\n");
</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->callback = callback;
</span><del>- if (logCompilationChanges())
</del><ins>+ if (logCompilationChanges(mode))
</ins><span class="cx"> dataLog("Deferring DFG compilation of ", *codeBlock, " with queue length ", worklist->queueLength(), ".\n");
</span><span class="cx"> worklist->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<CellUse>(node->child1());
+ break;
+ }
+
</ins><span class="cx"> case PutByOffset: {
</span><span class="cx"> if (!node->child1()->hasStorageResult())
</span><span class="cx"> fixEdge<KnownCellUse>(node->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, "id", storageAccessData.identifierNumber, "{", identifiers()[storageAccessData.identifierNumber], "}");
</span><span class="cx"> out.print(", ", static_cast<ptrdiff_t>(storageAccessData.offset));
</span><span class="cx"> }
</span><ins>+ if (node->hasMultiGetByOffsetData()) {
+ MultiGetByOffsetData& data = node->multiGetByOffsetData();
+ out.print(comma, "id", data.identifierNumber, "{", identifiers()[data.identifierNumber], "}");
+ for (unsigned i = 0; i < data.variants.size(); ++i)
+ out.print(comma, inContext(data.variants[i], context));
+ }
</ins><span class="cx"> ASSERT(node->hasVariableAccessData(*this) == node->hasLocal(*this));
</span><span class="cx"> if (node->hasVariableAccessData(*this)) {
</span><span class="cx"> VariableAccessData* variableAccessData = node->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->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<StructureTransitionData, 8> m_structureTransitionData;
</span><span class="cx"> SegmentedVector<NewArrayBufferData, 4> m_newArrayBufferData;
</span><span class="cx"> SegmentedVector<SwitchData, 4> m_switchData;
</span><ins>+ Bag<MultiGetByOffsetData> m_multiGetByOffsetData;
</ins><span class="cx"> Vector<InlineVariableData, 4> m_inlineVariableData;
</span><span class="cx"> OwnPtr<InlineCallFrameSet> m_inlineCallFrames;
</span><span class="cx"> HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> 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 "DFGNodeOrigin.h"
</span><span class="cx"> #include "DFGNodeType.h"
</span><span class="cx"> #include "DFGVariableAccessData.h"
</span><ins>+#include "GetByIdVariant.h"
</ins><span class="cx"> #include "JSCJSValue.h"
</span><span class="cx"> #include "Operands.h"
</span><span class="cx"> #include "SpeculatedType.h"
</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<GetByIdVariant, 2> 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& multiGetByOffsetData()
+ {
+ return *reinterpret_cast<MultiGetByOffsetData*>(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& 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& phase)
</span><span class="cx"> {
</span><span class="cx"> bool result = phase.run();
</span><del>- if (result && logCompilationChanges())
</del><ins>+ if (result && logCompilationChanges(phase.graph().m_plan.mode))
</ins><span class="cx"> dataLogF("Phase %s changed the IR.\n", 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& 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, "\n");
</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("DFG Compilation (Plan)");
</span><span class="cx"> CompilationScope compilationScope;
</span><span class="cx">
</span><del>- if (logCompilationChanges())
</del><ins>+ if (logCompilationChanges(mode))
</ins><span class="cx"> dataLog("DFG(Plan) compiling ", *codeBlock, " with ", mode, ", number of instructions = ", codeBlock->instructionCount(), "\n");
</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& longLivedState)
</span><span class="cx"> {
</span><del>- if (verboseCompilationEnabled() && osrEntryBytecodeIndex != UINT_MAX) {
</del><ins>+ if (verboseCompilationEnabled(mode) && osrEntryBytecodeIndex != UINT_MAX) {
</ins><span class="cx"> dataLog("\n");
</span><span class="cx"> dataLog("Compiler must handle OSR entry from bc#", osrEntryBytecodeIndex, " with values: ", mustHandleValues, "\n");
</span><span class="cx"> dataLog("\n");
</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("DFG beginning optimization fixpoint iteration #%u.\n", 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("DFG optimization fixpoint converged in %u iterations.\n", 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& info = state.finalizer->osrExit[i];
</span><span class="cx"> OSRExit& exit = jitCode->osrExit[i];
</span><span class="cx">
</span><del>- if (Options::verboseCompilation())
</del><ins>+ if (verboseCompilationEnabled())
</ins><span class="cx"> dataLog("Handling OSR stackmap #", exit.m_stackmapID, " for ", exit.m_codeOrigin, "\n");
</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(" Exit values: ", inContext(exit.m_values, &context), "\n");
</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& getById = state.getByIds[i];
</span><span class="cx">
</span><del>- if (Options::verboseCompilation())
</del><ins>+ if (verboseCompilationEnabled())
</ins><span class="cx"> dataLog("Handling GetById stackmap #", getById.stackmapID(), "\n");
</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& putById = state.putByIds[i];
</span><span class="cx">
</span><del>- if (Options::verboseCompilation())
</del><ins>+ if (verboseCompilationEnabled())
</ins><span class="cx"> dataLog("Handling PutById stackmap #", putById.stackmapID(), "\n");
</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->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("after optimization");
</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->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("Unwind info for ", CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT), ":\n ", state.jitCode->unwindInfo, "\n");
</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->child1());
+
+ MultiGetByOffsetData& data = m_node->multiGetByOffsetData();
+
+ Vector<LBasicBlock, 2> blocks(data.variants.size());
+ for (unsigned i = data.variants.size(); i--;)
+ blocks[i] = FTL_NEW_BLOCK(m_out, ("MultiGetByOffset case ", i));
+ LBasicBlock exit = FTL_NEW_BLOCK(m_out, ("MultiGetByOffset fail"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("MultiGetByOffset continuation"));
+
+ Vector<SwitchCase, 2> 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<ValueFromBlock, 2> results;
+ for (unsigned i = data.variants.size(); i--;) {
+ m_out.appendTo(blocks[i], i + 1 < 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()->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& 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 "DFGCommon.h"
</ins><span class="cx"> #include "DFGGraph.h"
</span><span class="cx"> #include "FTLAbbreviations.h"
</span><span class="cx"> #include "FTLGeneratedFunction.h"
</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(&vm, "DFGTrue"), 0, functionFalse, DFGTrue, DontEnum | JSC::Function);
</span><span class="cx">
</span><ins>+ addFunction(vm, "effectful42", functionEffectful42, 0);
+
</ins><span class="cx"> JSArray* array = constructEmptyArray(globalExec(), 0);
</span><span class="cx"> for (size_t i = 0; i < arguments.size(); ++i)
</span><span class="cx"> array->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 "CodeBlock.h"
</span><span class="cx"> #include "JSCInlines.h"
</span><span class="cx"> #include "StructureChain.h"
</span><ins>+#include <wtf/CommaPrinter.h>
</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(&m_vector[i]);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void IntendedStructureChain::dump(PrintStream& out) const
+{
+ dumpInContext(out, 0);
+}
+
+void IntendedStructureChain::dumpInContext(PrintStream& out, DumpContext* context) const
+{
+ out.print(
+ "(global = ", RawPointer(m_globalObject), ", head = ",
+ pointerDumpInContext(m_head, context), ", vector = [");
+ CommaPrinter comma;
+ for (unsigned i = 0; i < m_vector.size(); ++i)
+ out.print(comma, pointerDumpInContext(m_vector[i], context));
+ out.print("])");
+}
+
</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<IntendedStructureChain> {
</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&);
</span><ins>+ void dump(PrintStream&) const;
+ void dumpInContext(PrintStream&, 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 < 100; ++i) {
+ var result = foo((i & 1) ? {f:1, g:2} : {g:1, f:2});
+ if (result != 2 - (i & 1))
+ throw "Error: bad result in warm-up loop for i = " + i + ": " + result;
+}
+
+function bar(o) {
+ return o.g + effectful42() + foo(o);
+}
+
+noInline(bar);
+
+for (var i = 0; i < 100000; ++i) {
+ var result = bar({f:i, g:i * 3});
+ if (result != i * 4 + 42)
+ throw "Error: bad result for i = " + i + ": " + result;
+}
+
+if (reoptimizationRetryCount(bar))
+ throw "Error: reoptimized bar unexpectedly: " + 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 < 100; ++i) {
+ var result = foo((i & 1) ? {f:1, g:2} : {g:1, f:2});
+ if (result != 2 - (i & 1))
+ throw "Error: bad result in warm-up loop for i = " + i + ": " + result;
+}
+
+function bar(o) {
+ return o.g + foo(o);
+}
+
+noInline(bar);
+
+for (var i = 0; i < 100000; ++i) {
+ var result = bar({f:i, g:i * 3});
+ if (result != i * 4)
+ throw "Error: bad result for i = " + i + ": " + result;
+}
+
+if (reoptimizationRetryCount(bar))
+ throw "Error: reoptimized bar unexpectedly: " + 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 < 100000; ++i) {
+ if (i & 1) {
+ var result = foo(new Foo());
+ if (result != 42)
+ throw "Error: bad result for new Foo(): " + result;
+ } else {
+ var result = foo({f:24});
+ if (result != 24)
+ throw "Error: bad result for {f:24}: " + 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 <fpizlo@apple.com>
+
+ 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 <zdobersek@igalia.com>
</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<typename T, typename U>
</span><ins>+class PointerDumpInContext {
+public:
+ PointerDumpInContext(const T* ptr, U* context)
+ : m_ptr(ptr)
+ , m_context(context)
+ {
+ }
+
+ void dump(PrintStream& out) const
+ {
+ if (m_ptr)
+ m_ptr->dumpInContext(out, m_context);
+ else
+ out.print("(null)");
+ }
+
+private:
+ const T* m_ptr;
+ U* m_context;
+};
+
+template<typename T, typename U>
+PointerDumpInContext<T, U> pointerDumpInContext(const T* ptr, U* context)
+{
+ return PointerDumpInContext<T, U>(ptr, context);
+}
+
+template<typename T, typename U>
</ins><span class="cx"> class ValueIgnoringContext {
</span><span class="cx"> public:
</span><span class="cx"> ValueIgnoringContext(const U& 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>