Commit 687b646a authored by fpizlo@apple.com's avatar fpizlo@apple.com
Browse files

DFG CSE assumes that a holy PutByVal does not interfere with GetArrayLength, when it clearly does

https://bugs.webkit.org/show_bug.cgi?id=97373

Reviewed by Mark Hahnenberg.

Source/JavaScriptCore: 

* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::pureCSE):
(JSC::DFG::CSEPhase::getArrayLengthElimination):
(JSC::DFG::CSEPhase::putStructureStoreElimination):
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGGraph.h:
(Graph):

LayoutTests: 

* fast/js/dfg-holy-put-by-val-interferes-with-get-array-length-expected.txt: Added.
* fast/js/dfg-holy-put-by-val-interferes-with-get-array-length.html: Added.
* fast/js/jsc-test-list:
* fast/js/script-tests/dfg-holy-put-by-val-interferes-with-get-array-length.js: Added.
(foo):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@129266 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent ca66f9a2
2012-09-21 Filip Pizlo <fpizlo@apple.com>
DFG CSE assumes that a holy PutByVal does not interfere with GetArrayLength, when it clearly does
https://bugs.webkit.org/show_bug.cgi?id=97373
Reviewed by Mark Hahnenberg.
* fast/js/dfg-holy-put-by-val-interferes-with-get-array-length-expected.txt: Added.
* fast/js/dfg-holy-put-by-val-interferes-with-get-array-length.html: Added.
* fast/js/jsc-test-list:
* fast/js/script-tests/dfg-holy-put-by-val-interferes-with-get-array-length.js: Added.
(foo):
2012-09-21 Roger Fong <roger_fong@apple.com>
 
Unreviewed. Skipping http/tests/security/sandboxed-iframe-origin-add.html.
Tests that the DFG's interference analysis knows that a holy PutByVal interferes with a GetArrayLength.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS foo([75]) is [1,2]
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="resources/js-test-pre.js"></script>
</head>
<body>
<script src="script-tests/dfg-holy-put-by-val-interferes-with-get-array-length.js"></script>
<script src="resources/js-test-post.js"></script>
</body>
</html>
......@@ -99,6 +99,7 @@ fast/js/dfg-get-by-val-clobber
fast/js/dfg-get-by-val-getter-cse
fast/js/dfg-getter-throw
fast/js/dfg-getter
fast/js/dfg-holy-put-by-val-interferes-with-get-array-length
fast/js/dfg-inline-arguments-become-double
fast/js/dfg-inline-arguments-become-int32
fast/js/dfg-inline-arguments-int32
......
description(
"Tests that the DFG's interference analysis knows that a holy PutByVal interferes with a GetArrayLength."
);
function foo(array) {
var x = array.length;
array[1] = 42;
return [x, array.length];
}
for (var i = 0; i < 100; ++i)
shouldBe("foo([75])", "[1,2]");
2012-09-21 Filip Pizlo <fpizlo@apple.com>
DFG CSE assumes that a holy PutByVal does not interfere with GetArrayLength, when it clearly does
https://bugs.webkit.org/show_bug.cgi?id=97373
Reviewed by Mark Hahnenberg.
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::pureCSE):
(JSC::DFG::CSEPhase::getArrayLengthElimination):
(JSC::DFG::CSEPhase::putStructureStoreElimination):
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGGraph.h:
(Graph):
2012-09-21 Chris Rogers <crogers@google.com>
 
Add Web Audio support for deprecated/legacy APIs
......
......@@ -96,6 +96,9 @@ private:
break;
Node& otherNode = m_graph[index];
if (!otherNode.shouldGenerate())
continue;
if (node.op() != otherNode.op())
continue;
......@@ -157,38 +160,34 @@ private:
return NoNode;
}
NodeIndex impureCSE(Node& node)
NodeIndex getArrayLengthElimination(NodeIndex array)
{
NodeIndex child1 = canonicalize(node.child1());
NodeIndex child2 = canonicalize(node.child2());
NodeIndex child3 = canonicalize(node.child3());
for (unsigned i = m_indexInBlock; i--;) {
NodeIndex index = m_currentBlock->at(i);
if (index == child1 || index == child2 || index == child3)
break;
Node& otherNode = m_graph[index];
if (node.op() == otherNode.op()
&& node.arithNodeFlags() == otherNode.arithNodeFlags()) {
NodeIndex otherChild = canonicalize(otherNode.child1());
if (otherChild == NoNode)
Node& node = m_graph[index];
if (!node.shouldGenerate())
continue;
switch (node.op()) {
case GetArrayLength:
if (node.child1() == array)
return index;
if (otherChild == child1) {
otherChild = canonicalize(otherNode.child2());
if (otherChild == NoNode)
return index;
if (otherChild == child2) {
otherChild = canonicalize(otherNode.child3());
if (otherChild == NoNode)
return index;
if (otherChild == child3)
return index;
}
break;
case PutByVal:
if (!m_graph.byValIsPure(node))
return NoNode;
switch (node.arrayMode()) {
case ARRAY_STORAGE_TO_HOLE_MODES:
return NoNode;
default:
break;
}
}
if (m_graph.clobbersWorld(index))
break;
default:
if (m_graph.clobbersWorld(index))
return NoNode;
}
}
return NoNode;
}
......@@ -437,7 +436,7 @@ private:
break;
Node& node = m_graph[index];
if (!node.shouldGenerate())
break;
continue;
switch (node.op()) {
case CheckStructure:
case ForwardCheckStructure:
......@@ -1078,7 +1077,7 @@ private:
break;
case GetArrayLength:
setReplacement(impureCSE(node));
setReplacement(getArrayLengthElimination(node.child1().index()));
break;
case GetScopeChain:
......
......@@ -469,6 +469,12 @@ public:
return isNumberSpeculation(left) && isNumberSpeculation(right);
}
// Note that a 'true' return does not actually mean that the ByVal access clobbers nothing.
// It really means that it will not clobber the entire world. It's still up to you to
// carefully consider things like:
// - PutByVal definitely changes the array it stores to, and may even change its length.
// - PutByOffset definitely changes the object it stores to.
// - and so on.
bool byValIsPure(Node& node)
{
switch (node.arrayMode()) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment