summaryrefslogtreecommitdiffstats
path: root/js/src/jit/Recover.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit/Recover.h')
-rw-r--r--js/src/jit/Recover.h973
1 files changed, 973 insertions, 0 deletions
diff --git a/js/src/jit/Recover.h b/js/src/jit/Recover.h
new file mode 100644
index 0000000000..352b41cea3
--- /dev/null
+++ b/js/src/jit/Recover.h
@@ -0,0 +1,973 @@
+/* -*- 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 "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) \
+ _(Compare) \
+ _(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) \
+ _(Substr) \
+ _(TypeOf) \
+ _(TypeOfName) \
+ _(ToDouble) \
+ _(ToFloat32) \
+ _(TruncateToInt32) \
+ _(NewObject) \
+ _(NewPlainObject) \
+ _(NewArrayObject) \
+ _(NewTypedArray) \
+ _(NewArray) \
+ _(NewIterator) \
+ _(NewCallObject) \
+ _(Lambda) \
+ _(FunctionWithProto) \
+ _(ObjectState) \
+ _(ArrayState) \
+ _(SetArrayLength) \
+ _(AtomicIsLockFree) \
+ _(BigIntAsIntN) \
+ _(BigIntAsUintN) \
+ _(CreateArgumentsObject) \
+ _(CreateInlinedArgumentsObject) \
+ _(Rest) \
+ _(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 pcOffsetAndMode_; // Offset from script->code and ResumeMode.
+ uint32_t numOperands_; // Number of slots.
+
+ public:
+ RINSTRUCTION_HEADER_(ResumePoint)
+
+ // Used to encode/decode pcOffsetAndMode_.
+ static constexpr uint32_t PCOffsetShift = 4;
+ static constexpr uint32_t ResumeModeMask = 0b1111;
+ static_assert(uint32_t(ResumeMode::Last) <= ResumeModeMask);
+
+ uint32_t pcOffset() const { return pcOffsetAndMode_ >> PCOffsetShift; }
+ ResumeMode mode() const {
+ return ResumeMode(pcOffsetAndMode_ & ResumeModeMask);
+ }
+
+ 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 RCompare final : public RInstruction {
+ JSOp jsop_;
+
+ public:
+ RINSTRUCTION_HEADER_NUM_OP_(Compare, 2)
+
+ [[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 RSubstr final : public RInstruction {
+ public:
+ RINSTRUCTION_HEADER_NUM_OP_(Substr, 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 RTypeOfName final : public RInstruction {
+ public:
+ RINSTRUCTION_HEADER_NUM_OP_(TypeOfName, 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 {
+ public:
+ RINSTRUCTION_HEADER_NUM_OP_(NewObject, 1)
+
+ [[nodiscard]] bool recover(JSContext* cx,
+ SnapshotIterator& iter) const override;
+};
+
+class RNewPlainObject final : public RInstruction {
+ private:
+ gc::AllocKind allocKind_;
+ gc::InitialHeap initialHeap_;
+
+ public:
+ RINSTRUCTION_HEADER_NUM_OP_(NewPlainObject, 1)
+
+ [[nodiscard]] bool recover(JSContext* cx,
+ SnapshotIterator& iter) const override;
+};
+
+class RNewArrayObject final : public RInstruction {
+ private:
+ uint32_t length_;
+ gc::InitialHeap initialHeap_;
+
+ public:
+ RINSTRUCTION_HEADER_NUM_OP_(NewArrayObject, 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 RLambda final : public RInstruction {
+ public:
+ RINSTRUCTION_HEADER_NUM_OP_(Lambda, 2)
+
+ [[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 RCreateArgumentsObject final : public RInstruction {
+ public:
+ RINSTRUCTION_HEADER_NUM_OP_(CreateArgumentsObject, 1)
+
+ [[nodiscard]] bool recover(JSContext* cx,
+ SnapshotIterator& iter) const override;
+};
+
+class RCreateInlinedArgumentsObject final : public RInstruction {
+ private:
+ uint32_t numActuals_;
+
+ public:
+ RINSTRUCTION_HEADER_(CreateInlinedArgumentsObject)
+
+ uint32_t numActuals() const { return numActuals_; }
+ uint32_t numOperands() const override {
+ // +1 for the callObj.
+ // +1 for the callee.
+ return numActuals() + 2;
+ }
+
+ [[nodiscard]] bool recover(JSContext* cx,
+ SnapshotIterator& iter) const override;
+};
+
+class RRest final : public RInstruction {
+ uint32_t numFormals_;
+
+ public:
+ RINSTRUCTION_HEADER_NUM_OP_(Rest, 1)
+
+ [[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 */