Bug 1483189 - Add PrimitiveUndefined support to CacheIR r=tcampbell
authorMatthew Gaudet <mgaudet@mozilla.com>
Tue, 14 Aug 2018 14:45:47 -0400
changeset 431693 fde17a23425676f852797e25d93ca736d36f4291
parent 431692 de505fb3dfcdf779a76dc97b9f4da91138288307
child 431694 4d191bd81bbea9db56246856e9b09b11e2a6b4be
push id34451
push userebalazs@mozilla.com
push dateThu, 16 Aug 2018 09:25:15 +0000
treeherdermozilla-central@161817e6d127 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1483189
milestone63.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 1483189 - Add PrimitiveUndefined support to CacheIR r=tcampbell
js/src/jit/CacheIR.cpp
js/src/jit/CacheIR.h
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -4923,16 +4923,68 @@ CompareIRGenerator::tryAttachNumberUndef
     // and always be false for other compare ops.
     writer.loadBooleanResult(op_ == JSOP_NE || op_ == JSOP_STRICTNE);
     writer.returnFromIC();
 
     trackAttached("NumberUndefined");
     return true;
 }
 
+// Handle Primitive x {undefined,null} equality comparisons
+bool
+CompareIRGenerator::tryAttachPrimitiveUndefined(ValOperandId lhsId, ValOperandId rhsId)
+{
+    MOZ_ASSERT(IsEqualityOp(op_));
+
+    // The set of primitive cases we want to handle here (excluding null, undefined)
+    auto isPrimitive = [](HandleValue& x) {
+        return x.isString() || x.isSymbol() || x.isBoolean() || x.isNumber();
+    };
+
+    if (!(lhsVal_.isNullOrUndefined() && isPrimitive(rhsVal_)) &&
+        !(rhsVal_.isNullOrUndefined() && isPrimitive(lhsVal_)))
+    {
+        return false;
+    }
+
+    auto guardPrimitive = [&](HandleValue v, ValOperandId id) {
+        if (v.isNumber()) {
+            writer.guardIsNumber(id);
+            return;
+        }
+        switch (v.extractNonDoubleType()) {
+          case JSVAL_TYPE_BOOLEAN:
+            writer.guardIsBoolean(id);
+            return;
+          case JSVAL_TYPE_SYMBOL:
+            writer.guardIsSymbol(id);
+            return;
+          case JSVAL_TYPE_STRING:
+            writer.guardIsString(id);
+            return;
+          default:
+            MOZ_CRASH("unexpected type");
+            return;
+        }
+    };
+
+    isPrimitive(lhsVal_) ? guardPrimitive(lhsVal_, lhsId)
+                         : writer.guardIsNullOrUndefined(lhsId);
+    isPrimitive(rhsVal_) ? guardPrimitive(rhsVal_, rhsId)
+                         : writer.guardIsNullOrUndefined(rhsId);
+
+    // Comparing a primitive with undefined/null will always be true for NE/STRICTNE,
+    // and always be false for other compare ops.
+    writer.loadBooleanResult(op_ == JSOP_NE || op_ == JSOP_STRICTNE);
+    writer.returnFromIC();
+
+    trackAttached("PrimitiveUndefined");
+    return true;
+}
+
 // Handle {null/undefined} x {null,undefined} equality comparisons
 bool
 CompareIRGenerator::tryAttachNullUndefined(ValOperandId lhsId, ValOperandId rhsId)
 {
     if (!lhsVal_.isNullOrUndefined() || !rhsVal_.isNullOrUndefined())
         return false;
 
     if (op_ == JSOP_EQ || op_ == JSOP_NE) {
@@ -4982,16 +5034,21 @@ CompareIRGenerator::tryAttachStub()
             return true;
         if (tryAttachSymbol(lhsId, rhsId))
             return true;
         if (tryAttachObjectUndefined(lhsId, rhsId))
             return true;
         if (tryAttachStrictDifferentTypes(lhsId, rhsId))
             return true;
 
+        // These checks should come after tryAttachStrictDifferentTypes since it handles
+        // strict inequality with a more generic IC.
+        if (tryAttachPrimitiveUndefined(lhsId, rhsId))
+            return true;
+
         // This should come after strictDifferent types to
         // allow it to only handle sloppy equality.
         if (tryAttachNullUndefined(lhsId, rhsId))
             return true;
     }
 
     // This should preceed the Int32/Number cases to allow
     // them to not concern themselves with handling undefined
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -1867,16 +1867,17 @@ class MOZ_RAII CompareIRGenerator : publ
 
     bool tryAttachString(ValOperandId lhsId, ValOperandId rhsId);
     bool tryAttachObject(ValOperandId lhsId, ValOperandId rhsId);
     bool tryAttachSymbol(ValOperandId lhsId, ValOperandId rhsId);
     bool tryAttachStrictDifferentTypes(ValOperandId lhsId, ValOperandId rhsId);
     bool tryAttachInt32(ValOperandId lhsId, ValOperandId rhsId);
     bool tryAttachNumber(ValOperandId lhsId, ValOperandId rhsId);
     bool tryAttachNumberUndefined(ValOperandId lhsId, ValOperandId rhsId);
+    bool tryAttachPrimitiveUndefined(ValOperandId lhsId, ValOperandId rhsId);
     bool tryAttachObjectUndefined(ValOperandId lhsId, ValOperandId rhsId);
     bool tryAttachNullUndefined(ValOperandId lhsId, ValOperandId rhsId);
 
     void trackAttached(const char* name);
 
   public:
     CompareIRGenerator(JSContext* cx, HandleScript, jsbytecode* pc, ICState::Mode mode,
                        JSOp op, HandleValue lhsVal, HandleValue rhsVal);