Bug 994016: IonMonkey: Add MTypeOf folding to MCompare, r=jandem
authorHannes Verschore <hv1989@gmail.com>
Sat, 28 Feb 2015 01:30:38 +0100
changeset 231227 14df9078d7a7b0f44b3c4260a2ae87972b62164d
parent 231226 928ec762c672961919983ccc7ef7d642fe83313c
child 231228 68c6f7e33f1e5479be8d45fa43e142eb90c9b53d
push id56210
push userhv1989@gmail.com
push dateSat, 28 Feb 2015 00:37:44 +0000
treeherdermozilla-inbound@490afdad9ba1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs994016
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 994016: IonMonkey: Add MTypeOf folding to MCompare, r=jandem
js/src/jit-test/tests/ion/bug994016.js
js/src/jit/MIR.cpp
js/src/jit/MIR.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug994016.js
@@ -0,0 +1,48 @@
+
+function test(x) {
+    return typeof x != "object"
+}
+
+var obj = {};
+var func = function() {};
+
+assertEq(test(""), true)
+assertEq(test(""), true)
+assertEq(test(1), true)
+assertEq(test(1), true)
+assertEq(test(1.5), true)
+assertEq(test(1.5), true)
+assertEq(test(undefined), true)
+assertEq(test(undefined), true)
+assertEq(test(func), true)
+assertEq(test(func), true)
+
+function test2(x) {
+    return typeof x != "string"
+}
+
+assertEq(test2(1), true)
+assertEq(test2(1), true)
+assertEq(test2(1.5), true)
+assertEq(test2(1.5), true)
+assertEq(test2(undefined), true)
+assertEq(test2(undefined), true)
+assertEq(test2(func), true)
+assertEq(test2(func), true)
+assertEq(test2(obj), true)
+assertEq(test2(obj), true)
+
+function test3(x) {
+    return typeof x != "undefined"
+}
+
+assertEq(test3(1), true)
+assertEq(test3(1), true)
+assertEq(test3(1.5), true)
+assertEq(test3(1.5), true)
+assertEq(test3(func), true)
+assertEq(test3(func), true)
+assertEq(test3(obj), true)
+assertEq(test3(obj), true)
+assertEq(test(""), true)
+assertEq(test(""), true)
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -2810,16 +2810,17 @@ MTypeOf::foldsTo(TempAllocator &alloc)
     // Note: we can't use input->type() here, type analysis has
     // boxed the input.
     MOZ_ASSERT(input()->type() == MIRType_Value);
 
     JSType type;
 
     switch (inputType()) {
       case MIRType_Double:
+      case MIRType_Float32:
       case MIRType_Int32:
         type = JSTYPE_NUMBER;
         break;
       case MIRType_String:
         type = JSTYPE_STRING;
         break;
       case MIRType_Symbol:
         type = JSTYPE_SYMBOL;
@@ -3270,23 +3271,94 @@ MCompare::tryFoldEqualOperands(bool *res
             return false;
     }
 
     *result = (jsop() == JSOP_STRICTEQ);
     return true;
 }
 
 bool
+MCompare::tryFoldTypeOf(bool *result)
+{
+    if (!lhs()->isTypeOf() && !rhs()->isTypeOf())
+        return false;
+    if (!lhs()->isConstantValue() && !rhs()->isConstantValue())
+        return false;
+
+    MTypeOf *typeOf = lhs()->isTypeOf() ? lhs()->toTypeOf() : rhs()->toTypeOf();
+    const Value *constant = lhs()->isConstantValue() ? lhs()->constantVp() : rhs()->constantVp();
+
+    if (!constant->isString())
+        return false;
+
+    if (jsop() != JSOP_STRICTEQ && jsop() != JSOP_STRICTNE &&
+        jsop() != JSOP_EQ && jsop() != JSOP_NE)
+    {
+        return false;
+    }
+
+    const JSAtomState &names = GetJitContext()->runtime->names();
+    if (constant->toString() == TypeName(JSTYPE_VOID, names)) {
+        if (!typeOf->input()->mightBeType(MIRType_Undefined) &&
+            !typeOf->inputMaybeCallableOrEmulatesUndefined())
+        {
+            *result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE);
+            return true;
+        }
+    } else if (constant->toString() == TypeName(JSTYPE_BOOLEAN, names)) {
+        if (!typeOf->input()->mightBeType(MIRType_Boolean)) {
+            *result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE);
+            return true;
+        }
+    } else if (constant->toString() == TypeName(JSTYPE_NUMBER, names)) {
+        if (!typeOf->input()->mightBeType(MIRType_Int32) &&
+            !typeOf->input()->mightBeType(MIRType_Float32) &&
+            !typeOf->input()->mightBeType(MIRType_Double))
+        {
+            *result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE);
+            return true;
+        }
+    } else if (constant->toString() == TypeName(JSTYPE_STRING, names)) {
+        if (!typeOf->input()->mightBeType(MIRType_String)) {
+            *result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE);
+            return true;
+        }
+    } else if (constant->toString() == TypeName(JSTYPE_SYMBOL, names)) {
+        if (!typeOf->input()->mightBeType(MIRType_Symbol)) {
+            *result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE);
+            return true;
+        }
+    } else if (constant->toString() == TypeName(JSTYPE_OBJECT, names)) {
+        if (!typeOf->input()->mightBeType(MIRType_Object) &&
+            !typeOf->input()->mightBeType(MIRType_Null))
+        {
+            *result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE);
+            return true;
+        }
+    } else if (constant->toString() == TypeName(JSTYPE_FUNCTION, names)) {
+        if (!typeOf->inputMaybeCallableOrEmulatesUndefined()) {
+            *result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE);
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool
 MCompare::tryFold(bool *result)
 {
     JSOp op = jsop();
 
     if (tryFoldEqualOperands(result))
         return true;
 
+    if (tryFoldTypeOf(result))
+        return true;
+
     if (compareType_ == Compare_Null || compareType_ == Compare_Undefined) {
         // The LHS is the value we want to test against null or undefined.
         if (op == JSOP_STRICTEQ || op == JSOP_STRICTNE) {
             if (lhs()->type() == inputType()) {
                 *result = (op == JSOP_STRICTEQ);
                 return true;
             }
             if (!lhs()->mightBeType(inputType())) {
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -3992,16 +3992,17 @@ class MCompare
         return compareType_ == Compare_Float32;
     }
 # endif
 
     ALLOW_CLONE(MCompare)
 
   protected:
     bool tryFoldEqualOperands(bool *result);
+    bool tryFoldTypeOf(bool *result);
 
     bool congruentTo(const MDefinition *ins) const MOZ_OVERRIDE {
         if (!binaryCongruentTo(ins))
             return false;
         return compareType() == ins->toCompare()->compareType() &&
                jsop() == ins->toCompare()->jsop();
     }
 };