Bug 1492995 - Adding CacheIR support for String + Boolean. r=mgaudet
☠☠ backed out by 0700688b9a22 ☠ ☠
authorAdam Holm <asorholm@email.arizona.edu>
Tue, 23 Apr 2019 20:46:14 +0000
changeset 470557 fd2bf318a8b29e7c1ab67b985c19c2c218a76d6e
parent 470556 5a728b586c417ce346840297353cb86a7d38629c
child 470558 db8e013ac78c8b0b4436fd86f867ce75e0064b5a
push id35908
push useraciure@mozilla.com
push dateWed, 24 Apr 2019 04:28:40 +0000
treeherdermozilla-central@c9f0730a57a6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmgaudet
bugs1492995
milestone68.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 1492995 - Adding CacheIR support for String + Boolean. r=mgaudet Differential Revision: https://phabricator.services.mozilla.com/D27376
js/src/jit-test/tests/cacheir/binaryarith.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
--- a/js/src/jit-test/tests/cacheir/binaryarith.js
+++ b/js/src/jit-test/tests/cacheir/binaryarith.js
@@ -45,16 +45,21 @@ var funAdd5 = (a, b) => { return a + b; 
 warmup(funAdd5, [[true, 10, 11], [false, 1, 1], [10, true, 11], [1, false, 1],
                  [2147483647, true, 2147483648],[true, 2147483647, 2147483648]]);
 
 // Add: String Number Concat
 var funAdd6 = (a, b) => { return a + b; }
 warmup(funAdd6, [["x", 10, "x10"], [10, "bba", "10bba"], ["x", 1.2, "x1.2"],
                  [1.2, "bba", "1.2bba"]]);
 
+// Add: String Boolean
+var funAddStrBool = (a, b) => { return a + b; }
+warmup(funAddStrBool, [[true, "true", "truetrue"], [false, "true", "falsetrue"],
+  ["a string", true, "a stringtrue"]]);
+
 // Sub Int32
 var funSub1 = (a, b) => { return a - b; }
 warmup(funSub1, [[7, 0, 7], [7, 8, -1], [4294967295, 2, 4294967293], [0,0,0]]);
 
 // Sub Double
 var funSub2 = (a, b) => { return a - b; }
 warmup(funSub2, [[7.5, 0, 7.5], [7, 8.125, -1.125], [4294967295.3125, 2, 4294967293.3125], [NaN,10,NaN]]);
 
--- a/js/src/jit/BaselineInspector.cpp
+++ b/js/src/jit/BaselineInspector.cpp
@@ -279,16 +279,17 @@ static MIRType ParseCacheIRStub(ICStub* 
     case CacheOp::LoadUndefinedResult:
       return MIRType::Undefined;
     case CacheOp::LoadBooleanResult:
       return MIRType::Boolean;
     case CacheOp::LoadStringResult:
     case CacheOp::CallStringConcatResult:
     case CacheOp::CallStringObjectConcatResult:
     case CacheOp::CallInt32ToString:
+    case CacheOp::BooleanToString:
     case CacheOp::CallNumberToString:
       return MIRType::String;
     case CacheOp::DoubleAddResult:
     case CacheOp::DoubleSubResult:
     case CacheOp::DoubleMulResult:
     case CacheOp::DoubleDivResult:
     case CacheOp::DoubleModResult:
     case CacheOp::DoubleNegationResult:
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -6398,16 +6398,21 @@ bool BinaryArithIRGenerator::tryAttachSt
   if (tryAttachStringObjectConcat()) {
     return true;
   }
 
   if (tryAttachStringNumberConcat()) {
     return true;
   }
 
+  // String + Boolean
+  if (tryAttachStringBooleanConcat()) {
+    return true;
+  }
+
   trackAttached(IRGenerator::NotAttached);
   return false;
 }
 
 bool BinaryArithIRGenerator::tryAttachBitwise() {
   // Only bit-wise and shifts.
   if (op_ != JSOP_BITOR && op_ != JSOP_BITXOR && op_ != JSOP_BITAND &&
       op_ != JSOP_LSH && op_ != JSOP_RSH && op_ != JSOP_URSH) {
@@ -6616,16 +6621,49 @@ bool BinaryArithIRGenerator::tryAttachSt
 
   writer.callStringConcatResult(lhsStrId, rhsStrId);
 
   writer.returnFromIC();
   trackAttached("BinaryArith.StringNumberConcat");
   return true;
 }
 
+bool BinaryArithIRGenerator::tryAttachStringBooleanConcat() {
+  // Only Addition
+  if (op_ != JSOP_ADD) {
+    return false;
+  }
+
+  if ((!lhs_.isString() || !rhs_.isBoolean()) &&
+      (!lhs_.isBoolean() || !rhs_.isString())) {
+    return false;
+  }
+
+  ValOperandId lhsId(writer.setInputOperandId(0));
+  ValOperandId rhsId(writer.setInputOperandId(1));
+
+  auto guardToString = [&](ValOperandId id, HandleValue v) {
+    if (v.isString()) {
+      return writer.guardIsString(id);
+    }
+    MOZ_ASSERT(v.isBoolean());
+    writer.guardIsBoolean(id);
+    return writer.callBooleanToString(id);
+  };
+
+  StringOperandId lhsStrId = guardToString(lhsId, lhs_);
+  StringOperandId rhsStrId = guardToString(rhsId, rhs_);
+
+  writer.callStringConcatResult(lhsStrId, rhsStrId);
+
+  writer.returnFromIC();
+  trackAttached("BinaryArith.StringBooleanConcat");
+  return true;
+}
+
 bool BinaryArithIRGenerator::tryAttachStringConcat() {
   // Only Addition
   if (op_ != JSOP_ADD) {
     return false;
   }
 
   // Check guards
   if (!lhs_.isString() || !rhs_.isString()) {
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -289,16 +289,17 @@ extern const uint32_t ArgLengths[];
   _(CallNativeSetter, Id, Id, Field)                                           \
   _(CallScriptedSetter, Id, Field, Id, Byte)                                   \
   _(CallSetArrayLength, Id, Byte, Id)                                          \
   _(CallProxySet, Id, Id, Field, Byte)                                         \
   _(CallProxySetByValue, Id, Id, Id, Byte)                                     \
   _(CallAddOrUpdateSparseElementHelper, Id, Id, Id, Byte)                      \
   _(CallInt32ToString, Id, Id)                                                 \
   _(CallNumberToString, Id, Id)                                                \
+  _(BooleanToString, Id, Id)                                                   \
   _(CallScriptedFunction, Id, Id, Byte)                                        \
   _(CallNativeFunction, Id, Id, Byte, IF_SIMULATOR(Field, Byte))               \
   _(CallClassHook, Id, Id, Byte, Field)                                        \
                                                                                \
   /* Meta ops generate no code, but contain data for BaselineInspector */      \
   _(MetaTwoByte, Byte, Field, Field)                                           \
                                                                                \
   /* The *Result ops load a value into the cache's result register. */         \
@@ -1292,16 +1293,22 @@ class MOZ_RAII CacheIRWriter : public JS
     return res;
   }
   StringOperandId callNumberToString(ValOperandId id) {
     StringOperandId res(nextOperandId_++);
     writeOpWithOperandId(CacheOp::CallNumberToString, id);
     writeOperandId(res);
     return res;
   }
+  StringOperandId callBooleanToString(ValOperandId id) {
+    StringOperandId res(nextOperandId_++);
+    writeOpWithOperandId(CacheOp::BooleanToString, id);
+    writeOperandId(res);
+    return res;
+  }
   void callScriptedFunction(ObjOperandId calleeId, Int32OperandId argc,
                             CallFlags flags) {
     writeOpWithOperandId(CacheOp::CallScriptedFunction, calleeId);
     writeOperandId(argc);
     writeCallFlags(flags);
   }
   void callNativeFunction(ObjOperandId calleeId, Int32OperandId argc, JSOp op,
                           HandleFunction calleeFunc, CallFlags flags) {
@@ -2435,16 +2442,17 @@ class MOZ_RAII BinaryArithIRGenerator : 
   void trackAttached(const char* name);
 
   bool tryAttachInt32();
   bool tryAttachDouble();
   bool tryAttachBitwise();
   bool tryAttachStringConcat();
   bool tryAttachStringObjectConcat();
   bool tryAttachStringNumberConcat();
+  bool tryAttachStringBooleanConcat();
 
  public:
   BinaryArithIRGenerator(JSContext* cx, HandleScript, jsbytecode* pc,
                          ICState::Mode, JSOp op, HandleValue lhs,
                          HandleValue rhs, HandleValue res);
 
   bool tryAttachStub();
 };
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -4279,16 +4279,37 @@ bool CacheIRCompiler::emitCallNumberToSt
 
   masm.mov(ReturnReg, result);
   masm.PopRegsInMask(volatileRegs);
 
   masm.branchPtr(Assembler::Equal, result, ImmPtr(0), failure->label());
   return true;
 }
 
+bool CacheIRCompiler::emitBooleanToString() {
+  JitSpew(JitSpew_Codegen, __FUNCTION__);
+  Register boolean = allocator.useRegister(masm, reader.objOperandId());
+  Register result = allocator.defineRegister(masm, reader.stringOperandId());
+  const JSAtomState& names = cx_->names();
+  Label true_, done;
+
+  masm.branchTest32(Assembler::NonZero, boolean, boolean, &true_);
+
+  // False case
+  masm.movePtr(ImmGCPtr(names.false_), result);
+  masm.jump(&done);
+
+  // True case
+  masm.bind(&true_);
+  masm.movePtr(ImmGCPtr(names.true_), result);
+  masm.bind(&done);
+
+  return true;
+}
+
 void js::jit::LoadTypedThingData(MacroAssembler& masm, TypedThingLayout layout,
                                  Register obj, Register result) {
   switch (layout) {
     case Layout_TypedArray:
       masm.loadPtr(Address(obj, TypedArrayObject::dataOffset()), result);
       break;
     case Layout_OutlineTypedObject:
       masm.loadPtr(Address(obj, OutlineTypedObject::offsetOfData()), result);
--- a/js/src/jit/CacheIRCompiler.h
+++ b/js/src/jit/CacheIRCompiler.h
@@ -121,16 +121,17 @@ namespace jit {
   _(Breakpoint)                           \
   _(MegamorphicLoadSlotResult)            \
   _(MegamorphicLoadSlotByValueResult)     \
   _(MegamorphicStoreSlot)                 \
   _(MegamorphicHasPropResult)             \
   _(CallObjectHasSparseElementResult)     \
   _(CallInt32ToString)                    \
   _(CallNumberToString)                   \
+  _(BooleanToString)                      \
   _(CallIsSuspendedGeneratorResult)       \
   _(MetaTwoByte)                          \
   _(WrapResult)
 
 // [SMDDOC] CacheIR Value Representation and Tracking
 //
 // While compiling an IC stub the CacheIR compiler needs to keep track of the
 // physical location for each logical piece of data we care about, as well as