<!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>[170275] 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/170275">170275</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-06-22 18:02:01 -0700 (Sun, 22 Jun 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>[ftlopt] Fold GetById/PutById to MultiGetByOffset/GetByOffset or MultiPutByOffset/PutByOffset, which implies handling non-singleton sets
https://bugs.webkit.org/show_bug.cgi?id=134090
Reviewed by Oliver Hunt.
Source/JavaScriptCore:
This pretty much finishes off the work to eliminate the special-casing of singleton
structure sets by making it possible to fold GetById and PutById to various polymorphic
forms of the ByOffset nodes.
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeForStubInfo):
(JSC::GetByIdStatus::computeFor):
* bytecode/GetByIdStatus.h:
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeFor):
* bytecode/PutByIdStatus.h:
* bytecode/PutByIdVariant.h:
(JSC::PutByIdVariant::constantChecks):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
(JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
(JSC::DFG::ConstantFoldingPhase::addChecks):
* dfg/DFGNode.h:
(JSC::DFG::Node::convertToMultiGetByOffset):
(JSC::DFG::Node::convertToMultiPutByOffset):
* dfg/DFGSpeculativeJIT64.cpp: Also convert all release assertions to DFG assertions in this file, because I was hitting some of them while debugging.
(JSC::DFG::SpeculativeJIT::fillJSValue):
(JSC::DFG::SpeculativeJIT::nonSpeculativeCompareNull):
(JSC::DFG::SpeculativeJIT::emitCall):
(JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal):
(JSC::DFG::SpeculativeJIT::fillSpeculateInt32Strict):
(JSC::DFG::SpeculativeJIT::fillSpeculateInt52):
(JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
(JSC::DFG::SpeculativeJIT::compileLogicalNot):
(JSC::DFG::SpeculativeJIT::emitBranch):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStructureAbstractValue.h:
(JSC::DFG::StructureAbstractValue::set):
LayoutTests:
* js/regress/fold-get-by-id-to-multi-get-by-offset-expected.txt: Added.
* js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int-expected.txt: Added.
* js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int.html: Added.
* js/regress/fold-get-by-id-to-multi-get-by-offset.html: Added.
* js/regress/fold-put-by-id-to-multi-put-by-offset-expected.txt: Added.
* js/regress/fold-put-by-id-to-multi-put-by-offset.html: Added.
* js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset-rare-int.js: Added.
(foo):
(fu):
(bar):
(.bar):
(Number):
* js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset.js: Added.
(foo):
(fu):
(bar):
(.bar):
(Number):
* js/regress/script-tests/fold-put-by-id-to-multi-put-by-offset.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="#branchesftloptSourceJavaScriptCorebytecodeGetByIdStatuscpp">branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorebytecodeGetByIdStatush">branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdStatus.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorebytecodePutByIdStatuscpp">branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorebytecodePutByIdStatush">branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdStatus.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorebytecodePutByIdVarianth">branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdVariant.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGByteCodeParsercpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGNodeh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGStructureAbstractValueh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#branchesftloptLayoutTestsjsregressfoldgetbyidtomultigetbyoffsetexpectedtxt">branches/ftlopt/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-expected.txt</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressfoldgetbyidtomultigetbyoffsetrareintexpectedtxt">branches/ftlopt/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int-expected.txt</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressfoldgetbyidtomultigetbyoffsetrareinthtml">branches/ftlopt/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int.html</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressfoldgetbyidtomultigetbyoffsethtml">branches/ftlopt/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset.html</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressfoldputbyidtomultiputbyoffsetexpectedtxt">branches/ftlopt/LayoutTests/js/regress/fold-put-by-id-to-multi-put-by-offset-expected.txt</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressfoldputbyidtomultiputbyoffsethtml">branches/ftlopt/LayoutTests/js/regress/fold-put-by-id-to-multi-put-by-offset.html</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressscripttestsfoldgetbyidtomultigetbyoffsetrareintjs">branches/ftlopt/LayoutTests/js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset-rare-int.js</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressscripttestsfoldgetbyidtomultigetbyoffsetjs">branches/ftlopt/LayoutTests/js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset.js</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressscripttestsfoldputbyidtomultiputbyoffsetjs">branches/ftlopt/LayoutTests/js/regress/script-tests/fold-put-by-id-to-multi-put-by-offset.js</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchesftloptLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/LayoutTests/ChangeLog (170274 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/ChangeLog        2014-06-23 00:51:33 UTC (rev 170274)
+++ branches/ftlopt/LayoutTests/ChangeLog        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -1,3 +1,34 @@
</span><ins>+2014-06-21 Filip Pizlo <fpizlo@apple.com>
+
+ [ftlopt] Fold GetById/PutById to MultiGetByOffset/GetByOffset or MultiPutByOffset/PutByOffset, which implies handling non-singleton sets
+ https://bugs.webkit.org/show_bug.cgi?id=134090
+
+ Reviewed by Oliver Hunt.
+
+ * js/regress/fold-get-by-id-to-multi-get-by-offset-expected.txt: Added.
+ * js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int-expected.txt: Added.
+ * js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int.html: Added.
+ * js/regress/fold-get-by-id-to-multi-get-by-offset.html: Added.
+ * js/regress/fold-put-by-id-to-multi-put-by-offset-expected.txt: Added.
+ * js/regress/fold-put-by-id-to-multi-put-by-offset.html: Added.
+ * js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset-rare-int.js: Added.
+ (foo):
+ (fu):
+ (bar):
+ (.bar):
+ (Number):
+ * js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset.js: Added.
+ (foo):
+ (fu):
+ (bar):
+ (.bar):
+ (Number):
+ * js/regress/script-tests/fold-put-by-id-to-multi-put-by-offset.js: Added.
+ (foo):
+ (fu):
+ (bar):
+ (.bar):
+
</ins><span class="cx"> 2014-06-19 Filip Pizlo <fpizlo@apple.com>
</span><span class="cx">
</span><span class="cx"> [ftlopt] LICM should be able to hoist CheckStructure even if the loop clobbers structures so long as the structures being checked are watchable
</span></span></pre></div>
<a id="branchesftloptLayoutTestsjsregressfoldgetbyidtomultigetbyoffsetexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-expected.txt (0 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-expected.txt         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-expected.txt        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/fold-get-by-id-to-multi-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="branchesftloptLayoutTestsjsregressfoldgetbyidtomultigetbyoffsetrareintexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int-expected.txt (0 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int-expected.txt         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int-expected.txt        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/fold-get-by-id-to-multi-get-by-offset-rare-int
+
+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="branchesftloptLayoutTestsjsregressfoldgetbyidtomultigetbyoffsetrareinthtml"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int.html (0 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int.html         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int.html        2014-06-23 01:02:01 UTC (rev 170275)
</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-get-by-id-to-multi-get-by-offset-rare-int.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="branchesftloptLayoutTestsjsregressfoldgetbyidtomultigetbyoffsethtml"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset.html (0 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset.html         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset.html        2014-06-23 01:02:01 UTC (rev 170275)
</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-get-by-id-to-multi-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="branchesftloptLayoutTestsjsregressfoldputbyidtomultiputbyoffsetexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-put-by-id-to-multi-put-by-offset-expected.txt (0 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-put-by-id-to-multi-put-by-offset-expected.txt         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-put-by-id-to-multi-put-by-offset-expected.txt        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/fold-put-by-id-to-multi-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="branchesftloptLayoutTestsjsregressfoldputbyidtomultiputbyoffsethtml"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/fold-put-by-id-to-multi-put-by-offset.html (0 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/fold-put-by-id-to-multi-put-by-offset.html         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/fold-put-by-id-to-multi-put-by-offset.html        2014-06-23 01:02:01 UTC (rev 170275)
</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-by-id-to-multi-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="branchesftloptLayoutTestsjsregressscripttestsfoldgetbyidtomultigetbyoffsetrareintjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset-rare-int.js (0 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset-rare-int.js         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset-rare-int.js        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -0,0 +1,47 @@
</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 < 1000; ++i) {
+ var o = {f:1};
+ o["i" + i] = 42;
+ foo(o);
+ fu({f:1, e:2});
+ fu({e:1, f:2});
+}
+
+for (var i = 0; i < 100; ++i) {
+ bar(foo, {f:1});
+ bar(function() { }, null);
+ bar(function() { return 42 }, null);
+}
+
+Number.prototype.f = 100;
+
+(function(f, o, p) {
+ var result = 0;
+ var n = 1000000;
+ for (var i = 0; i < n + 1; ++i) {
+ result += fu(o);
+ var q;
+ if (i == n)
+ q = 42;
+ else
+ q = o;
+ result += bar(f, q);
+ var tmp = o;
+ o = p;
+ p = tmp;
+ }
+ if (result != (o.f + o.e + p.f + p.e) * n / 2 + 100 + p.e)
+ throw "Error: bad result: " + result;
+})(foo, {f:42, e:43}, {e:44, f:45});
+
</ins></span></pre></div>
<a id="branchesftloptLayoutTestsjsregressscripttestsfoldgetbyidtomultigetbyoffsetjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset.js (0 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset.js         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset.js        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -0,0 +1,42 @@
</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 < 1000; ++i) {
+ var o = {f:1};
+ o["i" + i] = 42;
+ foo(o);
+ fu({f:1, e:2});
+ fu({e:1, f:2});
+}
+
+for (var i = 0; i < 100; ++i) {
+ bar(foo, {f:1});
+ bar(function() { }, null);
+ bar(function() { return 42 }, null);
+}
+
+Number.prototype.f = 100;
+
+(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 != (o.f + o.e + p.f + p.e) * n / 2)
+ throw "Error: bad result: " + result;
+})(foo, {f:42, e:43}, {e:44, f:45});
+
</ins></span></pre></div>
<a id="branchesftloptLayoutTestsjsregressscripttestsfoldputbyidtomultiputbyoffsetjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/script-tests/fold-put-by-id-to-multi-put-by-offset.js (0 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/script-tests/fold-put-by-id-to-multi-put-by-offset.js         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/script-tests/fold-put-by-id-to-multi-put-by-offset.js        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -0,0 +1,46 @@
</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 < 1000; ++i) {
+ var o = {};
+ o["i" + i] = 42;
+ foo(o);
+ fu({f:1, e:2});
+ fu({e:1, f:2, g: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}, {e:23, f:42, g:100});
+
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/ChangeLog (170274 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/ChangeLog        2014-06-23 00:51:33 UTC (rev 170274)
+++ branches/ftlopt/Source/JavaScriptCore/ChangeLog        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -1,3 +1,50 @@
</span><ins>+2014-06-21 Filip Pizlo <fpizlo@apple.com>
+
+ [ftlopt] Fold GetById/PutById to MultiGetByOffset/GetByOffset or MultiPutByOffset/PutByOffset, which implies handling non-singleton sets
+ https://bugs.webkit.org/show_bug.cgi?id=134090
+
+ Reviewed by Oliver Hunt.
+
+ This pretty much finishes off the work to eliminate the special-casing of singleton
+ structure sets by making it possible to fold GetById and PutById to various polymorphic
+ forms of the ByOffset nodes.
+
+ * bytecode/GetByIdStatus.cpp:
+ (JSC::GetByIdStatus::computeForStubInfo):
+ (JSC::GetByIdStatus::computeFor):
+ * bytecode/GetByIdStatus.h:
+ * bytecode/PutByIdStatus.cpp:
+ (JSC::PutByIdStatus::computeFor):
+ * bytecode/PutByIdStatus.h:
+ * bytecode/PutByIdVariant.h:
+ (JSC::PutByIdVariant::constantChecks):
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::foldConstants):
+ (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
+ (JSC::DFG::ConstantFoldingPhase::addChecks):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::convertToMultiGetByOffset):
+ (JSC::DFG::Node::convertToMultiPutByOffset):
+ * dfg/DFGSpeculativeJIT64.cpp: Also convert all release assertions to DFG assertions in this file, because I was hitting some of them while debugging.
+ (JSC::DFG::SpeculativeJIT::fillJSValue):
+ (JSC::DFG::SpeculativeJIT::nonSpeculativeCompareNull):
+ (JSC::DFG::SpeculativeJIT::emitCall):
+ (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal):
+ (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Strict):
+ (JSC::DFG::SpeculativeJIT::fillSpeculateInt52):
+ (JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
+ (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
+ (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
+ (JSC::DFG::SpeculativeJIT::compileLogicalNot):
+ (JSC::DFG::SpeculativeJIT::emitBranch):
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGStructureAbstractValue.h:
+ (JSC::DFG::StructureAbstractValue::set):
+
</ins><span class="cx"> 2014-06-20 Mark Hahnenberg <mhahnenberg@apple.com>
</span><span class="cx">
</span><span class="cx"> Merge r169903 to the branch.
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodeGetByIdStatuscpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp (170274 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp        2014-06-23 00:51:33 UTC (rev 170274)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -170,7 +170,8 @@
</span><span class="cx">
</span><span class="cx"> variant.m_structureSet.add(structure);
</span><span class="cx"> variant.m_specificValue = JSValue(specificValue);
</span><del>- result.appendVariant(variant);
</del><ins>+ bool didAppend = result.appendVariant(variant);
+ ASSERT_UNUSED(didAppend, didAppend);
</ins><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -312,34 +313,43 @@
</span><span class="cx"> return computeFor(profiledBlock, baselineMap, codeOrigin.bytecodeIndex, uid);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-GetByIdStatus GetByIdStatus::computeFor(VM& vm, Structure* structure, StringImpl* uid)
</del><ins>+GetByIdStatus GetByIdStatus::computeFor(VM& vm, const StructureSet& set, StringImpl* uid)
</ins><span class="cx"> {
</span><span class="cx"> // For now we only handle the super simple self access case. We could handle the
</span><span class="cx"> // prototype case in the future.
</span><span class="cx">
</span><del>- if (!structure)
- return GetByIdStatus(TakesSlowPath);
</del><ins>+ if (set.isEmpty())
+ return GetByIdStatus();
</ins><span class="cx">
</span><span class="cx"> if (toUInt32FromStringImpl(uid) != PropertyName::NotAnIndex)
</span><span class="cx"> return GetByIdStatus(TakesSlowPath);
</span><span class="cx">
</span><del>- if (structure->typeInfo().overridesGetOwnPropertySlot() && structure->typeInfo().type() != GlobalObjectType)
- return GetByIdStatus(TakesSlowPath);
</del><ins>+ GetByIdStatus result;
+ result.m_state = Simple;
+ result.m_wasSeenInJIT = false;
+ for (unsigned i = 0; i < set.size(); ++i) {
+ Structure* structure = set[i];
+ if (structure->typeInfo().overridesGetOwnPropertySlot() && structure->typeInfo().type() != GlobalObjectType)
+ return GetByIdStatus(TakesSlowPath);
+
+ if (!structure->propertyAccessesAreCacheable())
+ return GetByIdStatus(TakesSlowPath);
+
+ unsigned attributes;
+ JSCell* specificValue;
+ PropertyOffset offset = structure->getConcurrently(vm, uid, attributes, specificValue);
+ if (!isValidOffset(offset))
+ 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.
+ if (attributes & Accessor)
+ return GetByIdStatus(MakesCalls); // We could be smarter here, like strenght-reducing this to a Call.
+ if (structure->isDictionary())
+ specificValue = 0;
+
+ if (!result.appendVariant(GetByIdVariant(structure, offset, specificValue)))
+ return GetByIdStatus(TakesSlowPath);
+ }
</ins><span class="cx">
</span><del>- if (!structure->propertyAccessesAreCacheable())
- return GetByIdStatus(TakesSlowPath);
-
- unsigned attributes;
- JSCell* specificValue;
- PropertyOffset offset = structure->getConcurrently(vm, uid, attributes, specificValue);
- if (!isValidOffset(offset))
- 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.
- if (attributes & Accessor)
- return GetByIdStatus(MakesCalls);
- if (structure->isDictionary())
- specificValue = 0;
- return GetByIdStatus(
- Simple, false, GetByIdVariant(StructureSet(structure), offset, specificValue));
</del><ins>+ return result;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool GetByIdStatus::makesCalls() const
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodeGetByIdStatush"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdStatus.h (170274 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdStatus.h        2014-06-23 00:51:33 UTC (rev 170274)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdStatus.h        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -68,7 +68,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static GetByIdStatus computeFor(CodeBlock*, StubInfoMap&, unsigned bytecodeIndex, StringImpl* uid);
</span><del>- static GetByIdStatus computeFor(VM&, Structure*, StringImpl* uid);
</del><ins>+ static GetByIdStatus computeFor(VM&, const StructureSet&, StringImpl* uid);
</ins><span class="cx">
</span><span class="cx"> static GetByIdStatus computeFor(CodeBlock* baselineBlock, CodeBlock* dfgBlock, StubInfoMap& baselineMap, StubInfoMap& dfgMap, CodeOrigin, StringImpl* uid);
</span><span class="cx">
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodePutByIdStatuscpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp (170274 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp        2014-06-23 00:51:33 UTC (rev 170274)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -259,88 +259,101 @@
</span><span class="cx"> return computeFor(baselineBlock, baselineMap, codeOrigin.bytecodeIndex, uid);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PutByIdStatus PutByIdStatus::computeFor(VM& vm, JSGlobalObject* globalObject, Structure* structure, StringImpl* uid, bool isDirect)
</del><ins>+PutByIdStatus PutByIdStatus::computeFor(VM& vm, JSGlobalObject* globalObject, const StructureSet& set, StringImpl* uid, bool isDirect)
</ins><span class="cx"> {
</span><span class="cx"> if (toUInt32FromStringImpl(uid) != PropertyName::NotAnIndex)
</span><span class="cx"> return PutByIdStatus(TakesSlowPath);
</span><span class="cx">
</span><del>- if (!structure)
- return PutByIdStatus(TakesSlowPath);
</del><ins>+ if (set.isEmpty())
+ return PutByIdStatus();
</ins><span class="cx">
</span><del>- if (structure->typeInfo().overridesGetOwnPropertySlot() && structure->typeInfo().type() != GlobalObjectType)
- return PutByIdStatus(TakesSlowPath);
</del><ins>+ PutByIdStatus result;
+ result.m_state = Simple;
+ for (unsigned i = 0; i < set.size(); ++i) {
+ Structure* structure = set[i];
+
+ if (structure->typeInfo().overridesGetOwnPropertySlot() && structure->typeInfo().type() != GlobalObjectType)
+ return PutByIdStatus(TakesSlowPath);
</ins><span class="cx">
</span><del>- if (!structure->propertyAccessesAreCacheable())
- return PutByIdStatus(TakesSlowPath);
</del><ins>+ if (!structure->propertyAccessesAreCacheable())
+ return PutByIdStatus(TakesSlowPath);
</ins><span class="cx">
</span><del>- unsigned attributes;
- JSCell* specificValue;
- PropertyOffset offset = structure->getConcurrently(vm, uid, attributes, specificValue);
- if (isValidOffset(offset)) {
- if (attributes & CustomAccessor)
- return PutByIdStatus(MakesCalls);
</del><ins>+ unsigned attributes;
+ JSCell* specificValue;
+ PropertyOffset offset = structure->getConcurrently(vm, uid, attributes, specificValue);
+ if (isValidOffset(offset)) {
+ if (attributes & CustomAccessor)
+ return PutByIdStatus(MakesCalls);
</ins><span class="cx">
</span><del>- if (attributes & (Accessor | ReadOnly))
- return PutByIdStatus(TakesSlowPath);
- if (specificValue) {
- // We need the PutById slow path to verify that we're storing the right value into
- // the specialized slot.
- return PutByIdStatus(TakesSlowPath);
</del><ins>+ if (attributes & (Accessor | ReadOnly))
+ return PutByIdStatus(TakesSlowPath);
+ if (specificValue) {
+ // We need the PutById slow path to verify that we're storing the right value into
+ // the specialized slot.
+ return PutByIdStatus(TakesSlowPath);
+ }
+ if (!result.appendVariant(PutByIdVariant::replace(structure, offset)))
+ return PutByIdStatus(TakesSlowPath);
+ continue;
</ins><span class="cx"> }
</span><del>- return PutByIdVariant::replace(structure, offset);
- }
</del><span class="cx">
</span><del>- // Our hypothesis is that we're doing a transition. Before we prove that this is really
- // true, we want to do some sanity checks.
</del><ins>+ // Our hypothesis is that we're doing a transition. Before we prove that this is really
+ // true, we want to do some sanity checks.
</ins><span class="cx">
</span><del>- // Don't cache put transitions on dictionaries.
- if (structure->isDictionary())
- return PutByIdStatus(TakesSlowPath);
</del><ins>+ // Don't cache put transitions on dictionaries.
+ if (structure->isDictionary())
+ return PutByIdStatus(TakesSlowPath);
</ins><span class="cx">
</span><del>- // If the structure corresponds to something that isn't an object, then give up, since
- // we don't want to be adding properties to strings.
- if (structure->typeInfo().type() == StringType)
- return PutByIdStatus(TakesSlowPath);
</del><ins>+ // If the structure corresponds to something that isn't an object, then give up, since
+ // we don't want to be adding properties to strings.
+ if (structure->typeInfo().type() == StringType)
+ return PutByIdStatus(TakesSlowPath);
</ins><span class="cx">
</span><del>- RefPtr<IntendedStructureChain> chain;
- if (!isDirect) {
- chain = adoptRef(new IntendedStructureChain(globalObject, structure));
</del><ins>+ RefPtr<IntendedStructureChain> chain;
+ if (!isDirect) {
+ chain = adoptRef(new IntendedStructureChain(globalObject, structure));
</ins><span class="cx">
</span><del>- // If the prototype chain has setters or read-only properties, then give up.
- if (chain->mayInterceptStoreTo(vm, uid))
- return PutByIdStatus(TakesSlowPath);
</del><ins>+ // If the prototype chain has setters or read-only properties, then give up.
+ if (chain->mayInterceptStoreTo(vm, uid))
+ return PutByIdStatus(TakesSlowPath);
</ins><span class="cx">
</span><del>- // If the prototype chain hasn't been normalized (i.e. there are proxies or dictionaries)
- // then give up. The dictionary case would only happen if this structure has not been
- // used in an optimized put_by_id transition. And really the only reason why we would
- // bail here is that I don't really feel like having the optimizing JIT go and flatten
- // dictionaries if we have evidence to suggest that those objects were never used as
- // prototypes in a cacheable prototype access - i.e. there's a good chance that some of
- // the other checks below will fail.
- if (structure->isProxy() || !chain->isNormalized())
</del><ins>+ // If the prototype chain hasn't been normalized (i.e. there are proxies or dictionaries)
+ // then give up. The dictionary case would only happen if this structure has not been
+ // used in an optimized put_by_id transition. And really the only reason why we would
+ // bail here is that I don't really feel like having the optimizing JIT go and flatten
+ // dictionaries if we have evidence to suggest that those objects were never used as
+ // prototypes in a cacheable prototype access - i.e. there's a good chance that some of
+ // the other checks below will fail.
+ if (structure->isProxy() || !chain->isNormalized())
+ return PutByIdStatus(TakesSlowPath);
+ }
+
+ // We only optimize if there is already a structure that the transition is cached to.
+ // Among other things, this allows us to guard against a transition with a specific
+ // value.
+ //
+ // - If we're storing a value that could be specific: this would only be a problem if
+ // the existing transition did have a specific value already, since if it didn't,
+ // then we would behave "as if" we were not storing a specific value. If it did
+ // have a specific value, then we'll know - the fact that we pass 0 for
+ // specificValue will tell us.
+ //
+ // - If we're not storing a value that could be specific: again, this would only be a
+ // problem if the existing transition did have a specific value, which we check for
+ // by passing 0 for the specificValue.
+ Structure* transition = Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, 0, offset);
+ if (!transition)
+ return PutByIdStatus(TakesSlowPath); // This occurs in bizarre cases only. See above.
+ ASSERT(!transition->transitionDidInvolveSpecificValue());
+ ASSERT(isValidOffset(offset));
+
+ bool didAppend = result.appendVariant(
+ PutByIdVariant::transition(structure, transition, chain.release(), offset));
+ if (!didAppend)
</ins><span class="cx"> return PutByIdStatus(TakesSlowPath);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- // We only optimize if there is already a structure that the transition is cached to.
- // Among other things, this allows us to guard against a transition with a specific
- // value.
- //
- // - If we're storing a value that could be specific: this would only be a problem if
- // the existing transition did have a specific value already, since if it didn't,
- // then we would behave "as if" we were not storing a specific value. If it did
- // have a specific value, then we'll know - the fact that we pass 0 for
- // specificValue will tell us.
- //
- // - If we're not storing a value that could be specific: again, this would only be a
- // problem if the existing transition did have a specific value, which we check for
- // by passing 0 for the specificValue.
- Structure* transition = Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, 0, offset);
- if (!transition)
- return PutByIdStatus(TakesSlowPath); // This occurs in bizarre cases only. See above.
- ASSERT(!transition->transitionDidInvolveSpecificValue());
- ASSERT(isValidOffset(offset));
-
- return PutByIdVariant::transition(structure, transition, chain.release(), offset);
</del><ins>+ return result;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void PutByIdStatus::dump(PrintStream& out) const
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodePutByIdStatush"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdStatus.h (170274 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdStatus.h        2014-06-23 00:51:33 UTC (rev 170274)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdStatus.h        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -70,7 +70,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static PutByIdStatus computeFor(CodeBlock*, StubInfoMap&, unsigned bytecodeIndex, StringImpl* uid);
</span><del>- static PutByIdStatus computeFor(VM&, JSGlobalObject*, Structure*, StringImpl* uid, bool isDirect);
</del><ins>+ static PutByIdStatus computeFor(VM&, JSGlobalObject*, const StructureSet&, StringImpl* uid, bool isDirect);
</ins><span class="cx">
</span><span class="cx"> static PutByIdStatus computeFor(CodeBlock* baselineBlock, CodeBlock* dfgBlock, StubInfoMap& baselineMap, StubInfoMap& dfgMap, CodeOrigin, StringImpl* uid);
</span><span class="cx">
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodePutByIdVarianth"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdVariant.h (170274 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdVariant.h        2014-06-23 00:51:33 UTC (rev 170274)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdVariant.h        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -106,7 +106,6 @@
</span><span class="cx">
</span><span class="cx"> const ConstantStructureCheckVector& constantChecks() const
</span><span class="cx"> {
</span><del>- ASSERT(kind() == Transition);
</del><span class="cx"> return m_constantChecks;
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (170274 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-06-23 00:51:33 UTC (rev 170274)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -1370,46 +1370,45 @@
</span><span class="cx"> break;
</span><span class="cx">
</span><span class="cx"> case GetById:
</span><del>- case GetByIdFlush:
</del><ins>+ case GetByIdFlush: {
</ins><span class="cx"> if (!node->prediction()) {
</span><span class="cx"> m_state.setIsValid(false);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- if (isCellSpeculation(node->child1()->prediction())) {
- // This use of onlyStructure() should be replaced by giving GetByIdStatus the ability
- // to compute things based on a StructureSet, and then to factor ByteCodeParser's
- // ability to generate code based on a GetByIdStatus out of ByteCodeParser so that
- // ConstantFoldingPhase can use it.
- // https://bugs.webkit.org/show_bug.cgi?id=133229
- if (Structure* structure = forNode(node->child1()).m_structure.onlyStructure()) {
- GetByIdStatus status = GetByIdStatus::computeFor(
- m_graph.m_vm, structure,
- m_graph.identifiers()[node->identifierNumber()]);
- if (status.isSimple() && status.numVariants() == 1) {
- // Assert things that we can't handle and that the computeFor() method
- // above won't be able to return.
- ASSERT(status[0].structureSet().size() == 1);
- ASSERT(status[0].constantChecks().isEmpty());
- ASSERT(!status[0].alternateBase());
</del><ins>+
+ AbstractValue& value = forNode(node->child1());
+ if (!value.m_structure.isTop() && !value.m_structure.isClobbered()
+ && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
+ GetByIdStatus status = GetByIdStatus::computeFor(
+ m_graph.m_vm, value.m_structure.set(),
+ m_graph.identifiers()[node->identifierNumber()]);
+ if (status.isSimple()) {
+ // Figure out what the result is going to be - is it TOP, a constant, or maybe
+ // something more subtle?
+ AbstractValue result;
+ for (unsigned i = status.numVariants(); i--;) {
+ if (!status[i].specificValue()) {
+ result.makeHeapTop();
+ break;
+ }
</ins><span class="cx">
</span><del>- if (status[0].specificValue()) {
- if (status[0].specificValue().isCell()) {
- Structure* structure = status[0].specificValue().asCell()->structure();
- m_graph.watchpoints().consider(structure);
- }
- setConstant(node, *m_graph.freeze(status[0].specificValue()));
- } else
- forNode(node).makeHeapTop();
- filter(node->child1(), status[0].structureSet());
-
</del><ins>+ AbstractValue thisResult;
+ thisResult.set(
+ m_graph, *m_graph.freeze(status[i].specificValue()),
+ m_state.structureClobberState());
+ result.merge(thisResult);
+ }
+ if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
</ins><span class="cx"> m_state.setFoundConstants(true);
</span><del>- break;
- }
</del><ins>+ forNode(node) = result;
+ break;
</ins><span class="cx"> }
</span><span class="cx"> }
</span><ins>+
</ins><span class="cx"> clobberWorld(node->origin.semantic, clobberLimit);
</span><span class="cx"> forNode(node).makeHeapTop();
</span><span class="cx"> break;
</span><ins>+ }
</ins><span class="cx">
</span><span class="cx"> case GetArrayLength:
</span><span class="cx"> forNode(node).setType(SpecInt32);
</span><span class="lines">@@ -1685,37 +1684,46 @@
</span><span class="cx">
</span><span class="cx"> case PutById:
</span><span class="cx"> case PutByIdFlush:
</span><del>- case PutByIdDirect:
- // This use of onlyStructure() should be replaced by giving PutByIdStatus the ability
- // to compute things based on a StructureSet, and then to factor ByteCodeParser's
- // ability to generate code based on a PutByIdStatus out of ByteCodeParser so that
- // ConstantFoldingPhase can use it.
- // https://bugs.webkit.org/show_bug.cgi?id=133229
- if (Structure* structure = forNode(node->child1()).m_structure.onlyStructure()) {
</del><ins>+ case PutByIdDirect: {
+ AbstractValue& value = forNode(node->child1());
+ if (!value.m_structure.isTop() && !value.m_structure.isClobbered()) {
</ins><span class="cx"> PutByIdStatus status = PutByIdStatus::computeFor(
</span><span class="cx"> m_graph.m_vm,
</span><span class="cx"> m_graph.globalObjectFor(node->origin.semantic),
</span><del>- structure,
</del><ins>+ value.m_structure.set(),
</ins><span class="cx"> m_graph.identifiers()[node->identifierNumber()],
</span><span class="cx"> node->op() == PutByIdDirect);
</span><del>- if (status.isSimple() && status.numVariants() == 1) {
- if (status[0].kind() == PutByIdVariant::Replace) {
- filter(node->child1(), structure);
- m_state.setFoundConstants(true);
- break;
</del><ins>+
+ if (status.isSimple()) {
+ StructureSet newSet;
+ TransitionVector transitions;
+
+ for (unsigned i = status.numVariants(); i--;) {
+ const PutByIdVariant& variant = status[i];
+ if (variant.kind() == PutByIdVariant::Transition) {
+ transitions.append(
+ Transition(
+ variant.oldStructureForTransition(), variant.newStructure()));
+ newSet.add(variant.newStructure());
+ } else {
+ ASSERT(variant.kind() == PutByIdVariant::Replace);
+ newSet.merge(variant.oldStructure());
+ }
</ins><span class="cx"> }
</span><del>- if (status[0].kind() == PutByIdVariant::Transition
- && structure->transitionWatchpointSetHasBeenInvalidated()) {
- m_graph.watchpoints().consider(status[0].newStructure());
- clobberStructures(clobberLimit);
- forNode(node->child1()).set(m_graph, status[0].newStructure());
</del><ins>+
+ if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
</ins><span class="cx"> m_state.setFoundConstants(true);
</span><del>- break;
- }
</del><ins>+
+ observeTransitions(clobberLimit, transitions);
+ if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
+ m_state.setIsValid(false);
+ break;
</ins><span class="cx"> }
</span><span class="cx"> }
</span><ins>+
</ins><span class="cx"> clobberWorld(node->origin.semantic, clobberLimit);
</span><span class="cx"> break;
</span><ins>+ }
</ins><span class="cx">
</span><span class="cx"> case In:
</span><span class="cx"> // FIXME: We can determine when the property definitely exists based on abstract
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (170274 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-06-23 00:51:33 UTC (rev 170274)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -2862,7 +2862,9 @@
</span><span class="cx"> case GlobalPropertyWithVarInjectionChecks: {
</span><span class="cx"> SpeculatedType prediction = getPrediction();
</span><span class="cx"> GetByIdStatus status = GetByIdStatus::computeFor(*m_vm, structure, uid);
</span><del>- if (status.state() != GetByIdStatus::Simple || status.numVariants() != 1) {
</del><ins>+ if (status.state() != GetByIdStatus::Simple
+ || status.numVariants() != 1
+ || status[0].structureSet().size() != 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><span class="lines">@@ -2947,7 +2949,9 @@
</span><span class="cx"> case GlobalProperty:
</span><span class="cx"> case GlobalPropertyWithVarInjectionChecks: {
</span><span class="cx"> PutByIdStatus status = PutByIdStatus::computeFor(*m_vm, globalObject, structure, uid, false);
</span><del>- if (status.numVariants() != 1 || status[0].kind() != PutByIdVariant::Replace) {
</del><ins>+ if (status.numVariants() != 1
+ || status[0].kind() != PutByIdVariant::Replace
+ || status[0].structure().size() != 1) {
</ins><span class="cx"> addToGraph(PutById, OpInfo(identifierNumber), get(VirtualRegister(scope)), get(VirtualRegister(value)));
</span><span class="cx"> break;
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (170274 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2014-06-23 00:51:33 UTC (rev 170274)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -228,35 +228,47 @@
</span><span class="cx"> Node* child = childEdge.node();
</span><span class="cx"> unsigned identifierNumber = node->identifierNumber();
</span><span class="cx">
</span><del>- if (childEdge.useKind() != CellUse)
- break;
-
</del><span class="cx"> AbstractValue baseValue = m_state.forNode(child);
</span><span class="cx">
</span><span class="cx"> m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
</span><span class="cx"> eliminated = true; // Don't allow the default constant folder to do things to this.
</span><span class="cx">
</span><del>- Structure* structure = baseValue.m_structure.onlyStructure();
- if (!structure)
</del><ins>+ if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered()
+ || (node->child1().useKind() == UntypedUse || (baseValue.m_type & ~SpecCell)))
</ins><span class="cx"> break;
</span><del>-
</del><ins>+
</ins><span class="cx"> GetByIdStatus status = GetByIdStatus::computeFor(
</span><del>- vm(), structure, m_graph.identifiers()[identifierNumber]);
</del><ins>+ vm(), baseValue.m_structure.set(), m_graph.identifiers()[identifierNumber]);
+ if (!status.isSimple())
+ break;
</ins><span class="cx">
</span><del>- if (!status.isSimple() || status.numVariants() != 1 ||
- !status[0].constantChecks().isEmpty() || status[0].alternateBase()) {
- // FIXME: We could handle prototype cases.
- // https://bugs.webkit.org/show_bug.cgi?id=110386
</del><ins>+ for (unsigned i = status.numVariants(); i--;) {
+ if (!status[i].constantChecks().isEmpty()
+ || status[i].alternateBase()) {
+ // FIXME: We could handle prototype cases.
+ // https://bugs.webkit.org/show_bug.cgi?id=110386
+ break;
+ }
+ }
+
+ if (status.numVariants() == 1) {
+ emitGetByOffset(indexInBlock, node, baseValue, status[0], identifierNumber);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- emitGetByOffset(indexInBlock, node, baseValue, status[0], identifierNumber);
- eliminated = true;
</del><ins>+ if (!isFTL(m_graph.m_plan.mode))
+ break;
+
+ MultiGetByOffsetData* data = m_graph.m_multiGetByOffsetData.add();
+ data->variants = status.variants();
+ data->identifierNumber = identifierNumber;
+ node->convertToMultiGetByOffset(data);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case PutById:
</span><del>- case PutByIdDirect: {
</del><ins>+ case PutByIdDirect:
+ case PutByIdFlush: {
</ins><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="lines">@@ -269,24 +281,34 @@
</span><span class="cx"> m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
</span><span class="cx"> eliminated = true; // Don't allow the default constant folder to do things to this.
</span><span class="cx">
</span><del>- Structure* structure = baseValue.m_structure.onlyStructure();
- if (!structure)
</del><ins>+ if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered())
</ins><span class="cx"> break;
</span><span class="cx">
</span><span class="cx"> PutByIdStatus status = PutByIdStatus::computeFor(
</span><span class="cx"> vm(),
</span><span class="cx"> m_graph.globalObjectFor(origin.semantic),
</span><del>- structure,
</del><ins>+ baseValue.m_structure.set(),
</ins><span class="cx"> m_graph.identifiers()[identifierNumber],
</span><span class="cx"> node->op() == PutByIdDirect);
</span><span class="cx">
</span><span class="cx"> if (!status.isSimple())
</span><span class="cx"> break;
</span><del>- if (status.numVariants() != 1)
</del><ins>+
+ for (unsigned i = status.numVariants(); i--;)
+ addChecks(origin, indexInBlock, status[i].constantChecks());
+
+ if (status.numVariants() == 1) {
+ emitPutByOffset(indexInBlock, node, baseValue, status[0], identifierNumber);
</ins><span class="cx"> break;
</span><ins>+ }
</ins><span class="cx">
</span><del>- emitPutByOffset(indexInBlock, node, baseValue, status[0], identifierNumber);
- eliminated = true;
</del><ins>+ if (!isFTL(m_graph.m_plan.mode))
+ break;
+
+ MultiPutByOffsetData* data = m_graph.m_multiPutByOffsetData.add();
+ data->variants = status.variants();
+ data->identifierNumber = identifierNumber;
+ node->convertToMultiPutByOffset(data);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -426,13 +448,6 @@
</span><span class="cx"> if (variant.kind() == PutByIdVariant::Transition) {
</span><span class="cx"> transition = m_graph.m_transitions.add(
</span><span class="cx"> variant.oldStructureForTransition(), variant.newStructure());
</span><del>-
- for (unsigned i = 0; i < variant.constantChecks().size(); ++i) {
- addStructureTransitionCheck(
- origin, indexInBlock,
- variant.constantChecks()[i].constant(),
- variant.constantChecks()[i].structure());
- }
</del><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> Edge propertyStorage;
</span><span class="lines">@@ -499,6 +514,15 @@
</span><span class="cx"> indexInBlock, SpecNone, Phantom, node->origin, node->child1());
</span><span class="cx"> }
</span><span class="cx"> }
</span><ins>+
+ void addChecks(
+ NodeOrigin origin, unsigned indexInBlock, const ConstantStructureCheckVector& checks)
+ {
+ for (unsigned i = 0; i < checks.size(); ++i) {
+ addStructureTransitionCheck(
+ origin, indexInBlock, checks[i].constant(), checks[i].structure());
+ }
+ }
</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="branchesftloptSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGNode.h (170274 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGNode.h        2014-06-23 00:51:33 UTC (rev 170274)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGNode.h        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -458,6 +458,15 @@
</span><span class="cx"> m_flags &= ~NodeClobbersWorld;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ void convertToMultiGetByOffset(MultiGetByOffsetData* data)
+ {
+ ASSERT(m_op == GetById || m_op == GetByIdFlush);
+ m_opInfo = bitwise_cast<intptr_t>(data);
+ child1().setUseKind(CellUse);
+ m_op = MultiGetByOffset;
+ m_flags &= ~NodeClobbersWorld;
+ }
+
</ins><span class="cx"> void convertToPutByOffset(unsigned storageAccessDataIndex, Edge storage)
</span><span class="cx"> {
</span><span class="cx"> ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == MultiPutByOffset);
</span><span class="lines">@@ -469,6 +478,14 @@
</span><span class="cx"> m_flags &= ~NodeClobbersWorld;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ void convertToMultiPutByOffset(MultiPutByOffsetData* data)
+ {
+ ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush);
+ m_opInfo = bitwise_cast<intptr_t>(data);
+ m_op = MultiPutByOffset;
+ m_flags &= ~NodeClobbersWorld;
+ }
+
</ins><span class="cx"> void convertToPhantomLocal()
</span><span class="cx"> {
</span><span class="cx"> ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (170274 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-06-23 00:51:33 UTC (rev 170274)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -97,7 +97,7 @@
</span><span class="cx">
</span><span class="cx"> default:
</span><span class="cx"> m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
</span><del>- RELEASE_ASSERT(spillFormat & DataFormatJS);
</del><ins>+ DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat & DataFormatJS);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> info.fillJSValue(*m_stream, gpr, spillFormat);
</span><span class="lines">@@ -137,10 +137,10 @@
</span><span class="cx"> case DataFormatDouble:
</span><span class="cx"> case DataFormatInt52:
</span><span class="cx"> // this type currently never occurs
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
</ins><span class="cx">
</span><span class="cx"> default:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
</ins><span class="cx"> return InvalidGPRReg;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -311,7 +311,7 @@
</span><span class="cx"> if (branchIndexInBlock != UINT_MAX) {
</span><span class="cx"> Node* branchNode = m_block->at(branchIndexInBlock);
</span><span class="cx">
</span><del>- RELEASE_ASSERT(node->adjustedRefCount() == 1);
</del><ins>+ DFG_ASSERT(m_jit.graph(), node, node->adjustedRefCount() == 1);
</ins><span class="cx">
</span><span class="cx"> nonSpeculativePeepholeBranchNull(operand, branchNode, invert);
</span><span class="cx">
</span><span class="lines">@@ -628,8 +628,8 @@
</span><span class="cx">
</span><span class="cx"> bool isCall = node->op() == Call;
</span><span class="cx"> if (!isCall)
</span><del>- RELEASE_ASSERT(node->op() == Construct);
-
</del><ins>+ DFG_ASSERT(m_jit.graph(), node, node->op() == Construct);
+
</ins><span class="cx"> // For constructors, the this argument is not passed but we have to make space
</span><span class="cx"> // for it.
</span><span class="cx"> int dummyThisArgument = isCall ? 0 : 1;
</span><span class="lines">@@ -741,7 +741,7 @@
</span><span class="cx">
</span><span class="cx"> DataFormat spillFormat = info.spillFormat();
</span><span class="cx">
</span><del>- RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32);
</del><ins>+ DFG_ASSERT(m_jit.graph(), m_currentNode, (spillFormat & DataFormatJS) || spillFormat == DataFormatInt32);
</ins><span class="cx">
</span><span class="cx"> m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
</span><span class="cx">
</span><span class="lines">@@ -771,7 +771,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case DataFormatJS: {
</span><del>- RELEASE_ASSERT(!(type & SpecInt52));
</del><ins>+ DFG_ASSERT(m_jit.graph(), m_currentNode, !(type & SpecInt52));
</ins><span class="cx"> // Check the value is an integer.
</span><span class="cx"> GPRReg gpr = info.gpr();
</span><span class="cx"> m_gprs.lock(gpr);
</span><span class="lines">@@ -834,10 +834,10 @@
</span><span class="cx"> case DataFormatStorage:
</span><span class="cx"> case DataFormatInt52:
</span><span class="cx"> case DataFormatStrictInt52:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
</ins><span class="cx">
</span><span class="cx"> default:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
</ins><span class="cx"> return InvalidGPRReg;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -854,7 +854,7 @@
</span><span class="cx"> {
</span><span class="cx"> DataFormat mustBeDataFormatInt32;
</span><span class="cx"> GPRReg result = fillSpeculateInt32Internal<true>(edge, mustBeDataFormatInt32);
</span><del>- RELEASE_ASSERT(mustBeDataFormatInt32 == DataFormatInt32);
</del><ins>+ DFG_ASSERT(m_jit.graph(), m_currentNode, mustBeDataFormatInt32 == DataFormatInt32);
</ins><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -889,7 +889,7 @@
</span><span class="cx">
</span><span class="cx"> DataFormat spillFormat = info.spillFormat();
</span><span class="cx">
</span><del>- RELEASE_ASSERT(spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
</del><ins>+ DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
</ins><span class="cx">
</span><span class="cx"> m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
</span><span class="cx">
</span><span class="lines">@@ -941,7 +941,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> default:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
</ins><span class="cx"> return InvalidGPRReg;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -972,7 +972,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> DataFormat spillFormat = info.spillFormat();
</span><del>- RELEASE_ASSERT(spillFormat == DataFormatDouble);
</del><ins>+ DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatDouble);
</ins><span class="cx"> FPRReg fpr = fprAllocate();
</span><span class="cx"> m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
</span><span class="cx"> m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
</span><span class="lines">@@ -980,7 +980,7 @@
</span><span class="cx"> return fpr;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- RELEASE_ASSERT(info.registerFormat() == DataFormatDouble);
</del><ins>+ DFG_ASSERT(m_jit.graph(), m_currentNode, info.registerFormat() == DataFormatDouble);
</ins><span class="cx"> FPRReg fpr = info.fpr();
</span><span class="cx"> m_fprs.lock(fpr);
</span><span class="cx"> return fpr;
</span><span class="lines">@@ -1010,7 +1010,7 @@
</span><span class="cx"> terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
</span><span class="cx"> return gpr;
</span><span class="cx"> }
</span><del>- RELEASE_ASSERT(info.spillFormat() & DataFormatJS);
</del><ins>+ DFG_ASSERT(m_jit.graph(), m_currentNode, info.spillFormat() & DataFormatJS);
</ins><span class="cx"> m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
</span><span class="cx"> m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
</span><span class="cx">
</span><span class="lines">@@ -1055,10 +1055,10 @@
</span><span class="cx"> case DataFormatStorage:
</span><span class="cx"> case DataFormatInt52:
</span><span class="cx"> case DataFormatStrictInt52:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
</ins><span class="cx">
</span><span class="cx"> default:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
</ins><span class="cx"> return InvalidGPRReg;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -1091,7 +1091,7 @@
</span><span class="cx"> terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
</span><span class="cx"> return gpr;
</span><span class="cx"> }
</span><del>- RELEASE_ASSERT(info.spillFormat() & DataFormatJS);
</del><ins>+ DFG_ASSERT(m_jit.graph(), m_currentNode, info.spillFormat() & DataFormatJS);
</ins><span class="cx"> m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
</span><span class="cx"> m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
</span><span class="cx">
</span><span class="lines">@@ -1136,10 +1136,10 @@
</span><span class="cx"> case DataFormatStorage:
</span><span class="cx"> case DataFormatInt52:
</span><span class="cx"> case DataFormatStrictInt52:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
</ins><span class="cx">
</span><span class="cx"> default:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
</ins><span class="cx"> return InvalidGPRReg;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -1603,7 +1603,7 @@
</span><span class="cx"> return compileStringZeroLength(node);
</span><span class="cx">
</span><span class="cx"> default:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), node, "Bad use kind");
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -1758,7 +1758,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> default:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), m_currentNode, "Bad use kind");
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1783,7 +1783,7 @@
</span><span class="cx">
</span><span class="cx"> case Identity: {
</span><span class="cx"> // CSE should always eliminate this.
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), node, "Unexpected Identity node");
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1864,7 +1864,7 @@
</span><span class="cx"> case MovHint:
</span><span class="cx"> case ZombieHint:
</span><span class="cx"> case Check: {
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), node, "Unexpected node");
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1924,7 +1924,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> default:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), node, "Bad flush format");
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -2103,7 +2103,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> default:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), node, "Bad use kind");
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> break;
</span><span class="lines">@@ -2170,7 +2170,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> default:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), node, "Bad use kind");
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> break;
</span><span class="lines">@@ -2292,8 +2292,7 @@
</span><span class="cx"> switch (node->arrayMode().type()) {
</span><span class="cx"> case Array::SelectUsingPredictions:
</span><span class="cx"> case Array::ForceExit:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
- terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
</del><ins>+ DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
</ins><span class="cx"> break;
</span><span class="cx"> case Array::Generic: {
</span><span class="cx"> JSValueOperand base(this, node->child1());
</span><span class="lines">@@ -2494,12 +2493,10 @@
</span><span class="cx"> switch (arrayMode.type()) {
</span><span class="cx"> case Array::SelectUsingPredictions:
</span><span class="cx"> case Array::ForceExit:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
- terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
- alreadyHandled = true;
</del><ins>+ DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
</ins><span class="cx"> break;
</span><span class="cx"> case Array::Generic: {
</span><del>- RELEASE_ASSERT(node->op() == PutByVal);
</del><ins>+ DFG_ASSERT(m_jit.graph(), node, node->op() == PutByVal);
</ins><span class="cx">
</span><span class="cx"> JSValueOperand arg1(this, child1);
</span><span class="cx"> JSValueOperand arg2(this, child2);
</span><span class="lines">@@ -3038,7 +3035,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case ToPrimitive: {
</span><del>- RELEASE_ASSERT(node->child1().useKind() == UntypedUse);
</del><ins>+ DFG_ASSERT(m_jit.graph(), node, node->child1().useKind() == UntypedUse);
</ins><span class="cx"> JSValueOperand op1(this, node->child1());
</span><span class="cx"> GPRTemporary result(this, Reuse, op1);
</span><span class="cx">
</span><span class="lines">@@ -3105,7 +3102,7 @@
</span><span class="cx"> JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
</span><span class="cx"> if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(node->indexingType())) {
</span><span class="cx"> Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType());
</span><del>- RELEASE_ASSERT(structure->indexingType() == node->indexingType());
</del><ins>+ DFG_ASSERT(m_jit.graph(), node, structure->indexingType() == node->indexingType());
</ins><span class="cx"> ASSERT(
</span><span class="cx"> hasUndecided(structure->indexingType())
</span><span class="cx"> || hasInt32(structure->indexingType())
</span><span class="lines">@@ -3356,7 +3353,7 @@
</span><span class="cx">
</span><span class="cx"> emitAllocateJSArray(resultGPR, globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType), storageGPR, numElements);
</span><span class="cx">
</span><del>- RELEASE_ASSERT(indexingType & IsArray);
</del><ins>+ DFG_ASSERT(m_jit.graph(), node, indexingType & IsArray);
</ins><span class="cx"> JSValue* data = m_jit.codeBlock()->constantBuffer(node->startConstant());
</span><span class="cx"> if (indexingType == ArrayWithDouble) {
</span><span class="cx"> for (unsigned index = 0; index < node->numConstants(); ++index) {
</span><span class="lines">@@ -3410,7 +3407,7 @@
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> default:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), node, "Bad use kind");
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> break;
</span><span class="lines">@@ -3640,7 +3637,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> default:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), node, "Bad use kind");
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> break;
</span><span class="lines">@@ -3690,7 +3687,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> default:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), node, "Bad use kind");
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> break;
</span><span class="lines">@@ -4154,7 +4151,7 @@
</span><span class="cx"> break;
</span><span class="cx">
</span><span class="cx"> case CreateActivation: {
</span><del>- RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);
</del><ins>+ DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame);
</ins><span class="cx">
</span><span class="cx"> JSValueOperand value(this, node->child1());
</span><span class="cx"> GPRTemporary result(this, Reuse, value);
</span><span class="lines">@@ -4227,7 +4224,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case TearOffActivation: {
</span><del>- RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);
</del><ins>+ DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame);
</ins><span class="cx">
</span><span class="cx"> JSValueOperand activationValue(this, node->child1());
</span><span class="cx"> GPRTemporary scratch(this);
</span><span class="lines">@@ -4299,7 +4296,7 @@
</span><span class="cx"> m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic))));
</span><span class="cx"> }
</span><span class="cx">
</span><del>- RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);
</del><ins>+ DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame);
</ins><span class="cx"> m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), resultGPR);
</span><span class="cx"> m_jit.sub32(TrustedImm32(1), resultGPR);
</span><span class="cx"> int32Result(resultGPR, node);
</span><span class="lines">@@ -4375,7 +4372,7 @@
</span><span class="cx"> JITCompiler::JumpList slowArgument;
</span><span class="cx"> JITCompiler::JumpList slowArgumentOutOfBounds;
</span><span class="cx"> if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) {
</span><del>- RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);
</del><ins>+ DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame);
</ins><span class="cx"> const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get();
</span><span class="cx">
</span><span class="cx"> slowArgumentOutOfBounds.append(
</span><span class="lines">@@ -4442,7 +4439,7 @@
</span><span class="cx"> JITCompiler::JumpList slowArgument;
</span><span class="cx"> JITCompiler::JumpList slowArgumentOutOfBounds;
</span><span class="cx"> if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) {
</span><del>- RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);
</del><ins>+ DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame);
</ins><span class="cx"> const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get();
</span><span class="cx">
</span><span class="cx"> slowArgumentOutOfBounds.append(
</span><span class="lines">@@ -4576,7 +4573,7 @@
</span><span class="cx"> break;
</span><span class="cx">
</span><span class="cx"> case Unreachable:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), node, "Unexpected Unreachable node");
</ins><span class="cx"> break;
</span><span class="cx">
</span><span class="cx"> case StoreBarrier:
</span><span class="lines">@@ -4644,7 +4641,7 @@
</span><span class="cx"> case CheckTierUpInLoop:
</span><span class="cx"> case CheckTierUpAtReturn:
</span><span class="cx"> case CheckTierUpAndOSREnter:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), node, "Unexpected tier-up node");
</ins><span class="cx"> break;
</span><span class="cx"> #endif // ENABLE(FTL_JIT)
</span><span class="cx">
</span><span class="lines">@@ -4659,7 +4656,7 @@
</span><span class="cx"> case ArithIMul:
</span><span class="cx"> case MultiGetByOffset:
</span><span class="cx"> case MultiPutByOffset:
</span><del>- RELEASE_ASSERT_NOT_REACHED();
</del><ins>+ DFG_CRASH(m_jit.graph(), node, "Unexpected FTL-only node");
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGStructureAbstractValueh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h (170274 => 170275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h        2014-06-23 00:51:33 UTC (rev 170274)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h        2014-06-23 01:02:01 UTC (rev 170275)
</span><span class="lines">@@ -161,6 +161,12 @@
</span><span class="cx"> return equalsSlow(other);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ const StructureSet& set() const
+ {
+ ASSERT(!isTop());
+ return m_set;
+ }
+
</ins><span class="cx"> size_t size() const
</span><span class="cx"> {
</span><span class="cx"> ASSERT(!isTop());
</span></span></pre>
</div>
</div>
</body>
</html>