diff options
Diffstat (limited to 'js/src/jit/Recover.h')
-rw-r--r-- | js/src/jit/Recover.h | 893 |
1 files changed, 893 insertions, 0 deletions
diff --git a/js/src/jit/Recover.h b/js/src/jit/Recover.h new file mode 100644 index 0000000000..78352c8248 --- /dev/null +++ b/js/src/jit/Recover.h @@ -0,0 +1,893 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef jit_Recover_h +#define jit_Recover_h + +#include "mozilla/Attributes.h" + +#include "builtin/Array.h" + +#include "jit/MIR.h" +#include "jit/Snapshots.h" + +namespace js { +namespace jit { + +// [SMDOC] IonMonkey Recover Instructions +// +// This file contains all recover instructions. +// +// A recover instruction is an equivalent of a MIR instruction which is executed +// before the reconstruction of a baseline frame. Recover instructions are used +// by resume points to fill the value which are not produced by the code +// compiled by IonMonkey. For example, if a value is optimized away by +// IonMonkey, but required by Baseline, then we should have a recover +// instruction to fill the missing baseline frame slot. +// +// Recover instructions are executed either during a bailout, or under a call +// when the stack frame is introspected. If the stack is introspected, then any +// use of recover instruction must lead to an invalidation of the code. +// +// For each MIR instruction where |canRecoverOnBailout| might return true, we +// have a RInstruction of the same name. +// +// Recover instructions are encoded by the code generator into a compact buffer +// (RecoverWriter). The MIR instruction method |writeRecoverData| should write a +// tag in the |CompactBufferWriter| which is used by +// |RInstruction::readRecoverData| to dispatch to the right Recover +// instruction. Then |writeRecoverData| writes any local fields which are +// necessary for the execution of the |recover| method. These fields are decoded +// by the Recover instruction constructor which has a |CompactBufferReader| as +// argument. The constructor of the Recover instruction should follow the same +// sequence as the |writeRecoverData| method of the MIR instruction. +// +// Recover instructions are decoded by the |SnapshotIterator| (RecoverReader), +// which is given as argument of the |recover| methods, in order to read the +// operands. The number of operands read should be the same as the result of +// |numOperands|, which corresponds to the number of operands of the MIR +// instruction. Operands should be decoded in the same order as the operands of +// the MIR instruction. +// +// The result of the |recover| method should either be a failure, or a value +// stored on the |SnapshotIterator|, by using the |storeInstructionResult| +// method. + +#define RECOVER_OPCODE_LIST(_) \ + _(ResumePoint) \ + _(BitNot) \ + _(BitAnd) \ + _(BitOr) \ + _(BitXor) \ + _(Lsh) \ + _(Rsh) \ + _(Ursh) \ + _(SignExtendInt32) \ + _(Add) \ + _(Sub) \ + _(Mul) \ + _(Div) \ + _(Mod) \ + _(Not) \ + _(BigIntAdd) \ + _(BigIntSub) \ + _(BigIntMul) \ + _(BigIntDiv) \ + _(BigIntMod) \ + _(BigIntPow) \ + _(BigIntBitAnd) \ + _(BigIntBitOr) \ + _(BigIntBitXor) \ + _(BigIntLsh) \ + _(BigIntRsh) \ + _(BigIntIncrement) \ + _(BigIntDecrement) \ + _(BigIntNegate) \ + _(BigIntBitNot) \ + _(Concat) \ + _(StringLength) \ + _(ArgumentsLength) \ + _(Floor) \ + _(Ceil) \ + _(Round) \ + _(Trunc) \ + _(CharCodeAt) \ + _(FromCharCode) \ + _(Pow) \ + _(PowHalf) \ + _(MinMax) \ + _(Abs) \ + _(Sqrt) \ + _(Atan2) \ + _(Hypot) \ + _(NearbyInt) \ + _(Sign) \ + _(MathFunction) \ + _(Random) \ + _(StringSplit) \ + _(NaNToZero) \ + _(RegExpMatcher) \ + _(RegExpSearcher) \ + _(RegExpTester) \ + _(StringReplace) \ + _(TypeOf) \ + _(ToDouble) \ + _(ToFloat32) \ + _(TruncateToInt32) \ + _(NewObject) \ + _(NewTypedArray) \ + _(NewArray) \ + _(NewIterator) \ + _(NewCallObject) \ + _(CreateThisWithTemplate) \ + _(Lambda) \ + _(LambdaArrow) \ + _(FunctionWithProto) \ + _(ObjectState) \ + _(ArrayState) \ + _(SetArrayLength) \ + _(AtomicIsLockFree) \ + _(BigIntAsIntN) \ + _(BigIntAsUintN) \ + _(AssertRecoveredOnBailout) + +class RResumePoint; +class SnapshotIterator; + +class MOZ_NON_PARAM RInstruction { + public: + enum Opcode { +#define DEFINE_OPCODES_(op) Recover_##op, + RECOVER_OPCODE_LIST(DEFINE_OPCODES_) +#undef DEFINE_OPCODES_ + Recover_Invalid + }; + + virtual Opcode opcode() const = 0; + + // As opposed to the MIR, there is no need to add more methods as every + // other instruction is well abstracted under the "recover" method. + bool isResumePoint() const { return opcode() == Recover_ResumePoint; } + inline const RResumePoint* toResumePoint() const; + + // Call the copy constructor of a specific RInstruction, to do a copy of the + // RInstruction content. + virtual void cloneInto(RInstructionStorage* raw) const = 0; + + // Number of allocations which are encoded in the Snapshot for recovering + // the current instruction. + virtual uint32_t numOperands() const = 0; + + // Function used to recover the value computed by this instruction. This + // function reads its arguments from the allocations listed on the snapshot + // iterator and stores its returned value on the snapshot iterator too. + [[nodiscard]] virtual bool recover(JSContext* cx, + SnapshotIterator& iter) const = 0; + + // Decode an RInstruction on top of the reserved storage space, based on the + // tag written by the writeRecoverData function of the corresponding MIR + // instruction. + static void readRecoverData(CompactBufferReader& reader, + RInstructionStorage* raw); +}; + +#define RINSTRUCTION_HEADER_(op) \ + private: \ + friend class RInstruction; \ + explicit R##op(CompactBufferReader& reader); \ + explicit R##op(const R##op& src) = default; \ + \ + public: \ + Opcode opcode() const override { return RInstruction::Recover_##op; } \ + void cloneInto(RInstructionStorage* raw) const override { \ + new (raw->addr()) R##op(*this); \ + } + +#define RINSTRUCTION_HEADER_NUM_OP_MAIN(op, numOp) \ + RINSTRUCTION_HEADER_(op) \ + uint32_t numOperands() const override { return numOp; } + +#ifdef DEBUG +# define RINSTRUCTION_HEADER_NUM_OP_(op, numOp) \ + RINSTRUCTION_HEADER_NUM_OP_MAIN(op, numOp) \ + static_assert( \ + M##op::staticNumOperands == numOp, \ + "The recover instructions's numOperands should equal to the " \ + "MIR's numOperands"); +#else +# define RINSTRUCTION_HEADER_NUM_OP_(op, numOp) \ + RINSTRUCTION_HEADER_NUM_OP_MAIN(op, numOp) +#endif + +class RResumePoint final : public RInstruction { + private: + uint32_t pcOffset_; // Offset from script->code. + uint32_t numOperands_; // Number of slots. + + public: + RINSTRUCTION_HEADER_(ResumePoint) + + uint32_t pcOffset() const { return pcOffset_; } + uint32_t numOperands() const override { return numOperands_; } + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBitNot final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BitNot, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBitAnd final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BitAnd, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBitOr final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BitOr, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBitXor final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BitXor, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RLsh final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(Lsh, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RRsh final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(Rsh, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RUrsh final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(Ursh, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RSignExtendInt32 final : public RInstruction { + private: + uint8_t mode_; + + public: + RINSTRUCTION_HEADER_NUM_OP_(SignExtendInt32, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RAdd final : public RInstruction { + private: + bool isFloatOperation_; + + public: + RINSTRUCTION_HEADER_NUM_OP_(Add, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RSub final : public RInstruction { + private: + bool isFloatOperation_; + + public: + RINSTRUCTION_HEADER_NUM_OP_(Sub, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RMul final : public RInstruction { + private: + bool isFloatOperation_; + uint8_t mode_; + + public: + RINSTRUCTION_HEADER_NUM_OP_(Mul, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RDiv final : public RInstruction { + private: + bool isFloatOperation_; + + public: + RINSTRUCTION_HEADER_NUM_OP_(Div, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RMod final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(Mod, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RNot final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(Not, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBigIntAdd final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BigIntAdd, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBigIntSub final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BigIntSub, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBigIntMul final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BigIntMul, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBigIntDiv final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BigIntDiv, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBigIntMod final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BigIntMod, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBigIntPow final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BigIntPow, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBigIntBitAnd final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BigIntBitAnd, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBigIntBitOr final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BigIntBitOr, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBigIntBitXor final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BigIntBitXor, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBigIntLsh final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BigIntLsh, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBigIntRsh final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BigIntRsh, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBigIntIncrement final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BigIntIncrement, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBigIntDecrement final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BigIntDecrement, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBigIntNegate final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BigIntNegate, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBigIntBitNot final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BigIntBitNot, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RConcat final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(Concat, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RStringLength final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(StringLength, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RArgumentsLength final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(ArgumentsLength, 0) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RFloor final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(Floor, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RCeil final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(Ceil, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RRound final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(Round, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RTrunc final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(Trunc, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RCharCodeAt final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(CharCodeAt, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RFromCharCode final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(FromCharCode, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RPow final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(Pow, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RPowHalf final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(PowHalf, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RMinMax final : public RInstruction { + private: + bool isMax_; + + public: + RINSTRUCTION_HEADER_NUM_OP_(MinMax, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RAbs final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(Abs, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RSqrt final : public RInstruction { + private: + bool isFloatOperation_; + + public: + RINSTRUCTION_HEADER_NUM_OP_(Sqrt, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RAtan2 final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(Atan2, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RHypot final : public RInstruction { + private: + uint32_t numOperands_; + + public: + RINSTRUCTION_HEADER_(Hypot) + + uint32_t numOperands() const override { return numOperands_; } + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RNearbyInt final : public RInstruction { + private: + uint8_t roundingMode_; + + public: + RINSTRUCTION_HEADER_NUM_OP_(NearbyInt, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RSign final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(Sign, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RMathFunction final : public RInstruction { + private: + UnaryMathFunction function_; + + public: + RINSTRUCTION_HEADER_NUM_OP_(MathFunction, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RRandom final : public RInstruction { + RINSTRUCTION_HEADER_NUM_OP_(Random, 0) + public: + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RStringSplit final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(StringSplit, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RNaNToZero final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(NaNToZero, 1); + + bool recover(JSContext* cx, SnapshotIterator& iter) const override; +}; + +class RRegExpMatcher final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(RegExpMatcher, 3) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RRegExpSearcher final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(RegExpSearcher, 3) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RRegExpTester final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(RegExpTester, 3) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RStringReplace final : public RInstruction { + private: + bool isFlatReplacement_; + + public: + RINSTRUCTION_HEADER_NUM_OP_(StringReplace, 3) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RTypeOf final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(TypeOf, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RToDouble final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(ToDouble, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RToFloat32 final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(ToFloat32, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RTruncateToInt32 final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(TruncateToInt32, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RNewObject final : public RInstruction { + private: + MNewObject::Mode mode_; + + public: + RINSTRUCTION_HEADER_NUM_OP_(NewObject, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RNewTypedArray final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(NewTypedArray, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RNewArray final : public RInstruction { + private: + uint32_t count_; + + public: + RINSTRUCTION_HEADER_NUM_OP_(NewArray, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RNewIterator final : public RInstruction { + private: + uint8_t type_; + + public: + RINSTRUCTION_HEADER_NUM_OP_(NewIterator, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RCreateThisWithTemplate final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(CreateThisWithTemplate, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RLambda final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(Lambda, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RLambdaArrow final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(LambdaArrow, 3) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RFunctionWithProto final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(FunctionWithProto, 3) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RNewCallObject final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(NewCallObject, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RObjectState final : public RInstruction { + private: + uint32_t numSlots_; // Number of slots. + + public: + RINSTRUCTION_HEADER_(ObjectState) + + uint32_t numSlots() const { return numSlots_; } + uint32_t numOperands() const override { + // +1 for the object. + return numSlots() + 1; + } + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RArrayState final : public RInstruction { + private: + uint32_t numElements_; + + public: + RINSTRUCTION_HEADER_(ArrayState) + + uint32_t numElements() const { return numElements_; } + uint32_t numOperands() const override { + // +1 for the array. + // +1 for the initalized length. + return numElements() + 2; + } + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RSetArrayLength final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(SetArrayLength, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RAtomicIsLockFree final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(AtomicIsLockFree, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBigIntAsIntN final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BigIntAsIntN, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RBigIntAsUintN final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(BigIntAsUintN, 2) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +class RAssertRecoveredOnBailout final : public RInstruction { + public: + RINSTRUCTION_HEADER_NUM_OP_(AssertRecoveredOnBailout, 1) + + [[nodiscard]] bool recover(JSContext* cx, + SnapshotIterator& iter) const override; +}; + +#undef RINSTRUCTION_HEADER_ +#undef RINSTRUCTION_HEADER_NUM_OP_ +#undef RINSTRUCTION_HEADER_NUM_OP_MAIN + +const RResumePoint* RInstruction::toResumePoint() const { + MOZ_ASSERT(isResumePoint()); + return static_cast<const RResumePoint*>(this); +} + +} // namespace jit +} // namespace js + +#endif /* jit_Recover_h */ |