js/src/jit/LIR-Common.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef jit_LIR_Common_h
michael@0 8 #define jit_LIR_Common_h
michael@0 9
michael@0 10 #include "jit/shared/Assembler-shared.h"
michael@0 11
michael@0 12 // This file declares LIR instructions that are common to every platform.
michael@0 13
michael@0 14 namespace js {
michael@0 15 namespace jit {
michael@0 16
michael@0 17 class Range;
michael@0 18
michael@0 19 template <size_t Temps, size_t ExtraUses = 0>
michael@0 20 class LBinaryMath : public LInstructionHelper<1, 2 + ExtraUses, Temps>
michael@0 21 {
michael@0 22 public:
michael@0 23 const LAllocation *lhs() {
michael@0 24 return this->getOperand(0);
michael@0 25 }
michael@0 26 const LAllocation *rhs() {
michael@0 27 return this->getOperand(1);
michael@0 28 }
michael@0 29 };
michael@0 30
michael@0 31 // Simplifies register allocation since the first instruction of a block is
michael@0 32 // guaranteed to have no uses.
michael@0 33 class LLabel : public LInstructionHelper<0, 0, 0>
michael@0 34 {
michael@0 35 public:
michael@0 36 LIR_HEADER(Label)
michael@0 37 };
michael@0 38
michael@0 39 class LNop : public LInstructionHelper<0, 0, 0>
michael@0 40 {
michael@0 41 public:
michael@0 42 LIR_HEADER(Nop)
michael@0 43 };
michael@0 44
michael@0 45 // An LOsiPoint captures a snapshot after a call and ensures enough space to
michael@0 46 // patch in a call to the invalidation mechanism.
michael@0 47 //
michael@0 48 // Note: LSafepoints are 1:1 with LOsiPoints, so it holds a reference to the
michael@0 49 // corresponding LSafepoint to inform it of the LOsiPoint's masm offset when it
michael@0 50 // gets CG'd.
michael@0 51 class LOsiPoint : public LInstructionHelper<0, 0, 0>
michael@0 52 {
michael@0 53 LSafepoint *safepoint_;
michael@0 54
michael@0 55 public:
michael@0 56 LOsiPoint(LSafepoint *safepoint, LSnapshot *snapshot)
michael@0 57 : safepoint_(safepoint)
michael@0 58 {
michael@0 59 JS_ASSERT(safepoint && snapshot);
michael@0 60 assignSnapshot(snapshot);
michael@0 61 }
michael@0 62
michael@0 63 LSafepoint *associatedSafepoint() {
michael@0 64 return safepoint_;
michael@0 65 }
michael@0 66
michael@0 67 LIR_HEADER(OsiPoint)
michael@0 68 };
michael@0 69
michael@0 70 class LMove
michael@0 71 {
michael@0 72 LAllocation *from_;
michael@0 73 LAllocation *to_;
michael@0 74 LDefinition::Type type_;
michael@0 75
michael@0 76 public:
michael@0 77 LMove(LAllocation *from, LAllocation *to, LDefinition::Type type)
michael@0 78 : from_(from),
michael@0 79 to_(to),
michael@0 80 type_(type)
michael@0 81 { }
michael@0 82
michael@0 83 LAllocation *from() {
michael@0 84 return from_;
michael@0 85 }
michael@0 86 const LAllocation *from() const {
michael@0 87 return from_;
michael@0 88 }
michael@0 89 LAllocation *to() {
michael@0 90 return to_;
michael@0 91 }
michael@0 92 const LAllocation *to() const {
michael@0 93 return to_;
michael@0 94 }
michael@0 95 LDefinition::Type type() const {
michael@0 96 return type_;
michael@0 97 }
michael@0 98 };
michael@0 99
michael@0 100 class LMoveGroup : public LInstructionHelper<0, 0, 0>
michael@0 101 {
michael@0 102 js::Vector<LMove, 2, IonAllocPolicy> moves_;
michael@0 103
michael@0 104 LMoveGroup(TempAllocator &alloc)
michael@0 105 : moves_(alloc)
michael@0 106 { }
michael@0 107
michael@0 108 public:
michael@0 109 LIR_HEADER(MoveGroup)
michael@0 110
michael@0 111 static LMoveGroup *New(TempAllocator &alloc) {
michael@0 112 return new(alloc) LMoveGroup(alloc);
michael@0 113 }
michael@0 114
michael@0 115 void printOperands(FILE *fp);
michael@0 116
michael@0 117 // Add a move which takes place simultaneously with all others in the group.
michael@0 118 bool add(LAllocation *from, LAllocation *to, LDefinition::Type type);
michael@0 119
michael@0 120 // Add a move which takes place after existing moves in the group.
michael@0 121 bool addAfter(LAllocation *from, LAllocation *to, LDefinition::Type type);
michael@0 122
michael@0 123 size_t numMoves() const {
michael@0 124 return moves_.length();
michael@0 125 }
michael@0 126 const LMove &getMove(size_t i) const {
michael@0 127 return moves_[i];
michael@0 128 }
michael@0 129 };
michael@0 130
michael@0 131 // Constant 32-bit integer.
michael@0 132 class LInteger : public LInstructionHelper<1, 0, 0>
michael@0 133 {
michael@0 134 int32_t i32_;
michael@0 135
michael@0 136 public:
michael@0 137 LIR_HEADER(Integer)
michael@0 138
michael@0 139 LInteger(int32_t i32)
michael@0 140 : i32_(i32)
michael@0 141 { }
michael@0 142
michael@0 143 int32_t getValue() const {
michael@0 144 return i32_;
michael@0 145 }
michael@0 146 };
michael@0 147
michael@0 148 // Constant pointer.
michael@0 149 class LPointer : public LInstructionHelper<1, 0, 0>
michael@0 150 {
michael@0 151 public:
michael@0 152 enum Kind {
michael@0 153 GC_THING,
michael@0 154 NON_GC_THING
michael@0 155 };
michael@0 156
michael@0 157 private:
michael@0 158 void *ptr_;
michael@0 159 Kind kind_;
michael@0 160
michael@0 161 public:
michael@0 162 LIR_HEADER(Pointer)
michael@0 163
michael@0 164 LPointer(gc::Cell *ptr)
michael@0 165 : ptr_(ptr), kind_(GC_THING)
michael@0 166 { }
michael@0 167
michael@0 168 LPointer(void *ptr, Kind kind)
michael@0 169 : ptr_(ptr), kind_(kind)
michael@0 170 { }
michael@0 171
michael@0 172 void *ptr() const {
michael@0 173 return ptr_;
michael@0 174 }
michael@0 175 Kind kind() const {
michael@0 176 return kind_;
michael@0 177 }
michael@0 178 const char *extraName() const {
michael@0 179 return kind_ == GC_THING ? "GC_THING" : "NON_GC_THING";
michael@0 180 }
michael@0 181
michael@0 182 gc::Cell *gcptr() const {
michael@0 183 JS_ASSERT(kind() == GC_THING);
michael@0 184 return (gc::Cell *) ptr_;
michael@0 185 }
michael@0 186 };
michael@0 187
michael@0 188 // Constant double.
michael@0 189 class LDouble : public LInstructionHelper<1, 0, 0>
michael@0 190 {
michael@0 191 double d_;
michael@0 192 public:
michael@0 193 LIR_HEADER(Double);
michael@0 194
michael@0 195 LDouble(double d) : d_(d)
michael@0 196 { }
michael@0 197 double getDouble() const {
michael@0 198 return d_;
michael@0 199 }
michael@0 200 };
michael@0 201
michael@0 202 // Constant float32.
michael@0 203 class LFloat32 : public LInstructionHelper<1, 0, 0>
michael@0 204 {
michael@0 205 float f_;
michael@0 206 public:
michael@0 207 LIR_HEADER(Float32);
michael@0 208
michael@0 209 LFloat32(float f)
michael@0 210 : f_(f)
michael@0 211 { }
michael@0 212
michael@0 213 float getFloat() const {
michael@0 214 return f_;
michael@0 215 }
michael@0 216 };
michael@0 217
michael@0 218 // A constant Value.
michael@0 219 class LValue : public LInstructionHelper<BOX_PIECES, 0, 0>
michael@0 220 {
michael@0 221 Value v_;
michael@0 222
michael@0 223 public:
michael@0 224 LIR_HEADER(Value)
michael@0 225
michael@0 226 LValue(const Value &v)
michael@0 227 : v_(v)
michael@0 228 { }
michael@0 229
michael@0 230 Value value() const {
michael@0 231 return v_;
michael@0 232 }
michael@0 233 };
michael@0 234
michael@0 235 // Clone an object literal such as we are not modifying the object contained in
michael@0 236 // the sources.
michael@0 237 class LCloneLiteral : public LCallInstructionHelper<1, 1, 0>
michael@0 238 {
michael@0 239 public:
michael@0 240 LIR_HEADER(CloneLiteral)
michael@0 241
michael@0 242 LCloneLiteral(const LAllocation &obj)
michael@0 243 {
michael@0 244 setOperand(0, obj);
michael@0 245 }
michael@0 246
michael@0 247 const LAllocation *getObjectLiteral() {
michael@0 248 return getOperand(0);
michael@0 249 }
michael@0 250
michael@0 251 MCloneLiteral *mir() const {
michael@0 252 return mir_->toCloneLiteral();
michael@0 253 }
michael@0 254 };
michael@0 255
michael@0 256 // Formal argument for a function, returning a box. Formal arguments are
michael@0 257 // initially read from the stack.
michael@0 258 class LParameter : public LInstructionHelper<BOX_PIECES, 0, 0>
michael@0 259 {
michael@0 260 public:
michael@0 261 LIR_HEADER(Parameter)
michael@0 262 };
michael@0 263
michael@0 264 // Stack offset for a word-sized immutable input value to a frame.
michael@0 265 class LCallee : public LInstructionHelper<1, 0, 0>
michael@0 266 {
michael@0 267 public:
michael@0 268 LIR_HEADER(Callee)
michael@0 269 };
michael@0 270
michael@0 271 // Base class for control instructions (goto, branch, etc.)
michael@0 272 template <size_t Succs, size_t Operands, size_t Temps>
michael@0 273 class LControlInstructionHelper : public LInstructionHelper<0, Operands, Temps> {
michael@0 274
michael@0 275 mozilla::Array<MBasicBlock *, Succs> successors_;
michael@0 276
michael@0 277 public:
michael@0 278 virtual size_t numSuccessors() const MOZ_FINAL MOZ_OVERRIDE { return Succs; }
michael@0 279
michael@0 280 virtual MBasicBlock *getSuccessor(size_t i) const MOZ_FINAL MOZ_OVERRIDE {
michael@0 281 return successors_[i];
michael@0 282 }
michael@0 283
michael@0 284 virtual void setSuccessor(size_t i, MBasicBlock *successor) MOZ_FINAL MOZ_OVERRIDE {
michael@0 285 successors_[i] = successor;
michael@0 286 }
michael@0 287 };
michael@0 288
michael@0 289 // Jumps to the start of a basic block.
michael@0 290 class LGoto : public LControlInstructionHelper<1, 0, 0>
michael@0 291 {
michael@0 292 public:
michael@0 293 LIR_HEADER(Goto)
michael@0 294
michael@0 295 LGoto(MBasicBlock *block)
michael@0 296 {
michael@0 297 setSuccessor(0, block);
michael@0 298 }
michael@0 299
michael@0 300 MBasicBlock *target() const {
michael@0 301 return getSuccessor(0);
michael@0 302 }
michael@0 303 };
michael@0 304
michael@0 305 class LNewSlots : public LCallInstructionHelper<1, 0, 3>
michael@0 306 {
michael@0 307 public:
michael@0 308 LIR_HEADER(NewSlots)
michael@0 309
michael@0 310 LNewSlots(const LDefinition &temp1, const LDefinition &temp2, const LDefinition &temp3) {
michael@0 311 setTemp(0, temp1);
michael@0 312 setTemp(1, temp2);
michael@0 313 setTemp(2, temp3);
michael@0 314 }
michael@0 315
michael@0 316 const LDefinition *temp1() {
michael@0 317 return getTemp(0);
michael@0 318 }
michael@0 319 const LDefinition *temp2() {
michael@0 320 return getTemp(1);
michael@0 321 }
michael@0 322 const LDefinition *temp3() {
michael@0 323 return getTemp(2);
michael@0 324 }
michael@0 325
michael@0 326 MNewSlots *mir() const {
michael@0 327 return mir_->toNewSlots();
michael@0 328 }
michael@0 329 };
michael@0 330
michael@0 331 class LNewArray : public LInstructionHelper<1, 0, 1>
michael@0 332 {
michael@0 333 public:
michael@0 334 LIR_HEADER(NewArray)
michael@0 335
michael@0 336 LNewArray(const LDefinition &temp) {
michael@0 337 setTemp(0, temp);
michael@0 338 }
michael@0 339
michael@0 340 const char *extraName() const {
michael@0 341 return mir()->shouldUseVM() ? "VMCall" : nullptr;
michael@0 342 }
michael@0 343
michael@0 344 const LDefinition *temp() {
michael@0 345 return getTemp(0);
michael@0 346 }
michael@0 347
michael@0 348 MNewArray *mir() const {
michael@0 349 return mir_->toNewArray();
michael@0 350 }
michael@0 351 };
michael@0 352
michael@0 353 class LNewObject : public LInstructionHelper<1, 0, 1>
michael@0 354 {
michael@0 355 public:
michael@0 356 LIR_HEADER(NewObject)
michael@0 357
michael@0 358 LNewObject(const LDefinition &temp) {
michael@0 359 setTemp(0, temp);
michael@0 360 }
michael@0 361
michael@0 362 const char *extraName() const {
michael@0 363 return mir()->shouldUseVM() ? "VMCall" : nullptr;
michael@0 364 }
michael@0 365
michael@0 366 const LDefinition *temp() {
michael@0 367 return getTemp(0);
michael@0 368 }
michael@0 369
michael@0 370 MNewObject *mir() const {
michael@0 371 return mir_->toNewObject();
michael@0 372 }
michael@0 373 };
michael@0 374
michael@0 375 class LNewPar : public LInstructionHelper<1, 1, 2>
michael@0 376 {
michael@0 377 public:
michael@0 378 LIR_HEADER(NewPar);
michael@0 379
michael@0 380 LNewPar(const LAllocation &cx, const LDefinition &temp1, const LDefinition &temp2) {
michael@0 381 setOperand(0, cx);
michael@0 382 setTemp(0, temp1);
michael@0 383 setTemp(1, temp2);
michael@0 384 }
michael@0 385
michael@0 386 MNewPar *mir() const {
michael@0 387 return mir_->toNewPar();
michael@0 388 }
michael@0 389
michael@0 390 const LAllocation *forkJoinContext() {
michael@0 391 return getOperand(0);
michael@0 392 }
michael@0 393
michael@0 394 const LDefinition *getTemp0() {
michael@0 395 return getTemp(0);
michael@0 396 }
michael@0 397
michael@0 398 const LDefinition *getTemp1() {
michael@0 399 return getTemp(1);
michael@0 400 }
michael@0 401 };
michael@0 402
michael@0 403 class LNewDenseArrayPar : public LCallInstructionHelper<1, 2, 3>
michael@0 404 {
michael@0 405 public:
michael@0 406 LIR_HEADER(NewDenseArrayPar);
michael@0 407
michael@0 408 LNewDenseArrayPar(const LAllocation &cx, const LAllocation &length,
michael@0 409 const LDefinition &temp1, const LDefinition &temp2, const LDefinition &temp3)
michael@0 410 {
michael@0 411 setOperand(0, cx);
michael@0 412 setOperand(1, length);
michael@0 413 setTemp(0, temp1);
michael@0 414 setTemp(1, temp2);
michael@0 415 setTemp(2, temp3);
michael@0 416 }
michael@0 417
michael@0 418 MNewDenseArrayPar *mir() const {
michael@0 419 return mir_->toNewDenseArrayPar();
michael@0 420 }
michael@0 421
michael@0 422 const LAllocation *forkJoinContext() {
michael@0 423 return getOperand(0);
michael@0 424 }
michael@0 425
michael@0 426 const LAllocation *length() {
michael@0 427 return getOperand(1);
michael@0 428 }
michael@0 429
michael@0 430 const LDefinition *getTemp0() {
michael@0 431 return getTemp(0);
michael@0 432 }
michael@0 433
michael@0 434 const LDefinition *getTemp1() {
michael@0 435 return getTemp(1);
michael@0 436 }
michael@0 437
michael@0 438 const LDefinition *getTemp2() {
michael@0 439 return getTemp(2);
michael@0 440 }
michael@0 441 };
michael@0 442
michael@0 443 // Allocates a new DeclEnvObject.
michael@0 444 //
michael@0 445 // This instruction generates two possible instruction sets:
michael@0 446 // (1) An inline allocation of the call object is attempted.
michael@0 447 // (2) Otherwise, a callVM create a new object.
michael@0 448 //
michael@0 449 class LNewDeclEnvObject : public LInstructionHelper<1, 0, 1>
michael@0 450 {
michael@0 451 public:
michael@0 452 LIR_HEADER(NewDeclEnvObject);
michael@0 453
michael@0 454 LNewDeclEnvObject(const LDefinition &temp) {
michael@0 455 setTemp(0, temp);
michael@0 456 }
michael@0 457
michael@0 458 const LDefinition *temp() {
michael@0 459 return getTemp(0);
michael@0 460 }
michael@0 461
michael@0 462 MNewDeclEnvObject *mir() const {
michael@0 463 return mir_->toNewDeclEnvObject();
michael@0 464 }
michael@0 465 };
michael@0 466
michael@0 467 // Allocates a new CallObject. The inputs are:
michael@0 468 // slots: either a reg representing a HeapSlot *, or a placeholder
michael@0 469 // meaning that no slots pointer is needed.
michael@0 470 //
michael@0 471 // This instruction generates two possible instruction sets:
michael@0 472 // (1) If the call object is extensible, this is a callVM to create the
michael@0 473 // call object.
michael@0 474 // (2) Otherwise, an inline allocation of the call object is attempted.
michael@0 475 //
michael@0 476 class LNewCallObject : public LInstructionHelper<1, 1, 1>
michael@0 477 {
michael@0 478 public:
michael@0 479 LIR_HEADER(NewCallObject)
michael@0 480
michael@0 481 LNewCallObject(const LAllocation &slots, const LDefinition &temp) {
michael@0 482 setOperand(0, slots);
michael@0 483 setTemp(0, temp);
michael@0 484 }
michael@0 485
michael@0 486 const LDefinition *temp() {
michael@0 487 return getTemp(0);
michael@0 488 }
michael@0 489
michael@0 490 const LAllocation *slots() {
michael@0 491 return getOperand(0);
michael@0 492 }
michael@0 493
michael@0 494 MNewCallObject *mir() const {
michael@0 495 return mir_->toNewCallObject();
michael@0 496 }
michael@0 497 };
michael@0 498
michael@0 499 // Allocates a new CallObject with singleton type through an out-of-line VM
michael@0 500 // call. The inputs are:
michael@0 501 // slots: either a reg representing a HeapSlot *, or a placeholder
michael@0 502 // meaning that no slots pointer is needed.
michael@0 503 //
michael@0 504 class LNewSingletonCallObject : public LInstructionHelper<1, 1, 0>
michael@0 505 {
michael@0 506 public:
michael@0 507 LIR_HEADER(NewSingletonCallObject)
michael@0 508
michael@0 509 LNewSingletonCallObject(const LAllocation &slots) {
michael@0 510 setOperand(0, slots);
michael@0 511 }
michael@0 512
michael@0 513 const LAllocation *slots() {
michael@0 514 return getOperand(0);
michael@0 515 }
michael@0 516
michael@0 517 MNewCallObjectBase * mir() const {
michael@0 518 MOZ_ASSERT(mir_->isNewCallObject() || mir_->isNewRunOnceCallObject());
michael@0 519 return static_cast<MNewCallObjectBase *>(mir_);
michael@0 520 }
michael@0 521 };
michael@0 522
michael@0 523 class LNewCallObjectPar : public LInstructionHelper<1, 2, 2>
michael@0 524 {
michael@0 525 LNewCallObjectPar(const LAllocation &cx, const LAllocation &slots,
michael@0 526 const LDefinition &temp1, const LDefinition &temp2)
michael@0 527 {
michael@0 528 setOperand(0, cx);
michael@0 529 setOperand(1, slots);
michael@0 530 setTemp(0, temp1);
michael@0 531 setTemp(1, temp2);
michael@0 532 }
michael@0 533
michael@0 534 public:
michael@0 535 LIR_HEADER(NewCallObjectPar);
michael@0 536
michael@0 537 static LNewCallObjectPar *NewWithSlots(TempAllocator &alloc,
michael@0 538 const LAllocation &cx, const LAllocation &slots,
michael@0 539 const LDefinition &temp1, const LDefinition &temp2)
michael@0 540 {
michael@0 541 return new(alloc) LNewCallObjectPar(cx, slots, temp1, temp2);
michael@0 542 }
michael@0 543
michael@0 544 static LNewCallObjectPar *NewSansSlots(TempAllocator &alloc,
michael@0 545 const LAllocation &cx,
michael@0 546 const LDefinition &temp1, const LDefinition &temp2)
michael@0 547 {
michael@0 548 LAllocation slots = LConstantIndex::Bogus();
michael@0 549 return new(alloc) LNewCallObjectPar(cx, slots, temp1, temp2);
michael@0 550 }
michael@0 551
michael@0 552 const LAllocation *forkJoinContext() {
michael@0 553 return getOperand(0);
michael@0 554 }
michael@0 555
michael@0 556 const LAllocation *slots() {
michael@0 557 return getOperand(1);
michael@0 558 }
michael@0 559
michael@0 560 const bool hasDynamicSlots() {
michael@0 561 // TO INVESTIGATE: Felix tried using isRegister() method here,
michael@0 562 // but for useFixed(_, CallTempN), isRegister() is false (and
michael@0 563 // isUse() is true). So for now ignore that and try to match
michael@0 564 // the LConstantIndex::Bogus() generated above instead.
michael@0 565 return slots() && ! slots()->isConstant();
michael@0 566 }
michael@0 567
michael@0 568 const MNewCallObjectPar *mir() const {
michael@0 569 return mir_->toNewCallObjectPar();
michael@0 570 }
michael@0 571
michael@0 572 const LDefinition *getTemp0() {
michael@0 573 return getTemp(0);
michael@0 574 }
michael@0 575
michael@0 576 const LDefinition *getTemp1() {
michael@0 577 return getTemp(1);
michael@0 578 }
michael@0 579 };
michael@0 580
michael@0 581 class LNewDerivedTypedObject : public LCallInstructionHelper<1, 3, 0>
michael@0 582 {
michael@0 583 public:
michael@0 584 LIR_HEADER(NewDerivedTypedObject);
michael@0 585
michael@0 586 LNewDerivedTypedObject(const LAllocation &type,
michael@0 587 const LAllocation &owner,
michael@0 588 const LAllocation &offset) {
michael@0 589 setOperand(0, type);
michael@0 590 setOperand(1, owner);
michael@0 591 setOperand(2, offset);
michael@0 592 }
michael@0 593
michael@0 594 const LAllocation *type() {
michael@0 595 return getOperand(0);
michael@0 596 }
michael@0 597
michael@0 598 const LAllocation *owner() {
michael@0 599 return getOperand(1);
michael@0 600 }
michael@0 601
michael@0 602 const LAllocation *offset() {
michael@0 603 return getOperand(2);
michael@0 604 }
michael@0 605 };
michael@0 606
michael@0 607 class LNewStringObject : public LInstructionHelper<1, 1, 1>
michael@0 608 {
michael@0 609 public:
michael@0 610 LIR_HEADER(NewStringObject)
michael@0 611
michael@0 612 LNewStringObject(const LAllocation &input, const LDefinition &temp) {
michael@0 613 setOperand(0, input);
michael@0 614 setTemp(0, temp);
michael@0 615 }
michael@0 616
michael@0 617 const LAllocation *input() {
michael@0 618 return getOperand(0);
michael@0 619 }
michael@0 620 const LDefinition *temp() {
michael@0 621 return getTemp(0);
michael@0 622 }
michael@0 623 MNewStringObject *mir() const {
michael@0 624 return mir_->toNewStringObject();
michael@0 625 }
michael@0 626 };
michael@0 627
michael@0 628 class LAbortPar : public LInstructionHelper<0, 0, 0>
michael@0 629 {
michael@0 630 public:
michael@0 631 LIR_HEADER(AbortPar);
michael@0 632 };
michael@0 633
michael@0 634 class LInitElem : public LCallInstructionHelper<0, 1 + 2*BOX_PIECES, 0>
michael@0 635 {
michael@0 636 public:
michael@0 637 LIR_HEADER(InitElem)
michael@0 638
michael@0 639 LInitElem(const LAllocation &object) {
michael@0 640 setOperand(0, object);
michael@0 641 }
michael@0 642
michael@0 643 static const size_t IdIndex = 1;
michael@0 644 static const size_t ValueIndex = 1 + BOX_PIECES;
michael@0 645
michael@0 646 const LAllocation *getObject() {
michael@0 647 return getOperand(0);
michael@0 648 }
michael@0 649 MInitElem *mir() const {
michael@0 650 return mir_->toInitElem();
michael@0 651 }
michael@0 652 };
michael@0 653
michael@0 654 class LInitElemGetterSetter : public LCallInstructionHelper<0, 2 + BOX_PIECES, 0>
michael@0 655 {
michael@0 656 public:
michael@0 657 LIR_HEADER(InitElemGetterSetter)
michael@0 658
michael@0 659 LInitElemGetterSetter(const LAllocation &object, const LAllocation &value) {
michael@0 660 setOperand(0, object);
michael@0 661 setOperand(1, value);
michael@0 662 }
michael@0 663
michael@0 664 static const size_t IdIndex = 2;
michael@0 665
michael@0 666 const LAllocation *object() {
michael@0 667 return getOperand(0);
michael@0 668 }
michael@0 669 const LAllocation *value() {
michael@0 670 return getOperand(1);
michael@0 671 }
michael@0 672 MInitElemGetterSetter *mir() const {
michael@0 673 return mir_->toInitElemGetterSetter();
michael@0 674 }
michael@0 675 };
michael@0 676
michael@0 677 // Takes in an Object and a Value.
michael@0 678 class LMutateProto : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
michael@0 679 {
michael@0 680 public:
michael@0 681 LIR_HEADER(MutateProto)
michael@0 682
michael@0 683 LMutateProto(const LAllocation &object) {
michael@0 684 setOperand(0, object);
michael@0 685 }
michael@0 686
michael@0 687 static const size_t ValueIndex = 1;
michael@0 688
michael@0 689 const LAllocation *getObject() {
michael@0 690 return getOperand(0);
michael@0 691 }
michael@0 692 const LAllocation *getValue() {
michael@0 693 return getOperand(1);
michael@0 694 }
michael@0 695 };
michael@0 696
michael@0 697 // Takes in an Object and a Value.
michael@0 698 class LInitProp : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
michael@0 699 {
michael@0 700 public:
michael@0 701 LIR_HEADER(InitProp)
michael@0 702
michael@0 703 LInitProp(const LAllocation &object) {
michael@0 704 setOperand(0, object);
michael@0 705 }
michael@0 706
michael@0 707 static const size_t ValueIndex = 1;
michael@0 708
michael@0 709 const LAllocation *getObject() {
michael@0 710 return getOperand(0);
michael@0 711 }
michael@0 712 const LAllocation *getValue() {
michael@0 713 return getOperand(1);
michael@0 714 }
michael@0 715
michael@0 716 MInitProp *mir() const {
michael@0 717 return mir_->toInitProp();
michael@0 718 }
michael@0 719 };
michael@0 720
michael@0 721 class LInitPropGetterSetter : public LCallInstructionHelper<0, 2, 0>
michael@0 722 {
michael@0 723 public:
michael@0 724 LIR_HEADER(InitPropGetterSetter)
michael@0 725
michael@0 726 LInitPropGetterSetter(const LAllocation &object, const LAllocation &value) {
michael@0 727 setOperand(0, object);
michael@0 728 setOperand(1, value);
michael@0 729 }
michael@0 730
michael@0 731 const LAllocation *object() {
michael@0 732 return getOperand(0);
michael@0 733 }
michael@0 734 const LAllocation *value() {
michael@0 735 return getOperand(1);
michael@0 736 }
michael@0 737
michael@0 738 MInitPropGetterSetter *mir() const {
michael@0 739 return mir_->toInitPropGetterSetter();
michael@0 740 }
michael@0 741 };
michael@0 742
michael@0 743 class LCheckOverRecursed : public LInstructionHelper<0, 0, 0>
michael@0 744 {
michael@0 745 public:
michael@0 746 LIR_HEADER(CheckOverRecursed)
michael@0 747
michael@0 748 LCheckOverRecursed()
michael@0 749 { }
michael@0 750 };
michael@0 751
michael@0 752 class LCheckOverRecursedPar : public LInstructionHelper<0, 1, 1>
michael@0 753 {
michael@0 754 public:
michael@0 755 LIR_HEADER(CheckOverRecursedPar);
michael@0 756
michael@0 757 LCheckOverRecursedPar(const LAllocation &cx, const LDefinition &tempReg) {
michael@0 758 setOperand(0, cx);
michael@0 759 setTemp(0, tempReg);
michael@0 760 }
michael@0 761
michael@0 762 const LAllocation *forkJoinContext() {
michael@0 763 return getOperand(0);
michael@0 764 }
michael@0 765
michael@0 766 const LDefinition *getTempReg() {
michael@0 767 return getTemp(0);
michael@0 768 }
michael@0 769 };
michael@0 770
michael@0 771 // Alternative to LInterruptCheck which does not emit an explicit check of the
michael@0 772 // interrupt flag but relies on the loop backedge being patched via a signal
michael@0 773 // handler.
michael@0 774 class LInterruptCheckImplicit : public LInstructionHelper<0, 0, 0>
michael@0 775 {
michael@0 776 Label *oolEntry_;
michael@0 777
michael@0 778 public:
michael@0 779 LIR_HEADER(InterruptCheckImplicit)
michael@0 780
michael@0 781 LInterruptCheckImplicit()
michael@0 782 : oolEntry_(nullptr)
michael@0 783 {}
michael@0 784
michael@0 785 Label *oolEntry() {
michael@0 786 return oolEntry_;
michael@0 787 }
michael@0 788
michael@0 789 void setOolEntry(Label *oolEntry) {
michael@0 790 oolEntry_ = oolEntry;
michael@0 791 }
michael@0 792 };
michael@0 793
michael@0 794 class LInterruptCheckPar : public LInstructionHelper<0, 1, 1>
michael@0 795 {
michael@0 796 public:
michael@0 797 LIR_HEADER(InterruptCheckPar);
michael@0 798
michael@0 799 LInterruptCheckPar(const LAllocation &cx, const LDefinition &tempReg) {
michael@0 800 setOperand(0, cx);
michael@0 801 setTemp(0, tempReg);
michael@0 802 }
michael@0 803
michael@0 804 const LAllocation *forkJoinContext() {
michael@0 805 return getOperand(0);
michael@0 806 }
michael@0 807
michael@0 808 const LDefinition *getTempReg() {
michael@0 809 return getTemp(0);
michael@0 810 }
michael@0 811 };
michael@0 812
michael@0 813 class LDefVar : public LCallInstructionHelper<0, 1, 0>
michael@0 814 {
michael@0 815 public:
michael@0 816 LIR_HEADER(DefVar)
michael@0 817
michael@0 818 LDefVar(const LAllocation &scopeChain)
michael@0 819 {
michael@0 820 setOperand(0, scopeChain);
michael@0 821 }
michael@0 822
michael@0 823 const LAllocation *scopeChain() {
michael@0 824 return getOperand(0);
michael@0 825 }
michael@0 826 MDefVar *mir() const {
michael@0 827 return mir_->toDefVar();
michael@0 828 }
michael@0 829 };
michael@0 830
michael@0 831 class LDefFun : public LCallInstructionHelper<0, 1, 0>
michael@0 832 {
michael@0 833 public:
michael@0 834 LIR_HEADER(DefFun)
michael@0 835
michael@0 836 LDefFun(const LAllocation &scopeChain)
michael@0 837 {
michael@0 838 setOperand(0, scopeChain);
michael@0 839 }
michael@0 840
michael@0 841 const LAllocation *scopeChain() {
michael@0 842 return getOperand(0);
michael@0 843 }
michael@0 844 MDefFun *mir() const {
michael@0 845 return mir_->toDefFun();
michael@0 846 }
michael@0 847 };
michael@0 848
michael@0 849 class LTypeOfV : public LInstructionHelper<1, BOX_PIECES, 1>
michael@0 850 {
michael@0 851 public:
michael@0 852 LIR_HEADER(TypeOfV)
michael@0 853
michael@0 854 LTypeOfV(const LDefinition &tempToUnbox) {
michael@0 855 setTemp(0, tempToUnbox);
michael@0 856 }
michael@0 857
michael@0 858 static const size_t Input = 0;
michael@0 859
michael@0 860 const LDefinition *tempToUnbox() {
michael@0 861 return getTemp(0);
michael@0 862 }
michael@0 863
michael@0 864 MTypeOf *mir() const {
michael@0 865 return mir_->toTypeOf();
michael@0 866 }
michael@0 867 };
michael@0 868
michael@0 869 class LToIdV : public LInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 1>
michael@0 870 {
michael@0 871 public:
michael@0 872 LIR_HEADER(ToIdV)
michael@0 873
michael@0 874 LToIdV(const LDefinition &temp)
michael@0 875 {
michael@0 876 setTemp(0, temp);
michael@0 877 }
michael@0 878
michael@0 879 static const size_t Object = 0;
michael@0 880 static const size_t Index = BOX_PIECES;
michael@0 881
michael@0 882 MToId *mir() const {
michael@0 883 return mir_->toToId();
michael@0 884 }
michael@0 885
michael@0 886 const LDefinition *tempFloat() {
michael@0 887 return getTemp(0);
michael@0 888 }
michael@0 889 };
michael@0 890
michael@0 891 // Allocate an object for |new| on the caller-side,
michael@0 892 // when there is no templateObject or prototype known
michael@0 893 class LCreateThis : public LCallInstructionHelper<BOX_PIECES, 1, 0>
michael@0 894 {
michael@0 895 public:
michael@0 896 LIR_HEADER(CreateThis)
michael@0 897
michael@0 898 LCreateThis(const LAllocation &callee)
michael@0 899 {
michael@0 900 setOperand(0, callee);
michael@0 901 }
michael@0 902
michael@0 903 const LAllocation *getCallee() {
michael@0 904 return getOperand(0);
michael@0 905 }
michael@0 906
michael@0 907 MCreateThis *mir() const {
michael@0 908 return mir_->toCreateThis();
michael@0 909 }
michael@0 910 };
michael@0 911
michael@0 912 // Allocate an object for |new| on the caller-side,
michael@0 913 // when the prototype is known.
michael@0 914 class LCreateThisWithProto : public LCallInstructionHelper<1, 2, 0>
michael@0 915 {
michael@0 916 public:
michael@0 917 LIR_HEADER(CreateThisWithProto)
michael@0 918
michael@0 919 LCreateThisWithProto(const LAllocation &callee, const LAllocation &prototype)
michael@0 920 {
michael@0 921 setOperand(0, callee);
michael@0 922 setOperand(1, prototype);
michael@0 923 }
michael@0 924
michael@0 925 const LAllocation *getCallee() {
michael@0 926 return getOperand(0);
michael@0 927 }
michael@0 928 const LAllocation *getPrototype() {
michael@0 929 return getOperand(1);
michael@0 930 }
michael@0 931
michael@0 932 MCreateThis *mir() const {
michael@0 933 return mir_->toCreateThis();
michael@0 934 }
michael@0 935 };
michael@0 936
michael@0 937 // Allocate an object for |new| on the caller-side.
michael@0 938 // Always performs object initialization with a fast path.
michael@0 939 class LCreateThisWithTemplate : public LInstructionHelper<1, 0, 1>
michael@0 940 {
michael@0 941 public:
michael@0 942 LIR_HEADER(CreateThisWithTemplate)
michael@0 943
michael@0 944 LCreateThisWithTemplate(const LDefinition &temp) {
michael@0 945 setTemp(0, temp);
michael@0 946 }
michael@0 947
michael@0 948 MCreateThisWithTemplate *mir() const {
michael@0 949 return mir_->toCreateThisWithTemplate();
michael@0 950 }
michael@0 951
michael@0 952 const LDefinition *temp() {
michael@0 953 return getTemp(0);
michael@0 954 }
michael@0 955 };
michael@0 956
michael@0 957 // Allocate a new arguments object for the frame.
michael@0 958 class LCreateArgumentsObject : public LCallInstructionHelper<1, 1, 1>
michael@0 959 {
michael@0 960 public:
michael@0 961 LIR_HEADER(CreateArgumentsObject)
michael@0 962
michael@0 963 LCreateArgumentsObject(const LAllocation &callObj, const LDefinition &temp)
michael@0 964 {
michael@0 965 setOperand(0, callObj);
michael@0 966 setTemp(0, temp);
michael@0 967 }
michael@0 968
michael@0 969 const LAllocation *getCallObject() {
michael@0 970 return getOperand(0);
michael@0 971 }
michael@0 972
michael@0 973 MCreateArgumentsObject *mir() const {
michael@0 974 return mir_->toCreateArgumentsObject();
michael@0 975 }
michael@0 976 };
michael@0 977
michael@0 978 // Get argument from arguments object.
michael@0 979 class LGetArgumentsObjectArg : public LInstructionHelper<BOX_PIECES, 1, 1>
michael@0 980 {
michael@0 981 public:
michael@0 982 LIR_HEADER(GetArgumentsObjectArg)
michael@0 983
michael@0 984 LGetArgumentsObjectArg(const LAllocation &argsObj, const LDefinition &temp)
michael@0 985 {
michael@0 986 setOperand(0, argsObj);
michael@0 987 setTemp(0, temp);
michael@0 988 }
michael@0 989
michael@0 990 const LAllocation *getArgsObject() {
michael@0 991 return getOperand(0);
michael@0 992 }
michael@0 993
michael@0 994 MGetArgumentsObjectArg *mir() const {
michael@0 995 return mir_->toGetArgumentsObjectArg();
michael@0 996 }
michael@0 997 };
michael@0 998
michael@0 999 // Set argument on arguments object.
michael@0 1000 class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 + BOX_PIECES, 1>
michael@0 1001 {
michael@0 1002 public:
michael@0 1003 LIR_HEADER(SetArgumentsObjectArg)
michael@0 1004
michael@0 1005 LSetArgumentsObjectArg(const LAllocation &argsObj, const LDefinition &temp)
michael@0 1006 {
michael@0 1007 setOperand(0, argsObj);
michael@0 1008 setTemp(0, temp);
michael@0 1009 }
michael@0 1010
michael@0 1011 const LAllocation *getArgsObject() {
michael@0 1012 return getOperand(0);
michael@0 1013 }
michael@0 1014
michael@0 1015 MSetArgumentsObjectArg *mir() const {
michael@0 1016 return mir_->toSetArgumentsObjectArg();
michael@0 1017 }
michael@0 1018
michael@0 1019 static const size_t ValueIndex = 1;
michael@0 1020 };
michael@0 1021
michael@0 1022 // If the Value is an Object, return unbox(Value).
michael@0 1023 // Otherwise, return the other Object.
michael@0 1024 class LReturnFromCtor : public LInstructionHelper<1, BOX_PIECES + 1, 0>
michael@0 1025 {
michael@0 1026 public:
michael@0 1027 LIR_HEADER(ReturnFromCtor)
michael@0 1028
michael@0 1029 LReturnFromCtor(const LAllocation &object)
michael@0 1030 {
michael@0 1031 // Value set by useBox() during lowering.
michael@0 1032 setOperand(LReturnFromCtor::ObjectIndex, object);
michael@0 1033 }
michael@0 1034
michael@0 1035 const LAllocation *getObject() {
michael@0 1036 return getOperand(LReturnFromCtor::ObjectIndex);
michael@0 1037 }
michael@0 1038
michael@0 1039 static const size_t ValueIndex = 0;
michael@0 1040 static const size_t ObjectIndex = BOX_PIECES;
michael@0 1041 };
michael@0 1042
michael@0 1043 class LComputeThis : public LInstructionHelper<1, BOX_PIECES, 0>
michael@0 1044 {
michael@0 1045 public:
michael@0 1046 LIR_HEADER(ComputeThis)
michael@0 1047
michael@0 1048 static const size_t ValueIndex = 0;
michael@0 1049
michael@0 1050 const LDefinition *output() {
michael@0 1051 return getDef(0);
michael@0 1052 }
michael@0 1053
michael@0 1054 MComputeThis *mir() const {
michael@0 1055 return mir_->toComputeThis();
michael@0 1056 }
michael@0 1057 };
michael@0 1058
michael@0 1059 class LLoadArrowThis : public LInstructionHelper<BOX_PIECES, 1, 0>
michael@0 1060 {
michael@0 1061 public:
michael@0 1062 LLoadArrowThis(const LAllocation &callee) {
michael@0 1063 setOperand(0, callee);
michael@0 1064 }
michael@0 1065
michael@0 1066 LIR_HEADER(LoadArrowThis)
michael@0 1067
michael@0 1068 const LAllocation *callee() {
michael@0 1069 return getOperand(0);
michael@0 1070 }
michael@0 1071 };
michael@0 1072
michael@0 1073 // Writes a typed argument for a function call to the frame's argument vector.
michael@0 1074 class LStackArgT : public LInstructionHelper<0, 1, 0>
michael@0 1075 {
michael@0 1076 uint32_t argslot_; // Index into frame-scope argument vector.
michael@0 1077 MIRType type_;
michael@0 1078
michael@0 1079 public:
michael@0 1080 LIR_HEADER(StackArgT)
michael@0 1081
michael@0 1082 LStackArgT(uint32_t argslot, MIRType type, const LAllocation &arg)
michael@0 1083 : argslot_(argslot),
michael@0 1084 type_(type)
michael@0 1085 {
michael@0 1086 setOperand(0, arg);
michael@0 1087 }
michael@0 1088 uint32_t argslot() const {
michael@0 1089 return argslot_;
michael@0 1090 }
michael@0 1091 MIRType type() const {
michael@0 1092 return type_;
michael@0 1093 }
michael@0 1094 const LAllocation *getArgument() {
michael@0 1095 return getOperand(0);
michael@0 1096 }
michael@0 1097 };
michael@0 1098
michael@0 1099 // Writes an untyped argument for a function call to the frame's argument vector.
michael@0 1100 class LStackArgV : public LInstructionHelper<0, BOX_PIECES, 0>
michael@0 1101 {
michael@0 1102 uint32_t argslot_; // Index into frame-scope argument vector.
michael@0 1103
michael@0 1104 public:
michael@0 1105 LIR_HEADER(StackArgV)
michael@0 1106
michael@0 1107 LStackArgV(uint32_t argslot)
michael@0 1108 : argslot_(argslot)
michael@0 1109 { }
michael@0 1110
michael@0 1111 uint32_t argslot() const {
michael@0 1112 return argslot_;
michael@0 1113 }
michael@0 1114 };
michael@0 1115
michael@0 1116 // Common code for LIR descended from MCall.
michael@0 1117 template <size_t Defs, size_t Operands, size_t Temps>
michael@0 1118 class LJSCallInstructionHelper : public LCallInstructionHelper<Defs, Operands, Temps>
michael@0 1119 {
michael@0 1120 public:
michael@0 1121 uint32_t argslot() const {
michael@0 1122 return mir()->numStackArgs();
michael@0 1123 }
michael@0 1124 MCall *mir() const {
michael@0 1125 return this->mir_->toCall();
michael@0 1126 }
michael@0 1127
michael@0 1128 bool hasSingleTarget() const {
michael@0 1129 return getSingleTarget() != nullptr;
michael@0 1130 }
michael@0 1131 JSFunction *getSingleTarget() const {
michael@0 1132 return mir()->getSingleTarget();
michael@0 1133 }
michael@0 1134
michael@0 1135 // The number of stack arguments is the max between the number of formal
michael@0 1136 // arguments and the number of actual arguments. The number of stack
michael@0 1137 // argument includes the |undefined| padding added in case of underflow.
michael@0 1138 // Does not include |this|.
michael@0 1139 uint32_t numStackArgs() const {
michael@0 1140 JS_ASSERT(mir()->numStackArgs() >= 1);
michael@0 1141 return mir()->numStackArgs() - 1; // |this| is not a formal argument.
michael@0 1142 }
michael@0 1143 // Does not include |this|.
michael@0 1144 uint32_t numActualArgs() const {
michael@0 1145 return mir()->numActualArgs();
michael@0 1146 }
michael@0 1147 };
michael@0 1148
michael@0 1149 // Generates a polymorphic callsite, wherein the function being called is
michael@0 1150 // unknown and anticipated to vary.
michael@0 1151 class LCallGeneric : public LJSCallInstructionHelper<BOX_PIECES, 1, 2>
michael@0 1152 {
michael@0 1153 public:
michael@0 1154 LIR_HEADER(CallGeneric)
michael@0 1155
michael@0 1156 LCallGeneric(const LAllocation &func, const LDefinition &nargsreg,
michael@0 1157 const LDefinition &tmpobjreg)
michael@0 1158 {
michael@0 1159 setOperand(0, func);
michael@0 1160 setTemp(0, nargsreg);
michael@0 1161 setTemp(1, tmpobjreg);
michael@0 1162 }
michael@0 1163
michael@0 1164 const LAllocation *getFunction() {
michael@0 1165 return getOperand(0);
michael@0 1166 }
michael@0 1167 const LDefinition *getNargsReg() {
michael@0 1168 return getTemp(0);
michael@0 1169 }
michael@0 1170 const LDefinition *getTempObject() {
michael@0 1171 return getTemp(1);
michael@0 1172 }
michael@0 1173 };
michael@0 1174
michael@0 1175 // Generates a hardcoded callsite for a known, non-native target.
michael@0 1176 class LCallKnown : public LJSCallInstructionHelper<BOX_PIECES, 1, 1>
michael@0 1177 {
michael@0 1178 public:
michael@0 1179 LIR_HEADER(CallKnown)
michael@0 1180
michael@0 1181 LCallKnown(const LAllocation &func, const LDefinition &tmpobjreg)
michael@0 1182 {
michael@0 1183 setOperand(0, func);
michael@0 1184 setTemp(0, tmpobjreg);
michael@0 1185 }
michael@0 1186
michael@0 1187 const LAllocation *getFunction() {
michael@0 1188 return getOperand(0);
michael@0 1189 }
michael@0 1190 const LDefinition *getTempObject() {
michael@0 1191 return getTemp(0);
michael@0 1192 }
michael@0 1193 };
michael@0 1194
michael@0 1195 // Generates a hardcoded callsite for a known, native target.
michael@0 1196 class LCallNative : public LJSCallInstructionHelper<BOX_PIECES, 0, 4>
michael@0 1197 {
michael@0 1198 public:
michael@0 1199 LIR_HEADER(CallNative)
michael@0 1200
michael@0 1201 LCallNative(const LDefinition &argContext, const LDefinition &argUintN,
michael@0 1202 const LDefinition &argVp, const LDefinition &tmpreg)
michael@0 1203 {
michael@0 1204 // Registers used for callWithABI().
michael@0 1205 setTemp(0, argContext);
michael@0 1206 setTemp(1, argUintN);
michael@0 1207 setTemp(2, argVp);
michael@0 1208
michael@0 1209 // Temporary registers.
michael@0 1210 setTemp(3, tmpreg);
michael@0 1211 }
michael@0 1212
michael@0 1213 const LDefinition *getArgContextReg() {
michael@0 1214 return getTemp(0);
michael@0 1215 }
michael@0 1216 const LDefinition *getArgUintNReg() {
michael@0 1217 return getTemp(1);
michael@0 1218 }
michael@0 1219 const LDefinition *getArgVpReg() {
michael@0 1220 return getTemp(2);
michael@0 1221 }
michael@0 1222 const LDefinition *getTempReg() {
michael@0 1223 return getTemp(3);
michael@0 1224 }
michael@0 1225 };
michael@0 1226
michael@0 1227 // Generates a hardcoded callsite for a known, DOM-native target.
michael@0 1228 class LCallDOMNative : public LJSCallInstructionHelper<BOX_PIECES, 0, 4>
michael@0 1229 {
michael@0 1230 public:
michael@0 1231 LIR_HEADER(CallDOMNative)
michael@0 1232
michael@0 1233 LCallDOMNative(const LDefinition &argJSContext, const LDefinition &argObj,
michael@0 1234 const LDefinition &argPrivate, const LDefinition &argArgs)
michael@0 1235 {
michael@0 1236 setTemp(0, argJSContext);
michael@0 1237 setTemp(1, argObj);
michael@0 1238 setTemp(2, argPrivate);
michael@0 1239 setTemp(3, argArgs);
michael@0 1240 }
michael@0 1241
michael@0 1242 const LDefinition *getArgJSContext() {
michael@0 1243 return getTemp(0);
michael@0 1244 }
michael@0 1245 const LDefinition *getArgObj() {
michael@0 1246 return getTemp(1);
michael@0 1247 }
michael@0 1248 const LDefinition *getArgPrivate() {
michael@0 1249 return getTemp(2);
michael@0 1250 }
michael@0 1251 const LDefinition *getArgArgs() {
michael@0 1252 return getTemp(3);
michael@0 1253 }
michael@0 1254 };
michael@0 1255
michael@0 1256 class LBail : public LInstructionHelper<0, 0, 0>
michael@0 1257 {
michael@0 1258 public:
michael@0 1259 LIR_HEADER(Bail)
michael@0 1260 };
michael@0 1261
michael@0 1262 template <size_t defs, size_t ops>
michael@0 1263 class LDOMPropertyInstructionHelper : public LCallInstructionHelper<defs, 1 + ops, 3>
michael@0 1264 {
michael@0 1265 protected:
michael@0 1266 LDOMPropertyInstructionHelper(const LDefinition &JSContextReg, const LAllocation &ObjectReg,
michael@0 1267 const LDefinition &PrivReg, const LDefinition &ValueReg)
michael@0 1268 {
michael@0 1269 this->setOperand(0, ObjectReg);
michael@0 1270 this->setTemp(0, JSContextReg);
michael@0 1271 this->setTemp(1, PrivReg);
michael@0 1272 this->setTemp(2, ValueReg);
michael@0 1273 }
michael@0 1274
michael@0 1275 public:
michael@0 1276 const LDefinition *getJSContextReg() {
michael@0 1277 return this->getTemp(0);
michael@0 1278 }
michael@0 1279 const LAllocation *getObjectReg() {
michael@0 1280 return this->getOperand(0);
michael@0 1281 }
michael@0 1282 const LDefinition *getPrivReg() {
michael@0 1283 return this->getTemp(1);
michael@0 1284 }
michael@0 1285 const LDefinition *getValueReg() {
michael@0 1286 return this->getTemp(2);
michael@0 1287 }
michael@0 1288 };
michael@0 1289
michael@0 1290
michael@0 1291 class LGetDOMProperty : public LDOMPropertyInstructionHelper<BOX_PIECES, 0>
michael@0 1292 {
michael@0 1293 public:
michael@0 1294 LIR_HEADER(GetDOMProperty)
michael@0 1295
michael@0 1296 LGetDOMProperty(const LDefinition &JSContextReg, const LAllocation &ObjectReg,
michael@0 1297 const LDefinition &PrivReg, const LDefinition &ValueReg)
michael@0 1298 : LDOMPropertyInstructionHelper<BOX_PIECES, 0>(JSContextReg, ObjectReg,
michael@0 1299 PrivReg, ValueReg)
michael@0 1300 { }
michael@0 1301
michael@0 1302 MGetDOMProperty *mir() const {
michael@0 1303 return mir_->toGetDOMProperty();
michael@0 1304 }
michael@0 1305 };
michael@0 1306
michael@0 1307 class LGetDOMMember : public LInstructionHelper<BOX_PIECES, 1, 0>
michael@0 1308 {
michael@0 1309 public:
michael@0 1310 LIR_HEADER(GetDOMMember);
michael@0 1311 LGetDOMMember(const LAllocation &object) {
michael@0 1312 setOperand(0, object);
michael@0 1313 }
michael@0 1314
michael@0 1315 const LAllocation *object() {
michael@0 1316 return getOperand(0);
michael@0 1317 }
michael@0 1318
michael@0 1319 MGetDOMMember *mir() const {
michael@0 1320 return mir_->toGetDOMMember();
michael@0 1321 }
michael@0 1322 };
michael@0 1323
michael@0 1324 class LSetDOMProperty : public LDOMPropertyInstructionHelper<0, BOX_PIECES>
michael@0 1325 {
michael@0 1326 public:
michael@0 1327 LIR_HEADER(SetDOMProperty)
michael@0 1328
michael@0 1329 LSetDOMProperty(const LDefinition &JSContextReg, const LAllocation &ObjectReg,
michael@0 1330 const LDefinition &PrivReg, const LDefinition &ValueReg)
michael@0 1331 : LDOMPropertyInstructionHelper<0, BOX_PIECES>(JSContextReg, ObjectReg,
michael@0 1332 PrivReg, ValueReg)
michael@0 1333 { }
michael@0 1334
michael@0 1335 static const size_t Value = 1;
michael@0 1336
michael@0 1337 MSetDOMProperty *mir() const {
michael@0 1338 return mir_->toSetDOMProperty();
michael@0 1339 }
michael@0 1340 };
michael@0 1341
michael@0 1342 // Generates a polymorphic callsite, wherein the function being called is
michael@0 1343 // unknown and anticipated to vary.
michael@0 1344 class LApplyArgsGeneric : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES + 2, 2>
michael@0 1345 {
michael@0 1346 public:
michael@0 1347 LIR_HEADER(ApplyArgsGeneric)
michael@0 1348
michael@0 1349 LApplyArgsGeneric(const LAllocation &func, const LAllocation &argc,
michael@0 1350 const LDefinition &tmpobjreg, const LDefinition &tmpcopy)
michael@0 1351 {
michael@0 1352 setOperand(0, func);
michael@0 1353 setOperand(1, argc);
michael@0 1354 setTemp(0, tmpobjreg);
michael@0 1355 setTemp(1, tmpcopy);
michael@0 1356 }
michael@0 1357
michael@0 1358 MApplyArgs *mir() const {
michael@0 1359 return mir_->toApplyArgs();
michael@0 1360 }
michael@0 1361
michael@0 1362 bool hasSingleTarget() const {
michael@0 1363 return getSingleTarget() != nullptr;
michael@0 1364 }
michael@0 1365 JSFunction *getSingleTarget() const {
michael@0 1366 return mir()->getSingleTarget();
michael@0 1367 }
michael@0 1368
michael@0 1369 const LAllocation *getFunction() {
michael@0 1370 return getOperand(0);
michael@0 1371 }
michael@0 1372 const LAllocation *getArgc() {
michael@0 1373 return getOperand(1);
michael@0 1374 }
michael@0 1375 static const size_t ThisIndex = 2;
michael@0 1376
michael@0 1377 const LDefinition *getTempObject() {
michael@0 1378 return getTemp(0);
michael@0 1379 }
michael@0 1380 const LDefinition *getTempCopy() {
michael@0 1381 return getTemp(1);
michael@0 1382 }
michael@0 1383 };
michael@0 1384
michael@0 1385 class LArraySplice : public LCallInstructionHelper<0, 3, 0>
michael@0 1386 {
michael@0 1387 public:
michael@0 1388 LIR_HEADER(ArraySplice)
michael@0 1389
michael@0 1390 LArraySplice(const LAllocation &object, const LAllocation &start,
michael@0 1391 const LAllocation &deleteCount)
michael@0 1392 {
michael@0 1393 setOperand(0, object);
michael@0 1394 setOperand(1, start);
michael@0 1395 setOperand(2, deleteCount);
michael@0 1396 }
michael@0 1397
michael@0 1398 MArraySplice *mir() const {
michael@0 1399 return mir_->toArraySplice();
michael@0 1400 }
michael@0 1401
michael@0 1402 const LAllocation *getObject() {
michael@0 1403 return getOperand(0);
michael@0 1404 }
michael@0 1405 const LAllocation *getStart() {
michael@0 1406 return getOperand(1);
michael@0 1407 }
michael@0 1408 const LAllocation *getDeleteCount() {
michael@0 1409 return getOperand(2);
michael@0 1410 }
michael@0 1411 };
michael@0 1412
michael@0 1413 class LGetDynamicName : public LCallInstructionHelper<BOX_PIECES, 2, 3>
michael@0 1414 {
michael@0 1415 public:
michael@0 1416 LIR_HEADER(GetDynamicName)
michael@0 1417
michael@0 1418 LGetDynamicName(const LAllocation &scopeChain, const LAllocation &name,
michael@0 1419 const LDefinition &temp1, const LDefinition &temp2, const LDefinition &temp3)
michael@0 1420 {
michael@0 1421 setOperand(0, scopeChain);
michael@0 1422 setOperand(1, name);
michael@0 1423 setTemp(0, temp1);
michael@0 1424 setTemp(1, temp2);
michael@0 1425 setTemp(2, temp3);
michael@0 1426 }
michael@0 1427
michael@0 1428 MGetDynamicName *mir() const {
michael@0 1429 return mir_->toGetDynamicName();
michael@0 1430 }
michael@0 1431
michael@0 1432 const LAllocation *getScopeChain() {
michael@0 1433 return getOperand(0);
michael@0 1434 }
michael@0 1435 const LAllocation *getName() {
michael@0 1436 return getOperand(1);
michael@0 1437 }
michael@0 1438
michael@0 1439 const LDefinition *temp1() {
michael@0 1440 return getTemp(0);
michael@0 1441 }
michael@0 1442 const LDefinition *temp2() {
michael@0 1443 return getTemp(1);
michael@0 1444 }
michael@0 1445 const LDefinition *temp3() {
michael@0 1446 return getTemp(2);
michael@0 1447 }
michael@0 1448 };
michael@0 1449
michael@0 1450 class LFilterArgumentsOrEvalS : public LCallInstructionHelper<0, 1, 2>
michael@0 1451 {
michael@0 1452 public:
michael@0 1453 LIR_HEADER(FilterArgumentsOrEvalS)
michael@0 1454
michael@0 1455 LFilterArgumentsOrEvalS(const LAllocation &string, const LDefinition &temp1,
michael@0 1456 const LDefinition &temp2)
michael@0 1457 {
michael@0 1458 setOperand(0, string);
michael@0 1459 setTemp(0, temp1);
michael@0 1460 setTemp(1, temp2);
michael@0 1461 }
michael@0 1462
michael@0 1463 MFilterArgumentsOrEval *mir() const {
michael@0 1464 return mir_->toFilterArgumentsOrEval();
michael@0 1465 }
michael@0 1466
michael@0 1467 const LAllocation *getString() {
michael@0 1468 return getOperand(0);
michael@0 1469 }
michael@0 1470 const LDefinition *temp1() {
michael@0 1471 return getTemp(0);
michael@0 1472 }
michael@0 1473 const LDefinition *temp2() {
michael@0 1474 return getTemp(1);
michael@0 1475 }
michael@0 1476 };
michael@0 1477
michael@0 1478 class LFilterArgumentsOrEvalV : public LCallInstructionHelper<0, BOX_PIECES, 3>
michael@0 1479 {
michael@0 1480 public:
michael@0 1481 LIR_HEADER(FilterArgumentsOrEvalV)
michael@0 1482
michael@0 1483 LFilterArgumentsOrEvalV(const LDefinition &temp1, const LDefinition &temp2,
michael@0 1484 const LDefinition &temp3)
michael@0 1485 {
michael@0 1486 setTemp(0, temp1);
michael@0 1487 setTemp(1, temp2);
michael@0 1488 setTemp(2, temp3);
michael@0 1489 }
michael@0 1490
michael@0 1491 static const size_t Input = 0;
michael@0 1492
michael@0 1493 MFilterArgumentsOrEval *mir() const {
michael@0 1494 return mir_->toFilterArgumentsOrEval();
michael@0 1495 }
michael@0 1496
michael@0 1497 const LDefinition *temp1() {
michael@0 1498 return getTemp(0);
michael@0 1499 }
michael@0 1500 const LDefinition *temp2() {
michael@0 1501 return getTemp(1);
michael@0 1502 }
michael@0 1503 const LDefinition *temp3() {
michael@0 1504 return getTemp(2);
michael@0 1505 }
michael@0 1506 };
michael@0 1507
michael@0 1508 class LCallDirectEvalS : public LCallInstructionHelper<BOX_PIECES, 2 + BOX_PIECES, 0>
michael@0 1509 {
michael@0 1510 public:
michael@0 1511 LIR_HEADER(CallDirectEvalS)
michael@0 1512
michael@0 1513 LCallDirectEvalS(const LAllocation &scopeChain, const LAllocation &string)
michael@0 1514 {
michael@0 1515 setOperand(0, scopeChain);
michael@0 1516 setOperand(1, string);
michael@0 1517 }
michael@0 1518
michael@0 1519 static const size_t ThisValue = 2;
michael@0 1520
michael@0 1521 MCallDirectEval *mir() const {
michael@0 1522 return mir_->toCallDirectEval();
michael@0 1523 }
michael@0 1524
michael@0 1525 const LAllocation *getScopeChain() {
michael@0 1526 return getOperand(0);
michael@0 1527 }
michael@0 1528 const LAllocation *getString() {
michael@0 1529 return getOperand(1);
michael@0 1530 }
michael@0 1531 };
michael@0 1532
michael@0 1533 class LCallDirectEvalV : public LCallInstructionHelper<BOX_PIECES, 1 + (2 * BOX_PIECES), 0>
michael@0 1534 {
michael@0 1535 public:
michael@0 1536 LIR_HEADER(CallDirectEvalV)
michael@0 1537
michael@0 1538 LCallDirectEvalV(const LAllocation &scopeChain)
michael@0 1539 {
michael@0 1540 setOperand(0, scopeChain);
michael@0 1541 }
michael@0 1542
michael@0 1543 static const size_t Argument = 1;
michael@0 1544 static const size_t ThisValue = 1 + BOX_PIECES;
michael@0 1545
michael@0 1546 MCallDirectEval *mir() const {
michael@0 1547 return mir_->toCallDirectEval();
michael@0 1548 }
michael@0 1549
michael@0 1550 const LAllocation *getScopeChain() {
michael@0 1551 return getOperand(0);
michael@0 1552 }
michael@0 1553 };
michael@0 1554
michael@0 1555 // Takes in either an integer or boolean input and tests it for truthiness.
michael@0 1556 class LTestIAndBranch : public LControlInstructionHelper<2, 1, 0>
michael@0 1557 {
michael@0 1558 public:
michael@0 1559 LIR_HEADER(TestIAndBranch)
michael@0 1560
michael@0 1561 LTestIAndBranch(const LAllocation &in, MBasicBlock *ifTrue, MBasicBlock *ifFalse)
michael@0 1562 {
michael@0 1563 setOperand(0, in);
michael@0 1564 setSuccessor(0, ifTrue);
michael@0 1565 setSuccessor(1, ifFalse);
michael@0 1566 }
michael@0 1567
michael@0 1568 MBasicBlock *ifTrue() const {
michael@0 1569 return getSuccessor(0);
michael@0 1570 }
michael@0 1571 MBasicBlock *ifFalse() const {
michael@0 1572 return getSuccessor(1);
michael@0 1573 }
michael@0 1574 };
michael@0 1575
michael@0 1576 // Takes in either an integer or boolean input and tests it for truthiness.
michael@0 1577 class LTestDAndBranch : public LControlInstructionHelper<2, 1, 0>
michael@0 1578 {
michael@0 1579 public:
michael@0 1580 LIR_HEADER(TestDAndBranch)
michael@0 1581
michael@0 1582 LTestDAndBranch(const LAllocation &in, MBasicBlock *ifTrue, MBasicBlock *ifFalse)
michael@0 1583 {
michael@0 1584 setOperand(0, in);
michael@0 1585 setSuccessor(0, ifTrue);
michael@0 1586 setSuccessor(1, ifFalse);
michael@0 1587 }
michael@0 1588
michael@0 1589 MBasicBlock *ifTrue() const {
michael@0 1590 return getSuccessor(0);
michael@0 1591 }
michael@0 1592 MBasicBlock *ifFalse() const {
michael@0 1593 return getSuccessor(1);
michael@0 1594 }
michael@0 1595 };
michael@0 1596
michael@0 1597 // Takes in either an integer or boolean input and tests it for truthiness.
michael@0 1598 class LTestFAndBranch : public LControlInstructionHelper<2, 1, 0>
michael@0 1599 {
michael@0 1600 public:
michael@0 1601 LIR_HEADER(TestFAndBranch)
michael@0 1602
michael@0 1603 LTestFAndBranch(const LAllocation &in, MBasicBlock *ifTrue, MBasicBlock *ifFalse)
michael@0 1604 {
michael@0 1605 setOperand(0, in);
michael@0 1606 setSuccessor(0, ifTrue);
michael@0 1607 setSuccessor(1, ifFalse);
michael@0 1608 }
michael@0 1609
michael@0 1610 MBasicBlock *ifTrue() const {
michael@0 1611 return getSuccessor(0);
michael@0 1612 }
michael@0 1613 MBasicBlock *ifFalse() const {
michael@0 1614 return getSuccessor(1);
michael@0 1615 }
michael@0 1616 };
michael@0 1617
michael@0 1618 // Takes an object and tests it for truthiness. An object is falsy iff it
michael@0 1619 // emulates |undefined|; see js::EmulatesUndefined.
michael@0 1620 class LTestOAndBranch : public LControlInstructionHelper<2, 1, 1>
michael@0 1621 {
michael@0 1622 public:
michael@0 1623 LIR_HEADER(TestOAndBranch)
michael@0 1624
michael@0 1625 LTestOAndBranch(const LAllocation &input, MBasicBlock *ifTruthy, MBasicBlock *ifFalsy,
michael@0 1626 const LDefinition &temp)
michael@0 1627 {
michael@0 1628 setOperand(0, input);
michael@0 1629 setSuccessor(0, ifTruthy);
michael@0 1630 setSuccessor(1, ifFalsy);
michael@0 1631 setTemp(0, temp);
michael@0 1632 }
michael@0 1633
michael@0 1634 const LDefinition *temp() {
michael@0 1635 return getTemp(0);
michael@0 1636 }
michael@0 1637
michael@0 1638 MBasicBlock *ifTruthy() {
michael@0 1639 return getSuccessor(0);
michael@0 1640 }
michael@0 1641 MBasicBlock *ifFalsy() {
michael@0 1642 return getSuccessor(1);
michael@0 1643 }
michael@0 1644
michael@0 1645 MTest *mir() {
michael@0 1646 return mir_->toTest();
michael@0 1647 }
michael@0 1648 };
michael@0 1649
michael@0 1650 // Takes in a boxed value and tests it for truthiness.
michael@0 1651 class LTestVAndBranch : public LControlInstructionHelper<2, BOX_PIECES, 3>
michael@0 1652 {
michael@0 1653 public:
michael@0 1654 LIR_HEADER(TestVAndBranch)
michael@0 1655
michael@0 1656 LTestVAndBranch(MBasicBlock *ifTruthy, MBasicBlock *ifFalsy, const LDefinition &temp0,
michael@0 1657 const LDefinition &temp1, const LDefinition &temp2)
michael@0 1658 {
michael@0 1659 setSuccessor(0, ifTruthy);
michael@0 1660 setSuccessor(1, ifFalsy);
michael@0 1661 setTemp(0, temp0);
michael@0 1662 setTemp(1, temp1);
michael@0 1663 setTemp(2, temp2);
michael@0 1664 }
michael@0 1665
michael@0 1666 const char *extraName() const {
michael@0 1667 return mir()->operandMightEmulateUndefined() ? "MightEmulateUndefined" : nullptr;
michael@0 1668 }
michael@0 1669
michael@0 1670 static const size_t Input = 0;
michael@0 1671
michael@0 1672 const LDefinition *tempFloat() {
michael@0 1673 return getTemp(0);
michael@0 1674 }
michael@0 1675
michael@0 1676 const LDefinition *temp1() {
michael@0 1677 return getTemp(1);
michael@0 1678 }
michael@0 1679
michael@0 1680 const LDefinition *temp2() {
michael@0 1681 return getTemp(2);
michael@0 1682 }
michael@0 1683
michael@0 1684 MBasicBlock *ifTruthy() {
michael@0 1685 return getSuccessor(0);
michael@0 1686 }
michael@0 1687 MBasicBlock *ifFalsy() {
michael@0 1688 return getSuccessor(1);
michael@0 1689 }
michael@0 1690
michael@0 1691 MTest *mir() const {
michael@0 1692 return mir_->toTest();
michael@0 1693 }
michael@0 1694 };
michael@0 1695
michael@0 1696 // Dispatches control flow to a successor based on incoming JSFunction*.
michael@0 1697 // Used to implemenent polymorphic inlining.
michael@0 1698 class LFunctionDispatch : public LInstructionHelper<0, 1, 0>
michael@0 1699 {
michael@0 1700 // Dispatch is performed based on a function -> block map
michael@0 1701 // stored in the MIR.
michael@0 1702
michael@0 1703 public:
michael@0 1704 LIR_HEADER(FunctionDispatch);
michael@0 1705
michael@0 1706 LFunctionDispatch(const LAllocation &in) {
michael@0 1707 setOperand(0, in);
michael@0 1708 }
michael@0 1709
michael@0 1710 MFunctionDispatch *mir() {
michael@0 1711 return mir_->toFunctionDispatch();
michael@0 1712 }
michael@0 1713 };
michael@0 1714
michael@0 1715 class LTypeObjectDispatch : public LInstructionHelper<0, 1, 1>
michael@0 1716 {
michael@0 1717 // Dispatch is performed based on a TypeObject -> block
michael@0 1718 // map inferred by the MIR.
michael@0 1719
michael@0 1720 public:
michael@0 1721 LIR_HEADER(TypeObjectDispatch);
michael@0 1722
michael@0 1723 LTypeObjectDispatch(const LAllocation &in, const LDefinition &temp) {
michael@0 1724 setOperand(0, in);
michael@0 1725 setTemp(0, temp);
michael@0 1726 }
michael@0 1727
michael@0 1728 const LDefinition *temp() {
michael@0 1729 return getTemp(0);
michael@0 1730 }
michael@0 1731
michael@0 1732 MTypeObjectDispatch *mir() {
michael@0 1733 return mir_->toTypeObjectDispatch();
michael@0 1734 }
michael@0 1735 };
michael@0 1736
michael@0 1737 // Compares two integral values of the same JS type, either integer or object.
michael@0 1738 // For objects, both operands are in registers.
michael@0 1739 class LCompare : public LInstructionHelper<1, 2, 0>
michael@0 1740 {
michael@0 1741 JSOp jsop_;
michael@0 1742
michael@0 1743 public:
michael@0 1744 LIR_HEADER(Compare)
michael@0 1745 LCompare(JSOp jsop, const LAllocation &left, const LAllocation &right)
michael@0 1746 : jsop_(jsop)
michael@0 1747 {
michael@0 1748 setOperand(0, left);
michael@0 1749 setOperand(1, right);
michael@0 1750 }
michael@0 1751
michael@0 1752 JSOp jsop() const {
michael@0 1753 return jsop_;
michael@0 1754 }
michael@0 1755 const LAllocation *left() {
michael@0 1756 return getOperand(0);
michael@0 1757 }
michael@0 1758 const LAllocation *right() {
michael@0 1759 return getOperand(1);
michael@0 1760 }
michael@0 1761 MCompare *mir() {
michael@0 1762 return mir_->toCompare();
michael@0 1763 }
michael@0 1764 const char *extraName() const {
michael@0 1765 return js_CodeName[jsop_];
michael@0 1766 }
michael@0 1767 };
michael@0 1768
michael@0 1769 // Compares two integral values of the same JS type, either integer or object.
michael@0 1770 // For objects, both operands are in registers.
michael@0 1771 class LCompareAndBranch : public LControlInstructionHelper<2, 2, 0>
michael@0 1772 {
michael@0 1773 MCompare *cmpMir_;
michael@0 1774 JSOp jsop_;
michael@0 1775
michael@0 1776 public:
michael@0 1777 LIR_HEADER(CompareAndBranch)
michael@0 1778 LCompareAndBranch(MCompare *cmpMir, JSOp jsop,
michael@0 1779 const LAllocation &left, const LAllocation &right,
michael@0 1780 MBasicBlock *ifTrue, MBasicBlock *ifFalse)
michael@0 1781 : cmpMir_(cmpMir), jsop_(jsop)
michael@0 1782 {
michael@0 1783 setOperand(0, left);
michael@0 1784 setOperand(1, right);
michael@0 1785 setSuccessor(0, ifTrue);
michael@0 1786 setSuccessor(1, ifFalse);
michael@0 1787 }
michael@0 1788
michael@0 1789 JSOp jsop() const {
michael@0 1790 return jsop_;
michael@0 1791 }
michael@0 1792 MBasicBlock *ifTrue() const {
michael@0 1793 return getSuccessor(0);
michael@0 1794 }
michael@0 1795 MBasicBlock *ifFalse() const {
michael@0 1796 return getSuccessor(1);
michael@0 1797 }
michael@0 1798 const LAllocation *left() {
michael@0 1799 return getOperand(0);
michael@0 1800 }
michael@0 1801 const LAllocation *right() {
michael@0 1802 return getOperand(1);
michael@0 1803 }
michael@0 1804 MTest *mir() const {
michael@0 1805 return mir_->toTest();
michael@0 1806 }
michael@0 1807 MCompare *cmpMir() const {
michael@0 1808 return cmpMir_;
michael@0 1809 }
michael@0 1810 const char *extraName() const {
michael@0 1811 return js_CodeName[jsop_];
michael@0 1812 }
michael@0 1813 };
michael@0 1814
michael@0 1815 class LCompareD : public LInstructionHelper<1, 2, 0>
michael@0 1816 {
michael@0 1817 public:
michael@0 1818 LIR_HEADER(CompareD)
michael@0 1819 LCompareD(const LAllocation &left, const LAllocation &right) {
michael@0 1820 setOperand(0, left);
michael@0 1821 setOperand(1, right);
michael@0 1822 }
michael@0 1823
michael@0 1824 const LAllocation *left() {
michael@0 1825 return getOperand(0);
michael@0 1826 }
michael@0 1827 const LAllocation *right() {
michael@0 1828 return getOperand(1);
michael@0 1829 }
michael@0 1830 MCompare *mir() {
michael@0 1831 return mir_->toCompare();
michael@0 1832 }
michael@0 1833 };
michael@0 1834
michael@0 1835 class LCompareF : public LInstructionHelper<1, 2, 0>
michael@0 1836 {
michael@0 1837 public:
michael@0 1838 LIR_HEADER(CompareF)
michael@0 1839 LCompareF(const LAllocation &left, const LAllocation &right) {
michael@0 1840 setOperand(0, left);
michael@0 1841 setOperand(1, right);
michael@0 1842 }
michael@0 1843
michael@0 1844 const LAllocation *left() {
michael@0 1845 return getOperand(0);
michael@0 1846 }
michael@0 1847 const LAllocation *right() {
michael@0 1848 return getOperand(1);
michael@0 1849 }
michael@0 1850 MCompare *mir() {
michael@0 1851 return mir_->toCompare();
michael@0 1852 }
michael@0 1853 };
michael@0 1854
michael@0 1855 class LCompareDAndBranch : public LControlInstructionHelper<2, 2, 0>
michael@0 1856 {
michael@0 1857 MCompare *cmpMir_;
michael@0 1858
michael@0 1859 public:
michael@0 1860 LIR_HEADER(CompareDAndBranch)
michael@0 1861 LCompareDAndBranch(MCompare *cmpMir, const LAllocation &left, const LAllocation &right,
michael@0 1862 MBasicBlock *ifTrue, MBasicBlock *ifFalse)
michael@0 1863 : cmpMir_(cmpMir)
michael@0 1864 {
michael@0 1865 setOperand(0, left);
michael@0 1866 setOperand(1, right);
michael@0 1867 setSuccessor(0, ifTrue);
michael@0 1868 setSuccessor(1, ifFalse);
michael@0 1869 }
michael@0 1870
michael@0 1871 MBasicBlock *ifTrue() const {
michael@0 1872 return getSuccessor(0);
michael@0 1873 }
michael@0 1874 MBasicBlock *ifFalse() const {
michael@0 1875 return getSuccessor(1);
michael@0 1876 }
michael@0 1877 const LAllocation *left() {
michael@0 1878 return getOperand(0);
michael@0 1879 }
michael@0 1880 const LAllocation *right() {
michael@0 1881 return getOperand(1);
michael@0 1882 }
michael@0 1883 MTest *mir() const {
michael@0 1884 return mir_->toTest();
michael@0 1885 }
michael@0 1886 MCompare *cmpMir() const {
michael@0 1887 return cmpMir_;
michael@0 1888 }
michael@0 1889 };
michael@0 1890
michael@0 1891 class LCompareFAndBranch : public LControlInstructionHelper<2, 2, 0>
michael@0 1892 {
michael@0 1893 MCompare *cmpMir_;
michael@0 1894
michael@0 1895 public:
michael@0 1896 LIR_HEADER(CompareFAndBranch)
michael@0 1897 LCompareFAndBranch(MCompare *cmpMir, const LAllocation &left, const LAllocation &right,
michael@0 1898 MBasicBlock *ifTrue, MBasicBlock *ifFalse)
michael@0 1899 : cmpMir_(cmpMir)
michael@0 1900 {
michael@0 1901 setOperand(0, left);
michael@0 1902 setOperand(1, right);
michael@0 1903 setSuccessor(0, ifTrue);
michael@0 1904 setSuccessor(1, ifFalse);
michael@0 1905 }
michael@0 1906
michael@0 1907 MBasicBlock *ifTrue() const {
michael@0 1908 return getSuccessor(0);
michael@0 1909 }
michael@0 1910 MBasicBlock *ifFalse() const {
michael@0 1911 return getSuccessor(1);
michael@0 1912 }
michael@0 1913 const LAllocation *left() {
michael@0 1914 return getOperand(0);
michael@0 1915 }
michael@0 1916 const LAllocation *right() {
michael@0 1917 return getOperand(1);
michael@0 1918 }
michael@0 1919 MTest *mir() const {
michael@0 1920 return mir_->toTest();
michael@0 1921 }
michael@0 1922 MCompare *cmpMir() const {
michael@0 1923 return cmpMir_;
michael@0 1924 }
michael@0 1925 };
michael@0 1926
michael@0 1927 class LCompareS : public LInstructionHelper<1, 2, 1>
michael@0 1928 {
michael@0 1929 public:
michael@0 1930 LIR_HEADER(CompareS)
michael@0 1931 LCompareS(const LAllocation &left, const LAllocation &right,
michael@0 1932 const LDefinition &temp) {
michael@0 1933 setOperand(0, left);
michael@0 1934 setOperand(1, right);
michael@0 1935 setTemp(0, temp);
michael@0 1936 }
michael@0 1937
michael@0 1938 const LAllocation *left() {
michael@0 1939 return getOperand(0);
michael@0 1940 }
michael@0 1941 const LAllocation *right() {
michael@0 1942 return getOperand(1);
michael@0 1943 }
michael@0 1944 const LDefinition *temp() {
michael@0 1945 return getTemp(0);
michael@0 1946 }
michael@0 1947 MCompare *mir() {
michael@0 1948 return mir_->toCompare();
michael@0 1949 }
michael@0 1950 };
michael@0 1951
michael@0 1952 // strict-equality between value and string.
michael@0 1953 class LCompareStrictS : public LInstructionHelper<1, BOX_PIECES + 1, 2>
michael@0 1954 {
michael@0 1955 public:
michael@0 1956 LIR_HEADER(CompareStrictS)
michael@0 1957 LCompareStrictS(const LAllocation &rhs, const LDefinition &temp0,
michael@0 1958 const LDefinition &temp1) {
michael@0 1959 setOperand(BOX_PIECES, rhs);
michael@0 1960 setTemp(0, temp0);
michael@0 1961 setTemp(1, temp1);
michael@0 1962 }
michael@0 1963
michael@0 1964 static const size_t Lhs = 0;
michael@0 1965
michael@0 1966 const LAllocation *right() {
michael@0 1967 return getOperand(BOX_PIECES);
michael@0 1968 }
michael@0 1969 const LDefinition *temp() {
michael@0 1970 return getTemp(0);
michael@0 1971 }
michael@0 1972 const LDefinition *tempToUnbox() {
michael@0 1973 return getTemp(1);
michael@0 1974 }
michael@0 1975 MCompare *mir() {
michael@0 1976 return mir_->toCompare();
michael@0 1977 }
michael@0 1978 };
michael@0 1979
michael@0 1980 // Used for strict-equality comparisons where one side is a boolean
michael@0 1981 // and the other is a value. Note that CompareI is used to compare
michael@0 1982 // two booleans.
michael@0 1983 class LCompareB : public LInstructionHelper<1, BOX_PIECES + 1, 0>
michael@0 1984 {
michael@0 1985 public:
michael@0 1986 LIR_HEADER(CompareB)
michael@0 1987
michael@0 1988 LCompareB(const LAllocation &rhs) {
michael@0 1989 setOperand(BOX_PIECES, rhs);
michael@0 1990 }
michael@0 1991
michael@0 1992 static const size_t Lhs = 0;
michael@0 1993
michael@0 1994 const LAllocation *rhs() {
michael@0 1995 return getOperand(BOX_PIECES);
michael@0 1996 }
michael@0 1997
michael@0 1998 MCompare *mir() {
michael@0 1999 return mir_->toCompare();
michael@0 2000 }
michael@0 2001 };
michael@0 2002
michael@0 2003 class LCompareBAndBranch : public LControlInstructionHelper<2, BOX_PIECES + 1, 0>
michael@0 2004 {
michael@0 2005 MCompare *cmpMir_;
michael@0 2006
michael@0 2007 public:
michael@0 2008 LIR_HEADER(CompareBAndBranch)
michael@0 2009
michael@0 2010 LCompareBAndBranch(MCompare *cmpMir, const LAllocation &rhs,
michael@0 2011 MBasicBlock *ifTrue, MBasicBlock *ifFalse)
michael@0 2012 : cmpMir_(cmpMir)
michael@0 2013 {
michael@0 2014 setOperand(BOX_PIECES, rhs);
michael@0 2015 setSuccessor(0, ifTrue);
michael@0 2016 setSuccessor(1, ifFalse);
michael@0 2017 }
michael@0 2018
michael@0 2019 static const size_t Lhs = 0;
michael@0 2020
michael@0 2021 const LAllocation *rhs() {
michael@0 2022 return getOperand(BOX_PIECES);
michael@0 2023 }
michael@0 2024
michael@0 2025 MBasicBlock *ifTrue() const {
michael@0 2026 return getSuccessor(0);
michael@0 2027 }
michael@0 2028 MBasicBlock *ifFalse() const {
michael@0 2029 return getSuccessor(1);
michael@0 2030 }
michael@0 2031 MTest *mir() const {
michael@0 2032 return mir_->toTest();
michael@0 2033 }
michael@0 2034 MCompare *cmpMir() const {
michael@0 2035 return cmpMir_;
michael@0 2036 }
michael@0 2037 };
michael@0 2038
michael@0 2039 class LCompareV : public LInstructionHelper<1, 2 * BOX_PIECES, 0>
michael@0 2040 {
michael@0 2041 public:
michael@0 2042 LIR_HEADER(CompareV)
michael@0 2043
michael@0 2044 static const size_t LhsInput = 0;
michael@0 2045 static const size_t RhsInput = BOX_PIECES;
michael@0 2046
michael@0 2047 MCompare *mir() const {
michael@0 2048 return mir_->toCompare();
michael@0 2049 }
michael@0 2050 };
michael@0 2051
michael@0 2052 class LCompareVAndBranch : public LControlInstructionHelper<2, 2 * BOX_PIECES, 0>
michael@0 2053 {
michael@0 2054 MCompare *cmpMir_;
michael@0 2055
michael@0 2056 public:
michael@0 2057 LIR_HEADER(CompareVAndBranch)
michael@0 2058
michael@0 2059 static const size_t LhsInput = 0;
michael@0 2060 static const size_t RhsInput = BOX_PIECES;
michael@0 2061
michael@0 2062 LCompareVAndBranch(MCompare *cmpMir, MBasicBlock *ifTrue, MBasicBlock *ifFalse)
michael@0 2063 : cmpMir_(cmpMir)
michael@0 2064 {
michael@0 2065 setSuccessor(0, ifTrue);
michael@0 2066 setSuccessor(1, ifFalse);
michael@0 2067 }
michael@0 2068
michael@0 2069 MBasicBlock *ifTrue() const {
michael@0 2070 return getSuccessor(0);
michael@0 2071 }
michael@0 2072 MBasicBlock *ifFalse() const {
michael@0 2073 return getSuccessor(1);
michael@0 2074 }
michael@0 2075 MTest *mir() const {
michael@0 2076 return mir_->toTest();
michael@0 2077 }
michael@0 2078 MCompare *cmpMir() const {
michael@0 2079 return cmpMir_;
michael@0 2080 }
michael@0 2081 };
michael@0 2082
michael@0 2083 class LCompareVM : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
michael@0 2084 {
michael@0 2085 public:
michael@0 2086 LIR_HEADER(CompareVM)
michael@0 2087
michael@0 2088 static const size_t LhsInput = 0;
michael@0 2089 static const size_t RhsInput = BOX_PIECES;
michael@0 2090
michael@0 2091 MCompare *mir() const {
michael@0 2092 return mir_->toCompare();
michael@0 2093 }
michael@0 2094 };
michael@0 2095
michael@0 2096 class LBitAndAndBranch : public LControlInstructionHelper<2, 2, 0>
michael@0 2097 {
michael@0 2098 public:
michael@0 2099 LIR_HEADER(BitAndAndBranch)
michael@0 2100 LBitAndAndBranch(MBasicBlock *ifTrue, MBasicBlock *ifFalse)
michael@0 2101 {
michael@0 2102 setSuccessor(0, ifTrue);
michael@0 2103 setSuccessor(1, ifFalse);
michael@0 2104 }
michael@0 2105
michael@0 2106 MBasicBlock *ifTrue() const {
michael@0 2107 return getSuccessor(0);
michael@0 2108 }
michael@0 2109 MBasicBlock *ifFalse() const {
michael@0 2110 return getSuccessor(1);
michael@0 2111 }
michael@0 2112 const LAllocation *left() {
michael@0 2113 return getOperand(0);
michael@0 2114 }
michael@0 2115 const LAllocation *right() {
michael@0 2116 return getOperand(1);
michael@0 2117 }
michael@0 2118 };
michael@0 2119
michael@0 2120 class LIsNullOrLikeUndefined : public LInstructionHelper<1, BOX_PIECES, 2>
michael@0 2121 {
michael@0 2122 public:
michael@0 2123 LIR_HEADER(IsNullOrLikeUndefined)
michael@0 2124
michael@0 2125 LIsNullOrLikeUndefined(const LDefinition &temp, const LDefinition &tempToUnbox)
michael@0 2126 {
michael@0 2127 setTemp(0, temp);
michael@0 2128 setTemp(1, tempToUnbox);
michael@0 2129 }
michael@0 2130
michael@0 2131 static const size_t Value = 0;
michael@0 2132
michael@0 2133 MCompare *mir() {
michael@0 2134 return mir_->toCompare();
michael@0 2135 }
michael@0 2136
michael@0 2137 const LDefinition *temp() {
michael@0 2138 return getTemp(0);
michael@0 2139 }
michael@0 2140
michael@0 2141 const LDefinition *tempToUnbox() {
michael@0 2142 return getTemp(1);
michael@0 2143 }
michael@0 2144 };
michael@0 2145
michael@0 2146 class LIsNullOrLikeUndefinedAndBranch : public LControlInstructionHelper<2, BOX_PIECES, 2>
michael@0 2147 {
michael@0 2148 MCompare *cmpMir_;
michael@0 2149
michael@0 2150 public:
michael@0 2151 LIR_HEADER(IsNullOrLikeUndefinedAndBranch)
michael@0 2152
michael@0 2153 LIsNullOrLikeUndefinedAndBranch(MCompare *cmpMir, MBasicBlock *ifTrue, MBasicBlock *ifFalse,
michael@0 2154 const LDefinition &temp, const LDefinition &tempToUnbox)
michael@0 2155 : cmpMir_(cmpMir)
michael@0 2156 {
michael@0 2157 setSuccessor(0, ifTrue);
michael@0 2158 setSuccessor(1, ifFalse);
michael@0 2159 setTemp(0, temp);
michael@0 2160 setTemp(1, tempToUnbox);
michael@0 2161 }
michael@0 2162
michael@0 2163 static const size_t Value = 0;
michael@0 2164
michael@0 2165 MBasicBlock *ifTrue() const {
michael@0 2166 return getSuccessor(0);
michael@0 2167 }
michael@0 2168 MBasicBlock *ifFalse() const {
michael@0 2169 return getSuccessor(1);
michael@0 2170 }
michael@0 2171 MTest *mir() const {
michael@0 2172 return mir_->toTest();
michael@0 2173 }
michael@0 2174 MCompare *cmpMir() const {
michael@0 2175 return cmpMir_;
michael@0 2176 }
michael@0 2177 const LDefinition *temp() {
michael@0 2178 return getTemp(0);
michael@0 2179 }
michael@0 2180 const LDefinition *tempToUnbox() {
michael@0 2181 return getTemp(1);
michael@0 2182 }
michael@0 2183 };
michael@0 2184
michael@0 2185 // Takes an object and tests whether it emulates |undefined|, as determined by
michael@0 2186 // the JSCLASS_EMULATES_UNDEFINED class flag on unwrapped objects. See also
michael@0 2187 // js::EmulatesUndefined.
michael@0 2188 class LEmulatesUndefined : public LInstructionHelper<1, 1, 0>
michael@0 2189 {
michael@0 2190 public:
michael@0 2191 LIR_HEADER(EmulatesUndefined)
michael@0 2192
michael@0 2193 LEmulatesUndefined(const LAllocation &input)
michael@0 2194 {
michael@0 2195 setOperand(0, input);
michael@0 2196 }
michael@0 2197
michael@0 2198 MCompare *mir() {
michael@0 2199 return mir_->toCompare();
michael@0 2200 }
michael@0 2201 };
michael@0 2202
michael@0 2203 class LEmulatesUndefinedAndBranch : public LControlInstructionHelper<2, 1, 1>
michael@0 2204 {
michael@0 2205 MCompare *cmpMir_;
michael@0 2206
michael@0 2207 public:
michael@0 2208 LIR_HEADER(EmulatesUndefinedAndBranch)
michael@0 2209
michael@0 2210 LEmulatesUndefinedAndBranch(MCompare *cmpMir, const LAllocation &input,
michael@0 2211 MBasicBlock *ifTrue, MBasicBlock *ifFalse,
michael@0 2212 const LDefinition &temp)
michael@0 2213 : cmpMir_(cmpMir)
michael@0 2214 {
michael@0 2215 setOperand(0, input);
michael@0 2216 setSuccessor(0, ifTrue);
michael@0 2217 setSuccessor(1, ifFalse);
michael@0 2218 setTemp(0, temp);
michael@0 2219 }
michael@0 2220
michael@0 2221 MBasicBlock *ifTrue() const {
michael@0 2222 return getSuccessor(0);
michael@0 2223 }
michael@0 2224 MBasicBlock *ifFalse() const {
michael@0 2225 return getSuccessor(1);
michael@0 2226 }
michael@0 2227 MTest *mir() const {
michael@0 2228 return mir_->toTest();
michael@0 2229 }
michael@0 2230 MCompare *cmpMir() const {
michael@0 2231 return cmpMir_;
michael@0 2232 }
michael@0 2233 const LDefinition *temp() {
michael@0 2234 return getTemp(0);
michael@0 2235 }
michael@0 2236 };
michael@0 2237
michael@0 2238 // Not operation on an integer.
michael@0 2239 class LNotI : public LInstructionHelper<1, 1, 0>
michael@0 2240 {
michael@0 2241 public:
michael@0 2242 LIR_HEADER(NotI)
michael@0 2243
michael@0 2244 LNotI(const LAllocation &input) {
michael@0 2245 setOperand(0, input);
michael@0 2246 }
michael@0 2247 };
michael@0 2248
michael@0 2249 // Not operation on a double.
michael@0 2250 class LNotD : public LInstructionHelper<1, 1, 0>
michael@0 2251 {
michael@0 2252 public:
michael@0 2253 LIR_HEADER(NotD)
michael@0 2254
michael@0 2255 LNotD(const LAllocation &input) {
michael@0 2256 setOperand(0, input);
michael@0 2257 }
michael@0 2258
michael@0 2259 MNot *mir() {
michael@0 2260 return mir_->toNot();
michael@0 2261 }
michael@0 2262 };
michael@0 2263
michael@0 2264 // Not operation on a float32.
michael@0 2265 class LNotF : public LInstructionHelper<1, 1, 0>
michael@0 2266 {
michael@0 2267 public:
michael@0 2268 LIR_HEADER(NotF)
michael@0 2269
michael@0 2270 LNotF(const LAllocation &input) {
michael@0 2271 setOperand(0, input);
michael@0 2272 }
michael@0 2273
michael@0 2274 MNot *mir() {
michael@0 2275 return mir_->toNot();
michael@0 2276 }
michael@0 2277 };
michael@0 2278
michael@0 2279 // Boolean complement operation on an object.
michael@0 2280 class LNotO : public LInstructionHelper<1, 1, 0>
michael@0 2281 {
michael@0 2282 public:
michael@0 2283 LIR_HEADER(NotO)
michael@0 2284
michael@0 2285 LNotO(const LAllocation &input)
michael@0 2286 {
michael@0 2287 setOperand(0, input);
michael@0 2288 }
michael@0 2289
michael@0 2290 MNot *mir() {
michael@0 2291 return mir_->toNot();
michael@0 2292 }
michael@0 2293 };
michael@0 2294
michael@0 2295 // Boolean complement operation on a value.
michael@0 2296 class LNotV : public LInstructionHelper<1, BOX_PIECES, 3>
michael@0 2297 {
michael@0 2298 public:
michael@0 2299 LIR_HEADER(NotV)
michael@0 2300
michael@0 2301 static const size_t Input = 0;
michael@0 2302 LNotV(const LDefinition &temp0, const LDefinition &temp1, const LDefinition &temp2)
michael@0 2303 {
michael@0 2304 setTemp(0, temp0);
michael@0 2305 setTemp(1, temp1);
michael@0 2306 setTemp(2, temp2);
michael@0 2307 }
michael@0 2308
michael@0 2309 const LDefinition *tempFloat() {
michael@0 2310 return getTemp(0);
michael@0 2311 }
michael@0 2312
michael@0 2313 const LDefinition *temp1() {
michael@0 2314 return getTemp(1);
michael@0 2315 }
michael@0 2316
michael@0 2317 const LDefinition *temp2() {
michael@0 2318 return getTemp(2);
michael@0 2319 }
michael@0 2320
michael@0 2321 MNot *mir() {
michael@0 2322 return mir_->toNot();
michael@0 2323 }
michael@0 2324 };
michael@0 2325
michael@0 2326 // Bitwise not operation, takes a 32-bit integer as input and returning
michael@0 2327 // a 32-bit integer result as an output.
michael@0 2328 class LBitNotI : public LInstructionHelper<1, 1, 0>
michael@0 2329 {
michael@0 2330 public:
michael@0 2331 LIR_HEADER(BitNotI)
michael@0 2332 };
michael@0 2333
michael@0 2334 // Call a VM function to perform a BITNOT operation.
michael@0 2335 class LBitNotV : public LCallInstructionHelper<1, BOX_PIECES, 0>
michael@0 2336 {
michael@0 2337 public:
michael@0 2338 LIR_HEADER(BitNotV)
michael@0 2339
michael@0 2340 static const size_t Input = 0;
michael@0 2341 };
michael@0 2342
michael@0 2343 // Binary bitwise operation, taking two 32-bit integers as inputs and returning
michael@0 2344 // a 32-bit integer result as an output.
michael@0 2345 class LBitOpI : public LInstructionHelper<1, 2, 0>
michael@0 2346 {
michael@0 2347 JSOp op_;
michael@0 2348
michael@0 2349 public:
michael@0 2350 LIR_HEADER(BitOpI)
michael@0 2351
michael@0 2352 LBitOpI(JSOp op)
michael@0 2353 : op_(op)
michael@0 2354 { }
michael@0 2355
michael@0 2356 const char *extraName() const {
michael@0 2357 if (bitop() == JSOP_URSH && mir_->toUrsh()->bailoutsDisabled())
michael@0 2358 return "ursh:BailoutsDisabled";
michael@0 2359 return js_CodeName[op_];
michael@0 2360 }
michael@0 2361
michael@0 2362 JSOp bitop() const {
michael@0 2363 return op_;
michael@0 2364 }
michael@0 2365 };
michael@0 2366
michael@0 2367 // Call a VM function to perform a bitwise operation.
michael@0 2368 class LBitOpV : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
michael@0 2369 {
michael@0 2370 JSOp jsop_;
michael@0 2371
michael@0 2372 public:
michael@0 2373 LIR_HEADER(BitOpV)
michael@0 2374
michael@0 2375 LBitOpV(JSOp jsop)
michael@0 2376 : jsop_(jsop)
michael@0 2377 { }
michael@0 2378
michael@0 2379 JSOp jsop() const {
michael@0 2380 return jsop_;
michael@0 2381 }
michael@0 2382
michael@0 2383 const char *extraName() const {
michael@0 2384 return js_CodeName[jsop_];
michael@0 2385 }
michael@0 2386
michael@0 2387 static const size_t LhsInput = 0;
michael@0 2388 static const size_t RhsInput = BOX_PIECES;
michael@0 2389 };
michael@0 2390
michael@0 2391 // Shift operation, taking two 32-bit integers as inputs and returning
michael@0 2392 // a 32-bit integer result as an output.
michael@0 2393 class LShiftI : public LBinaryMath<0>
michael@0 2394 {
michael@0 2395 JSOp op_;
michael@0 2396
michael@0 2397 public:
michael@0 2398 LIR_HEADER(ShiftI)
michael@0 2399
michael@0 2400 LShiftI(JSOp op)
michael@0 2401 : op_(op)
michael@0 2402 { }
michael@0 2403
michael@0 2404 JSOp bitop() {
michael@0 2405 return op_;
michael@0 2406 }
michael@0 2407
michael@0 2408 MInstruction *mir() {
michael@0 2409 return mir_->toInstruction();
michael@0 2410 }
michael@0 2411
michael@0 2412 const char *extraName() const {
michael@0 2413 return js_CodeName[op_];
michael@0 2414 }
michael@0 2415 };
michael@0 2416
michael@0 2417 class LUrshD : public LBinaryMath<1>
michael@0 2418 {
michael@0 2419 public:
michael@0 2420 LIR_HEADER(UrshD)
michael@0 2421
michael@0 2422 LUrshD(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp) {
michael@0 2423 setOperand(0, lhs);
michael@0 2424 setOperand(1, rhs);
michael@0 2425 setTemp(0, temp);
michael@0 2426 }
michael@0 2427 const LDefinition *temp() {
michael@0 2428 return getTemp(0);
michael@0 2429 }
michael@0 2430 };
michael@0 2431
michael@0 2432 // Returns from the function being compiled (not used in inlined frames). The
michael@0 2433 // input must be a box.
michael@0 2434 class LReturn : public LInstructionHelper<0, BOX_PIECES, 0>
michael@0 2435 {
michael@0 2436 public:
michael@0 2437 LIR_HEADER(Return)
michael@0 2438 };
michael@0 2439
michael@0 2440 class LThrow : public LCallInstructionHelper<0, BOX_PIECES, 0>
michael@0 2441 {
michael@0 2442 public:
michael@0 2443 LIR_HEADER(Throw)
michael@0 2444
michael@0 2445 static const size_t Value = 0;
michael@0 2446 };
michael@0 2447
michael@0 2448 class LMinMaxI : public LInstructionHelper<1, 2, 0>
michael@0 2449 {
michael@0 2450 public:
michael@0 2451 LIR_HEADER(MinMaxI)
michael@0 2452 LMinMaxI(const LAllocation &first, const LAllocation &second)
michael@0 2453 {
michael@0 2454 setOperand(0, first);
michael@0 2455 setOperand(1, second);
michael@0 2456 }
michael@0 2457
michael@0 2458 const LAllocation *first() {
michael@0 2459 return this->getOperand(0);
michael@0 2460 }
michael@0 2461 const LAllocation *second() {
michael@0 2462 return this->getOperand(1);
michael@0 2463 }
michael@0 2464 const LDefinition *output() {
michael@0 2465 return this->getDef(0);
michael@0 2466 }
michael@0 2467 MMinMax *mir() const {
michael@0 2468 return mir_->toMinMax();
michael@0 2469 }
michael@0 2470 const char *extraName() const {
michael@0 2471 return mir()->isMax() ? "Max" : "Min";
michael@0 2472 }
michael@0 2473 };
michael@0 2474
michael@0 2475 class LMinMaxD : public LInstructionHelper<1, 2, 0>
michael@0 2476 {
michael@0 2477 public:
michael@0 2478 LIR_HEADER(MinMaxD)
michael@0 2479 LMinMaxD(const LAllocation &first, const LAllocation &second)
michael@0 2480 {
michael@0 2481 setOperand(0, first);
michael@0 2482 setOperand(1, second);
michael@0 2483 }
michael@0 2484
michael@0 2485 const LAllocation *first() {
michael@0 2486 return this->getOperand(0);
michael@0 2487 }
michael@0 2488 const LAllocation *second() {
michael@0 2489 return this->getOperand(1);
michael@0 2490 }
michael@0 2491 const LDefinition *output() {
michael@0 2492 return this->getDef(0);
michael@0 2493 }
michael@0 2494 MMinMax *mir() const {
michael@0 2495 return mir_->toMinMax();
michael@0 2496 }
michael@0 2497 const char *extraName() const {
michael@0 2498 return mir()->isMax() ? "Max" : "Min";
michael@0 2499 }
michael@0 2500 };
michael@0 2501
michael@0 2502 // Negative of an integer
michael@0 2503 class LNegI : public LInstructionHelper<1, 1, 0>
michael@0 2504 {
michael@0 2505 public:
michael@0 2506 LIR_HEADER(NegI);
michael@0 2507 LNegI(const LAllocation &num) {
michael@0 2508 setOperand(0, num);
michael@0 2509 }
michael@0 2510 };
michael@0 2511
michael@0 2512 // Negative of a double.
michael@0 2513 class LNegD : public LInstructionHelper<1, 1, 0>
michael@0 2514 {
michael@0 2515 public:
michael@0 2516 LIR_HEADER(NegD)
michael@0 2517 LNegD(const LAllocation &num) {
michael@0 2518 setOperand(0, num);
michael@0 2519 }
michael@0 2520 };
michael@0 2521
michael@0 2522 // Negative of a float32.
michael@0 2523 class LNegF : public LInstructionHelper<1, 1, 0>
michael@0 2524 {
michael@0 2525 public:
michael@0 2526 LIR_HEADER(NegF)
michael@0 2527 LNegF(const LAllocation &num) {
michael@0 2528 setOperand(0, num);
michael@0 2529 }
michael@0 2530 };
michael@0 2531
michael@0 2532 // Absolute value of an integer.
michael@0 2533 class LAbsI : public LInstructionHelper<1, 1, 0>
michael@0 2534 {
michael@0 2535 public:
michael@0 2536 LIR_HEADER(AbsI)
michael@0 2537 LAbsI(const LAllocation &num) {
michael@0 2538 setOperand(0, num);
michael@0 2539 }
michael@0 2540 };
michael@0 2541
michael@0 2542 // Absolute value of a double.
michael@0 2543 class LAbsD : public LInstructionHelper<1, 1, 0>
michael@0 2544 {
michael@0 2545 public:
michael@0 2546 LIR_HEADER(AbsD)
michael@0 2547 LAbsD(const LAllocation &num) {
michael@0 2548 setOperand(0, num);
michael@0 2549 }
michael@0 2550 };
michael@0 2551
michael@0 2552 // Absolute value of a float32.
michael@0 2553 class LAbsF : public LInstructionHelper<1, 1, 0>
michael@0 2554 {
michael@0 2555 public:
michael@0 2556 LIR_HEADER(AbsF)
michael@0 2557 LAbsF(const LAllocation &num) {
michael@0 2558 setOperand(0, num);
michael@0 2559 }
michael@0 2560 };
michael@0 2561
michael@0 2562 // Square root of a double.
michael@0 2563 class LSqrtD : public LInstructionHelper<1, 1, 0>
michael@0 2564 {
michael@0 2565 public:
michael@0 2566 LIR_HEADER(SqrtD)
michael@0 2567 LSqrtD(const LAllocation &num) {
michael@0 2568 setOperand(0, num);
michael@0 2569 }
michael@0 2570 };
michael@0 2571
michael@0 2572 // Square root of a float32.
michael@0 2573 class LSqrtF : public LInstructionHelper<1, 1, 0>
michael@0 2574 {
michael@0 2575 public:
michael@0 2576 LIR_HEADER(SqrtF)
michael@0 2577 LSqrtF(const LAllocation &num) {
michael@0 2578 setOperand(0, num);
michael@0 2579 }
michael@0 2580 };
michael@0 2581
michael@0 2582 class LAtan2D : public LCallInstructionHelper<1, 2, 1>
michael@0 2583 {
michael@0 2584 public:
michael@0 2585 LIR_HEADER(Atan2D)
michael@0 2586 LAtan2D(const LAllocation &y, const LAllocation &x, const LDefinition &temp) {
michael@0 2587 setOperand(0, y);
michael@0 2588 setOperand(1, x);
michael@0 2589 setTemp(0, temp);
michael@0 2590 }
michael@0 2591
michael@0 2592 const LAllocation *y() {
michael@0 2593 return getOperand(0);
michael@0 2594 }
michael@0 2595
michael@0 2596 const LAllocation *x() {
michael@0 2597 return getOperand(1);
michael@0 2598 }
michael@0 2599
michael@0 2600 const LDefinition *temp() {
michael@0 2601 return getTemp(0);
michael@0 2602 }
michael@0 2603
michael@0 2604 const LDefinition *output() {
michael@0 2605 return getDef(0);
michael@0 2606 }
michael@0 2607 };
michael@0 2608
michael@0 2609 class LHypot : public LCallInstructionHelper<1, 2, 1>
michael@0 2610 {
michael@0 2611 public:
michael@0 2612 LIR_HEADER(Hypot)
michael@0 2613 LHypot(const LAllocation &x, const LAllocation &y, const LDefinition &temp) {
michael@0 2614 setOperand(0, x);
michael@0 2615 setOperand(1, y);
michael@0 2616 setTemp(0, temp);
michael@0 2617 }
michael@0 2618
michael@0 2619 const LAllocation *x() {
michael@0 2620 return getOperand(0);
michael@0 2621 }
michael@0 2622
michael@0 2623 const LAllocation *y() {
michael@0 2624 return getOperand(1);
michael@0 2625 }
michael@0 2626
michael@0 2627 const LDefinition *temp() {
michael@0 2628 return getTemp(0);
michael@0 2629 }
michael@0 2630
michael@0 2631 const LDefinition *output() {
michael@0 2632 return getDef(0);
michael@0 2633 }
michael@0 2634 };
michael@0 2635
michael@0 2636 // Double raised to an integer power.
michael@0 2637 class LPowI : public LCallInstructionHelper<1, 2, 1>
michael@0 2638 {
michael@0 2639 public:
michael@0 2640 LIR_HEADER(PowI)
michael@0 2641 LPowI(const LAllocation &value, const LAllocation &power, const LDefinition &temp) {
michael@0 2642 setOperand(0, value);
michael@0 2643 setOperand(1, power);
michael@0 2644 setTemp(0, temp);
michael@0 2645 }
michael@0 2646
michael@0 2647 const LAllocation *value() {
michael@0 2648 return getOperand(0);
michael@0 2649 }
michael@0 2650 const LAllocation *power() {
michael@0 2651 return getOperand(1);
michael@0 2652 }
michael@0 2653 const LDefinition *temp() {
michael@0 2654 return getTemp(0);
michael@0 2655 }
michael@0 2656 };
michael@0 2657
michael@0 2658 // Double raised to a double power.
michael@0 2659 class LPowD : public LCallInstructionHelper<1, 2, 1>
michael@0 2660 {
michael@0 2661 public:
michael@0 2662 LIR_HEADER(PowD)
michael@0 2663 LPowD(const LAllocation &value, const LAllocation &power, const LDefinition &temp) {
michael@0 2664 setOperand(0, value);
michael@0 2665 setOperand(1, power);
michael@0 2666 setTemp(0, temp);
michael@0 2667 }
michael@0 2668
michael@0 2669 const LAllocation *value() {
michael@0 2670 return getOperand(0);
michael@0 2671 }
michael@0 2672 const LAllocation *power() {
michael@0 2673 return getOperand(1);
michael@0 2674 }
michael@0 2675 const LDefinition *temp() {
michael@0 2676 return getTemp(0);
michael@0 2677 }
michael@0 2678 };
michael@0 2679
michael@0 2680 // Math.random().
michael@0 2681 class LRandom : public LCallInstructionHelper<1, 0, 2>
michael@0 2682 {
michael@0 2683 public:
michael@0 2684 LIR_HEADER(Random)
michael@0 2685 LRandom(const LDefinition &temp, const LDefinition &temp2) {
michael@0 2686 setTemp(0, temp);
michael@0 2687 setTemp(1, temp2);
michael@0 2688 }
michael@0 2689 const LDefinition *temp() {
michael@0 2690 return getTemp(0);
michael@0 2691 }
michael@0 2692 const LDefinition *temp2() {
michael@0 2693 return getTemp(1);
michael@0 2694 }
michael@0 2695 };
michael@0 2696
michael@0 2697 class LMathFunctionD : public LCallInstructionHelper<1, 1, 1>
michael@0 2698 {
michael@0 2699 public:
michael@0 2700 LIR_HEADER(MathFunctionD)
michael@0 2701 LMathFunctionD(const LAllocation &input, const LDefinition &temp) {
michael@0 2702 setOperand(0, input);
michael@0 2703 setTemp(0, temp);
michael@0 2704 }
michael@0 2705
michael@0 2706 const LDefinition *temp() {
michael@0 2707 return getTemp(0);
michael@0 2708 }
michael@0 2709 MMathFunction *mir() const {
michael@0 2710 return mir_->toMathFunction();
michael@0 2711 }
michael@0 2712 const char *extraName() const {
michael@0 2713 return MMathFunction::FunctionName(mir()->function());
michael@0 2714 }
michael@0 2715 };
michael@0 2716
michael@0 2717 class LMathFunctionF : public LCallInstructionHelper<1, 1, 1>
michael@0 2718 {
michael@0 2719 public:
michael@0 2720 LIR_HEADER(MathFunctionF)
michael@0 2721 LMathFunctionF(const LAllocation &input, const LDefinition &temp) {
michael@0 2722 setOperand(0, input);
michael@0 2723 setTemp(0, temp);
michael@0 2724 }
michael@0 2725
michael@0 2726 const LDefinition *temp() {
michael@0 2727 return getTemp(0);
michael@0 2728 }
michael@0 2729 MMathFunction *mir() const {
michael@0 2730 return mir_->toMathFunction();
michael@0 2731 }
michael@0 2732 const char *extraName() const {
michael@0 2733 return MMathFunction::FunctionName(mir()->function());
michael@0 2734 }
michael@0 2735 };
michael@0 2736
michael@0 2737 // Adds two integers, returning an integer value.
michael@0 2738 class LAddI : public LBinaryMath<0>
michael@0 2739 {
michael@0 2740 bool recoversInput_;
michael@0 2741
michael@0 2742 public:
michael@0 2743 LIR_HEADER(AddI)
michael@0 2744
michael@0 2745 LAddI()
michael@0 2746 : recoversInput_(false)
michael@0 2747 { }
michael@0 2748
michael@0 2749 const char *extraName() const {
michael@0 2750 return snapshot() ? "OverflowCheck" : nullptr;
michael@0 2751 }
michael@0 2752
michael@0 2753 virtual bool recoversInput() const {
michael@0 2754 return recoversInput_;
michael@0 2755 }
michael@0 2756 void setRecoversInput() {
michael@0 2757 recoversInput_ = true;
michael@0 2758 }
michael@0 2759 };
michael@0 2760
michael@0 2761 // Subtracts two integers, returning an integer value.
michael@0 2762 class LSubI : public LBinaryMath<0>
michael@0 2763 {
michael@0 2764 bool recoversInput_;
michael@0 2765
michael@0 2766 public:
michael@0 2767 LIR_HEADER(SubI)
michael@0 2768
michael@0 2769 LSubI()
michael@0 2770 : recoversInput_(false)
michael@0 2771 { }
michael@0 2772
michael@0 2773 const char *extraName() const {
michael@0 2774 return snapshot() ? "OverflowCheck" : nullptr;
michael@0 2775 }
michael@0 2776
michael@0 2777 virtual bool recoversInput() const {
michael@0 2778 return recoversInput_;
michael@0 2779 }
michael@0 2780 void setRecoversInput() {
michael@0 2781 recoversInput_ = true;
michael@0 2782 }
michael@0 2783 };
michael@0 2784
michael@0 2785 // Performs an add, sub, mul, or div on two double values.
michael@0 2786 class LMathD : public LBinaryMath<0>
michael@0 2787 {
michael@0 2788 JSOp jsop_;
michael@0 2789
michael@0 2790 public:
michael@0 2791 LIR_HEADER(MathD)
michael@0 2792
michael@0 2793 LMathD(JSOp jsop)
michael@0 2794 : jsop_(jsop)
michael@0 2795 { }
michael@0 2796
michael@0 2797 JSOp jsop() const {
michael@0 2798 return jsop_;
michael@0 2799 }
michael@0 2800
michael@0 2801 const char *extraName() const {
michael@0 2802 return js_CodeName[jsop_];
michael@0 2803 }
michael@0 2804 };
michael@0 2805
michael@0 2806 // Performs an add, sub, mul, or div on two double values.
michael@0 2807 class LMathF: public LBinaryMath<0>
michael@0 2808 {
michael@0 2809 JSOp jsop_;
michael@0 2810
michael@0 2811 public:
michael@0 2812 LIR_HEADER(MathF)
michael@0 2813
michael@0 2814 LMathF(JSOp jsop)
michael@0 2815 : jsop_(jsop)
michael@0 2816 { }
michael@0 2817
michael@0 2818 JSOp jsop() const {
michael@0 2819 return jsop_;
michael@0 2820 }
michael@0 2821
michael@0 2822 const char *extraName() const {
michael@0 2823 return js_CodeName[jsop_];
michael@0 2824 }
michael@0 2825 };
michael@0 2826
michael@0 2827 class LModD : public LBinaryMath<1>
michael@0 2828 {
michael@0 2829 public:
michael@0 2830 LIR_HEADER(ModD)
michael@0 2831
michael@0 2832 LModD(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp) {
michael@0 2833 setOperand(0, lhs);
michael@0 2834 setOperand(1, rhs);
michael@0 2835 setTemp(0, temp);
michael@0 2836 }
michael@0 2837 const LDefinition *temp() {
michael@0 2838 return getTemp(0);
michael@0 2839 }
michael@0 2840 bool isCall() const {
michael@0 2841 return true;
michael@0 2842 }
michael@0 2843 };
michael@0 2844
michael@0 2845 // Call a VM function to perform a binary operation.
michael@0 2846 class LBinaryV : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0>
michael@0 2847 {
michael@0 2848 JSOp jsop_;
michael@0 2849
michael@0 2850 public:
michael@0 2851 LIR_HEADER(BinaryV)
michael@0 2852
michael@0 2853 LBinaryV(JSOp jsop)
michael@0 2854 : jsop_(jsop)
michael@0 2855 { }
michael@0 2856
michael@0 2857 JSOp jsop() const {
michael@0 2858 return jsop_;
michael@0 2859 }
michael@0 2860
michael@0 2861 const char *extraName() const {
michael@0 2862 return js_CodeName[jsop_];
michael@0 2863 }
michael@0 2864
michael@0 2865 static const size_t LhsInput = 0;
michael@0 2866 static const size_t RhsInput = BOX_PIECES;
michael@0 2867 };
michael@0 2868
michael@0 2869 // Adds two string, returning a string.
michael@0 2870 class LConcat : public LInstructionHelper<1, 2, 5>
michael@0 2871 {
michael@0 2872 public:
michael@0 2873 LIR_HEADER(Concat)
michael@0 2874
michael@0 2875 LConcat(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp1,
michael@0 2876 const LDefinition &temp2, const LDefinition &temp3, const LDefinition &temp4,
michael@0 2877 const LDefinition &temp5)
michael@0 2878 {
michael@0 2879 setOperand(0, lhs);
michael@0 2880 setOperand(1, rhs);
michael@0 2881 setTemp(0, temp1);
michael@0 2882 setTemp(1, temp2);
michael@0 2883 setTemp(2, temp3);
michael@0 2884 setTemp(3, temp4);
michael@0 2885 setTemp(4, temp5);
michael@0 2886 }
michael@0 2887
michael@0 2888 const LAllocation *lhs() {
michael@0 2889 return this->getOperand(0);
michael@0 2890 }
michael@0 2891 const LAllocation *rhs() {
michael@0 2892 return this->getOperand(1);
michael@0 2893 }
michael@0 2894 const LDefinition *temp1() {
michael@0 2895 return this->getTemp(0);
michael@0 2896 }
michael@0 2897 const LDefinition *temp2() {
michael@0 2898 return this->getTemp(1);
michael@0 2899 }
michael@0 2900 const LDefinition *temp3() {
michael@0 2901 return this->getTemp(2);
michael@0 2902 }
michael@0 2903 const LDefinition *temp4() {
michael@0 2904 return this->getTemp(3);
michael@0 2905 }
michael@0 2906 const LDefinition *temp5() {
michael@0 2907 return this->getTemp(4);
michael@0 2908 }
michael@0 2909 };
michael@0 2910
michael@0 2911 class LConcatPar : public LInstructionHelper<1, 3, 4>
michael@0 2912 {
michael@0 2913 public:
michael@0 2914 LIR_HEADER(ConcatPar)
michael@0 2915
michael@0 2916 LConcatPar(const LAllocation &cx, const LAllocation &lhs, const LAllocation &rhs,
michael@0 2917 const LDefinition &temp1, const LDefinition &temp2, const LDefinition &temp3,
michael@0 2918 const LDefinition &temp4)
michael@0 2919 {
michael@0 2920 setOperand(0, cx);
michael@0 2921 setOperand(1, lhs);
michael@0 2922 setOperand(2, rhs);
michael@0 2923 setTemp(0, temp1);
michael@0 2924 setTemp(1, temp2);
michael@0 2925 setTemp(2, temp3);
michael@0 2926 setTemp(3, temp4);
michael@0 2927 }
michael@0 2928
michael@0 2929 const LAllocation *forkJoinContext() {
michael@0 2930 return this->getOperand(0);
michael@0 2931 }
michael@0 2932 const LAllocation *lhs() {
michael@0 2933 return this->getOperand(1);
michael@0 2934 }
michael@0 2935 const LAllocation *rhs() {
michael@0 2936 return this->getOperand(2);
michael@0 2937 }
michael@0 2938 const LDefinition *temp1() {
michael@0 2939 return this->getTemp(0);
michael@0 2940 }
michael@0 2941 const LDefinition *temp2() {
michael@0 2942 return this->getTemp(1);
michael@0 2943 }
michael@0 2944 const LDefinition *temp3() {
michael@0 2945 return this->getTemp(2);
michael@0 2946 }
michael@0 2947 const LDefinition *temp4() {
michael@0 2948 return this->getTemp(3);
michael@0 2949 }
michael@0 2950 };
michael@0 2951
michael@0 2952 // Get uint16 character code from a string.
michael@0 2953 class LCharCodeAt : public LInstructionHelper<1, 2, 0>
michael@0 2954 {
michael@0 2955 public:
michael@0 2956 LIR_HEADER(CharCodeAt)
michael@0 2957
michael@0 2958 LCharCodeAt(const LAllocation &str, const LAllocation &index) {
michael@0 2959 setOperand(0, str);
michael@0 2960 setOperand(1, index);
michael@0 2961 }
michael@0 2962
michael@0 2963 const LAllocation *str() {
michael@0 2964 return this->getOperand(0);
michael@0 2965 }
michael@0 2966 const LAllocation *index() {
michael@0 2967 return this->getOperand(1);
michael@0 2968 }
michael@0 2969 };
michael@0 2970
michael@0 2971 // Convert uint16 character code to a string.
michael@0 2972 class LFromCharCode : public LInstructionHelper<1, 1, 0>
michael@0 2973 {
michael@0 2974 public:
michael@0 2975 LIR_HEADER(FromCharCode)
michael@0 2976
michael@0 2977 LFromCharCode(const LAllocation &code) {
michael@0 2978 setOperand(0, code);
michael@0 2979 }
michael@0 2980
michael@0 2981 const LAllocation *code() {
michael@0 2982 return this->getOperand(0);
michael@0 2983 }
michael@0 2984 };
michael@0 2985
michael@0 2986 class LStringSplit : public LCallInstructionHelper<1, 2, 0>
michael@0 2987 {
michael@0 2988 public:
michael@0 2989 LIR_HEADER(StringSplit)
michael@0 2990
michael@0 2991 LStringSplit(const LAllocation &string, const LAllocation &separator) {
michael@0 2992 setOperand(0, string);
michael@0 2993 setOperand(1, separator);
michael@0 2994 }
michael@0 2995 const LAllocation *string() {
michael@0 2996 return getOperand(0);
michael@0 2997 }
michael@0 2998 const LAllocation *separator() {
michael@0 2999 return getOperand(1);
michael@0 3000 }
michael@0 3001 const MStringSplit *mir() const {
michael@0 3002 return mir_->toStringSplit();
michael@0 3003 }
michael@0 3004 };
michael@0 3005
michael@0 3006 // Convert a 32-bit integer to a double.
michael@0 3007 class LInt32ToDouble : public LInstructionHelper<1, 1, 0>
michael@0 3008 {
michael@0 3009 public:
michael@0 3010 LIR_HEADER(Int32ToDouble)
michael@0 3011
michael@0 3012 LInt32ToDouble(const LAllocation &input) {
michael@0 3013 setOperand(0, input);
michael@0 3014 }
michael@0 3015 };
michael@0 3016
michael@0 3017 // Convert a 32-bit float to a double.
michael@0 3018 class LFloat32ToDouble : public LInstructionHelper<1, 1, 0>
michael@0 3019 {
michael@0 3020 public:
michael@0 3021 LIR_HEADER(Float32ToDouble)
michael@0 3022
michael@0 3023 LFloat32ToDouble(const LAllocation &input) {
michael@0 3024 setOperand(0, input);
michael@0 3025 }
michael@0 3026 };
michael@0 3027
michael@0 3028 // Convert a double to a 32-bit float.
michael@0 3029 class LDoubleToFloat32 : public LInstructionHelper<1, 1, 0>
michael@0 3030 {
michael@0 3031 public:
michael@0 3032 LIR_HEADER(DoubleToFloat32)
michael@0 3033
michael@0 3034 LDoubleToFloat32(const LAllocation &input) {
michael@0 3035 setOperand(0, input);
michael@0 3036 }
michael@0 3037 };
michael@0 3038
michael@0 3039 // Convert a 32-bit integer to a float32.
michael@0 3040 class LInt32ToFloat32 : public LInstructionHelper<1, 1, 0>
michael@0 3041 {
michael@0 3042 public:
michael@0 3043 LIR_HEADER(Int32ToFloat32)
michael@0 3044
michael@0 3045 LInt32ToFloat32(const LAllocation &input) {
michael@0 3046 setOperand(0, input);
michael@0 3047 }
michael@0 3048 };
michael@0 3049
michael@0 3050 // Convert a value to a double.
michael@0 3051 class LValueToDouble : public LInstructionHelper<1, BOX_PIECES, 0>
michael@0 3052 {
michael@0 3053 public:
michael@0 3054 LIR_HEADER(ValueToDouble)
michael@0 3055 static const size_t Input = 0;
michael@0 3056
michael@0 3057 MToDouble *mir() {
michael@0 3058 return mir_->toToDouble();
michael@0 3059 }
michael@0 3060 };
michael@0 3061
michael@0 3062 // Convert a value to a float32.
michael@0 3063 class LValueToFloat32 : public LInstructionHelper<1, BOX_PIECES, 0>
michael@0 3064 {
michael@0 3065 public:
michael@0 3066 LIR_HEADER(ValueToFloat32)
michael@0 3067 static const size_t Input = 0;
michael@0 3068
michael@0 3069 MToFloat32 *mir() {
michael@0 3070 return mir_->toToFloat32();
michael@0 3071 }
michael@0 3072 };
michael@0 3073
michael@0 3074 // Convert a value to an int32.
michael@0 3075 // Input: components of a Value
michael@0 3076 // Output: 32-bit integer
michael@0 3077 // Bailout: undefined, string, object, or non-int32 double
michael@0 3078 // Temps: one float register, one GP register
michael@0 3079 //
michael@0 3080 // This instruction requires a temporary float register.
michael@0 3081 class LValueToInt32 : public LInstructionHelper<1, BOX_PIECES, 2>
michael@0 3082 {
michael@0 3083 public:
michael@0 3084 enum Mode {
michael@0 3085 NORMAL,
michael@0 3086 TRUNCATE
michael@0 3087 };
michael@0 3088
michael@0 3089 private:
michael@0 3090 Mode mode_;
michael@0 3091
michael@0 3092 public:
michael@0 3093 LIR_HEADER(ValueToInt32)
michael@0 3094
michael@0 3095 LValueToInt32(const LDefinition &temp0, const LDefinition &temp1, Mode mode)
michael@0 3096 : mode_(mode)
michael@0 3097 {
michael@0 3098 setTemp(0, temp0);
michael@0 3099 setTemp(1, temp1);
michael@0 3100 }
michael@0 3101
michael@0 3102 const char *extraName() const {
michael@0 3103 return mode() == NORMAL ? "Normal" : "Truncate";
michael@0 3104 }
michael@0 3105
michael@0 3106 static const size_t Input = 0;
michael@0 3107
michael@0 3108 Mode mode() const {
michael@0 3109 return mode_;
michael@0 3110 }
michael@0 3111 const LDefinition *tempFloat() {
michael@0 3112 return getTemp(0);
michael@0 3113 }
michael@0 3114 const LDefinition *temp() {
michael@0 3115 return getTemp(1);
michael@0 3116 }
michael@0 3117 MToInt32 *mirNormal() const {
michael@0 3118 JS_ASSERT(mode_ == NORMAL);
michael@0 3119 return mir_->toToInt32();
michael@0 3120 }
michael@0 3121 MTruncateToInt32 *mirTruncate() const {
michael@0 3122 JS_ASSERT(mode_ == TRUNCATE);
michael@0 3123 return mir_->toTruncateToInt32();
michael@0 3124 }
michael@0 3125 };
michael@0 3126
michael@0 3127 // Convert a double to an int32.
michael@0 3128 // Input: floating-point register
michael@0 3129 // Output: 32-bit integer
michael@0 3130 // Bailout: if the double cannot be converted to an integer.
michael@0 3131 class LDoubleToInt32 : public LInstructionHelper<1, 1, 0>
michael@0 3132 {
michael@0 3133 public:
michael@0 3134 LIR_HEADER(DoubleToInt32)
michael@0 3135
michael@0 3136 LDoubleToInt32(const LAllocation &in) {
michael@0 3137 setOperand(0, in);
michael@0 3138 }
michael@0 3139
michael@0 3140 MToInt32 *mir() const {
michael@0 3141 return mir_->toToInt32();
michael@0 3142 }
michael@0 3143 };
michael@0 3144
michael@0 3145 // Convert a float32 to an int32.
michael@0 3146 // Input: floating-point register
michael@0 3147 // Output: 32-bit integer
michael@0 3148 // Bailout: if the float32 cannot be converted to an integer.
michael@0 3149 class LFloat32ToInt32 : public LInstructionHelper<1, 1, 0>
michael@0 3150 {
michael@0 3151 public:
michael@0 3152 LIR_HEADER(Float32ToInt32)
michael@0 3153
michael@0 3154 LFloat32ToInt32(const LAllocation &in) {
michael@0 3155 setOperand(0, in);
michael@0 3156 }
michael@0 3157
michael@0 3158 MToInt32 *mir() const {
michael@0 3159 return mir_->toToInt32();
michael@0 3160 }
michael@0 3161 };
michael@0 3162
michael@0 3163 // Convert a double to a truncated int32.
michael@0 3164 // Input: floating-point register
michael@0 3165 // Output: 32-bit integer
michael@0 3166 class LTruncateDToInt32 : public LInstructionHelper<1, 1, 1>
michael@0 3167 {
michael@0 3168 public:
michael@0 3169 LIR_HEADER(TruncateDToInt32)
michael@0 3170
michael@0 3171 LTruncateDToInt32(const LAllocation &in, const LDefinition &temp) {
michael@0 3172 setOperand(0, in);
michael@0 3173 setTemp(0, temp);
michael@0 3174 }
michael@0 3175
michael@0 3176 const LDefinition *tempFloat() {
michael@0 3177 return getTemp(0);
michael@0 3178 }
michael@0 3179 };
michael@0 3180
michael@0 3181 // Convert a float32 to a truncated int32.
michael@0 3182 // Input: floating-point register
michael@0 3183 // Output: 32-bit integer
michael@0 3184 class LTruncateFToInt32 : public LInstructionHelper<1, 1, 1>
michael@0 3185 {
michael@0 3186 public:
michael@0 3187 LIR_HEADER(TruncateFToInt32)
michael@0 3188
michael@0 3189 LTruncateFToInt32(const LAllocation &in, const LDefinition &temp) {
michael@0 3190 setOperand(0, in);
michael@0 3191 setTemp(0, temp);
michael@0 3192 }
michael@0 3193
michael@0 3194 const LDefinition *tempFloat() {
michael@0 3195 return getTemp(0);
michael@0 3196 }
michael@0 3197 };
michael@0 3198
michael@0 3199 // Convert a boolean value to a string.
michael@0 3200 class LBooleanToString : public LInstructionHelper<1, 1, 0>
michael@0 3201 {
michael@0 3202 public:
michael@0 3203 LIR_HEADER(BooleanToString)
michael@0 3204
michael@0 3205 LBooleanToString(const LAllocation &input) {
michael@0 3206 setOperand(0, input);
michael@0 3207 }
michael@0 3208
michael@0 3209 const MToString *mir() {
michael@0 3210 return mir_->toToString();
michael@0 3211 }
michael@0 3212 };
michael@0 3213
michael@0 3214 // Convert an integer hosted on one definition to a string with a function call.
michael@0 3215 class LIntToString : public LInstructionHelper<1, 1, 0>
michael@0 3216 {
michael@0 3217 public:
michael@0 3218 LIR_HEADER(IntToString)
michael@0 3219
michael@0 3220 LIntToString(const LAllocation &input) {
michael@0 3221 setOperand(0, input);
michael@0 3222 }
michael@0 3223
michael@0 3224 const MToString *mir() {
michael@0 3225 return mir_->toToString();
michael@0 3226 }
michael@0 3227 };
michael@0 3228
michael@0 3229 // Convert a double hosted on one definition to a string with a function call.
michael@0 3230 class LDoubleToString : public LInstructionHelper<1, 1, 1>
michael@0 3231 {
michael@0 3232 public:
michael@0 3233 LIR_HEADER(DoubleToString)
michael@0 3234
michael@0 3235 LDoubleToString(const LAllocation &input, const LDefinition &temp) {
michael@0 3236 setOperand(0, input);
michael@0 3237 setTemp(0, temp);
michael@0 3238 }
michael@0 3239
michael@0 3240 const LDefinition *tempInt() {
michael@0 3241 return getTemp(0);
michael@0 3242 }
michael@0 3243 const MToString *mir() {
michael@0 3244 return mir_->toToString();
michael@0 3245 }
michael@0 3246 };
michael@0 3247
michael@0 3248 // Convert a primitive to a string with a function call.
michael@0 3249 class LPrimitiveToString : public LInstructionHelper<1, BOX_PIECES, 1>
michael@0 3250 {
michael@0 3251 public:
michael@0 3252 LIR_HEADER(PrimitiveToString)
michael@0 3253
michael@0 3254 LPrimitiveToString(const LDefinition &tempToUnbox)
michael@0 3255 {
michael@0 3256 setTemp(0, tempToUnbox);
michael@0 3257 }
michael@0 3258
michael@0 3259 static const size_t Input = 0;
michael@0 3260
michael@0 3261 const MToString *mir() {
michael@0 3262 return mir_->toToString();
michael@0 3263 }
michael@0 3264
michael@0 3265 const LDefinition *tempToUnbox() {
michael@0 3266 return getTemp(0);
michael@0 3267 }
michael@0 3268 };
michael@0 3269
michael@0 3270 // No-op instruction that is used to hold the entry snapshot. This simplifies
michael@0 3271 // register allocation as it doesn't need to sniff the snapshot out of the
michael@0 3272 // LIRGraph.
michael@0 3273 class LStart : public LInstructionHelper<0, 0, 0>
michael@0 3274 {
michael@0 3275 public:
michael@0 3276 LIR_HEADER(Start)
michael@0 3277 };
michael@0 3278
michael@0 3279 // Passed the BaselineFrame address in the OsrFrameReg by SideCannon().
michael@0 3280 // Forwards this object to the LOsrValues for Value materialization.
michael@0 3281 class LOsrEntry : public LInstructionHelper<1, 0, 0>
michael@0 3282 {
michael@0 3283 protected:
michael@0 3284 Label label_;
michael@0 3285 uint32_t frameDepth_;
michael@0 3286
michael@0 3287 public:
michael@0 3288 LIR_HEADER(OsrEntry)
michael@0 3289
michael@0 3290 LOsrEntry()
michael@0 3291 : frameDepth_(0)
michael@0 3292 { }
michael@0 3293
michael@0 3294 void setFrameDepth(uint32_t depth) {
michael@0 3295 frameDepth_ = depth;
michael@0 3296 }
michael@0 3297 uint32_t getFrameDepth() {
michael@0 3298 return frameDepth_;
michael@0 3299 }
michael@0 3300 Label *label() {
michael@0 3301 return &label_;
michael@0 3302 }
michael@0 3303
michael@0 3304 };
michael@0 3305
michael@0 3306 // Materialize a Value stored in an interpreter frame for OSR.
michael@0 3307 class LOsrValue : public LInstructionHelper<BOX_PIECES, 1, 0>
michael@0 3308 {
michael@0 3309 public:
michael@0 3310 LIR_HEADER(OsrValue)
michael@0 3311
michael@0 3312 LOsrValue(const LAllocation &entry)
michael@0 3313 {
michael@0 3314 setOperand(0, entry);
michael@0 3315 }
michael@0 3316
michael@0 3317 const MOsrValue *mir() {
michael@0 3318 return mir_->toOsrValue();
michael@0 3319 }
michael@0 3320 };
michael@0 3321
michael@0 3322 // Materialize a JSObject scope chain stored in an interpreter frame for OSR.
michael@0 3323 class LOsrScopeChain : public LInstructionHelper<1, 1, 0>
michael@0 3324 {
michael@0 3325 public:
michael@0 3326 LIR_HEADER(OsrScopeChain)
michael@0 3327
michael@0 3328 LOsrScopeChain(const LAllocation &entry)
michael@0 3329 {
michael@0 3330 setOperand(0, entry);
michael@0 3331 }
michael@0 3332
michael@0 3333 const MOsrScopeChain *mir() {
michael@0 3334 return mir_->toOsrScopeChain();
michael@0 3335 }
michael@0 3336 };
michael@0 3337
michael@0 3338 // Materialize a JSObject scope chain stored in an interpreter frame for OSR.
michael@0 3339 class LOsrReturnValue : public LInstructionHelper<BOX_PIECES, 1, 0>
michael@0 3340 {
michael@0 3341 public:
michael@0 3342 LIR_HEADER(OsrReturnValue)
michael@0 3343
michael@0 3344 LOsrReturnValue(const LAllocation &entry)
michael@0 3345 {
michael@0 3346 setOperand(0, entry);
michael@0 3347 }
michael@0 3348
michael@0 3349 const MOsrReturnValue *mir() {
michael@0 3350 return mir_->toOsrReturnValue();
michael@0 3351 }
michael@0 3352 };
michael@0 3353
michael@0 3354 // Materialize a JSObject ArgumentsObject stored in an interpreter frame for OSR.
michael@0 3355 class LOsrArgumentsObject : public LInstructionHelper<1, 1, 0>
michael@0 3356 {
michael@0 3357 public:
michael@0 3358 LIR_HEADER(OsrArgumentsObject)
michael@0 3359
michael@0 3360 LOsrArgumentsObject(const LAllocation &entry)
michael@0 3361 {
michael@0 3362 setOperand(0, entry);
michael@0 3363 }
michael@0 3364
michael@0 3365 const MOsrArgumentsObject *mir() {
michael@0 3366 return mir_->toOsrArgumentsObject();
michael@0 3367 }
michael@0 3368 };
michael@0 3369
michael@0 3370 class LRegExp : public LCallInstructionHelper<1, 0, 0>
michael@0 3371 {
michael@0 3372 public:
michael@0 3373 LIR_HEADER(RegExp)
michael@0 3374
michael@0 3375 const MRegExp *mir() const {
michael@0 3376 return mir_->toRegExp();
michael@0 3377 }
michael@0 3378 };
michael@0 3379
michael@0 3380 class LRegExpExec : public LCallInstructionHelper<BOX_PIECES, 2, 0>
michael@0 3381 {
michael@0 3382 public:
michael@0 3383 LIR_HEADER(RegExpExec)
michael@0 3384
michael@0 3385 LRegExpExec(const LAllocation &regexp, const LAllocation &string)
michael@0 3386 {
michael@0 3387 setOperand(0, regexp);
michael@0 3388 setOperand(1, string);
michael@0 3389 }
michael@0 3390
michael@0 3391 const LAllocation *regexp() {
michael@0 3392 return getOperand(0);
michael@0 3393 }
michael@0 3394 const LAllocation *string() {
michael@0 3395 return getOperand(1);
michael@0 3396 }
michael@0 3397
michael@0 3398 const MRegExpExec *mir() const {
michael@0 3399 return mir_->toRegExpExec();
michael@0 3400 }
michael@0 3401 };
michael@0 3402
michael@0 3403 class LRegExpTest : public LCallInstructionHelper<1, 2, 0>
michael@0 3404 {
michael@0 3405 public:
michael@0 3406 LIR_HEADER(RegExpTest)
michael@0 3407
michael@0 3408 LRegExpTest(const LAllocation &regexp, const LAllocation &string)
michael@0 3409 {
michael@0 3410 setOperand(0, regexp);
michael@0 3411 setOperand(1, string);
michael@0 3412 }
michael@0 3413
michael@0 3414 const LAllocation *regexp() {
michael@0 3415 return getOperand(0);
michael@0 3416 }
michael@0 3417 const LAllocation *string() {
michael@0 3418 return getOperand(1);
michael@0 3419 }
michael@0 3420
michael@0 3421 const MRegExpTest *mir() const {
michael@0 3422 return mir_->toRegExpTest();
michael@0 3423 }
michael@0 3424 };
michael@0 3425
michael@0 3426
michael@0 3427 class LStrReplace : public LCallInstructionHelper<1, 3, 0>
michael@0 3428 {
michael@0 3429 public:
michael@0 3430 LStrReplace(const LAllocation &string, const LAllocation &pattern,
michael@0 3431 const LAllocation &replacement)
michael@0 3432 {
michael@0 3433 setOperand(0, string);
michael@0 3434 setOperand(1, pattern);
michael@0 3435 setOperand(2, replacement);
michael@0 3436 }
michael@0 3437
michael@0 3438 const LAllocation *string() {
michael@0 3439 return getOperand(0);
michael@0 3440 }
michael@0 3441 const LAllocation *pattern() {
michael@0 3442 return getOperand(1);
michael@0 3443 }
michael@0 3444 const LAllocation *replacement() {
michael@0 3445 return getOperand(2);
michael@0 3446 }
michael@0 3447 };
michael@0 3448
michael@0 3449 class LRegExpReplace: public LStrReplace
michael@0 3450 {
michael@0 3451 public:
michael@0 3452 LIR_HEADER(RegExpReplace);
michael@0 3453
michael@0 3454 LRegExpReplace(const LAllocation &string, const LAllocation &pattern,
michael@0 3455 const LAllocation &replacement)
michael@0 3456 : LStrReplace(string, pattern, replacement)
michael@0 3457 {
michael@0 3458 }
michael@0 3459
michael@0 3460 const MRegExpReplace *mir() const {
michael@0 3461 return mir_->toRegExpReplace();
michael@0 3462 }
michael@0 3463 };
michael@0 3464
michael@0 3465 class LStringReplace: public LStrReplace
michael@0 3466 {
michael@0 3467 public:
michael@0 3468 LIR_HEADER(StringReplace);
michael@0 3469
michael@0 3470 LStringReplace(const LAllocation &string, const LAllocation &pattern,
michael@0 3471 const LAllocation &replacement)
michael@0 3472 : LStrReplace(string, pattern, replacement)
michael@0 3473 {
michael@0 3474 }
michael@0 3475
michael@0 3476 const MStringReplace *mir() const {
michael@0 3477 return mir_->toStringReplace();
michael@0 3478 }
michael@0 3479 };
michael@0 3480
michael@0 3481 class LLambdaForSingleton : public LCallInstructionHelper<1, 1, 0>
michael@0 3482 {
michael@0 3483 public:
michael@0 3484 LIR_HEADER(LambdaForSingleton)
michael@0 3485
michael@0 3486 LLambdaForSingleton(const LAllocation &scopeChain)
michael@0 3487 {
michael@0 3488 setOperand(0, scopeChain);
michael@0 3489 }
michael@0 3490 const LAllocation *scopeChain() {
michael@0 3491 return getOperand(0);
michael@0 3492 }
michael@0 3493 const MLambda *mir() const {
michael@0 3494 return mir_->toLambda();
michael@0 3495 }
michael@0 3496 };
michael@0 3497
michael@0 3498 class LLambda : public LInstructionHelper<1, 1, 1>
michael@0 3499 {
michael@0 3500 public:
michael@0 3501 LIR_HEADER(Lambda)
michael@0 3502
michael@0 3503 LLambda(const LAllocation &scopeChain, const LDefinition &temp) {
michael@0 3504 setOperand(0, scopeChain);
michael@0 3505 setTemp(0, temp);
michael@0 3506 }
michael@0 3507 const LAllocation *scopeChain() {
michael@0 3508 return getOperand(0);
michael@0 3509 }
michael@0 3510 const LDefinition *temp() {
michael@0 3511 return getTemp(0);
michael@0 3512 }
michael@0 3513 const MLambda *mir() const {
michael@0 3514 return mir_->toLambda();
michael@0 3515 }
michael@0 3516 };
michael@0 3517
michael@0 3518 class LLambdaArrow : public LInstructionHelper<1, 1 + BOX_PIECES, 1>
michael@0 3519 {
michael@0 3520 public:
michael@0 3521 LIR_HEADER(LambdaArrow)
michael@0 3522
michael@0 3523 static const size_t ThisValue = 1;
michael@0 3524
michael@0 3525 LLambdaArrow(const LAllocation &scopeChain, const LDefinition &temp) {
michael@0 3526 setOperand(0, scopeChain);
michael@0 3527 setTemp(0, temp);
michael@0 3528 }
michael@0 3529 const LAllocation *scopeChain() {
michael@0 3530 return getOperand(0);
michael@0 3531 }
michael@0 3532 const LDefinition *temp() {
michael@0 3533 return getTemp(0);
michael@0 3534 }
michael@0 3535 const MLambdaArrow *mir() const {
michael@0 3536 return mir_->toLambdaArrow();
michael@0 3537 }
michael@0 3538 };
michael@0 3539
michael@0 3540 class LLambdaPar : public LInstructionHelper<1, 2, 2>
michael@0 3541 {
michael@0 3542 public:
michael@0 3543 LIR_HEADER(LambdaPar);
michael@0 3544
michael@0 3545 LLambdaPar(const LAllocation &cx, const LAllocation &scopeChain,
michael@0 3546 const LDefinition &temp1, const LDefinition &temp2)
michael@0 3547 {
michael@0 3548 setOperand(0, cx);
michael@0 3549 setOperand(1, scopeChain);
michael@0 3550 setTemp(0, temp1);
michael@0 3551 setTemp(1, temp2);
michael@0 3552 }
michael@0 3553 const LAllocation *forkJoinContext() {
michael@0 3554 return getOperand(0);
michael@0 3555 }
michael@0 3556 const LAllocation *scopeChain() {
michael@0 3557 return getOperand(1);
michael@0 3558 }
michael@0 3559 const MLambdaPar *mir() const {
michael@0 3560 return mir_->toLambdaPar();
michael@0 3561 }
michael@0 3562 const LDefinition *getTemp0() {
michael@0 3563 return getTemp(0);
michael@0 3564 }
michael@0 3565 const LDefinition *getTemp1() {
michael@0 3566 return getTemp(1);
michael@0 3567 }
michael@0 3568 };
michael@0 3569
michael@0 3570 // Determines the implicit |this| value for function calls.
michael@0 3571 class LImplicitThis : public LInstructionHelper<BOX_PIECES, 1, 0>
michael@0 3572 {
michael@0 3573 public:
michael@0 3574 LIR_HEADER(ImplicitThis)
michael@0 3575
michael@0 3576 LImplicitThis(const LAllocation &callee) {
michael@0 3577 setOperand(0, callee);
michael@0 3578 }
michael@0 3579
michael@0 3580 const MImplicitThis *mir() const {
michael@0 3581 return mir_->toImplicitThis();
michael@0 3582 }
michael@0 3583 const LAllocation *callee() {
michael@0 3584 return getOperand(0);
michael@0 3585 }
michael@0 3586 };
michael@0 3587
michael@0 3588 // Load the "slots" member out of a JSObject.
michael@0 3589 // Input: JSObject pointer
michael@0 3590 // Output: slots pointer
michael@0 3591 class LSlots : public LInstructionHelper<1, 1, 0>
michael@0 3592 {
michael@0 3593 public:
michael@0 3594 LIR_HEADER(Slots)
michael@0 3595
michael@0 3596 LSlots(const LAllocation &object) {
michael@0 3597 setOperand(0, object);
michael@0 3598 }
michael@0 3599
michael@0 3600 const LAllocation *object() {
michael@0 3601 return getOperand(0);
michael@0 3602 }
michael@0 3603 };
michael@0 3604
michael@0 3605 // Load the "elements" member out of a JSObject.
michael@0 3606 // Input: JSObject pointer
michael@0 3607 // Output: elements pointer
michael@0 3608 class LElements : public LInstructionHelper<1, 1, 0>
michael@0 3609 {
michael@0 3610 public:
michael@0 3611 LIR_HEADER(Elements)
michael@0 3612
michael@0 3613 LElements(const LAllocation &object) {
michael@0 3614 setOperand(0, object);
michael@0 3615 }
michael@0 3616
michael@0 3617 const LAllocation *object() {
michael@0 3618 return getOperand(0);
michael@0 3619 }
michael@0 3620 };
michael@0 3621
michael@0 3622 // If necessary, convert any int32 elements in a vector into doubles.
michael@0 3623 class LConvertElementsToDoubles : public LInstructionHelper<0, 1, 0>
michael@0 3624 {
michael@0 3625 public:
michael@0 3626 LIR_HEADER(ConvertElementsToDoubles)
michael@0 3627
michael@0 3628 LConvertElementsToDoubles(const LAllocation &elements) {
michael@0 3629 setOperand(0, elements);
michael@0 3630 }
michael@0 3631
michael@0 3632 const LAllocation *elements() {
michael@0 3633 return getOperand(0);
michael@0 3634 }
michael@0 3635 };
michael@0 3636
michael@0 3637 // If |elements| has the CONVERT_DOUBLE_ELEMENTS flag, convert int32 value to
michael@0 3638 // double. Else return the original value.
michael@0 3639 class LMaybeToDoubleElement : public LInstructionHelper<BOX_PIECES, 2, 1>
michael@0 3640 {
michael@0 3641 public:
michael@0 3642 LIR_HEADER(MaybeToDoubleElement)
michael@0 3643
michael@0 3644 LMaybeToDoubleElement(const LAllocation &elements, const LAllocation &value,
michael@0 3645 const LDefinition &tempFloat) {
michael@0 3646 setOperand(0, elements);
michael@0 3647 setOperand(1, value);
michael@0 3648 setTemp(0, tempFloat);
michael@0 3649 }
michael@0 3650
michael@0 3651 const LAllocation *elements() {
michael@0 3652 return getOperand(0);
michael@0 3653 }
michael@0 3654 const LAllocation *value() {
michael@0 3655 return getOperand(1);
michael@0 3656 }
michael@0 3657 const LDefinition *tempFloat() {
michael@0 3658 return getTemp(0);
michael@0 3659 }
michael@0 3660 };
michael@0 3661
michael@0 3662 // Load the initialized length from an elements header.
michael@0 3663 class LInitializedLength : public LInstructionHelper<1, 1, 0>
michael@0 3664 {
michael@0 3665 public:
michael@0 3666 LIR_HEADER(InitializedLength)
michael@0 3667
michael@0 3668 LInitializedLength(const LAllocation &elements) {
michael@0 3669 setOperand(0, elements);
michael@0 3670 }
michael@0 3671
michael@0 3672 const LAllocation *elements() {
michael@0 3673 return getOperand(0);
michael@0 3674 }
michael@0 3675 };
michael@0 3676
michael@0 3677 // Store to the initialized length in an elements header. Note the input is an
michael@0 3678 // *index*, one less than the desired initialized length.
michael@0 3679 class LSetInitializedLength : public LInstructionHelper<0, 2, 0>
michael@0 3680 {
michael@0 3681 public:
michael@0 3682 LIR_HEADER(SetInitializedLength)
michael@0 3683
michael@0 3684 LSetInitializedLength(const LAllocation &elements, const LAllocation &index) {
michael@0 3685 setOperand(0, elements);
michael@0 3686 setOperand(1, index);
michael@0 3687 }
michael@0 3688
michael@0 3689 const LAllocation *elements() {
michael@0 3690 return getOperand(0);
michael@0 3691 }
michael@0 3692 const LAllocation *index() {
michael@0 3693 return getOperand(1);
michael@0 3694 }
michael@0 3695 };
michael@0 3696
michael@0 3697 // Load the length from an elements header.
michael@0 3698 class LArrayLength : public LInstructionHelper<1, 1, 0>
michael@0 3699 {
michael@0 3700 public:
michael@0 3701 LIR_HEADER(ArrayLength)
michael@0 3702
michael@0 3703 LArrayLength(const LAllocation &elements) {
michael@0 3704 setOperand(0, elements);
michael@0 3705 }
michael@0 3706
michael@0 3707 const LAllocation *elements() {
michael@0 3708 return getOperand(0);
michael@0 3709 }
michael@0 3710 };
michael@0 3711
michael@0 3712 // Store to the length in an elements header. Note the input is an *index*,
michael@0 3713 // one less than the desired length.
michael@0 3714 class LSetArrayLength : public LInstructionHelper<0, 2, 0>
michael@0 3715 {
michael@0 3716 public:
michael@0 3717 LIR_HEADER(SetArrayLength)
michael@0 3718
michael@0 3719 LSetArrayLength(const LAllocation &elements, const LAllocation &index) {
michael@0 3720 setOperand(0, elements);
michael@0 3721 setOperand(1, index);
michael@0 3722 }
michael@0 3723
michael@0 3724 const LAllocation *elements() {
michael@0 3725 return getOperand(0);
michael@0 3726 }
michael@0 3727 const LAllocation *index() {
michael@0 3728 return getOperand(1);
michael@0 3729 }
michael@0 3730 };
michael@0 3731
michael@0 3732 // Read the length of a typed array.
michael@0 3733 class LTypedArrayLength : public LInstructionHelper<1, 1, 0>
michael@0 3734 {
michael@0 3735 public:
michael@0 3736 LIR_HEADER(TypedArrayLength)
michael@0 3737
michael@0 3738 LTypedArrayLength(const LAllocation &obj) {
michael@0 3739 setOperand(0, obj);
michael@0 3740 }
michael@0 3741
michael@0 3742 const LAllocation *object() {
michael@0 3743 return getOperand(0);
michael@0 3744 }
michael@0 3745 };
michael@0 3746
michael@0 3747 // Load a typed array's elements vector.
michael@0 3748 class LTypedArrayElements : public LInstructionHelper<1, 1, 0>
michael@0 3749 {
michael@0 3750 public:
michael@0 3751 LIR_HEADER(TypedArrayElements)
michael@0 3752
michael@0 3753 LTypedArrayElements(const LAllocation &object) {
michael@0 3754 setOperand(0, object);
michael@0 3755 }
michael@0 3756 const LAllocation *object() {
michael@0 3757 return getOperand(0);
michael@0 3758 }
michael@0 3759 };
michael@0 3760
michael@0 3761 // Load a typed array's elements vector.
michael@0 3762 class LTypedObjectElements : public LInstructionHelper<1, 1, 0>
michael@0 3763 {
michael@0 3764 public:
michael@0 3765 LIR_HEADER(TypedObjectElements)
michael@0 3766
michael@0 3767 LTypedObjectElements(const LAllocation &object) {
michael@0 3768 setOperand(0, object);
michael@0 3769 }
michael@0 3770 const LAllocation *object() {
michael@0 3771 return getOperand(0);
michael@0 3772 }
michael@0 3773 const MTypedObjectElements *mir() const {
michael@0 3774 return mir_->toTypedObjectElements();
michael@0 3775 }
michael@0 3776 };
michael@0 3777
michael@0 3778 // Load a typed array's elements vector.
michael@0 3779 class LSetTypedObjectOffset : public LInstructionHelper<0, 2, 1>
michael@0 3780 {
michael@0 3781 public:
michael@0 3782 LIR_HEADER(SetTypedObjectOffset)
michael@0 3783
michael@0 3784 LSetTypedObjectOffset(const LAllocation &object,
michael@0 3785 const LAllocation &offset,
michael@0 3786 const LDefinition &temp0)
michael@0 3787 {
michael@0 3788 setOperand(0, object);
michael@0 3789 setOperand(1, offset);
michael@0 3790 setTemp(0, temp0);
michael@0 3791 }
michael@0 3792 const LAllocation *object() {
michael@0 3793 return getOperand(0);
michael@0 3794 }
michael@0 3795 const LAllocation *offset() {
michael@0 3796 return getOperand(1);
michael@0 3797 }
michael@0 3798 const LDefinition *temp0() {
michael@0 3799 return getTemp(0);
michael@0 3800 }
michael@0 3801 };
michael@0 3802
michael@0 3803 // Check whether a typed object has a neutered owner buffer.
michael@0 3804 class LNeuterCheck : public LInstructionHelper<0, 1, 1>
michael@0 3805 {
michael@0 3806 public:
michael@0 3807 LIR_HEADER(NeuterCheck)
michael@0 3808
michael@0 3809 LNeuterCheck(const LAllocation &object, const LDefinition &temp) {
michael@0 3810 setOperand(0, object);
michael@0 3811 setTemp(0, temp);
michael@0 3812 }
michael@0 3813 const LAllocation *object() {
michael@0 3814 return getOperand(0);
michael@0 3815 }
michael@0 3816 const LDefinition *temp() {
michael@0 3817 return getTemp(0);
michael@0 3818 }
michael@0 3819 };
michael@0 3820
michael@0 3821 // Bailout if index >= length.
michael@0 3822 class LBoundsCheck : public LInstructionHelper<0, 2, 0>
michael@0 3823 {
michael@0 3824 public:
michael@0 3825 LIR_HEADER(BoundsCheck)
michael@0 3826
michael@0 3827 LBoundsCheck(const LAllocation &index, const LAllocation &length) {
michael@0 3828 setOperand(0, index);
michael@0 3829 setOperand(1, length);
michael@0 3830 }
michael@0 3831 const MBoundsCheck *mir() const {
michael@0 3832 return mir_->toBoundsCheck();
michael@0 3833 }
michael@0 3834 const LAllocation *index() {
michael@0 3835 return getOperand(0);
michael@0 3836 }
michael@0 3837 const LAllocation *length() {
michael@0 3838 return getOperand(1);
michael@0 3839 }
michael@0 3840 };
michael@0 3841
michael@0 3842 // Bailout if index + minimum < 0 or index + maximum >= length.
michael@0 3843 class LBoundsCheckRange : public LInstructionHelper<0, 2, 1>
michael@0 3844 {
michael@0 3845 public:
michael@0 3846 LIR_HEADER(BoundsCheckRange)
michael@0 3847
michael@0 3848 LBoundsCheckRange(const LAllocation &index, const LAllocation &length,
michael@0 3849 const LDefinition &temp)
michael@0 3850 {
michael@0 3851 setOperand(0, index);
michael@0 3852 setOperand(1, length);
michael@0 3853 setTemp(0, temp);
michael@0 3854 }
michael@0 3855 const MBoundsCheck *mir() const {
michael@0 3856 return mir_->toBoundsCheck();
michael@0 3857 }
michael@0 3858 const LAllocation *index() {
michael@0 3859 return getOperand(0);
michael@0 3860 }
michael@0 3861 const LAllocation *length() {
michael@0 3862 return getOperand(1);
michael@0 3863 }
michael@0 3864 };
michael@0 3865
michael@0 3866 // Bailout if index < minimum.
michael@0 3867 class LBoundsCheckLower : public LInstructionHelper<0, 1, 0>
michael@0 3868 {
michael@0 3869 public:
michael@0 3870 LIR_HEADER(BoundsCheckLower)
michael@0 3871
michael@0 3872 LBoundsCheckLower(const LAllocation &index)
michael@0 3873 {
michael@0 3874 setOperand(0, index);
michael@0 3875 }
michael@0 3876 MBoundsCheckLower *mir() const {
michael@0 3877 return mir_->toBoundsCheckLower();
michael@0 3878 }
michael@0 3879 const LAllocation *index() {
michael@0 3880 return getOperand(0);
michael@0 3881 }
michael@0 3882 };
michael@0 3883
michael@0 3884 // Load a value from a dense array's elements vector. Bail out if it's the hole value.
michael@0 3885 class LLoadElementV : public LInstructionHelper<BOX_PIECES, 2, 0>
michael@0 3886 {
michael@0 3887 public:
michael@0 3888 LIR_HEADER(LoadElementV)
michael@0 3889
michael@0 3890 LLoadElementV(const LAllocation &elements, const LAllocation &index) {
michael@0 3891 setOperand(0, elements);
michael@0 3892 setOperand(1, index);
michael@0 3893 }
michael@0 3894
michael@0 3895 const char *extraName() const {
michael@0 3896 return mir()->needsHoleCheck() ? "HoleCheck" : nullptr;
michael@0 3897 }
michael@0 3898
michael@0 3899 const MLoadElement *mir() const {
michael@0 3900 return mir_->toLoadElement();
michael@0 3901 }
michael@0 3902 const LAllocation *elements() {
michael@0 3903 return getOperand(0);
michael@0 3904 }
michael@0 3905 const LAllocation *index() {
michael@0 3906 return getOperand(1);
michael@0 3907 }
michael@0 3908 };
michael@0 3909
michael@0 3910 class LInArray : public LInstructionHelper<1, 4, 0>
michael@0 3911 {
michael@0 3912 public:
michael@0 3913 LIR_HEADER(InArray)
michael@0 3914
michael@0 3915 LInArray(const LAllocation &elements, const LAllocation &index,
michael@0 3916 const LAllocation &initLength, const LAllocation &object)
michael@0 3917 {
michael@0 3918 setOperand(0, elements);
michael@0 3919 setOperand(1, index);
michael@0 3920 setOperand(2, initLength);
michael@0 3921 setOperand(3, object);
michael@0 3922 }
michael@0 3923 const MInArray *mir() const {
michael@0 3924 return mir_->toInArray();
michael@0 3925 }
michael@0 3926 const LAllocation *elements() {
michael@0 3927 return getOperand(0);
michael@0 3928 }
michael@0 3929 const LAllocation *index() {
michael@0 3930 return getOperand(1);
michael@0 3931 }
michael@0 3932 const LAllocation *initLength() {
michael@0 3933 return getOperand(2);
michael@0 3934 }
michael@0 3935 const LAllocation *object() {
michael@0 3936 return getOperand(3);
michael@0 3937 }
michael@0 3938 };
michael@0 3939
michael@0 3940
michael@0 3941 // Load a value from a dense array's elements vector. Bail out if it's the hole value.
michael@0 3942 class LLoadElementHole : public LInstructionHelper<BOX_PIECES, 3, 0>
michael@0 3943 {
michael@0 3944 public:
michael@0 3945 LIR_HEADER(LoadElementHole)
michael@0 3946
michael@0 3947 LLoadElementHole(const LAllocation &elements, const LAllocation &index, const LAllocation &initLength) {
michael@0 3948 setOperand(0, elements);
michael@0 3949 setOperand(1, index);
michael@0 3950 setOperand(2, initLength);
michael@0 3951 }
michael@0 3952
michael@0 3953 const char *extraName() const {
michael@0 3954 return mir()->needsHoleCheck() ? "HoleCheck" : nullptr;
michael@0 3955 }
michael@0 3956
michael@0 3957 const MLoadElementHole *mir() const {
michael@0 3958 return mir_->toLoadElementHole();
michael@0 3959 }
michael@0 3960 const LAllocation *elements() {
michael@0 3961 return getOperand(0);
michael@0 3962 }
michael@0 3963 const LAllocation *index() {
michael@0 3964 return getOperand(1);
michael@0 3965 }
michael@0 3966 const LAllocation *initLength() {
michael@0 3967 return getOperand(2);
michael@0 3968 }
michael@0 3969 };
michael@0 3970
michael@0 3971 // Load a typed value from a dense array's elements vector. The array must be
michael@0 3972 // known to be packed, so that we don't have to check for the hole value.
michael@0 3973 // This instruction does not load the type tag and can directly load into a
michael@0 3974 // FP register.
michael@0 3975 class LLoadElementT : public LInstructionHelper<1, 2, 0>
michael@0 3976 {
michael@0 3977 public:
michael@0 3978 LIR_HEADER(LoadElementT)
michael@0 3979
michael@0 3980 LLoadElementT(const LAllocation &elements, const LAllocation &index) {
michael@0 3981 setOperand(0, elements);
michael@0 3982 setOperand(1, index);
michael@0 3983 }
michael@0 3984
michael@0 3985 const char *extraName() const {
michael@0 3986 return mir()->needsHoleCheck() ? "HoleCheck"
michael@0 3987 : (mir()->loadDoubles() ? "Doubles" : nullptr);
michael@0 3988 }
michael@0 3989
michael@0 3990 const MLoadElement *mir() const {
michael@0 3991 return mir_->toLoadElement();
michael@0 3992 }
michael@0 3993 const LAllocation *elements() {
michael@0 3994 return getOperand(0);
michael@0 3995 }
michael@0 3996 const LAllocation *index() {
michael@0 3997 return getOperand(1);
michael@0 3998 }
michael@0 3999 };
michael@0 4000
michael@0 4001 // Store a boxed value to a dense array's element vector.
michael@0 4002 class LStoreElementV : public LInstructionHelper<0, 2 + BOX_PIECES, 0>
michael@0 4003 {
michael@0 4004 public:
michael@0 4005 LIR_HEADER(StoreElementV)
michael@0 4006
michael@0 4007 LStoreElementV(const LAllocation &elements, const LAllocation &index) {
michael@0 4008 setOperand(0, elements);
michael@0 4009 setOperand(1, index);
michael@0 4010 }
michael@0 4011
michael@0 4012 const char *extraName() const {
michael@0 4013 return mir()->needsHoleCheck() ? "HoleCheck" : nullptr;
michael@0 4014 }
michael@0 4015
michael@0 4016 static const size_t Value = 2;
michael@0 4017
michael@0 4018 const MStoreElement *mir() const {
michael@0 4019 return mir_->toStoreElement();
michael@0 4020 }
michael@0 4021 const LAllocation *elements() {
michael@0 4022 return getOperand(0);
michael@0 4023 }
michael@0 4024 const LAllocation *index() {
michael@0 4025 return getOperand(1);
michael@0 4026 }
michael@0 4027 };
michael@0 4028
michael@0 4029 // Store a typed value to a dense array's elements vector. Compared to
michael@0 4030 // LStoreElementV, this instruction can store doubles and constants directly,
michael@0 4031 // and does not store the type tag if the array is monomorphic and known to
michael@0 4032 // be packed.
michael@0 4033 class LStoreElementT : public LInstructionHelper<0, 3, 0>
michael@0 4034 {
michael@0 4035 public:
michael@0 4036 LIR_HEADER(StoreElementT)
michael@0 4037
michael@0 4038 LStoreElementT(const LAllocation &elements, const LAllocation &index, const LAllocation &value) {
michael@0 4039 setOperand(0, elements);
michael@0 4040 setOperand(1, index);
michael@0 4041 setOperand(2, value);
michael@0 4042 }
michael@0 4043
michael@0 4044 const char *extraName() const {
michael@0 4045 return mir()->needsHoleCheck() ? "HoleCheck" : nullptr;
michael@0 4046 }
michael@0 4047
michael@0 4048 const MStoreElement *mir() const {
michael@0 4049 return mir_->toStoreElement();
michael@0 4050 }
michael@0 4051 const LAllocation *elements() {
michael@0 4052 return getOperand(0);
michael@0 4053 }
michael@0 4054 const LAllocation *index() {
michael@0 4055 return getOperand(1);
michael@0 4056 }
michael@0 4057 const LAllocation *value() {
michael@0 4058 return getOperand(2);
michael@0 4059 }
michael@0 4060 };
michael@0 4061
michael@0 4062 // Like LStoreElementV, but supports indexes >= initialized length.
michael@0 4063 class LStoreElementHoleV : public LInstructionHelper<0, 3 + BOX_PIECES, 0>
michael@0 4064 {
michael@0 4065 public:
michael@0 4066 LIR_HEADER(StoreElementHoleV)
michael@0 4067
michael@0 4068 LStoreElementHoleV(const LAllocation &object, const LAllocation &elements,
michael@0 4069 const LAllocation &index) {
michael@0 4070 setOperand(0, object);
michael@0 4071 setOperand(1, elements);
michael@0 4072 setOperand(2, index);
michael@0 4073 }
michael@0 4074
michael@0 4075 static const size_t Value = 3;
michael@0 4076
michael@0 4077 const MStoreElementHole *mir() const {
michael@0 4078 return mir_->toStoreElementHole();
michael@0 4079 }
michael@0 4080 const LAllocation *object() {
michael@0 4081 return getOperand(0);
michael@0 4082 }
michael@0 4083 const LAllocation *elements() {
michael@0 4084 return getOperand(1);
michael@0 4085 }
michael@0 4086 const LAllocation *index() {
michael@0 4087 return getOperand(2);
michael@0 4088 }
michael@0 4089 };
michael@0 4090
michael@0 4091 // Like LStoreElementT, but supports indexes >= initialized length.
michael@0 4092 class LStoreElementHoleT : public LInstructionHelper<0, 4, 0>
michael@0 4093 {
michael@0 4094 public:
michael@0 4095 LIR_HEADER(StoreElementHoleT)
michael@0 4096
michael@0 4097 LStoreElementHoleT(const LAllocation &object, const LAllocation &elements,
michael@0 4098 const LAllocation &index, const LAllocation &value) {
michael@0 4099 setOperand(0, object);
michael@0 4100 setOperand(1, elements);
michael@0 4101 setOperand(2, index);
michael@0 4102 setOperand(3, value);
michael@0 4103 }
michael@0 4104
michael@0 4105 const MStoreElementHole *mir() const {
michael@0 4106 return mir_->toStoreElementHole();
michael@0 4107 }
michael@0 4108 const LAllocation *object() {
michael@0 4109 return getOperand(0);
michael@0 4110 }
michael@0 4111 const LAllocation *elements() {
michael@0 4112 return getOperand(1);
michael@0 4113 }
michael@0 4114 const LAllocation *index() {
michael@0 4115 return getOperand(2);
michael@0 4116 }
michael@0 4117 const LAllocation *value() {
michael@0 4118 return getOperand(3);
michael@0 4119 }
michael@0 4120 };
michael@0 4121
michael@0 4122 class LArrayPopShiftV : public LInstructionHelper<BOX_PIECES, 1, 2>
michael@0 4123 {
michael@0 4124 public:
michael@0 4125 LIR_HEADER(ArrayPopShiftV)
michael@0 4126
michael@0 4127 LArrayPopShiftV(const LAllocation &object, const LDefinition &temp0, const LDefinition &temp1) {
michael@0 4128 setOperand(0, object);
michael@0 4129 setTemp(0, temp0);
michael@0 4130 setTemp(1, temp1);
michael@0 4131 }
michael@0 4132
michael@0 4133 const char *extraName() const {
michael@0 4134 return mir()->mode() == MArrayPopShift::Pop ? "Pop" : "Shift";
michael@0 4135 }
michael@0 4136
michael@0 4137 const MArrayPopShift *mir() const {
michael@0 4138 return mir_->toArrayPopShift();
michael@0 4139 }
michael@0 4140 const LAllocation *object() {
michael@0 4141 return getOperand(0);
michael@0 4142 }
michael@0 4143 const LDefinition *temp0() {
michael@0 4144 return getTemp(0);
michael@0 4145 }
michael@0 4146 const LDefinition *temp1() {
michael@0 4147 return getTemp(1);
michael@0 4148 }
michael@0 4149 };
michael@0 4150
michael@0 4151 class LArrayPopShiftT : public LInstructionHelper<1, 1, 2>
michael@0 4152 {
michael@0 4153 public:
michael@0 4154 LIR_HEADER(ArrayPopShiftT)
michael@0 4155
michael@0 4156 LArrayPopShiftT(const LAllocation &object, const LDefinition &temp0, const LDefinition &temp1) {
michael@0 4157 setOperand(0, object);
michael@0 4158 setTemp(0, temp0);
michael@0 4159 setTemp(1, temp1);
michael@0 4160 }
michael@0 4161
michael@0 4162 const char *extraName() const {
michael@0 4163 return mir()->mode() == MArrayPopShift::Pop ? "Pop" : "Shift";
michael@0 4164 }
michael@0 4165
michael@0 4166 const MArrayPopShift *mir() const {
michael@0 4167 return mir_->toArrayPopShift();
michael@0 4168 }
michael@0 4169 const LAllocation *object() {
michael@0 4170 return getOperand(0);
michael@0 4171 }
michael@0 4172 const LDefinition *temp0() {
michael@0 4173 return getTemp(0);
michael@0 4174 }
michael@0 4175 const LDefinition *temp1() {
michael@0 4176 return getTemp(1);
michael@0 4177 }
michael@0 4178 };
michael@0 4179
michael@0 4180 class LArrayPushV : public LInstructionHelper<1, 1 + BOX_PIECES, 1>
michael@0 4181 {
michael@0 4182 public:
michael@0 4183 LIR_HEADER(ArrayPushV)
michael@0 4184
michael@0 4185 LArrayPushV(const LAllocation &object, const LDefinition &temp) {
michael@0 4186 setOperand(0, object);
michael@0 4187 setTemp(0, temp);
michael@0 4188 }
michael@0 4189
michael@0 4190 static const size_t Value = 1;
michael@0 4191
michael@0 4192 const MArrayPush *mir() const {
michael@0 4193 return mir_->toArrayPush();
michael@0 4194 }
michael@0 4195 const LAllocation *object() {
michael@0 4196 return getOperand(0);
michael@0 4197 }
michael@0 4198 const LDefinition *temp() {
michael@0 4199 return getTemp(0);
michael@0 4200 }
michael@0 4201 };
michael@0 4202
michael@0 4203 class LArrayPushT : public LInstructionHelper<1, 2, 1>
michael@0 4204 {
michael@0 4205 public:
michael@0 4206 LIR_HEADER(ArrayPushT)
michael@0 4207
michael@0 4208 LArrayPushT(const LAllocation &object, const LAllocation &value, const LDefinition &temp) {
michael@0 4209 setOperand(0, object);
michael@0 4210 setOperand(1, value);
michael@0 4211 setTemp(0, temp);
michael@0 4212 }
michael@0 4213
michael@0 4214 const MArrayPush *mir() const {
michael@0 4215 return mir_->toArrayPush();
michael@0 4216 }
michael@0 4217 const LAllocation *object() {
michael@0 4218 return getOperand(0);
michael@0 4219 }
michael@0 4220 const LAllocation *value() {
michael@0 4221 return getOperand(1);
michael@0 4222 }
michael@0 4223 const LDefinition *temp() {
michael@0 4224 return getTemp(0);
michael@0 4225 }
michael@0 4226 };
michael@0 4227
michael@0 4228 class LArrayConcat : public LCallInstructionHelper<1, 2, 2>
michael@0 4229 {
michael@0 4230 public:
michael@0 4231 LIR_HEADER(ArrayConcat)
michael@0 4232
michael@0 4233 LArrayConcat(const LAllocation &lhs, const LAllocation &rhs,
michael@0 4234 const LDefinition &temp1, const LDefinition &temp2) {
michael@0 4235 setOperand(0, lhs);
michael@0 4236 setOperand(1, rhs);
michael@0 4237 setTemp(0, temp1);
michael@0 4238 setTemp(1, temp2);
michael@0 4239 }
michael@0 4240 const MArrayConcat *mir() const {
michael@0 4241 return mir_->toArrayConcat();
michael@0 4242 }
michael@0 4243 const LAllocation *lhs() {
michael@0 4244 return getOperand(0);
michael@0 4245 }
michael@0 4246 const LAllocation *rhs() {
michael@0 4247 return getOperand(1);
michael@0 4248 }
michael@0 4249 const LDefinition *temp1() {
michael@0 4250 return getTemp(0);
michael@0 4251 }
michael@0 4252 const LDefinition *temp2() {
michael@0 4253 return getTemp(1);
michael@0 4254 }
michael@0 4255 };
michael@0 4256
michael@0 4257 // Load a typed value from a typed array's elements vector.
michael@0 4258 class LLoadTypedArrayElement : public LInstructionHelper<1, 2, 1>
michael@0 4259 {
michael@0 4260 public:
michael@0 4261 LIR_HEADER(LoadTypedArrayElement)
michael@0 4262
michael@0 4263 LLoadTypedArrayElement(const LAllocation &elements, const LAllocation &index,
michael@0 4264 const LDefinition &temp) {
michael@0 4265 setOperand(0, elements);
michael@0 4266 setOperand(1, index);
michael@0 4267 setTemp(0, temp);
michael@0 4268 }
michael@0 4269 const MLoadTypedArrayElement *mir() const {
michael@0 4270 return mir_->toLoadTypedArrayElement();
michael@0 4271 }
michael@0 4272 const LAllocation *elements() {
michael@0 4273 return getOperand(0);
michael@0 4274 }
michael@0 4275 const LAllocation *index() {
michael@0 4276 return getOperand(1);
michael@0 4277 }
michael@0 4278 const LDefinition *temp() {
michael@0 4279 return getTemp(0);
michael@0 4280 }
michael@0 4281 };
michael@0 4282
michael@0 4283 class LLoadTypedArrayElementHole : public LInstructionHelper<BOX_PIECES, 2, 0>
michael@0 4284 {
michael@0 4285 public:
michael@0 4286 LIR_HEADER(LoadTypedArrayElementHole)
michael@0 4287
michael@0 4288 LLoadTypedArrayElementHole(const LAllocation &object, const LAllocation &index) {
michael@0 4289 setOperand(0, object);
michael@0 4290 setOperand(1, index);
michael@0 4291 }
michael@0 4292 const MLoadTypedArrayElementHole *mir() const {
michael@0 4293 return mir_->toLoadTypedArrayElementHole();
michael@0 4294 }
michael@0 4295 const LAllocation *object() {
michael@0 4296 return getOperand(0);
michael@0 4297 }
michael@0 4298 const LAllocation *index() {
michael@0 4299 return getOperand(1);
michael@0 4300 }
michael@0 4301 };
michael@0 4302
michael@0 4303 class LLoadTypedArrayElementStatic : public LInstructionHelper<1, 1, 0>
michael@0 4304 {
michael@0 4305 public:
michael@0 4306 LIR_HEADER(LoadTypedArrayElementStatic);
michael@0 4307 LLoadTypedArrayElementStatic(const LAllocation &ptr) {
michael@0 4308 setOperand(0, ptr);
michael@0 4309 }
michael@0 4310 MLoadTypedArrayElementStatic *mir() const {
michael@0 4311 return mir_->toLoadTypedArrayElementStatic();
michael@0 4312 }
michael@0 4313 const LAllocation *ptr() {
michael@0 4314 return getOperand(0);
michael@0 4315 }
michael@0 4316 };
michael@0 4317
michael@0 4318 class LStoreTypedArrayElement : public LInstructionHelper<0, 3, 0>
michael@0 4319 {
michael@0 4320 public:
michael@0 4321 LIR_HEADER(StoreTypedArrayElement)
michael@0 4322
michael@0 4323 LStoreTypedArrayElement(const LAllocation &elements, const LAllocation &index,
michael@0 4324 const LAllocation &value) {
michael@0 4325 setOperand(0, elements);
michael@0 4326 setOperand(1, index);
michael@0 4327 setOperand(2, value);
michael@0 4328 }
michael@0 4329
michael@0 4330 const MStoreTypedArrayElement *mir() const {
michael@0 4331 return mir_->toStoreTypedArrayElement();
michael@0 4332 }
michael@0 4333 const LAllocation *elements() {
michael@0 4334 return getOperand(0);
michael@0 4335 }
michael@0 4336 const LAllocation *index() {
michael@0 4337 return getOperand(1);
michael@0 4338 }
michael@0 4339 const LAllocation *value() {
michael@0 4340 return getOperand(2);
michael@0 4341 }
michael@0 4342 };
michael@0 4343
michael@0 4344 class LStoreTypedArrayElementHole : public LInstructionHelper<0, 4, 0>
michael@0 4345 {
michael@0 4346 public:
michael@0 4347 LIR_HEADER(StoreTypedArrayElementHole)
michael@0 4348
michael@0 4349 LStoreTypedArrayElementHole(const LAllocation &elements, const LAllocation &length,
michael@0 4350 const LAllocation &index, const LAllocation &value)
michael@0 4351 {
michael@0 4352 setOperand(0, elements);
michael@0 4353 setOperand(1, length);
michael@0 4354 setOperand(2, index);
michael@0 4355 setOperand(3, value);
michael@0 4356 }
michael@0 4357
michael@0 4358 const MStoreTypedArrayElementHole *mir() const {
michael@0 4359 return mir_->toStoreTypedArrayElementHole();
michael@0 4360 }
michael@0 4361 const LAllocation *elements() {
michael@0 4362 return getOperand(0);
michael@0 4363 }
michael@0 4364 const LAllocation *length() {
michael@0 4365 return getOperand(1);
michael@0 4366 }
michael@0 4367 const LAllocation *index() {
michael@0 4368 return getOperand(2);
michael@0 4369 }
michael@0 4370 const LAllocation *value() {
michael@0 4371 return getOperand(3);
michael@0 4372 }
michael@0 4373 };
michael@0 4374
michael@0 4375 class LStoreTypedArrayElementStatic : public LInstructionHelper<0, 2, 0>
michael@0 4376 {
michael@0 4377 public:
michael@0 4378 LIR_HEADER(StoreTypedArrayElementStatic);
michael@0 4379 LStoreTypedArrayElementStatic(const LAllocation &ptr, const LAllocation &value) {
michael@0 4380 setOperand(0, ptr);
michael@0 4381 setOperand(1, value);
michael@0 4382 }
michael@0 4383 MStoreTypedArrayElementStatic *mir() const {
michael@0 4384 return mir_->toStoreTypedArrayElementStatic();
michael@0 4385 }
michael@0 4386 const LAllocation *ptr() {
michael@0 4387 return getOperand(0);
michael@0 4388 }
michael@0 4389 const LAllocation *value() {
michael@0 4390 return getOperand(1);
michael@0 4391 }
michael@0 4392 };
michael@0 4393
michael@0 4394 class LEffectiveAddress : public LInstructionHelper<1, 2, 0>
michael@0 4395 {
michael@0 4396 public:
michael@0 4397 LIR_HEADER(EffectiveAddress);
michael@0 4398
michael@0 4399 LEffectiveAddress(const LAllocation &base, const LAllocation &index) {
michael@0 4400 setOperand(0, base);
michael@0 4401 setOperand(1, index);
michael@0 4402 }
michael@0 4403 const MEffectiveAddress *mir() const {
michael@0 4404 return mir_->toEffectiveAddress();
michael@0 4405 }
michael@0 4406 const LAllocation *base() {
michael@0 4407 return getOperand(0);
michael@0 4408 }
michael@0 4409 const LAllocation *index() {
michael@0 4410 return getOperand(1);
michael@0 4411 }
michael@0 4412 };
michael@0 4413
michael@0 4414 class LClampIToUint8 : public LInstructionHelper<1, 1, 0>
michael@0 4415 {
michael@0 4416 public:
michael@0 4417 LIR_HEADER(ClampIToUint8)
michael@0 4418
michael@0 4419 LClampIToUint8(const LAllocation &in) {
michael@0 4420 setOperand(0, in);
michael@0 4421 }
michael@0 4422 };
michael@0 4423
michael@0 4424 class LClampDToUint8 : public LInstructionHelper<1, 1, 1>
michael@0 4425 {
michael@0 4426 public:
michael@0 4427 LIR_HEADER(ClampDToUint8)
michael@0 4428
michael@0 4429 LClampDToUint8(const LAllocation &in, const LDefinition &temp) {
michael@0 4430 setOperand(0, in);
michael@0 4431 setTemp(0, temp);
michael@0 4432 }
michael@0 4433 };
michael@0 4434
michael@0 4435 class LClampVToUint8 : public LInstructionHelper<1, BOX_PIECES, 1>
michael@0 4436 {
michael@0 4437 public:
michael@0 4438 LIR_HEADER(ClampVToUint8)
michael@0 4439
michael@0 4440 LClampVToUint8(const LDefinition &tempFloat) {
michael@0 4441 setTemp(0, tempFloat);
michael@0 4442 }
michael@0 4443
michael@0 4444 static const size_t Input = 0;
michael@0 4445
michael@0 4446 const LDefinition *tempFloat() {
michael@0 4447 return getTemp(0);
michael@0 4448 }
michael@0 4449 const MClampToUint8 *mir() const {
michael@0 4450 return mir_->toClampToUint8();
michael@0 4451 }
michael@0 4452 };
michael@0 4453
michael@0 4454 // Load a boxed value from an object's fixed slot.
michael@0 4455 class LLoadFixedSlotV : public LInstructionHelper<BOX_PIECES, 1, 0>
michael@0 4456 {
michael@0 4457 public:
michael@0 4458 LIR_HEADER(LoadFixedSlotV)
michael@0 4459
michael@0 4460 LLoadFixedSlotV(const LAllocation &object) {
michael@0 4461 setOperand(0, object);
michael@0 4462 }
michael@0 4463 const MLoadFixedSlot *mir() const {
michael@0 4464 return mir_->toLoadFixedSlot();
michael@0 4465 }
michael@0 4466 };
michael@0 4467
michael@0 4468 // Load a typed value from an object's fixed slot.
michael@0 4469 class LLoadFixedSlotT : public LInstructionHelper<1, 1, 0>
michael@0 4470 {
michael@0 4471 public:
michael@0 4472 LIR_HEADER(LoadFixedSlotT)
michael@0 4473
michael@0 4474 LLoadFixedSlotT(const LAllocation &object) {
michael@0 4475 setOperand(0, object);
michael@0 4476 }
michael@0 4477 const MLoadFixedSlot *mir() const {
michael@0 4478 return mir_->toLoadFixedSlot();
michael@0 4479 }
michael@0 4480 };
michael@0 4481
michael@0 4482 // Store a boxed value to an object's fixed slot.
michael@0 4483 class LStoreFixedSlotV : public LInstructionHelper<0, 1 + BOX_PIECES, 0>
michael@0 4484 {
michael@0 4485 public:
michael@0 4486 LIR_HEADER(StoreFixedSlotV)
michael@0 4487
michael@0 4488 LStoreFixedSlotV(const LAllocation &obj) {
michael@0 4489 setOperand(0, obj);
michael@0 4490 }
michael@0 4491
michael@0 4492 static const size_t Value = 1;
michael@0 4493
michael@0 4494 const MStoreFixedSlot *mir() const {
michael@0 4495 return mir_->toStoreFixedSlot();
michael@0 4496 }
michael@0 4497 const LAllocation *obj() {
michael@0 4498 return getOperand(0);
michael@0 4499 }
michael@0 4500 };
michael@0 4501
michael@0 4502 // Store a typed value to an object's fixed slot.
michael@0 4503 class LStoreFixedSlotT : public LInstructionHelper<0, 2, 0>
michael@0 4504 {
michael@0 4505 public:
michael@0 4506 LIR_HEADER(StoreFixedSlotT)
michael@0 4507
michael@0 4508 LStoreFixedSlotT(const LAllocation &obj, const LAllocation &value)
michael@0 4509 {
michael@0 4510 setOperand(0, obj);
michael@0 4511 setOperand(1, value);
michael@0 4512 }
michael@0 4513 const MStoreFixedSlot *mir() const {
michael@0 4514 return mir_->toStoreFixedSlot();
michael@0 4515 }
michael@0 4516 const LAllocation *obj() {
michael@0 4517 return getOperand(0);
michael@0 4518 }
michael@0 4519 const LAllocation *value() {
michael@0 4520 return getOperand(1);
michael@0 4521 }
michael@0 4522 };
michael@0 4523
michael@0 4524 // Note, Name ICs always return a Value. There are no V/T variants.
michael@0 4525 class LGetNameCache : public LInstructionHelper<BOX_PIECES, 1, 0>
michael@0 4526 {
michael@0 4527 public:
michael@0 4528 LIR_HEADER(GetNameCache)
michael@0 4529
michael@0 4530 LGetNameCache(const LAllocation &scopeObj) {
michael@0 4531 setOperand(0, scopeObj);
michael@0 4532 }
michael@0 4533 const LAllocation *scopeObj() {
michael@0 4534 return getOperand(0);
michael@0 4535 }
michael@0 4536 const MGetNameCache *mir() const {
michael@0 4537 return mir_->toGetNameCache();
michael@0 4538 }
michael@0 4539 };
michael@0 4540
michael@0 4541 class LCallGetIntrinsicValue : public LCallInstructionHelper<BOX_PIECES, 0, 0>
michael@0 4542 {
michael@0 4543 public:
michael@0 4544 LIR_HEADER(CallGetIntrinsicValue)
michael@0 4545
michael@0 4546 const MCallGetIntrinsicValue *mir() const {
michael@0 4547 return mir_->toCallGetIntrinsicValue();
michael@0 4548 }
michael@0 4549 };
michael@0 4550
michael@0 4551 class LCallsiteCloneCache : public LInstructionHelper<1, 1, 0>
michael@0 4552 {
michael@0 4553 public:
michael@0 4554 LIR_HEADER(CallsiteCloneCache);
michael@0 4555
michael@0 4556 LCallsiteCloneCache(const LAllocation &callee) {
michael@0 4557 setOperand(0, callee);
michael@0 4558 }
michael@0 4559 const LAllocation *callee() {
michael@0 4560 return getOperand(0);
michael@0 4561 }
michael@0 4562 const MCallsiteCloneCache *mir() const {
michael@0 4563 return mir_->toCallsiteCloneCache();
michael@0 4564 }
michael@0 4565 };
michael@0 4566
michael@0 4567 // Patchable jump to stubs generated for a GetProperty cache, which loads a
michael@0 4568 // boxed value.
michael@0 4569 class LGetPropertyCacheV : public LInstructionHelper<BOX_PIECES, 1, 0>
michael@0 4570 {
michael@0 4571 public:
michael@0 4572 LIR_HEADER(GetPropertyCacheV)
michael@0 4573
michael@0 4574 LGetPropertyCacheV(const LAllocation &object) {
michael@0 4575 setOperand(0, object);
michael@0 4576 }
michael@0 4577 const MGetPropertyCache *mir() const {
michael@0 4578 return mir_->toGetPropertyCache();
michael@0 4579 }
michael@0 4580 };
michael@0 4581
michael@0 4582 // Patchable jump to stubs generated for a GetProperty cache, which loads a
michael@0 4583 // value of a known type, possibly into an FP register.
michael@0 4584 class LGetPropertyCacheT : public LInstructionHelper<1, 1, 1>
michael@0 4585 {
michael@0 4586 public:
michael@0 4587 LIR_HEADER(GetPropertyCacheT)
michael@0 4588
michael@0 4589 LGetPropertyCacheT(const LAllocation &object, const LDefinition &temp) {
michael@0 4590 setOperand(0, object);
michael@0 4591 setTemp(0, temp);
michael@0 4592 }
michael@0 4593 const LDefinition *temp() {
michael@0 4594 return getTemp(0);
michael@0 4595 }
michael@0 4596 const MGetPropertyCache *mir() const {
michael@0 4597 return mir_->toGetPropertyCache();
michael@0 4598 }
michael@0 4599 };
michael@0 4600
michael@0 4601 // Emit code to load a boxed value from an object's slots if its shape matches
michael@0 4602 // one of the shapes observed by the baseline IC, else bails out.
michael@0 4603 class LGetPropertyPolymorphicV : public LInstructionHelper<BOX_PIECES, 1, 0>
michael@0 4604 {
michael@0 4605 public:
michael@0 4606 LIR_HEADER(GetPropertyPolymorphicV)
michael@0 4607
michael@0 4608 LGetPropertyPolymorphicV(const LAllocation &obj) {
michael@0 4609 setOperand(0, obj);
michael@0 4610 }
michael@0 4611 const LAllocation *obj() {
michael@0 4612 return getOperand(0);
michael@0 4613 }
michael@0 4614 const MGetPropertyPolymorphic *mir() const {
michael@0 4615 return mir_->toGetPropertyPolymorphic();
michael@0 4616 }
michael@0 4617 };
michael@0 4618
michael@0 4619 // Emit code to load a typed value from an object's slots if its shape matches
michael@0 4620 // one of the shapes observed by the baseline IC, else bails out.
michael@0 4621 class LGetPropertyPolymorphicT : public LInstructionHelper<1, 1, 1>
michael@0 4622 {
michael@0 4623 public:
michael@0 4624 LIR_HEADER(GetPropertyPolymorphicT)
michael@0 4625
michael@0 4626 LGetPropertyPolymorphicT(const LAllocation &obj, const LDefinition &temp) {
michael@0 4627 setOperand(0, obj);
michael@0 4628 setTemp(0, temp);
michael@0 4629 }
michael@0 4630 const LAllocation *obj() {
michael@0 4631 return getOperand(0);
michael@0 4632 }
michael@0 4633 const LDefinition *temp() {
michael@0 4634 return getTemp(0);
michael@0 4635 }
michael@0 4636 const MGetPropertyPolymorphic *mir() const {
michael@0 4637 return mir_->toGetPropertyPolymorphic();
michael@0 4638 }
michael@0 4639 };
michael@0 4640
michael@0 4641 // Emit code to store a boxed value to an object's slots if its shape matches
michael@0 4642 // one of the shapes observed by the baseline IC, else bails out.
michael@0 4643 class LSetPropertyPolymorphicV : public LInstructionHelper<0, 1 + BOX_PIECES, 1>
michael@0 4644 {
michael@0 4645 public:
michael@0 4646 LIR_HEADER(SetPropertyPolymorphicV)
michael@0 4647
michael@0 4648 LSetPropertyPolymorphicV(const LAllocation &obj, const LDefinition &temp) {
michael@0 4649 setOperand(0, obj);
michael@0 4650 setTemp(0, temp);
michael@0 4651 }
michael@0 4652
michael@0 4653 static const size_t Value = 1;
michael@0 4654
michael@0 4655 const LAllocation *obj() {
michael@0 4656 return getOperand(0);
michael@0 4657 }
michael@0 4658 const LDefinition *temp() {
michael@0 4659 return getTemp(0);
michael@0 4660 }
michael@0 4661 const MSetPropertyPolymorphic *mir() const {
michael@0 4662 return mir_->toSetPropertyPolymorphic();
michael@0 4663 }
michael@0 4664 };
michael@0 4665
michael@0 4666 // Emit code to store a typed value to an object's slots if its shape matches
michael@0 4667 // one of the shapes observed by the baseline IC, else bails out.
michael@0 4668 class LSetPropertyPolymorphicT : public LInstructionHelper<0, 2, 1>
michael@0 4669 {
michael@0 4670 MIRType valueType_;
michael@0 4671
michael@0 4672 public:
michael@0 4673 LIR_HEADER(SetPropertyPolymorphicT)
michael@0 4674
michael@0 4675 LSetPropertyPolymorphicT(const LAllocation &obj, const LAllocation &value, MIRType valueType,
michael@0 4676 const LDefinition &temp)
michael@0 4677 : valueType_(valueType)
michael@0 4678 {
michael@0 4679 setOperand(0, obj);
michael@0 4680 setOperand(1, value);
michael@0 4681 setTemp(0, temp);
michael@0 4682 }
michael@0 4683
michael@0 4684 const LAllocation *obj() {
michael@0 4685 return getOperand(0);
michael@0 4686 }
michael@0 4687 const LAllocation *value() {
michael@0 4688 return getOperand(1);
michael@0 4689 }
michael@0 4690 const LDefinition *temp() {
michael@0 4691 return getTemp(0);
michael@0 4692 }
michael@0 4693 MIRType valueType() const {
michael@0 4694 return valueType_;
michael@0 4695 }
michael@0 4696 const MSetPropertyPolymorphic *mir() const {
michael@0 4697 return mir_->toSetPropertyPolymorphic();
michael@0 4698 }
michael@0 4699 const char *extraName() const {
michael@0 4700 return StringFromMIRType(valueType_);
michael@0 4701 }
michael@0 4702 };
michael@0 4703
michael@0 4704 class LGetElementCacheV : public LInstructionHelper<BOX_PIECES, 1 + BOX_PIECES, 0>
michael@0 4705 {
michael@0 4706 public:
michael@0 4707 LIR_HEADER(GetElementCacheV)
michael@0 4708
michael@0 4709 static const size_t Index = 1;
michael@0 4710
michael@0 4711 LGetElementCacheV(const LAllocation &object) {
michael@0 4712 setOperand(0, object);
michael@0 4713 }
michael@0 4714 const LAllocation *object() {
michael@0 4715 return getOperand(0);
michael@0 4716 }
michael@0 4717 const MGetElementCache *mir() const {
michael@0 4718 return mir_->toGetElementCache();
michael@0 4719 }
michael@0 4720 };
michael@0 4721
michael@0 4722 class LGetElementCacheT : public LInstructionHelper<1, 2, 1>
michael@0 4723 {
michael@0 4724 public:
michael@0 4725 LIR_HEADER(GetElementCacheT)
michael@0 4726
michael@0 4727 LGetElementCacheT(const LAllocation &object, const LAllocation &index,
michael@0 4728 const LDefinition &temp) {
michael@0 4729 setOperand(0, object);
michael@0 4730 setOperand(1, index);
michael@0 4731 setTemp(0, temp);
michael@0 4732 }
michael@0 4733 const LAllocation *object() {
michael@0 4734 return getOperand(0);
michael@0 4735 }
michael@0 4736 const LAllocation *index() {
michael@0 4737 return getOperand(1);
michael@0 4738 }
michael@0 4739 const LDefinition *output() {
michael@0 4740 return getDef(0);
michael@0 4741 }
michael@0 4742 const LDefinition *temp() {
michael@0 4743 return getTemp(0);
michael@0 4744 }
michael@0 4745 const MGetElementCache *mir() const {
michael@0 4746 return mir_->toGetElementCache();
michael@0 4747 }
michael@0 4748 };
michael@0 4749
michael@0 4750 class LBindNameCache : public LInstructionHelper<1, 1, 0>
michael@0 4751 {
michael@0 4752 public:
michael@0 4753 LIR_HEADER(BindNameCache)
michael@0 4754
michael@0 4755 LBindNameCache(const LAllocation &scopeChain) {
michael@0 4756 setOperand(0, scopeChain);
michael@0 4757 }
michael@0 4758 const LAllocation *scopeChain() {
michael@0 4759 return getOperand(0);
michael@0 4760 }
michael@0 4761 const MBindNameCache *mir() const {
michael@0 4762 return mir_->toBindNameCache();
michael@0 4763 }
michael@0 4764 };
michael@0 4765
michael@0 4766 // Load a value from an object's dslots or a slots vector.
michael@0 4767 class LLoadSlotV : public LInstructionHelper<BOX_PIECES, 1, 0>
michael@0 4768 {
michael@0 4769 public:
michael@0 4770 LIR_HEADER(LoadSlotV)
michael@0 4771
michael@0 4772 LLoadSlotV(const LAllocation &in) {
michael@0 4773 setOperand(0, in);
michael@0 4774 }
michael@0 4775 const MLoadSlot *mir() const {
michael@0 4776 return mir_->toLoadSlot();
michael@0 4777 }
michael@0 4778 };
michael@0 4779
michael@0 4780 // Load a typed value from an object's dslots or a slots vector. Unlike
michael@0 4781 // LLoadSlotV, this can bypass extracting a type tag, directly retrieving a
michael@0 4782 // pointer, integer, or double.
michael@0 4783 class LLoadSlotT : public LInstructionHelper<1, 1, 0>
michael@0 4784 {
michael@0 4785 public:
michael@0 4786 LIR_HEADER(LoadSlotT)
michael@0 4787
michael@0 4788 LLoadSlotT(const LAllocation &in) {
michael@0 4789 setOperand(0, in);
michael@0 4790 }
michael@0 4791 const MLoadSlot *mir() const {
michael@0 4792 return mir_->toLoadSlot();
michael@0 4793 }
michael@0 4794 };
michael@0 4795
michael@0 4796 // Store a value to an object's dslots or a slots vector.
michael@0 4797 class LStoreSlotV : public LInstructionHelper<0, 1 + BOX_PIECES, 0>
michael@0 4798 {
michael@0 4799 public:
michael@0 4800 LIR_HEADER(StoreSlotV)
michael@0 4801
michael@0 4802 LStoreSlotV(const LAllocation &slots) {
michael@0 4803 setOperand(0, slots);
michael@0 4804 }
michael@0 4805
michael@0 4806 static const size_t Value = 1;
michael@0 4807
michael@0 4808 const MStoreSlot *mir() const {
michael@0 4809 return mir_->toStoreSlot();
michael@0 4810 }
michael@0 4811 const LAllocation *slots() {
michael@0 4812 return getOperand(0);
michael@0 4813 }
michael@0 4814 };
michael@0 4815
michael@0 4816 // Store a typed value to an object's dslots or a slots vector. This has a
michael@0 4817 // few advantages over LStoreSlotV:
michael@0 4818 // 1) We can bypass storing the type tag if the slot has the same type as
michael@0 4819 // the value.
michael@0 4820 // 2) Better register allocation: we can store constants and FP regs directly
michael@0 4821 // without requiring a second register for the value.
michael@0 4822 class LStoreSlotT : public LInstructionHelper<0, 2, 0>
michael@0 4823 {
michael@0 4824 public:
michael@0 4825 LIR_HEADER(StoreSlotT)
michael@0 4826
michael@0 4827 LStoreSlotT(const LAllocation &slots, const LAllocation &value) {
michael@0 4828 setOperand(0, slots);
michael@0 4829 setOperand(1, value);
michael@0 4830 }
michael@0 4831 const MStoreSlot *mir() const {
michael@0 4832 return mir_->toStoreSlot();
michael@0 4833 }
michael@0 4834 const LAllocation *slots() {
michael@0 4835 return getOperand(0);
michael@0 4836 }
michael@0 4837 const LAllocation *value() {
michael@0 4838 return getOperand(1);
michael@0 4839 }
michael@0 4840 };
michael@0 4841
michael@0 4842 // Read length field of a JSString*.
michael@0 4843 class LStringLength : public LInstructionHelper<1, 1, 0>
michael@0 4844 {
michael@0 4845 public:
michael@0 4846 LIR_HEADER(StringLength)
michael@0 4847
michael@0 4848 LStringLength(const LAllocation &string) {
michael@0 4849 setOperand(0, string);
michael@0 4850 }
michael@0 4851
michael@0 4852 const LAllocation *string() {
michael@0 4853 return getOperand(0);
michael@0 4854 }
michael@0 4855 };
michael@0 4856
michael@0 4857 // Take the floor of a double precision number. Implements Math.floor().
michael@0 4858 class LFloor : public LInstructionHelper<1, 1, 0>
michael@0 4859 {
michael@0 4860 public:
michael@0 4861 LIR_HEADER(Floor)
michael@0 4862
michael@0 4863 LFloor(const LAllocation &num) {
michael@0 4864 setOperand(0, num);
michael@0 4865 }
michael@0 4866 };
michael@0 4867
michael@0 4868 // Take the floor of a single precision number. Implements Math.floor().
michael@0 4869 class LFloorF : public LInstructionHelper<1, 1, 0>
michael@0 4870 {
michael@0 4871 public:
michael@0 4872 LIR_HEADER(FloorF)
michael@0 4873
michael@0 4874 LFloorF(const LAllocation &num) {
michael@0 4875 setOperand(0, num);
michael@0 4876 }
michael@0 4877 };
michael@0 4878
michael@0 4879 // Round a double precision number. Implements Math.round().
michael@0 4880 class LRound : public LInstructionHelper<1, 1, 1>
michael@0 4881 {
michael@0 4882 public:
michael@0 4883 LIR_HEADER(Round)
michael@0 4884
michael@0 4885 LRound(const LAllocation &num, const LDefinition &temp) {
michael@0 4886 setOperand(0, num);
michael@0 4887 setTemp(0, temp);
michael@0 4888 }
michael@0 4889
michael@0 4890 const LDefinition *temp() {
michael@0 4891 return getTemp(0);
michael@0 4892 }
michael@0 4893 MRound *mir() const {
michael@0 4894 return mir_->toRound();
michael@0 4895 }
michael@0 4896 };
michael@0 4897
michael@0 4898 // Round a single precision number. Implements Math.round().
michael@0 4899 class LRoundF : public LInstructionHelper<1, 1, 1>
michael@0 4900 {
michael@0 4901 public:
michael@0 4902 LIR_HEADER(RoundF)
michael@0 4903
michael@0 4904 LRoundF(const LAllocation &num, const LDefinition &temp) {
michael@0 4905 setOperand(0, num);
michael@0 4906 setTemp(0, temp);
michael@0 4907 }
michael@0 4908
michael@0 4909 const LDefinition *temp() {
michael@0 4910 return getTemp(0);
michael@0 4911 }
michael@0 4912 MRound *mir() const {
michael@0 4913 return mir_->toRound();
michael@0 4914 }
michael@0 4915 };
michael@0 4916
michael@0 4917 // Load a function's call environment.
michael@0 4918 class LFunctionEnvironment : public LInstructionHelper<1, 1, 0>
michael@0 4919 {
michael@0 4920 public:
michael@0 4921 LIR_HEADER(FunctionEnvironment)
michael@0 4922
michael@0 4923 LFunctionEnvironment(const LAllocation &function) {
michael@0 4924 setOperand(0, function);
michael@0 4925 }
michael@0 4926 const LAllocation *function() {
michael@0 4927 return getOperand(0);
michael@0 4928 }
michael@0 4929 };
michael@0 4930
michael@0 4931 class LForkJoinContext : public LCallInstructionHelper<1, 0, 1>
michael@0 4932 {
michael@0 4933 public:
michael@0 4934 LIR_HEADER(ForkJoinContext);
michael@0 4935
michael@0 4936 LForkJoinContext(const LDefinition &temp1) {
michael@0 4937 setTemp(0, temp1);
michael@0 4938 }
michael@0 4939
michael@0 4940 const LDefinition *getTempReg() {
michael@0 4941 return getTemp(0);
michael@0 4942 }
michael@0 4943 };
michael@0 4944
michael@0 4945 class LForkJoinGetSlice : public LInstructionHelper<1, 1, 4>
michael@0 4946 {
michael@0 4947 public:
michael@0 4948 LIR_HEADER(ForkJoinGetSlice);
michael@0 4949
michael@0 4950 LForkJoinGetSlice(const LAllocation &cx,
michael@0 4951 const LDefinition &temp1, const LDefinition &temp2,
michael@0 4952 const LDefinition &temp3, const LDefinition &temp4) {
michael@0 4953 setOperand(0, cx);
michael@0 4954 setTemp(0, temp1);
michael@0 4955 setTemp(1, temp2);
michael@0 4956 setTemp(2, temp3);
michael@0 4957 setTemp(3, temp4);
michael@0 4958 }
michael@0 4959
michael@0 4960 const LAllocation *forkJoinContext() {
michael@0 4961 return getOperand(0);
michael@0 4962 }
michael@0 4963 const LDefinition *temp1() {
michael@0 4964 return getTemp(0);
michael@0 4965 }
michael@0 4966 const LDefinition *temp2() {
michael@0 4967 return getTemp(1);
michael@0 4968 }
michael@0 4969 const LDefinition *temp3() {
michael@0 4970 return getTemp(2);
michael@0 4971 }
michael@0 4972 const LDefinition *temp4() {
michael@0 4973 return getTemp(3);
michael@0 4974 }
michael@0 4975 };
michael@0 4976
michael@0 4977 class LCallGetProperty : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
michael@0 4978 {
michael@0 4979 public:
michael@0 4980 LIR_HEADER(CallGetProperty)
michael@0 4981
michael@0 4982 static const size_t Value = 0;
michael@0 4983
michael@0 4984 MCallGetProperty *mir() const {
michael@0 4985 return mir_->toCallGetProperty();
michael@0 4986 }
michael@0 4987 };
michael@0 4988
michael@0 4989 // Call js::GetElement.
michael@0 4990 class LCallGetElement : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0>
michael@0 4991 {
michael@0 4992 public:
michael@0 4993 LIR_HEADER(CallGetElement)
michael@0 4994
michael@0 4995 static const size_t LhsInput = 0;
michael@0 4996 static const size_t RhsInput = BOX_PIECES;
michael@0 4997
michael@0 4998 MCallGetElement *mir() const {
michael@0 4999 return mir_->toCallGetElement();
michael@0 5000 }
michael@0 5001 };
michael@0 5002
michael@0 5003 // Call js::SetElement.
michael@0 5004 class LCallSetElement : public LCallInstructionHelper<0, 1 + 2 * BOX_PIECES, 0>
michael@0 5005 {
michael@0 5006 public:
michael@0 5007 LIR_HEADER(CallSetElement)
michael@0 5008
michael@0 5009 static const size_t Index = 1;
michael@0 5010 static const size_t Value = 1 + BOX_PIECES;
michael@0 5011 };
michael@0 5012
michael@0 5013 // Call js::InitElementArray.
michael@0 5014 class LCallInitElementArray : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
michael@0 5015 {
michael@0 5016 public:
michael@0 5017 LIR_HEADER(CallInitElementArray)
michael@0 5018
michael@0 5019 static const size_t Value = 1;
michael@0 5020
michael@0 5021 const MCallInitElementArray *mir() const {
michael@0 5022 return mir_->toCallInitElementArray();
michael@0 5023 }
michael@0 5024 };
michael@0 5025
michael@0 5026 // Call a VM function to perform a property or name assignment of a generic value.
michael@0 5027 class LCallSetProperty : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
michael@0 5028 {
michael@0 5029 public:
michael@0 5030 LIR_HEADER(CallSetProperty)
michael@0 5031
michael@0 5032 LCallSetProperty(const LAllocation &obj) {
michael@0 5033 setOperand(0, obj);
michael@0 5034 }
michael@0 5035
michael@0 5036 static const size_t Value = 1;
michael@0 5037
michael@0 5038 const MCallSetProperty *mir() const {
michael@0 5039 return mir_->toCallSetProperty();
michael@0 5040 }
michael@0 5041 };
michael@0 5042
michael@0 5043 class LCallDeleteProperty : public LCallInstructionHelper<1, BOX_PIECES, 0>
michael@0 5044 {
michael@0 5045 public:
michael@0 5046 LIR_HEADER(CallDeleteProperty)
michael@0 5047
michael@0 5048 static const size_t Value = 0;
michael@0 5049
michael@0 5050 MDeleteProperty *mir() const {
michael@0 5051 return mir_->toDeleteProperty();
michael@0 5052 }
michael@0 5053 };
michael@0 5054
michael@0 5055 class LCallDeleteElement : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
michael@0 5056 {
michael@0 5057 public:
michael@0 5058 LIR_HEADER(CallDeleteElement)
michael@0 5059
michael@0 5060 static const size_t Value = 0;
michael@0 5061 static const size_t Index = BOX_PIECES;
michael@0 5062
michael@0 5063 MDeleteElement *mir() const {
michael@0 5064 return mir_->toDeleteElement();
michael@0 5065 }
michael@0 5066 };
michael@0 5067
michael@0 5068 // Patchable jump to stubs generated for a SetProperty cache, which stores a
michael@0 5069 // boxed value.
michael@0 5070 class LSetPropertyCacheV : public LInstructionHelper<0, 1 + BOX_PIECES, 2>
michael@0 5071 {
michael@0 5072 public:
michael@0 5073 LIR_HEADER(SetPropertyCacheV)
michael@0 5074
michael@0 5075 LSetPropertyCacheV(const LAllocation &object, const LDefinition &slots,
michael@0 5076 const LDefinition &temp) {
michael@0 5077 setOperand(0, object);
michael@0 5078 setTemp(0, slots);
michael@0 5079 setTemp(1, temp);
michael@0 5080 }
michael@0 5081
michael@0 5082 static const size_t Value = 1;
michael@0 5083
michael@0 5084 const MSetPropertyCache *mir() const {
michael@0 5085 return mir_->toSetPropertyCache();
michael@0 5086 }
michael@0 5087
michael@0 5088 const LDefinition *tempForDispatchCache() {
michael@0 5089 return getTemp(1);
michael@0 5090 }
michael@0 5091 };
michael@0 5092
michael@0 5093 // Patchable jump to stubs generated for a SetProperty cache, which stores a
michael@0 5094 // value of a known type.
michael@0 5095 class LSetPropertyCacheT : public LInstructionHelper<0, 2, 2>
michael@0 5096 {
michael@0 5097 MIRType valueType_;
michael@0 5098
michael@0 5099 public:
michael@0 5100 LIR_HEADER(SetPropertyCacheT)
michael@0 5101
michael@0 5102 LSetPropertyCacheT(const LAllocation &object, const LDefinition &slots,
michael@0 5103 const LAllocation &value, const LDefinition &temp,
michael@0 5104 MIRType valueType)
michael@0 5105 : valueType_(valueType)
michael@0 5106 {
michael@0 5107 setOperand(0, object);
michael@0 5108 setOperand(1, value);
michael@0 5109 setTemp(0, slots);
michael@0 5110 setTemp(1, temp);
michael@0 5111 }
michael@0 5112
michael@0 5113 const MSetPropertyCache *mir() const {
michael@0 5114 return mir_->toSetPropertyCache();
michael@0 5115 }
michael@0 5116 MIRType valueType() {
michael@0 5117 return valueType_;
michael@0 5118 }
michael@0 5119 const char *extraName() const {
michael@0 5120 return StringFromMIRType(valueType_);
michael@0 5121 }
michael@0 5122
michael@0 5123 const LDefinition *tempForDispatchCache() {
michael@0 5124 return getTemp(1);
michael@0 5125 }
michael@0 5126 };
michael@0 5127
michael@0 5128 class LSetElementCacheV : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 3>
michael@0 5129 {
michael@0 5130 public:
michael@0 5131 LIR_HEADER(SetElementCacheV);
michael@0 5132
michael@0 5133 static const size_t Index = 1;
michael@0 5134 static const size_t Value = 1 + BOX_PIECES;
michael@0 5135
michael@0 5136 LSetElementCacheV(const LAllocation &object, const LDefinition &tempToUnboxIndex,
michael@0 5137 const LDefinition &temp, const LDefinition &tempFloat)
michael@0 5138 {
michael@0 5139 setOperand(0, object);
michael@0 5140 setTemp(0, tempToUnboxIndex);
michael@0 5141 setTemp(1, temp);
michael@0 5142 setTemp(2, tempFloat);
michael@0 5143 }
michael@0 5144 const MSetElementCache *mir() const {
michael@0 5145 return mir_->toSetElementCache();
michael@0 5146 }
michael@0 5147
michael@0 5148 const LAllocation *object() {
michael@0 5149 return getOperand(0);
michael@0 5150 }
michael@0 5151 const LDefinition *tempToUnboxIndex() {
michael@0 5152 return getTemp(0);
michael@0 5153 }
michael@0 5154 const LDefinition *temp() {
michael@0 5155 return getTemp(1);
michael@0 5156 }
michael@0 5157 const LDefinition *tempFloat() {
michael@0 5158 return getTemp(2);
michael@0 5159 }
michael@0 5160 };
michael@0 5161
michael@0 5162 class LSetElementCacheT : public LInstructionHelper<0, 2 + BOX_PIECES, 3>
michael@0 5163 {
michael@0 5164 public:
michael@0 5165 LIR_HEADER(SetElementCacheT);
michael@0 5166
michael@0 5167 static const size_t Index = 2;
michael@0 5168
michael@0 5169 LSetElementCacheT(const LAllocation &object, const LAllocation &value,
michael@0 5170 const LDefinition &tempToUnboxIndex,
michael@0 5171 const LDefinition &temp, const LDefinition &tempFloat) {
michael@0 5172 setOperand(0, object);
michael@0 5173 setOperand(1, value);
michael@0 5174 setTemp(0, tempToUnboxIndex);
michael@0 5175 setTemp(1, temp);
michael@0 5176 setTemp(2, tempFloat);
michael@0 5177 }
michael@0 5178 const MSetElementCache *mir() const {
michael@0 5179 return mir_->toSetElementCache();
michael@0 5180 }
michael@0 5181
michael@0 5182 const LAllocation *object() {
michael@0 5183 return getOperand(0);
michael@0 5184 }
michael@0 5185 const LAllocation *value() {
michael@0 5186 return getOperand(1);
michael@0 5187 }
michael@0 5188 const LDefinition *tempToUnboxIndex() {
michael@0 5189 return getTemp(0);
michael@0 5190 }
michael@0 5191 const LDefinition *temp() {
michael@0 5192 return getTemp(1);
michael@0 5193 }
michael@0 5194 const LDefinition *tempFloat() {
michael@0 5195 return getTemp(2);
michael@0 5196 }
michael@0 5197 };
michael@0 5198
michael@0 5199 class LCallIteratorStart : public LCallInstructionHelper<1, 1, 0>
michael@0 5200 {
michael@0 5201 public:
michael@0 5202 LIR_HEADER(CallIteratorStart)
michael@0 5203
michael@0 5204 LCallIteratorStart(const LAllocation &object) {
michael@0 5205 setOperand(0, object);
michael@0 5206 }
michael@0 5207 const LAllocation *object() {
michael@0 5208 return getOperand(0);
michael@0 5209 }
michael@0 5210 MIteratorStart *mir() const {
michael@0 5211 return mir_->toIteratorStart();
michael@0 5212 }
michael@0 5213 };
michael@0 5214
michael@0 5215 class LIteratorStart : public LInstructionHelper<1, 1, 3>
michael@0 5216 {
michael@0 5217 public:
michael@0 5218 LIR_HEADER(IteratorStart)
michael@0 5219
michael@0 5220 LIteratorStart(const LAllocation &object, const LDefinition &temp1,
michael@0 5221 const LDefinition &temp2, const LDefinition &temp3) {
michael@0 5222 setOperand(0, object);
michael@0 5223 setTemp(0, temp1);
michael@0 5224 setTemp(1, temp2);
michael@0 5225 setTemp(2, temp3);
michael@0 5226 }
michael@0 5227 const LAllocation *object() {
michael@0 5228 return getOperand(0);
michael@0 5229 }
michael@0 5230 const LDefinition *temp1() {
michael@0 5231 return getTemp(0);
michael@0 5232 }
michael@0 5233 const LDefinition *temp2() {
michael@0 5234 return getTemp(1);
michael@0 5235 }
michael@0 5236 const LDefinition *temp3() {
michael@0 5237 return getTemp(2);
michael@0 5238 }
michael@0 5239 MIteratorStart *mir() const {
michael@0 5240 return mir_->toIteratorStart();
michael@0 5241 }
michael@0 5242 };
michael@0 5243
michael@0 5244 class LIteratorNext : public LInstructionHelper<BOX_PIECES, 1, 1>
michael@0 5245 {
michael@0 5246 public:
michael@0 5247 LIR_HEADER(IteratorNext)
michael@0 5248
michael@0 5249 LIteratorNext(const LAllocation &iterator, const LDefinition &temp) {
michael@0 5250 setOperand(0, iterator);
michael@0 5251 setTemp(0, temp);
michael@0 5252 }
michael@0 5253 const LAllocation *object() {
michael@0 5254 return getOperand(0);
michael@0 5255 }
michael@0 5256 const LDefinition *temp() {
michael@0 5257 return getTemp(0);
michael@0 5258 }
michael@0 5259 MIteratorNext *mir() const {
michael@0 5260 return mir_->toIteratorNext();
michael@0 5261 }
michael@0 5262 };
michael@0 5263
michael@0 5264 class LIteratorMore : public LInstructionHelper<1, 1, 1>
michael@0 5265 {
michael@0 5266 public:
michael@0 5267 LIR_HEADER(IteratorMore)
michael@0 5268
michael@0 5269 LIteratorMore(const LAllocation &iterator, const LDefinition &temp) {
michael@0 5270 setOperand(0, iterator);
michael@0 5271 setTemp(0, temp);
michael@0 5272 }
michael@0 5273 const LAllocation *object() {
michael@0 5274 return getOperand(0);
michael@0 5275 }
michael@0 5276 const LDefinition *temp() {
michael@0 5277 return getTemp(0);
michael@0 5278 }
michael@0 5279 MIteratorMore *mir() const {
michael@0 5280 return mir_->toIteratorMore();
michael@0 5281 }
michael@0 5282 };
michael@0 5283
michael@0 5284 class LIteratorEnd : public LInstructionHelper<0, 1, 3>
michael@0 5285 {
michael@0 5286 public:
michael@0 5287 LIR_HEADER(IteratorEnd)
michael@0 5288
michael@0 5289 LIteratorEnd(const LAllocation &iterator, const LDefinition &temp1,
michael@0 5290 const LDefinition &temp2, const LDefinition &temp3) {
michael@0 5291 setOperand(0, iterator);
michael@0 5292 setTemp(0, temp1);
michael@0 5293 setTemp(1, temp2);
michael@0 5294 setTemp(2, temp3);
michael@0 5295 }
michael@0 5296 const LAllocation *object() {
michael@0 5297 return getOperand(0);
michael@0 5298 }
michael@0 5299 const LDefinition *temp1() {
michael@0 5300 return getTemp(0);
michael@0 5301 }
michael@0 5302 const LDefinition *temp2() {
michael@0 5303 return getTemp(1);
michael@0 5304 }
michael@0 5305 const LDefinition *temp3() {
michael@0 5306 return getTemp(2);
michael@0 5307 }
michael@0 5308 MIteratorEnd *mir() const {
michael@0 5309 return mir_->toIteratorEnd();
michael@0 5310 }
michael@0 5311 };
michael@0 5312
michael@0 5313 // Read the number of actual arguments.
michael@0 5314 class LArgumentsLength : public LInstructionHelper<1, 0, 0>
michael@0 5315 {
michael@0 5316 public:
michael@0 5317 LIR_HEADER(ArgumentsLength)
michael@0 5318 };
michael@0 5319
michael@0 5320 // Load a value from the actual arguments.
michael@0 5321 class LGetFrameArgument : public LInstructionHelper<BOX_PIECES, 1, 0>
michael@0 5322 {
michael@0 5323 public:
michael@0 5324 LIR_HEADER(GetFrameArgument)
michael@0 5325
michael@0 5326 LGetFrameArgument(const LAllocation &index) {
michael@0 5327 setOperand(0, index);
michael@0 5328 }
michael@0 5329 const LAllocation *index() {
michael@0 5330 return getOperand(0);
michael@0 5331 }
michael@0 5332 };
michael@0 5333
michael@0 5334 // Load a value from the actual arguments.
michael@0 5335 class LSetFrameArgumentT : public LInstructionHelper<0, 1, 0>
michael@0 5336 {
michael@0 5337 public:
michael@0 5338 LIR_HEADER(SetFrameArgumentT)
michael@0 5339
michael@0 5340 LSetFrameArgumentT(const LAllocation &input) {
michael@0 5341 setOperand(0, input);
michael@0 5342 }
michael@0 5343 MSetFrameArgument *mir() const {
michael@0 5344 return mir_->toSetFrameArgument();
michael@0 5345 }
michael@0 5346 const LAllocation *input() {
michael@0 5347 return getOperand(0);
michael@0 5348 }
michael@0 5349 };
michael@0 5350
michael@0 5351 // Load a value from the actual arguments.
michael@0 5352 class LSetFrameArgumentC : public LInstructionHelper<0, 0, 0>
michael@0 5353 {
michael@0 5354 Value val_;
michael@0 5355
michael@0 5356 public:
michael@0 5357 LIR_HEADER(SetFrameArgumentC)
michael@0 5358
michael@0 5359 LSetFrameArgumentC(const Value &val) {
michael@0 5360 val_ = val;
michael@0 5361 }
michael@0 5362 MSetFrameArgument *mir() const {
michael@0 5363 return mir_->toSetFrameArgument();
michael@0 5364 }
michael@0 5365 const Value &val() const {
michael@0 5366 return val_;
michael@0 5367 }
michael@0 5368 };
michael@0 5369
michael@0 5370 // Load a value from the actual arguments.
michael@0 5371 class LSetFrameArgumentV : public LInstructionHelper<0, BOX_PIECES, 0>
michael@0 5372 {
michael@0 5373 public:
michael@0 5374 LIR_HEADER(SetFrameArgumentV)
michael@0 5375
michael@0 5376 LSetFrameArgumentV() {}
michael@0 5377
michael@0 5378 static const size_t Input = 0;
michael@0 5379
michael@0 5380 MSetFrameArgument *mir() const {
michael@0 5381 return mir_->toSetFrameArgument();
michael@0 5382 }
michael@0 5383 };
michael@0 5384
michael@0 5385 class LRunOncePrologue : public LCallInstructionHelper<0, 0, 0>
michael@0 5386 {
michael@0 5387 public:
michael@0 5388 LIR_HEADER(RunOncePrologue)
michael@0 5389
michael@0 5390 MRunOncePrologue *mir() const {
michael@0 5391 return mir_->toRunOncePrologue();
michael@0 5392 }
michael@0 5393 };
michael@0 5394
michael@0 5395 // Create the rest parameter.
michael@0 5396 class LRest : public LCallInstructionHelper<1, 1, 3>
michael@0 5397 {
michael@0 5398 public:
michael@0 5399 LIR_HEADER(Rest)
michael@0 5400
michael@0 5401 LRest(const LAllocation &numActuals, const LDefinition &temp1, const LDefinition &temp2,
michael@0 5402 const LDefinition &temp3)
michael@0 5403 {
michael@0 5404 setOperand(0, numActuals);
michael@0 5405 setTemp(0, temp1);
michael@0 5406 setTemp(1, temp2);
michael@0 5407 setTemp(2, temp3);
michael@0 5408 }
michael@0 5409 const LAllocation *numActuals() {
michael@0 5410 return getOperand(0);
michael@0 5411 }
michael@0 5412 MRest *mir() const {
michael@0 5413 return mir_->toRest();
michael@0 5414 }
michael@0 5415 };
michael@0 5416
michael@0 5417 class LRestPar : public LCallInstructionHelper<1, 2, 3>
michael@0 5418 {
michael@0 5419 public:
michael@0 5420 LIR_HEADER(RestPar);
michael@0 5421
michael@0 5422 LRestPar(const LAllocation &cx, const LAllocation &numActuals,
michael@0 5423 const LDefinition &temp1, const LDefinition &temp2, const LDefinition &temp3)
michael@0 5424 {
michael@0 5425 setOperand(0, cx);
michael@0 5426 setOperand(1, numActuals);
michael@0 5427 setTemp(0, temp1);
michael@0 5428 setTemp(1, temp2);
michael@0 5429 setTemp(2, temp3);
michael@0 5430 }
michael@0 5431 const LAllocation *forkJoinContext() {
michael@0 5432 return getOperand(0);
michael@0 5433 }
michael@0 5434 const LAllocation *numActuals() {
michael@0 5435 return getOperand(1);
michael@0 5436 }
michael@0 5437 MRestPar *mir() const {
michael@0 5438 return mir_->toRestPar();
michael@0 5439 }
michael@0 5440 };
michael@0 5441
michael@0 5442 class LGuardThreadExclusive : public LCallInstructionHelper<0, 2, 1>
michael@0 5443 {
michael@0 5444 public:
michael@0 5445 LIR_HEADER(GuardThreadExclusive);
michael@0 5446
michael@0 5447 LGuardThreadExclusive(const LAllocation &cx, const LAllocation &object, const LDefinition &temp1) {
michael@0 5448 setOperand(0, cx);
michael@0 5449 setOperand(1, object);
michael@0 5450 setTemp(0, temp1);
michael@0 5451 }
michael@0 5452
michael@0 5453 const LAllocation *forkJoinContext() {
michael@0 5454 return getOperand(0);
michael@0 5455 }
michael@0 5456
michael@0 5457 const LAllocation *object() {
michael@0 5458 return getOperand(1);
michael@0 5459 }
michael@0 5460
michael@0 5461 const LDefinition *getTempReg() {
michael@0 5462 return getTemp(0);
michael@0 5463 }
michael@0 5464 };
michael@0 5465
michael@0 5466 // Guard that a value is in a TypeSet.
michael@0 5467 class LTypeBarrierV : public LInstructionHelper<0, BOX_PIECES, 1>
michael@0 5468 {
michael@0 5469 public:
michael@0 5470 LIR_HEADER(TypeBarrierV)
michael@0 5471
michael@0 5472 LTypeBarrierV(const LDefinition &temp) {
michael@0 5473 setTemp(0, temp);
michael@0 5474 }
michael@0 5475
michael@0 5476 static const size_t Input = 0;
michael@0 5477
michael@0 5478 const MTypeBarrier *mir() const {
michael@0 5479 return mir_->toTypeBarrier();
michael@0 5480 }
michael@0 5481 const LDefinition *temp() {
michael@0 5482 return getTemp(0);
michael@0 5483 }
michael@0 5484 };
michael@0 5485
michael@0 5486 // Guard that a object is in a TypeSet.
michael@0 5487 class LTypeBarrierO : public LInstructionHelper<0, 1, 1>
michael@0 5488 {
michael@0 5489 public:
michael@0 5490 LIR_HEADER(TypeBarrierO)
michael@0 5491
michael@0 5492 LTypeBarrierO(const LAllocation &obj, const LDefinition &temp) {
michael@0 5493 setOperand(0, obj);
michael@0 5494 setTemp(0, temp);
michael@0 5495 }
michael@0 5496 const MTypeBarrier *mir() const {
michael@0 5497 return mir_->toTypeBarrier();
michael@0 5498 }
michael@0 5499 const LAllocation *object() {
michael@0 5500 return getOperand(0);
michael@0 5501 }
michael@0 5502 const LDefinition *temp() {
michael@0 5503 return getTemp(0);
michael@0 5504 }
michael@0 5505 };
michael@0 5506
michael@0 5507 // Guard that a value is in a TypeSet.
michael@0 5508 class LMonitorTypes : public LInstructionHelper<0, BOX_PIECES, 1>
michael@0 5509 {
michael@0 5510 public:
michael@0 5511 LIR_HEADER(MonitorTypes)
michael@0 5512
michael@0 5513 LMonitorTypes(const LDefinition &temp) {
michael@0 5514 setTemp(0, temp);
michael@0 5515 }
michael@0 5516
michael@0 5517 static const size_t Input = 0;
michael@0 5518
michael@0 5519 const MMonitorTypes *mir() const {
michael@0 5520 return mir_->toMonitorTypes();
michael@0 5521 }
michael@0 5522 const LDefinition *temp() {
michael@0 5523 return getTemp(0);
michael@0 5524 }
michael@0 5525 };
michael@0 5526
michael@0 5527 // Generational write barrier used when writing an object to another object.
michael@0 5528 class LPostWriteBarrierO : public LInstructionHelper<0, 2, 1>
michael@0 5529 {
michael@0 5530 public:
michael@0 5531 LIR_HEADER(PostWriteBarrierO)
michael@0 5532
michael@0 5533 LPostWriteBarrierO(const LAllocation &obj, const LAllocation &value,
michael@0 5534 const LDefinition &temp) {
michael@0 5535 setOperand(0, obj);
michael@0 5536 setOperand(1, value);
michael@0 5537 setTemp(0, temp);
michael@0 5538 }
michael@0 5539
michael@0 5540 const MPostWriteBarrier *mir() const {
michael@0 5541 return mir_->toPostWriteBarrier();
michael@0 5542 }
michael@0 5543 const LAllocation *object() {
michael@0 5544 return getOperand(0);
michael@0 5545 }
michael@0 5546 const LAllocation *value() {
michael@0 5547 return getOperand(1);
michael@0 5548 }
michael@0 5549 const LDefinition *temp() {
michael@0 5550 return getTemp(0);
michael@0 5551 }
michael@0 5552 };
michael@0 5553
michael@0 5554 // Generational write barrier used when writing a value to another object.
michael@0 5555 class LPostWriteBarrierV : public LInstructionHelper<0, 1 + BOX_PIECES, 1>
michael@0 5556 {
michael@0 5557 public:
michael@0 5558 LIR_HEADER(PostWriteBarrierV)
michael@0 5559
michael@0 5560 LPostWriteBarrierV(const LAllocation &obj, const LDefinition &temp) {
michael@0 5561 setOperand(0, obj);
michael@0 5562 setTemp(0, temp);
michael@0 5563 }
michael@0 5564
michael@0 5565 static const size_t Input = 1;
michael@0 5566
michael@0 5567 const MPostWriteBarrier *mir() const {
michael@0 5568 return mir_->toPostWriteBarrier();
michael@0 5569 }
michael@0 5570 const LAllocation *object() {
michael@0 5571 return getOperand(0);
michael@0 5572 }
michael@0 5573 const LDefinition *temp() {
michael@0 5574 return getTemp(0);
michael@0 5575 }
michael@0 5576 };
michael@0 5577
michael@0 5578 // Guard against an object's identity.
michael@0 5579 class LGuardObjectIdentity : public LInstructionHelper<0, 1, 0>
michael@0 5580 {
michael@0 5581 public:
michael@0 5582 LIR_HEADER(GuardObjectIdentity)
michael@0 5583
michael@0 5584 LGuardObjectIdentity(const LAllocation &in) {
michael@0 5585 setOperand(0, in);
michael@0 5586 }
michael@0 5587 const MGuardObjectIdentity *mir() const {
michael@0 5588 return mir_->toGuardObjectIdentity();
michael@0 5589 }
michael@0 5590 };
michael@0 5591
michael@0 5592 // Guard against an object's class.
michael@0 5593 class LGuardClass : public LInstructionHelper<0, 1, 1>
michael@0 5594 {
michael@0 5595 public:
michael@0 5596 LIR_HEADER(GuardClass)
michael@0 5597
michael@0 5598 LGuardClass(const LAllocation &in, const LDefinition &temp) {
michael@0 5599 setOperand(0, in);
michael@0 5600 setTemp(0, temp);
michael@0 5601 }
michael@0 5602 const MGuardClass *mir() const {
michael@0 5603 return mir_->toGuardClass();
michael@0 5604 }
michael@0 5605 const LDefinition *tempInt() {
michael@0 5606 return getTemp(0);
michael@0 5607 }
michael@0 5608 };
michael@0 5609
michael@0 5610 class MPhi;
michael@0 5611
michael@0 5612 // Phi is a pseudo-instruction that emits no code, and is an annotation for the
michael@0 5613 // register allocator. Like its equivalent in MIR, phis are collected at the
michael@0 5614 // top of blocks and are meant to be executed in parallel, choosing the input
michael@0 5615 // corresponding to the predecessor taken in the control flow graph.
michael@0 5616 class LPhi MOZ_FINAL : public LInstruction
michael@0 5617 {
michael@0 5618 LAllocation *inputs_;
michael@0 5619 LDefinition def_;
michael@0 5620
michael@0 5621 LPhi()
michael@0 5622 { }
michael@0 5623
michael@0 5624 public:
michael@0 5625 LIR_HEADER(Phi)
michael@0 5626
michael@0 5627 static LPhi *New(MIRGenerator *gen, MPhi *phi);
michael@0 5628
michael@0 5629 size_t numDefs() const {
michael@0 5630 return 1;
michael@0 5631 }
michael@0 5632 LDefinition *getDef(size_t index) {
michael@0 5633 JS_ASSERT(index == 0);
michael@0 5634 return &def_;
michael@0 5635 }
michael@0 5636 void setDef(size_t index, const LDefinition &def) {
michael@0 5637 JS_ASSERT(index == 0);
michael@0 5638 def_ = def;
michael@0 5639 }
michael@0 5640 size_t numOperands() const {
michael@0 5641 return mir_->toPhi()->numOperands();
michael@0 5642 }
michael@0 5643 LAllocation *getOperand(size_t index) {
michael@0 5644 JS_ASSERT(index < numOperands());
michael@0 5645 return &inputs_[index];
michael@0 5646 }
michael@0 5647 void setOperand(size_t index, const LAllocation &a) {
michael@0 5648 JS_ASSERT(index < numOperands());
michael@0 5649 inputs_[index] = a;
michael@0 5650 }
michael@0 5651 size_t numTemps() const {
michael@0 5652 return 0;
michael@0 5653 }
michael@0 5654 LDefinition *getTemp(size_t index) {
michael@0 5655 MOZ_ASSUME_UNREACHABLE("no temps");
michael@0 5656 }
michael@0 5657 void setTemp(size_t index, const LDefinition &temp) {
michael@0 5658 MOZ_ASSUME_UNREACHABLE("no temps");
michael@0 5659 }
michael@0 5660 size_t numSuccessors() const {
michael@0 5661 return 0;
michael@0 5662 }
michael@0 5663 MBasicBlock *getSuccessor(size_t i) const {
michael@0 5664 MOZ_ASSUME_UNREACHABLE("no successors");
michael@0 5665 }
michael@0 5666 void setSuccessor(size_t i, MBasicBlock *) {
michael@0 5667 MOZ_ASSUME_UNREACHABLE("no successors");
michael@0 5668 }
michael@0 5669
michael@0 5670 virtual void printInfo(FILE *fp) {
michael@0 5671 printOperands(fp);
michael@0 5672 }
michael@0 5673 };
michael@0 5674
michael@0 5675 class LIn : public LCallInstructionHelper<1, BOX_PIECES+1, 0>
michael@0 5676 {
michael@0 5677 public:
michael@0 5678 LIR_HEADER(In)
michael@0 5679 LIn(const LAllocation &rhs) {
michael@0 5680 setOperand(RHS, rhs);
michael@0 5681 }
michael@0 5682
michael@0 5683 const LAllocation *lhs() {
michael@0 5684 return getOperand(LHS);
michael@0 5685 }
michael@0 5686 const LAllocation *rhs() {
michael@0 5687 return getOperand(RHS);
michael@0 5688 }
michael@0 5689
michael@0 5690 static const size_t LHS = 0;
michael@0 5691 static const size_t RHS = BOX_PIECES;
michael@0 5692 };
michael@0 5693
michael@0 5694 class LInstanceOfO : public LInstructionHelper<1, 1, 0>
michael@0 5695 {
michael@0 5696 public:
michael@0 5697 LIR_HEADER(InstanceOfO)
michael@0 5698 LInstanceOfO(const LAllocation &lhs) {
michael@0 5699 setOperand(0, lhs);
michael@0 5700 }
michael@0 5701
michael@0 5702 MInstanceOf *mir() const {
michael@0 5703 return mir_->toInstanceOf();
michael@0 5704 }
michael@0 5705
michael@0 5706 const LAllocation *lhs() {
michael@0 5707 return getOperand(0);
michael@0 5708 }
michael@0 5709 };
michael@0 5710
michael@0 5711 class LInstanceOfV : public LInstructionHelper<1, BOX_PIECES, 0>
michael@0 5712 {
michael@0 5713 public:
michael@0 5714 LIR_HEADER(InstanceOfV)
michael@0 5715 LInstanceOfV() {
michael@0 5716 }
michael@0 5717
michael@0 5718 MInstanceOf *mir() const {
michael@0 5719 return mir_->toInstanceOf();
michael@0 5720 }
michael@0 5721
michael@0 5722 const LAllocation *lhs() {
michael@0 5723 return getOperand(LHS);
michael@0 5724 }
michael@0 5725
michael@0 5726 static const size_t LHS = 0;
michael@0 5727 };
michael@0 5728
michael@0 5729 class LCallInstanceOf : public LCallInstructionHelper<1, BOX_PIECES+1, 0>
michael@0 5730 {
michael@0 5731 public:
michael@0 5732 LIR_HEADER(CallInstanceOf)
michael@0 5733 LCallInstanceOf(const LAllocation &rhs) {
michael@0 5734 setOperand(RHS, rhs);
michael@0 5735 }
michael@0 5736
michael@0 5737 const LDefinition *output() {
michael@0 5738 return this->getDef(0);
michael@0 5739 }
michael@0 5740 const LAllocation *lhs() {
michael@0 5741 return getOperand(LHS);
michael@0 5742 }
michael@0 5743 const LAllocation *rhs() {
michael@0 5744 return getOperand(RHS);
michael@0 5745 }
michael@0 5746
michael@0 5747 static const size_t LHS = 0;
michael@0 5748 static const size_t RHS = BOX_PIECES;
michael@0 5749 };
michael@0 5750
michael@0 5751 class LProfilerStackOp : public LInstructionHelper<0, 0, 1>
michael@0 5752 {
michael@0 5753 public:
michael@0 5754 LIR_HEADER(ProfilerStackOp)
michael@0 5755
michael@0 5756 LProfilerStackOp(const LDefinition &temp) {
michael@0 5757 setTemp(0, temp);
michael@0 5758 }
michael@0 5759
michael@0 5760 const LDefinition *temp() {
michael@0 5761 return getTemp(0);
michael@0 5762 }
michael@0 5763
michael@0 5764 JSScript *script() {
michael@0 5765 return mir_->toProfilerStackOp()->script();
michael@0 5766 }
michael@0 5767
michael@0 5768 MProfilerStackOp::Type type() {
michael@0 5769 return mir_->toProfilerStackOp()->type();
michael@0 5770 }
michael@0 5771
michael@0 5772 unsigned inlineLevel() {
michael@0 5773 return mir_->toProfilerStackOp()->inlineLevel();
michael@0 5774 }
michael@0 5775 };
michael@0 5776
michael@0 5777 class LIsCallable : public LInstructionHelper<1, 1, 0>
michael@0 5778 {
michael@0 5779 public:
michael@0 5780 LIR_HEADER(IsCallable);
michael@0 5781 LIsCallable(const LAllocation &object) {
michael@0 5782 setOperand(0, object);
michael@0 5783 }
michael@0 5784
michael@0 5785 const LAllocation *object() {
michael@0 5786 return getOperand(0);
michael@0 5787 }
michael@0 5788 MIsCallable *mir() const {
michael@0 5789 return mir_->toIsCallable();
michael@0 5790 }
michael@0 5791 };
michael@0 5792
michael@0 5793 class LHaveSameClass : public LInstructionHelper<1, 2, 1>
michael@0 5794 {
michael@0 5795 public:
michael@0 5796 LIR_HEADER(HaveSameClass);
michael@0 5797 LHaveSameClass(const LAllocation &left, const LAllocation &right,
michael@0 5798 const LDefinition &temp) {
michael@0 5799 setOperand(0, left);
michael@0 5800 setOperand(1, right);
michael@0 5801 setTemp(0, temp);
michael@0 5802 }
michael@0 5803
michael@0 5804 const LAllocation *lhs() {
michael@0 5805 return getOperand(0);
michael@0 5806 }
michael@0 5807 const LAllocation *rhs() {
michael@0 5808 return getOperand(1);
michael@0 5809 }
michael@0 5810 MHaveSameClass *mir() const {
michael@0 5811 return mir_->toHaveSameClass();
michael@0 5812 }
michael@0 5813 };
michael@0 5814
michael@0 5815 class LHasClass : public LInstructionHelper<1, 1, 0>
michael@0 5816 {
michael@0 5817 public:
michael@0 5818 LIR_HEADER(HasClass);
michael@0 5819 LHasClass(const LAllocation &lhs) {
michael@0 5820 setOperand(0, lhs);
michael@0 5821 }
michael@0 5822
michael@0 5823 const LAllocation *lhs() {
michael@0 5824 return getOperand(0);
michael@0 5825 }
michael@0 5826 MHasClass *mir() const {
michael@0 5827 return mir_->toHasClass();
michael@0 5828 }
michael@0 5829 };
michael@0 5830
michael@0 5831 class LAsmJSLoadHeap : public LInstructionHelper<1, 1, 0>
michael@0 5832 {
michael@0 5833 public:
michael@0 5834 LIR_HEADER(AsmJSLoadHeap);
michael@0 5835 LAsmJSLoadHeap(const LAllocation &ptr) {
michael@0 5836 setOperand(0, ptr);
michael@0 5837 }
michael@0 5838 MAsmJSLoadHeap *mir() const {
michael@0 5839 return mir_->toAsmJSLoadHeap();
michael@0 5840 }
michael@0 5841 const LAllocation *ptr() {
michael@0 5842 return getOperand(0);
michael@0 5843 }
michael@0 5844 };
michael@0 5845
michael@0 5846 class LAsmJSStoreHeap : public LInstructionHelper<0, 2, 0>
michael@0 5847 {
michael@0 5848 public:
michael@0 5849 LIR_HEADER(AsmJSStoreHeap);
michael@0 5850 LAsmJSStoreHeap(const LAllocation &ptr, const LAllocation &value) {
michael@0 5851 setOperand(0, ptr);
michael@0 5852 setOperand(1, value);
michael@0 5853 }
michael@0 5854 MAsmJSStoreHeap *mir() const {
michael@0 5855 return mir_->toAsmJSStoreHeap();
michael@0 5856 }
michael@0 5857 const LAllocation *ptr() {
michael@0 5858 return getOperand(0);
michael@0 5859 }
michael@0 5860 const LAllocation *value() {
michael@0 5861 return getOperand(1);
michael@0 5862 }
michael@0 5863 };
michael@0 5864
michael@0 5865 class LAsmJSLoadGlobalVar : public LInstructionHelper<1, 0, 0>
michael@0 5866 {
michael@0 5867 public:
michael@0 5868 LIR_HEADER(AsmJSLoadGlobalVar);
michael@0 5869 MAsmJSLoadGlobalVar *mir() const {
michael@0 5870 return mir_->toAsmJSLoadGlobalVar();
michael@0 5871 }
michael@0 5872 };
michael@0 5873
michael@0 5874 class LAsmJSStoreGlobalVar : public LInstructionHelper<0, 1, 0>
michael@0 5875 {
michael@0 5876 public:
michael@0 5877 LIR_HEADER(AsmJSStoreGlobalVar);
michael@0 5878 LAsmJSStoreGlobalVar(const LAllocation &value) {
michael@0 5879 setOperand(0, value);
michael@0 5880 }
michael@0 5881 MAsmJSStoreGlobalVar *mir() const {
michael@0 5882 return mir_->toAsmJSStoreGlobalVar();
michael@0 5883 }
michael@0 5884 const LAllocation *value() {
michael@0 5885 return getOperand(0);
michael@0 5886 }
michael@0 5887 };
michael@0 5888
michael@0 5889 class LAsmJSLoadFFIFunc : public LInstructionHelper<1, 0, 0>
michael@0 5890 {
michael@0 5891 public:
michael@0 5892 LIR_HEADER(AsmJSLoadFFIFunc);
michael@0 5893 MAsmJSLoadFFIFunc *mir() const {
michael@0 5894 return mir_->toAsmJSLoadFFIFunc();
michael@0 5895 }
michael@0 5896 };
michael@0 5897
michael@0 5898 class LAsmJSParameter : public LInstructionHelper<1, 0, 0>
michael@0 5899 {
michael@0 5900 public:
michael@0 5901 LIR_HEADER(AsmJSParameter);
michael@0 5902 };
michael@0 5903
michael@0 5904 class LAsmJSReturn : public LInstructionHelper<0, 1, 0>
michael@0 5905 {
michael@0 5906 public:
michael@0 5907 LIR_HEADER(AsmJSReturn);
michael@0 5908 };
michael@0 5909
michael@0 5910 class LAsmJSVoidReturn : public LInstructionHelper<0, 0, 0>
michael@0 5911 {
michael@0 5912 public:
michael@0 5913 LIR_HEADER(AsmJSVoidReturn);
michael@0 5914 };
michael@0 5915
michael@0 5916 class LAsmJSPassStackArg : public LInstructionHelper<0, 1, 0>
michael@0 5917 {
michael@0 5918 public:
michael@0 5919 LIR_HEADER(AsmJSPassStackArg);
michael@0 5920 LAsmJSPassStackArg(const LAllocation &arg) {
michael@0 5921 setOperand(0, arg);
michael@0 5922 }
michael@0 5923 MAsmJSPassStackArg *mir() const {
michael@0 5924 return mirRaw()->toAsmJSPassStackArg();
michael@0 5925 }
michael@0 5926 const LAllocation *arg() {
michael@0 5927 return getOperand(0);
michael@0 5928 }
michael@0 5929 };
michael@0 5930
michael@0 5931 class LAsmJSCall MOZ_FINAL : public LInstruction
michael@0 5932 {
michael@0 5933 LAllocation *operands_;
michael@0 5934 uint32_t numOperands_;
michael@0 5935 LDefinition def_;
michael@0 5936
michael@0 5937 public:
michael@0 5938 LIR_HEADER(AsmJSCall);
michael@0 5939
michael@0 5940 LAsmJSCall(LAllocation *operands, uint32_t numOperands)
michael@0 5941 : operands_(operands),
michael@0 5942 numOperands_(numOperands),
michael@0 5943 def_(LDefinition::BogusTemp())
michael@0 5944 {}
michael@0 5945
michael@0 5946 MAsmJSCall *mir() const {
michael@0 5947 return mir_->toAsmJSCall();
michael@0 5948 }
michael@0 5949
michael@0 5950 bool isCall() const {
michael@0 5951 return true;
michael@0 5952 }
michael@0 5953
michael@0 5954 // LInstruction interface
michael@0 5955 size_t numDefs() const {
michael@0 5956 return def_.isBogusTemp() ? 0 : 1;
michael@0 5957 }
michael@0 5958 LDefinition *getDef(size_t index) {
michael@0 5959 JS_ASSERT(numDefs() == 1);
michael@0 5960 JS_ASSERT(index == 0);
michael@0 5961 return &def_;
michael@0 5962 }
michael@0 5963 void setDef(size_t index, const LDefinition &def) {
michael@0 5964 JS_ASSERT(index == 0);
michael@0 5965 def_ = def;
michael@0 5966 }
michael@0 5967 size_t numOperands() const {
michael@0 5968 return numOperands_;
michael@0 5969 }
michael@0 5970 LAllocation *getOperand(size_t index) {
michael@0 5971 JS_ASSERT(index < numOperands_);
michael@0 5972 return &operands_[index];
michael@0 5973 }
michael@0 5974 void setOperand(size_t index, const LAllocation &a) {
michael@0 5975 JS_ASSERT(index < numOperands_);
michael@0 5976 operands_[index] = a;
michael@0 5977 }
michael@0 5978 size_t numTemps() const {
michael@0 5979 return 0;
michael@0 5980 }
michael@0 5981 LDefinition *getTemp(size_t index) {
michael@0 5982 MOZ_ASSUME_UNREACHABLE("no temps");
michael@0 5983 }
michael@0 5984 void setTemp(size_t index, const LDefinition &a) {
michael@0 5985 MOZ_ASSUME_UNREACHABLE("no temps");
michael@0 5986 }
michael@0 5987 size_t numSuccessors() const {
michael@0 5988 return 0;
michael@0 5989 }
michael@0 5990 MBasicBlock *getSuccessor(size_t i) const {
michael@0 5991 MOZ_ASSUME_UNREACHABLE("no successors");
michael@0 5992 }
michael@0 5993 void setSuccessor(size_t i, MBasicBlock *) {
michael@0 5994 MOZ_ASSUME_UNREACHABLE("no successors");
michael@0 5995 }
michael@0 5996 };
michael@0 5997
michael@0 5998 class LAssertRangeI : public LInstructionHelper<0, 1, 0>
michael@0 5999 {
michael@0 6000 public:
michael@0 6001 LIR_HEADER(AssertRangeI)
michael@0 6002
michael@0 6003 LAssertRangeI(const LAllocation &input) {
michael@0 6004 setOperand(0, input);
michael@0 6005 }
michael@0 6006
michael@0 6007 const LAllocation *input() {
michael@0 6008 return getOperand(0);
michael@0 6009 }
michael@0 6010
michael@0 6011 MAssertRange *mir() {
michael@0 6012 return mir_->toAssertRange();
michael@0 6013 }
michael@0 6014 const Range *range() {
michael@0 6015 return mir()->assertedRange();
michael@0 6016 }
michael@0 6017 };
michael@0 6018
michael@0 6019 class LAssertRangeD : public LInstructionHelper<0, 1, 1>
michael@0 6020 {
michael@0 6021 public:
michael@0 6022 LIR_HEADER(AssertRangeD)
michael@0 6023
michael@0 6024 LAssertRangeD(const LAllocation &input, const LDefinition &temp) {
michael@0 6025 setOperand(0, input);
michael@0 6026 setTemp(0, temp);
michael@0 6027 }
michael@0 6028
michael@0 6029 const LAllocation *input() {
michael@0 6030 return getOperand(0);
michael@0 6031 }
michael@0 6032
michael@0 6033 const LDefinition *temp() {
michael@0 6034 return getTemp(0);
michael@0 6035 }
michael@0 6036
michael@0 6037 MAssertRange *mir() {
michael@0 6038 return mir_->toAssertRange();
michael@0 6039 }
michael@0 6040 const Range *range() {
michael@0 6041 return mir()->assertedRange();
michael@0 6042 }
michael@0 6043 };
michael@0 6044
michael@0 6045 class LAssertRangeF : public LInstructionHelper<0, 1, 1>
michael@0 6046 {
michael@0 6047 public:
michael@0 6048 LIR_HEADER(AssertRangeF)
michael@0 6049
michael@0 6050 LAssertRangeF(const LAllocation &input, const LDefinition &temp) {
michael@0 6051 setOperand(0, input);
michael@0 6052 setTemp(0, temp);
michael@0 6053 }
michael@0 6054
michael@0 6055 const LAllocation *input() {
michael@0 6056 return getOperand(0);
michael@0 6057 }
michael@0 6058
michael@0 6059 const LDefinition *temp() {
michael@0 6060 return getTemp(0);
michael@0 6061 }
michael@0 6062
michael@0 6063 MAssertRange *mir() {
michael@0 6064 return mir_->toAssertRange();
michael@0 6065 }
michael@0 6066 const Range *range() {
michael@0 6067 return mir()->assertedRange();
michael@0 6068 }
michael@0 6069 };
michael@0 6070
michael@0 6071 class LAssertRangeV : public LInstructionHelper<0, BOX_PIECES, 3>
michael@0 6072 {
michael@0 6073 public:
michael@0 6074 LIR_HEADER(AssertRangeV)
michael@0 6075
michael@0 6076 LAssertRangeV(const LDefinition &temp, const LDefinition &floatTemp1,
michael@0 6077 const LDefinition &floatTemp2)
michael@0 6078 {
michael@0 6079 setTemp(0, temp);
michael@0 6080 setTemp(1, floatTemp1);
michael@0 6081 setTemp(2, floatTemp2);
michael@0 6082 }
michael@0 6083
michael@0 6084 static const size_t Input = 0;
michael@0 6085
michael@0 6086 const LDefinition *temp() {
michael@0 6087 return getTemp(0);
michael@0 6088 }
michael@0 6089 const LDefinition *floatTemp1() {
michael@0 6090 return getTemp(1);
michael@0 6091 }
michael@0 6092 const LDefinition *floatTemp2() {
michael@0 6093 return getTemp(2);
michael@0 6094 }
michael@0 6095
michael@0 6096 MAssertRange *mir() {
michael@0 6097 return mir_->toAssertRange();
michael@0 6098 }
michael@0 6099 const Range *range() {
michael@0 6100 return mir()->assertedRange();
michael@0 6101 }
michael@0 6102 };
michael@0 6103
michael@0 6104 class LRecompileCheck : public LInstructionHelper<0, 0, 1>
michael@0 6105 {
michael@0 6106 public:
michael@0 6107 LIR_HEADER(RecompileCheck)
michael@0 6108
michael@0 6109 LRecompileCheck(const LDefinition &scratch) {
michael@0 6110 setTemp(0, scratch);
michael@0 6111 }
michael@0 6112
michael@0 6113 const LDefinition *scratch() {
michael@0 6114 return getTemp(0);
michael@0 6115 }
michael@0 6116 MRecompileCheck *mir() {
michael@0 6117 return mir_->toRecompileCheck();
michael@0 6118 }
michael@0 6119 };
michael@0 6120
michael@0 6121 } // namespace jit
michael@0 6122 } // namespace js
michael@0 6123
michael@0 6124 #endif /* jit_LIR_Common_h */

mercurial