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