tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Recover.h (33763B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef jit_Recover_h
      8 #define jit_Recover_h
      9 
     10 #include "mozilla/Attributes.h"
     11 
     12 #include "jit/MIR-wasm.h"
     13 #include "jit/MIR.h"
     14 #include "jit/Snapshots.h"
     15 
     16 namespace js {
     17 namespace jit {
     18 
     19 // [SMDOC] IonMonkey Recover Instructions
     20 //
     21 // This file contains all recover instructions.
     22 //
     23 // A recover instruction is an equivalent of a MIR instruction which is executed
     24 // before the reconstruction of a baseline frame. Recover instructions are used
     25 // by resume points to fill the value which are not produced by the code
     26 // compiled by IonMonkey. For example, if a value is optimized away by
     27 // IonMonkey, but required by Baseline, then we should have a recover
     28 // instruction to fill the missing baseline frame slot.
     29 //
     30 // Recover instructions are executed either during a bailout, or under a call
     31 // when the stack frame is introspected. If the stack is introspected, then any
     32 // use of recover instruction must lead to an invalidation of the code.
     33 //
     34 // For each MIR instruction where |canRecoverOnBailout| might return true, we
     35 // have a RInstruction of the same name.
     36 //
     37 // Recover instructions are encoded by the code generator into a compact buffer
     38 // (RecoverWriter). The MIR instruction method |writeRecoverData| should write a
     39 // tag in the |CompactBufferWriter| which is used by
     40 // |RInstruction::readRecoverData| to dispatch to the right Recover
     41 // instruction. Then |writeRecoverData| writes any local fields which are
     42 // necessary for the execution of the |recover| method. These fields are decoded
     43 // by the Recover instruction constructor which has a |CompactBufferReader| as
     44 // argument. The constructor of the Recover instruction should follow the same
     45 // sequence as the |writeRecoverData| method of the MIR instruction.
     46 //
     47 // Recover instructions are decoded by the |SnapshotIterator| (RecoverReader),
     48 // which is given as argument of the |recover| methods, in order to read the
     49 // operands.  The number of operands read should be the same as the result of
     50 // |numOperands|, which corresponds to the number of operands of the MIR
     51 // instruction.  Operands should be decoded in the same order as the operands of
     52 // the MIR instruction.
     53 //
     54 // The result of the |recover| method should either be a failure, or a value
     55 // stored on the |SnapshotIterator|, by using the |storeInstructionResult|
     56 // method.
     57 
     58 #define RECOVER_OPCODE_LIST(_)    \
     59  _(ResumePoint)                  \
     60  _(BitNot)                       \
     61  _(BitAnd)                       \
     62  _(BitOr)                        \
     63  _(BitXor)                       \
     64  _(Lsh)                          \
     65  _(Rsh)                          \
     66  _(Ursh)                         \
     67  _(SignExtendInt32)              \
     68  _(Add)                          \
     69  _(Sub)                          \
     70  _(Mul)                          \
     71  _(Div)                          \
     72  _(Mod)                          \
     73  _(Not)                          \
     74  _(BigIntAdd)                    \
     75  _(BigIntSub)                    \
     76  _(BigIntMul)                    \
     77  _(BigIntDiv)                    \
     78  _(BigIntMod)                    \
     79  _(BigIntPow)                    \
     80  _(BigIntBitAnd)                 \
     81  _(BigIntBitOr)                  \
     82  _(BigIntBitXor)                 \
     83  _(BigIntLsh)                    \
     84  _(BigIntRsh)                    \
     85  _(BigIntIncrement)              \
     86  _(BigIntDecrement)              \
     87  _(BigIntNegate)                 \
     88  _(BigIntBitNot)                 \
     89  _(BigIntToIntPtr)               \
     90  _(IntPtrToBigInt)               \
     91  _(BigIntPtrAdd)                 \
     92  _(BigIntPtrSub)                 \
     93  _(BigIntPtrMul)                 \
     94  _(BigIntPtrDiv)                 \
     95  _(BigIntPtrMod)                 \
     96  _(BigIntPtrPow)                 \
     97  _(BigIntPtrBitAnd)              \
     98  _(BigIntPtrBitOr)               \
     99  _(BigIntPtrBitXor)              \
    100  _(BigIntPtrLsh)                 \
    101  _(BigIntPtrRsh)                 \
    102  _(BigIntPtrBitNot)              \
    103  _(Compare)                      \
    104  _(StrictConstantCompareInt32)   \
    105  _(StrictConstantCompareBoolean) \
    106  _(Concat)                       \
    107  _(StringLength)                 \
    108  _(ArgumentsLength)              \
    109  _(Floor)                        \
    110  _(Ceil)                         \
    111  _(Round)                        \
    112  _(Trunc)                        \
    113  _(CharCodeAt)                   \
    114  _(FromCharCode)                 \
    115  _(FromCharCodeEmptyIfNegative)  \
    116  _(Pow)                          \
    117  _(PowHalf)                      \
    118  _(MinMax)                       \
    119  _(Abs)                          \
    120  _(Sqrt)                         \
    121  _(Atan2)                        \
    122  _(Hypot)                        \
    123  _(Sign)                         \
    124  _(MathFunction)                 \
    125  _(Random)                       \
    126  _(StringSplit)                  \
    127  _(NaNToZero)                    \
    128  _(StringReplace)                \
    129  _(Substr)                       \
    130  _(TypeOf)                       \
    131  _(TypeOfName)                   \
    132  _(ToDouble)                     \
    133  _(ToFloat32)                    \
    134  _(ToFloat16)                    \
    135  _(TruncateToInt32)              \
    136  _(NewObject)                    \
    137  _(NewPlainObject)               \
    138  _(NewArrayObject)               \
    139  _(NewTypedArray)                \
    140  _(NewArray)                     \
    141  _(NewIterator)                  \
    142  _(NewCallObject)                \
    143  _(Lambda)                       \
    144  _(FunctionWithProto)            \
    145  _(Callee)                       \
    146  _(FunctionEnvironment)          \
    147  _(ObjectKeys)                   \
    148  _(ObjectKeysFromIterator)       \
    149  _(ObjectState)                  \
    150  _(ArrayState)                   \
    151  _(AtomicIsLockFree)             \
    152  _(Int64ToBigInt)                \
    153  _(BigIntAsIntN)                 \
    154  _(BigIntAsUintN)                \
    155  _(CreateArgumentsObject)        \
    156  _(CreateInlinedArgumentsObject) \
    157  _(Rest)                         \
    158  _(TypedArraySubarray)           \
    159  _(AssertRecoveredOnBailout)
    160 
    161 class RResumePoint;
    162 class SnapshotIterator;
    163 
    164 class MOZ_NON_PARAM RInstruction {
    165 public:
    166  enum Opcode {
    167 #define DEFINE_OPCODES_(op) Recover_##op,
    168    RECOVER_OPCODE_LIST(DEFINE_OPCODES_)
    169 #undef DEFINE_OPCODES_
    170        Recover_Invalid
    171  };
    172 
    173  virtual Opcode opcode() const = 0;
    174 
    175  // As opposed to the MIR, there is no need to add more methods as every
    176  // other instruction is well abstracted under the "recover" method.
    177  bool isResumePoint() const { return opcode() == Recover_ResumePoint; }
    178  inline const RResumePoint* toResumePoint() const;
    179 
    180  // Call the copy constructor of a specific RInstruction, to do a copy of the
    181  // RInstruction content.
    182  virtual void cloneInto(RInstructionStorage* raw) const = 0;
    183 
    184  // Number of allocations which are encoded in the Snapshot for recovering
    185  // the current instruction.
    186  virtual uint32_t numOperands() const = 0;
    187 
    188  // Function used to recover the value computed by this instruction. This
    189  // function reads its arguments from the allocations listed on the snapshot
    190  // iterator and stores its returned value on the snapshot iterator too.
    191  [[nodiscard]] virtual bool recover(JSContext* cx,
    192                                     SnapshotIterator& iter) const = 0;
    193 
    194  // Decode an RInstruction on top of the reserved storage space, based on the
    195  // tag written by the writeRecoverData function of the corresponding MIR
    196  // instruction.
    197  static void readRecoverData(CompactBufferReader& reader,
    198                              RInstructionStorage* raw);
    199 };
    200 
    201 #define RINSTRUCTION_HEADER_(op)                                        \
    202 private:                                                               \
    203  friend class RInstruction;                                            \
    204  explicit R##op(CompactBufferReader& reader);                          \
    205  explicit R##op(const R##op& src) = default;                           \
    206                                                                        \
    207 public:                                                                \
    208  Opcode opcode() const override { return RInstruction::Recover_##op; } \
    209  void cloneInto(RInstructionStorage* raw) const override {             \
    210    new (raw->addr()) R##op(*this);                                     \
    211  }
    212 
    213 #define RINSTRUCTION_HEADER_NUM_OP_MAIN(op, numOp) \
    214  RINSTRUCTION_HEADER_(op)                         \
    215  uint32_t numOperands() const override { return numOp; }
    216 
    217 #ifdef DEBUG
    218 #  define RINSTRUCTION_HEADER_NUM_OP_(op, numOp)                      \
    219    RINSTRUCTION_HEADER_NUM_OP_MAIN(op, numOp)                        \
    220    static_assert(                                                    \
    221        M##op::staticNumOperands == numOp,                            \
    222        "The recover instructions's numOperands should equal to the " \
    223        "MIR's numOperands");
    224 #else
    225 #  define RINSTRUCTION_HEADER_NUM_OP_(op, numOp) \
    226    RINSTRUCTION_HEADER_NUM_OP_MAIN(op, numOp)
    227 #endif
    228 
    229 class RResumePoint final : public RInstruction {
    230 private:
    231  uint32_t pcOffsetAndMode_;  // Offset from script->code and ResumeMode.
    232  uint32_t numOperands_;      // Number of slots.
    233 
    234 public:
    235  RINSTRUCTION_HEADER_(ResumePoint)
    236 
    237  // Used to encode/decode pcOffsetAndMode_.
    238  static constexpr uint32_t PCOffsetShift = 4;
    239  static constexpr uint32_t ResumeModeMask = 0b1111;
    240  static_assert(uint32_t(ResumeMode::Last) <= ResumeModeMask);
    241 
    242  uint32_t pcOffset() const { return pcOffsetAndMode_ >> PCOffsetShift; }
    243  ResumeMode mode() const {
    244    return ResumeMode(pcOffsetAndMode_ & ResumeModeMask);
    245  }
    246 
    247  uint32_t numOperands() const override { return numOperands_; }
    248  [[nodiscard]] bool recover(JSContext* cx,
    249                             SnapshotIterator& iter) const override;
    250 };
    251 
    252 class RBitNot final : public RInstruction {
    253 public:
    254  RINSTRUCTION_HEADER_NUM_OP_(BitNot, 1)
    255 
    256  [[nodiscard]] bool recover(JSContext* cx,
    257                             SnapshotIterator& iter) const override;
    258 };
    259 
    260 class RBitAnd final : public RInstruction {
    261 public:
    262  RINSTRUCTION_HEADER_NUM_OP_(BitAnd, 2)
    263 
    264  [[nodiscard]] bool recover(JSContext* cx,
    265                             SnapshotIterator& iter) const override;
    266 };
    267 
    268 class RBitOr final : public RInstruction {
    269 public:
    270  RINSTRUCTION_HEADER_NUM_OP_(BitOr, 2)
    271 
    272  [[nodiscard]] bool recover(JSContext* cx,
    273                             SnapshotIterator& iter) const override;
    274 };
    275 
    276 class RBitXor final : public RInstruction {
    277 public:
    278  RINSTRUCTION_HEADER_NUM_OP_(BitXor, 2)
    279 
    280  [[nodiscard]] bool recover(JSContext* cx,
    281                             SnapshotIterator& iter) const override;
    282 };
    283 
    284 class RLsh final : public RInstruction {
    285 public:
    286  RINSTRUCTION_HEADER_NUM_OP_(Lsh, 2)
    287 
    288  [[nodiscard]] bool recover(JSContext* cx,
    289                             SnapshotIterator& iter) const override;
    290 };
    291 
    292 class RRsh final : public RInstruction {
    293 public:
    294  RINSTRUCTION_HEADER_NUM_OP_(Rsh, 2)
    295 
    296  [[nodiscard]] bool recover(JSContext* cx,
    297                             SnapshotIterator& iter) const override;
    298 };
    299 
    300 class RUrsh final : public RInstruction {
    301 public:
    302  RINSTRUCTION_HEADER_NUM_OP_(Ursh, 2)
    303 
    304  [[nodiscard]] bool recover(JSContext* cx,
    305                             SnapshotIterator& iter) const override;
    306 };
    307 
    308 class RSignExtendInt32 final : public RInstruction {
    309 private:
    310  uint8_t mode_;
    311 
    312 public:
    313  RINSTRUCTION_HEADER_NUM_OP_(SignExtendInt32, 1)
    314 
    315  [[nodiscard]] bool recover(JSContext* cx,
    316                             SnapshotIterator& iter) const override;
    317 };
    318 
    319 class RAdd final : public RInstruction {
    320 private:
    321  bool isFloatOperation_;
    322 
    323 public:
    324  RINSTRUCTION_HEADER_NUM_OP_(Add, 2)
    325 
    326  [[nodiscard]] bool recover(JSContext* cx,
    327                             SnapshotIterator& iter) const override;
    328 };
    329 
    330 class RSub final : public RInstruction {
    331 private:
    332  bool isFloatOperation_;
    333 
    334 public:
    335  RINSTRUCTION_HEADER_NUM_OP_(Sub, 2)
    336 
    337  [[nodiscard]] bool recover(JSContext* cx,
    338                             SnapshotIterator& iter) const override;
    339 };
    340 
    341 class RMul final : public RInstruction {
    342 private:
    343  bool isFloatOperation_;
    344  uint8_t mode_;
    345 
    346 public:
    347  RINSTRUCTION_HEADER_NUM_OP_(Mul, 2)
    348 
    349  [[nodiscard]] bool recover(JSContext* cx,
    350                             SnapshotIterator& iter) const override;
    351 };
    352 
    353 class RDiv final : public RInstruction {
    354 private:
    355  bool isFloatOperation_;
    356 
    357 public:
    358  RINSTRUCTION_HEADER_NUM_OP_(Div, 2)
    359 
    360  [[nodiscard]] bool recover(JSContext* cx,
    361                             SnapshotIterator& iter) const override;
    362 };
    363 
    364 class RMod final : public RInstruction {
    365 public:
    366  RINSTRUCTION_HEADER_NUM_OP_(Mod, 2)
    367 
    368  [[nodiscard]] bool recover(JSContext* cx,
    369                             SnapshotIterator& iter) const override;
    370 };
    371 
    372 class RNot final : public RInstruction {
    373 public:
    374  RINSTRUCTION_HEADER_NUM_OP_(Not, 1)
    375 
    376  [[nodiscard]] bool recover(JSContext* cx,
    377                             SnapshotIterator& iter) const override;
    378 };
    379 
    380 class RBigIntAdd final : public RInstruction {
    381 public:
    382  RINSTRUCTION_HEADER_NUM_OP_(BigIntAdd, 2)
    383 
    384  [[nodiscard]] bool recover(JSContext* cx,
    385                             SnapshotIterator& iter) const override;
    386 };
    387 
    388 class RBigIntSub final : public RInstruction {
    389 public:
    390  RINSTRUCTION_HEADER_NUM_OP_(BigIntSub, 2)
    391 
    392  [[nodiscard]] bool recover(JSContext* cx,
    393                             SnapshotIterator& iter) const override;
    394 };
    395 
    396 class RBigIntMul final : public RInstruction {
    397 public:
    398  RINSTRUCTION_HEADER_NUM_OP_(BigIntMul, 2)
    399 
    400  [[nodiscard]] bool recover(JSContext* cx,
    401                             SnapshotIterator& iter) const override;
    402 };
    403 
    404 class RBigIntDiv final : public RInstruction {
    405 public:
    406  RINSTRUCTION_HEADER_NUM_OP_(BigIntDiv, 2)
    407 
    408  [[nodiscard]] bool recover(JSContext* cx,
    409                             SnapshotIterator& iter) const override;
    410 };
    411 
    412 class RBigIntMod final : public RInstruction {
    413 public:
    414  RINSTRUCTION_HEADER_NUM_OP_(BigIntMod, 2)
    415 
    416  [[nodiscard]] bool recover(JSContext* cx,
    417                             SnapshotIterator& iter) const override;
    418 };
    419 
    420 class RBigIntPow final : public RInstruction {
    421 public:
    422  RINSTRUCTION_HEADER_NUM_OP_(BigIntPow, 2)
    423 
    424  [[nodiscard]] bool recover(JSContext* cx,
    425                             SnapshotIterator& iter) const override;
    426 };
    427 
    428 class RBigIntBitAnd final : public RInstruction {
    429 public:
    430  RINSTRUCTION_HEADER_NUM_OP_(BigIntBitAnd, 2)
    431 
    432  [[nodiscard]] bool recover(JSContext* cx,
    433                             SnapshotIterator& iter) const override;
    434 };
    435 
    436 class RBigIntBitOr final : public RInstruction {
    437 public:
    438  RINSTRUCTION_HEADER_NUM_OP_(BigIntBitOr, 2)
    439 
    440  [[nodiscard]] bool recover(JSContext* cx,
    441                             SnapshotIterator& iter) const override;
    442 };
    443 
    444 class RBigIntBitXor final : public RInstruction {
    445 public:
    446  RINSTRUCTION_HEADER_NUM_OP_(BigIntBitXor, 2)
    447 
    448  [[nodiscard]] bool recover(JSContext* cx,
    449                             SnapshotIterator& iter) const override;
    450 };
    451 
    452 class RBigIntLsh final : public RInstruction {
    453 public:
    454  RINSTRUCTION_HEADER_NUM_OP_(BigIntLsh, 2)
    455 
    456  [[nodiscard]] bool recover(JSContext* cx,
    457                             SnapshotIterator& iter) const override;
    458 };
    459 
    460 class RBigIntRsh final : public RInstruction {
    461 public:
    462  RINSTRUCTION_HEADER_NUM_OP_(BigIntRsh, 2)
    463 
    464  [[nodiscard]] bool recover(JSContext* cx,
    465                             SnapshotIterator& iter) const override;
    466 };
    467 
    468 class RBigIntIncrement final : public RInstruction {
    469 public:
    470  RINSTRUCTION_HEADER_NUM_OP_(BigIntIncrement, 1)
    471 
    472  [[nodiscard]] bool recover(JSContext* cx,
    473                             SnapshotIterator& iter) const override;
    474 };
    475 
    476 class RBigIntDecrement final : public RInstruction {
    477 public:
    478  RINSTRUCTION_HEADER_NUM_OP_(BigIntDecrement, 1)
    479 
    480  [[nodiscard]] bool recover(JSContext* cx,
    481                             SnapshotIterator& iter) const override;
    482 };
    483 
    484 class RBigIntNegate final : public RInstruction {
    485 public:
    486  RINSTRUCTION_HEADER_NUM_OP_(BigIntNegate, 1)
    487 
    488  [[nodiscard]] bool recover(JSContext* cx,
    489                             SnapshotIterator& iter) const override;
    490 };
    491 
    492 class RBigIntBitNot final : public RInstruction {
    493 public:
    494  RINSTRUCTION_HEADER_NUM_OP_(BigIntBitNot, 1)
    495 
    496  [[nodiscard]] bool recover(JSContext* cx,
    497                             SnapshotIterator& iter) const override;
    498 };
    499 
    500 class RBigIntToIntPtr final : public RInstruction {
    501 public:
    502  RINSTRUCTION_HEADER_NUM_OP_(BigIntToIntPtr, 1)
    503 
    504  [[nodiscard]] bool recover(JSContext* cx,
    505                             SnapshotIterator& iter) const override;
    506 };
    507 
    508 class RIntPtrToBigInt final : public RInstruction {
    509 public:
    510  RINSTRUCTION_HEADER_NUM_OP_(IntPtrToBigInt, 1)
    511 
    512  [[nodiscard]] bool recover(JSContext* cx,
    513                             SnapshotIterator& iter) const override;
    514 };
    515 
    516 class RBigIntPtrAdd final : public RInstruction {
    517 public:
    518  RINSTRUCTION_HEADER_NUM_OP_(BigIntPtrAdd, 2)
    519 
    520  [[nodiscard]] bool recover(JSContext* cx,
    521                             SnapshotIterator& iter) const override;
    522 };
    523 
    524 class RBigIntPtrSub final : public RInstruction {
    525 public:
    526  RINSTRUCTION_HEADER_NUM_OP_(BigIntPtrSub, 2)
    527 
    528  [[nodiscard]] bool recover(JSContext* cx,
    529                             SnapshotIterator& iter) const override;
    530 };
    531 
    532 class RBigIntPtrMul final : public RInstruction {
    533 public:
    534  RINSTRUCTION_HEADER_NUM_OP_(BigIntPtrMul, 2)
    535 
    536  [[nodiscard]] bool recover(JSContext* cx,
    537                             SnapshotIterator& iter) const override;
    538 };
    539 
    540 class RBigIntPtrDiv final : public RInstruction {
    541 public:
    542  RINSTRUCTION_HEADER_NUM_OP_(BigIntPtrDiv, 2)
    543 
    544  [[nodiscard]] bool recover(JSContext* cx,
    545                             SnapshotIterator& iter) const override;
    546 };
    547 
    548 class RBigIntPtrMod final : public RInstruction {
    549 public:
    550  RINSTRUCTION_HEADER_NUM_OP_(BigIntPtrMod, 2)
    551 
    552  [[nodiscard]] bool recover(JSContext* cx,
    553                             SnapshotIterator& iter) const override;
    554 };
    555 
    556 class RBigIntPtrPow final : public RInstruction {
    557 public:
    558  RINSTRUCTION_HEADER_NUM_OP_(BigIntPtrPow, 2)
    559 
    560  [[nodiscard]] bool recover(JSContext* cx,
    561                             SnapshotIterator& iter) const override;
    562 };
    563 
    564 class RBigIntPtrBitAnd final : public RInstruction {
    565 public:
    566  RINSTRUCTION_HEADER_NUM_OP_(BigIntPtrBitAnd, 2)
    567 
    568  [[nodiscard]] bool recover(JSContext* cx,
    569                             SnapshotIterator& iter) const override;
    570 };
    571 
    572 class RBigIntPtrBitOr final : public RInstruction {
    573 public:
    574  RINSTRUCTION_HEADER_NUM_OP_(BigIntPtrBitOr, 2)
    575 
    576  [[nodiscard]] bool recover(JSContext* cx,
    577                             SnapshotIterator& iter) const override;
    578 };
    579 
    580 class RBigIntPtrBitXor final : public RInstruction {
    581 public:
    582  RINSTRUCTION_HEADER_NUM_OP_(BigIntPtrBitXor, 2)
    583 
    584  [[nodiscard]] bool recover(JSContext* cx,
    585                             SnapshotIterator& iter) const override;
    586 };
    587 
    588 class RBigIntPtrLsh final : public RInstruction {
    589 public:
    590  RINSTRUCTION_HEADER_NUM_OP_(BigIntPtrLsh, 2)
    591 
    592  [[nodiscard]] bool recover(JSContext* cx,
    593                             SnapshotIterator& iter) const override;
    594 };
    595 
    596 class RBigIntPtrRsh final : public RInstruction {
    597 public:
    598  RINSTRUCTION_HEADER_NUM_OP_(BigIntPtrRsh, 2)
    599 
    600  [[nodiscard]] bool recover(JSContext* cx,
    601                             SnapshotIterator& iter) const override;
    602 };
    603 
    604 class RBigIntPtrBitNot final : public RInstruction {
    605 public:
    606  RINSTRUCTION_HEADER_NUM_OP_(BigIntPtrBitNot, 1)
    607 
    608  [[nodiscard]] bool recover(JSContext* cx,
    609                             SnapshotIterator& iter) const override;
    610 };
    611 
    612 class RCompare final : public RInstruction {
    613  JSOp jsop_;
    614 
    615 public:
    616  RINSTRUCTION_HEADER_NUM_OP_(Compare, 2)
    617 
    618  [[nodiscard]] bool recover(JSContext* cx,
    619                             SnapshotIterator& iter) const override;
    620 };
    621 
    622 class RStrictConstantCompareInt32 final : public RInstruction {
    623  JSOp jsop_;
    624  int32_t constant_;
    625 
    626 public:
    627  RINSTRUCTION_HEADER_NUM_OP_(StrictConstantCompareInt32, 1)
    628 
    629  [[nodiscard]] bool recover(JSContext* cx,
    630                             SnapshotIterator& iter) const override;
    631 };
    632 
    633 class RStrictConstantCompareBoolean final : public RInstruction {
    634  JSOp jsop_;
    635  bool constant_;
    636 
    637 public:
    638  RINSTRUCTION_HEADER_NUM_OP_(StrictConstantCompareBoolean, 1)
    639 
    640  [[nodiscard]] bool recover(JSContext* cx,
    641                             SnapshotIterator& iter) const override;
    642 };
    643 
    644 class RConcat final : public RInstruction {
    645 public:
    646  RINSTRUCTION_HEADER_NUM_OP_(Concat, 2)
    647 
    648  [[nodiscard]] bool recover(JSContext* cx,
    649                             SnapshotIterator& iter) const override;
    650 };
    651 
    652 class RStringLength final : public RInstruction {
    653 public:
    654  RINSTRUCTION_HEADER_NUM_OP_(StringLength, 1)
    655 
    656  [[nodiscard]] bool recover(JSContext* cx,
    657                             SnapshotIterator& iter) const override;
    658 };
    659 
    660 class RArgumentsLength final : public RInstruction {
    661 public:
    662  RINSTRUCTION_HEADER_NUM_OP_(ArgumentsLength, 0)
    663 
    664  [[nodiscard]] bool recover(JSContext* cx,
    665                             SnapshotIterator& iter) const override;
    666 };
    667 
    668 class RFloor final : public RInstruction {
    669 public:
    670  RINSTRUCTION_HEADER_NUM_OP_(Floor, 1)
    671 
    672  [[nodiscard]] bool recover(JSContext* cx,
    673                             SnapshotIterator& iter) const override;
    674 };
    675 
    676 class RCeil final : public RInstruction {
    677 public:
    678  RINSTRUCTION_HEADER_NUM_OP_(Ceil, 1)
    679 
    680  [[nodiscard]] bool recover(JSContext* cx,
    681                             SnapshotIterator& iter) const override;
    682 };
    683 
    684 class RRound final : public RInstruction {
    685 public:
    686  RINSTRUCTION_HEADER_NUM_OP_(Round, 1)
    687 
    688  [[nodiscard]] bool recover(JSContext* cx,
    689                             SnapshotIterator& iter) const override;
    690 };
    691 
    692 class RTrunc final : public RInstruction {
    693 public:
    694  RINSTRUCTION_HEADER_NUM_OP_(Trunc, 1)
    695 
    696  [[nodiscard]] bool recover(JSContext* cx,
    697                             SnapshotIterator& iter) const override;
    698 };
    699 
    700 class RCharCodeAt final : public RInstruction {
    701 public:
    702  RINSTRUCTION_HEADER_NUM_OP_(CharCodeAt, 2)
    703 
    704  [[nodiscard]] bool recover(JSContext* cx,
    705                             SnapshotIterator& iter) const override;
    706 };
    707 
    708 class RFromCharCode final : public RInstruction {
    709 public:
    710  RINSTRUCTION_HEADER_NUM_OP_(FromCharCode, 1)
    711 
    712  [[nodiscard]] bool recover(JSContext* cx,
    713                             SnapshotIterator& iter) const override;
    714 };
    715 
    716 class RFromCharCodeEmptyIfNegative final : public RInstruction {
    717 public:
    718  RINSTRUCTION_HEADER_NUM_OP_(FromCharCodeEmptyIfNegative, 1)
    719 
    720  [[nodiscard]] bool recover(JSContext* cx,
    721                             SnapshotIterator& iter) const override;
    722 };
    723 
    724 class RPow final : public RInstruction {
    725 public:
    726  RINSTRUCTION_HEADER_NUM_OP_(Pow, 2)
    727 
    728  [[nodiscard]] bool recover(JSContext* cx,
    729                             SnapshotIterator& iter) const override;
    730 };
    731 
    732 class RPowHalf final : public RInstruction {
    733 public:
    734  RINSTRUCTION_HEADER_NUM_OP_(PowHalf, 1)
    735 
    736  [[nodiscard]] bool recover(JSContext* cx,
    737                             SnapshotIterator& iter) const override;
    738 };
    739 
    740 class RMinMax final : public RInstruction {
    741 private:
    742  bool isMax_;
    743 
    744 public:
    745  RINSTRUCTION_HEADER_NUM_OP_(MinMax, 2)
    746 
    747  [[nodiscard]] bool recover(JSContext* cx,
    748                             SnapshotIterator& iter) const override;
    749 };
    750 
    751 class RAbs final : public RInstruction {
    752 public:
    753  RINSTRUCTION_HEADER_NUM_OP_(Abs, 1)
    754 
    755  [[nodiscard]] bool recover(JSContext* cx,
    756                             SnapshotIterator& iter) const override;
    757 };
    758 
    759 class RSqrt final : public RInstruction {
    760 private:
    761  bool isFloatOperation_;
    762 
    763 public:
    764  RINSTRUCTION_HEADER_NUM_OP_(Sqrt, 1)
    765 
    766  [[nodiscard]] bool recover(JSContext* cx,
    767                             SnapshotIterator& iter) const override;
    768 };
    769 
    770 class RAtan2 final : public RInstruction {
    771 public:
    772  RINSTRUCTION_HEADER_NUM_OP_(Atan2, 2)
    773 
    774  [[nodiscard]] bool recover(JSContext* cx,
    775                             SnapshotIterator& iter) const override;
    776 };
    777 
    778 class RHypot final : public RInstruction {
    779 private:
    780  uint32_t numOperands_;
    781 
    782 public:
    783  RINSTRUCTION_HEADER_(Hypot)
    784 
    785  uint32_t numOperands() const override { return numOperands_; }
    786 
    787  [[nodiscard]] bool recover(JSContext* cx,
    788                             SnapshotIterator& iter) const override;
    789 };
    790 
    791 class RSign final : public RInstruction {
    792 public:
    793  RINSTRUCTION_HEADER_NUM_OP_(Sign, 1)
    794 
    795  [[nodiscard]] bool recover(JSContext* cx,
    796                             SnapshotIterator& iter) const override;
    797 };
    798 
    799 class RMathFunction final : public RInstruction {
    800 private:
    801  UnaryMathFunction function_;
    802 
    803 public:
    804  RINSTRUCTION_HEADER_NUM_OP_(MathFunction, 1)
    805 
    806  [[nodiscard]] bool recover(JSContext* cx,
    807                             SnapshotIterator& iter) const override;
    808 };
    809 
    810 class RRandom final : public RInstruction {
    811  RINSTRUCTION_HEADER_NUM_OP_(Random, 0)
    812 public:
    813  [[nodiscard]] bool recover(JSContext* cx,
    814                             SnapshotIterator& iter) const override;
    815 };
    816 
    817 class RStringSplit final : public RInstruction {
    818 public:
    819  RINSTRUCTION_HEADER_NUM_OP_(StringSplit, 2)
    820 
    821  [[nodiscard]] bool recover(JSContext* cx,
    822                             SnapshotIterator& iter) const override;
    823 };
    824 
    825 class RNaNToZero final : public RInstruction {
    826 public:
    827  RINSTRUCTION_HEADER_NUM_OP_(NaNToZero, 1);
    828 
    829  bool recover(JSContext* cx, SnapshotIterator& iter) const override;
    830 };
    831 
    832 class RStringReplace final : public RInstruction {
    833 private:
    834  bool isFlatReplacement_;
    835 
    836 public:
    837  RINSTRUCTION_HEADER_NUM_OP_(StringReplace, 3)
    838 
    839  [[nodiscard]] bool recover(JSContext* cx,
    840                             SnapshotIterator& iter) const override;
    841 };
    842 
    843 class RSubstr final : public RInstruction {
    844 public:
    845  RINSTRUCTION_HEADER_NUM_OP_(Substr, 3)
    846 
    847  [[nodiscard]] bool recover(JSContext* cx,
    848                             SnapshotIterator& iter) const override;
    849 };
    850 
    851 class RTypeOf final : public RInstruction {
    852 public:
    853  RINSTRUCTION_HEADER_NUM_OP_(TypeOf, 1)
    854 
    855  [[nodiscard]] bool recover(JSContext* cx,
    856                             SnapshotIterator& iter) const override;
    857 };
    858 
    859 class RTypeOfName final : public RInstruction {
    860 public:
    861  RINSTRUCTION_HEADER_NUM_OP_(TypeOfName, 1)
    862 
    863  [[nodiscard]] bool recover(JSContext* cx,
    864                             SnapshotIterator& iter) const override;
    865 };
    866 
    867 class RToDouble final : public RInstruction {
    868 public:
    869  RINSTRUCTION_HEADER_NUM_OP_(ToDouble, 1)
    870 
    871  [[nodiscard]] bool recover(JSContext* cx,
    872                             SnapshotIterator& iter) const override;
    873 };
    874 
    875 class RToFloat32 final : public RInstruction {
    876 public:
    877  RINSTRUCTION_HEADER_NUM_OP_(ToFloat32, 1)
    878 
    879  [[nodiscard]] bool recover(JSContext* cx,
    880                             SnapshotIterator& iter) const override;
    881 };
    882 
    883 class RToFloat16 final : public RInstruction {
    884 public:
    885  RINSTRUCTION_HEADER_NUM_OP_(ToFloat16, 1)
    886 
    887  [[nodiscard]] bool recover(JSContext* cx,
    888                             SnapshotIterator& iter) const override;
    889 };
    890 
    891 class RTruncateToInt32 final : public RInstruction {
    892 public:
    893  RINSTRUCTION_HEADER_NUM_OP_(TruncateToInt32, 1)
    894 
    895  [[nodiscard]] bool recover(JSContext* cx,
    896                             SnapshotIterator& iter) const override;
    897 };
    898 
    899 class RNewObject final : public RInstruction {
    900 public:
    901  RINSTRUCTION_HEADER_NUM_OP_(NewObject, 1)
    902 
    903  [[nodiscard]] bool recover(JSContext* cx,
    904                             SnapshotIterator& iter) const override;
    905 };
    906 
    907 class RNewPlainObject final : public RInstruction {
    908 private:
    909  gc::AllocKind allocKind_;
    910  gc::Heap initialHeap_;
    911 
    912 public:
    913  RINSTRUCTION_HEADER_NUM_OP_(NewPlainObject, 1)
    914 
    915  [[nodiscard]] bool recover(JSContext* cx,
    916                             SnapshotIterator& iter) const override;
    917 };
    918 
    919 class RNewArrayObject final : public RInstruction {
    920 private:
    921  uint32_t length_;
    922  gc::Heap initialHeap_;
    923 
    924 public:
    925  RINSTRUCTION_HEADER_NUM_OP_(NewArrayObject, 1)
    926 
    927  [[nodiscard]] bool recover(JSContext* cx,
    928                             SnapshotIterator& iter) const override;
    929 };
    930 
    931 class RNewTypedArray final : public RInstruction {
    932 public:
    933  RINSTRUCTION_HEADER_NUM_OP_(NewTypedArray, 1)
    934 
    935  [[nodiscard]] bool recover(JSContext* cx,
    936                             SnapshotIterator& iter) const override;
    937 };
    938 
    939 class RNewArray final : public RInstruction {
    940 private:
    941  uint32_t count_;
    942 
    943 public:
    944  RINSTRUCTION_HEADER_NUM_OP_(NewArray, 1)
    945 
    946  [[nodiscard]] bool recover(JSContext* cx,
    947                             SnapshotIterator& iter) const override;
    948 };
    949 
    950 class RNewIterator final : public RInstruction {
    951 private:
    952  uint8_t type_;
    953 
    954 public:
    955  RINSTRUCTION_HEADER_NUM_OP_(NewIterator, 1)
    956 
    957  [[nodiscard]] bool recover(JSContext* cx,
    958                             SnapshotIterator& iter) const override;
    959 };
    960 
    961 class RLambda final : public RInstruction {
    962 public:
    963  RINSTRUCTION_HEADER_NUM_OP_(Lambda, 2)
    964 
    965  [[nodiscard]] bool recover(JSContext* cx,
    966                             SnapshotIterator& iter) const override;
    967 };
    968 
    969 class RFunctionWithProto final : public RInstruction {
    970 public:
    971  RINSTRUCTION_HEADER_NUM_OP_(FunctionWithProto, 3)
    972 
    973  [[nodiscard]] bool recover(JSContext* cx,
    974                             SnapshotIterator& iter) const override;
    975 };
    976 
    977 class RCallee final : public RInstruction {
    978 public:
    979  RINSTRUCTION_HEADER_NUM_OP_(Callee, 0)
    980 
    981  [[nodiscard]] bool recover(JSContext* cx,
    982                             SnapshotIterator& iter) const override;
    983 };
    984 
    985 class RFunctionEnvironment final : public RInstruction {
    986 public:
    987  RINSTRUCTION_HEADER_NUM_OP_(FunctionEnvironment, 1)
    988 
    989  [[nodiscard]] bool recover(JSContext* cx,
    990                             SnapshotIterator& iter) const override;
    991 };
    992 
    993 class RNewCallObject final : public RInstruction {
    994 public:
    995  RINSTRUCTION_HEADER_NUM_OP_(NewCallObject, 1)
    996 
    997  [[nodiscard]] bool recover(JSContext* cx,
    998                             SnapshotIterator& iter) const override;
    999 };
   1000 
   1001 class RObjectKeys final : public RInstruction {
   1002 public:
   1003  RINSTRUCTION_HEADER_NUM_OP_(ObjectKeys, 1)
   1004 
   1005  [[nodiscard]] bool recover(JSContext* cx,
   1006                             SnapshotIterator& iter) const override;
   1007 };
   1008 
   1009 class RObjectKeysFromIterator final : public RInstruction {
   1010 public:
   1011  RINSTRUCTION_HEADER_NUM_OP_(ObjectKeysFromIterator, 1)
   1012 
   1013  [[nodiscard]] bool recover(JSContext* cx,
   1014                             SnapshotIterator& iter) const override;
   1015 };
   1016 
   1017 class RObjectState final : public RInstruction {
   1018 private:
   1019  uint32_t numSlots_;  // Number of slots.
   1020 
   1021 public:
   1022  RINSTRUCTION_HEADER_(ObjectState)
   1023 
   1024  uint32_t numSlots() const { return numSlots_; }
   1025  uint32_t numOperands() const override {
   1026    // +1 for the object.
   1027    return numSlots() + 1;
   1028  }
   1029 
   1030  [[nodiscard]] bool recover(JSContext* cx,
   1031                             SnapshotIterator& iter) const override;
   1032 };
   1033 
   1034 class RArrayState final : public RInstruction {
   1035 private:
   1036  uint32_t numElements_;
   1037 
   1038 public:
   1039  RINSTRUCTION_HEADER_(ArrayState)
   1040 
   1041  uint32_t numElements() const { return numElements_; }
   1042  uint32_t numOperands() const override {
   1043    // +1 for the array.
   1044    // +1 for the initalized length.
   1045    return numElements() + 2;
   1046  }
   1047 
   1048  [[nodiscard]] bool recover(JSContext* cx,
   1049                             SnapshotIterator& iter) const override;
   1050 };
   1051 
   1052 class RAtomicIsLockFree final : public RInstruction {
   1053 public:
   1054  RINSTRUCTION_HEADER_NUM_OP_(AtomicIsLockFree, 1)
   1055 
   1056  [[nodiscard]] bool recover(JSContext* cx,
   1057                             SnapshotIterator& iter) const override;
   1058 };
   1059 
   1060 class RInt64ToBigInt final : public RInstruction {
   1061  bool isSigned_;
   1062 
   1063 public:
   1064  RINSTRUCTION_HEADER_NUM_OP_(Int64ToBigInt, 1)
   1065 
   1066  [[nodiscard]] bool recover(JSContext* cx,
   1067                             SnapshotIterator& iter) const override;
   1068 };
   1069 
   1070 class RBigIntAsIntN final : public RInstruction {
   1071 public:
   1072  RINSTRUCTION_HEADER_NUM_OP_(BigIntAsIntN, 2)
   1073 
   1074  [[nodiscard]] bool recover(JSContext* cx,
   1075                             SnapshotIterator& iter) const override;
   1076 };
   1077 
   1078 class RBigIntAsUintN final : public RInstruction {
   1079 public:
   1080  RINSTRUCTION_HEADER_NUM_OP_(BigIntAsUintN, 2)
   1081 
   1082  [[nodiscard]] bool recover(JSContext* cx,
   1083                             SnapshotIterator& iter) const override;
   1084 };
   1085 
   1086 class RCreateArgumentsObject final : public RInstruction {
   1087 public:
   1088  RINSTRUCTION_HEADER_NUM_OP_(CreateArgumentsObject, 1)
   1089 
   1090  [[nodiscard]] bool recover(JSContext* cx,
   1091                             SnapshotIterator& iter) const override;
   1092 };
   1093 
   1094 class RCreateInlinedArgumentsObject final : public RInstruction {
   1095 private:
   1096  uint32_t numActuals_;
   1097 
   1098 public:
   1099  RINSTRUCTION_HEADER_(CreateInlinedArgumentsObject)
   1100 
   1101  uint32_t numActuals() const { return numActuals_; }
   1102  uint32_t numOperands() const override {
   1103    // +1 for the callObj.
   1104    // +1 for the callee.
   1105    return numActuals() + 2;
   1106  }
   1107 
   1108  [[nodiscard]] bool recover(JSContext* cx,
   1109                             SnapshotIterator& iter) const override;
   1110 };
   1111 
   1112 class RRest final : public RInstruction {
   1113  uint32_t numFormals_;
   1114 
   1115 public:
   1116  RINSTRUCTION_HEADER_NUM_OP_(Rest, 1)
   1117 
   1118  [[nodiscard]] bool recover(JSContext* cx,
   1119                             SnapshotIterator& iter) const override;
   1120 };
   1121 
   1122 class RTypedArraySubarray final : public RInstruction {
   1123 public:
   1124  RINSTRUCTION_HEADER_NUM_OP_(TypedArraySubarray, 3)
   1125 
   1126  [[nodiscard]] bool recover(JSContext* cx,
   1127                             SnapshotIterator& iter) const override;
   1128 };
   1129 
   1130 class RAssertRecoveredOnBailout final : public RInstruction {
   1131 public:
   1132  RINSTRUCTION_HEADER_NUM_OP_(AssertRecoveredOnBailout, 1)
   1133 
   1134  [[nodiscard]] bool recover(JSContext* cx,
   1135                             SnapshotIterator& iter) const override;
   1136 };
   1137 
   1138 #undef RINSTRUCTION_HEADER_
   1139 #undef RINSTRUCTION_HEADER_NUM_OP_
   1140 #undef RINSTRUCTION_HEADER_NUM_OP_MAIN
   1141 
   1142 const RResumePoint* RInstruction::toResumePoint() const {
   1143  MOZ_ASSERT(isResumePoint());
   1144  return static_cast<const RResumePoint*>(this);
   1145 }
   1146 
   1147 }  // namespace jit
   1148 }  // namespace js
   1149 
   1150 #endif /* jit_Recover_h */