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;