Loading js/src/jit-test/tests/cacheir/compare.js +34 −1 Original line number Diff line number Diff line Loading @@ -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]]); js/src/jit/CacheIR.cpp +36 −2 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -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_)) { Loading Loading @@ -5073,6 +5104,9 @@ CompareIRGenerator::tryAttachStub() if (tryAttachNumber(lhsId, rhsId)) return true; if (tryAttachStringNumber(lhsId, rhsId)) return true; trackAttached(IRGenerator::NotAttached); return false; } Loading js/src/jit/CacheIR.h +8 −0 Original line number Diff line number Diff line Loading @@ -217,6 +217,7 @@ extern const char* const CacheKindNames[]; _(GuardNoUnboxedExpando) \ _(GuardAndLoadUnboxedExpando) \ _(GuardAndGetIndexFromString) \ _(GuardAndGetNumberFromString) \ _(GuardAndGetIterator) \ _(GuardHasGetterSetter) \ _(GuardGroupHasUnanalyzedNewScript) \ Loading Loading @@ -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) { Loading Loading @@ -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); Loading js/src/jit/CacheIRCompiler.cpp +61 −0 Original line number Diff line number Diff line Loading @@ -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() { Loading js/src/jit/CacheIRCompiler.h +1 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ namespace jit { _(GuardAndLoadUnboxedExpando) \ _(GuardNoDetachedTypedObjects) \ _(GuardNoDenseElements) \ _(GuardAndGetNumberFromString) \ _(GuardAndGetIndexFromString) \ _(GuardIndexIsNonNegative) \ _(GuardTagNotEqual) \ Loading Loading
js/src/jit-test/tests/cacheir/compare.js +34 −1 Original line number Diff line number Diff line Loading @@ -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]]);
js/src/jit/CacheIR.cpp +36 −2 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -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_)) { Loading Loading @@ -5073,6 +5104,9 @@ CompareIRGenerator::tryAttachStub() if (tryAttachNumber(lhsId, rhsId)) return true; if (tryAttachStringNumber(lhsId, rhsId)) return true; trackAttached(IRGenerator::NotAttached); return false; } Loading
js/src/jit/CacheIR.h +8 −0 Original line number Diff line number Diff line Loading @@ -217,6 +217,7 @@ extern const char* const CacheKindNames[]; _(GuardNoUnboxedExpando) \ _(GuardAndLoadUnboxedExpando) \ _(GuardAndGetIndexFromString) \ _(GuardAndGetNumberFromString) \ _(GuardAndGetIterator) \ _(GuardHasGetterSetter) \ _(GuardGroupHasUnanalyzedNewScript) \ Loading Loading @@ -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) { Loading Loading @@ -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); Loading
js/src/jit/CacheIRCompiler.cpp +61 −0 Original line number Diff line number Diff line Loading @@ -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() { Loading
js/src/jit/CacheIRCompiler.h +1 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ namespace jit { _(GuardAndLoadUnboxedExpando) \ _(GuardNoDetachedTypedObjects) \ _(GuardNoDenseElements) \ _(GuardAndGetNumberFromString) \ _(GuardAndGetIndexFromString) \ _(GuardIndexIsNonNegative) \ _(GuardTagNotEqual) \ Loading