<!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>[170141] branches/ftlopt</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/170141">170141</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-06-18 21:34:25 -0700 (Wed, 18 Jun 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>DFG AI and constant folder should be able to precisely prune MultiGetByOffset/MultiPutByOffset even if the base structure abstract value is not a singleton
https://bugs.webkit.org/show_bug.cgi?id=133918
Reviewed by Mark Hahnenberg.
Source/JavaScriptCore:
This also adds pruning of PutStructure, since I basically had no choice but
to implement such logic within MultiPutByOffset.
Also adds a bunch of PutById cache status dumping to bytecode dumping.
* bytecode/GetByIdVariant.cpp:
(JSC::GetByIdVariant::dumpInContext):
* bytecode/GetByIdVariant.h:
(JSC::GetByIdVariant::structureSet):
* bytecode/PutByIdVariant.h:
(JSC::PutByIdVariant::oldStructure):
* bytecode/StructureSet.cpp:
(JSC::StructureSet::filter):
(JSC::StructureSet::filterArrayModes):
* bytecode/StructureSet.h:
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGAbstractValue.cpp:
(JSC::DFG::AbstractValue::changeStructure):
(JSC::DFG::AbstractValue::contains):
* dfg/DFGAbstractValue.h:
(JSC::DFG::AbstractValue::couldBeType):
(JSC::DFG::AbstractValue::isType):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
(JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
(JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
(JSC::DFG::ConstantFoldingPhase::addBaseCheck):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::freezeStrong):
* dfg/DFGGraph.h:
* dfg/DFGStructureAbstractValue.h:
(JSC::DFG::StructureAbstractValue::operator=):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset):
* tests/stress/fold-multi-get-by-offset-to-get-by-offset-without-folding-the-structure-check.js: Added.
(foo):
(fu):
(bar):
(baz):
(.bar):
(.baz):
* tests/stress/fold-multi-put-by-offset-to-put-by-offset-without-folding-the-structure-check.js: Added.
(foo):
(fu):
(bar):
(baz):
(.bar):
(.baz):
* tests/stress/prune-multi-put-by-offset-replace-or-transition-variant.js: Added.
(foo):
(fu):
(bar):
(baz):
(.bar):
(.baz):
LayoutTests:
* js/regress/fold-multi-get-by-offset-to-get-by-offset-expected.txt: Added.
* js/regress/fold-multi-get-by-offset-to-get-by-offset.html: Added.
* js/regress/fold-multi-get-by-offset-to-poly-get-by-offset-expected.txt: Added.
* js/regress/fold-multi-get-by-offset-to-poly-get-by-offset.html: Added.
* js/regress/fold-multi-put-by-offset-to-poly-put-by-offset-expected.txt: Added.
* js/regress/fold-multi-put-by-offset-to-poly-put-by-offset.html: Added.
* js/regress/fold-multi-put-by-offset-to-put-by-offset-expected.txt: Added.
* js/regress/fold-multi-put-by-offset-to-put-by-offset.html: Added.
* js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset-expected.txt: Added.
* js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.html: Added.
* js/regress/fold-put-structure-expected.txt: Added.
* js/regress/fold-put-structure.html: Added.
* js/regress/script-tests/fold-multi-get-by-offset-to-get-by-offset.js: Added.
(foo):
(fu):
(bar):
(.bar):
* js/regress/script-tests/fold-multi-get-by-offset-to-poly-get-by-offset.js: Added.
(foo):
(fu):
(bar):
(.bar):
* js/regress/script-tests/fold-multi-put-by-offset-to-poly-put-by-offset.js: Added.
(foo):
(fu):
(bar):
(.bar):
* js/regress/script-tests/fold-multi-put-by-offset-to-put-by-offset.js: Added.
(foo):
(fu):
(bar):
(.bar):
* js/regress/script-tests/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.js: Added.
(foo):
(fu):
(bar):
(.bar):
* js/regress/script-tests/fold-put-structure.js: Added.
(foo):
(fu):
(bar):
(.bar):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#branchesftloptLayoutTestsChangeLog">branches/ftlopt/LayoutTests/ChangeLog</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreChangeLog">branches/ftlopt/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorebytecodeCodeBlockcpp">branches/ftlopt/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorebytecodeCodeBlockh">branches/ftlopt/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorebytecodeGetByIdVariantcpp">branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorebytecodeGetByIdVarianth">branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdVariant.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorebytecodePutByIdVarianth">branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdVariant.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorebytecodeStructureSetcpp">branches/ftlopt/Source/JavaScriptCore/bytecode/StructureSet.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorebytecodeStructureSeth">branches/ftlopt/Source/JavaScriptCore/bytecode/StructureSet.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGAbstractValuecpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractValue.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGAbstractValueh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractValue.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGGraphcpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGGraph.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGGraphh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGGraph.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGStructureAbstractValueh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">branches/ftlopt/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#branchesftloptLayoutTestsjsregressfoldmultigetbyoffsettogetbyoffsetexpectedtxt">branches/ftlopt/LayoutTests/js/regress/fold-multi-get-by-offset-to-get-by-offset-expected.txt</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressfoldmultigetbyoffsettogetbyoffsethtml">branches/ftlopt/LayoutTests/js/regress/fold-multi-get-by-offset-to-get-by-offset.html</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressfoldmultigetbyoffsettopolygetbyoffsetexpectedtxt">branches/ftlopt/LayoutTests/js/regress/fold-multi-get-by-offset-to-poly-get-by-offset-expected.txt</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressfoldmultigetbyoffsettopolygetbyoffsethtml">branches/ftlopt/LayoutTests/js/regress/fold-multi-get-by-offset-to-poly-get-by-offset.html</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressfoldmultiputbyoffsettopolyputbyoffsetexpectedtxt">branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-poly-put-by-offset-expected.txt</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressfoldmultiputbyoffsettopolyputbyoffsethtml">branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-poly-put-by-offset.html</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressfoldmultiputbyoffsettoputbyoffsetexpectedtxt">branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-put-by-offset-expected.txt</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressfoldmultiputbyoffsettoputbyoffsethtml">branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-put-by-offset.html</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressfoldmultiputbyoffsettoreplaceortransitionputbyoffsetexpectedtxt">branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset-expected.txt</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressfoldmultiputbyoffsettoreplaceortransitionputbyoffsethtml">branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.html</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressfoldputstructureexpectedtxt">branches/ftlopt/LayoutTests/js/regress/fold-put-structure-expected.txt</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressfoldputstructurehtml">branches/ftlopt/LayoutTests/js/regress/fold-put-structure.html</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressscripttestsfoldmultigetbyoffsettogetbyoffsetjs">branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-get-by-offset-to-get-by-offset.js</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressscripttestsfoldmultigetbyoffsettopolygetbyoffsetjs">branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-get-by-offset-to-poly-get-by-offset.js</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressscripttestsfoldmultiputbyoffsettopolyputbyoffsetjs">branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-poly-put-by-offset.js</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressscripttestsfoldmultiputbyoffsettoputbyoffsetjs">branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-put-by-offset.js</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressscripttestsfoldmultiputbyoffsettoreplaceortransitionputbyoffsetjs">branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.js</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressscripttestsfoldputstructurejs">branches/ftlopt/LayoutTests/js/regress/script-tests/fold-put-structure.js</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoretestsstressfoldmultigetbyoffsettogetbyoffsetwithoutfoldingthestructurecheckjs">branches/ftlopt/Source/JavaScriptCore/tests/stress/fold-multi-get-by-offset-to-get-by-offset-without-folding-the-structure-check.js</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoretestsstressfoldmultiputbyoffsettoputbyoffsetwithoutfoldingthestructurecheckjs">branches/ftlopt/Source/JavaScriptCore/tests/stress/fold-multi-put-by-offset-to-put-by-offset-without-folding-the-structure-check.js</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoretestsstressprunemultiputbyoffsetreplaceortransitionvariantjs">branches/ftlopt/Source/JavaScriptCore/tests/stress/prune-multi-put-by-offset-replace-or-transition-variant.js</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchesftloptLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/LayoutTests/ChangeLog (170140 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/ChangeLog        2014-06-19 04:16:04 UTC (rev 170140)
+++ branches/ftlopt/LayoutTests/ChangeLog        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -1,3 +1,53 @@
</span><ins>+2014-06-18 Filip Pizlo <fpizlo@apple.com>
+
+ DFG AI and constant folder should be able to precisely prune MultiGetByOffset/MultiPutByOffset even if the base structure abstract value is not a singleton
+ https://bugs.webkit.org/show_bug.cgi?id=133918
+
+ Reviewed by Mark Hahnenberg.
+
+ * js/regress/fold-multi-get-by-offset-to-get-by-offset-expected.txt: Added.
+ * js/regress/fold-multi-get-by-offset-to-get-by-offset.html: Added.
+ * js/regress/fold-multi-get-by-offset-to-poly-get-by-offset-expected.txt: Added.
+ * js/regress/fold-multi-get-by-offset-to-poly-get-by-offset.html: Added.
+ * js/regress/fold-multi-put-by-offset-to-poly-put-by-offset-expected.txt: Added.
+ * js/regress/fold-multi-put-by-offset-to-poly-put-by-offset.html: Added.
+ * js/regress/fold-multi-put-by-offset-to-put-by-offset-expected.txt: Added.
+ * js/regress/fold-multi-put-by-offset-to-put-by-offset.html: Added.
+ * js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset-expected.txt: Added.
+ * js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.html: Added.
+ * js/regress/fold-put-structure-expected.txt: Added.
+ * js/regress/fold-put-structure.html: Added.
+ * js/regress/script-tests/fold-multi-get-by-offset-to-get-by-offset.js: Added.
+ (foo):
+ (fu):
+ (bar):
+ (.bar):
+ * js/regress/script-tests/fold-multi-get-by-offset-to-poly-get-by-offset.js: Added.
+ (foo):
+ (fu):
+ (bar):
+ (.bar):
+ * js/regress/script-tests/fold-multi-put-by-offset-to-poly-put-by-offset.js: Added.
+ (foo):
+ (fu):
+ (bar):
+ (.bar):
+ * js/regress/script-tests/fold-multi-put-by-offset-to-put-by-offset.js: Added.
+ (foo):
+ (fu):
+ (bar):
+ (.bar):
+ * js/regress/script-tests/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.js: Added.
+ (foo):
+ (fu):
+ (bar):
+ (.bar):
+ * js/regress/script-tests/fold-put-structure.js: Added.
+ (foo):
+ (fu):
+ (bar):
+ (.bar):
+
</ins><span class="cx"> 2014-06-17 Filip Pizlo <fpizlo@apple.com>
</span><span class="cx">
</span><span class="cx"> [ftlopt] DFG put_by_id should inline accesses with a slightly polymorphic base
</span></span></pre></div>
<a id="branchesftloptLayoutTestsjsregressfoldmultigetbyoffsettogetbyoffsetexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-multi-get-by-offset-to-get-by-offset-expected.txt (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-multi-get-by-offset-to-get-by-offset-expected.txt         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-multi-get-by-offset-to-get-by-offset-expected.txt        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/fold-multi-get-by-offset-to-get-by-offset
+
+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="branchesftloptLayoutTestsjsregressfoldmultigetbyoffsettogetbyoffsethtml"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-multi-get-by-offset-to-get-by-offset.html (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-multi-get-by-offset-to-get-by-offset.html         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-multi-get-by-offset-to-get-by-offset.html        2014-06-19 04:34:25 UTC (rev 170141)
</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/fold-multi-get-by-offset-to-get-by-offset.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="branchesftloptLayoutTestsjsregressfoldmultigetbyoffsettopolygetbyoffsetexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-multi-get-by-offset-to-poly-get-by-offset-expected.txt (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-multi-get-by-offset-to-poly-get-by-offset-expected.txt         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-multi-get-by-offset-to-poly-get-by-offset-expected.txt        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/fold-multi-get-by-offset-to-poly-get-by-offset
+
+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="branchesftloptLayoutTestsjsregressfoldmultigetbyoffsettopolygetbyoffsethtml"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-multi-get-by-offset-to-poly-get-by-offset.html (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-multi-get-by-offset-to-poly-get-by-offset.html         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-multi-get-by-offset-to-poly-get-by-offset.html        2014-06-19 04:34:25 UTC (rev 170141)
</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/fold-multi-get-by-offset-to-poly-get-by-offset.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="branchesftloptLayoutTestsjsregressfoldmultiputbyoffsettopolyputbyoffsetexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-poly-put-by-offset-expected.txt (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-poly-put-by-offset-expected.txt         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-poly-put-by-offset-expected.txt        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/fold-multi-put-by-offset-to-poly-put-by-offset
+
+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="branchesftloptLayoutTestsjsregressfoldmultiputbyoffsettopolyputbyoffsethtml"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-poly-put-by-offset.html (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-poly-put-by-offset.html         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-poly-put-by-offset.html        2014-06-19 04:34:25 UTC (rev 170141)
</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/fold-multi-put-by-offset-to-poly-put-by-offset.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="branchesftloptLayoutTestsjsregressfoldmultiputbyoffsettoputbyoffsetexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-put-by-offset-expected.txt (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-put-by-offset-expected.txt         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-put-by-offset-expected.txt        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/fold-multi-put-by-offset-to-put-by-offset
+
+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="branchesftloptLayoutTestsjsregressfoldmultiputbyoffsettoputbyoffsethtml"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-put-by-offset.html (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-put-by-offset.html         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-put-by-offset.html        2014-06-19 04:34:25 UTC (rev 170141)
</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/fold-multi-put-by-offset-to-put-by-offset.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="branchesftloptLayoutTestsjsregressfoldmultiputbyoffsettoreplaceortransitionputbyoffsetexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset-expected.txt (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset-expected.txt         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset-expected.txt        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset
+
+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="branchesftloptLayoutTestsjsregressfoldmultiputbyoffsettoreplaceortransitionputbyoffsethtml"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.html (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.html         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.html        2014-06-19 04:34:25 UTC (rev 170141)
</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/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.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="branchesftloptLayoutTestsjsregressfoldputstructureexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-put-structure-expected.txt (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-put-structure-expected.txt         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-put-structure-expected.txt        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/fold-put-structure
+
+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="branchesftloptLayoutTestsjsregressfoldputstructurehtml"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-put-structure.html (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-put-structure.html         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-put-structure.html        2014-06-19 04:34:25 UTC (rev 170141)
</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/fold-put-structure.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="branchesftloptLayoutTestsjsregressscripttestsfoldmultigetbyoffsettogetbyoffsetjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-get-by-offset-to-get-by-offset.js (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-get-by-offset-to-get-by-offset.js         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-get-by-offset-to-get-by-offset.js        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -0,0 +1,43 @@
</span><ins>+function foo(o) {
+ return o.f;
+}
+
+function fu(o) {
+ return o.e;
+}
+
+function bar(f, o) {
+ return f(o);
+}
+
+for (var i = 0; i < 100; ++i) {
+ foo({f:1, e:2});
+ foo({e:1, f:2});
+ foo({d:1, e:2, f:3});
+ fu({f:1, e:2});
+ fu({e:1, f:2});
+ fu({d:1, e:2, f:3});
+}
+
+for (var i = 0; i < 100; ++i) {
+ bar(foo, {f:1});
+ bar(function() { }, null);
+ bar(function() { return 42 }, null);
+}
+
+(function(f, o) {
+ var result = 0;
+ var n = 1000000;
+ for (var i = 0; i < n; ++i) {
+ var p;
+ if (i == n - 1) // Defeat LICM.
+ p = {f: 42, e: 42};
+ else
+ p = o;
+ result += fu(p);
+ result += bar(f, p);
+ }
+ if (result != (n - 1) * (o.f + o.e) + 42 * 2)
+ throw "Error: bad result: " + result;
+})(foo, {f:42, e:2});
+
</ins></span></pre></div>
<a id="branchesftloptLayoutTestsjsregressscripttestsfoldmultigetbyoffsettopolygetbyoffsetjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-get-by-offset-to-poly-get-by-offset.js (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-get-by-offset-to-poly-get-by-offset.js         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-get-by-offset-to-poly-get-by-offset.js        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -0,0 +1,41 @@
</span><ins>+function foo(o) {
+ return o.f;
+}
+
+function fu(o) {
+ return o.e;
+}
+
+function bar(f, o) {
+ return f(o);
+}
+
+for (var i = 0; i < 100; ++i) {
+ foo({f:1, e:2});
+ foo({e:1, f:2});
+ foo({d:1, e:2, f:3});
+ fu({f:1, e:2});
+ fu({e:1, f:2});
+ fu({d:1, e:2, f:3});
+}
+
+for (var i = 0; i < 100; ++i) {
+ bar(foo, {f:1});
+ bar(function() { }, null);
+ bar(function() { return 42 }, null);
+}
+
+(function(f, o, p) {
+ var result = 0;
+ var n = 1000000;
+ for (var i = 0; i < n; ++i) {
+ result += fu(o);
+ result += bar(f, o);
+ var tmp = o;
+ o = p;
+ p = tmp;
+ }
+ if (result != n * o.f + n * o.e)
+ throw "Error: bad result: " + result;
+})(foo, {f:42, e:23}, {f:42, e:23, g:100});
+
</ins></span></pre></div>
<a id="branchesftloptLayoutTestsjsregressscripttestsfoldmultiputbyoffsettopolyputbyoffsetjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-poly-put-by-offset.js (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-poly-put-by-offset.js         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-poly-put-by-offset.js        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -0,0 +1,47 @@
</span><ins>+function foo(o) {
+ o.f = 1;
+}
+
+function fu(o) {
+ o.e = 2;
+}
+
+function bar(f, o) {
+ f(o);
+}
+
+for (var i = 0; i < 100; ++i) {
+ foo({f:1, e:2});
+ foo({e:1, f:2});
+ foo({d:1, e:2, f:3});
+ fu({f:1, e:2});
+ fu({e:1, f:2});
+ fu({d:1, e:2, f:3});
+}
+
+for (var i = 0; i < 100; ++i) {
+ bar(foo, {f:1});
+ bar(function() { }, null);
+ bar(function() { return 42 }, null);
+}
+
+(function(f, o, p) {
+ var result = 0;
+ var n = 1000000;
+ for (var i = 0; i < n; ++i) {
+ fu(o);
+ bar(f, o);
+ var tmp = o;
+ o = p;
+ p = tmp;
+ }
+ if (o.e != 2)
+ throw "Error: bad value in o.e: " + o.e;
+ if (o.f != 1)
+ throw "Error: bad value in o.f: " + o.f;
+ if (p.e != 2)
+ throw "Error: bad value in p.e: " + p.e;
+ if (p.f != 1)
+ throw "Error: bad value in p.f: " + p.f;
+})(foo, {f:42, e:23}, {f:42, e:23, g:100});
+
</ins></span></pre></div>
<a id="branchesftloptLayoutTestsjsregressscripttestsfoldmultiputbyoffsettoputbyoffsetjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-put-by-offset.js (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-put-by-offset.js         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-put-by-offset.js        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+function foo(o) {
+ o.f = 1;
+}
+
+function fu(o) {
+ o.e = 2;
+}
+
+function bar(f, o) {
+ f(o);
+}
+
+for (var i = 0; i < 100; ++i) {
+ foo({f:1, e:2});
+ foo({e:1, f:2});
+ foo({d:1, e:2, f:3});
+ fu({f:1, e:2});
+ fu({e:1, f:2});
+ fu({d:1, e:2, f:3});
+}
+
+for (var i = 0; i < 100; ++i) {
+ bar(foo, {f:1});
+ bar(function() { }, null);
+ bar(function() { return 42 }, null);
+}
+
+(function(f, o) {
+ var result = 0;
+ var n = 1000000;
+ for (var i = 0; i < n; ++i) {
+ fu(o);
+ bar(f, o);
+ }
+ if (o.e != 2)
+ throw "Error: bad value in o.e: " + o.e;
+ if (o.f != 1)
+ throw "Error: bad value in o.f: " + o.f;
+})(foo, {f:42, e:23});
+
</ins></span></pre></div>
<a id="branchesftloptLayoutTestsjsregressscripttestsfoldmultiputbyoffsettoreplaceortransitionputbyoffsetjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.js (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.js         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.js        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -0,0 +1,50 @@
</span><ins>+function foo(o) {
+ o.f = 1;
+}
+
+function fu(o) {
+ o.e = 2;
+}
+
+function bar(f, o) {
+ f(o);
+}
+
+for (var i = 0; i < 100; ++i) {
+ foo({f:1, e:2});
+ foo({e:1, f:2});
+ foo({d:1, e:2, f:3});
+ fu({f:1, e:2});
+ fu({e:1, f:2});
+ fu({d:1, e:2, f:3});
+}
+
+for (var i = 0; i < 100; ++i) {
+ bar(foo, {f:1});
+ bar(function() { }, null);
+ bar(function() { return 42 }, null);
+}
+
+(function(f, o) {
+ var result = 0;
+ var n = 1000000;
+ var p;
+ for (var i = 0; i < n; ++i) {
+ var q;
+ if (i & 1)
+ q = o;
+ else
+ p = q = {e:61};
+ fu(q);
+ bar(f, q);
+ }
+ if (o.e != 2)
+ throw "Error: bad value in o.e: " + o.e;
+ if (o.f != 1)
+ throw "Error: bad value in o.f: " + o.f;
+ if (p.e != 2)
+ throw "Error: bad value in p.e: " + p.e;
+ if (p.f != 1)
+ throw "Error: bad value in p.f: " + p.f;
+})(foo, {e:23, f:42});
+
</ins></span></pre></div>
<a id="branchesftloptLayoutTestsjsregressscripttestsfoldputstructurejs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/script-tests/fold-put-structure.js (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/script-tests/fold-put-structure.js         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/script-tests/fold-put-structure.js        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+function foo(o) {
+ o.f = 1;
+}
+
+function fu(o) {
+ o.e = 2;
+}
+
+function bar(f, o) {
+ f(o);
+}
+
+for (var i = 0; i < 100; ++i) {
+ foo({e:2});
+ foo({e:1, f:2});
+ fu({f:1, e:2});
+ fu({e:1, f:2});
+ fu({d:1, e:2, f:3});
+}
+
+for (var i = 0; i < 100; ++i) {
+ bar(foo, {e:1});
+ bar(function() { }, null);
+ bar(function() { return 42 }, null);
+}
+
+(function(f, o) {
+ var result = 0;
+ var n = 1000000;
+ for (var i = 0; i < n; ++i) {
+ fu(o);
+ bar(f, o);
+ }
+ if (o.e != 2)
+ throw "Error: bad value in o.e: " + o.e;
+ if (o.f != 1)
+ throw "Error: bad value in o.f: " + o.f;
+})(foo, {e:42, f:23});
+
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/ChangeLog (170140 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/ChangeLog        2014-06-19 04:16:04 UTC (rev 170140)
+++ branches/ftlopt/Source/JavaScriptCore/ChangeLog        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -1,3 +1,67 @@
</span><ins>+2014-06-18 Filip Pizlo <fpizlo@apple.com>
+
+ DFG AI and constant folder should be able to precisely prune MultiGetByOffset/MultiPutByOffset even if the base structure abstract value is not a singleton
+ https://bugs.webkit.org/show_bug.cgi?id=133918
+
+ Reviewed by Mark Hahnenberg.
+
+ This also adds pruning of PutStructure, since I basically had no choice but
+ to implement such logic within MultiPutByOffset.
+
+ Also adds a bunch of PutById cache status dumping to bytecode dumping.
+
+ * bytecode/GetByIdVariant.cpp:
+ (JSC::GetByIdVariant::dumpInContext):
+ * bytecode/GetByIdVariant.h:
+ (JSC::GetByIdVariant::structureSet):
+ * bytecode/PutByIdVariant.h:
+ (JSC::PutByIdVariant::oldStructure):
+ * bytecode/StructureSet.cpp:
+ (JSC::StructureSet::filter):
+ (JSC::StructureSet::filterArrayModes):
+ * bytecode/StructureSet.h:
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGAbstractValue.cpp:
+ (JSC::DFG::AbstractValue::changeStructure):
+ (JSC::DFG::AbstractValue::contains):
+ * dfg/DFGAbstractValue.h:
+ (JSC::DFG::AbstractValue::couldBeType):
+ (JSC::DFG::AbstractValue::isType):
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::foldConstants):
+ (JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
+ (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
+ (JSC::DFG::ConstantFoldingPhase::addBaseCheck):
+ * dfg/DFGGraph.cpp:
+ (JSC::DFG::Graph::freezeStrong):
+ * dfg/DFGGraph.h:
+ * dfg/DFGStructureAbstractValue.h:
+ (JSC::DFG::StructureAbstractValue::operator=):
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset):
+ * tests/stress/fold-multi-get-by-offset-to-get-by-offset-without-folding-the-structure-check.js: Added.
+ (foo):
+ (fu):
+ (bar):
+ (baz):
+ (.bar):
+ (.baz):
+ * tests/stress/fold-multi-put-by-offset-to-put-by-offset-without-folding-the-structure-check.js: Added.
+ (foo):
+ (fu):
+ (bar):
+ (baz):
+ (.bar):
+ (.baz):
+ * tests/stress/prune-multi-put-by-offset-replace-or-transition-variant.js: Added.
+ (foo):
+ (fu):
+ (bar):
+ (baz):
+ (.bar):
+ (.baz):
+
</ins><span class="cx"> 2014-06-18 Mark Hahnenberg <mhahnenberg@apple.com>
</span><span class="cx">
</span><span class="cx"> Remove CompoundType and LeafType
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/CodeBlock.cpp (170140 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2014-06-19 04:16:04 UTC (rev 170140)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -402,6 +402,120 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void CodeBlock::printPutByIdCacheStatus(PrintStream& out, ExecState* exec, int location, const StubInfoMap& map)
+{
+ Instruction* instruction = instructions().begin() + location;
+
+ const Identifier& ident = identifier(instruction[2].u.operand);
+
+ UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations.
+
+#if ENABLE(LLINT)
+ if (Structure* structure = instruction[4].u.structure.get()) {
+ switch (exec->interpreter()->getOpcodeID(instruction[0].u.opcode)) {
+ case op_put_by_id:
+ case op_put_by_id_out_of_line:
+ out.print(" llint(");
+ dumpStructure(out, "struct", exec, structure, ident);
+ out.print(")");
+ break;
+
+ case op_put_by_id_transition_direct:
+ case op_put_by_id_transition_normal:
+ case op_put_by_id_transition_direct_out_of_line:
+ case op_put_by_id_transition_normal_out_of_line:
+ out.print(" llint(");
+ dumpStructure(out, "prev", exec, structure, ident);
+ out.print(", ");
+ dumpStructure(out, "next", exec, instruction[6].u.structure.get(), ident);
+ if (StructureChain* chain = instruction[7].u.structureChain.get()) {
+ out.print(", ");
+ dumpChain(out, exec, chain, ident);
+ }
+ out.print(")");
+ break;
+
+ default:
+ out.print(" llint(unknown)");
+ break;
+ }
+ }
+#endif
+
+#if ENABLE(JIT)
+ if (StructureStubInfo* stubPtr = map.get(CodeOrigin(location))) {
+ StructureStubInfo& stubInfo = *stubPtr;
+ if (stubInfo.resetByGC)
+ out.print(" (Reset By GC)");
+
+ if (stubInfo.seen) {
+ out.printf(" jit(");
+
+ switch (stubInfo.accessType) {
+ case access_put_by_id_replace:
+ out.print("replace, ");
+ dumpStructure(out, "struct", exec, stubInfo.u.putByIdReplace.baseObjectStructure.get(), ident);
+ break;
+ case access_put_by_id_transition_normal:
+ case access_put_by_id_transition_direct:
+ out.print("transition, ");
+ dumpStructure(out, "prev", exec, stubInfo.u.putByIdTransition.previousStructure.get(), ident);
+ out.print(", ");
+ dumpStructure(out, "next", exec, stubInfo.u.putByIdTransition.structure.get(), ident);
+ if (StructureChain* chain = stubInfo.u.putByIdTransition.chain.get()) {
+ out.print(", ");
+ dumpChain(out, exec, chain, ident);
+ }
+ break;
+ case access_put_by_id_list: {
+ out.printf("list = [");
+ PolymorphicPutByIdList* list = stubInfo.u.putByIdList.list;
+ CommaPrinter comma;
+ for (unsigned i = 0; i < list->size(); ++i) {
+ out.print(comma, "(");
+ const PutByIdAccess& access = list->at(i);
+
+ if (access.isReplace()) {
+ out.print("replace, ");
+ dumpStructure(out, "struct", exec, access.oldStructure(), ident);
+ } else if (access.isSetter()) {
+ out.print("setter, ");
+ dumpStructure(out, "struct", exec, access.oldStructure(), ident);
+ } else if (access.isCustom()) {
+ out.print("custom, ");
+ dumpStructure(out, "struct", exec, access.oldStructure(), ident);
+ } else if (access.isTransition()) {
+ out.print("transition, ");
+ dumpStructure(out, "prev", exec, access.oldStructure(), ident);
+ out.print(", ");
+ dumpStructure(out, "next", exec, access.newStructure(), ident);
+ if (access.chain()) {
+ out.print(", ");
+ dumpChain(out, exec, access.chain(), ident);
+ }
+ } else
+ out.print("unknown");
+
+ out.print(")");
+ }
+ out.print("]");
+ break;
+ }
+ case access_unset:
+ out.printf("unset");
+ break;
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ break;
+ }
+ out.printf(")");
+ }
+ }
+#else
+ UNUSED_PARAM(map);
+#endif
+}
+
</ins><span class="cx"> void CodeBlock::printCallOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op, CacheDumpMode cacheDumpMode, bool& hasPrintedProfiling, const CallLinkInfoMap& map)
</span><span class="cx"> {
</span><span class="cx"> int dst = (++it)->u.operand;
</span><span class="lines">@@ -926,26 +1040,32 @@
</span><span class="cx"> }
</span><span class="cx"> case op_put_by_id: {
</span><span class="cx"> printPutByIdOp(out, exec, location, it, "put_by_id");
</span><ins>+ printPutByIdCacheStatus(out, exec, location, stubInfos);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case op_put_by_id_out_of_line: {
</span><span class="cx"> printPutByIdOp(out, exec, location, it, "put_by_id_out_of_line");
</span><ins>+ printPutByIdCacheStatus(out, exec, location, stubInfos);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case op_put_by_id_transition_direct: {
</span><span class="cx"> printPutByIdOp(out, exec, location, it, "put_by_id_transition_direct");
</span><ins>+ printPutByIdCacheStatus(out, exec, location, stubInfos);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case op_put_by_id_transition_direct_out_of_line: {
</span><span class="cx"> printPutByIdOp(out, exec, location, it, "put_by_id_transition_direct_out_of_line");
</span><ins>+ printPutByIdCacheStatus(out, exec, location, stubInfos);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case op_put_by_id_transition_normal: {
</span><span class="cx"> printPutByIdOp(out, exec, location, it, "put_by_id_transition_normal");
</span><ins>+ printPutByIdCacheStatus(out, exec, location, stubInfos);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case op_put_by_id_transition_normal_out_of_line: {
</span><span class="cx"> printPutByIdOp(out, exec, location, it, "put_by_id_transition_normal_out_of_line");
</span><ins>+ printPutByIdCacheStatus(out, exec, location, stubInfos);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case op_put_getter_setter: {
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/CodeBlock.h (170140 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/CodeBlock.h        2014-06-19 04:16:04 UTC (rev 170140)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/CodeBlock.h        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -989,6 +989,7 @@
</span><span class="cx"> enum CacheDumpMode { DumpCaches, DontDumpCaches };
</span><span class="cx"> void printCallOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op, CacheDumpMode, bool& hasPrintedProfiling, const CallLinkInfoMap&);
</span><span class="cx"> void printPutByIdOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);
</span><ins>+ void printPutByIdCacheStatus(PrintStream&, ExecState*, int location, const StubInfoMap&);
</ins><span class="cx"> void printLocationAndOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);
</span><span class="cx"> void printLocationOpAndRegisterOperand(PrintStream&, ExecState*, int location, const Instruction*& it, const char* op, int operand);
</span><span class="cx">
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodeGetByIdVariantcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp (170140 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp        2014-06-19 04:16:04 UTC (rev 170140)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -108,12 +108,14 @@
</span><span class="cx">
</span><span class="cx"> out.print(
</span><span class="cx"> "<", inContext(structureSet(), context), ", ",
</span><del>- "[", listDumpInContext(m_constantChecks, context), "], ",
- "alternateBase = ", inContext(JSValue(m_alternateBase), context), ", ",
- "specificValue = ", inContext(specificValue(), context), ", ",
- "offset = ", offset());
</del><ins>+ "[", listDumpInContext(m_constantChecks, context), "]");
+ if (m_alternateBase)
+ out.print(", alternateBase = ", inContext(JSValue(m_alternateBase), context));
+ if (specificValue())
+ out.print(", specificValue = ", inContext(specificValue(), context));
+ out.print(", offset = ", offset());
</ins><span class="cx"> if (m_callLinkStatus)
</span><del>- out.print("call = ", *m_callLinkStatus);
</del><ins>+ out.print(", call = ", *m_callLinkStatus);
</ins><span class="cx"> out.print(">");
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodeGetByIdVarianth"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdVariant.h (170140 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdVariant.h        2014-06-19 04:16:04 UTC (rev 170140)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdVariant.h        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -55,6 +55,7 @@
</span><span class="cx"> bool isSet() const { return !!m_structureSet.size(); }
</span><span class="cx"> bool operator!() const { return !isSet(); }
</span><span class="cx"> const StructureSet& structureSet() const { return m_structureSet; }
</span><ins>+ StructureSet& structureSet() { return m_structureSet; }
</ins><span class="cx"> const ConstantStructureCheckVector& constantChecks() const { return m_constantChecks; }
</span><span class="cx"> JSObject* alternateBase() const { return m_alternateBase; }
</span><span class="cx"> JSValue specificValue() const { return m_specificValue; }
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodePutByIdVarianth"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdVariant.h (170140 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdVariant.h        2014-06-19 04:16:04 UTC (rev 170140)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdVariant.h        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -87,6 +87,12 @@
</span><span class="cx"> return m_oldStructure;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ StructureSet& oldStructure()
+ {
+ ASSERT(kind() == Transition || kind() == Replace);
+ return m_oldStructure;
+ }
+
</ins><span class="cx"> Structure* oldStructureForTransition() const;
</span><span class="cx">
</span><span class="cx"> Structure* newStructure() const
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodeStructureSetcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/StructureSet.cpp (170140 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/StructureSet.cpp        2014-06-19 04:16:04 UTC (rev 170140)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/StructureSet.cpp        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #include "config.h"
</span><span class="cx"> #include "StructureSet.h"
</span><span class="cx">
</span><ins>+#include "DFGAbstractValue.h"
</ins><span class="cx"> #include <wtf/CommaPrinter.h>
</span><span class="cx">
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -160,6 +161,80 @@
</span><span class="cx"> clear();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+namespace {
+
+class StructureAbstractValueContains {
+public:
+ StructureAbstractValueContains(const DFG::StructureAbstractValue& value)
+ : m_value(value)
+ {
+ }
+
+ bool operator()(Structure* structure)
+ {
+ return m_value.contains(structure);
+ }
+private:
+ const DFG::StructureAbstractValue& m_value;
+};
+
+class SpeculatedTypeContains {
+public:
+ SpeculatedTypeContains(SpeculatedType type)
+ : m_type(type)
+ {
+ }
+
+ bool operator()(Structure* structure)
+ {
+ return m_type & speculationFromStructure(structure);
+ }
+private:
+ SpeculatedType m_type;
+};
+
+class ArrayModesContains {
+public:
+ ArrayModesContains(ArrayModes arrayModes)
+ : m_arrayModes(arrayModes)
+ {
+ }
+
+ bool operator()(Structure* structure)
+ {
+ return m_arrayModes & arrayModeFromStructure(structure);
+ }
+private:
+ ArrayModes m_arrayModes;
+};
+
+} // anonymous namespace
+
+void StructureSet::filter(const DFG::StructureAbstractValue& other)
+{
+ StructureAbstractValueContains functor(other);
+ genericFilter(functor);
+}
+
+void StructureSet::filter(SpeculatedType type)
+{
+ SpeculatedTypeContains functor(type);
+ genericFilter(functor);
+}
+
+void StructureSet::filterArrayModes(ArrayModes arrayModes)
+{
+ ArrayModesContains functor(arrayModes);
+ genericFilter(functor);
+}
+
+void StructureSet::filter(const DFG::AbstractValue& other)
+{
+ filter(other.m_structure);
+ filter(other.m_type);
+ filterArrayModes(other.m_arrayModes);
+}
+
</ins><span class="cx"> bool StructureSet::isSubsetOf(const StructureSet& other) const
</span><span class="cx"> {
</span><span class="cx"> if (isThin()) {
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodeStructureSeth"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/StructureSet.h (170140 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/StructureSet.h        2014-06-19 04:16:04 UTC (rev 170140)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/StructureSet.h        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx">
</span><span class="cx"> namespace DFG {
</span><span class="cx"> class StructureAbstractValue;
</span><ins>+struct AbstractValue;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> class StructureSet {
</span><span class="lines">@@ -96,6 +97,11 @@
</span><span class="cx"> void filter(const StructureSet&);
</span><span class="cx"> void exclude(const StructureSet&);
</span><span class="cx">
</span><ins>+ void filter(const DFG::StructureAbstractValue&);
+ void filter(SpeculatedType);
+ void filterArrayModes(ArrayModes);
+ void filter(const DFG::AbstractValue&);
+
</ins><span class="cx"> template<typename Functor>
</span><span class="cx"> void genericFilter(Functor& functor)
</span><span class="cx"> {
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (170140 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-06-19 04:16:04 UTC (rev 170140)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -1445,9 +1445,13 @@
</span><span class="cx">
</span><span class="cx"> case PutStructure:
</span><span class="cx"> if (!forNode(node->child1()).m_structure.isClear()) {
</span><del>- observeTransition(
- clobberLimit, node->transition()->previous, node->transition()->next);
- forNode(node->child1()).set(m_graph, node->transition()->next);
</del><ins>+ if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next)
+ m_state.setFoundConstants(true);
+ else {
+ observeTransition(
+ clobberLimit, node->transition()->previous, node->transition()->next);
+ forNode(node->child1()).changeStructure(m_graph, node->transition()->next);
+ }
</ins><span class="cx"> }
</span><span class="cx"> break;
</span><span class="cx"> case GetButterfly:
</span><span class="lines">@@ -1576,39 +1580,45 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case MultiGetByOffset: {
</span><del>- AbstractValue& value = forNode(node->child1());
- ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
-
- // This should just filter down the cases in MultiGetByOffset. If that results in all
- // cases having the same offset then we should strength reduce it to a CheckStructure +
- // GetByOffset.
- // https://bugs.webkit.org/show_bug.cgi?id=133229
- if (Structure* structure = value.m_structure.onlyStructure()) {
- 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.alternateBase())
- break;
-
- filter(value, structure);
- forNode(node).makeHeapTop();
- m_state.setFoundConstants(true);
- done = true;
- break;
</del><ins>+ // This code will filter the base value in a manner that is possibly different (either more
+ // or less precise) than the way it would be filtered if this was strength-reduced to a
+ // CheckStructure. This is fine. It's legal for different passes over the code to prove
+ // different things about the code, so long as all of them are sound. That even includes
+ // one guy proving that code should never execute (due to a contradiction) and another guy
+ // not finding that contradiction. If someone ever proved that there would be a
+ // contradiction then there must always be a contradiction even if subsequent passes don't
+ // realize it. This is the case here.
+
+ // Ordinarily you have to be careful with calling setFoundConstants()
+ // because of the effect on compile times, but this node is FTL-only.
+ m_state.setFoundConstants(true);
+
+ AbstractValue base = forNode(node->child1());
+ StructureSet baseSet;
+ AbstractValue result;
+ for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) {
+ GetByIdVariant& variant = node->multiGetByOffsetData().variants[i];
+ StructureSet set = variant.structureSet();
+ set.filter(base);
+ if (set.isEmpty())
+ continue;
+ baseSet.merge(set);
+ if (!variant.specificValue()) {
+ result.makeHeapTop();
+ continue;
</ins><span class="cx"> }
</span><del>- if (done)
- break;
</del><ins>+ AbstractValue thisResult;
+ thisResult.set(
+ m_graph,
+ *m_graph.freeze(variant.specificValue()),
+ m_state.structureClobberState());
+ result.merge(thisResult);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- StructureSet set;
- for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;)
- set.merge(node->multiGetByOffsetData().variants[i].structureSet());
</del><ins>+ if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
+ m_state.setIsValid(false);
</ins><span class="cx">
</span><del>- filter(node->child1(), set);
- forNode(node).makeHeapTop();
</del><ins>+ forNode(node) = result;
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1617,58 +1627,36 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case MultiPutByOffset: {
</span><del>- AbstractValue& value = forNode(node->child1());
- ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
-
- // This should just filter down the cases in MultiPutByOffset. If that results in either
- // one case, or nothing but replace cases and they have the same offset, then we should
- // just strength reduce it to the appropriate combination of CheckStructure,
- // [Re]AllocatePropertyStorage, PutStructure, and PutByOffset.
- // https://bugs.webkit.org/show_bug.cgi?id=133229
- if (Structure* structure = value.m_structure.onlyStructure()) {
- bool done = false;
- for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
- const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
- if (!variant.oldStructure().contains(structure))
- continue;
-
- if (variant.kind() == PutByIdVariant::Replace) {
- filter(node->child1(), structure);
- m_state.setFoundConstants(true);
- done = true;
- break;
- }
-
- ASSERT(variant.kind() == PutByIdVariant::Transition);
- clobberStructures(clobberLimit);
- forNode(node->child1()).set(m_graph, variant.newStructure());
- m_state.setFoundConstants(true);
- done = true;
- break;
- }
- if (done)
- break;
- }
-
- StructureSet oldSet;
</del><span class="cx"> StructureSet newSet;
</span><span class="cx"> TransitionVector transitions;
</span><ins>+
+ // Ordinarily you have to be careful with calling setFoundConstants()
+ // because of the effect on compile times, but this node is FTL-only.
+ m_state.setFoundConstants(true);
+
+ AbstractValue base = forNode(node->child1());
+
</ins><span class="cx"> for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
</span><span class="cx"> const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
</span><del>- oldSet.merge(variant.oldStructure());
</del><ins>+ StructureSet thisSet = variant.oldStructure();
+ thisSet.filter(base);
+ if (thisSet.isEmpty())
+ continue;
</ins><span class="cx"> if (variant.kind() == PutByIdVariant::Transition) {
</span><del>- transitions.append(
- Transition(variant.oldStructureForTransition(), variant.newStructure()));
</del><ins>+ if (thisSet.onlyStructure() != variant.newStructure()) {
+ transitions.append(
+ Transition(variant.oldStructureForTransition(), variant.newStructure()));
+ } // else this is really a replace.
</ins><span class="cx"> newSet.add(variant.newStructure());
</span><span class="cx"> } else {
</span><span class="cx"> ASSERT(variant.kind() == PutByIdVariant::Replace);
</span><del>- newSet.merge(variant.oldStructure());
</del><ins>+ newSet.merge(thisSet);
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>- filter(node->child1(), oldSet);
</del><span class="cx"> observeTransitions(clobberLimit, transitions);
</span><del>- forNode(node->child1()).set(m_graph, newSet);
</del><ins>+ if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
+ m_state.setIsValid(false);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGAbstractValuecpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractValue.cpp (170140 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractValue.cpp        2014-06-19 04:16:04 UTC (rev 170140)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractValue.cpp        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -179,6 +179,17 @@
</span><span class="cx"> return normalizeClarity(graph);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+FiltrationResult AbstractValue::changeStructure(Graph& graph, const StructureSet& other)
+{
+ m_type &= other.speculationFromStructures();
+ m_arrayModes = other.arrayModesFromStructures();
+ m_structure = other;
+
+ filterValueByType();
+
+ return normalizeClarity(graph);
+}
+
</ins><span class="cx"> FiltrationResult AbstractValue::filterArrayModes(ArrayModes arrayModes)
</span><span class="cx"> {
</span><span class="cx"> ASSERT(arrayModes);
</span><span class="lines">@@ -229,6 +240,13 @@
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+bool AbstractValue::contains(Structure* structure) const
+{
+ return couldBeType(speculationFromStructure(structure))
+ && (m_arrayModes & arrayModeFromStructure(structure))
+ && m_structure.contains(structure);
+}
+
</ins><span class="cx"> FiltrationResult AbstractValue::filter(const AbstractValue& other)
</span><span class="cx"> {
</span><span class="cx"> m_type &= other.m_type;
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGAbstractValueh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractValue.h (170140 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractValue.h        2014-06-19 04:16:04 UTC (rev 170140)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractValue.h        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -267,12 +267,12 @@
</span><span class="cx"> checkConsistency();
</span><span class="cx"> }
</span><span class="cx">
</span><del>- bool couldBeType(SpeculatedType desiredType)
</del><ins>+ bool couldBeType(SpeculatedType desiredType) const
</ins><span class="cx"> {
</span><span class="cx"> return !!(m_type & desiredType);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- bool isType(SpeculatedType desiredType)
</del><ins>+ bool isType(SpeculatedType desiredType) const
</ins><span class="cx"> {
</span><span class="cx"> return !(m_type & ~desiredType);
</span><span class="cx"> }
</span><span class="lines">@@ -284,6 +284,10 @@
</span><span class="cx">
</span><span class="cx"> FiltrationResult filter(const AbstractValue&);
</span><span class="cx">
</span><ins>+ FiltrationResult changeStructure(Graph&, const StructureSet&);
+
+ bool contains(Structure*) const;
+
</ins><span class="cx"> bool validate(JSValue value) const
</span><span class="cx"> {
</span><span class="cx"> if (isHeapTop())
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (170140 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2014-06-19 04:16:04 UTC (rev 170140)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -125,6 +125,15 @@
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ case PutStructure: {
+ if (m_state.forNode(node->child1()).m_structure.onlyStructure() != node->transition()->next)
+ break;
+
+ node->convertToPhantom();
+ eliminated = true;
+ break;
+ }
+
</ins><span class="cx"> case CheckFunction: {
</span><span class="cx"> if (m_state.forNode(node->child1()).value() != node->function()->value())
</span><span class="cx"> break;
</span><span class="lines">@@ -147,47 +156,69 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case MultiGetByOffset: {
</span><del>- Edge childEdge = node->child1();
- Node* child = childEdge.node();
</del><ins>+ Edge baseEdge = node->child1();
+ Node* base = baseEdge.node();
</ins><span class="cx"> MultiGetByOffsetData& data = node->multiGetByOffsetData();
</span><span class="cx">
</span><del>- Structure* structure = m_state.forNode(child).m_structure.onlyStructure();
- if (!structure)
</del><ins>+ // First prune the variants, then check if the MultiGetByOffset can be
+ // strength-reduced to a GetByOffset.
+
+ AbstractValue baseValue = m_state.forNode(base);
+
+ m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
+ eliminated = true; // Don't allow the default constant folder to do things to this.
+
+ for (unsigned i = 0; i < data.variants.size(); ++i) {
+ GetByIdVariant& variant = data.variants[i];
+ variant.structureSet().filter(baseValue);
+ if (variant.structureSet().isEmpty()) {
+ data.variants[i--] = data.variants.last();
+ data.variants.removeLast();
+ }
+ }
+
+ if (data.variants.size() != 1)
</ins><span class="cx"> break;
</span><span class="cx">
</span><del>- for (unsigned i = data.variants.size(); i--;) {
- const GetByIdVariant& variant = data.variants[i];
- if (!variant.structureSet().contains(structure))
- continue;
-
- if (variant.alternateBase())
- break;
-
- emitGetByOffset(indexInBlock, node, structure, variant, data.identifierNumber);
- eliminated = true;
- break;
- }
</del><ins>+ emitGetByOffset(
+ indexInBlock, node, baseValue, data.variants[0], data.identifierNumber);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case MultiPutByOffset: {
</span><del>- Edge childEdge = node->child1();
- Node* child = childEdge.node();
</del><ins>+ Edge baseEdge = node->child1();
+ Node* base = baseEdge.node();
</ins><span class="cx"> MultiPutByOffsetData& data = node->multiPutByOffsetData();
</span><ins>+
+ AbstractValue baseValue = m_state.forNode(base);
</ins><span class="cx">
</span><del>- Structure* structure = m_state.forNode(child).m_structure.onlyStructure();
- if (!structure)
- break;
</del><ins>+ m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
+ eliminated = true; // Don't allow the default constant folder to do things to this.
</ins><span class="cx">
</span><del>- for (unsigned i = data.variants.size(); i--;) {
- const PutByIdVariant& variant = data.variants[i];
- if (!variant.oldStructure().contains(structure))
</del><ins>+
+ for (unsigned i = 0; i < data.variants.size(); ++i) {
+ PutByIdVariant& variant = data.variants[i];
+ variant.oldStructure().filter(baseValue);
+
+ if (variant.oldStructure().isEmpty()) {
+ data.variants[i--] = data.variants.last();
+ data.variants.removeLast();
</ins><span class="cx"> continue;
</span><ins>+ }
</ins><span class="cx">
</span><del>- emitPutByOffset(indexInBlock, node, variant, data.identifierNumber);
- eliminated = true;
</del><ins>+ if (variant.kind() == PutByIdVariant::Transition
+ && variant.oldStructure().onlyStructure() == variant.newStructure()) {
+ variant = PutByIdVariant::replace(
+ variant.oldStructure(),
+ variant.offset());
+ }
+ }
+
+ if (data.variants.size() != 1)
</ins><span class="cx"> break;
</span><del>- }
</del><ins>+
+ emitPutByOffset(
+ indexInBlock, node, baseValue, data.variants[0], data.identifierNumber);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -200,7 +231,12 @@
</span><span class="cx"> if (childEdge.useKind() != CellUse)
</span><span class="cx"> break;
</span><span class="cx">
</span><del>- Structure* structure = m_state.forNode(child).m_structure.onlyStructure();
</del><ins>+ AbstractValue baseValue = m_state.forNode(child);
+
+ m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
+ eliminated = true; // Don't allow the default constant folder to do things to this.
+
+ Structure* structure = baseValue.m_structure.onlyStructure();
</ins><span class="cx"> if (!structure)
</span><span class="cx"> break;
</span><span class="cx">
</span><span class="lines">@@ -214,7 +250,7 @@
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- emitGetByOffset(indexInBlock, node, structure, status[0], identifierNumber);
</del><ins>+ emitGetByOffset(indexInBlock, node, baseValue, status[0], identifierNumber);
</ins><span class="cx"> eliminated = true;
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="lines">@@ -228,7 +264,12 @@
</span><span class="cx">
</span><span class="cx"> ASSERT(childEdge.useKind() == CellUse);
</span><span class="cx">
</span><del>- Structure* structure = m_state.forNode(child).m_structure.onlyStructure();
</del><ins>+ AbstractValue baseValue = m_state.forNode(child);
+
+ m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
+ eliminated = true; // Don't allow the default constant folder to do things to this.
+
+ Structure* structure = baseValue.m_structure.onlyStructure();
</ins><span class="cx"> if (!structure)
</span><span class="cx"> break;
</span><span class="cx">
</span><span class="lines">@@ -244,7 +285,7 @@
</span><span class="cx"> if (status.numVariants() != 1)
</span><span class="cx"> break;
</span><span class="cx">
</span><del>- emitPutByOffset(indexInBlock, node, status[0], identifierNumber);
</del><ins>+ emitPutByOffset(indexInBlock, node, baseValue, status[0], identifierNumber);
</ins><span class="cx"> eliminated = true;
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="lines">@@ -336,33 +377,24 @@
</span><span class="cx"> return changed;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- void emitGetByOffset(unsigned indexInBlock, Node* node, Structure* structure, const GetByIdVariant& variant, unsigned identifierNumber)
</del><ins>+ void emitGetByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const GetByIdVariant& variant, unsigned identifierNumber)
</ins><span class="cx"> {
</span><span class="cx"> NodeOrigin origin = node->origin;
</span><span class="cx"> Edge childEdge = node->child1();
</span><span class="cx"> Node* child = childEdge.node();
</span><span class="cx">
</span><del>- bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell;
</del><ins>+ addBaseCheck(indexInBlock, node, baseValue, variant.structureSet());
</ins><span class="cx">
</span><del>- ASSERT(!variant.alternateBase());
- ASSERT_UNUSED(structure, 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 (needsCellCheck) {
- m_insertionSet.insertNode(
- indexInBlock, SpecNone, Phantom, origin, childEdge);
- }
-
</del><span class="cx"> if (variant.specificValue()) {
</span><span class="cx"> m_graph.convertToConstant(node, m_graph.freeze(variant.specificValue()));
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- childEdge.setUseKind(KnownCellUse);
</del><ins>+ if (variant.alternateBase()) {
+ child = m_insertionSet.insertConstant(indexInBlock, origin, variant.alternateBase());
+ childEdge = Edge(child, KnownCellUse);
+ } else
+ childEdge.setUseKind(KnownCellUse);
</ins><span class="cx">
</span><span class="cx"> Edge propertyStorage;
</span><span class="cx">
</span><span class="lines">@@ -381,24 +413,13 @@
</span><span class="cx"> m_graph.m_storageAccessData.append(storageAccessData);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- void emitPutByOffset(unsigned indexInBlock, Node* node, const PutByIdVariant& variant, unsigned identifierNumber)
</del><ins>+ void emitPutByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const PutByIdVariant& variant, unsigned identifierNumber)
</ins><span class="cx"> {
</span><span class="cx"> NodeOrigin origin = node->origin;
</span><span class="cx"> Edge childEdge = node->child1();
</span><del>- Node* child = childEdge.node();
</del><span class="cx">
</span><del>- bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell;
-
- // Now before we do anything else, push the CFA forward over the PutById
- // and make sure we signal to the loop that it should continue and not
- // do any eliminations.
- m_interpreter.execute(indexInBlock);
</del><ins>+ addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure());
</ins><span class="cx">
</span><del>- if (needsCellCheck) {
- m_insertionSet.insertNode(
- indexInBlock, SpecNone, Phantom, origin, childEdge);
- }
-
</del><span class="cx"> childEdge.setUseKind(KnownCellUse);
</span><span class="cx">
</span><span class="cx"> Transition* transition = 0;
</span><span class="lines">@@ -459,6 +480,25 @@
</span><span class="cx"> storageAccessData.identifierNumber = identifierNumber;
</span><span class="cx"> m_graph.m_storageAccessData.append(storageAccessData);
</span><span class="cx"> }
</span><ins>+
+ void addBaseCheck(
+ unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const StructureSet& set)
+ {
+ if (!baseValue.m_structure.isSubsetOf(set)) {
+ // Arises when we prune MultiGetByOffset. We could have a
+ // MultiGetByOffset with a single variant that checks for structure S,
+ // and the input has structures S and T, for example.
+ m_insertionSet.insertNode(
+ indexInBlock, SpecNone, CheckStructure, node->origin,
+ OpInfo(m_graph.addStructureSet(set)), node->child1());
+ return;
+ }
+
+ if (baseValue.m_type & ~SpecCell) {
+ m_insertionSet.insertNode(
+ indexInBlock, SpecNone, Phantom, node->origin, node->child1());
+ }
+ }
</ins><span class="cx">
</span><span class="cx"> void addStructureTransitionCheck(NodeOrigin origin, unsigned indexInBlock, JSCell* cell, Structure* structure)
</span><span class="cx"> {
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGGraphcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGGraph.cpp (170140 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGGraph.cpp        2014-06-19 04:16:04 UTC (rev 170140)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGGraph.cpp        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -952,7 +952,7 @@
</span><span class="cx">
</span><span class="cx"> FrozenValue* Graph::freezeStrong(JSValue value)
</span><span class="cx"> {
</span><del>- FrozenValue* result = freeze(value);
</del><ins>+ FrozenValue* result = freezeFragile(value);
</ins><span class="cx"> result->strengthenTo(StrongValue);
</span><span class="cx"> return result;
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGGraphh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGGraph.h (170140 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGGraph.h        2014-06-19 04:16:04 UTC (rev 170140)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGGraph.h        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -146,8 +146,8 @@
</span><span class="cx"> void dethread();
</span><span class="cx">
</span><span class="cx"> FrozenValue* freezeFragile(JSValue value);
</span><del>- FrozenValue* freeze(JSValue value); // We use weak freezing by default.
- FrozenValue* freezeStrong(JSValue value); // Shorthand for freeze(value)->markStrongly().
</del><ins>+ FrozenValue* freeze(JSValue value); // We use weak freezing by default. Shorthand for freezeFragile(value)->strengthenTo(WeakValue);
+ FrozenValue* freezeStrong(JSValue value); // Shorthand for freezeFragile(value)->strengthenTo(StrongValue).
</ins><span class="cx">
</span><span class="cx"> void convertToConstant(Node* node, FrozenValue* value);
</span><span class="cx"> void convertToConstant(Node* node, JSValue value);
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGStructureAbstractValueh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h (170140 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h        2014-06-19 04:16:04 UTC (rev 170140)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -55,6 +55,18 @@
</span><span class="cx"> setClobbered(other.isClobbered());
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ ALWAYS_INLINE StructureAbstractValue& operator=(Structure* structure)
+ {
+ m_set = structure;
+ setClobbered(false);
+ return *this;
+ }
+ ALWAYS_INLINE StructureAbstractValue& operator=(const StructureSet& other)
+ {
+ m_set = other;
+ setClobbered(false);
+ return *this;
+ }
</ins><span class="cx"> ALWAYS_INLINE StructureAbstractValue& operator=(const StructureAbstractValue& other)
</span><span class="cx"> {
</span><span class="cx"> m_set = other.m_set;
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (170140 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-06-19 04:16:04 UTC (rev 170140)
+++ branches/ftlopt/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -3202,6 +3202,12 @@
</span><span class="cx"> LValue base = lowCell(m_node->child1());
</span><span class="cx">
</span><span class="cx"> MultiGetByOffsetData& data = m_node->multiGetByOffsetData();
</span><ins>+
+ if (data.variants.isEmpty()) {
+ // Protect against creating a Phi function with zero inputs. LLVM doesn't like that.
+ terminate(BadCache);
+ return;
+ }
</ins><span class="cx">
</span><span class="cx"> Vector<LBasicBlock, 2> blocks(data.variants.size());
</span><span class="cx"> for (unsigned i = data.variants.size(); i--;)
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoretestsstressfoldmultigetbyoffsettogetbyoffsetwithoutfoldingthestructurecheckjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/Source/JavaScriptCore/tests/stress/fold-multi-get-by-offset-to-get-by-offset-without-folding-the-structure-check.js (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/tests/stress/fold-multi-get-by-offset-to-get-by-offset-without-folding-the-structure-check.js         (rev 0)
+++ branches/ftlopt/Source/JavaScriptCore/tests/stress/fold-multi-get-by-offset-to-get-by-offset-without-folding-the-structure-check.js        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -0,0 +1,50 @@
</span><ins>+function foo(o) {
+ return o.f;
+}
+
+function fu(o) {
+ return o.e;
+}
+
+function bar(f, o) {
+ return f(o);
+}
+
+function baz(f, o) {
+ return f(o);
+}
+
+for (var i = 0; i < 100; ++i) {
+ foo({f:1, e:2});
+ foo({e:1, f:2});
+ foo({d:1, e:2, f:3});
+ fu({f:1, e:2});
+ fu({e:1, f:2, g:3});
+ fu({d:1, e:2, f:3, g:4});
+}
+
+for (var i = 0; i < 100; ++i) {
+ bar(foo, {f:1});
+ bar(function() { }, null);
+ bar(function() { return 42; }, null);
+ baz(fu, {e:1});
+ baz(function() { }, null);
+ baz(function() { return 42; }, null);
+}
+
+(function(f, g, o, p) {
+ var result = 0;
+ var n = 1000000;
+ for (var i = 0; i < n; ++i) {
+ var q;
+ if (i == n - 1)
+ q = p;
+ else
+ q = o;
+ result += baz(g, q);
+ result += bar(f, q);
+ }
+ if (result != (n - 1) * (o.f + o.e) + 12 + 13)
+ throw "Error: bad result: " + result;
+})(foo, fu, {f:42, e:2}, {e:12, f:13, g:14});
+
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoretestsstressfoldmultiputbyoffsettoputbyoffsetwithoutfoldingthestructurecheckjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/Source/JavaScriptCore/tests/stress/fold-multi-put-by-offset-to-put-by-offset-without-folding-the-structure-check.js (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/tests/stress/fold-multi-put-by-offset-to-put-by-offset-without-folding-the-structure-check.js         (rev 0)
+++ branches/ftlopt/Source/JavaScriptCore/tests/stress/fold-multi-put-by-offset-to-put-by-offset-without-folding-the-structure-check.js        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -0,0 +1,56 @@
</span><ins>+function foo(o) {
+ o.f = 1;
+}
+
+function fu(o) {
+ o.e = 2;
+}
+
+function bar(f, o) {
+ f(o);
+}
+
+function baz(f, o) {
+ f(o);
+}
+
+for (var i = 0; i < 100; ++i) {
+ foo({f:1, e:2});
+ foo({e:1, f:2});
+ foo({d:1, e:2, f:3});
+ fu({f:1, e:2});
+ fu({e:1, f:2, g:3});
+ fu({d:1, e:2, f:3, g:4});
+}
+
+for (var i = 0; i < 100; ++i) {
+ bar(foo, {f:1});
+ bar(function() { }, null);
+ bar(function() { return 42; }, null);
+ baz(fu, {e:1});
+ baz(function() { }, null);
+ baz(function() { return 42; }, null);
+}
+
+(function(f, g, o, p) {
+ var result = 0;
+ var n = 1000000;
+ for (var i = 0; i < n; ++i) {
+ var q;
+ if (i == n - 1)
+ q = p;
+ else
+ q = o;
+ baz(g, q);
+ bar(f, q);
+ }
+ if (o.e != 2)
+ throw "Error: bad value in o.e: " + o.e;
+ if (o.f != 1)
+ throw "Error: bad value in o.f: " + o.f;
+ if (p.e != 2)
+ throw "Error: bad value in p.e: " + p.e;
+ if (p.f != 1)
+ throw "Error: bad value in p.f: " + p.f;
+})(foo, fu, {f:42, e:2}, {e:12, f:13, g:14});
+
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoretestsstressprunemultiputbyoffsetreplaceortransitionvariantjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/Source/JavaScriptCore/tests/stress/prune-multi-put-by-offset-replace-or-transition-variant.js (0 => 170141)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/tests/stress/prune-multi-put-by-offset-replace-or-transition-variant.js         (rev 0)
+++ branches/ftlopt/Source/JavaScriptCore/tests/stress/prune-multi-put-by-offset-replace-or-transition-variant.js        2014-06-19 04:34:25 UTC (rev 170141)
</span><span class="lines">@@ -0,0 +1,58 @@
</span><ins>+function foo(o) {
+ o.f = 1;
+}
+
+function fu(o) {
+ o.e = 2;
+}
+
+function bar(f, o) {
+ f(o);
+}
+
+function baz(f, o) {
+ f(o);
+}
+
+for (var i = 0; i < 100; ++i) {
+ foo({f:1, e:2});
+ foo({e:1, f:2});
+ foo({e:1});
+ foo({d:1, e:2, f:3});
+ fu({f:1, e:2});
+ fu({e:1, f:2});
+ fu({e:1, f:2, g:3});
+ fu({d:1, e:2, f:3, g:4});
+}
+
+for (var i = 0; i < 100; ++i) {
+ bar(foo, {f:1});
+ bar(function() { }, null);
+ bar(function() { return 42; }, null);
+ baz(fu, {e:1});
+ baz(function() { }, null);
+ baz(function() { return 42; }, null);
+}
+
+(function(f, g, o, p) {
+ var result = 0;
+ var n = 1000000;
+ for (var i = 0; i < n; ++i) {
+ var q;
+ if (i == n - 1)
+ q = p;
+ else
+ q = o;
+ baz(g, q);
+ bar(f, q);
+ }
+ if (o.e != 2)
+ throw "Error: bad value in o.e: " + o.e;
+ if (o.f != 1)
+ throw "Error: bad value in o.f: " + o.f;
+ if (p.e != 2)
+ throw "Error: bad value in p.e: " + p.e;
+ if (p.f != 1)
+ throw "Error: bad value in p.f: " + p.f;
+})(foo, fu, {e:42, f:2}, {e:12, f:13, g:14});
+
</ins></span></pre>
</div>
</div>
</body>
</html>