<!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>[169902] 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/169902">169902</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-06-12 10:42:10 -0700 (Thu, 12 Jun 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>[ftlopt] DFG get_by_id should inline chain accesses with a slightly polymorphic base
https://bugs.webkit.org/show_bug.cgi?id=133751
Reviewed by Mark Hahnenberg.
Source/JavaScriptCore:
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::appendVariant):
(JSC::GetByIdStatus::computeForStubInfo):
* bytecode/GetByIdVariant.cpp:
(JSC::GetByIdVariant::attemptToMerge):
* bytecode/GetByIdVariant.h:
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeFor):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::emitPrototypeChecks):
(JSC::DFG::ByteCodeParser::handleGetById):
(JSC::DFG::ByteCodeParser::handlePutById):
* runtime/IntendedStructureChain.cpp:
(JSC::IntendedStructureChain::IntendedStructureChain):
(JSC::IntendedStructureChain::isStillValid):
(JSC::IntendedStructureChain::isNormalized):
(JSC::IntendedStructureChain::terminalPrototype):
(JSC::IntendedStructureChain::operator==):
(JSC::IntendedStructureChain::visitChildren):
(JSC::IntendedStructureChain::dumpInContext):
(JSC::IntendedStructureChain::chain): Deleted.
* runtime/IntendedStructureChain.h:
(JSC::IntendedStructureChain::prototype):
(JSC::IntendedStructureChain::operator!=):
(JSC::IntendedStructureChain::head): Deleted.
LayoutTests:
* js/regress/poly-chain-access-expected.txt: Added.
* js/regress/poly-chain-access-simpler-expected.txt: Added.
* js/regress/poly-chain-access-simpler.html: Added.
* js/regress/poly-chain-access.html: Added.
* js/regress/script-tests/poly-chain-access-simpler.js: Added.
* js/regress/script-tests/poly-chain-access.js: Added.</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="#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="#branchesftloptSourceJavaScriptCorebytecodePutByIdStatuscpp">branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGByteCodeParsercpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeIntendedStructureChaincpp">branches/ftlopt/Source/JavaScriptCore/runtime/IntendedStructureChain.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeIntendedStructureChainh">branches/ftlopt/Source/JavaScriptCore/runtime/IntendedStructureChain.h</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#branchesftloptLayoutTestsjsregresspolychainaccessexpectedtxt">branches/ftlopt/LayoutTests/js/regress/poly-chain-access-expected.txt</a></li>
<li><a href="#branchesftloptLayoutTestsjsregresspolychainaccesssimplerexpectedtxt">branches/ftlopt/LayoutTests/js/regress/poly-chain-access-simpler-expected.txt</a></li>
<li><a href="#branchesftloptLayoutTestsjsregresspolychainaccesssimplerhtml">branches/ftlopt/LayoutTests/js/regress/poly-chain-access-simpler.html</a></li>
<li><a href="#branchesftloptLayoutTestsjsregresspolychainaccesshtml">branches/ftlopt/LayoutTests/js/regress/poly-chain-access.html</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressscripttestspolychainaccesssimplerjs">branches/ftlopt/LayoutTests/js/regress/script-tests/poly-chain-access-simpler.js</a></li>
<li><a href="#branchesftloptLayoutTestsjsregressscripttestspolychainaccessjs">branches/ftlopt/LayoutTests/js/regress/script-tests/poly-chain-access.js</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchesftloptLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/LayoutTests/ChangeLog (169901 => 169902)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/ChangeLog        2014-06-12 17:33:05 UTC (rev 169901)
+++ branches/ftlopt/LayoutTests/ChangeLog        2014-06-12 17:42:10 UTC (rev 169902)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2014-06-11 Filip Pizlo <fpizlo@apple.com>
+
+ [ftlopt] DFG get_by_id should inline chain accesses with a slightly polymorphic base
+ https://bugs.webkit.org/show_bug.cgi?id=133751
+
+ Reviewed by Mark Hahnenberg.
+
+ * js/regress/poly-chain-access-expected.txt: Added.
+ * js/regress/poly-chain-access-simpler-expected.txt: Added.
+ * js/regress/poly-chain-access-simpler.html: Added.
+ * js/regress/poly-chain-access.html: Added.
+ * js/regress/script-tests/poly-chain-access-simpler.js: Added.
+ * js/regress/script-tests/poly-chain-access.js: Added.
+
</ins><span class="cx"> 2014-06-01 Filip Pizlo <fpizlo@apple.com>
</span><span class="cx">
</span><span class="cx"> [ftlopt] AI should be able track structure sets larger than 1
</span></span></pre></div>
<a id="branchesftloptLayoutTestsjsregresspolychainaccessexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/poly-chain-access-expected.txt (0 => 169902)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/poly-chain-access-expected.txt         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/poly-chain-access-expected.txt        2014-06-12 17:42:10 UTC (rev 169902)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/poly-chain-access
+
+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="branchesftloptLayoutTestsjsregresspolychainaccesssimplerexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/poly-chain-access-simpler-expected.txt (0 => 169902)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/poly-chain-access-simpler-expected.txt         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/poly-chain-access-simpler-expected.txt        2014-06-12 17:42:10 UTC (rev 169902)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/poly-chain-access-simpler
+
+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="branchesftloptLayoutTestsjsregresspolychainaccesssimplerhtml"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/poly-chain-access-simpler.html (0 => 169902)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/poly-chain-access-simpler.html         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/poly-chain-access-simpler.html        2014-06-12 17:42:10 UTC (rev 169902)
</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/poly-chain-access-simpler.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="branchesftloptLayoutTestsjsregresspolychainaccesshtml"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/poly-chain-access.html (0 => 169902)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/poly-chain-access.html         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/poly-chain-access.html        2014-06-12 17:42:10 UTC (rev 169902)
</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/poly-chain-access.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="branchesftloptLayoutTestsjsregressscripttestspolychainaccesssimplerjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/script-tests/poly-chain-access-simpler.js (0 => 169902)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/script-tests/poly-chain-access-simpler.js         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/script-tests/poly-chain-access-simpler.js        2014-06-12 17:42:10 UTC (rev 169902)
</span><span class="lines">@@ -0,0 +1,26 @@
</span><ins>+(function() {
+ function Foo() { }
+ Foo.prototype.f = 42;
+ function Bar() { }
+ Bar.prototype = new Foo();
+
+ function foo(o, p) {
+ var n = 1000000;
+ var result = 0;
+ for (var i = 0; i < n; ++i) {
+ result += o.f;
+ var tmp = o;
+ o = p;
+ p = tmp;
+ }
+
+ if (result != n * 42)
+ throw "Error: bad result: " + result;
+ }
+
+ var o = new Bar();
+ var p = new Bar();
+ p.g = 43;
+
+ foo(o, p);
+})();
</ins></span></pre></div>
<a id="branchesftloptLayoutTestsjsregressscripttestspolychainaccessjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/LayoutTests/js/regress/script-tests/poly-chain-access.js (0 => 169902)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/LayoutTests/js/regress/script-tests/poly-chain-access.js         (rev 0)
+++ branches/ftlopt/LayoutTests/js/regress/script-tests/poly-chain-access.js        2014-06-12 17:42:10 UTC (rev 169902)
</span><span class="lines">@@ -0,0 +1,22 @@
</span><ins>+(function() {
+ function Foo() { }
+ Foo.prototype.f = 42;
+ function Bar() { }
+ Bar.prototype = new Foo();
+
+ var o = new Bar();
+ var p = new Bar();
+ p.g = 43;
+
+ var n = 1000000;
+ var result = 0;
+ for (var i = 0; i < n; ++i) {
+ result += o.f;
+ var tmp = o;
+ o = p;
+ p = tmp;
+ }
+
+ if (result != n * 42)
+ throw "Error: bad result: " + result;
+})();
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/ChangeLog (169901 => 169902)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/ChangeLog        2014-06-12 17:33:05 UTC (rev 169901)
+++ branches/ftlopt/Source/JavaScriptCore/ChangeLog        2014-06-12 17:42:10 UTC (rev 169902)
</span><span class="lines">@@ -1,3 +1,36 @@
</span><ins>+2014-06-11 Filip Pizlo <fpizlo@apple.com>
+
+ [ftlopt] DFG get_by_id should inline chain accesses with a slightly polymorphic base
+ https://bugs.webkit.org/show_bug.cgi?id=133751
+
+ Reviewed by Mark Hahnenberg.
+
+ * bytecode/GetByIdStatus.cpp:
+ (JSC::GetByIdStatus::appendVariant):
+ (JSC::GetByIdStatus::computeForStubInfo):
+ * bytecode/GetByIdVariant.cpp:
+ (JSC::GetByIdVariant::attemptToMerge):
+ * bytecode/GetByIdVariant.h:
+ * bytecode/PutByIdStatus.cpp:
+ (JSC::PutByIdStatus::computeFor):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::emitPrototypeChecks):
+ (JSC::DFG::ByteCodeParser::handleGetById):
+ (JSC::DFG::ByteCodeParser::handlePutById):
+ * runtime/IntendedStructureChain.cpp:
+ (JSC::IntendedStructureChain::IntendedStructureChain):
+ (JSC::IntendedStructureChain::isStillValid):
+ (JSC::IntendedStructureChain::isNormalized):
+ (JSC::IntendedStructureChain::terminalPrototype):
+ (JSC::IntendedStructureChain::operator==):
+ (JSC::IntendedStructureChain::visitChildren):
+ (JSC::IntendedStructureChain::dumpInContext):
+ (JSC::IntendedStructureChain::chain): Deleted.
+ * runtime/IntendedStructureChain.h:
+ (JSC::IntendedStructureChain::prototype):
+ (JSC::IntendedStructureChain::operator!=):
+ (JSC::IntendedStructureChain::head): Deleted.
+
</ins><span class="cx"> 2014-06-11 Matthew Mirman <mmirman@apple.com>
</span><span class="cx">
</span><span class="cx"> Readded native calling to the FTL and Split the DFG nodes
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodeGetByIdStatuscpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp (169901 => 169902)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp        2014-06-12 17:33:05 UTC (rev 169901)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp        2014-06-12 17:42:10 UTC (rev 169902)
</span><span class="lines">@@ -39,10 +39,20 @@
</span><span class="cx">
</span><span class="cx"> bool GetByIdStatus::appendVariant(const GetByIdVariant& variant)
</span><span class="cx"> {
</span><ins>+ // Attempt to merge this variant with an already existing variant.
</ins><span class="cx"> for (unsigned i = 0; i < m_variants.size(); ++i) {
</span><ins>+ if (m_variants[i].attemptToMerge(variant))
+ return true;
+ }
+
+ // Make sure there is no overlap. We should have pruned out opportunities for
+ // overlap but it's possible that an inline cache got into a weird state. We are
+ // defensive and bail if we detect crazy.
+ for (unsigned i = 0; i < m_variants.size(); ++i) {
</ins><span class="cx"> if (m_variants[i].structureSet().overlaps(variant.structureSet()))
</span><span class="cx"> return false;
</span><span class="cx"> }
</span><ins>+
</ins><span class="cx"> m_variants.append(variant);
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="lines">@@ -187,10 +197,12 @@
</span><span class="cx"> profiledBlock, structure, list->at(listIndex).chain(),
</span><span class="cx"> list->at(listIndex).chainCount()));
</span><span class="cx">
</span><del>- if (!chain->isStillValid())
- return GetByIdStatus(slowPathState, true);
</del><ins>+ if (!chain->isStillValid()) {
+ // This won't ever run again so skip it.
+ continue;
+ }
</ins><span class="cx">
</span><del>- if (chain->head()->takesSlowPathInDFGForImpureProperty())
</del><ins>+ if (structure->takesSlowPathInDFGForImpureProperty())
</ins><span class="cx"> return GetByIdStatus(slowPathState, true);
</span><span class="cx">
</span><span class="cx"> size_t chainSize = chain->size();
</span><span class="lines">@@ -217,36 +229,7 @@
</span><span class="cx">
</span><span class="cx"> if (!isValidOffset(myOffset))
</span><span class="cx"> return GetByIdStatus(slowPathState, true);
</span><del>-
- if (!chain && !list->at(listIndex).doesCalls()) {
- // For non-chain, non-getter accesses, we try to do some coalescing.
- bool found = false;
- for (unsigned variantIndex = 0; variantIndex < result.m_variants.size(); ++variantIndex) {
- GetByIdVariant& variant = result.m_variants[variantIndex];
- if (variant.m_chain)
- continue;
-
- if (variant.m_offset != myOffset)
- continue;
-
- if (variant.callLinkStatus())
- continue;
-
- found = true;
- if (variant.m_structureSet.contains(structure))
- break;
-
- if (variant.m_specificValue != JSValue(specificValue))
- variant.m_specificValue = JSValue();
-
- variant.m_structureSet.add(structure);
- break;
- }
</del><span class="cx">
</span><del>- if (found)
- continue;
- }
-
</del><span class="cx"> std::unique_ptr<CallLinkStatus> callLinkStatus;
</span><span class="cx"> switch (list->at(listIndex).type()) {
</span><span class="cx"> case GetByIdAccess::SimpleInline:
</span><span class="lines">@@ -272,6 +255,7 @@
</span><span class="cx"> GetByIdVariant variant(
</span><span class="cx"> StructureSet(structure), myOffset, specificValue, chain,
</span><span class="cx"> std::move(callLinkStatus));
</span><ins>+
</ins><span class="cx"> if (!result.appendVariant(variant))
</span><span class="cx"> return GetByIdStatus(slowPathState, true);
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodeGetByIdVariantcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp (169901 => 169902)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp        2014-06-12 17:33:05 UTC (rev 169901)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp        2014-06-12 17:42:10 UTC (rev 169902)
</span><span class="lines">@@ -51,6 +51,25 @@
</span><span class="cx"> return *this;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+bool GetByIdVariant::attemptToMerge(const GetByIdVariant& other)
+{
+ if (!!m_chain != !!other.m_chain)
+ return false;
+ if (m_chain && *m_chain != *other.m_chain)
+ return false;
+ if (m_offset != other.m_offset)
+ return false;
+ if (m_callLinkStatus || other.m_callLinkStatus)
+ return false;
+
+ if (m_specificValue != other.m_specificValue)
+ m_specificValue = JSValue();
+
+ m_structureSet.merge(other.m_structureSet);
+
+ return true;
+}
+
</ins><span class="cx"> void GetByIdVariant::dump(PrintStream& out) const
</span><span class="cx"> {
</span><span class="cx"> dumpInContext(out, 0);
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodeGetByIdVarianth"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdVariant.h (169901 => 169902)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdVariant.h        2014-06-12 17:33:05 UTC (rev 169901)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/GetByIdVariant.h        2014-06-12 17:42:10 UTC (rev 169902)
</span><span class="lines">@@ -71,6 +71,8 @@
</span><span class="cx"> PropertyOffset offset() const { return m_offset; }
</span><span class="cx"> CallLinkStatus* callLinkStatus() const { return m_callLinkStatus.get(); }
</span><span class="cx">
</span><ins>+ bool attemptToMerge(const GetByIdVariant& other);
+
</ins><span class="cx"> void dump(PrintStream&) const;
</span><span class="cx"> void dumpInContext(PrintStream&, DumpContext*) const;
</span><span class="cx">
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodePutByIdStatuscpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp (169901 => 169902)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp        2014-06-12 17:33:05 UTC (rev 169901)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp        2014-06-12 17:42:10 UTC (rev 169902)
</span><span class="lines">@@ -309,7 +309,7 @@
</span><span class="cx"> // dictionaries if we have evidence to suggest that those objects were never used as
</span><span class="cx"> // prototypes in a cacheable prototype access - i.e. there's a good chance that some of
</span><span class="cx"> // the other checks below will fail.
</span><del>- if (!chain->isNormalized())
</del><ins>+ if (structure->isProxy() || !chain->isNormalized())
</ins><span class="cx"> return PutByIdStatus(TakesSlowPath);
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (169901 => 169902)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-06-12 17:33:05 UTC (rev 169901)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-06-12 17:42:10 UTC (rev 169902)
</span><span class="lines">@@ -192,7 +192,7 @@
</span><span class="cx"> void handlePutById(
</span><span class="cx"> Node* base, unsigned identifierNumber, Node* value, const PutByIdStatus&,
</span><span class="cx"> bool isDirect);
</span><del>- Node* emitPrototypeChecks(Structure*, IntendedStructureChain*);
</del><ins>+ Node* emitPrototypeChecks(IntendedStructureChain*);
</ins><span class="cx">
</span><span class="cx"> Node* getScope(bool skipTop, unsigned skipCount);
</span><span class="cx">
</span><span class="lines">@@ -1705,18 +1705,18 @@
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-Node* ByteCodeParser::emitPrototypeChecks(
- Structure* structure, IntendedStructureChain* chain)
</del><ins>+Node* ByteCodeParser::emitPrototypeChecks(IntendedStructureChain* chain)
</ins><span class="cx"> {
</span><del>- ASSERT(structure);
- Node* base = 0;
</del><span class="cx"> m_graph.chains().addLazily(chain);
</span><del>- Structure* currentStructure = structure;
- JSObject* currentObject = 0;
</del><ins>+ JSValue prototype = chain->prototype();
+ if (prototype.isNull())
+ return nullptr;
+ Node* base = nullptr;
</ins><span class="cx"> for (unsigned i = 0; i < chain->size(); ++i) {
</span><del>- currentObject = asObject(currentStructure->prototypeForLookup(m_inlineStackTop->m_codeBlock));
- currentStructure = chain->at(i);
</del><ins>+ JSObject* currentObject = asObject(prototype);
+ Structure* currentStructure = chain->at(i);
</ins><span class="cx"> base = cellConstantWithStructureCheck(currentObject, currentStructure);
</span><ins>+ prototype = currentStructure->prototypeForLookup(m_inlineStackTop->m_codeBlock);
</ins><span class="cx"> }
</span><span class="cx"> return base;
</span><span class="cx"> }
</span><span class="lines">@@ -1748,11 +1748,8 @@
</span><span class="cx"> // optimal, if there is some rarely executed case in the chain that requires a lot
</span><span class="cx"> // of checks and those checks are not watchpointable.
</span><span class="cx"> for (unsigned variantIndex = getByIdStatus.numVariants(); variantIndex--;) {
</span><del>- if (getByIdStatus[variantIndex].chain()) {
- emitPrototypeChecks(
- getByIdStatus[variantIndex].structureSet().onlyStructure(),
- getByIdStatus[variantIndex].chain());
- }
</del><ins>+ if (getByIdStatus[variantIndex].chain())
+ emitPrototypeChecks(getByIdStatus[variantIndex].chain());
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // 2) Emit a MultiGetByOffset
</span><span class="lines">@@ -1774,10 +1771,8 @@
</span><span class="cx">
</span><span class="cx"> addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), base);
</span><span class="cx">
</span><del>- if (variant.chain()) {
- base = emitPrototypeChecks(
- variant.structureSet().onlyStructure(), variant.chain());
- }
</del><ins>+ if (variant.chain())
+ base = emitPrototypeChecks(variant.chain());
</ins><span class="cx">
</span><span class="cx"> // Unless we want bugs like https://bugs.webkit.org/show_bug.cgi?id=88783, we need to
</span><span class="cx"> // ensure that the base of the original get_by_id is kept alive until we're done with
</span><span class="lines">@@ -1876,9 +1871,7 @@
</span><span class="cx"> continue;
</span><span class="cx"> if (!putByIdStatus[variantIndex].structureChain())
</span><span class="cx"> continue;
</span><del>- emitPrototypeChecks(
- putByIdStatus[variantIndex].oldStructure(),
- putByIdStatus[variantIndex].structureChain());
</del><ins>+ emitPrototypeChecks(putByIdStatus[variantIndex].structureChain());
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1914,7 +1907,7 @@
</span><span class="cx">
</span><span class="cx"> addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.oldStructure())), base);
</span><span class="cx"> if (!isDirect)
</span><del>- emitPrototypeChecks(variant.oldStructure(), variant.structureChain());
</del><ins>+ emitPrototypeChecks(variant.structureChain());
</ins><span class="cx">
</span><span class="cx"> ASSERT(variant.oldStructure()->transitionWatchpointSetHasBeenInvalidated());
</span><span class="cx">
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeIntendedStructureChaincpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/IntendedStructureChain.cpp (169901 => 169902)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/IntendedStructureChain.cpp        2014-06-12 17:33:05 UTC (rev 169901)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/IntendedStructureChain.cpp        2014-06-12 17:42:10 UTC (rev 169902)
</span><span class="lines">@@ -33,27 +33,37 @@
</span><span class="cx">
</span><span class="cx"> namespace JSC {
</span><span class="cx">
</span><del>-IntendedStructureChain::IntendedStructureChain(JSGlobalObject* globalObject, Structure* head)
</del><ins>+IntendedStructureChain::IntendedStructureChain(JSGlobalObject* globalObject, JSValue prototype)
</ins><span class="cx"> : m_globalObject(globalObject)
</span><del>- , m_head(head)
</del><ins>+ , m_prototype(prototype)
</ins><span class="cx"> {
</span><del>- JSValue prototype = head->prototypeForLookup(globalObject);
</del><ins>+ ASSERT(m_prototype.isNull() || m_prototype.isObject());
</ins><span class="cx"> if (prototype.isNull())
</span><span class="cx"> return;
</span><span class="cx"> for (Structure* current = asObject(prototype)->structure(); current; current = current->storedPrototypeStructure())
</span><span class="cx"> m_vector.append(current);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+IntendedStructureChain::IntendedStructureChain(JSGlobalObject* globalObject, Structure* head)
+ : m_globalObject(globalObject)
+ , m_prototype(head->prototypeForLookup(m_globalObject))
+{
+ if (m_prototype.isNull())
+ return;
+ for (Structure* current = asObject(m_prototype)->structure(); current; current = current->storedPrototypeStructure())
+ m_vector.append(current);
+}
+
</ins><span class="cx"> IntendedStructureChain::IntendedStructureChain(CodeBlock* codeBlock, Structure* head, Structure* prototypeStructure)
</span><span class="cx"> : m_globalObject(codeBlock->globalObject())
</span><del>- , m_head(head)
</del><ins>+ , m_prototype(head->prototypeForLookup(m_globalObject))
</ins><span class="cx"> {
</span><span class="cx"> m_vector.append(prototypeStructure);
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> IntendedStructureChain::IntendedStructureChain(CodeBlock* codeBlock, Structure* head, StructureChain* chain)
</span><span class="cx"> : m_globalObject(codeBlock->globalObject())
</span><del>- , m_head(head)
</del><ins>+ , m_prototype(head->prototypeForLookup(m_globalObject))
</ins><span class="cx"> {
</span><span class="cx"> for (unsigned i = 0; chain->head()[i]; ++i)
</span><span class="cx"> m_vector.append(chain->head()[i].get());
</span><span class="lines">@@ -61,7 +71,7 @@
</span><span class="cx">
</span><span class="cx"> IntendedStructureChain::IntendedStructureChain(CodeBlock* codeBlock, Structure* head, StructureChain* chain, unsigned count)
</span><span class="cx"> : m_globalObject(codeBlock->globalObject())
</span><del>- , m_head(head)
</del><ins>+ , m_prototype(head->prototypeForLookup(m_globalObject))
</ins><span class="cx"> {
</span><span class="cx"> for (unsigned i = 0; i < count; ++i)
</span><span class="cx"> m_vector.append(chain->head()[i].get());
</span><span class="lines">@@ -73,7 +83,7 @@
</span><span class="cx">
</span><span class="cx"> bool IntendedStructureChain::isStillValid() const
</span><span class="cx"> {
</span><del>- JSValue currentPrototype = m_head->prototypeForLookup(m_globalObject);
</del><ins>+ JSValue currentPrototype = m_prototype;
</ins><span class="cx"> for (unsigned i = 0; i < m_vector.size(); ++i) {
</span><span class="cx"> if (asObject(currentPrototype)->structure() != m_vector[i])
</span><span class="cx"> return false;
</span><span class="lines">@@ -93,14 +103,6 @@
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-StructureChain* IntendedStructureChain::chain(VM& vm) const
-{
- ASSERT(isStillValid());
- StructureChain* result = StructureChain::create(vm, m_head);
- ASSERT(matches(result));
- return result;
-}
-
</del><span class="cx"> bool IntendedStructureChain::mayInterceptStoreTo(VM& vm, StringImpl* uid)
</span><span class="cx"> {
</span><span class="cx"> for (unsigned i = 0; i < m_vector.size(); ++i) {
</span><span class="lines">@@ -118,8 +120,6 @@
</span><span class="cx">
</span><span class="cx"> bool IntendedStructureChain::isNormalized()
</span><span class="cx"> {
</span><del>- if (m_head->isProxy())
- return false;
</del><span class="cx"> for (unsigned i = 0; i < m_vector.size(); ++i) {
</span><span class="cx"> Structure* structure = m_vector[i];
</span><span class="cx"> if (structure->isProxy())
</span><span class="lines">@@ -134,14 +134,21 @@
</span><span class="cx"> {
</span><span class="cx"> ASSERT(!m_vector.isEmpty());
</span><span class="cx"> if (m_vector.size() == 1)
</span><del>- return asObject(m_head->prototypeForLookup(m_globalObject));
</del><ins>+ return asObject(m_prototype);
</ins><span class="cx"> return asObject(m_vector[m_vector.size() - 2]->storedPrototype());
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+bool IntendedStructureChain::operator==(const IntendedStructureChain& other) const
+{
+ return m_globalObject == other.m_globalObject
+ && m_prototype == other.m_prototype
+ && m_vector == other.m_vector;
+}
+
</ins><span class="cx"> void IntendedStructureChain::visitChildren(SlotVisitor& visitor)
</span><span class="cx"> {
</span><span class="cx"> visitor.appendUnbarrieredPointer(&m_globalObject);
</span><del>- visitor.appendUnbarrieredPointer(&m_head);
</del><ins>+ visitor.appendUnbarrieredValue(&m_prototype);
</ins><span class="cx"> for (unsigned i = m_vector.size(); i--;)
</span><span class="cx"> visitor.appendUnbarrieredPointer(&m_vector[i]);
</span><span class="cx"> }
</span><span class="lines">@@ -155,7 +162,7 @@
</span><span class="cx"> {
</span><span class="cx"> out.print(
</span><span class="cx"> "(global = ", RawPointer(m_globalObject), ", head = ",
</span><del>- pointerDumpInContext(m_head, context), ", vector = [");
</del><ins>+ inContext(m_prototype, context), ", vector = [");
</ins><span class="cx"> CommaPrinter comma;
</span><span class="cx"> for (unsigned i = 0; i < m_vector.size(); ++i)
</span><span class="cx"> out.print(comma, pointerDumpInContext(m_vector[i], context));
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeIntendedStructureChainh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/IntendedStructureChain.h (169901 => 169902)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/IntendedStructureChain.h        2014-06-12 17:33:05 UTC (rev 169901)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/IntendedStructureChain.h        2014-06-12 17:42:10 UTC (rev 169902)
</span><span class="lines">@@ -39,7 +39,8 @@
</span><span class="cx">
</span><span class="cx"> class IntendedStructureChain : public RefCounted<IntendedStructureChain> {
</span><span class="cx"> public:
</span><del>- IntendedStructureChain(JSGlobalObject* globalObject, Structure* head);
</del><ins>+ IntendedStructureChain(JSGlobalObject* globalObject, JSValue prototype);
+ IntendedStructureChain(JSGlobalObject* globalObject, Structure*);
</ins><span class="cx"> IntendedStructureChain(CodeBlock* codeBlock, Structure* head, Structure* prototypeStructure);
</span><span class="cx"> IntendedStructureChain(CodeBlock* codeBlock, Structure* head, StructureChain* chain);
</span><span class="cx"> IntendedStructureChain(CodeBlock* codeBlock, Structure* head, StructureChain* chain, unsigned count);
</span><span class="lines">@@ -47,11 +48,10 @@
</span><span class="cx">
</span><span class="cx"> bool isStillValid() const;
</span><span class="cx"> bool matches(StructureChain*) const;
</span><del>- StructureChain* chain(VM&) const;
</del><span class="cx"> bool mayInterceptStoreTo(VM&, StringImpl* uid);
</span><span class="cx"> bool isNormalized();
</span><span class="cx">
</span><del>- Structure* head() const { return m_head; }
</del><ins>+ JSValue prototype() const { return m_prototype; }
</ins><span class="cx">
</span><span class="cx"> size_t size() const { return m_vector.size(); }
</span><span class="cx"> Structure* at(size_t index) { return m_vector[index]; }
</span><span class="lines">@@ -61,13 +61,19 @@
</span><span class="cx">
</span><span class="cx"> Structure* last() const { return m_vector.last(); }
</span><span class="cx">
</span><ins>+ bool operator==(const IntendedStructureChain&) const;
+ bool operator!=(const IntendedStructureChain& other) const
+ {
+ return !(*this == other);
+ }
+
</ins><span class="cx"> void visitChildren(SlotVisitor&);
</span><span class="cx"> void dump(PrintStream&) const;
</span><span class="cx"> void dumpInContext(PrintStream&, DumpContext*) const;
</span><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> JSGlobalObject* m_globalObject;
</span><del>- Structure* m_head;
</del><ins>+ JSValue m_prototype;
</ins><span class="cx"> Vector<Structure*> m_vector;
</span><span class="cx"> };
</span><span class="cx">
</span></span></pre>
</div>
</div>
</body>
</html>