Title: [163896] trunk/Source/_javascript_Core
Revision
163896
Author
fpi...@apple.com
Date
2014-02-11 12:28:59 -0800 (Tue, 11 Feb 2014)

Log Message

FTL should support CompareEq(ObjectOrOther:, Object:)
https://bugs.webkit.org/show_bug.cgi?id=127752

Reviewed by Oliver Hunt.
        
Also introduce some helpers for reasoning about nullness and truthyness.

* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileCompareEq):
(JSC::FTL::LowerDFGToLLVM::compareEqObjectOrOtherToObject):
(JSC::FTL::LowerDFGToLLVM::speculateTruthyObject):
(JSC::FTL::LowerDFGToLLVM::equalNullOrUndefined):
(JSC::FTL::LowerDFGToLLVM::isNotNully):
(JSC::FTL::LowerDFGToLLVM::isNully):
(JSC::FTL::LowerDFGToLLVM::speculateObjectOrOther):
* tests/stress/compare-eq-object-or-other-to-object.js: Added.
(foo):
(test):
* tests/stress/compare-eq-object-to-object-or-other.js: Added.
(foo):
(test):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (163895 => 163896)


--- trunk/Source/_javascript_Core/ChangeLog	2014-02-11 20:26:43 UTC (rev 163895)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-02-11 20:28:59 UTC (rev 163896)
@@ -1,3 +1,29 @@
+2014-02-11  Filip Pizlo  <fpi...@apple.com>
+
+        FTL should support CompareEq(ObjectOrOther:, Object:)
+        https://bugs.webkit.org/show_bug.cgi?id=127752
+
+        Reviewed by Oliver Hunt.
+        
+        Also introduce some helpers for reasoning about nullness and truthyness.
+
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileCompareEq):
+        (JSC::FTL::LowerDFGToLLVM::compareEqObjectOrOtherToObject):
+        (JSC::FTL::LowerDFGToLLVM::speculateTruthyObject):
+        (JSC::FTL::LowerDFGToLLVM::equalNullOrUndefined):
+        (JSC::FTL::LowerDFGToLLVM::isNotNully):
+        (JSC::FTL::LowerDFGToLLVM::isNully):
+        (JSC::FTL::LowerDFGToLLVM::speculateObjectOrOther):
+        * tests/stress/compare-eq-object-or-other-to-object.js: Added.
+        (foo):
+        (test):
+        * tests/stress/compare-eq-object-to-object-or-other.js: Added.
+        (foo):
+        (test):
+
 2014-02-11  Mark Hahnenberg  <mhahnenb...@apple.com>
 
         32-bit LLInt writeBarrierOnGlobalObject is wrong

Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (163895 => 163896)


--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2014-02-11 20:26:43 UTC (rev 163895)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2014-02-11 20:28:59 UTC (rev 163896)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -226,6 +226,12 @@
             break;
         if (node->isBinaryUseKind(UntypedUse))
             break;
+        if (node->child1().useKind() == ObjectUse
+            && node->child2().useKind() == ObjectOrOtherUse)
+            break;
+        if (node->child1().useKind() == ObjectOrOtherUse
+            && node->child2().useKind() == ObjectUse)
+            break;
         return CannotCompile;
     case CompareStrictEq:
         if (node->isBinaryUseKind(Int32Use))

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (163895 => 163896)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2014-02-11 20:26:43 UTC (rev 163895)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2014-02-11 20:28:59 UTC (rev 163896)
@@ -3208,6 +3208,18 @@
             return;
         }
         
+        if (m_node->child1().useKind() == ObjectUse
+            && m_node->child2().useKind() == ObjectOrOtherUse) {
+            compareEqObjectOrOtherToObject(m_node->child2(), m_node->child1());
+            return;
+        }
+        
+        if (m_node->child1().useKind() == ObjectOrOtherUse
+            && m_node->child2().useKind() == ObjectUse) {
+            compareEqObjectOrOtherToObject(m_node->child2(), m_node->child1());
+            return;
+        }
+        
         if (m_node->isBinaryUseKind(UntypedUse)) {
             nonSpeculativeCompare(LLVMIntEQ, operationCompareEq);
             return;
@@ -3606,6 +3618,52 @@
         RELEASE_ASSERT_NOT_REACHED();
     }
     
+    void compareEqObjectOrOtherToObject(Edge leftChild, Edge rightChild)
+    {
+        LValue rightCell = lowCell(rightChild);
+        LValue leftValue = lowJSValue(leftChild);
+        
+        speculateTruthyObject(rightChild, rightCell, SpecObject);
+        
+        LBasicBlock leftCellCase = FTL_NEW_BLOCK(m_out, ("CompareEqObjectOrOtherToObject left cell case"));
+        LBasicBlock leftNotCellCase = FTL_NEW_BLOCK(m_out, ("CompareEqObjectOrOtherToObject left not cell case"));
+        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CompareEqObjectOrOtherToObject continuation"));
+        
+        m_out.branch(isCell(leftValue), leftCellCase, leftNotCellCase);
+        
+        LBasicBlock lastNext = m_out.appendTo(leftCellCase, leftNotCellCase);
+        speculateTruthyObject(leftChild, leftValue, SpecObject | (~SpecCell));
+        ValueFromBlock cellResult = m_out.anchor(m_out.equal(rightCell, leftValue));
+        m_out.jump(continuation);
+        
+        m_out.appendTo(leftNotCellCase, continuation);
+        FTL_TYPE_CHECK(
+            jsValueValue(leftValue), leftChild, SpecOther | SpecCell, isNotNully(leftValue));
+        ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
+        m_out.jump(continuation);
+        
+        m_out.appendTo(continuation, lastNext);
+        setBoolean(m_out.phi(m_out.boolean, cellResult, notCellResult));
+    }
+    
+    void speculateTruthyObject(Edge edge, LValue cell, SpeculatedType filter)
+    {
+        if (masqueradesAsUndefinedWatchpointIsStillValid()) {
+            FTL_TYPE_CHECK(jsValueValue(cell), edge, filter, isNotObject(cell));
+            return;
+        }
+        
+        LValue structure = m_out.loadPtr(cell, m_heaps.JSCell_structure);
+        FTL_TYPE_CHECK(
+            jsValueValue(cell), edge, filter,
+            m_out.equal(structure, m_out.constIntPtr(vm().stringStructure.get())));
+        speculate(
+            BadType, jsValueValue(cell), edge.node(),
+            m_out.testNonZero8(
+                m_out.load8(structure, m_heaps.Structure_typeInfoFlags),
+                m_out.constInt8(MasqueradesAsUndefined)));
+    }
+    
     void nonSpeculativeCompare(LIntPredicate intCondition, S_JITOperation_EJJ helperFunction)
     {
         LValue left = lowJSValue(m_node->child1());
@@ -3912,16 +3970,11 @@
             primitiveResult = m_out.equal(value, m_out.constInt64(ValueUndefined));
             break;
         case EqualNullOrUndefined:
-            primitiveResult = m_out.equal(
-                m_out.bitAnd(value, m_out.constInt64(~TagBitUndefined)),
-                m_out.constInt64(ValueNull));
+            primitiveResult = isNully(value);
             break;
         case SpeculateNullOrUndefined:
             FTL_TYPE_CHECK(
-                jsValueValue(value), edge, SpecCell | SpecOther,
-                m_out.notEqual(
-                    m_out.bitAnd(value, m_out.constInt64(~TagBitUndefined)),
-                    m_out.constInt64(ValueNull)));
+                jsValueValue(value), edge, SpecCell | SpecOther, isNotNully(value));
             primitiveResult = m_out.booleanTrue;
             break;
         }
@@ -4567,6 +4620,19 @@
         return m_out.select(
             value, m_out.constInt64(ValueTrue), m_out.constInt64(ValueFalse));
     }
+    
+    LValue isNotNully(LValue value)
+    {
+        return m_out.notEqual(
+            m_out.bitAnd(value, m_out.constInt64(~TagBitUndefined)),
+            m_out.constInt64(ValueNull));
+    }
+    LValue isNully(LValue value)
+    {
+        return m_out.equal(
+            m_out.bitAnd(value, m_out.constInt64(~TagBitUndefined)),
+            m_out.constInt64(ValueNull));
+    }
 
     void speculate(Edge edge)
     {
@@ -4754,20 +4820,14 @@
         LBasicBlock lastNext = m_out.appendTo(cellCase, primitiveCase);
         
         FTL_TYPE_CHECK(
-            jsValueValue(value), edge, (~SpecCell) | SpecObject,
-            m_out.equal(
-                m_out.loadPtr(value, m_heaps.JSCell_structure),
-                m_out.constIntPtr(vm().stringStructure.get())));
+            jsValueValue(value), edge, (~SpecCell) | SpecObject, isNotObject(value));
         
         m_out.jump(continuation);
         
         m_out.appendTo(primitiveCase, continuation);
         
         FTL_TYPE_CHECK(
-            jsValueValue(value), edge, SpecCell | SpecOther,
-            m_out.notEqual(
-                m_out.bitAnd(value, m_out.constInt64(~TagBitUndefined)),
-                m_out.constInt64(ValueNull)));
+            jsValueValue(value), edge, SpecCell | SpecOther, isNotNully(value));
         
         m_out.jump(continuation);
         

Added: trunk/Source/_javascript_Core/tests/stress/compare-eq-object-or-other-to-object.js (0 => 163896)


--- trunk/Source/_javascript_Core/tests/stress/compare-eq-object-or-other-to-object.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/compare-eq-object-or-other-to-object.js	2014-02-11 20:28:59 UTC (rev 163896)
@@ -0,0 +1,24 @@
+function foo(a, b) {
+    return a == b;
+}
+
+noInline(foo);
+
+function test(a, b, expected) {
+    var result = foo(a, b);
+    if (result != expected)
+        throw new Error("Unexpected result: " + result);
+}
+
+for (var i = 0; i < 100000; ++i) {
+    var o = {f:42};
+    var p = {g:43};
+    test(o, o, true);
+    test(o, p, false);
+    test(p, o, false);
+    test(p, p, true);
+    test(null, o, false);
+    test(null, p, false);
+    test(void 0, o, false);
+    test(void 0, p, false);
+}

Added: trunk/Source/_javascript_Core/tests/stress/compare-eq-object-to-object-or-other.js (0 => 163896)


--- trunk/Source/_javascript_Core/tests/stress/compare-eq-object-to-object-or-other.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/compare-eq-object-to-object-or-other.js	2014-02-11 20:28:59 UTC (rev 163896)
@@ -0,0 +1,24 @@
+function foo(a, b) {
+    return a == b;
+}
+
+noInline(foo);
+
+function test(a, b, expected) {
+    var result = foo(a, b);
+    if (result != expected)
+        throw new Error("Unexpected result: " + result);
+}
+
+for (var i = 0; i < 100000; ++i) {
+    var o = {f:42};
+    var p = {g:43};
+    test(o, o, true);
+    test(o, p, false);
+    test(p, o, false);
+    test(p, p, true);
+    test(o, null, false);
+    test(p, null, false);
+    test(o, void 0, false);
+    test(p, void 0, false);
+}
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to