DFG should optimize a==b for a being an object and b being either an object or
null/undefined, and vice versa
https://bugs.webkit.org/show_bug.cgi?id=82656

Reviewed by Oliver Hunt.
        
Implements additional object equality optimizations for the case that one
operand is predicted to be an easily speculated object (like FinalObject or
Array) and the other is either an easily speculated object or Other, i.e.
Null or Undefined.
        
2-5% speed-up on V8/raytrace, leading to a sub-1% progression on V8.
        
I also took the opportunity to clean up the control flow for the speculation
decisions in the various Compare opcodes. And to fix a build bug in SamplingTool.
And to remove debug cruft I stupidly committed in my last patch.
        
* bytecode/SamplingTool.h:
(SamplingRegion):
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::execute):
* dfg/DFGOperations.cpp:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compilePeepHoleBranch):
(JSC::DFG::SpeculativeJIT::compare):
* dfg/DFGSpeculativeJIT.h:
(SpeculativeJIT):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranch):
(JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality):
(DFG):
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranch):
(JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality):
(DFG):
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@112762 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index 2f1e023..15ffcc8 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -409,6 +409,8 @@
     case CompareGreater:
     case CompareGreaterEq:
     case CompareEq: {
+        forNode(nodeIndex).set(PredictBoolean);
+        
         Node& left = m_graph[node.child1()];
         Node& right = m_graph[node.child2()];
         PredictedType filter;
@@ -416,17 +418,45 @@
             filter = PredictInt32;
         else if (Node::shouldSpeculateNumber(left, right))
             filter = PredictNumber;
-        else if (node.op() == CompareEq && Node::shouldSpeculateFinalObject(left, right))
-            filter = PredictFinalObject;
-        else if (node.op() == CompareEq && Node::shouldSpeculateArray(left, right))
-            filter = PredictArray;
-        else {
+        else if (node.op() == CompareEq) {
+            if ((m_graph.isConstant(node.child1().index())
+                 && m_graph.valueOfJSConstant(node.child1().index()).isNull())
+                || (m_graph.isConstant(node.child2().index())
+                    && m_graph.valueOfJSConstant(node.child2().index()).isNull())) {
+                // We know that this won't clobber the world. But that's all we know.
+                break;
+            }
+            
+            if (Node::shouldSpeculateFinalObject(left, right))
+                filter = PredictFinalObject;
+            else if (Node::shouldSpeculateArray(left, right))
+                filter = PredictArray;
+            else if (left.shouldSpeculateFinalObject() && right.shouldSpeculateFinalObjectOrOther()) {
+                forNode(node.child1()).filter(PredictFinalObject);
+                forNode(node.child2()).filter(PredictFinalObject | PredictOther);
+                break;
+            } else if (right.shouldSpeculateFinalObject() && left.shouldSpeculateFinalObjectOrOther()) {
+                forNode(node.child1()).filter(PredictFinalObject | PredictOther);
+                forNode(node.child2()).filter(PredictFinalObject);
+                break;
+            } else if (left.shouldSpeculateArray() && right.shouldSpeculateArrayOrOther()) {
+                forNode(node.child1()).filter(PredictFinalObject);
+                forNode(node.child2()).filter(PredictFinalObject | PredictOther);
+                break;
+            } else if (right.shouldSpeculateArray() && left.shouldSpeculateArrayOrOther()) {
+                forNode(node.child1()).filter(PredictFinalObject | PredictOther);
+                forNode(node.child2()).filter(PredictFinalObject);
+                break;
+            } else {
+                filter = PredictTop;
+                clobberStructures(indexInBlock);
+            }
+        } else {
             filter = PredictTop;
             clobberStructures(indexInBlock);
         }
         forNode(node.child1()).filter(filter);
         forNode(node.child2()).filter(filter);
-        forNode(nodeIndex).set(PredictBoolean);
         break;
     }