tor-browser

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

IonIC.h (21358B)


      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_IonIC_h
      8 #define jit_IonIC_h
      9 
     10 #include "jit/CacheIR.h"
     11 #include "jit/ICState.h"
     12 #include "jit/shared/Assembler-shared.h"
     13 #include "vm/CompletionKind.h"
     14 
     15 namespace js {
     16 namespace jit {
     17 
     18 class CacheIRStubInfo;
     19 class CacheIRWriter;
     20 class IonScript;
     21 
     22 // An optimized stub attached to an IonIC.
     23 class IonICStub {
     24  // Code to jump to when this stub fails. This is either the next optimized
     25  // stub or the OOL fallback path.
     26  uint8_t* nextCodeRaw_;
     27 
     28  // The next optimized stub in this chain, or nullptr if this is the last
     29  // one.
     30  IonICStub* next_;
     31 
     32  // Info about this stub.
     33  CacheIRStubInfo* stubInfo_;
     34 
     35 #ifndef JS_64BIT
     36 protected:  // Silence Clang warning about unused private fields.
     37  // Ensure stub data is 8-byte aligned on 32-bit.
     38  uintptr_t padding_ = 0;
     39 #endif
     40 
     41 public:
     42  IonICStub(uint8_t* fallbackCode, CacheIRStubInfo* stubInfo)
     43      : nextCodeRaw_(fallbackCode), next_(nullptr), stubInfo_(stubInfo) {}
     44 
     45  uint8_t* nextCodeRaw() const { return nextCodeRaw_; }
     46  uint8_t** nextCodeRawPtr() { return &nextCodeRaw_; }
     47  CacheIRStubInfo* stubInfo() const { return stubInfo_; }
     48  IonICStub* next() const { return next_; }
     49 
     50  uint8_t* stubDataStart();
     51 
     52  void setNext(IonICStub* next, uint8_t* nextCodeRaw) {
     53    MOZ_ASSERT(!next_);
     54    MOZ_ASSERT(next && nextCodeRaw);
     55    next_ = next;
     56    nextCodeRaw_ = nextCodeRaw;
     57  }
     58 
     59  // Null out pointers when we unlink stubs, to ensure we never use
     60  // discarded stubs.
     61  void poison() {
     62    nextCodeRaw_ = nullptr;
     63    next_ = nullptr;
     64    stubInfo_ = nullptr;
     65  }
     66 };
     67 
     68 class IonGetPropertyIC;
     69 class IonSetPropertyIC;
     70 class IonGetPropSuperIC;
     71 class IonGetNameIC;
     72 class IonBindNameIC;
     73 class IonGetIteratorIC;
     74 class IonHasOwnIC;
     75 class IonCheckPrivateFieldIC;
     76 class IonInIC;
     77 class IonInstanceOfIC;
     78 class IonCompareIC;
     79 class IonUnaryArithIC;
     80 class IonBinaryArithIC;
     81 class IonToPropertyKeyIC;
     82 class IonOptimizeSpreadCallIC;
     83 class IonCloseIterIC;
     84 class IonOptimizeGetIteratorIC;
     85 
     86 class IonIC {
     87  // This either points at the OOL path for the fallback path, or the code for
     88  // the first stub.
     89  uint8_t* codeRaw_;
     90 
     91  // The first optimized stub, or nullptr.
     92  IonICStub* firstStub_;
     93 
     94  // Location of this IC.
     95  JSScript* script_;
     96  jsbytecode* pc_;
     97 
     98  // The offset of the rejoin location in the IonScript's code (stubs jump to
     99  // this location).
    100  uint32_t rejoinOffset_;
    101 
    102  // The offset of the OOL path in the IonScript's code that calls the IC's
    103  // update function.
    104  uint32_t fallbackOffset_;
    105 
    106  CacheKind kind_;
    107  ICState state_;
    108 
    109 protected:
    110  explicit IonIC(CacheKind kind)
    111      : codeRaw_(nullptr),
    112        firstStub_(nullptr),
    113        script_(nullptr),
    114        pc_(nullptr),
    115        rejoinOffset_(0),
    116        fallbackOffset_(0),
    117        kind_(kind) {}
    118 
    119  void attachStub(IonICStub* newStub, JitCode* code);
    120 
    121 public:
    122  void setScriptedLocation(JSScript* script, jsbytecode* pc) {
    123    MOZ_ASSERT(!script_ && !pc_);
    124    MOZ_ASSERT(script && pc);
    125    script_ = script;
    126    pc_ = pc;
    127  }
    128 
    129  JSScript* script() const {
    130    MOZ_ASSERT(script_);
    131    return script_;
    132  }
    133  jsbytecode* pc() const {
    134    MOZ_ASSERT(pc_);
    135    return pc_;
    136  }
    137 
    138  // Discard all stubs.
    139  void discardStubs(Zone* zone, IonScript* ionScript);
    140 
    141  // Discard all stubs and reset the ICState.
    142  void reset(Zone* zone, IonScript* ionScript);
    143 
    144  ICState& state() { return state_; }
    145 
    146  CacheKind kind() const { return kind_; }
    147  uint8_t** codeRawPtr() { return &codeRaw_; }
    148 
    149  void setFallbackOffset(CodeOffset offset) {
    150    fallbackOffset_ = offset.offset();
    151  }
    152  void setRejoinOffset(CodeOffset offset) { rejoinOffset_ = offset.offset(); }
    153 
    154  void resetCodeRaw(IonScript* ionScript);
    155 
    156  uint8_t* fallbackAddr(IonScript* ionScript) const;
    157  uint8_t* rejoinAddr(IonScript* ionScript) const;
    158 
    159  IonGetPropertyIC* asGetPropertyIC() {
    160    MOZ_ASSERT(kind_ == CacheKind::GetProp || kind_ == CacheKind::GetElem);
    161    return (IonGetPropertyIC*)this;
    162  }
    163  IonSetPropertyIC* asSetPropertyIC() {
    164    MOZ_ASSERT(kind_ == CacheKind::SetProp || kind_ == CacheKind::SetElem);
    165    return (IonSetPropertyIC*)this;
    166  }
    167  IonGetPropSuperIC* asGetPropSuperIC() {
    168    MOZ_ASSERT(kind_ == CacheKind::GetPropSuper ||
    169               kind_ == CacheKind::GetElemSuper);
    170    return (IonGetPropSuperIC*)this;
    171  }
    172  IonGetNameIC* asGetNameIC() {
    173    MOZ_ASSERT(kind_ == CacheKind::GetName);
    174    return (IonGetNameIC*)this;
    175  }
    176  IonBindNameIC* asBindNameIC() {
    177    MOZ_ASSERT(kind_ == CacheKind::BindName);
    178    return (IonBindNameIC*)this;
    179  }
    180  IonGetIteratorIC* asGetIteratorIC() {
    181    MOZ_ASSERT(kind_ == CacheKind::GetIterator);
    182    return (IonGetIteratorIC*)this;
    183  }
    184  IonOptimizeSpreadCallIC* asOptimizeSpreadCallIC() {
    185    MOZ_ASSERT(kind_ == CacheKind::OptimizeSpreadCall);
    186    return (IonOptimizeSpreadCallIC*)this;
    187  }
    188  IonHasOwnIC* asHasOwnIC() {
    189    MOZ_ASSERT(kind_ == CacheKind::HasOwn);
    190    return (IonHasOwnIC*)this;
    191  }
    192  IonCheckPrivateFieldIC* asCheckPrivateFieldIC() {
    193    MOZ_ASSERT(kind_ == CacheKind::CheckPrivateField);
    194    return (IonCheckPrivateFieldIC*)this;
    195  }
    196  IonInIC* asInIC() {
    197    MOZ_ASSERT(kind_ == CacheKind::In);
    198    return (IonInIC*)this;
    199  }
    200  IonInstanceOfIC* asInstanceOfIC() {
    201    MOZ_ASSERT(kind_ == CacheKind::InstanceOf);
    202    return (IonInstanceOfIC*)this;
    203  }
    204  IonCompareIC* asCompareIC() {
    205    MOZ_ASSERT(kind_ == CacheKind::Compare);
    206    return (IonCompareIC*)this;
    207  }
    208  IonUnaryArithIC* asUnaryArithIC() {
    209    MOZ_ASSERT(kind_ == CacheKind::UnaryArith);
    210    return (IonUnaryArithIC*)this;
    211  }
    212  IonBinaryArithIC* asBinaryArithIC() {
    213    MOZ_ASSERT(kind_ == CacheKind::BinaryArith);
    214    return (IonBinaryArithIC*)this;
    215  }
    216  IonToPropertyKeyIC* asToPropertyKeyIC() {
    217    MOZ_ASSERT(kind_ == CacheKind::ToPropertyKey);
    218    return (IonToPropertyKeyIC*)this;
    219  }
    220  IonCloseIterIC* asCloseIterIC() {
    221    MOZ_ASSERT(kind_ == CacheKind::CloseIter);
    222    return (IonCloseIterIC*)this;
    223  }
    224  IonOptimizeGetIteratorIC* asOptimizeGetIteratorIC() {
    225    MOZ_ASSERT(kind_ == CacheKind::OptimizeGetIterator);
    226    return (IonOptimizeGetIteratorIC*)this;
    227  }
    228 
    229  // Returns the Register to use as scratch when entering IC stubs. This
    230  // should either be an output register or a temp.
    231  Register scratchRegisterForEntryJump();
    232 
    233  void trace(JSTracer* trc, IonScript* ionScript);
    234 
    235  void attachCacheIRStub(JSContext* cx, const CacheIRWriter& writer,
    236                         CacheKind kind, IonScript* ionScript, bool* attached);
    237 };
    238 
    239 class IonGetPropertyIC : public IonIC {
    240 private:
    241  LiveRegisterSet liveRegs_;
    242 
    243  TypedOrValueRegister value_;
    244  ConstantOrRegister id_;
    245  ValueOperand output_;
    246 
    247 public:
    248  IonGetPropertyIC(CacheKind kind, LiveRegisterSet liveRegs,
    249                   TypedOrValueRegister value, const ConstantOrRegister& id,
    250                   ValueOperand output)
    251      : IonIC(kind),
    252        liveRegs_(liveRegs),
    253        value_(value),
    254        id_(id),
    255        output_(output) {}
    256 
    257  TypedOrValueRegister value() const { return value_; }
    258  ConstantOrRegister id() const { return id_; }
    259  ValueOperand output() const { return output_; }
    260  LiveRegisterSet liveRegs() const { return liveRegs_; }
    261 
    262  [[nodiscard]] static bool update(JSContext* cx, HandleScript outerScript,
    263                                   IonGetPropertyIC* ic, HandleValue val,
    264                                   HandleValue idVal, MutableHandleValue res);
    265 };
    266 
    267 class IonGetPropSuperIC : public IonIC {
    268  LiveRegisterSet liveRegs_;
    269 
    270  Register object_;
    271  TypedOrValueRegister receiver_;
    272  ConstantOrRegister id_;
    273  ValueOperand output_;
    274 
    275 public:
    276  IonGetPropSuperIC(CacheKind kind, LiveRegisterSet liveRegs, Register object,
    277                    TypedOrValueRegister receiver, const ConstantOrRegister& id,
    278                    ValueOperand output)
    279      : IonIC(kind),
    280        liveRegs_(liveRegs),
    281        object_(object),
    282        receiver_(receiver),
    283        id_(id),
    284        output_(output) {}
    285 
    286  Register object() const { return object_; }
    287  TypedOrValueRegister receiver() const { return receiver_; }
    288  ConstantOrRegister id() const { return id_; }
    289  ValueOperand output() const { return output_; }
    290  LiveRegisterSet liveRegs() const { return liveRegs_; }
    291 
    292  [[nodiscard]] static bool update(JSContext* cx, HandleScript outerScript,
    293                                   IonGetPropSuperIC* ic, HandleObject obj,
    294                                   HandleValue receiver, HandleValue idVal,
    295                                   MutableHandleValue res);
    296 };
    297 
    298 class IonSetPropertyIC : public IonIC {
    299  LiveRegisterSet liveRegs_;
    300 
    301  Register object_;
    302  Register temp_;
    303  ConstantOrRegister id_;
    304  ConstantOrRegister rhs_;
    305  bool strict_ : 1;
    306 
    307 public:
    308  IonSetPropertyIC(CacheKind kind, LiveRegisterSet liveRegs, Register object,
    309                   Register temp, const ConstantOrRegister& id,
    310                   const ConstantOrRegister& rhs, bool strict)
    311      : IonIC(kind),
    312        liveRegs_(liveRegs),
    313        object_(object),
    314        temp_(temp),
    315        id_(id),
    316        rhs_(rhs),
    317        strict_(strict) {}
    318 
    319  LiveRegisterSet liveRegs() const { return liveRegs_; }
    320  Register object() const { return object_; }
    321  ConstantOrRegister id() const { return id_; }
    322  ConstantOrRegister rhs() const { return rhs_; }
    323 
    324  Register temp() const { return temp_; }
    325 
    326  bool strict() const { return strict_; }
    327 
    328  [[nodiscard]] static bool update(JSContext* cx, HandleScript outerScript,
    329                                   IonSetPropertyIC* ic, HandleObject obj,
    330                                   HandleValue idVal, HandleValue rhs);
    331 };
    332 
    333 class IonGetNameIC : public IonIC {
    334  LiveRegisterSet liveRegs_;
    335 
    336  Register environment_;
    337  ValueOperand output_;
    338  Register temp_;
    339 
    340 public:
    341  IonGetNameIC(LiveRegisterSet liveRegs, Register environment,
    342               ValueOperand output, Register temp)
    343      : IonIC(CacheKind::GetName),
    344        liveRegs_(liveRegs),
    345        environment_(environment),
    346        output_(output),
    347        temp_(temp) {}
    348 
    349  Register environment() const { return environment_; }
    350  ValueOperand output() const { return output_; }
    351  Register temp() const { return temp_; }
    352  LiveRegisterSet liveRegs() const { return liveRegs_; }
    353 
    354  [[nodiscard]] static bool update(JSContext* cx, HandleScript outerScript,
    355                                   IonGetNameIC* ic, HandleObject envChain,
    356                                   MutableHandleValue res);
    357 };
    358 
    359 class IonBindNameIC : public IonIC {
    360  LiveRegisterSet liveRegs_;
    361 
    362  Register environment_;
    363  Register output_;
    364  Register temp_;
    365 
    366 public:
    367  IonBindNameIC(LiveRegisterSet liveRegs, Register environment, Register output,
    368                Register temp)
    369      : IonIC(CacheKind::BindName),
    370        liveRegs_(liveRegs),
    371        environment_(environment),
    372        output_(output),
    373        temp_(temp) {}
    374 
    375  Register environment() const { return environment_; }
    376  Register output() const { return output_; }
    377  Register temp() const { return temp_; }
    378  LiveRegisterSet liveRegs() const { return liveRegs_; }
    379 
    380  static JSObject* update(JSContext* cx, HandleScript outerScript,
    381                          IonBindNameIC* ic, HandleObject envChain);
    382 };
    383 
    384 class IonGetIteratorIC : public IonIC {
    385  LiveRegisterSet liveRegs_;
    386  TypedOrValueRegister value_;
    387  Register output_;
    388  Register temp1_;
    389  Register temp2_;
    390 
    391 public:
    392  IonGetIteratorIC(LiveRegisterSet liveRegs, TypedOrValueRegister value,
    393                   Register output, Register temp1, Register temp2)
    394      : IonIC(CacheKind::GetIterator),
    395        liveRegs_(liveRegs),
    396        value_(value),
    397        output_(output),
    398        temp1_(temp1),
    399        temp2_(temp2) {}
    400 
    401  TypedOrValueRegister value() const { return value_; }
    402  Register output() const { return output_; }
    403  Register temp1() const { return temp1_; }
    404  Register temp2() const { return temp2_; }
    405  LiveRegisterSet liveRegs() const { return liveRegs_; }
    406 
    407  static JSObject* update(JSContext* cx, HandleScript outerScript,
    408                          IonGetIteratorIC* ic, HandleValue value);
    409 };
    410 
    411 class IonOptimizeSpreadCallIC : public IonIC {
    412  LiveRegisterSet liveRegs_;
    413  ValueOperand value_;
    414  ValueOperand output_;
    415  Register temp_;
    416 
    417 public:
    418  IonOptimizeSpreadCallIC(LiveRegisterSet liveRegs, ValueOperand value,
    419                          ValueOperand output, Register temp)
    420      : IonIC(CacheKind::OptimizeSpreadCall),
    421        liveRegs_(liveRegs),
    422        value_(value),
    423        output_(output),
    424        temp_(temp) {}
    425 
    426  ValueOperand value() const { return value_; }
    427  ValueOperand output() const { return output_; }
    428  Register temp() const { return temp_; }
    429  LiveRegisterSet liveRegs() const { return liveRegs_; }
    430 
    431  static bool update(JSContext* cx, HandleScript outerScript,
    432                     IonOptimizeSpreadCallIC* ic, HandleValue value,
    433                     MutableHandleValue result);
    434 };
    435 
    436 class IonHasOwnIC : public IonIC {
    437  LiveRegisterSet liveRegs_;
    438 
    439  TypedOrValueRegister value_;
    440  TypedOrValueRegister id_;
    441  Register output_;
    442 
    443 public:
    444  IonHasOwnIC(LiveRegisterSet liveRegs, TypedOrValueRegister value,
    445              TypedOrValueRegister id, Register output)
    446      : IonIC(CacheKind::HasOwn),
    447        liveRegs_(liveRegs),
    448        value_(value),
    449        id_(id),
    450        output_(output) {}
    451 
    452  TypedOrValueRegister value() const { return value_; }
    453  TypedOrValueRegister id() const { return id_; }
    454  Register output() const { return output_; }
    455  LiveRegisterSet liveRegs() const { return liveRegs_; }
    456 
    457  [[nodiscard]] static bool update(JSContext* cx, HandleScript outerScript,
    458                                   IonHasOwnIC* ic, HandleValue val,
    459                                   HandleValue idVal, int32_t* res);
    460 };
    461 
    462 class IonCheckPrivateFieldIC : public IonIC {
    463  LiveRegisterSet liveRegs_;
    464 
    465  TypedOrValueRegister value_;
    466  TypedOrValueRegister id_;
    467  Register output_;
    468 
    469 public:
    470  IonCheckPrivateFieldIC(LiveRegisterSet liveRegs, TypedOrValueRegister value,
    471                         TypedOrValueRegister id, Register output)
    472      : IonIC(CacheKind::CheckPrivateField),
    473        liveRegs_(liveRegs),
    474        value_(value),
    475        id_(id),
    476        output_(output) {}
    477 
    478  TypedOrValueRegister value() const { return value_; }
    479  TypedOrValueRegister id() const { return id_; }
    480  Register output() const { return output_; }
    481  LiveRegisterSet liveRegs() const { return liveRegs_; }
    482 
    483  [[nodiscard]] static bool update(JSContext* cx, HandleScript outerScript,
    484                                   IonCheckPrivateFieldIC* ic, HandleValue val,
    485                                   HandleValue idVal, bool* res);
    486 };
    487 
    488 class IonInIC : public IonIC {
    489  LiveRegisterSet liveRegs_;
    490 
    491  ConstantOrRegister key_;
    492  Register object_;
    493  Register output_;
    494  Register temp_;
    495 
    496 public:
    497  IonInIC(LiveRegisterSet liveRegs, const ConstantOrRegister& key,
    498          Register object, Register output, Register temp)
    499      : IonIC(CacheKind::In),
    500        liveRegs_(liveRegs),
    501        key_(key),
    502        object_(object),
    503        output_(output),
    504        temp_(temp) {}
    505 
    506  ConstantOrRegister key() const { return key_; }
    507  Register object() const { return object_; }
    508  Register output() const { return output_; }
    509  Register temp() const { return temp_; }
    510  LiveRegisterSet liveRegs() const { return liveRegs_; }
    511 
    512  [[nodiscard]] static bool update(JSContext* cx, HandleScript outerScript,
    513                                   IonInIC* ic, HandleValue key,
    514                                   HandleObject obj, bool* res);
    515 };
    516 
    517 class IonInstanceOfIC : public IonIC {
    518  LiveRegisterSet liveRegs_;
    519 
    520  TypedOrValueRegister lhs_;
    521  Register rhs_;
    522  Register output_;
    523 
    524 public:
    525  IonInstanceOfIC(LiveRegisterSet liveRegs, TypedOrValueRegister lhs,
    526                  Register rhs, Register output)
    527      : IonIC(CacheKind::InstanceOf),
    528        liveRegs_(liveRegs),
    529        lhs_(lhs),
    530        rhs_(rhs),
    531        output_(output) {}
    532 
    533  LiveRegisterSet liveRegs() const { return liveRegs_; }
    534  TypedOrValueRegister lhs() const { return lhs_; }
    535  Register rhs() const { return rhs_; }
    536  Register output() const { return output_; }
    537 
    538  // This signature mimics that of TryAttachInstanceOfStub in baseline
    539  [[nodiscard]] static bool update(JSContext* cx, HandleScript outerScript,
    540                                   IonInstanceOfIC* ic, HandleValue lhs,
    541                                   HandleObject rhs, bool* attached);
    542 };
    543 
    544 class IonCompareIC : public IonIC {
    545  LiveRegisterSet liveRegs_;
    546 
    547  TypedOrValueRegister lhs_;
    548  TypedOrValueRegister rhs_;
    549  Register output_;
    550 
    551 public:
    552  IonCompareIC(LiveRegisterSet liveRegs, TypedOrValueRegister lhs,
    553               TypedOrValueRegister rhs, Register output)
    554      : IonIC(CacheKind::Compare),
    555        liveRegs_(liveRegs),
    556        lhs_(lhs),
    557        rhs_(rhs),
    558        output_(output) {}
    559 
    560  LiveRegisterSet liveRegs() const { return liveRegs_; }
    561  TypedOrValueRegister lhs() const { return lhs_; }
    562  TypedOrValueRegister rhs() const { return rhs_; }
    563  Register output() const { return output_; }
    564 
    565  [[nodiscard]] static bool update(JSContext* cx, HandleScript outerScript,
    566                                   IonCompareIC* stub, HandleValue lhs,
    567                                   HandleValue rhs, bool* res);
    568 };
    569 
    570 class IonUnaryArithIC : public IonIC {
    571  LiveRegisterSet liveRegs_;
    572 
    573  TypedOrValueRegister input_;
    574  ValueOperand output_;
    575 
    576 public:
    577  IonUnaryArithIC(LiveRegisterSet liveRegs, TypedOrValueRegister input,
    578                  ValueOperand output)
    579      : IonIC(CacheKind::UnaryArith),
    580        liveRegs_(liveRegs),
    581        input_(input),
    582        output_(output) {}
    583 
    584  LiveRegisterSet liveRegs() const { return liveRegs_; }
    585  TypedOrValueRegister input() const { return input_; }
    586  ValueOperand output() const { return output_; }
    587 
    588  [[nodiscard]] static bool update(JSContext* cx, HandleScript outerScript,
    589                                   IonUnaryArithIC* stub, HandleValue val,
    590                                   MutableHandleValue res);
    591 };
    592 
    593 class IonToPropertyKeyIC : public IonIC {
    594  LiveRegisterSet liveRegs_;
    595  ValueOperand input_;
    596  ValueOperand output_;
    597 
    598 public:
    599  IonToPropertyKeyIC(LiveRegisterSet liveRegs, ValueOperand input,
    600                     ValueOperand output)
    601      : IonIC(CacheKind::ToPropertyKey),
    602        liveRegs_(liveRegs),
    603        input_(input),
    604        output_(output) {}
    605 
    606  LiveRegisterSet liveRegs() const { return liveRegs_; }
    607  ValueOperand input() const { return input_; }
    608  ValueOperand output() const { return output_; }
    609 
    610  [[nodiscard]] static bool update(JSContext* cx, HandleScript outerScript,
    611                                   IonToPropertyKeyIC* ic, HandleValue val,
    612                                   MutableHandleValue res);
    613 };
    614 
    615 class IonBinaryArithIC : public IonIC {
    616  LiveRegisterSet liveRegs_;
    617 
    618  TypedOrValueRegister lhs_;
    619  TypedOrValueRegister rhs_;
    620  ValueOperand output_;
    621 
    622 public:
    623  IonBinaryArithIC(LiveRegisterSet liveRegs, TypedOrValueRegister lhs,
    624                   TypedOrValueRegister rhs, ValueOperand output)
    625      : IonIC(CacheKind::BinaryArith),
    626        liveRegs_(liveRegs),
    627        lhs_(lhs),
    628        rhs_(rhs),
    629        output_(output) {}
    630 
    631  LiveRegisterSet liveRegs() const { return liveRegs_; }
    632  TypedOrValueRegister lhs() const { return lhs_; }
    633  TypedOrValueRegister rhs() const { return rhs_; }
    634  ValueOperand output() const { return output_; }
    635 
    636  [[nodiscard]] static bool update(JSContext* cx, HandleScript outerScript,
    637                                   IonBinaryArithIC* stub, HandleValue lhs,
    638                                   HandleValue rhs, MutableHandleValue res);
    639 };
    640 
    641 class IonCloseIterIC : public IonIC {
    642  LiveRegisterSet liveRegs_;
    643 
    644  Register iter_;
    645  Register temp_;
    646  CompletionKind completionKind_;
    647 
    648 public:
    649  IonCloseIterIC(LiveRegisterSet liveRegs, Register iter, Register temp,
    650                 CompletionKind completionKind)
    651      : IonIC(CacheKind::CloseIter),
    652        liveRegs_(liveRegs),
    653        iter_(iter),
    654        temp_(temp),
    655        completionKind_(completionKind) {}
    656 
    657  LiveRegisterSet liveRegs() const { return liveRegs_; }
    658  Register temp() const { return temp_; }
    659  Register iter() const { return iter_; }
    660  CompletionKind completionKind() const { return completionKind_; }
    661 
    662  [[nodiscard]] static bool update(JSContext* cx, HandleScript outerScript,
    663                                   IonCloseIterIC* ic, HandleObject iter);
    664 };
    665 
    666 class IonOptimizeGetIteratorIC : public IonIC {
    667  LiveRegisterSet liveRegs_;
    668  ValueOperand value_;
    669  Register output_;
    670  Register temp_;
    671 
    672 public:
    673  IonOptimizeGetIteratorIC(LiveRegisterSet liveRegs, ValueOperand value,
    674                           Register output, Register temp)
    675      : IonIC(CacheKind::OptimizeGetIterator),
    676        liveRegs_(liveRegs),
    677        value_(value),
    678        output_(output),
    679        temp_(temp) {}
    680 
    681  ValueOperand value() const { return value_; }
    682  Register output() const { return output_; }
    683  Register temp() const { return temp_; }
    684  LiveRegisterSet liveRegs() const { return liveRegs_; }
    685 
    686  static bool update(JSContext* cx, HandleScript outerScript,
    687                     IonOptimizeGetIteratorIC* ic, HandleValue value,
    688                     bool* result);
    689 };
    690 
    691 }  // namespace jit
    692 }  // namespace js
    693 
    694 #endif /* jit_IonIC_h */