Bug 1526872 - Add CacheIR support for comparisons of BigInt to null or undefined r=jandem
authorAndy Wingo <wingo@igalia.com>
Mon, 11 Feb 2019 15:10:51 +0000
changeset 458561 0361c4f078f2aa49786589345701547d19387113
parent 458560 6eca46400d21ca9f789d8f8f3e13f9291ec40305
child 458562 d33cbdb821913bfb19eb5a613faaea90aeb26dcb
push id35538
push userbtara@mozilla.com
push dateTue, 12 Feb 2019 05:25:24 +0000
treeherdermozilla-central@09beaf742eae [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1526872
milestone67.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 1526872 - Add CacheIR support for comparisons of BigInt to null or undefined r=jandem Differential Revision: https://phabricator.services.mozilla.com/D19332
js/src/jit-test/tests/cacheir/bug1526872.js
js/src/jit/BaselineInspector.cpp
js/src/jit/CacheIR.cpp
js/src/jit/CacheIR.h
js/src/jit/CacheIRCompiler.cpp
js/src/jit/CacheIRCompiler.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/cacheir/bug1526872.js
@@ -0,0 +1,11 @@
+
+setJitCompilerOption("offthread-compilation.enable", 0);
+setJitCompilerOption("ion.warmup.trigger", 0);
+
+for (var i = 0; i < 5; i++) {
+    assertEq(foo(1n), false);
+}
+
+function foo(x) {
+    return x == null || x == undefined;
+}
--- a/js/src/jit/BaselineInspector.cpp
+++ b/js/src/jit/BaselineInspector.cpp
@@ -480,16 +480,21 @@ static bool GuardType(CacheIRReader& rea
   switch (op) {
     // 0 Skip cases
     case CacheOp::GuardIsString:
       guardType[guardOperand] = MIRType::String;
       break;
     case CacheOp::GuardIsSymbol:
       guardType[guardOperand] = MIRType::Symbol;
       break;
+#ifdef ENABLE_BIGINT
+    case CacheOp::GuardIsBigInt:
+      guardType[guardOperand] = MIRType::BigInt;
+      break;
+#endif
     case CacheOp::GuardIsNumber:
       guardType[guardOperand] = MIRType::Double;
       break;
     case CacheOp::GuardIsUndefined:
       guardType[guardOperand] = MIRType::Undefined;
       break;
     // 1 skip
     case CacheOp::GuardIsInt32:
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -5438,17 +5438,18 @@ bool CompareIRGenerator::tryAttachNumber
 // 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();
+    return x.isString() || x.isSymbol() || x.isBoolean() || x.isNumber() ||
+           IF_BIGINT(x.isBigInt(), false);
   };
 
   if (!(lhsVal_.isNullOrUndefined() && isPrimitive(rhsVal_)) &&
       !(rhsVal_.isNullOrUndefined() && isPrimitive(lhsVal_))) {
     return false;
   }
 
   auto guardPrimitive = [&](HandleValue v, ValOperandId id) {
@@ -5458,16 +5459,21 @@ bool CompareIRGenerator::tryAttachPrimit
     }
     switch (v.extractNonDoubleType()) {
       case JSVAL_TYPE_BOOLEAN:
         writer.guardIsBoolean(id);
         return;
       case JSVAL_TYPE_SYMBOL:
         writer.guardIsSymbol(id);
         return;
+#ifdef ENABLE_BIGINT
+      case JSVAL_TYPE_BIGINT:
+        writer.guardIsBigInt(id);
+        return;
+#endif
       case JSVAL_TYPE_STRING:
         writer.guardIsString(id);
         return;
       default:
         MOZ_CRASH("unexpected type");
         return;
     }
   };
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -104,32 +104,44 @@ class StringOperandId : public OperandId
 };
 
 class SymbolOperandId : public OperandId {
  public:
   SymbolOperandId() = default;
   explicit SymbolOperandId(uint16_t id) : OperandId(id) {}
 };
 
+#ifdef ENABLE_BIGINT
+class BigIntOperandId : public OperandId {
+ public:
+  BigIntOperandId() = default;
+  explicit BigIntOperandId(uint16_t id) : OperandId(id) {}
+};
+#endif
+
 class Int32OperandId : public OperandId {
  public:
   Int32OperandId() = default;
   explicit Int32OperandId(uint16_t id) : OperandId(id) {}
 };
 
 class TypedOperandId : public OperandId {
   JSValueType type_;
 
  public:
   MOZ_IMPLICIT TypedOperandId(ObjOperandId id)
       : OperandId(id.id()), type_(JSVAL_TYPE_OBJECT) {}
   MOZ_IMPLICIT TypedOperandId(StringOperandId id)
       : OperandId(id.id()), type_(JSVAL_TYPE_STRING) {}
   MOZ_IMPLICIT TypedOperandId(SymbolOperandId id)
       : OperandId(id.id()), type_(JSVAL_TYPE_SYMBOL) {}
+#ifdef ENABLE_BIGINT
+  MOZ_IMPLICIT TypedOperandId(BigIntOperandId id)
+      : OperandId(id.id()), type_(JSVAL_TYPE_BIGINT) {}
+#endif
   MOZ_IMPLICIT TypedOperandId(Int32OperandId id)
       : OperandId(id.id()), type_(JSVAL_TYPE_INT32) {}
   MOZ_IMPLICIT TypedOperandId(ValueTagOperandId val)
       : OperandId(val.id()), type_(JSVAL_TYPE_UNKNOWN) {}
   TypedOperandId(ValOperandId val, JSValueType type)
       : OperandId(val.id()), type_(type) {}
 
   JSValueType type() const { return type_; }
@@ -170,16 +182,17 @@ extern const char* const CacheKindNames[
   _(GuardIsObjectOrNull)                                               \
   _(GuardIsNullOrUndefined)                                            \
   _(GuardIsNotNullOrUndefined)                                         \
   _(GuardIsNull)                                                       \
   _(GuardIsUndefined)                                                  \
   _(GuardIsBoolean)                                                    \
   _(GuardIsString)                                                     \
   _(GuardIsSymbol)                                                     \
+  IF_BIGINT(_(GuardIsBigInt), )                                        \
   _(GuardIsNumber)                                                     \
   _(GuardIsInt32)                                                      \
   _(GuardIsInt32Index)                                                 \
   _(GuardType)                                                         \
   _(GuardShape)                                                        \
   _(GuardGroup)                                                        \
   _(GuardProto)                                                        \
   _(GuardClass)    /* Guard an object class, per GuardClassKind */     \
@@ -590,16 +603,22 @@ class MOZ_RAII CacheIRWriter : public JS
   StringOperandId guardIsString(ValOperandId val) {
     writeOpWithOperandId(CacheOp::GuardIsString, val);
     return StringOperandId(val.id());
   }
   SymbolOperandId guardIsSymbol(ValOperandId val) {
     writeOpWithOperandId(CacheOp::GuardIsSymbol, val);
     return SymbolOperandId(val.id());
   }
+#ifdef ENABLE_BIGINT
+  BigIntOperandId guardIsBigInt(ValOperandId val) {
+    writeOpWithOperandId(CacheOp::GuardIsBigInt, val);
+    return BigIntOperandId(val.id());
+  }
+#endif
   Int32OperandId guardIsInt32(ValOperandId val) {
     Int32OperandId res(nextOperandId_++);
     writeOpWithOperandId(CacheOp::GuardIsInt32, val);
     writeOperandId(res);
     return res;
   }
   Int32OperandId guardIsInt32Index(ValOperandId val) {
     Int32OperandId res(nextOperandId_++);
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -1472,16 +1472,34 @@ bool CacheIRCompiler::emitGuardIsSymbol(
   FailurePath* failure;
   if (!addFailurePath(&failure)) {
     return false;
   }
   masm.branchTestSymbol(Assembler::NotEqual, input, failure->label());
   return true;
 }
 
+#ifdef ENABLE_BIGINT
+bool CacheIRCompiler::emitGuardIsBigInt() {
+  JitSpew(JitSpew_Codegen, __FUNCTION__);
+  ValOperandId inputId = reader.valOperandId();
+  if (allocator.knownType(inputId) == JSVAL_TYPE_BIGINT) {
+    return true;
+  }
+
+  ValueOperand input = allocator.useValueRegister(masm, inputId);
+  FailurePath* failure;
+  if (!addFailurePath(&failure)) {
+    return false;
+  }
+  masm.branchTestBigInt(Assembler::NotEqual, input, failure->label());
+  return true;
+}
+#endif
+
 bool CacheIRCompiler::emitGuardIsInt32() {
   JitSpew(JitSpew_Codegen, __FUNCTION__);
   ValOperandId inputId = reader.valOperandId();
   Register output = allocator.defineRegister(masm, reader.int32OperandId());
 
   if (allocator.knownType(inputId) == JSVAL_TYPE_INT32) {
     Register input = allocator.useRegister(masm, Int32OperandId(inputId.id()));
     masm.move32(input, output);
--- a/js/src/jit/CacheIRCompiler.h
+++ b/js/src/jit/CacheIRCompiler.h
@@ -21,16 +21,17 @@ namespace jit {
   _(GuardIsNullOrUndefined)               \
   _(GuardIsNotNullOrUndefined)            \
   _(GuardIsNull)                          \
   _(GuardIsUndefined)                     \
   _(GuardIsObjectOrNull)                  \
   _(GuardIsBoolean)                       \
   _(GuardIsString)                        \
   _(GuardIsSymbol)                        \
+  IF_BIGINT(_(GuardIsBigInt), )           \
   _(GuardIsNumber)                        \
   _(GuardIsInt32)                         \
   _(GuardIsInt32Index)                    \
   _(GuardType)                            \
   _(GuardClass)                           \
   _(GuardGroupHasUnanalyzedNewScript)     \
   _(GuardIsExtensible)                    \
   _(GuardIsNativeFunction)                \