author | Jan de Mooij <jdemooij@mozilla.com> |
Thu, 18 Feb 2016 14:18:07 +0100 | |
changeset 284742 | 2da9867fc1d2 |
parent 284741 | 5658512697c4 |
child 284743 | b34a59d6ffe8 |
push id | 30013 |
push user | cbook@mozilla.com |
push date | Fri, 19 Feb 2016 11:02:40 +0000 |
treeherder | mozilla-central@a87d6d52c1fc [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | luke |
bugs | 1246658 |
milestone | 47.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
|
--- a/js/src/jit/IonAnalysis.cpp +++ b/js/src/jit/IonAnalysis.cpp @@ -1264,17 +1264,19 @@ GuessPhiType(MPhi* phi, bool* hasInputsW convertibleToFloat32 = true; continue; } if (type != in->type()) { if (convertibleToFloat32 && in->type() == MIRType_Float32) { // If we only saw definitions that can be converted into Float32 before and // encounter a Float32 value, promote previous values to Float32 type = MIRType_Float32; - } else if (IsNumberType(type) && IsNumberType(in->type())) { + } else if (IsTypeRepresentableAsDouble(type) && + IsTypeRepresentableAsDouble(in->type())) + { // Specialize phis with int32 and double operands as double. type = MIRType_Double; convertibleToFloat32 &= in->canProduceFloat32(); } else { return MIRType_Value; } } } @@ -1324,17 +1326,19 @@ TypeAnalyzer::propagateSpecialization(MP (phi->type() == MIRType_Int32 && phi->canProduceFloat32() && use->type() == MIRType_Float32)) { if (!respecialize(use, MIRType_Float32)) return false; continue; } // Specialize phis with int32 and double operands as double. - if (IsNumberType(use->type()) && IsNumberType(phi->type())) { + if (IsTypeRepresentableAsDouble(use->type()) && + IsTypeRepresentableAsDouble(phi->type())) + { if (!respecialize(use, MIRType_Double)) return false; continue; } // This phi in our use chain can now no longer be specialized. if (!respecialize(use, MIRType_Value)) return false; @@ -2496,16 +2500,17 @@ IsResumableMIRType(MIRType type) case MIRType_None: case MIRType_Slots: case MIRType_Elements: case MIRType_Pointer: case MIRType_Shape: case MIRType_ObjectGroup: case MIRType_Doublex2: // NYI, see also RSimdBox::recover case MIRType_SinCosDouble: + case MIRType_Int64: return false; } MOZ_CRASH("Unknown MIRType."); } static void AssertResumableOperands(MNode* node) {
--- a/js/src/jit/IonTypes.h +++ b/js/src/jit/IonTypes.h @@ -394,16 +394,17 @@ class SimdConstant { // specialized type. Furthermore, anything < String has trivial conversion to // a number. enum MIRType { MIRType_Undefined, MIRType_Null, MIRType_Boolean, MIRType_Int32, + MIRType_Int64, MIRType_Double, MIRType_Float32, MIRType_String, MIRType_Symbol, MIRType_Object, MIRType_MagicOptimizedArguments, // JS_OPTIMIZED_ARGUMENTS magic value. MIRType_MagicOptimizedOut, // JS_OPTIMIZED_OUT magic value. MIRType_MagicHole, // JS_ELEMENTS_HOLE magic value. @@ -499,16 +500,18 @@ StringFromMIRType(MIRType type) case MIRType_Undefined: return "Undefined"; case MIRType_Null: return "Null"; case MIRType_Boolean: return "Bool"; case MIRType_Int32: return "Int32"; + case MIRType_Int64: + return "Int64"; case MIRType_Double: return "Double"; case MIRType_Float32: return "Float32"; case MIRType_String: return "String"; case MIRType_Symbol: return "Symbol"; @@ -552,17 +555,28 @@ StringFromMIRType(MIRType type) return "Doublex2"; } MOZ_CRASH("Unknown MIRType."); } static inline bool IsNumberType(MIRType type) { - return type == MIRType_Int32 || type == MIRType_Double || type == MIRType_Float32; + return type == MIRType_Int32 || + type == MIRType_Double || + type == MIRType_Float32 || + type == MIRType_Int64; +} + +static inline bool +IsTypeRepresentableAsDouble(MIRType type) +{ + return type == MIRType_Int32 || + type == MIRType_Double || + type == MIRType_Float32; } static inline bool IsFloatType(MIRType type) { return type == MIRType_Int32 || type == MIRType_Float32; }
--- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -1275,17 +1275,17 @@ IonBuilder::inlineMathPowHelper(MDefinit return InliningStatus_NotInlined; MDefinition* base = lhs; MDefinition* power = rhs; MDefinition* output = nullptr; // Optimize some constant powers. if (rhs->isConstant()) { - double pow = rhs->toConstant()->toNumber(); + double pow = rhs->toConstant()->numberToDouble(); // Math.pow(x, 0.5) is a sqrt with edge-case detection. if (pow == 0.5) { MPowHalf* half = MPowHalf::New(alloc(), base); current->add(half); output = half; } @@ -1481,17 +1481,17 @@ IonBuilder::inlineMathMinMax(CallInfo& c if (!int32_cases.append(arg)) return InliningStatus_Error; break; case MIRType_Double: case MIRType_Float32: // Don't force a double MMinMax for arguments that would be a NOP // when doing an integer MMinMax. if (arg->isConstant()) { - double cte = arg->toConstant()->toNumber(); + double cte = arg->toConstant()->numberToDouble(); // min(int32, cte >= INT32_MAX) = int32 if (cte >= INT32_MAX && !max) break; // max(int32, cte <= INT32_MIN) = int32 if (cte <= INT32_MIN && max) break; }
--- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -80,17 +80,18 @@ MDefinition::PrintOpcodeName(GenericPrin } static MConstant* EvaluateConstantOperands(TempAllocator& alloc, MBinaryInstruction* ins, bool* ptypeChange = nullptr) { MDefinition* left = ins->getOperand(0); MDefinition* right = ins->getOperand(1); - MOZ_ASSERT(IsNumberType(left->type()) && IsNumberType(right->type())); + MOZ_ASSERT(IsTypeRepresentableAsDouble(left->type())); + MOZ_ASSERT(IsTypeRepresentableAsDouble(right->type())); if (!left->isConstant() || !right->isConstant()) return nullptr; MConstant* lhs = left->toConstant(); MConstant* rhs = right->toConstant(); Value ret = UndefinedValue(); @@ -109,35 +110,35 @@ EvaluateConstantOperands(TempAllocator& break; case MDefinition::Op_Rsh: ret = Int32Value(lhs->toInt32() >> (rhs->toInt32() & 0x1F)); break; case MDefinition::Op_Ursh: ret.setNumber(uint32_t(lhs->toInt32()) >> (rhs->toInt32() & 0x1F)); break; case MDefinition::Op_Add: - ret.setNumber(lhs->toNumber() + rhs->toNumber()); + ret.setNumber(lhs->numberToDouble() + rhs->numberToDouble()); break; case MDefinition::Op_Sub: - ret.setNumber(lhs->toNumber() - rhs->toNumber()); + ret.setNumber(lhs->numberToDouble() - rhs->numberToDouble()); break; case MDefinition::Op_Mul: - ret.setNumber(lhs->toNumber() * rhs->toNumber()); + ret.setNumber(lhs->numberToDouble() * rhs->numberToDouble()); break; case MDefinition::Op_Div: if (ins->toDiv()->isUnsigned()) ret.setInt32(rhs->isInt32(0) ? 0 : uint32_t(lhs->toInt32()) / uint32_t(rhs->toInt32())); else - ret.setNumber(NumberDiv(lhs->toNumber(), rhs->toNumber())); + ret.setNumber(NumberDiv(lhs->numberToDouble(), rhs->numberToDouble())); break; case MDefinition::Op_Mod: if (ins->toMod()->isUnsigned()) ret.setInt32(rhs->isInt32(0) ? 0 : uint32_t(lhs->toInt32()) % uint32_t(rhs->toInt32())); else - ret.setNumber(NumberMod(lhs->toNumber(), rhs->toNumber())); + ret.setNumber(NumberMod(lhs->numberToDouble(), rhs->numberToDouble())); break; default: MOZ_CRASH("NYI"); } // setNumber eagerly transforms a number to int32. // Transform back to double, if the output type is double. if (ins->type() == MIRType_Double && ret.isInt32()) @@ -161,17 +162,17 @@ EvaluateExactReciprocal(TempAllocator& a MDefinition* left = ins->getOperand(0); MDefinition* right = ins->getOperand(1); if (!right->isConstant()) return nullptr; int32_t num; - if (!mozilla::NumberIsInt32(right->toConstant()->toNumber(), &num)) + if (!mozilla::NumberIsInt32(right->toConstant()->numberToDouble(), &num)) return nullptr; // check if rhs is a power of two if (mozilla::Abs(num) & (mozilla::Abs(num) - 1)) return nullptr; Value ret; ret.setDouble(1.0 / (double) num); @@ -666,16 +667,22 @@ MConstant::New(TempAllocator& alloc, con MConstant* MConstant::NewFloat32(TempAllocator& alloc, double d) { MOZ_ASSERT(IsNaN(d) || d == double(float(d))); return new(alloc) MConstant(float(d)); } MConstant* +MConstant::NewInt64(TempAllocator& alloc, int64_t i) +{ + return new(alloc) MConstant(i); +} + +MConstant* MConstant::NewAsmJS(TempAllocator& alloc, const Value& v, MIRType type) { if (type == MIRType_Float32) return NewFloat32(alloc, v.toNumber()); MConstant* res = New(alloc, v); MOZ_ASSERT(res->type() == type); return res; } @@ -804,32 +811,40 @@ MConstant::MConstant(JSObject* obj) MConstant::MConstant(float f) { setResultType(MIRType_Float32); payload_.f = f; setMovable(); } +MConstant::MConstant(int64_t i) +{ + setResultType(MIRType_Int64); + payload_.i64 = i; + setMovable(); +} + #ifdef DEBUG void MConstant::assertInitializedPayload() const { // valueHash() and equals() expect the unused payload bits to be // initialized to zero. Assert this in debug builds. switch (type()) { case MIRType_Int32: case MIRType_Float32: MOZ_ASSERT((payload_.asBits >> 32) == 0); break; case MIRType_Boolean: MOZ_ASSERT((payload_.asBits >> 1) == 0); break; case MIRType_Double: + case MIRType_Int64: break; case MIRType_String: case MIRType_Object: case MIRType_Symbol: MOZ_ASSERT_IF(JS_BITS_PER_WORD == 32, (payload_.asBits >> 32) == 0); break; default: MOZ_ASSERT(IsNullOrUndefined(type()) || IsMagicType(type())); @@ -936,17 +951,17 @@ MConstant::printOpcode(GenericPrinter& o default: MOZ_CRASH("unexpected type"); } } bool MConstant::canProduceFloat32() const { - if (!IsNumberType(type())) + if (!isTypeRepresentableAsDouble()) return false; if (type() == MIRType_Int32) return IsFloat32Representable(static_cast<double>(toInt32())); if (type() == MIRType_Double) return IsFloat32Representable(toDouble()); MOZ_ASSERT(type() == MIRType_Float32); return true; @@ -1062,17 +1077,17 @@ MSimdValueX4::foldsTo(TempAllocator& all for (size_t i = 0; i < 4; ++i) a[i] = getOperand(i)->toConstant()->toInt32(); cst = SimdConstant::CreateX4(a); break; } case MIRType_Float32x4: { float a[4]; for (size_t i = 0; i < 4; ++i) - a[i] = getOperand(i)->toConstant()->toNumber(); + a[i] = getOperand(i)->toConstant()->numberToDouble(); cst = SimdConstant::CreateX4(a); break; } default: MOZ_CRASH("unexpected type in MSimdValueX4::foldsTo"); } return MSimdConstant::New(alloc, cst, type()); } @@ -1098,17 +1113,17 @@ MSimdSplatX4::foldsTo(TempAllocator& all break; } case MIRType_Int32x4: { int32_t v = op->toConstant()->toInt32(); cst = SimdConstant::SplatX4(v); break; } case MIRType_Float32x4: { - float v = op->toConstant()->toNumber(); + float v = op->toConstant()->numberToDouble(); cst = SimdConstant::SplatX4(v); break; } default: MOZ_CRASH("unexpected type in MSimdSplatX4::foldsTo"); } return MSimdConstant::New(alloc, cst, type()); } @@ -1441,20 +1456,20 @@ MMathFunction::printOpcode(GenericPrinte MDefinition::printOpcode(out); out.printf(" %s", FunctionName(function())); } MDefinition* MMathFunction::foldsTo(TempAllocator& alloc) { MDefinition* input = getOperand(0); - if (!input->isConstant() || !input->toConstant()->isNumber()) + if (!input->isConstant() || !input->toConstant()->isTypeRepresentableAsDouble()) return this; - double in = input->toConstant()->toNumber(); + double in = input->toConstant()->numberToDouble(); double out; switch (function_) { case Log: out = js::math_log_uncached(in); break; case Sin: out = js::math_sin_uncached(in); break; @@ -2012,17 +2027,17 @@ MPhi::foldsTernary() !falseDef->block()->dominates(falsePred)) { return nullptr; } // If testArg is an int32 type we can: // - fold testArg ? testArg : 0 to testArg // - fold testArg ? 0 : testArg to 0 - if (testArg->type() == MIRType_Int32 && c->toNumber() == 0) { + if (testArg->type() == MIRType_Int32 && c->numberToDouble() == 0) { // When folding to the constant we need to hoist it. if (trueDef == c && !c->block()->dominates(block())) c->block()->moveBefore(pred->lastIns(), c); return trueDef; } // If testArg is a string type we can: // - fold testArg ? testArg : "" to testArg @@ -2154,17 +2169,17 @@ MakeMIRTypeSet(MIRType type) bool jit::MergeTypes(MIRType* ptype, TemporaryTypeSet** ptypeSet, MIRType newType, TemporaryTypeSet* newTypeSet) { if (newTypeSet && newTypeSet->empty()) return true; if (newType != *ptype) { - if (IsNumberType(newType) && IsNumberType(*ptype)) { + if (IsTypeRepresentableAsDouble(newType) && IsTypeRepresentableAsDouble(*ptype)) { *ptype = MIRType_Double; } else if (*ptype != MIRType_Value) { if (!*ptypeSet) { *ptypeSet = MakeMIRTypeSet(*ptype); if (!*ptypeSet) return false; } *ptype = MIRType_Value; @@ -2388,17 +2403,17 @@ MCall::addArg(size_t argnum, MDefinition } static inline bool IsConstant(MDefinition* def, double v) { if (!def->isConstant()) return false; - return NumbersAreIdentical(def->toConstant()->toNumber(), v); + return NumbersAreIdentical(def->toConstant()->numberToDouble(), v); } MDefinition* MBinaryBitwiseInstruction::foldsTo(TempAllocator& alloc) { if (specialization_ != MIRType_Int32) return this; @@ -2802,21 +2817,24 @@ MDefinition* MMinMax::foldsTo(TempAllocator& alloc) { if (!lhs()->isConstant() && !rhs()->isConstant()) return this; // Directly apply math utility to compare the rhs() and lhs() when // they are both constants. if (lhs()->isConstant() && rhs()->isConstant()) { - if (!lhs()->toConstant()->isNumber() || !rhs()->toConstant()->isNumber()) + if (!lhs()->toConstant()->isTypeRepresentableAsDouble() || + !rhs()->toConstant()->isTypeRepresentableAsDouble()) + { return this; - - double lnum = lhs()->toConstant()->toNumber(); - double rnum = rhs()->toConstant()->toNumber(); + } + + double lnum = lhs()->toConstant()->numberToDouble(); + double rnum = rhs()->toConstant()->numberToDouble(); double result; if (isMax()) result = js::math_max_impl(lnum, rnum); else result = js::math_min_impl(lnum, rnum); // The folded MConstant should maintain the same MIRType with // the original MMinMax. @@ -2832,26 +2850,32 @@ MMinMax::foldsTo(TempAllocator& alloc) } } MDefinition* operand = lhs()->isConstant() ? rhs() : lhs(); MConstant* constant = lhs()->isConstant() ? lhs()->toConstant() : rhs()->toConstant(); if (operand->isToDouble() && operand->getOperand(0)->type() == MIRType_Int32) { // min(int32, cte >= INT32_MAX) = int32 - if (constant->isNumber() && constant->toNumber() >= INT32_MAX && !isMax()) { + if (!isMax() && + constant->isTypeRepresentableAsDouble() && + constant->numberToDouble() >= INT32_MAX) + { MLimitedTruncate* limit = MLimitedTruncate::New(alloc, operand->getOperand(0), MDefinition::NoTruncate); block()->insertBefore(this, limit); MToDouble* toDouble = MToDouble::New(alloc, limit); return toDouble; } // max(int32, cte <= INT32_MIN) = int32 - if (constant->isNumber() && constant->toNumber() <= INT32_MIN && isMax()) { + if (isMax() && + constant->isTypeRepresentableAsDouble() && + constant->numberToDouble() <= INT32_MIN) + { MLimitedTruncate* limit = MLimitedTruncate::New(alloc, operand->getOperand(0), MDefinition::NoTruncate); block()->insertBefore(this, limit); MToDouble* toDouble = MToDouble::New(alloc, limit); return toDouble; } } return this; @@ -3233,17 +3257,17 @@ MCompare::determineCompareType(JSOp op, if (!strictEq && (lhs == MIRType_Int32 || lhs == MIRType_Boolean) && (rhs == MIRType_Int32 || rhs == MIRType_Boolean)) { return Compare_Int32MaybeCoerceBoth; } // Numeric comparisons against a double coerce to double. - if (IsNumberType(lhs) && IsNumberType(rhs)) + if (IsTypeRepresentableAsDouble(lhs) && IsTypeRepresentableAsDouble(rhs)) return Compare_Double; // Any comparison is allowed except strict eq. if (!strictEq && IsFloatingPointType(rhs) && SafelyCoercesToDouble(left)) return Compare_DoubleMaybeCoerceLHS; if (!strictEq && IsFloatingPointType(lhs) && SafelyCoercesToDouble(right)) return Compare_DoubleMaybeCoerceRHS; @@ -3643,17 +3667,17 @@ MToInt32::foldsTo(TempAllocator& alloc) convert == MacroAssembler::IntConversion_NumbersOrBoolsOnly); return MConstant::New(alloc, Int32Value(input->toConstant()->toBoolean())); case MIRType_Int32: return MConstant::New(alloc, Int32Value(input->toConstant()->toInt32())); case MIRType_Float32: case MIRType_Double: int32_t ival; // Only the value within the range of Int32 can be substituted as constant. - if (mozilla::NumberEqualsInt32(input->toConstant()->toNumber(), &ival)) + if (mozilla::NumberEqualsInt32(input->toConstant()->numberToDouble(), &ival)) return MConstant::New(alloc, Int32Value(ival)); break; default: break; } } if (input->type() == MIRType_Int32) @@ -3691,18 +3715,18 @@ MToDouble::foldsTo(TempAllocator& alloc) { MDefinition* input = getOperand(0); if (input->isBox()) input = input->getOperand(0); if (input->type() == MIRType_Double) return input; - if (input->isConstant() && input->toConstant()->isNumber()) { - double out = input->toConstant()->toNumber(); + if (input->isConstant() && input->toConstant()->isTypeRepresentableAsDouble()) { + double out = input->toConstant()->numberToDouble(); return MConstant::New(alloc, DoubleValue(out)); } return this; } MDefinition* MToFloat32::foldsTo(TempAllocator& alloc) @@ -3713,18 +3737,18 @@ MToFloat32::foldsTo(TempAllocator& alloc if (input->type() == MIRType_Float32) return input; // If x is a Float32, Float32(Double(x)) == x if (input->isToDouble() && input->toToDouble()->input()->type() == MIRType_Float32) return input->toToDouble()->input(); - if (input->isConstant() && input->toConstant()->isNumber()) - return MConstant::NewFloat32(alloc, float(input->toConstant()->toNumber())); + if (input->isConstant() && input->toConstant()->isTypeRepresentableAsDouble()) + return MConstant::NewFloat32(alloc, float(input->toConstant()->numberToDouble())); return this; } MDefinition* MToString::foldsTo(TempAllocator& alloc) { MDefinition* in = input(); @@ -3735,18 +3759,18 @@ MToString::foldsTo(TempAllocator& alloc) return in; return this; } MDefinition* MClampToUint8::foldsTo(TempAllocator& alloc) { if (MConstant* inputConst = input()->maybeConstantValue()) { - if (inputConst->isNumber()) { - int32_t clamped = ClampDoubleToUint8(inputConst->toNumber()); + if (inputConst->isTypeRepresentableAsDouble()) { + int32_t clamped = ClampDoubleToUint8(inputConst->numberToDouble()); return MConstant::New(alloc, Int32Value(clamped)); } } return this; } bool MCompare::tryFoldEqualOperands(bool* result) @@ -4078,39 +4102,39 @@ MCompare::evaluateConstantOperands(TempA break; default: MOZ_CRASH("Unexpected op."); } return true; } - if (!lhs->isNumber() || !rhs->isNumber()) + if (!lhs->isTypeRepresentableAsDouble() || !rhs->isTypeRepresentableAsDouble()) return false; switch (jsop_) { case JSOP_LT: - *result = (lhs->toNumber() < rhs->toNumber()); + *result = (lhs->numberToDouble() < rhs->numberToDouble()); break; case JSOP_LE: - *result = (lhs->toNumber() <= rhs->toNumber()); + *result = (lhs->numberToDouble() <= rhs->numberToDouble()); break; case JSOP_GT: - *result = (lhs->toNumber() > rhs->toNumber()); + *result = (lhs->numberToDouble() > rhs->numberToDouble()); break; case JSOP_GE: - *result = (lhs->toNumber() >= rhs->toNumber()); + *result = (lhs->numberToDouble() >= rhs->numberToDouble()); break; case JSOP_STRICTEQ: // Fall through. case JSOP_EQ: - *result = (lhs->toNumber() == rhs->toNumber()); + *result = (lhs->numberToDouble() == rhs->numberToDouble()); break; case JSOP_STRICTNE: // Fall through. case JSOP_NE: - *result = (lhs->toNumber() != rhs->toNumber()); + *result = (lhs->numberToDouble() != rhs->numberToDouble()); break; default: return false; } return true; }
--- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -1366,16 +1366,17 @@ class MLimitedTruncate // A constant js::Value. class MConstant : public MNullaryInstruction { struct Payload { union { bool b; int32_t i32; + int64_t i64; float f; double d; JSString* str; JS::Symbol* sym; JSObject* obj; uint64_t asBits; }; Payload() : asBits(0) {} @@ -1391,22 +1392,24 @@ class MConstant : public MNullaryInstruc #else void assertInitializedPayload() const {} #endif protected: MConstant(const Value& v, CompilerConstraintList* constraints); explicit MConstant(JSObject* obj); explicit MConstant(float f); + explicit MConstant(int64_t i); public: INSTRUCTION_HEADER(Constant) static MConstant* New(TempAllocator& alloc, const Value& v, CompilerConstraintList* constraints = nullptr); static MConstant* NewFloat32(TempAllocator& alloc, double d); + static MConstant* NewInt64(TempAllocator& alloc, int64_t i); static MConstant* NewAsmJS(TempAllocator& alloc, const Value& v, MIRType type); static MConstant* NewConstraintlessObject(TempAllocator& alloc, JSObject* v); // Try to convert this constant to boolean, similar to js::ToBoolean. // Returns false if the type is MIRType_Magic*. bool valueToBoolean(bool* res) const; // Like valueToBoolean, but returns the result directly instead of using @@ -1453,16 +1456,20 @@ class MConstant : public MNullaryInstruc bool toBoolean() const { MOZ_ASSERT(type() == MIRType_Boolean); return payload_.b; } int32_t toInt32() const { MOZ_ASSERT(type() == MIRType_Int32); return payload_.i32; } + int64_t toInt64() const { + MOZ_ASSERT(type() == MIRType_Int64); + return payload_.i64; + } bool isInt32(int32_t i) const { return type() == MIRType_Int32 && payload_.i32 == i; } double toDouble() const { MOZ_ASSERT(type() == MIRType_Double); return payload_.d; } float toFloat32() const { @@ -1483,25 +1490,25 @@ class MConstant : public MNullaryInstruc } JSObject* toObjectOrNull() const { if (type() == MIRType_Object) return payload_.obj; MOZ_ASSERT(type() == MIRType_Null); return nullptr; } - bool isNumber() const { - return IsNumberType(type()); - } - double toNumber() const { + bool isTypeRepresentableAsDouble() const { + return IsTypeRepresentableAsDouble(type()); + } + double numberToDouble() const { + MOZ_ASSERT(isTypeRepresentableAsDouble()); if (type() == MIRType_Int32) return toInt32(); if (type() == MIRType_Double) return toDouble(); - MOZ_ASSERT(type() == MIRType_Float32); return toFloat32(); } // Convert this constant to a js::Value. Float32 constants will be stored // as DoubleValue and NaNs are canonicalized. Callers must be careful: not // all constants can be represented by js::Value (wasm supports int64). Value toJSValue() const; };
--- a/js/src/jit/RangeAnalysis.cpp +++ b/js/src/jit/RangeAnalysis.cpp @@ -193,22 +193,22 @@ RangeAnalysis::addBetaNodes() if (branch_dir == FALSE_BRANCH) { jsop = NegateCompareOp(jsop); conservativeLower = GenericNaN(); conservativeUpper = GenericNaN(); } MConstant* leftConst = left->maybeConstantValue(); MConstant* rightConst = right->maybeConstantValue(); - if (leftConst && leftConst->isNumber()) { - bound = leftConst->toNumber(); + if (leftConst && leftConst->isTypeRepresentableAsDouble()) { + bound = leftConst->numberToDouble(); val = right; jsop = ReverseCompareOp(jsop); - } else if (rightConst && rightConst->isNumber()) { - bound = rightConst->toNumber(); + } else if (rightConst && rightConst->isTypeRepresentableAsDouble()) { + bound = rightConst->numberToDouble(); val = left; } else if (left->type() == MIRType_Int32 && right->type() == MIRType_Int32) { MDefinition* smaller = nullptr; MDefinition* greater = nullptr; if (jsop == JSOP_LT) { smaller = left; greater = right; } else if (jsop == JSOP_GT) { @@ -1286,18 +1286,18 @@ MBeta::computeRange(TempAllocator& alloc } else { setRange(range); } } void MConstant::computeRange(TempAllocator& alloc) { - if (isNumber()) { - double d = toNumber(); + if (isTypeRepresentableAsDouble()) { + double d = numberToDouble(); setRange(Range::NewDoubleSingletonRange(alloc, d)); } else if (type() == MIRType_Boolean) { bool b = toBoolean(); setRange(Range::NewInt32Range(alloc, b, b)); } } void @@ -2411,17 +2411,17 @@ MConstant::needTruncation(TruncateKind k } void MConstant::truncate() { MOZ_ASSERT(needTruncation(Truncate)); // Truncate the double to int, since all uses truncates it. - int32_t res = ToInt32(toNumber()); + int32_t res = ToInt32(numberToDouble()); payload_.asBits = 0; payload_.i32 = res; setResultType(MIRType_Int32); if (range()) range()->setInt32(res, res); } bool
--- a/js/src/jit/shared/CodeGenerator-shared-inl.h +++ b/js/src/jit/shared/CodeGenerator-shared-inl.h @@ -23,17 +23,17 @@ ToInt32(const LAllocation* a) if (a->isConstantIndex()) return a->toConstantIndex()->index(); MOZ_CRASH("this is not a constant!"); } static inline double ToDouble(const LAllocation* a) { - return a->toConstant()->toNumber(); + return a->toConstant()->numberToDouble(); } static inline Register ToRegister(const LAllocation& a) { MOZ_ASSERT(a.isGeneralReg()); return a.toGeneralReg()->reg(); }
--- a/js/src/jsapi-tests/testJitDCEinGVN.cpp +++ b/js/src/jsapi-tests/testJitDCEinGVN.cpp @@ -131,13 +131,13 @@ BEGIN_TEST(testJitDCEinGVN_phi) MReturn* ret = MReturn::New(func.alloc, y); joinBlock->end(ret); if (!func.runGVN()) return false; // c1 should be deleted. for (MInstructionIterator ins = block->begin(); ins != block->end(); ins++) { - CHECK(!ins->isConstant() || (ins->toConstant()->toNumber() != 1.0)); + CHECK(!ins->isConstant() || (ins->toConstant()->numberToDouble() != 1.0)); } return true; } END_TEST(testJitDCEinGVN_phi)
--- a/js/src/jsapi-tests/testJitFoldsTo.cpp +++ b/js/src/jsapi-tests/testJitFoldsTo.cpp @@ -37,17 +37,17 @@ BEGIN_TEST(testJitFoldsTo_DivReciprocal) if (!func.runGVN()) return false; // Test that the div got folded to p * 0.25. MDefinition* op = ret->getOperand(0); CHECK(op->isMul()); CHECK(op->getOperand(0) == left); CHECK(op->getOperand(1)->isConstant()); - CHECK(op->getOperand(1)->toConstant()->toNumber() == 0.25); + CHECK(op->getOperand(1)->toConstant()->numberToDouble() == 0.25); return true; } END_TEST(testJitFoldsTo_DivReciprocal) BEGIN_TEST(testJitFoldsTo_NoDivReciprocal) { MinimalFunc func; MBasicBlock* block = func.createEntryBlock(); @@ -224,17 +224,17 @@ BEGIN_TEST(testJitFoldsTo_UnsignedDiv) MReturn* ret = MReturn::New(func.alloc, div); block->end(ret); if (!func.runGVN()) return false; // Test that the div got folded to 0. MConstant* op = ret->getOperand(0)->toConstant(); - CHECK(mozilla::NumbersAreIdentical(op->toNumber(), 0.0)); + CHECK(mozilla::NumbersAreIdentical(op->numberToDouble(), 0.0)); return true; } END_TEST(testJitFoldsTo_UnsignedDiv) BEGIN_TEST(testJitFoldsTo_UnsignedMod) { MinimalFunc func; MBasicBlock* block = func.createEntryBlock(); @@ -249,12 +249,12 @@ BEGIN_TEST(testJitFoldsTo_UnsignedMod) MReturn* ret = MReturn::New(func.alloc, mod); block->end(ret); if (!func.runGVN()) return false; // Test that the mod got folded to 1. MConstant* op = ret->getOperand(0)->toConstant(); - CHECK(mozilla::NumbersAreIdentical(op->toNumber(), 1.0)); + CHECK(mozilla::NumbersAreIdentical(op->numberToDouble(), 1.0)); return true; } END_TEST(testJitFoldsTo_UnsignedMod)