DFG LogicalNot/Branch peephole removal and inversion ignores the possibility of things exiting
https://bugs.webkit.org/show_bug.cgi?id=109489
Source/JavaScriptCore:
Reviewed by Mark Hahnenberg.
If things can exit between the LogicalNot and the Branch then don't peephole.
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
LayoutTests:
Reviewed by Mark Hahnenberg.
* fast/js/dfg-branch-logical-not-peephole-around-osr-exit-expected.txt: Added.
* fast/js/dfg-branch-logical-not-peephole-around-osr-exit.html: Added.
* fast/js/jsc-test-list:
* fast/js/script-tests/dfg-branch-logical-not-peephole-around-osr-exit.js: Added.
(foo):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@142779 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index 1a93765..7b08c4c 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -232,16 +232,39 @@
Node* logicalNot = node->child1().node();
if (logicalNot->op() == LogicalNot
&& logicalNot->adjustedRefCount() == 1) {
- Edge newChildEdge = logicalNot->child1();
- if (newChildEdge->hasBooleanResult()) {
- m_graph.ref(newChildEdge);
- m_graph.deref(logicalNot);
- node->children.setChild1(newChildEdge);
-
- BlockIndex toBeTaken = node->notTakenBlockIndex();
- BlockIndex toBeNotTaken = node->takenBlockIndex();
- node->setTakenBlockIndex(toBeTaken);
- node->setNotTakenBlockIndex(toBeNotTaken);
+
+ // Make sure that OSR exit can't observe the LogicalNot. If it can,
+ // then we must compute it and cannot peephole around it.
+ bool found = false;
+ bool ok = true;
+ for (unsigned i = m_indexInBlock; i--;) {
+ Node* candidate = m_block->at(i);
+ if (!candidate->shouldGenerate())
+ continue;
+ if (candidate == logicalNot) {
+ found = true;
+ break;
+ }
+ if (candidate->canExit()) {
+ ok = false;
+ found = true;
+ break;
+ }
+ }
+ ASSERT_UNUSED(found, found);
+
+ if (ok) {
+ Edge newChildEdge = logicalNot->child1();
+ if (newChildEdge->hasBooleanResult()) {
+ m_graph.ref(newChildEdge);
+ m_graph.deref(logicalNot);
+ node->children.setChild1(newChildEdge);
+
+ BlockIndex toBeTaken = node->notTakenBlockIndex();
+ BlockIndex toBeNotTaken = node->takenBlockIndex();
+ node->setTakenBlockIndex(toBeTaken);
+ node->setNotTakenBlockIndex(toBeNotTaken);
+ }
}
}
break;