Bug 1341261 - Use CompareIR for symbol and object equality. r=jandem
authorTom Schuster <evilpies@gmail.com>
Wed, 12 Jul 2017 21:54:22 +0200
changeset 607742 63215af4995f74aae2a6b24ad148e83d47c732f9
parent 607741 0fef3ce5bc6360bedb4548cc4c3396c7480f6406
child 607743 2069d1720a985245e1dae87248632352495e75eb
child 607756 00e1ea28e70d4b2387049b75aadb563567b33c16
child 607767 a8809f15b58213f3292b9eaf7fa9583377d1fa30
push id68095
push userbmo:rbarker@mozilla.com
push dateWed, 12 Jul 2017 20:01:47 +0000
reviewersjandem
bugs1341261
milestone56.0a1
Bug 1341261 - Use CompareIR for symbol and object equality. r=jandem
js/src/jit/CacheIR.cpp
js/src/jit/CacheIR.h
js/src/jit/CacheIRCompiler.cpp
js/src/jit/CacheIRCompiler.h
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -3717,31 +3717,69 @@ CompareIRGenerator::tryAttachString(ValO
     writer.compareStringResult(op_, lhsStrId, rhsStrId);
     writer.returnFromIC();
 
     trackAttached("String");
     return true;
 }
 
 bool
+CompareIRGenerator::tryAttachObject(ValOperandId lhsId, ValOperandId rhsId)
+{
+    MOZ_ASSERT(IsEqualityOp(op_));
+
+    if (!lhsVal_.isObject() || !rhsVal_.isObject())
+        return false;
+
+    ObjOperandId lhsObjId = writer.guardIsObject(lhsId);
+    ObjOperandId rhsObjId = writer.guardIsObject(rhsId);
+    writer.compareObjectResult(op_, lhsObjId, rhsObjId);
+    writer.returnFromIC();
+
+    trackAttached("Object");
+    return true;
+}
+
+bool
+CompareIRGenerator::tryAttachSymbol(ValOperandId lhsId, ValOperandId rhsId)
+{
+    MOZ_ASSERT(IsEqualityOp(op_));
+
+    if (!lhsVal_.isSymbol() || !rhsVal_.isSymbol())
+        return false;
+
+    SymbolOperandId lhsSymId = writer.guardIsSymbol(lhsId);
+    SymbolOperandId rhsSymId = writer.guardIsSymbol(rhsId);
+    writer.compareSymbolResult(op_, lhsSymId, rhsSymId);
+    writer.returnFromIC();
+
+    trackAttached("Symbol");
+    return true;
+}
+
+bool
 CompareIRGenerator::tryAttachStub()
 {
     MOZ_ASSERT(cacheKind_ == CacheKind::Compare);
     MOZ_ASSERT(IsEqualityOp(op_) ||
                op_ == JSOP_LE || op_ == JSOP_LT ||
                op_ == JSOP_GE || op_ == JSOP_GT);
 
     AutoAssertNoPendingException aanpe(cx_);
 
     ValOperandId lhsId(writer.setInputOperandId(0));
     ValOperandId rhsId(writer.setInputOperandId(1));
 
     if (IsEqualityOp(op_)) {
         if (tryAttachString(lhsId, rhsId))
             return true;
+        if (tryAttachObject(lhsId, rhsId))
+            return true;
+        if (tryAttachSymbol(lhsId, rhsId))
+            return true;
 
         trackNotAttached();
         return false;
     }
 
     trackNotAttached();
     return false;
 }
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -254,16 +254,18 @@ extern const char* CacheKindNames[];
     _(LoadUndefinedResult)                \
     _(LoadBooleanResult)                  \
     _(LoadStringResult)                   \
     _(LoadTypeOfObjectResult)             \
                                           \
     _(CallStringSplitResult)              \
                                           \
     _(CompareStringResult)                \
+    _(CompareObjectResult)                \
+    _(CompareSymbolResult)                \
                                           \
     _(CallPrintString)                    \
     _(Breakpoint)                         \
                                           \
     _(TypeMonitorResult)                  \
     _(ReturnFromIC)                       \
     _(WrapResult)
 
@@ -958,16 +960,26 @@ class MOZ_RAII CacheIRWriter : public JS
         addStubField(uintptr_t(group), StubField::Type::ObjectGroup);
     }
 
     void compareStringResult(uint32_t op, StringOperandId lhs, StringOperandId rhs) {
         writeOpWithOperandId(CacheOp::CompareStringResult, lhs);
         writeOperandId(rhs);
         buffer_.writeByte(uint32_t(op));
     }
+    void compareObjectResult(uint32_t op, ObjOperandId lhs, ObjOperandId rhs) {
+        writeOpWithOperandId(CacheOp::CompareObjectResult, lhs);
+        writeOperandId(rhs);
+        buffer_.writeByte(uint32_t(op));
+    }
+    void compareSymbolResult(uint32_t op, SymbolOperandId lhs, SymbolOperandId rhs) {
+        writeOpWithOperandId(CacheOp::CompareSymbolResult, lhs);
+        writeOperandId(rhs);
+        buffer_.writeByte(uint32_t(op));
+    }
 
     void callPrintString(const char* str) {
         writeOp(CacheOp::CallPrintString);
         writePointer(const_cast<char*>(str));
     }
     void breakpoint() {
         writeOp(CacheOp::Breakpoint);
     }
@@ -1427,16 +1439,18 @@ class MOZ_RAII CallIRGenerator : public 
 
 class MOZ_RAII CompareIRGenerator : public IRGenerator
 {
     JSOp op_;
     HandleValue lhsVal_;
     HandleValue rhsVal_;
 
     bool tryAttachString(ValOperandId lhsId, ValOperandId rhsId);
+    bool tryAttachObject(ValOperandId lhsId, ValOperandId rhsId);
+    bool tryAttachSymbol(ValOperandId lhsId, ValOperandId rhsId);
 
     void trackAttached(const char* name);
     void trackNotAttached();
 
   public:
     CompareIRGenerator(JSContext* cx, HandleScript, jsbytecode* pc, ICState::Mode mode,
                        JSOp op, HandleValue lhsVal, HandleValue rhsVal);
 
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -2242,16 +2242,54 @@ CacheIRCompiler::emitCompareStringResult
         return false;
 
     masm.compareStrings(op, left, right, scratch, failure->label());
     masm.tagValue(JSVAL_TYPE_BOOLEAN, scratch, output.valueReg());
     return true;
 }
 
 bool
+CacheIRCompiler::emitComparePointerResultShared(bool symbol)
+{
+    AutoOutputRegister output(*this);
+
+    Register left = symbol ? allocator.useRegister(masm, reader.symbolOperandId())
+                           : allocator.useRegister(masm, reader.objOperandId());
+    Register right = symbol ? allocator.useRegister(masm, reader.symbolOperandId())
+                            : allocator.useRegister(masm, reader.objOperandId());
+    JSOp op = reader.jsop();
+
+    AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
+
+    Label ifTrue, done;
+    masm.branchPtr(JSOpToCondition(op, /* signed = */true), left, right, &ifTrue);
+
+    masm.moveValue(BooleanValue(false), output.valueReg());
+    masm.jump(&done);
+
+    masm.bind(&ifTrue);
+    masm.moveValue(BooleanValue(true), output.valueReg());
+    masm.bind(&done);
+    return true;
+}
+
+
+bool
+CacheIRCompiler::emitCompareObjectResult()
+{
+    return emitComparePointerResultShared(false);
+}
+
+bool
+CacheIRCompiler::emitCompareSymbolResult()
+{
+    return emitComparePointerResultShared(true);
+}
+
+bool
 CacheIRCompiler::emitCallPrintString()
 {
     const char* str = reinterpret_cast<char*>(reader.pointer());
     masm.printf(str);
     return true;
 }
 
 bool
--- a/js/src/jit/CacheIRCompiler.h
+++ b/js/src/jit/CacheIRCompiler.h
@@ -51,16 +51,18 @@ namespace jit {
     _(LoadDenseElementHoleResult)         \
     _(LoadDenseElementExistsResult)       \
     _(LoadDenseElementHoleExistsResult)   \
     _(LoadUnboxedArrayElementResult)      \
     _(LoadTypedElementResult)             \
     _(LoadObjectResult)                   \
     _(LoadTypeOfObjectResult)             \
     _(CompareStringResult)                \
+    _(CompareObjectResult)                \
+    _(CompareSymbolResult)                \
     _(CallPrintString)                    \
     _(Breakpoint)                         \
     _(MegamorphicLoadSlotByValueResult)   \
     _(MegamorphicHasOwnResult)            \
     _(WrapResult)
 
 // Represents a Value on the Baseline frame's expression stack. Slot 0 is the
 // value on top of the stack (the most recently pushed value), slot 1 is the
@@ -611,16 +613,18 @@ class MOZ_RAII CacheIRCompiler
     }
 
     template <typename T>
     void emitPostBarrierElement(Register obj, const T& val, Register scratch, Register index) {
         MOZ_ASSERT(index != InvalidReg);
         emitPostBarrierShared(obj, val, scratch, index);
     }
 
+    bool emitComparePointerResultShared(bool symbol);
+
 #define DEFINE_SHARED_OP(op) MOZ_MUST_USE bool emit##op();
     CACHE_IR_SHARED_OPS(DEFINE_SHARED_OP)
 #undef DEFINE_SHARED_OP
 };
 
 // Ensures the IC's output register is available for writing.
 class MOZ_RAII AutoOutputRegister
 {