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 */