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