diff options
Diffstat (limited to 'js/src/jit/Recover.cpp')
-rw-r--r-- | js/src/jit/Recover.cpp | 370 |
1 files changed, 173 insertions, 197 deletions
diff --git a/js/src/jit/Recover.cpp b/js/src/jit/Recover.cpp index 220ffe7bb2..4c1ff56436 100644 --- a/js/src/jit/Recover.cpp +++ b/js/src/jit/Recover.cpp @@ -6,6 +6,8 @@ #include "jit/Recover.h" +#include "mozilla/Casting.h" + #include "jsmath.h" #include "builtin/Object.h" @@ -495,16 +497,15 @@ bool MBigIntAdd::writeRecoverData(CompactBufferWriter& writer) const { RBigIntAdd::RBigIntAdd(CompactBufferReader& reader) {} bool RBigIntAdd::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedValue lhs(cx, iter.read()); - RootedValue rhs(cx, iter.read()); - RootedValue result(cx); + Rooted<BigInt*> lhs(cx, iter.readBigInt()); + Rooted<BigInt*> rhs(cx, iter.readBigInt()); - MOZ_ASSERT(lhs.isBigInt() && rhs.isBigInt()); - if (!js::AddValues(cx, &lhs, &rhs, &result)) { + BigInt* result = BigInt::add(cx, lhs, rhs); + if (!result) { return false; } - iter.storeInstructionResult(result); + iter.storeInstructionResult(BigIntValue(result)); return true; } @@ -517,16 +518,15 @@ bool MBigIntSub::writeRecoverData(CompactBufferWriter& writer) const { RBigIntSub::RBigIntSub(CompactBufferReader& reader) {} bool RBigIntSub::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedValue lhs(cx, iter.read()); - RootedValue rhs(cx, iter.read()); - RootedValue result(cx); + Rooted<BigInt*> lhs(cx, iter.readBigInt()); + Rooted<BigInt*> rhs(cx, iter.readBigInt()); - MOZ_ASSERT(lhs.isBigInt() && rhs.isBigInt()); - if (!js::SubValues(cx, &lhs, &rhs, &result)) { + BigInt* result = BigInt::sub(cx, lhs, rhs); + if (!result) { return false; } - iter.storeInstructionResult(result); + iter.storeInstructionResult(BigIntValue(result)); return true; } @@ -539,16 +539,15 @@ bool MBigIntMul::writeRecoverData(CompactBufferWriter& writer) const { RBigIntMul::RBigIntMul(CompactBufferReader& reader) {} bool RBigIntMul::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedValue lhs(cx, iter.read()); - RootedValue rhs(cx, iter.read()); - RootedValue result(cx); + Rooted<BigInt*> lhs(cx, iter.readBigInt()); + Rooted<BigInt*> rhs(cx, iter.readBigInt()); - MOZ_ASSERT(lhs.isBigInt() && rhs.isBigInt()); - if (!js::MulValues(cx, &lhs, &rhs, &result)) { + BigInt* result = BigInt::mul(cx, lhs, rhs); + if (!result) { return false; } - iter.storeInstructionResult(result); + iter.storeInstructionResult(BigIntValue(result)); return true; } @@ -561,18 +560,17 @@ bool MBigIntDiv::writeRecoverData(CompactBufferWriter& writer) const { RBigIntDiv::RBigIntDiv(CompactBufferReader& reader) {} bool RBigIntDiv::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedValue lhs(cx, iter.read()); - RootedValue rhs(cx, iter.read()); - RootedValue result(cx); - - MOZ_ASSERT(lhs.isBigInt() && rhs.isBigInt()); - MOZ_ASSERT(!rhs.toBigInt()->isZero(), + Rooted<BigInt*> lhs(cx, iter.readBigInt()); + Rooted<BigInt*> rhs(cx, iter.readBigInt()); + MOZ_ASSERT(!rhs->isZero(), "division by zero throws and therefore can't be recovered"); - if (!js::DivValues(cx, &lhs, &rhs, &result)) { + + BigInt* result = BigInt::div(cx, lhs, rhs); + if (!result) { return false; } - iter.storeInstructionResult(result); + iter.storeInstructionResult(BigIntValue(result)); return true; } @@ -585,18 +583,17 @@ bool MBigIntMod::writeRecoverData(CompactBufferWriter& writer) const { RBigIntMod::RBigIntMod(CompactBufferReader& reader) {} bool RBigIntMod::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedValue lhs(cx, iter.read()); - RootedValue rhs(cx, iter.read()); - RootedValue result(cx); - - MOZ_ASSERT(lhs.isBigInt() && rhs.isBigInt()); - MOZ_ASSERT(!rhs.toBigInt()->isZero(), + Rooted<BigInt*> lhs(cx, iter.readBigInt()); + Rooted<BigInt*> rhs(cx, iter.readBigInt()); + MOZ_ASSERT(!rhs->isZero(), "division by zero throws and therefore can't be recovered"); - if (!js::ModValues(cx, &lhs, &rhs, &result)) { + + BigInt* result = BigInt::mod(cx, lhs, rhs); + if (!result) { return false; } - iter.storeInstructionResult(result); + iter.storeInstructionResult(BigIntValue(result)); return true; } @@ -609,18 +606,17 @@ bool MBigIntPow::writeRecoverData(CompactBufferWriter& writer) const { RBigIntPow::RBigIntPow(CompactBufferReader& reader) {} bool RBigIntPow::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedValue lhs(cx, iter.read()); - RootedValue rhs(cx, iter.read()); - RootedValue result(cx); - - MOZ_ASSERT(lhs.isBigInt() && rhs.isBigInt()); - MOZ_ASSERT(!rhs.toBigInt()->isNegative(), + Rooted<BigInt*> lhs(cx, iter.readBigInt()); + Rooted<BigInt*> rhs(cx, iter.readBigInt()); + MOZ_ASSERT(!rhs->isNegative(), "negative exponent throws and therefore can't be recovered"); - if (!js::PowValues(cx, &lhs, &rhs, &result)) { + + BigInt* result = BigInt::pow(cx, lhs, rhs); + if (!result) { return false; } - iter.storeInstructionResult(result); + iter.storeInstructionResult(BigIntValue(result)); return true; } @@ -633,16 +629,15 @@ bool MBigIntBitAnd::writeRecoverData(CompactBufferWriter& writer) const { RBigIntBitAnd::RBigIntBitAnd(CompactBufferReader& reader) {} bool RBigIntBitAnd::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedValue lhs(cx, iter.read()); - RootedValue rhs(cx, iter.read()); - RootedValue result(cx); + Rooted<BigInt*> lhs(cx, iter.readBigInt()); + Rooted<BigInt*> rhs(cx, iter.readBigInt()); - MOZ_ASSERT(lhs.isBigInt() && rhs.isBigInt()); - if (!js::BitAnd(cx, &lhs, &rhs, &result)) { + BigInt* result = BigInt::bitAnd(cx, lhs, rhs); + if (!result) { return false; } - iter.storeInstructionResult(result); + iter.storeInstructionResult(BigIntValue(result)); return true; } @@ -655,16 +650,15 @@ bool MBigIntBitOr::writeRecoverData(CompactBufferWriter& writer) const { RBigIntBitOr::RBigIntBitOr(CompactBufferReader& reader) {} bool RBigIntBitOr::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedValue lhs(cx, iter.read()); - RootedValue rhs(cx, iter.read()); - RootedValue result(cx); + Rooted<BigInt*> lhs(cx, iter.readBigInt()); + Rooted<BigInt*> rhs(cx, iter.readBigInt()); - MOZ_ASSERT(lhs.isBigInt() && rhs.isBigInt()); - if (!js::BitOr(cx, &lhs, &rhs, &result)) { + BigInt* result = BigInt::bitOr(cx, lhs, rhs); + if (!result) { return false; } - iter.storeInstructionResult(result); + iter.storeInstructionResult(BigIntValue(result)); return true; } @@ -677,16 +671,15 @@ bool MBigIntBitXor::writeRecoverData(CompactBufferWriter& writer) const { RBigIntBitXor::RBigIntBitXor(CompactBufferReader& reader) {} bool RBigIntBitXor::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedValue lhs(cx, iter.read()); - RootedValue rhs(cx, iter.read()); - RootedValue result(cx); + Rooted<BigInt*> lhs(cx, iter.readBigInt()); + Rooted<BigInt*> rhs(cx, iter.readBigInt()); - MOZ_ASSERT(lhs.isBigInt() && rhs.isBigInt()); - if (!js::BitXor(cx, &lhs, &rhs, &result)) { + BigInt* result = BigInt::bitXor(cx, lhs, rhs); + if (!result) { return false; } - iter.storeInstructionResult(result); + iter.storeInstructionResult(BigIntValue(result)); return true; } @@ -699,16 +692,15 @@ bool MBigIntLsh::writeRecoverData(CompactBufferWriter& writer) const { RBigIntLsh::RBigIntLsh(CompactBufferReader& reader) {} bool RBigIntLsh::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedValue lhs(cx, iter.read()); - RootedValue rhs(cx, iter.read()); - RootedValue result(cx); + Rooted<BigInt*> lhs(cx, iter.readBigInt()); + Rooted<BigInt*> rhs(cx, iter.readBigInt()); - MOZ_ASSERT(lhs.isBigInt() && rhs.isBigInt()); - if (!js::BitLsh(cx, &lhs, &rhs, &result)) { + BigInt* result = BigInt::lsh(cx, lhs, rhs); + if (!result) { return false; } - iter.storeInstructionResult(result); + iter.storeInstructionResult(BigIntValue(result)); return true; } @@ -721,16 +713,15 @@ bool MBigIntRsh::writeRecoverData(CompactBufferWriter& writer) const { RBigIntRsh::RBigIntRsh(CompactBufferReader& reader) {} bool RBigIntRsh::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedValue lhs(cx, iter.read()); - RootedValue rhs(cx, iter.read()); - RootedValue result(cx); + Rooted<BigInt*> lhs(cx, iter.readBigInt()); + Rooted<BigInt*> rhs(cx, iter.readBigInt()); - MOZ_ASSERT(lhs.isBigInt() && rhs.isBigInt()); - if (!js::BitRsh(cx, &lhs, &rhs, &result)) { + BigInt* result = BigInt::rsh(cx, lhs, rhs); + if (!result) { return false; } - iter.storeInstructionResult(result); + iter.storeInstructionResult(BigIntValue(result)); return true; } @@ -743,15 +734,14 @@ bool MBigIntIncrement::writeRecoverData(CompactBufferWriter& writer) const { RBigIntIncrement::RBigIntIncrement(CompactBufferReader& reader) {} bool RBigIntIncrement::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedValue operand(cx, iter.read()); - RootedValue result(cx); + Rooted<BigInt*> operand(cx, iter.readBigInt()); - MOZ_ASSERT(operand.isBigInt()); - if (!js::IncOperation(cx, operand, &result)) { + BigInt* result = BigInt::inc(cx, operand); + if (!result) { return false; } - iter.storeInstructionResult(result); + iter.storeInstructionResult(BigIntValue(result)); return true; } @@ -764,15 +754,14 @@ bool MBigIntDecrement::writeRecoverData(CompactBufferWriter& writer) const { RBigIntDecrement::RBigIntDecrement(CompactBufferReader& reader) {} bool RBigIntDecrement::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedValue operand(cx, iter.read()); - RootedValue result(cx); + Rooted<BigInt*> operand(cx, iter.readBigInt()); - MOZ_ASSERT(operand.isBigInt()); - if (!js::DecOperation(cx, operand, &result)) { + BigInt* result = BigInt::dec(cx, operand); + if (!result) { return false; } - iter.storeInstructionResult(result); + iter.storeInstructionResult(BigIntValue(result)); return true; } @@ -785,15 +774,14 @@ bool MBigIntNegate::writeRecoverData(CompactBufferWriter& writer) const { RBigIntNegate::RBigIntNegate(CompactBufferReader& reader) {} bool RBigIntNegate::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedValue operand(cx, iter.read()); - RootedValue result(cx); + Rooted<BigInt*> operand(cx, iter.readBigInt()); - MOZ_ASSERT(operand.isBigInt()); - if (!js::NegOperation(cx, &operand, &result)) { + BigInt* result = BigInt::neg(cx, operand); + if (!result) { return false; } - iter.storeInstructionResult(result); + iter.storeInstructionResult(BigIntValue(result)); return true; } @@ -806,15 +794,14 @@ bool MBigIntBitNot::writeRecoverData(CompactBufferWriter& writer) const { RBigIntBitNot::RBigIntBitNot(CompactBufferReader& reader) {} bool RBigIntBitNot::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedValue operand(cx, iter.read()); - RootedValue result(cx); + Rooted<BigInt*> operand(cx, iter.readBigInt()); - MOZ_ASSERT(operand.isBigInt()); - if (!js::BitNot(cx, &operand, &result)) { + BigInt* result = BigInt::bitNot(cx, operand); + if (!result) { return false; } - iter.storeInstructionResult(result); + iter.storeInstructionResult(BigIntValue(result)); return true; } @@ -910,7 +897,7 @@ bool RConcat::recover(JSContext* cx, SnapshotIterator& iter) const { RStringLength::RStringLength(CompactBufferReader& reader) {} bool RStringLength::recover(JSContext* cx, SnapshotIterator& iter) const { - JSString* string = iter.read().toString(); + JSString* string = iter.readString(); static_assert(JSString::MAX_LENGTH <= INT32_MAX, "Can cast string length to int32_t"); @@ -953,7 +940,7 @@ bool MFloor::writeRecoverData(CompactBufferWriter& writer) const { RFloor::RFloor(CompactBufferReader& reader) {} bool RFloor::recover(JSContext* cx, SnapshotIterator& iter) const { - double num = iter.read().toNumber(); + double num = iter.readNumber(); double result = js::math_floor_impl(num); iter.storeInstructionResult(NumberValue(result)); @@ -969,7 +956,7 @@ bool MCeil::writeRecoverData(CompactBufferWriter& writer) const { RCeil::RCeil(CompactBufferReader& reader) {} bool RCeil::recover(JSContext* cx, SnapshotIterator& iter) const { - double num = iter.read().toNumber(); + double num = iter.readNumber(); double result = js::math_ceil_impl(num); iter.storeInstructionResult(NumberValue(result)); @@ -985,7 +972,7 @@ bool MRound::writeRecoverData(CompactBufferWriter& writer) const { RRound::RRound(CompactBufferReader& reader) {} bool RRound::recover(JSContext* cx, SnapshotIterator& iter) const { - double num = iter.read().toNumber(); + double num = iter.readNumber(); double result = js::math_round_impl(num); iter.storeInstructionResult(NumberValue(result)); @@ -1001,7 +988,7 @@ bool MTrunc::writeRecoverData(CompactBufferWriter& writer) const { RTrunc::RTrunc(CompactBufferReader& reader) {} bool RTrunc::recover(JSContext* cx, SnapshotIterator& iter) const { - double num = iter.read().toNumber(); + double num = iter.readNumber(); double result = js::math_trunc_impl(num); iter.storeInstructionResult(NumberValue(result)); @@ -1017,21 +1004,18 @@ bool MCharCodeAt::writeRecoverData(CompactBufferWriter& writer) const { RCharCodeAt::RCharCodeAt(CompactBufferReader& reader) {} bool RCharCodeAt::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedString string(cx, iter.read().toString()); - int32_t index = iter.read().toInt32(); + JSString* string = iter.readString(); - RootedValue result(cx); - if (0 <= index && size_t(index) < string->length()) { - char16_t c; - if (!string->getChar(cx, index, &c)) { - return false; - } - result.setInt32(c); - } else { - result.setNaN(); + // Int32 because |index| is computed from MBoundsCheck. + int32_t index = iter.readInt32(); + MOZ_RELEASE_ASSERT(0 <= index && size_t(index) < string->length()); + + char16_t c; + if (!string->getChar(cx, index, &c)) { + return false; } - iter.storeInstructionResult(result); + iter.storeInstructionResult(Int32Value(c)); return true; } @@ -1044,7 +1028,8 @@ bool MFromCharCode::writeRecoverData(CompactBufferWriter& writer) const { RFromCharCode::RFromCharCode(CompactBufferReader& reader) {} bool RFromCharCode::recover(JSContext* cx, SnapshotIterator& iter) const { - int32_t charCode = iter.read().toInt32(); + // Number because |charCode| is computed from (recoverable) user input. + int32_t charCode = JS::ToInt32(iter.readNumber()); JSString* str = StringFromCharCode(cx, charCode); if (!str) { @@ -1068,7 +1053,8 @@ RFromCharCodeEmptyIfNegative::RFromCharCodeEmptyIfNegative( bool RFromCharCodeEmptyIfNegative::recover(JSContext* cx, SnapshotIterator& iter) const { - int32_t charCode = iter.read().toInt32(); + // Int32 because |charCode| is computed from MCharCodeAtOrNegative. + int32_t charCode = iter.readInt32(); JSString* str; if (charCode < 0) { @@ -1093,8 +1079,8 @@ bool MPow::writeRecoverData(CompactBufferWriter& writer) const { RPow::RPow(CompactBufferReader& reader) {} bool RPow::recover(JSContext* cx, SnapshotIterator& iter) const { - double base = iter.read().toNumber(); - double power = iter.read().toNumber(); + double base = iter.readNumber(); + double power = iter.readNumber(); double result = ecmaPow(base, power); iter.storeInstructionResult(NumberValue(result)); @@ -1110,7 +1096,7 @@ bool MPowHalf::writeRecoverData(CompactBufferWriter& writer) const { RPowHalf::RPowHalf(CompactBufferReader& reader) {} bool RPowHalf::recover(JSContext* cx, SnapshotIterator& iter) const { - double base = iter.read().toNumber(); + double base = iter.readNumber(); double power = 0.5; double result = ecmaPow(base, power); @@ -1128,8 +1114,8 @@ bool MMinMax::writeRecoverData(CompactBufferWriter& writer) const { RMinMax::RMinMax(CompactBufferReader& reader) { isMax_ = reader.readByte(); } bool RMinMax::recover(JSContext* cx, SnapshotIterator& iter) const { - double x = iter.read().toNumber(); - double y = iter.read().toNumber(); + double x = iter.readNumber(); + double y = iter.readNumber(); double result; if (isMax_) { @@ -1151,7 +1137,7 @@ bool MAbs::writeRecoverData(CompactBufferWriter& writer) const { RAbs::RAbs(CompactBufferReader& reader) {} bool RAbs::recover(JSContext* cx, SnapshotIterator& iter) const { - double num = iter.read().toNumber(); + double num = iter.readNumber(); double result = js::math_abs_impl(num); iter.storeInstructionResult(NumberValue(result)); @@ -1170,7 +1156,7 @@ RSqrt::RSqrt(CompactBufferReader& reader) { } bool RSqrt::recover(JSContext* cx, SnapshotIterator& iter) const { - double num = iter.read().toNumber(); + double num = iter.readNumber(); double result = js::math_sqrt_impl(num); // MIRType::Float32 is a specialization embedding the fact that the result is @@ -1192,8 +1178,8 @@ bool MAtan2::writeRecoverData(CompactBufferWriter& writer) const { RAtan2::RAtan2(CompactBufferReader& reader) {} bool RAtan2::recover(JSContext* cx, SnapshotIterator& iter) const { - double y = iter.read().toNumber(); - double x = iter.read().toNumber(); + double y = iter.readNumber(); + double x = iter.readNumber(); double result = js::ecmaAtan2(y, x); iter.storeInstructionResult(DoubleValue(result)); @@ -1218,7 +1204,7 @@ bool RHypot::recover(JSContext* cx, SnapshotIterator& iter) const { } for (uint32_t i = 0; i < numOperands_; ++i) { - vec.infallibleAppend(iter.read()); + vec.infallibleAppend(NumberValue(iter.readNumber())); } RootedValue result(cx); @@ -1265,7 +1251,7 @@ bool MSign::writeRecoverData(CompactBufferWriter& writer) const { RSign::RSign(CompactBufferReader& reader) {} bool RSign::recover(JSContext* cx, SnapshotIterator& iter) const { - double num = iter.read().toNumber(); + double num = iter.readNumber(); double result = js::math_sign_impl(num); iter.storeInstructionResult(NumberValue(result)); @@ -1322,7 +1308,7 @@ RMathFunction::RMathFunction(CompactBufferReader& reader) { } bool RMathFunction::recover(JSContext* cx, SnapshotIterator& iter) const { - double num = iter.read().toNumber(); + double num = iter.readNumber(); double result; switch (function_) { @@ -1431,8 +1417,8 @@ bool MStringSplit::writeRecoverData(CompactBufferWriter& writer) const { RStringSplit::RStringSplit(CompactBufferReader& reader) {} bool RStringSplit::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedString str(cx, iter.read().toString()); - RootedString sep(cx, iter.read().toString()); + RootedString str(cx, iter.readString()); + RootedString sep(cx, iter.readString()); JSObject* res = StringSplitString(cx, str, sep, INT32_MAX); if (!res) { @@ -1452,7 +1438,7 @@ bool MNaNToZero::writeRecoverData(CompactBufferWriter& writer) const { RNaNToZero::RNaNToZero(CompactBufferReader& reader) {} bool RNaNToZero::recover(JSContext* cx, SnapshotIterator& iter) const { - double v = iter.read().toNumber(); + double v = iter.readNumber(); if (std::isnan(v) || mozilla::IsNegativeZero(v)) { v = 0.0; } @@ -1470,9 +1456,11 @@ bool MRegExpMatcher::writeRecoverData(CompactBufferWriter& writer) const { RRegExpMatcher::RRegExpMatcher(CompactBufferReader& reader) {} bool RRegExpMatcher::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedObject regexp(cx, &iter.read().toObject()); - RootedString input(cx, iter.read().toString()); - int32_t lastIndex = iter.read().toInt32(); + RootedObject regexp(cx, iter.readObject()); + RootedString input(cx, iter.readString()); + + // Int32 because |lastIndex| is computed from transpiled self-hosted call. + int32_t lastIndex = iter.readInt32(); RootedValue result(cx); if (!RegExpMatcherRaw(cx, regexp, input, lastIndex, nullptr, &result)) { @@ -1507,7 +1495,8 @@ bool MTypeOfName::writeRecoverData(CompactBufferWriter& writer) const { RTypeOfName::RTypeOfName(CompactBufferReader& reader) {} bool RTypeOfName::recover(JSContext* cx, SnapshotIterator& iter) const { - int32_t type = iter.read().toInt32(); + // Int32 because |type| is computed from MTypeOf. + int32_t type = iter.readInt32(); MOZ_ASSERT(JSTYPE_UNDEFINED <= type && type < JSTYPE_LIMIT); JSString* name = TypeName(JSType(type), *cx->runtime()->commonNames); @@ -1548,7 +1537,7 @@ bool MToFloat32::writeRecoverData(CompactBufferWriter& writer) const { RToFloat32::RToFloat32(CompactBufferReader& reader) {} bool RToFloat32::recover(JSContext* cx, SnapshotIterator& iter) const { - double num = iter.read().toNumber(); + double num = iter.readNumber(); double result = js::RoundFloat32(num); iter.storeInstructionResult(DoubleValue(result)); @@ -1588,7 +1577,7 @@ bool MNewObject::writeRecoverData(CompactBufferWriter& writer) const { RNewObject::RNewObject(CompactBufferReader& reader) {} bool RNewObject::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedObject templateObject(cx, &iter.read().toObject()); + RootedObject templateObject(cx, iter.readObject()); // See CodeGenerator::visitNewObjectVMCall. // Note that recover instructions are only used if mode == ObjectCreate. @@ -1622,8 +1611,7 @@ RNewPlainObject::RNewPlainObject(CompactBufferReader& reader) { } bool RNewPlainObject::recover(JSContext* cx, SnapshotIterator& iter) const { - Rooted<SharedShape*> shape(cx, - &iter.read().toGCCellPtr().as<Shape>().asShared()); + Rooted<SharedShape*> shape(cx, &iter.readGCCellPtr().as<Shape>().asShared()); // See CodeGenerator::visitNewPlainObject. JSObject* resultObject = @@ -1676,7 +1664,7 @@ bool MNewTypedArray::writeRecoverData(CompactBufferWriter& writer) const { RNewTypedArray::RNewTypedArray(CompactBufferReader& reader) {} bool RNewTypedArray::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedObject templateObject(cx, &iter.read().toObject()); + RootedObject templateObject(cx, iter.readObject()); size_t length = templateObject.as<FixedLengthTypedArrayObject>()->length(); MOZ_ASSERT(length <= INT32_MAX, @@ -1704,7 +1692,7 @@ RNewArray::RNewArray(CompactBufferReader& reader) { } bool RNewArray::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedObject templateObject(cx, &iter.read().toObject()); + RootedObject templateObject(cx, iter.readObject()); Rooted<Shape*> shape(cx, templateObject->shape()); ArrayObject* resultObject = NewArrayWithShape(cx, count_, shape); @@ -1728,7 +1716,7 @@ RNewIterator::RNewIterator(CompactBufferReader& reader) { } bool RNewIterator::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedObject templateObject(cx, &iter.read().toObject()); + RootedObject templateObject(cx, iter.readObject()); JSObject* resultObject = nullptr; switch (MNewIterator::Type(type_)) { @@ -1760,8 +1748,8 @@ bool MLambda::writeRecoverData(CompactBufferWriter& writer) const { RLambda::RLambda(CompactBufferReader& reader) {} bool RLambda::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedObject scopeChain(cx, &iter.read().toObject()); - RootedFunction fun(cx, &iter.read().toObject().as<JSFunction>()); + RootedObject scopeChain(cx, iter.readObject()); + RootedFunction fun(cx, &iter.readObject()->as<JSFunction>()); JSObject* resultObject = js::Lambda(cx, fun, scopeChain); if (!resultObject) { @@ -1781,9 +1769,9 @@ bool MFunctionWithProto::writeRecoverData(CompactBufferWriter& writer) const { RFunctionWithProto::RFunctionWithProto(CompactBufferReader& reader) {} bool RFunctionWithProto::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedObject scopeChain(cx, &iter.read().toObject()); - RootedObject prototype(cx, &iter.read().toObject()); - RootedFunction fun(cx, &iter.read().toObject().as<JSFunction>()); + RootedObject scopeChain(cx, iter.readObject()); + RootedObject prototype(cx, iter.readObject()); + RootedFunction fun(cx, &iter.readObject()->as<JSFunction>()); JSObject* resultObject = js::FunWithProtoOperation(cx, fun, scopeChain, prototype); @@ -1804,7 +1792,7 @@ bool MNewCallObject::writeRecoverData(CompactBufferWriter& writer) const { RNewCallObject::RNewCallObject(CompactBufferReader& reader) {} bool RNewCallObject::recover(JSContext* cx, SnapshotIterator& iter) const { - Rooted<CallObject*> templateObj(cx, &iter.read().toObject().as<CallObject>()); + Rooted<CallObject*> templateObj(cx, &iter.readObject()->as<CallObject>()); Rooted<SharedShape*> shape(cx, templateObj->sharedShape()); @@ -1832,7 +1820,7 @@ bool MObjectKeys::writeRecoverData(CompactBufferWriter& writer) const { RObjectKeys::RObjectKeys(CompactBufferReader& reader) {} bool RObjectKeys::recover(JSContext* cx, SnapshotIterator& iter) const { - Rooted<JSObject*> obj(cx, &iter.read().toObject()); + Rooted<JSObject*> obj(cx, iter.readObject()); JSObject* resultKeys = ObjectKeys(cx, obj); if (!resultKeys) { @@ -1855,7 +1843,7 @@ RObjectState::RObjectState(CompactBufferReader& reader) { } bool RObjectState::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedObject object(cx, &iter.read().toObject()); + RootedObject object(cx, iter.readObject()); Handle<NativeObject*> nativeObject = object.as<NativeObject>(); MOZ_ASSERT(!Watchtower::watchesPropertyModification(nativeObject)); MOZ_ASSERT(nativeObject->slotSpan() == numSlots()); @@ -1881,8 +1869,10 @@ RArrayState::RArrayState(CompactBufferReader& reader) { } bool RArrayState::recover(JSContext* cx, SnapshotIterator& iter) const { - ArrayObject* object = &iter.read().toObject().as<ArrayObject>(); - uint32_t initLength = iter.read().toInt32(); + ArrayObject* object = &iter.readObject()->as<ArrayObject>(); + + // Int32 because |initLength| is computed from MConstant. + uint32_t initLength = iter.readInt32(); MOZ_ASSERT(object->getDenseInitializedLength() == 0, "initDenseElement call below relies on this"); @@ -1903,37 +1893,6 @@ bool RArrayState::recover(JSContext* cx, SnapshotIterator& iter) const { return true; } -bool MSetArrayLength::writeRecoverData(CompactBufferWriter& writer) const { - MOZ_ASSERT(canRecoverOnBailout()); - // For simplicity, we capture directly the object instead of the elements - // pointer. - MOZ_ASSERT(elements()->type() != MIRType::Elements); - writer.writeUnsigned(uint32_t(RInstruction::Recover_SetArrayLength)); - return true; -} - -bool MSetArrayLength::canRecoverOnBailout() const { - return isRecoveredOnBailout(); -} - -RSetArrayLength::RSetArrayLength(CompactBufferReader& reader) {} - -bool RSetArrayLength::recover(JSContext* cx, SnapshotIterator& iter) const { - Rooted<ArrayObject*> obj(cx, &iter.read().toObject().as<ArrayObject>()); - RootedValue len(cx, iter.read()); - - RootedId id(cx, NameToId(cx->names().length)); - Rooted<PropertyDescriptor> desc( - cx, PropertyDescriptor::Data(len, JS::PropertyAttribute::Writable)); - ObjectOpResult error; - if (!ArraySetLength(cx, obj, id, desc, error)) { - return false; - } - - iter.storeInstructionResult(ObjectValue(*obj)); - return true; -} - bool MAssertRecoveredOnBailout::writeRecoverData( CompactBufferWriter& writer) const { MOZ_ASSERT(canRecoverOnBailout()); @@ -1966,9 +1925,9 @@ RStringReplace::RStringReplace(CompactBufferReader& reader) { } bool RStringReplace::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedString string(cx, iter.read().toString()); - RootedString pattern(cx, iter.read().toString()); - RootedString replace(cx, iter.read().toString()); + RootedString string(cx, iter.readString()); + RootedString pattern(cx, iter.readString()); + RootedString replace(cx, iter.readString()); JSString* result = isFlatReplacement_ @@ -1992,9 +1951,20 @@ bool MSubstr::writeRecoverData(CompactBufferWriter& writer) const { RSubstr::RSubstr(CompactBufferReader& reader) {} bool RSubstr::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedString str(cx, iter.read().toString()); - int32_t begin = iter.read().toInt32(); - int32_t length = iter.read().toInt32(); + RootedString str(cx, iter.readString()); + + // Int32 because |begin| is computed from MStringTrimStartIndex, MConstant, + // or CallSubstringKernelResult. + int32_t begin = iter.readInt32(); + + // |length| is computed from MSub(truncated), MStringTrimEndIndex, or + // CallSubstringKernelResult. The current MSub inputs won't overflow, so when + // RSub recovers the MSub instruction, the input will be representable as an + // Int32. This is only true as long as RSub calls |js::SubOperation|, which in + // turn calls |JS::Value::setNumber|. We don't want to rely on this exact call + // sequence, so instead use |readNumber| here and then release-assert the + // number is exactly representable as an Int32. + int32_t length = mozilla::ReleaseAssertedCast<int32_t>(iter.readNumber()); JSString* result = SubstringKernel(cx, str, begin, length); if (!result) { @@ -2014,10 +1984,11 @@ bool MAtomicIsLockFree::writeRecoverData(CompactBufferWriter& writer) const { RAtomicIsLockFree::RAtomicIsLockFree(CompactBufferReader& reader) {} bool RAtomicIsLockFree::recover(JSContext* cx, SnapshotIterator& iter) const { - Value operand = iter.read(); - MOZ_ASSERT(operand.isInt32()); + double dsize = JS::ToInteger(iter.readNumber()); - bool result = AtomicOperations::isLockfreeJS(operand.toInt32()); + int32_t size; + bool result = mozilla::NumberEqualsInt32(dsize, &size) && + AtomicOperations::isLockfreeJS(size); iter.storeInstructionResult(BooleanValue(result)); return true; } @@ -2031,10 +2002,12 @@ bool MBigIntAsIntN::writeRecoverData(CompactBufferWriter& writer) const { RBigIntAsIntN::RBigIntAsIntN(CompactBufferReader& reader) {} bool RBigIntAsIntN::recover(JSContext* cx, SnapshotIterator& iter) const { - int32_t bits = iter.read().toInt32(); - RootedBigInt input(cx, iter.read().toBigInt()); - + // Int32 because |bits| is computed from MGuardInt32IsNonNegative. + int32_t bits = iter.readInt32(); MOZ_ASSERT(bits >= 0); + + RootedBigInt input(cx, iter.readBigInt()); + BigInt* result = BigInt::asIntN(cx, input, bits); if (!result) { return false; @@ -2053,10 +2026,12 @@ bool MBigIntAsUintN::writeRecoverData(CompactBufferWriter& writer) const { RBigIntAsUintN::RBigIntAsUintN(CompactBufferReader& reader) {} bool RBigIntAsUintN::recover(JSContext* cx, SnapshotIterator& iter) const { - int32_t bits = iter.read().toInt32(); - RootedBigInt input(cx, iter.read().toBigInt()); - + // Int32 because |bits| is computed from MGuardInt32IsNonNegative. + int32_t bits = iter.readInt32(); MOZ_ASSERT(bits >= 0); + + RootedBigInt input(cx, iter.readBigInt()); + BigInt* result = BigInt::asUintN(cx, input, bits); if (!result) { return false; @@ -2077,7 +2052,7 @@ RCreateArgumentsObject::RCreateArgumentsObject(CompactBufferReader& reader) {} bool RCreateArgumentsObject::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedObject callObject(cx, &iter.read().toObject()); + RootedObject callObject(cx, iter.readObject()); RootedObject result( cx, ArgumentsObject::createForIon(cx, iter.frame(), callObject)); if (!result) { @@ -2104,8 +2079,8 @@ RCreateInlinedArgumentsObject::RCreateInlinedArgumentsObject( bool RCreateInlinedArgumentsObject::recover(JSContext* cx, SnapshotIterator& iter) const { - RootedObject callObject(cx, &iter.read().toObject()); - RootedFunction callee(cx, &iter.read().toObject().as<JSFunction>()); + RootedObject callObject(cx, iter.readObject()); + RootedFunction callee(cx, &iter.readObject()->as<JSFunction>()); JS::RootedValueArray<ArgumentsObject::MaxInlinedArgs> argsArray(cx); for (uint32_t i = 0; i < numActuals_; i++) { @@ -2136,7 +2111,8 @@ RRest::RRest(CompactBufferReader& reader) { bool RRest::recover(JSContext* cx, SnapshotIterator& iter) const { JitFrameLayout* frame = iter.frame(); - uint32_t numActuals = iter.read().toInt32(); + // Int32 because |numActuals| is computed from MArgumentsLength. + uint32_t numActuals = iter.readInt32(); MOZ_ASSERT(numActuals == frame->numActualArgs()); uint32_t numFormals = numFormals_; |