Commit a41fd8cb authored by Matthew Gaudet's avatar Matthew Gaudet
Browse files

Bug 1467907 - Add an IC for String x Number comparison r=jandem

Differential Revision: https://phabricator.services.mozilla.com/D4259

--HG--
extra : moz-landing-system : lando
parent a4f9eea8
Loading
Loading
Loading
Loading
+34 −1
Original line number Diff line number Diff line
@@ -191,3 +191,36 @@ warmup(UndefNull_SNEQ1, [[undefined, null, true], [undefined, undefined, false],
var typeDifference = function(a,b) { return a === b; }
warmup(typeDifference, [[1,1, true], [3,3, true], [3, typeDifference, false],[typeDifference, {}, false],
                        [3.2, 1, false], [0, -0, true]]);

// String + Number
var String_Number_GT1 = (a, b) => { return a > b; }
warmup(String_Number_GT1, [["1.4",2, false], [1,"1", false], ["3",4, false],
                           [-1024, "-1023", false], [1.3, "1.2", true]]);

var String_Number_GTE1 = (a, b) => { return a >= b; }
warmup(String_Number_GTE1, [["1.4",2, false], [1,"1", true], [3,"4", false],
                            [-1024, "-1023", false], [1.2, "1.2", true]]);

var String_Number_LT1 = (a, b) => { return a < b; }
warmup(String_Number_LT1, [["1.4",2, true], ["1",1, false], [3,"4", true],
                           [-1024, "-1023", true], [1.2, "1.2", false]]);

var String_Number_LTE1 = (a, b) => { return a <= b; }
warmup(String_Number_LTE1, [["1.4",2, true], ["1",1, true], [3,"4", true],
                            [-1024, "-1023", true], [1.2, "1.2", true]]);

var String_Number_EQ1 = (a, b) => { return a == b; }
warmup(String_Number_EQ1, [["1.4",2, false], ["1",1, true], [3,"4", false],
                          [-1024, "-1023", false], [1.2, "1.2", true]]);

var String_Number_NEQ1 = (a, b) => { return a != b; }
warmup(String_Number_NEQ1, [["1.4",2, true], ["1",1, false], [3,"4", true],
                            [-1024, "-1023", true], [1.2, "1.2", false]]);

var String_Number_SEQ1 = (a, b) => { return a === b; }
warmup(String_Number_SEQ1, [["1.4",2, false],  ["1",1, false], [3,"4", false],
                            [-1024, "-1023", false], [1.2, "1.2", false]]);

var String_Number_SNEQ1 = (a, b) => { return a !== b; }
warmup(String_Number_SNEQ1, [["1.4",2, true], ["1",1, true], [3,"4", true],
                             [-1024, "-1023", true], [1.2, "1.2", true]]);
+36 −2
Original line number Diff line number Diff line
@@ -5008,6 +5008,38 @@ CompareIRGenerator::tryAttachNullUndefined(ValOperandId lhsId, ValOperandId rhsI
    return true;
}

bool
CompareIRGenerator::tryAttachStringNumber(ValOperandId lhsId, ValOperandId rhsId)
{
    // Ensure String x Number
    if (!(lhsVal_.isString() && rhsVal_.isNumber()) &&
        !(rhsVal_.isString() && lhsVal_.isNumber()))
    {
        return false;
    }

    // Case should have been handled by tryAttachStrictlDifferentTypes
    MOZ_ASSERT(op_ != JSOP_STRICTEQ && op_ != JSOP_STRICTNE);

    auto createGuards = [&](HandleValue v, ValOperandId vId) {
        if (v.isString()) {
            StringOperandId strId = writer.guardIsString(vId);
            return writer.guardAndGetNumberFromString(strId);
        }
        MOZ_ASSERT(v.isNumber());
        writer.guardIsNumber(vId);
        return vId;
    };

    ValOperandId lhsGuardedId = createGuards(lhsVal_, lhsId);
    ValOperandId rhsGuardedId = createGuards(rhsVal_, rhsId);
    writer.compareDoubleResult(op_, lhsGuardedId, rhsGuardedId);
    writer.returnFromIC();

    trackAttached("StringNumber");
    return true;
}

bool
CompareIRGenerator::tryAttachStub()
{
@@ -5029,8 +5061,7 @@ CompareIRGenerator::tryAttachStub()

    // For sloppy equality ops, there are cases this IC does not handle:
    // - {Symbol} x {Null, Undefined, String, Bool, Number}.
    // - {String} x {Null, Undefined, Symbol, Bool, Number}. Bug 1467907 will add support
    //   for {String} x {Int32}.
    // - {String} x {Null, Undefined, Symbol, Bool, Number}.
    // - {Bool} x {Double}.
    // - {Object} x {String, Symbol, Bool, Number}.
    if (IsEqualityOp(op_)) {
@@ -5073,6 +5104,9 @@ CompareIRGenerator::tryAttachStub()
    if (tryAttachNumber(lhsId, rhsId))
        return true;

    if (tryAttachStringNumber(lhsId, rhsId))
        return true;

    trackAttached(IRGenerator::NotAttached);
    return false;
}
+8 −0
Original line number Diff line number Diff line
@@ -217,6 +217,7 @@ extern const char* const CacheKindNames[];
    _(GuardNoUnboxedExpando)              \
    _(GuardAndLoadUnboxedExpando)         \
    _(GuardAndGetIndexFromString)         \
    _(GuardAndGetNumberFromString)        \
    _(GuardAndGetIterator)                \
    _(GuardHasGetterSetter)               \
    _(GuardGroupHasUnanalyzedNewScript)   \
@@ -770,6 +771,12 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
        writeOperandId(res);
        return res;
    }
    ValOperandId guardAndGetNumberFromString(StringOperandId str) {
        ValOperandId res(nextOperandId_++);
        writeOpWithOperandId(CacheOp::GuardAndGetNumberFromString, str);
        writeOperandId(res);
        return res;
    }
    ObjOperandId guardAndGetIterator(ObjOperandId obj, PropertyIteratorObject* iter,
                                     NativeIterator** enumeratorsAddr)
    {
@@ -1884,6 +1891,7 @@ class MOZ_RAII CompareIRGenerator : public IRGenerator
    bool tryAttachPrimitiveUndefined(ValOperandId lhsId, ValOperandId rhsId);
    bool tryAttachObjectUndefined(ValOperandId lhsId, ValOperandId rhsId);
    bool tryAttachNullUndefined(ValOperandId lhsId, ValOperandId rhsId);
    bool tryAttachStringNumber(ValOperandId lhsId, ValOperandId rhsId);

    void trackAttached(const char* name);

+61 −0
Original line number Diff line number Diff line
@@ -1855,6 +1855,67 @@ CacheIRCompiler::emitGuardNoDenseElements()
    return true;
}

bool
CacheIRCompiler::emitGuardAndGetNumberFromString()
{
    Register str = allocator.useRegister(masm, reader.stringOperandId());
    ValueOperand output = allocator.defineValueRegister(masm, reader.valOperandId());
    AutoScratchRegister scratch(allocator, masm);

    FailurePath* failure;
    if (!addFailurePath(&failure))
        return false;

    Label vmCall, done, failureRestoreStack;
    // Use indexed value as fast path if possible.
    masm.loadStringIndexValue(str, scratch, &vmCall);
    masm.tagValue(JSVAL_TYPE_INT32, scratch, output);
    masm.jump(&done);
    {
        masm.bind(&vmCall);
        // Reserve stack for holding the result value of the call.
        masm.reserveStack(sizeof(double));
        masm.moveStackPtrTo(output.payloadOrValueReg());

        // We cannot use callVM, as callVM exepcts to be able to clobber all operands,
        // however, since this op is not the last in the generated IC, we want to be able
        // to reference other live values.
        LiveRegisterSet volatileRegs(GeneralRegisterSet::Volatile(), liveVolatileFloatRegs());
        masm.PushRegsInMask(volatileRegs);

        masm.setupUnalignedABICall(scratch);
        masm.loadJSContext(scratch);
        masm.passABIArg(scratch);
        masm.passABIArg(str);
        masm.passABIArg(output.payloadOrValueReg());
        masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, StringToNumberDontReportOOM));
        masm.mov(ReturnReg, scratch);

        LiveRegisterSet ignore;
        ignore.add(scratch);
        masm.PopRegsInMaskIgnore(volatileRegs, ignore);

        Label ok;
        masm.branchIfTrueBool(scratch, &ok);
        {
            // OOM path, recovered by StringToNumberDontReportOOM.
            //
            // Use addToStackPtr instead of freeStack as freeStack tracks stack height
            // flow-insensitively, and using it twice would confuse the stack height
            // tracking. 
            masm.addToStackPtr(Imm32(sizeof(double)));
            masm.jump(failure->label());
        }
        masm.bind(&ok);
        
        masm.loadDouble(Address(output.payloadOrValueReg(), 0), FloatReg0);
        masm.boxDouble(FloatReg0, output, FloatReg0);
        masm.freeStack(sizeof(double));
    }
    masm.bind(&done);
    return true;
}

bool
CacheIRCompiler::emitGuardAndGetIndexFromString()
{
+1 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ namespace jit {
    _(GuardAndLoadUnboxedExpando)         \
    _(GuardNoDetachedTypedObjects)        \
    _(GuardNoDenseElements)               \
    _(GuardAndGetNumberFromString)        \
    _(GuardAndGetIndexFromString)         \
    _(GuardIndexIsNonNegative)            \
    _(GuardTagNotEqual)                   \
Loading