1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef jit_shared_LIR_shared_h
8 #define jit_shared_LIR_shared_h
9
10 #include "jit/AtomicOp.h"
11 #include "jit/shared/Assembler-shared.h"
12 #include "util/Memory.h"
13
14 // This file declares LIR instructions that are common to every platform.
15
16 namespace js {
17 namespace jit {
18
19 class LBox : public LInstructionHelper<BOX_PIECES, 1, 0> {
20 MIRType type_;
21
22 public:
23 LIR_HEADER(Box);
24
LBox(const LAllocation & payload,MIRType type)25 LBox(const LAllocation& payload, MIRType type)
26 : LInstructionHelper(classOpcode), type_(type) {
27 setOperand(0, payload);
28 }
29
type()30 MIRType type() const { return type_; }
extraName()31 const char* extraName() const { return StringFromMIRType(type_); }
32 };
33
34 template <size_t Temps, size_t ExtraUses = 0>
35 class LBinaryMath : public LInstructionHelper<1, 2 + ExtraUses, Temps> {
36 protected:
LBinaryMath(LNode::Opcode opcode)37 explicit LBinaryMath(LNode::Opcode opcode)
38 : LInstructionHelper<1, 2 + ExtraUses, Temps>(opcode) {}
39
40 public:
lhs()41 const LAllocation* lhs() { return this->getOperand(0); }
rhs()42 const LAllocation* rhs() { return this->getOperand(1); }
43 };
44
45 template <size_t Temps, size_t ExtraUses = 0>
46 class LUnaryMath : public LInstructionHelper<1, 1 + ExtraUses, Temps> {
47 protected:
LUnaryMath(LNode::Opcode opcode)48 explicit LUnaryMath(LNode::Opcode opcode)
49 : LInstructionHelper<1, 1 + ExtraUses, Temps>(opcode) {}
50
51 public:
input()52 const LAllocation* input() { return this->getOperand(0); }
53 };
54
55 // An LOsiPoint captures a snapshot after a call and ensures enough space to
56 // patch in a call to the invalidation mechanism.
57 //
58 // Note: LSafepoints are 1:1 with LOsiPoints, so it holds a reference to the
59 // corresponding LSafepoint to inform it of the LOsiPoint's masm offset when it
60 // gets GC'd.
61 class LOsiPoint : public LInstructionHelper<0, 0, 0> {
62 LSafepoint* safepoint_;
63
64 public:
LOsiPoint(LSafepoint * safepoint,LSnapshot * snapshot)65 LOsiPoint(LSafepoint* safepoint, LSnapshot* snapshot)
66 : LInstructionHelper(classOpcode), safepoint_(safepoint) {
67 MOZ_ASSERT(safepoint && snapshot);
68 assignSnapshot(snapshot);
69 }
70
associatedSafepoint()71 LSafepoint* associatedSafepoint() { return safepoint_; }
72
73 LIR_HEADER(OsiPoint)
74 };
75
76 class LMove {
77 LAllocation from_;
78 LAllocation to_;
79 LDefinition::Type type_;
80
81 public:
LMove(LAllocation from,LAllocation to,LDefinition::Type type)82 LMove(LAllocation from, LAllocation to, LDefinition::Type type)
83 : from_(from), to_(to), type_(type) {}
84
from()85 LAllocation from() const { return from_; }
to()86 LAllocation to() const { return to_; }
type()87 LDefinition::Type type() const { return type_; }
88 };
89
90 class LMoveGroup : public LInstructionHelper<0, 0, 0> {
91 js::Vector<LMove, 2, JitAllocPolicy> moves_;
92
93 #ifdef JS_CODEGEN_X86
94 // Optional general register available for use when executing moves.
95 LAllocation scratchRegister_;
96 #endif
97
LMoveGroup(TempAllocator & alloc)98 explicit LMoveGroup(TempAllocator& alloc)
99 : LInstructionHelper(classOpcode), moves_(alloc) {}
100
101 public:
LIR_HEADER(MoveGroup)102 LIR_HEADER(MoveGroup)
103
104 static LMoveGroup* New(TempAllocator& alloc) {
105 return new (alloc) LMoveGroup(alloc);
106 }
107
108 void printOperands(GenericPrinter& out);
109
110 // Add a move which takes place simultaneously with all others in the group.
111 bool add(LAllocation from, LAllocation to, LDefinition::Type type);
112
113 // Add a move which takes place after existing moves in the group.
114 bool addAfter(LAllocation from, LAllocation to, LDefinition::Type type);
115
numMoves()116 size_t numMoves() const { return moves_.length(); }
getMove(size_t i)117 const LMove& getMove(size_t i) const { return moves_[i]; }
118
119 #ifdef JS_CODEGEN_X86
setScratchRegister(Register reg)120 void setScratchRegister(Register reg) { scratchRegister_ = LGeneralReg(reg); }
maybeScratchRegister()121 LAllocation maybeScratchRegister() { return scratchRegister_; }
122 #endif
123
uses(Register reg)124 bool uses(Register reg) {
125 for (size_t i = 0; i < numMoves(); i++) {
126 LMove move = getMove(i);
127 if (move.from() == LGeneralReg(reg) || move.to() == LGeneralReg(reg)) {
128 return true;
129 }
130 }
131 return false;
132 }
133 };
134
135 // Constant 32-bit integer.
136 class LInteger : public LInstructionHelper<1, 0, 0> {
137 int32_t i32_;
138
139 public:
LIR_HEADER(Integer)140 LIR_HEADER(Integer)
141
142 explicit LInteger(int32_t i32) : LInstructionHelper(classOpcode), i32_(i32) {}
143
getValue()144 int32_t getValue() const { return i32_; }
145 };
146
147 // Constant 64-bit integer.
148 class LInteger64 : public LInstructionHelper<INT64_PIECES, 0, 0> {
149 int64_t i64_;
150
151 public:
LIR_HEADER(Integer64)152 LIR_HEADER(Integer64)
153
154 explicit LInteger64(int64_t i64)
155 : LInstructionHelper(classOpcode), i64_(i64) {}
156
getValue()157 int64_t getValue() const { return i64_; }
158 };
159
160 // Constant pointer.
161 class LPointer : public LInstructionHelper<1, 0, 0> {
162 gc::Cell* ptr_;
163
164 public:
LIR_HEADER(Pointer)165 LIR_HEADER(Pointer)
166
167 explicit LPointer(gc::Cell* ptr)
168 : LInstructionHelper(classOpcode), ptr_(ptr) {}
169
gcptr()170 gc::Cell* gcptr() const { return ptr_; }
171 };
172
173 // Constant double.
174 class LDouble : public LInstructionHelper<1, 0, 0> {
175 double d_;
176
177 public:
178 LIR_HEADER(Double);
179
LDouble(double d)180 explicit LDouble(double d) : LInstructionHelper(classOpcode), d_(d) {}
181
getDouble()182 const double& getDouble() const { return d_; }
183 };
184
185 // Constant float32.
186 class LFloat32 : public LInstructionHelper<1, 0, 0> {
187 float f_;
188
189 public:
190 LIR_HEADER(Float32);
191
LFloat32(float f)192 explicit LFloat32(float f) : LInstructionHelper(classOpcode), f_(f) {}
193
getFloat()194 const float& getFloat() const { return f_; }
195 };
196
197 // A constant Value.
198 class LValue : public LInstructionHelper<BOX_PIECES, 0, 0> {
199 Value v_;
200
201 public:
LIR_HEADER(Value)202 LIR_HEADER(Value)
203
204 explicit LValue(const Value& v) : LInstructionHelper(classOpcode), v_(v) {}
205
value()206 Value value() const { return v_; }
207 };
208
209 class LNurseryObject : public LInstructionHelper<1, 0, 0> {
210 public:
211 LIR_HEADER(NurseryObject);
212
LNurseryObject()213 LNurseryObject() : LInstructionHelper(classOpcode) {}
214
mir()215 MNurseryObject* mir() const { return mir_->toNurseryObject(); }
216 };
217
218 // Formal argument for a function, returning a box. Formal arguments are
219 // initially read from the stack.
220 class LParameter : public LInstructionHelper<BOX_PIECES, 0, 0> {
221 public:
LIR_HEADER(Parameter)222 LIR_HEADER(Parameter)
223
224 LParameter() : LInstructionHelper(classOpcode) {}
225 };
226
227 // Stack offset for a word-sized immutable input value to a frame.
228 class LCallee : public LInstructionHelper<1, 0, 0> {
229 public:
LIR_HEADER(Callee)230 LIR_HEADER(Callee)
231
232 LCallee() : LInstructionHelper(classOpcode) {}
233 };
234
235 class LIsConstructing : public LInstructionHelper<1, 0, 0> {
236 public:
LIR_HEADER(IsConstructing)237 LIR_HEADER(IsConstructing)
238
239 LIsConstructing() : LInstructionHelper(classOpcode) {}
240 };
241
242 // Base class for control instructions (goto, branch, etc.)
243 template <size_t Succs, size_t Operands, size_t Temps>
244 class LControlInstructionHelper
245 : public LInstructionHelper<0, Operands, Temps> {
246 mozilla::Array<MBasicBlock*, Succs> successors_;
247
248 protected:
LControlInstructionHelper(LNode::Opcode opcode)249 explicit LControlInstructionHelper(LNode::Opcode opcode)
250 : LInstructionHelper<0, Operands, Temps>(opcode) {}
251
252 public:
numSuccessors()253 size_t numSuccessors() const { return Succs; }
getSuccessor(size_t i)254 MBasicBlock* getSuccessor(size_t i) const { return successors_[i]; }
255
setSuccessor(size_t i,MBasicBlock * successor)256 void setSuccessor(size_t i, MBasicBlock* successor) {
257 successors_[i] = successor;
258 }
259 };
260
261 // Jumps to the start of a basic block.
262 class LGoto : public LControlInstructionHelper<1, 0, 0> {
263 public:
LIR_HEADER(Goto)264 LIR_HEADER(Goto)
265
266 explicit LGoto(MBasicBlock* block) : LControlInstructionHelper(classOpcode) {
267 setSuccessor(0, block);
268 }
269
target()270 MBasicBlock* target() const { return getSuccessor(0); }
271 };
272
273 class LNewArray : public LInstructionHelper<1, 0, 1> {
274 public:
LIR_HEADER(NewArray)275 LIR_HEADER(NewArray)
276
277 explicit LNewArray(const LDefinition& temp)
278 : LInstructionHelper(classOpcode) {
279 setTemp(0, temp);
280 }
281
extraName()282 const char* extraName() const {
283 return mir()->isVMCall() ? "VMCall" : nullptr;
284 }
285
temp()286 const LDefinition* temp() { return getTemp(0); }
287
mir()288 MNewArray* mir() const { return mir_->toNewArray(); }
289 };
290
291 class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1> {
292 public:
LIR_HEADER(NewArrayDynamicLength)293 LIR_HEADER(NewArrayDynamicLength)
294
295 explicit LNewArrayDynamicLength(const LAllocation& length,
296 const LDefinition& temp)
297 : LInstructionHelper(classOpcode) {
298 setOperand(0, length);
299 setTemp(0, temp);
300 }
301
length()302 const LAllocation* length() { return getOperand(0); }
temp()303 const LDefinition* temp() { return getTemp(0); }
304
mir()305 MNewArrayDynamicLength* mir() const {
306 return mir_->toNewArrayDynamicLength();
307 }
308 };
309
310 class LNewIterator : public LInstructionHelper<1, 0, 1> {
311 public:
LIR_HEADER(NewIterator)312 LIR_HEADER(NewIterator)
313
314 explicit LNewIterator(const LDefinition& temp)
315 : LInstructionHelper(classOpcode) {
316 setTemp(0, temp);
317 }
318
temp()319 const LDefinition* temp() { return getTemp(0); }
320
mir()321 MNewIterator* mir() const { return mir_->toNewIterator(); }
322 };
323
324 class LNewTypedArray : public LInstructionHelper<1, 0, 2> {
325 public:
LIR_HEADER(NewTypedArray)326 LIR_HEADER(NewTypedArray)
327
328 LNewTypedArray(const LDefinition& temp1, const LDefinition& temp2)
329 : LInstructionHelper(classOpcode) {
330 setTemp(0, temp1);
331 setTemp(1, temp2);
332 }
333
temp1()334 const LDefinition* temp1() { return getTemp(0); }
335
temp2()336 const LDefinition* temp2() { return getTemp(1); }
337
mir()338 MNewTypedArray* mir() const { return mir_->toNewTypedArray(); }
339 };
340
341 class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1> {
342 public:
LIR_HEADER(NewTypedArrayDynamicLength)343 LIR_HEADER(NewTypedArrayDynamicLength)
344
345 LNewTypedArrayDynamicLength(const LAllocation& length,
346 const LDefinition& temp)
347 : LInstructionHelper(classOpcode) {
348 setOperand(0, length);
349 setTemp(0, temp);
350 }
351
length()352 const LAllocation* length() { return getOperand(0); }
temp()353 const LDefinition* temp() { return getTemp(0); }
354
mir()355 MNewTypedArrayDynamicLength* mir() const {
356 return mir_->toNewTypedArrayDynamicLength();
357 }
358 };
359
360 class LNewTypedArrayFromArray : public LCallInstructionHelper<1, 1, 0> {
361 public:
LIR_HEADER(NewTypedArrayFromArray)362 LIR_HEADER(NewTypedArrayFromArray)
363
364 explicit LNewTypedArrayFromArray(const LAllocation& array)
365 : LCallInstructionHelper(classOpcode) {
366 setOperand(0, array);
367 }
368
array()369 const LAllocation* array() { return getOperand(0); }
370
mir()371 MNewTypedArrayFromArray* mir() const {
372 return mir_->toNewTypedArrayFromArray();
373 }
374 };
375
376 class LNewTypedArrayFromArrayBuffer
377 : public LCallInstructionHelper<1, 1 + 2 * BOX_PIECES, 0> {
378 public:
LIR_HEADER(NewTypedArrayFromArrayBuffer)379 LIR_HEADER(NewTypedArrayFromArrayBuffer)
380
381 LNewTypedArrayFromArrayBuffer(const LAllocation& arrayBuffer,
382 const LBoxAllocation& byteOffset,
383 const LBoxAllocation& length)
384 : LCallInstructionHelper(classOpcode) {
385 setOperand(0, arrayBuffer);
386 setBoxOperand(ByteOffsetIndex, byteOffset);
387 setBoxOperand(LengthIndex, length);
388 }
389
390 static const size_t ByteOffsetIndex = 1;
391 static const size_t LengthIndex = 1 + BOX_PIECES;
392
arrayBuffer()393 const LAllocation* arrayBuffer() { return getOperand(0); }
394
mir()395 MNewTypedArrayFromArrayBuffer* mir() const {
396 return mir_->toNewTypedArrayFromArrayBuffer();
397 }
398 };
399
400 class LNewObject : public LInstructionHelper<1, 0, 1> {
401 public:
LIR_HEADER(NewObject)402 LIR_HEADER(NewObject)
403
404 explicit LNewObject(const LDefinition& temp)
405 : LInstructionHelper(classOpcode) {
406 setTemp(0, temp);
407 }
408
extraName()409 const char* extraName() const {
410 return mir()->isVMCall() ? "VMCall" : nullptr;
411 }
412
temp()413 const LDefinition* temp() { return getTemp(0); }
414
mir()415 MNewObject* mir() const { return mir_->toNewObject(); }
416 };
417
418 class LNewPlainObject : public LInstructionHelper<1, 0, 3> {
419 public:
LIR_HEADER(NewPlainObject)420 LIR_HEADER(NewPlainObject)
421
422 explicit LNewPlainObject(const LDefinition& temp0, const LDefinition& temp1,
423 const LDefinition& temp2)
424 : LInstructionHelper(classOpcode) {
425 setTemp(0, temp0);
426 setTemp(1, temp1);
427 setTemp(2, temp2);
428 }
429
temp0()430 const LDefinition* temp0() { return getTemp(0); }
temp1()431 const LDefinition* temp1() { return getTemp(1); }
temp2()432 const LDefinition* temp2() { return getTemp(2); }
433
mir()434 MNewPlainObject* mir() const { return mir_->toNewPlainObject(); }
435 };
436
437 class LNewArrayObject : public LInstructionHelper<1, 0, 2> {
438 public:
LIR_HEADER(NewArrayObject)439 LIR_HEADER(NewArrayObject)
440
441 explicit LNewArrayObject(const LDefinition& temp0, const LDefinition& temp1)
442 : LInstructionHelper(classOpcode) {
443 setTemp(0, temp0);
444 setTemp(1, temp1);
445 }
446
temp0()447 const LDefinition* temp0() { return getTemp(0); }
temp1()448 const LDefinition* temp1() { return getTemp(1); }
449
mir()450 MNewArrayObject* mir() const { return mir_->toNewArrayObject(); }
451 };
452
453 // Allocates a new NamedLambdaObject.
454 //
455 // This instruction generates two possible instruction sets:
456 // (1) An inline allocation of the call object is attempted.
457 // (2) Otherwise, a callVM create a new object.
458 //
459 class LNewNamedLambdaObject : public LInstructionHelper<1, 0, 1> {
460 public:
461 LIR_HEADER(NewNamedLambdaObject);
462
LNewNamedLambdaObject(const LDefinition & temp)463 explicit LNewNamedLambdaObject(const LDefinition& temp)
464 : LInstructionHelper(classOpcode) {
465 setTemp(0, temp);
466 }
467
temp()468 const LDefinition* temp() { return getTemp(0); }
469
mir()470 MNewNamedLambdaObject* mir() const { return mir_->toNewNamedLambdaObject(); }
471 };
472
473 // Allocates a new CallObject.
474 //
475 // This instruction generates two possible instruction sets:
476 // (1) If the call object is extensible, this is a callVM to create the
477 // call object.
478 // (2) Otherwise, an inline allocation of the call object is attempted.
479 //
480 class LNewCallObject : public LInstructionHelper<1, 0, 1> {
481 public:
LIR_HEADER(NewCallObject)482 LIR_HEADER(NewCallObject)
483
484 explicit LNewCallObject(const LDefinition& temp)
485 : LInstructionHelper(classOpcode) {
486 setTemp(0, temp);
487 }
488
temp()489 const LDefinition* temp() { return getTemp(0); }
490
mir()491 MNewCallObject* mir() const { return mir_->toNewCallObject(); }
492 };
493
494 class LNewStringObject : public LInstructionHelper<1, 1, 1> {
495 public:
LIR_HEADER(NewStringObject)496 LIR_HEADER(NewStringObject)
497
498 LNewStringObject(const LAllocation& input, const LDefinition& temp)
499 : LInstructionHelper(classOpcode) {
500 setOperand(0, input);
501 setTemp(0, temp);
502 }
503
input()504 const LAllocation* input() { return getOperand(0); }
temp()505 const LDefinition* temp() { return getTemp(0); }
mir()506 MNewStringObject* mir() const { return mir_->toNewStringObject(); }
507 };
508
509 class LInitElemGetterSetter
510 : public LCallInstructionHelper<0, 2 + BOX_PIECES, 0> {
511 public:
LIR_HEADER(InitElemGetterSetter)512 LIR_HEADER(InitElemGetterSetter)
513
514 LInitElemGetterSetter(const LAllocation& object, const LBoxAllocation& id,
515 const LAllocation& value)
516 : LCallInstructionHelper(classOpcode) {
517 setOperand(0, object);
518 setOperand(1, value);
519 setBoxOperand(IdIndex, id);
520 }
521
522 static const size_t IdIndex = 2;
523
object()524 const LAllocation* object() { return getOperand(0); }
value()525 const LAllocation* value() { return getOperand(1); }
mir()526 MInitElemGetterSetter* mir() const { return mir_->toInitElemGetterSetter(); }
527 };
528
529 // Takes in an Object and a Value.
530 class LMutateProto : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0> {
531 public:
LIR_HEADER(MutateProto)532 LIR_HEADER(MutateProto)
533
534 LMutateProto(const LAllocation& object, const LBoxAllocation& value)
535 : LCallInstructionHelper(classOpcode) {
536 setOperand(0, object);
537 setBoxOperand(ValueIndex, value);
538 }
539
540 static const size_t ValueIndex = 1;
541
getObject()542 const LAllocation* getObject() { return getOperand(0); }
getValue()543 const LAllocation* getValue() { return getOperand(1); }
544 };
545
546 class LInitPropGetterSetter : public LCallInstructionHelper<0, 2, 0> {
547 public:
LIR_HEADER(InitPropGetterSetter)548 LIR_HEADER(InitPropGetterSetter)
549
550 LInitPropGetterSetter(const LAllocation& object, const LAllocation& value)
551 : LCallInstructionHelper(classOpcode) {
552 setOperand(0, object);
553 setOperand(1, value);
554 }
555
object()556 const LAllocation* object() { return getOperand(0); }
value()557 const LAllocation* value() { return getOperand(1); }
558
mir()559 MInitPropGetterSetter* mir() const { return mir_->toInitPropGetterSetter(); }
560 };
561
562 class LCheckOverRecursed : public LInstructionHelper<0, 0, 0> {
563 public:
LIR_HEADER(CheckOverRecursed)564 LIR_HEADER(CheckOverRecursed)
565
566 LCheckOverRecursed() : LInstructionHelper(classOpcode) {}
567
mir()568 MCheckOverRecursed* mir() const { return mir_->toCheckOverRecursed(); }
569 };
570
571 class LWasmTrap : public LInstructionHelper<0, 0, 0> {
572 public:
573 LIR_HEADER(WasmTrap);
574
LWasmTrap()575 LWasmTrap() : LInstructionHelper(classOpcode) {}
576
mir()577 const MWasmTrap* mir() const { return mir_->toWasmTrap(); }
578 };
579
580 template <size_t Defs, size_t Ops>
581 class LWasmReinterpretBase : public LInstructionHelper<Defs, Ops, 0> {
582 typedef LInstructionHelper<Defs, Ops, 0> Base;
583
584 protected:
LWasmReinterpretBase(LNode::Opcode opcode)585 explicit LWasmReinterpretBase(LNode::Opcode opcode) : Base(opcode) {}
586
587 public:
input()588 const LAllocation* input() { return Base::getOperand(0); }
mir()589 MWasmReinterpret* mir() const { return Base::mir_->toWasmReinterpret(); }
590 };
591
592 class LWasmReinterpret : public LWasmReinterpretBase<1, 1> {
593 public:
594 LIR_HEADER(WasmReinterpret);
LWasmReinterpret(const LAllocation & input)595 explicit LWasmReinterpret(const LAllocation& input)
596 : LWasmReinterpretBase(classOpcode) {
597 setOperand(0, input);
598 }
599 };
600
601 class LWasmReinterpretFromI64 : public LWasmReinterpretBase<1, INT64_PIECES> {
602 public:
603 static const size_t Input = 0;
604
605 LIR_HEADER(WasmReinterpretFromI64);
LWasmReinterpretFromI64(const LInt64Allocation & input)606 explicit LWasmReinterpretFromI64(const LInt64Allocation& input)
607 : LWasmReinterpretBase(classOpcode) {
608 setInt64Operand(Input, input);
609 }
610 };
611
612 class LWasmReinterpretToI64 : public LWasmReinterpretBase<INT64_PIECES, 1> {
613 public:
614 LIR_HEADER(WasmReinterpretToI64);
LWasmReinterpretToI64(const LAllocation & input)615 explicit LWasmReinterpretToI64(const LAllocation& input)
616 : LWasmReinterpretBase(classOpcode) {
617 setOperand(0, input);
618 }
619 };
620
621 namespace details {
622 template <size_t Defs, size_t Ops, size_t Temps>
623 class RotateBase : public LInstructionHelper<Defs, Ops, Temps> {
624 typedef LInstructionHelper<Defs, Ops, Temps> Base;
625
626 protected:
RotateBase(LNode::Opcode opcode)627 explicit RotateBase(LNode::Opcode opcode) : Base(opcode) {}
628
629 public:
mir()630 MRotate* mir() { return Base::mir_->toRotate(); }
631 };
632 } // namespace details
633
634 class LRotate : public details::RotateBase<1, 2, 0> {
635 public:
636 LIR_HEADER(Rotate);
637
LRotate()638 LRotate() : RotateBase(classOpcode) {}
639
input()640 const LAllocation* input() { return getOperand(0); }
count()641 LAllocation* count() { return getOperand(1); }
642 };
643
644 class LRotateI64
645 : public details::RotateBase<INT64_PIECES, INT64_PIECES + 1, 1> {
646 public:
647 LIR_HEADER(RotateI64);
648
LRotateI64()649 LRotateI64() : RotateBase(classOpcode) {
650 setTemp(0, LDefinition::BogusTemp());
651 }
652
653 static const size_t Input = 0;
654 static const size_t Count = INT64_PIECES;
655
input()656 const LInt64Allocation input() { return getInt64Operand(Input); }
temp()657 const LDefinition* temp() { return getTemp(0); }
count()658 LAllocation* count() { return getOperand(Count); }
659 };
660
661 class LInterruptCheck : public LInstructionHelper<0, 0, 0> {
662 public:
LIR_HEADER(InterruptCheck)663 LIR_HEADER(InterruptCheck)
664
665 LInterruptCheck() : LInstructionHelper(classOpcode) {}
mir()666 MInterruptCheck* mir() const { return mir_->toInterruptCheck(); }
667 };
668
669 class LWasmInterruptCheck : public LInstructionHelper<0, 1, 0> {
670 public:
LIR_HEADER(WasmInterruptCheck)671 LIR_HEADER(WasmInterruptCheck)
672
673 explicit LWasmInterruptCheck(const LAllocation& tlsData)
674 : LInstructionHelper(classOpcode) {
675 setOperand(0, tlsData);
676 }
mir()677 MWasmInterruptCheck* mir() const { return mir_->toWasmInterruptCheck(); }
tlsPtr()678 const LAllocation* tlsPtr() { return getOperand(0); }
679 };
680
681 class LTypeOfV : public LInstructionHelper<1, BOX_PIECES, 1> {
682 public:
LIR_HEADER(TypeOfV)683 LIR_HEADER(TypeOfV)
684
685 LTypeOfV(const LBoxAllocation& input, const LDefinition& tempToUnbox)
686 : LInstructionHelper(classOpcode) {
687 setBoxOperand(Input, input);
688 setTemp(0, tempToUnbox);
689 }
690
691 static const size_t Input = 0;
692
tempToUnbox()693 const LDefinition* tempToUnbox() { return getTemp(0); }
694
mir()695 MTypeOf* mir() const { return mir_->toTypeOf(); }
696 };
697
698 class LTypeOfO : public LInstructionHelper<1, 1, 0> {
699 public:
LIR_HEADER(TypeOfO)700 LIR_HEADER(TypeOfO)
701
702 explicit LTypeOfO(const LAllocation& obj) : LInstructionHelper(classOpcode) {
703 setOperand(0, obj);
704 }
705
object()706 const LAllocation* object() { return getOperand(0); }
707
mir()708 MTypeOf* mir() const { return mir_->toTypeOf(); }
709 };
710
711 class LToAsyncIter : public LCallInstructionHelper<1, 1 + BOX_PIECES, 0> {
712 public:
LIR_HEADER(ToAsyncIter)713 LIR_HEADER(ToAsyncIter)
714
715 explicit LToAsyncIter(const LAllocation& iterator,
716 const LBoxAllocation& nextMethod)
717 : LCallInstructionHelper(classOpcode) {
718 setOperand(0, iterator);
719 setBoxOperand(NextMethodIndex, nextMethod);
720 }
721
722 static const size_t NextMethodIndex = 1;
723
iterator()724 const LAllocation* iterator() { return getOperand(0); }
725 };
726
727 class LToPropertyKeyCache
728 : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 0> {
729 public:
LIR_HEADER(ToPropertyKeyCache)730 LIR_HEADER(ToPropertyKeyCache)
731
732 explicit LToPropertyKeyCache(const LBoxAllocation& input)
733 : LInstructionHelper(classOpcode) {
734 setBoxOperand(Input, input);
735 }
736
mir()737 const MToPropertyKeyCache* mir() const {
738 return mir_->toToPropertyKeyCache();
739 }
740
input()741 const LAllocation* input() { return getOperand(Input); }
742
743 static const size_t Input = 0;
744 };
745
746 // Allocate an object for |new| on the caller-side,
747 // when there is no templateObject or prototype known
748 class LCreateThis : public LCallInstructionHelper<BOX_PIECES, 2, 0> {
749 public:
LIR_HEADER(CreateThis)750 LIR_HEADER(CreateThis)
751
752 LCreateThis(const LAllocation& callee, const LAllocation& newTarget)
753 : LCallInstructionHelper(classOpcode) {
754 setOperand(0, callee);
755 setOperand(1, newTarget);
756 }
757
getCallee()758 const LAllocation* getCallee() { return getOperand(0); }
getNewTarget()759 const LAllocation* getNewTarget() { return getOperand(1); }
760
mir()761 MCreateThis* mir() const { return mir_->toCreateThis(); }
762 };
763
764 // Allocate an object for |new| on the caller-side.
765 // Always performs object initialization with a fast path.
766 class LCreateThisWithTemplate : public LInstructionHelper<1, 0, 1> {
767 public:
LIR_HEADER(CreateThisWithTemplate)768 LIR_HEADER(CreateThisWithTemplate)
769
770 explicit LCreateThisWithTemplate(const LDefinition& temp)
771 : LInstructionHelper(classOpcode) {
772 setTemp(0, temp);
773 }
774
mir()775 MCreateThisWithTemplate* mir() const {
776 return mir_->toCreateThisWithTemplate();
777 }
778
temp()779 const LDefinition* temp() { return getTemp(0); }
780 };
781
782 // Allocate a new arguments object for the frame.
783 class LCreateArgumentsObject : public LCallInstructionHelper<1, 1, 3> {
784 public:
LIR_HEADER(CreateArgumentsObject)785 LIR_HEADER(CreateArgumentsObject)
786
787 LCreateArgumentsObject(const LAllocation& callObj, const LDefinition& temp0,
788 const LDefinition& temp1, const LDefinition& temp2)
789 : LCallInstructionHelper(classOpcode) {
790 setOperand(0, callObj);
791 setTemp(0, temp0);
792 setTemp(1, temp1);
793 setTemp(2, temp2);
794 }
795
temp0()796 const LDefinition* temp0() { return getTemp(0); }
temp1()797 const LDefinition* temp1() { return getTemp(1); }
temp2()798 const LDefinition* temp2() { return getTemp(2); }
799
getCallObject()800 const LAllocation* getCallObject() { return getOperand(0); }
801
mir()802 MCreateArgumentsObject* mir() const {
803 return mir_->toCreateArgumentsObject();
804 }
805 };
806
807 // Allocate a new arguments object for an inlined frame.
808 class LCreateInlinedArgumentsObject : public LVariadicInstruction<1, 1> {
809 public:
810 LIR_HEADER(CreateInlinedArgumentsObject)
811
812 static const size_t CallObj = 0;
813 static const size_t Callee = 1;
814 static const size_t NumNonArgumentOperands = 2;
ArgIndex(size_t i)815 static size_t ArgIndex(size_t i) {
816 return NumNonArgumentOperands + BOX_PIECES * i;
817 }
818
LCreateInlinedArgumentsObject(uint32_t numOperands,const LDefinition & temp)819 LCreateInlinedArgumentsObject(uint32_t numOperands, const LDefinition& temp)
820 : LVariadicInstruction(classOpcode, numOperands) {
821 setIsCall();
822 setTemp(0, temp);
823 }
824
getCallObject()825 const LAllocation* getCallObject() { return getOperand(CallObj); }
getCallee()826 const LAllocation* getCallee() { return getOperand(Callee); }
827
temp()828 const LDefinition* temp() { return getTemp(0); }
829
mir()830 MCreateInlinedArgumentsObject* mir() const {
831 return mir_->toCreateInlinedArgumentsObject();
832 }
833 };
834
835 class LGetInlinedArgument : public LVariadicInstruction<BOX_PIECES, 0> {
836 public:
837 LIR_HEADER(GetInlinedArgument)
838
839 static const size_t Index = 0;
840 static const size_t NumNonArgumentOperands = 1;
ArgIndex(size_t i)841 static size_t ArgIndex(size_t i) {
842 return NumNonArgumentOperands + BOX_PIECES * i;
843 }
844
LGetInlinedArgument(uint32_t numOperands)845 explicit LGetInlinedArgument(uint32_t numOperands)
846 : LVariadicInstruction(classOpcode, numOperands) {}
847
getIndex()848 const LAllocation* getIndex() { return getOperand(Index); }
849
mir()850 MGetInlinedArgument* mir() const { return mir_->toGetInlinedArgument(); }
851 };
852
853 // Get argument from arguments object.
854 class LGetArgumentsObjectArg : public LInstructionHelper<BOX_PIECES, 1, 1> {
855 public:
LIR_HEADER(GetArgumentsObjectArg)856 LIR_HEADER(GetArgumentsObjectArg)
857
858 LGetArgumentsObjectArg(const LAllocation& argsObj, const LDefinition& temp)
859 : LInstructionHelper(classOpcode) {
860 setOperand(0, argsObj);
861 setTemp(0, temp);
862 }
863
getArgsObject()864 const LAllocation* getArgsObject() { return getOperand(0); }
865
mir()866 MGetArgumentsObjectArg* mir() const {
867 return mir_->toGetArgumentsObjectArg();
868 }
869 };
870
871 // Set argument on arguments object.
872 class LSetArgumentsObjectArg : public LInstructionHelper<0, 1 + BOX_PIECES, 1> {
873 public:
LIR_HEADER(SetArgumentsObjectArg)874 LIR_HEADER(SetArgumentsObjectArg)
875
876 LSetArgumentsObjectArg(const LAllocation& argsObj,
877 const LBoxAllocation& value, const LDefinition& temp)
878 : LInstructionHelper(classOpcode) {
879 setOperand(0, argsObj);
880 setBoxOperand(ValueIndex, value);
881 setTemp(0, temp);
882 }
883
getArgsObject()884 const LAllocation* getArgsObject() { return getOperand(0); }
885
mir()886 MSetArgumentsObjectArg* mir() const {
887 return mir_->toSetArgumentsObjectArg();
888 }
889
890 static const size_t ValueIndex = 1;
891 };
892
893 // Load an element from an arguments object.
894 class LLoadArgumentsObjectArg : public LInstructionHelper<BOX_PIECES, 2, 1> {
895 public:
LIR_HEADER(LoadArgumentsObjectArg)896 LIR_HEADER(LoadArgumentsObjectArg)
897
898 LLoadArgumentsObjectArg(const LAllocation& argsObj, const LAllocation& index,
899 const LDefinition& temp)
900 : LInstructionHelper(classOpcode) {
901 setOperand(0, argsObj);
902 setOperand(1, index);
903 setTemp(0, temp);
904 }
905
getArgsObject()906 const LAllocation* getArgsObject() { return getOperand(0); }
index()907 const LAllocation* index() { return getOperand(1); }
temp()908 const LDefinition* temp() { return this->getTemp(0); }
909 };
910
911 // Return |arguments.length| unless it has been overridden.
912 class LArgumentsObjectLength : public LInstructionHelper<1, 1, 0> {
913 public:
LIR_HEADER(ArgumentsObjectLength)914 LIR_HEADER(ArgumentsObjectLength)
915
916 explicit LArgumentsObjectLength(const LAllocation& argsObj)
917 : LInstructionHelper(classOpcode) {
918 setOperand(0, argsObj);
919 }
920
getArgsObject()921 const LAllocation* getArgsObject() { return getOperand(0); }
922 };
923
924 // Guard that the given flags are not set on the arguments object.
925 class LGuardArgumentsObjectFlags : public LInstructionHelper<0, 1, 1> {
926 public:
LIR_HEADER(GuardArgumentsObjectFlags)927 LIR_HEADER(GuardArgumentsObjectFlags)
928
929 explicit LGuardArgumentsObjectFlags(const LAllocation& argsObj,
930 const LDefinition& temp)
931 : LInstructionHelper(classOpcode) {
932 setOperand(0, argsObj);
933 setTemp(0, temp);
934 }
935
getArgsObject()936 const LAllocation* getArgsObject() { return getOperand(0); }
temp()937 const LDefinition* temp() { return this->getTemp(0); }
938
mir()939 MGuardArgumentsObjectFlags* mir() const {
940 return mir_->toGuardArgumentsObjectFlags();
941 }
942 };
943
944 // If the Value is an Object, return unbox(Value).
945 // Otherwise, return the other Object.
946 class LReturnFromCtor : public LInstructionHelper<1, BOX_PIECES + 1, 0> {
947 public:
LIR_HEADER(ReturnFromCtor)948 LIR_HEADER(ReturnFromCtor)
949
950 LReturnFromCtor(const LBoxAllocation& value, const LAllocation& object)
951 : LInstructionHelper(classOpcode) {
952 setBoxOperand(ValueIndex, value);
953 setOperand(ObjectIndex, object);
954 }
955
getObject()956 const LAllocation* getObject() { return getOperand(ObjectIndex); }
957
958 static const size_t ValueIndex = 0;
959 static const size_t ObjectIndex = BOX_PIECES;
960 };
961
962 class LBoxNonStrictThis : public LInstructionHelper<1, BOX_PIECES, 0> {
963 public:
964 LIR_HEADER(BoxNonStrictThis)
965
966 static const size_t ValueIndex = 0;
967
LBoxNonStrictThis(const LBoxAllocation & value)968 explicit LBoxNonStrictThis(const LBoxAllocation& value)
969 : LInstructionHelper(classOpcode) {
970 setBoxOperand(ValueIndex, value);
971 }
972
mir()973 MBoxNonStrictThis* mir() const { return mir_->toBoxNonStrictThis(); }
974 };
975
976 class LImplicitThis : public LCallInstructionHelper<BOX_PIECES, 1, 0> {
977 public:
LIR_HEADER(ImplicitThis)978 LIR_HEADER(ImplicitThis)
979
980 explicit LImplicitThis(const LAllocation& env)
981 : LCallInstructionHelper(classOpcode) {
982 setOperand(0, env);
983 }
984
env()985 const LAllocation* env() { return getOperand(0); }
986
mir()987 MImplicitThis* mir() const { return mir_->toImplicitThis(); }
988 };
989
990 // Writes a typed argument for a function call to the frame's argument vector.
991 class LStackArgT : public LInstructionHelper<0, 1, 0> {
992 uint32_t argslot_; // Index into frame-scope argument vector.
993 MIRType type_;
994
995 public:
LIR_HEADER(StackArgT)996 LIR_HEADER(StackArgT)
997
998 LStackArgT(uint32_t argslot, MIRType type, const LAllocation& arg)
999 : LInstructionHelper(classOpcode), argslot_(argslot), type_(type) {
1000 setOperand(0, arg);
1001 }
argslot()1002 uint32_t argslot() const { return argslot_; }
type()1003 MIRType type() const { return type_; }
getArgument()1004 const LAllocation* getArgument() { return getOperand(0); }
1005 };
1006
1007 // Writes an untyped argument for a function call to the frame's argument
1008 // vector.
1009 class LStackArgV : public LInstructionHelper<0, BOX_PIECES, 0> {
1010 uint32_t argslot_; // Index into frame-scope argument vector.
1011
1012 public:
LIR_HEADER(StackArgV)1013 LIR_HEADER(StackArgV)
1014
1015 LStackArgV(uint32_t argslot, const LBoxAllocation& value)
1016 : LInstructionHelper(classOpcode), argslot_(argslot) {
1017 setBoxOperand(0, value);
1018 }
1019
argslot()1020 uint32_t argslot() const { return argslot_; }
1021 };
1022
1023 // Common code for LIR descended from MCall.
1024 template <size_t Defs, size_t Operands, size_t Temps>
1025 class LJSCallInstructionHelper
1026 : public LCallInstructionHelper<Defs, Operands, Temps> {
1027 protected:
LJSCallInstructionHelper(LNode::Opcode opcode)1028 explicit LJSCallInstructionHelper(LNode::Opcode opcode)
1029 : LCallInstructionHelper<Defs, Operands, Temps>(opcode) {}
1030
1031 public:
argslot()1032 uint32_t argslot() const {
1033 if (JitStackValueAlignment > 1) {
1034 return AlignBytes(mir()->numStackArgs(), JitStackValueAlignment);
1035 }
1036 return mir()->numStackArgs();
1037 }
mir()1038 MCall* mir() const { return this->mir_->toCall(); }
1039
hasSingleTarget()1040 bool hasSingleTarget() const { return getSingleTarget() != nullptr; }
getSingleTarget()1041 WrappedFunction* getSingleTarget() const { return mir()->getSingleTarget(); }
1042
1043 // Does not include |this|.
numActualArgs()1044 uint32_t numActualArgs() const { return mir()->numActualArgs(); }
1045
isConstructing()1046 bool isConstructing() const { return mir()->isConstructing(); }
ignoresReturnValue()1047 bool ignoresReturnValue() const { return mir()->ignoresReturnValue(); }
1048 };
1049
1050 // Generates a polymorphic callsite, wherein the function being called is
1051 // unknown and anticipated to vary.
1052 class LCallGeneric : public LJSCallInstructionHelper<BOX_PIECES, 1, 2> {
1053 public:
LIR_HEADER(CallGeneric)1054 LIR_HEADER(CallGeneric)
1055
1056 LCallGeneric(const LAllocation& func, const LDefinition& nargsreg,
1057 const LDefinition& tmpobjreg)
1058 : LJSCallInstructionHelper(classOpcode) {
1059 setOperand(0, func);
1060 setTemp(0, nargsreg);
1061 setTemp(1, tmpobjreg);
1062 }
1063
getFunction()1064 const LAllocation* getFunction() { return getOperand(0); }
getNargsReg()1065 const LDefinition* getNargsReg() { return getTemp(0); }
getTempObject()1066 const LDefinition* getTempObject() { return getTemp(1); }
1067 };
1068
1069 // Generates a hardcoded callsite for a known, non-native target.
1070 class LCallKnown : public LJSCallInstructionHelper<BOX_PIECES, 1, 1> {
1071 public:
LIR_HEADER(CallKnown)1072 LIR_HEADER(CallKnown)
1073
1074 LCallKnown(const LAllocation& func, const LDefinition& tmpobjreg)
1075 : LJSCallInstructionHelper(classOpcode) {
1076 setOperand(0, func);
1077 setTemp(0, tmpobjreg);
1078 }
1079
getFunction()1080 const LAllocation* getFunction() { return getOperand(0); }
getTempObject()1081 const LDefinition* getTempObject() { return getTemp(0); }
1082 };
1083
1084 // Generates a hardcoded callsite for a known, native target.
1085 class LCallNative : public LJSCallInstructionHelper<BOX_PIECES, 0, 4> {
1086 public:
LIR_HEADER(CallNative)1087 LIR_HEADER(CallNative)
1088
1089 LCallNative(const LDefinition& argContext, const LDefinition& argUintN,
1090 const LDefinition& argVp, const LDefinition& tmpreg)
1091 : LJSCallInstructionHelper(classOpcode) {
1092 // Registers used for callWithABI().
1093 setTemp(0, argContext);
1094 setTemp(1, argUintN);
1095 setTemp(2, argVp);
1096
1097 // Temporary registers.
1098 setTemp(3, tmpreg);
1099 }
1100
getArgContextReg()1101 const LDefinition* getArgContextReg() { return getTemp(0); }
getArgUintNReg()1102 const LDefinition* getArgUintNReg() { return getTemp(1); }
getArgVpReg()1103 const LDefinition* getArgVpReg() { return getTemp(2); }
getTempReg()1104 const LDefinition* getTempReg() { return getTemp(3); }
1105 };
1106
1107 // Generates a hardcoded callsite for a known, DOM-native target.
1108 class LCallDOMNative : public LJSCallInstructionHelper<BOX_PIECES, 0, 4> {
1109 public:
LIR_HEADER(CallDOMNative)1110 LIR_HEADER(CallDOMNative)
1111
1112 LCallDOMNative(const LDefinition& argJSContext, const LDefinition& argObj,
1113 const LDefinition& argPrivate, const LDefinition& argArgs)
1114 : LJSCallInstructionHelper(classOpcode) {
1115 setTemp(0, argJSContext);
1116 setTemp(1, argObj);
1117 setTemp(2, argPrivate);
1118 setTemp(3, argArgs);
1119 }
1120
getArgJSContext()1121 const LDefinition* getArgJSContext() { return getTemp(0); }
getArgObj()1122 const LDefinition* getArgObj() { return getTemp(1); }
getArgPrivate()1123 const LDefinition* getArgPrivate() { return getTemp(2); }
getArgArgs()1124 const LDefinition* getArgArgs() { return getTemp(3); }
1125 };
1126
1127 class LBail : public LInstructionHelper<0, 0, 0> {
1128 public:
LIR_HEADER(Bail)1129 LIR_HEADER(Bail)
1130
1131 LBail() : LInstructionHelper(classOpcode) {}
1132 };
1133
1134 class LUnreachable : public LControlInstructionHelper<0, 0, 0> {
1135 public:
LIR_HEADER(Unreachable)1136 LIR_HEADER(Unreachable)
1137
1138 LUnreachable() : LControlInstructionHelper(classOpcode) {}
1139 };
1140
1141 class LEncodeSnapshot : public LInstructionHelper<0, 0, 0> {
1142 public:
LIR_HEADER(EncodeSnapshot)1143 LIR_HEADER(EncodeSnapshot)
1144
1145 LEncodeSnapshot() : LInstructionHelper(classOpcode) {}
1146 };
1147
1148 class LUnreachableResultV : public LInstructionHelper<BOX_PIECES, 0, 0> {
1149 public:
LIR_HEADER(UnreachableResultV)1150 LIR_HEADER(UnreachableResultV)
1151
1152 LUnreachableResultV() : LInstructionHelper(classOpcode) {}
1153 };
1154
1155 class LUnreachableResultT : public LInstructionHelper<1, 0, 0> {
1156 public:
LIR_HEADER(UnreachableResultT)1157 LIR_HEADER(UnreachableResultT)
1158
1159 LUnreachableResultT() : LInstructionHelper(classOpcode) {}
1160 };
1161
1162 template <size_t defs, size_t ops>
1163 class LDOMPropertyInstructionHelper
1164 : public LCallInstructionHelper<defs, 1 + ops, 3> {
1165 protected:
LDOMPropertyInstructionHelper(LNode::Opcode opcode,const LDefinition & JSContextReg,const LAllocation & ObjectReg,const LDefinition & PrivReg,const LDefinition & ValueReg)1166 LDOMPropertyInstructionHelper(LNode::Opcode opcode,
1167 const LDefinition& JSContextReg,
1168 const LAllocation& ObjectReg,
1169 const LDefinition& PrivReg,
1170 const LDefinition& ValueReg)
1171 : LCallInstructionHelper<defs, 1 + ops, 3>(opcode) {
1172 this->setOperand(0, ObjectReg);
1173 this->setTemp(0, JSContextReg);
1174 this->setTemp(1, PrivReg);
1175 this->setTemp(2, ValueReg);
1176 }
1177
1178 public:
getJSContextReg()1179 const LDefinition* getJSContextReg() { return this->getTemp(0); }
getObjectReg()1180 const LAllocation* getObjectReg() { return this->getOperand(0); }
getPrivReg()1181 const LDefinition* getPrivReg() { return this->getTemp(1); }
getValueReg()1182 const LDefinition* getValueReg() { return this->getTemp(2); }
1183 };
1184
1185 class LGetDOMProperty : public LDOMPropertyInstructionHelper<BOX_PIECES, 0> {
1186 public:
LIR_HEADER(GetDOMProperty)1187 LIR_HEADER(GetDOMProperty)
1188
1189 LGetDOMProperty(const LDefinition& JSContextReg, const LAllocation& ObjectReg,
1190 const LDefinition& PrivReg, const LDefinition& ValueReg)
1191 : LDOMPropertyInstructionHelper<BOX_PIECES, 0>(
1192 classOpcode, JSContextReg, ObjectReg, PrivReg, ValueReg) {}
1193
mir()1194 MGetDOMProperty* mir() const { return mir_->toGetDOMProperty(); }
1195 };
1196
1197 class LGetDOMMemberV : public LInstructionHelper<BOX_PIECES, 1, 0> {
1198 public:
1199 LIR_HEADER(GetDOMMemberV);
LGetDOMMemberV(const LAllocation & object)1200 explicit LGetDOMMemberV(const LAllocation& object)
1201 : LInstructionHelper(classOpcode) {
1202 setOperand(0, object);
1203 }
1204
object()1205 const LAllocation* object() { return getOperand(0); }
1206
mir()1207 MGetDOMMember* mir() const { return mir_->toGetDOMMember(); }
1208 };
1209
1210 class LGetDOMMemberT : public LInstructionHelper<1, 1, 0> {
1211 public:
1212 LIR_HEADER(GetDOMMemberT);
LGetDOMMemberT(const LAllocation & object)1213 explicit LGetDOMMemberT(const LAllocation& object)
1214 : LInstructionHelper(classOpcode) {
1215 setOperand(0, object);
1216 }
1217
object()1218 const LAllocation* object() { return getOperand(0); }
1219
mir()1220 MGetDOMMember* mir() const { return mir_->toGetDOMMember(); }
1221 };
1222
1223 class LSetDOMProperty : public LDOMPropertyInstructionHelper<0, BOX_PIECES> {
1224 public:
LIR_HEADER(SetDOMProperty)1225 LIR_HEADER(SetDOMProperty)
1226
1227 LSetDOMProperty(const LDefinition& JSContextReg, const LAllocation& ObjectReg,
1228 const LBoxAllocation& value, const LDefinition& PrivReg,
1229 const LDefinition& ValueReg)
1230 : LDOMPropertyInstructionHelper<0, BOX_PIECES>(
1231 classOpcode, JSContextReg, ObjectReg, PrivReg, ValueReg) {
1232 setBoxOperand(Value, value);
1233 }
1234
1235 static const size_t Value = 1;
1236
mir()1237 MSetDOMProperty* mir() const { return mir_->toSetDOMProperty(); }
1238 };
1239
1240 class LLoadDOMExpandoValue : public LInstructionHelper<BOX_PIECES, 1, 0> {
1241 public:
LIR_HEADER(LoadDOMExpandoValue)1242 LIR_HEADER(LoadDOMExpandoValue)
1243
1244 explicit LLoadDOMExpandoValue(const LAllocation& proxy)
1245 : LInstructionHelper(classOpcode) {
1246 setOperand(0, proxy);
1247 }
1248
proxy()1249 const LAllocation* proxy() { return getOperand(0); }
1250
mir()1251 const MLoadDOMExpandoValue* mir() const {
1252 return mir_->toLoadDOMExpandoValue();
1253 }
1254 };
1255
1256 class LLoadDOMExpandoValueGuardGeneration
1257 : public LInstructionHelper<BOX_PIECES, 1, 0> {
1258 public:
LIR_HEADER(LoadDOMExpandoValueGuardGeneration)1259 LIR_HEADER(LoadDOMExpandoValueGuardGeneration)
1260
1261 explicit LLoadDOMExpandoValueGuardGeneration(const LAllocation& proxy)
1262 : LInstructionHelper(classOpcode) {
1263 setOperand(0, proxy);
1264 }
1265
proxy()1266 const LAllocation* proxy() { return getOperand(0); }
1267
mir()1268 const MLoadDOMExpandoValueGuardGeneration* mir() const {
1269 return mir_->toLoadDOMExpandoValueGuardGeneration();
1270 }
1271 };
1272
1273 class LLoadDOMExpandoValueIgnoreGeneration
1274 : public LInstructionHelper<BOX_PIECES, 1, 0> {
1275 public:
LIR_HEADER(LoadDOMExpandoValueIgnoreGeneration)1276 LIR_HEADER(LoadDOMExpandoValueIgnoreGeneration)
1277
1278 explicit LLoadDOMExpandoValueIgnoreGeneration(const LAllocation& proxy)
1279 : LInstructionHelper(classOpcode) {
1280 setOperand(0, proxy);
1281 }
1282
proxy()1283 const LAllocation* proxy() { return getOperand(0); }
1284 };
1285
1286 class LGuardDOMExpandoMissingOrGuardShape
1287 : public LInstructionHelper<0, BOX_PIECES, 1> {
1288 public:
LIR_HEADER(GuardDOMExpandoMissingOrGuardShape)1289 LIR_HEADER(GuardDOMExpandoMissingOrGuardShape)
1290
1291 explicit LGuardDOMExpandoMissingOrGuardShape(const LBoxAllocation& input,
1292 const LDefinition& temp)
1293 : LInstructionHelper(classOpcode) {
1294 setBoxOperand(Input, input);
1295 setTemp(0, temp);
1296 }
1297
temp()1298 const LDefinition* temp() { return getTemp(0); }
1299
1300 static const size_t Input = 0;
1301
mir()1302 MGuardDOMExpandoMissingOrGuardShape* mir() {
1303 return mir_->toGuardDOMExpandoMissingOrGuardShape();
1304 }
1305 };
1306
1307 // Generates a polymorphic callsite, wherein the function being called is
1308 // unknown and anticipated to vary.
1309 class LApplyArgsGeneric
1310 : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES + 2, 2> {
1311 public:
LIR_HEADER(ApplyArgsGeneric)1312 LIR_HEADER(ApplyArgsGeneric)
1313
1314 LApplyArgsGeneric(const LAllocation& func, const LAllocation& argc,
1315 const LBoxAllocation& thisv, const LDefinition& tmpobjreg,
1316 const LDefinition& tmpcopy)
1317 : LCallInstructionHelper(classOpcode) {
1318 setOperand(0, func);
1319 setOperand(1, argc);
1320 setBoxOperand(ThisIndex, thisv);
1321 setTemp(0, tmpobjreg);
1322 setTemp(1, tmpcopy);
1323 }
1324
mir()1325 MApplyArgs* mir() const { return mir_->toApplyArgs(); }
1326
hasSingleTarget()1327 bool hasSingleTarget() const { return getSingleTarget() != nullptr; }
getSingleTarget()1328 WrappedFunction* getSingleTarget() const { return mir()->getSingleTarget(); }
1329
getFunction()1330 const LAllocation* getFunction() { return getOperand(0); }
getArgc()1331 const LAllocation* getArgc() { return getOperand(1); }
1332 static const size_t ThisIndex = 2;
1333
getTempObject()1334 const LDefinition* getTempObject() { return getTemp(0); }
getTempStackCounter()1335 const LDefinition* getTempStackCounter() { return getTemp(1); }
1336 };
1337
1338 class LApplyArgsObj
1339 : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES + 2, 2> {
1340 public:
LIR_HEADER(ApplyArgsObj)1341 LIR_HEADER(ApplyArgsObj)
1342
1343 LApplyArgsObj(const LAllocation& func, const LAllocation& argsObj,
1344 const LBoxAllocation& thisv, const LDefinition& tmpObjReg,
1345 const LDefinition& tmpCopy)
1346 : LCallInstructionHelper(classOpcode) {
1347 setOperand(0, func);
1348 setOperand(1, argsObj);
1349 setBoxOperand(ThisIndex, thisv);
1350 setTemp(0, tmpObjReg);
1351 setTemp(1, tmpCopy);
1352 }
1353
mir()1354 MApplyArgsObj* mir() const { return mir_->toApplyArgsObj(); }
1355
hasSingleTarget()1356 bool hasSingleTarget() const { return getSingleTarget() != nullptr; }
getSingleTarget()1357 WrappedFunction* getSingleTarget() const { return mir()->getSingleTarget(); }
1358
getFunction()1359 const LAllocation* getFunction() { return getOperand(0); }
getArgsObj()1360 const LAllocation* getArgsObj() { return getOperand(1); }
1361 // All registers are calltemps. argc is mapped to the same register as
1362 // ArgsObj. argc becomes live as ArgsObj is dying.
getArgc()1363 const LAllocation* getArgc() { return getOperand(1); }
1364 static const size_t ThisIndex = 2;
1365
getTempObject()1366 const LDefinition* getTempObject() { return getTemp(0); }
getTempStackCounter()1367 const LDefinition* getTempStackCounter() { return getTemp(1); }
1368 };
1369
1370 class LApplyArrayGeneric
1371 : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES + 2, 2> {
1372 public:
LIR_HEADER(ApplyArrayGeneric)1373 LIR_HEADER(ApplyArrayGeneric)
1374
1375 LApplyArrayGeneric(const LAllocation& func, const LAllocation& elements,
1376 const LBoxAllocation& thisv, const LDefinition& tmpobjreg,
1377 const LDefinition& tmpcopy)
1378 : LCallInstructionHelper(classOpcode) {
1379 setOperand(0, func);
1380 setOperand(1, elements);
1381 setBoxOperand(ThisIndex, thisv);
1382 setTemp(0, tmpobjreg);
1383 setTemp(1, tmpcopy);
1384 }
1385
mir()1386 MApplyArray* mir() const { return mir_->toApplyArray(); }
1387
hasSingleTarget()1388 bool hasSingleTarget() const { return getSingleTarget() != nullptr; }
getSingleTarget()1389 WrappedFunction* getSingleTarget() const { return mir()->getSingleTarget(); }
1390
getFunction()1391 const LAllocation* getFunction() { return getOperand(0); }
getElements()1392 const LAllocation* getElements() { return getOperand(1); }
1393 // argc is mapped to the same register as elements: argc becomes
1394 // live as elements is dying, all registers are calltemps.
getArgc()1395 const LAllocation* getArgc() { return getOperand(1); }
1396 static const size_t ThisIndex = 2;
1397
getTempObject()1398 const LDefinition* getTempObject() { return getTemp(0); }
getTempStackCounter()1399 const LDefinition* getTempStackCounter() { return getTemp(1); }
1400 };
1401
1402 class LConstructArrayGeneric
1403 : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES + 3, 1> {
1404 public:
LIR_HEADER(ConstructArrayGeneric)1405 LIR_HEADER(ConstructArrayGeneric)
1406
1407 LConstructArrayGeneric(const LAllocation& func, const LAllocation& elements,
1408 const LAllocation& newTarget,
1409 const LBoxAllocation& thisv,
1410 const LDefinition& tmpobjreg)
1411 : LCallInstructionHelper(classOpcode) {
1412 setOperand(0, func);
1413 setOperand(1, elements);
1414 setOperand(2, newTarget);
1415 setBoxOperand(ThisIndex, thisv);
1416 setTemp(0, tmpobjreg);
1417 }
1418
mir()1419 MConstructArray* mir() const { return mir_->toConstructArray(); }
1420
hasSingleTarget()1421 bool hasSingleTarget() const { return getSingleTarget() != nullptr; }
getSingleTarget()1422 WrappedFunction* getSingleTarget() const { return mir()->getSingleTarget(); }
1423
getFunction()1424 const LAllocation* getFunction() { return getOperand(0); }
getElements()1425 const LAllocation* getElements() { return getOperand(1); }
getNewTarget()1426 const LAllocation* getNewTarget() { return getOperand(2); }
1427
1428 static const size_t ThisIndex = 3;
1429
getTempObject()1430 const LDefinition* getTempObject() { return getTemp(0); }
1431
1432 // argc is mapped to the same register as elements: argc becomes
1433 // live as elements is dying, all registers are calltemps.
getArgc()1434 const LAllocation* getArgc() { return getOperand(1); }
1435
1436 // tempStackCounter is mapped to the same register as newTarget:
1437 // tempStackCounter becomes live as newTarget is dying, all registers are
1438 // calltemps.
getTempStackCounter()1439 const LAllocation* getTempStackCounter() { return getOperand(2); }
1440 };
1441
1442 // Takes in either an integer or boolean input and tests it for truthiness.
1443 class LTestIAndBranch : public LControlInstructionHelper<2, 1, 0> {
1444 public:
LIR_HEADER(TestIAndBranch)1445 LIR_HEADER(TestIAndBranch)
1446
1447 LTestIAndBranch(const LAllocation& in, MBasicBlock* ifTrue,
1448 MBasicBlock* ifFalse)
1449 : LControlInstructionHelper(classOpcode) {
1450 setOperand(0, in);
1451 setSuccessor(0, ifTrue);
1452 setSuccessor(1, ifFalse);
1453 }
1454
ifTrue()1455 MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()1456 MBasicBlock* ifFalse() const { return getSuccessor(1); }
1457 };
1458
1459 // Takes in an int64 input and tests it for truthiness.
1460 class LTestI64AndBranch : public LControlInstructionHelper<2, INT64_PIECES, 0> {
1461 public:
LIR_HEADER(TestI64AndBranch)1462 LIR_HEADER(TestI64AndBranch)
1463
1464 LTestI64AndBranch(const LInt64Allocation& in, MBasicBlock* ifTrue,
1465 MBasicBlock* ifFalse)
1466 : LControlInstructionHelper(classOpcode) {
1467 setInt64Operand(0, in);
1468 setSuccessor(0, ifTrue);
1469 setSuccessor(1, ifFalse);
1470 }
1471
ifTrue()1472 MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()1473 MBasicBlock* ifFalse() const { return getSuccessor(1); }
1474 };
1475
1476 // Takes in a double input and tests it for truthiness.
1477 class LTestDAndBranch : public LControlInstructionHelper<2, 1, 0> {
1478 public:
LIR_HEADER(TestDAndBranch)1479 LIR_HEADER(TestDAndBranch)
1480
1481 LTestDAndBranch(const LAllocation& in, MBasicBlock* ifTrue,
1482 MBasicBlock* ifFalse)
1483 : LControlInstructionHelper(classOpcode) {
1484 setOperand(0, in);
1485 setSuccessor(0, ifTrue);
1486 setSuccessor(1, ifFalse);
1487 }
1488
ifTrue()1489 MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()1490 MBasicBlock* ifFalse() const { return getSuccessor(1); }
1491 };
1492
1493 // Takes in a float32 input and tests it for truthiness.
1494 class LTestFAndBranch : public LControlInstructionHelper<2, 1, 0> {
1495 public:
LIR_HEADER(TestFAndBranch)1496 LIR_HEADER(TestFAndBranch)
1497
1498 LTestFAndBranch(const LAllocation& in, MBasicBlock* ifTrue,
1499 MBasicBlock* ifFalse)
1500 : LControlInstructionHelper(classOpcode) {
1501 setOperand(0, in);
1502 setSuccessor(0, ifTrue);
1503 setSuccessor(1, ifFalse);
1504 }
1505
ifTrue()1506 MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()1507 MBasicBlock* ifFalse() const { return getSuccessor(1); }
1508 };
1509
1510 // Takes in a bigint input and tests it for truthiness.
1511 class LTestBIAndBranch : public LControlInstructionHelper<2, 1, 0> {
1512 public:
LIR_HEADER(TestBIAndBranch)1513 LIR_HEADER(TestBIAndBranch)
1514
1515 LTestBIAndBranch(const LAllocation& in, MBasicBlock* ifTrue,
1516 MBasicBlock* ifFalse)
1517 : LControlInstructionHelper(classOpcode) {
1518 setOperand(0, in);
1519 setSuccessor(0, ifTrue);
1520 setSuccessor(1, ifFalse);
1521 }
1522
ifTrue()1523 MBasicBlock* ifTrue() { return getSuccessor(0); }
ifFalse()1524 MBasicBlock* ifFalse() { return getSuccessor(1); }
1525 };
1526
1527 // Takes an object and tests it for truthiness. An object is falsy iff it
1528 // emulates |undefined|; see js::EmulatesUndefined.
1529 class LTestOAndBranch : public LControlInstructionHelper<2, 1, 1> {
1530 public:
LIR_HEADER(TestOAndBranch)1531 LIR_HEADER(TestOAndBranch)
1532
1533 LTestOAndBranch(const LAllocation& input, MBasicBlock* ifTruthy,
1534 MBasicBlock* ifFalsy, const LDefinition& temp)
1535 : LControlInstructionHelper(classOpcode) {
1536 setOperand(0, input);
1537 setSuccessor(0, ifTruthy);
1538 setSuccessor(1, ifFalsy);
1539 setTemp(0, temp);
1540 }
1541
temp()1542 const LDefinition* temp() { return getTemp(0); }
1543
ifTruthy()1544 MBasicBlock* ifTruthy() { return getSuccessor(0); }
ifFalsy()1545 MBasicBlock* ifFalsy() { return getSuccessor(1); }
1546
mir()1547 MTest* mir() { return mir_->toTest(); }
1548 };
1549
1550 // Takes in a boxed value and tests it for truthiness.
1551 class LTestVAndBranch : public LControlInstructionHelper<2, BOX_PIECES, 3> {
1552 public:
LIR_HEADER(TestVAndBranch)1553 LIR_HEADER(TestVAndBranch)
1554
1555 LTestVAndBranch(MBasicBlock* ifTruthy, MBasicBlock* ifFalsy,
1556 const LBoxAllocation& input, const LDefinition& temp0,
1557 const LDefinition& temp1, const LDefinition& temp2)
1558 : LControlInstructionHelper(classOpcode) {
1559 setSuccessor(0, ifTruthy);
1560 setSuccessor(1, ifFalsy);
1561 setBoxOperand(Input, input);
1562 setTemp(0, temp0);
1563 setTemp(1, temp1);
1564 setTemp(2, temp2);
1565 }
1566
1567 static const size_t Input = 0;
1568
tempFloat()1569 const LDefinition* tempFloat() { return getTemp(0); }
1570
temp1()1571 const LDefinition* temp1() { return getTemp(1); }
1572
temp2()1573 const LDefinition* temp2() { return getTemp(2); }
1574
ifTruthy()1575 MBasicBlock* ifTruthy() { return getSuccessor(0); }
ifFalsy()1576 MBasicBlock* ifFalsy() { return getSuccessor(1); }
1577
mir()1578 MTest* mir() const { return mir_->toTest(); }
1579 };
1580
1581 // Compares two integral values of the same JS type, either integer or object.
1582 // For objects, both operands are in registers.
1583 class LCompare : public LInstructionHelper<1, 2, 0> {
1584 JSOp jsop_;
1585
1586 public:
LIR_HEADER(Compare)1587 LIR_HEADER(Compare)
1588 LCompare(JSOp jsop, const LAllocation& left, const LAllocation& right)
1589 : LInstructionHelper(classOpcode), jsop_(jsop) {
1590 setOperand(0, left);
1591 setOperand(1, right);
1592 }
1593
jsop()1594 JSOp jsop() const { return jsop_; }
left()1595 const LAllocation* left() { return getOperand(0); }
right()1596 const LAllocation* right() { return getOperand(1); }
mir()1597 MCompare* mir() { return mir_->toCompare(); }
extraName()1598 const char* extraName() const { return CodeName(jsop_); }
1599 };
1600
1601 class LCompareI64 : public LInstructionHelper<1, 2 * INT64_PIECES, 0> {
1602 JSOp jsop_;
1603
1604 public:
1605 LIR_HEADER(CompareI64)
1606
1607 static const size_t Lhs = 0;
1608 static const size_t Rhs = INT64_PIECES;
1609
LCompareI64(JSOp jsop,const LInt64Allocation & left,const LInt64Allocation & right)1610 LCompareI64(JSOp jsop, const LInt64Allocation& left,
1611 const LInt64Allocation& right)
1612 : LInstructionHelper(classOpcode), jsop_(jsop) {
1613 setInt64Operand(Lhs, left);
1614 setInt64Operand(Rhs, right);
1615 }
1616
jsop()1617 JSOp jsop() const { return jsop_; }
mir()1618 MCompare* mir() { return mir_->toCompare(); }
extraName()1619 const char* extraName() const { return CodeName(jsop_); }
1620 };
1621
1622 class LCompareI64AndBranch
1623 : public LControlInstructionHelper<2, 2 * INT64_PIECES, 0> {
1624 MCompare* cmpMir_;
1625 JSOp jsop_;
1626
1627 public:
1628 LIR_HEADER(CompareI64AndBranch)
1629
1630 static const size_t Lhs = 0;
1631 static const size_t Rhs = INT64_PIECES;
1632
LCompareI64AndBranch(MCompare * cmpMir,JSOp jsop,const LInt64Allocation & left,const LInt64Allocation & right,MBasicBlock * ifTrue,MBasicBlock * ifFalse)1633 LCompareI64AndBranch(MCompare* cmpMir, JSOp jsop,
1634 const LInt64Allocation& left,
1635 const LInt64Allocation& right, MBasicBlock* ifTrue,
1636 MBasicBlock* ifFalse)
1637 : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {
1638 setInt64Operand(Lhs, left);
1639 setInt64Operand(Rhs, right);
1640 setSuccessor(0, ifTrue);
1641 setSuccessor(1, ifFalse);
1642 }
1643
jsop()1644 JSOp jsop() const { return jsop_; }
ifTrue()1645 MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()1646 MBasicBlock* ifFalse() const { return getSuccessor(1); }
mir()1647 MTest* mir() const { return mir_->toTest(); }
cmpMir()1648 MCompare* cmpMir() const { return cmpMir_; }
extraName()1649 const char* extraName() const { return CodeName(jsop_); }
1650 };
1651
1652 // Compares two integral values of the same JS type, either integer or object.
1653 // For objects, both operands are in registers.
1654 class LCompareAndBranch : public LControlInstructionHelper<2, 2, 0> {
1655 MCompare* cmpMir_;
1656 JSOp jsop_;
1657
1658 public:
LIR_HEADER(CompareAndBranch)1659 LIR_HEADER(CompareAndBranch)
1660 LCompareAndBranch(MCompare* cmpMir, JSOp jsop, const LAllocation& left,
1661 const LAllocation& right, MBasicBlock* ifTrue,
1662 MBasicBlock* ifFalse)
1663 : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir), jsop_(jsop) {
1664 setOperand(0, left);
1665 setOperand(1, right);
1666 setSuccessor(0, ifTrue);
1667 setSuccessor(1, ifFalse);
1668 }
1669
jsop()1670 JSOp jsop() const { return jsop_; }
ifTrue()1671 MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()1672 MBasicBlock* ifFalse() const { return getSuccessor(1); }
left()1673 const LAllocation* left() { return getOperand(0); }
right()1674 const LAllocation* right() { return getOperand(1); }
mir()1675 MTest* mir() const { return mir_->toTest(); }
cmpMir()1676 MCompare* cmpMir() const { return cmpMir_; }
extraName()1677 const char* extraName() const { return CodeName(jsop_); }
1678 };
1679
1680 class LCompareD : public LInstructionHelper<1, 2, 0> {
1681 public:
LIR_HEADER(CompareD)1682 LIR_HEADER(CompareD)
1683 LCompareD(const LAllocation& left, const LAllocation& right)
1684 : LInstructionHelper(classOpcode) {
1685 setOperand(0, left);
1686 setOperand(1, right);
1687 }
1688
left()1689 const LAllocation* left() { return getOperand(0); }
right()1690 const LAllocation* right() { return getOperand(1); }
mir()1691 MCompare* mir() { return mir_->toCompare(); }
1692 };
1693
1694 class LCompareF : public LInstructionHelper<1, 2, 0> {
1695 public:
LIR_HEADER(CompareF)1696 LIR_HEADER(CompareF)
1697
1698 LCompareF(const LAllocation& left, const LAllocation& right)
1699 : LInstructionHelper(classOpcode) {
1700 setOperand(0, left);
1701 setOperand(1, right);
1702 }
1703
left()1704 const LAllocation* left() { return getOperand(0); }
right()1705 const LAllocation* right() { return getOperand(1); }
mir()1706 MCompare* mir() { return mir_->toCompare(); }
1707 };
1708
1709 class LCompareDAndBranch : public LControlInstructionHelper<2, 2, 0> {
1710 MCompare* cmpMir_;
1711
1712 public:
LIR_HEADER(CompareDAndBranch)1713 LIR_HEADER(CompareDAndBranch)
1714
1715 LCompareDAndBranch(MCompare* cmpMir, const LAllocation& left,
1716 const LAllocation& right, MBasicBlock* ifTrue,
1717 MBasicBlock* ifFalse)
1718 : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {
1719 setOperand(0, left);
1720 setOperand(1, right);
1721 setSuccessor(0, ifTrue);
1722 setSuccessor(1, ifFalse);
1723 }
1724
ifTrue()1725 MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()1726 MBasicBlock* ifFalse() const { return getSuccessor(1); }
left()1727 const LAllocation* left() { return getOperand(0); }
right()1728 const LAllocation* right() { return getOperand(1); }
mir()1729 MTest* mir() const { return mir_->toTest(); }
cmpMir()1730 MCompare* cmpMir() const { return cmpMir_; }
1731 };
1732
1733 class LCompareFAndBranch : public LControlInstructionHelper<2, 2, 0> {
1734 MCompare* cmpMir_;
1735
1736 public:
LIR_HEADER(CompareFAndBranch)1737 LIR_HEADER(CompareFAndBranch)
1738 LCompareFAndBranch(MCompare* cmpMir, const LAllocation& left,
1739 const LAllocation& right, MBasicBlock* ifTrue,
1740 MBasicBlock* ifFalse)
1741 : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {
1742 setOperand(0, left);
1743 setOperand(1, right);
1744 setSuccessor(0, ifTrue);
1745 setSuccessor(1, ifFalse);
1746 }
1747
ifTrue()1748 MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()1749 MBasicBlock* ifFalse() const { return getSuccessor(1); }
left()1750 const LAllocation* left() { return getOperand(0); }
right()1751 const LAllocation* right() { return getOperand(1); }
mir()1752 MTest* mir() const { return mir_->toTest(); }
cmpMir()1753 MCompare* cmpMir() const { return cmpMir_; }
1754 };
1755
1756 class LCompareS : public LInstructionHelper<1, 2, 0> {
1757 public:
LIR_HEADER(CompareS)1758 LIR_HEADER(CompareS)
1759
1760 LCompareS(const LAllocation& left, const LAllocation& right)
1761 : LInstructionHelper(classOpcode) {
1762 setOperand(0, left);
1763 setOperand(1, right);
1764 }
1765
left()1766 const LAllocation* left() { return getOperand(0); }
right()1767 const LAllocation* right() { return getOperand(1); }
mir()1768 MCompare* mir() { return mir_->toCompare(); }
1769 };
1770
1771 class LCompareBigInt : public LInstructionHelper<1, 2, 3> {
1772 public:
LIR_HEADER(CompareBigInt)1773 LIR_HEADER(CompareBigInt)
1774
1775 LCompareBigInt(const LAllocation& left, const LAllocation& right,
1776 const LDefinition& temp1, const LDefinition& temp2,
1777 const LDefinition& temp3)
1778 : LInstructionHelper(classOpcode) {
1779 setOperand(0, left);
1780 setOperand(1, right);
1781 setTemp(0, temp1);
1782 setTemp(1, temp2);
1783 setTemp(2, temp3);
1784 }
1785
left()1786 const LAllocation* left() { return getOperand(0); }
right()1787 const LAllocation* right() { return getOperand(1); }
temp1()1788 const LDefinition* temp1() { return getTemp(0); }
temp2()1789 const LDefinition* temp2() { return getTemp(1); }
temp3()1790 const LDefinition* temp3() { return getTemp(2); }
mir()1791 MCompare* mir() { return mir_->toCompare(); }
1792 };
1793
1794 class LCompareBigIntInt32 : public LInstructionHelper<1, 2, 2> {
1795 public:
LIR_HEADER(CompareBigIntInt32)1796 LIR_HEADER(CompareBigIntInt32)
1797
1798 LCompareBigIntInt32(const LAllocation& left, const LAllocation& right,
1799 const LDefinition& temp1, const LDefinition& temp2)
1800 : LInstructionHelper(classOpcode) {
1801 setOperand(0, left);
1802 setOperand(1, right);
1803 setTemp(0, temp1);
1804 setTemp(1, temp2);
1805 }
1806
left()1807 const LAllocation* left() { return getOperand(0); }
right()1808 const LAllocation* right() { return getOperand(1); }
temp1()1809 const LDefinition* temp1() { return getTemp(0); }
temp2()1810 const LDefinition* temp2() { return getTemp(1); }
mir()1811 MCompare* mir() { return mir_->toCompare(); }
1812 };
1813
1814 class LCompareBigIntDouble : public LCallInstructionHelper<1, 2, 1> {
1815 public:
LIR_HEADER(CompareBigIntDouble)1816 LIR_HEADER(CompareBigIntDouble)
1817
1818 LCompareBigIntDouble(const LAllocation& left, const LAllocation& right,
1819 const LDefinition& temp)
1820 : LCallInstructionHelper(classOpcode) {
1821 setOperand(0, left);
1822 setOperand(1, right);
1823 setTemp(0, temp);
1824 }
1825
left()1826 const LAllocation* left() { return getOperand(0); }
right()1827 const LAllocation* right() { return getOperand(1); }
temp()1828 const LDefinition* temp() { return getTemp(0); }
mir()1829 MCompare* mir() { return mir_->toCompare(); }
1830 };
1831
1832 class LCompareBigIntString : public LCallInstructionHelper<1, 2, 0> {
1833 public:
LIR_HEADER(CompareBigIntString)1834 LIR_HEADER(CompareBigIntString)
1835
1836 LCompareBigIntString(const LAllocation& left, const LAllocation& right)
1837 : LCallInstructionHelper(classOpcode) {
1838 setOperand(0, left);
1839 setOperand(1, right);
1840 }
1841
left()1842 const LAllocation* left() { return getOperand(0); }
right()1843 const LAllocation* right() { return getOperand(1); }
mir()1844 MCompare* mir() { return mir_->toCompare(); }
1845 };
1846
1847 class LBitAndAndBranch : public LControlInstructionHelper<2, 2, 0> {
1848 Assembler::Condition cond_;
1849
1850 public:
LIR_HEADER(BitAndAndBranch)1851 LIR_HEADER(BitAndAndBranch)
1852 LBitAndAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse,
1853 Assembler::Condition cond = Assembler::NonZero)
1854 : LControlInstructionHelper(classOpcode), cond_(cond) {
1855 setSuccessor(0, ifTrue);
1856 setSuccessor(1, ifFalse);
1857 }
1858
ifTrue()1859 MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()1860 MBasicBlock* ifFalse() const { return getSuccessor(1); }
left()1861 const LAllocation* left() { return getOperand(0); }
right()1862 const LAllocation* right() { return getOperand(1); }
cond()1863 Assembler::Condition cond() const {
1864 MOZ_ASSERT(cond_ == Assembler::Zero || cond_ == Assembler::NonZero);
1865 return cond_;
1866 }
1867 };
1868
1869 // Takes a value and tests whether it is null, undefined, or is an object that
1870 // emulates |undefined|, as determined by the JSCLASS_EMULATES_UNDEFINED class
1871 // flag on unwrapped objects. See also js::EmulatesUndefined.
1872 class LIsNullOrLikeUndefinedV : public LInstructionHelper<1, BOX_PIECES, 2> {
1873 public:
LIR_HEADER(IsNullOrLikeUndefinedV)1874 LIR_HEADER(IsNullOrLikeUndefinedV)
1875
1876 LIsNullOrLikeUndefinedV(const LBoxAllocation& value, const LDefinition& temp,
1877 const LDefinition& tempToUnbox)
1878 : LInstructionHelper(classOpcode) {
1879 setBoxOperand(Value, value);
1880 setTemp(0, temp);
1881 setTemp(1, tempToUnbox);
1882 }
1883
1884 static const size_t Value = 0;
1885
mir()1886 MCompare* mir() { return mir_->toCompare(); }
1887
temp()1888 const LDefinition* temp() { return getTemp(0); }
1889
tempToUnbox()1890 const LDefinition* tempToUnbox() { return getTemp(1); }
1891 };
1892
1893 // Takes an object pointer and tests whether it is an object that emulates
1894 // |undefined|, as above.
1895 class LIsNullOrLikeUndefinedT : public LInstructionHelper<1, 1, 0> {
1896 public:
LIR_HEADER(IsNullOrLikeUndefinedT)1897 LIR_HEADER(IsNullOrLikeUndefinedT)
1898
1899 explicit LIsNullOrLikeUndefinedT(const LAllocation& input)
1900 : LInstructionHelper(classOpcode) {
1901 setOperand(0, input);
1902 }
1903
mir()1904 MCompare* mir() { return mir_->toCompare(); }
1905 };
1906
1907 class LIsNullOrLikeUndefinedAndBranchV
1908 : public LControlInstructionHelper<2, BOX_PIECES, 2> {
1909 MCompare* cmpMir_;
1910
1911 public:
LIR_HEADER(IsNullOrLikeUndefinedAndBranchV)1912 LIR_HEADER(IsNullOrLikeUndefinedAndBranchV)
1913
1914 LIsNullOrLikeUndefinedAndBranchV(MCompare* cmpMir, MBasicBlock* ifTrue,
1915 MBasicBlock* ifFalse,
1916 const LBoxAllocation& value,
1917 const LDefinition& temp,
1918 const LDefinition& tempToUnbox)
1919 : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {
1920 setSuccessor(0, ifTrue);
1921 setSuccessor(1, ifFalse);
1922 setBoxOperand(Value, value);
1923 setTemp(0, temp);
1924 setTemp(1, tempToUnbox);
1925 }
1926
1927 static const size_t Value = 0;
1928
ifTrue()1929 MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()1930 MBasicBlock* ifFalse() const { return getSuccessor(1); }
mir()1931 MTest* mir() const { return mir_->toTest(); }
cmpMir()1932 MCompare* cmpMir() const { return cmpMir_; }
temp()1933 const LDefinition* temp() { return getTemp(0); }
tempToUnbox()1934 const LDefinition* tempToUnbox() { return getTemp(1); }
1935 };
1936
1937 class LIsNullOrLikeUndefinedAndBranchT
1938 : public LControlInstructionHelper<2, 1, 1> {
1939 MCompare* cmpMir_;
1940
1941 public:
LIR_HEADER(IsNullOrLikeUndefinedAndBranchT)1942 LIR_HEADER(IsNullOrLikeUndefinedAndBranchT)
1943
1944 LIsNullOrLikeUndefinedAndBranchT(MCompare* cmpMir, const LAllocation& input,
1945 MBasicBlock* ifTrue, MBasicBlock* ifFalse,
1946 const LDefinition& temp)
1947 : LControlInstructionHelper(classOpcode), cmpMir_(cmpMir) {
1948 setOperand(0, input);
1949 setSuccessor(0, ifTrue);
1950 setSuccessor(1, ifFalse);
1951 setTemp(0, temp);
1952 }
1953
ifTrue()1954 MBasicBlock* ifTrue() const { return getSuccessor(0); }
ifFalse()1955 MBasicBlock* ifFalse() const { return getSuccessor(1); }
mir()1956 MTest* mir() const { return mir_->toTest(); }
cmpMir()1957 MCompare* cmpMir() const { return cmpMir_; }
temp()1958 const LDefinition* temp() { return getTemp(0); }
1959 };
1960
1961 class LSameValueDouble : public LInstructionHelper<1, 2, 1> {
1962 public:
LIR_HEADER(SameValueDouble)1963 LIR_HEADER(SameValueDouble)
1964 LSameValueDouble(const LAllocation& left, const LAllocation& right,
1965 const LDefinition& temp)
1966 : LInstructionHelper(classOpcode) {
1967 setOperand(0, left);
1968 setOperand(1, right);
1969 setTemp(0, temp);
1970 }
1971
left()1972 const LAllocation* left() { return getOperand(0); }
right()1973 const LAllocation* right() { return getOperand(1); }
tempFloat()1974 const LDefinition* tempFloat() { return getTemp(0); }
1975 };
1976
1977 class LSameValue : public LInstructionHelper<1, 2 * BOX_PIECES, 0> {
1978 public:
LIR_HEADER(SameValue)1979 LIR_HEADER(SameValue)
1980 LSameValue(const LBoxAllocation& lhs, const LBoxAllocation& rhs)
1981 : LInstructionHelper(classOpcode) {
1982 setBoxOperand(LhsIndex, lhs);
1983 setBoxOperand(RhsIndex, rhs);
1984 }
1985
1986 static const size_t LhsIndex = 0;
1987 static const size_t RhsIndex = BOX_PIECES;
1988 };
1989
1990 // Not operation on an integer.
1991 class LNotI : public LInstructionHelper<1, 1, 0> {
1992 public:
LIR_HEADER(NotI)1993 LIR_HEADER(NotI)
1994
1995 explicit LNotI(const LAllocation& input) : LInstructionHelper(classOpcode) {
1996 setOperand(0, input);
1997 }
1998 };
1999
2000 // Not operation on an int64.
2001 class LNotI64 : public LInstructionHelper<1, INT64_PIECES, 0> {
2002 public:
LIR_HEADER(NotI64)2003 LIR_HEADER(NotI64)
2004
2005 explicit LNotI64(const LInt64Allocation& input)
2006 : LInstructionHelper(classOpcode) {
2007 setInt64Operand(0, input);
2008 }
2009 };
2010
2011 // Not operation on a double.
2012 class LNotD : public LInstructionHelper<1, 1, 0> {
2013 public:
LIR_HEADER(NotD)2014 LIR_HEADER(NotD)
2015
2016 explicit LNotD(const LAllocation& input) : LInstructionHelper(classOpcode) {
2017 setOperand(0, input);
2018 }
2019
mir()2020 MNot* mir() { return mir_->toNot(); }
2021 };
2022
2023 // Not operation on a float32.
2024 class LNotF : public LInstructionHelper<1, 1, 0> {
2025 public:
LIR_HEADER(NotF)2026 LIR_HEADER(NotF)
2027
2028 explicit LNotF(const LAllocation& input) : LInstructionHelper(classOpcode) {
2029 setOperand(0, input);
2030 }
2031
mir()2032 MNot* mir() { return mir_->toNot(); }
2033 };
2034
2035 // Not operation on a BigInt.
2036 class LNotBI : public LInstructionHelper<1, 1, 0> {
2037 public:
LIR_HEADER(NotBI)2038 LIR_HEADER(NotBI)
2039
2040 explicit LNotBI(const LAllocation& input) : LInstructionHelper(classOpcode) {
2041 setOperand(0, input);
2042 }
2043
mir()2044 MNot* mir() { return mir_->toNot(); }
2045 };
2046
2047 // Boolean complement operation on an object.
2048 class LNotO : public LInstructionHelper<1, 1, 0> {
2049 public:
LIR_HEADER(NotO)2050 LIR_HEADER(NotO)
2051
2052 explicit LNotO(const LAllocation& input) : LInstructionHelper(classOpcode) {
2053 setOperand(0, input);
2054 }
2055
mir()2056 MNot* mir() { return mir_->toNot(); }
2057 };
2058
2059 // Boolean complement operation on a value.
2060 class LNotV : public LInstructionHelper<1, BOX_PIECES, 3> {
2061 public:
2062 LIR_HEADER(NotV)
2063
2064 static const size_t Input = 0;
LNotV(const LBoxAllocation & input,const LDefinition & temp0,const LDefinition & temp1,const LDefinition & temp2)2065 LNotV(const LBoxAllocation& input, const LDefinition& temp0,
2066 const LDefinition& temp1, const LDefinition& temp2)
2067 : LInstructionHelper(classOpcode) {
2068 setBoxOperand(Input, input);
2069 setTemp(0, temp0);
2070 setTemp(1, temp1);
2071 setTemp(2, temp2);
2072 }
2073
tempFloat()2074 const LDefinition* tempFloat() { return getTemp(0); }
2075
temp1()2076 const LDefinition* temp1() { return getTemp(1); }
2077
temp2()2078 const LDefinition* temp2() { return getTemp(2); }
2079
mir()2080 MNot* mir() { return mir_->toNot(); }
2081 };
2082
2083 // Bitwise not operation, takes a 32-bit integer as input and returning
2084 // a 32-bit integer result as an output.
2085 class LBitNotI : public LInstructionHelper<1, 1, 0> {
2086 public:
LIR_HEADER(BitNotI)2087 LIR_HEADER(BitNotI)
2088
2089 LBitNotI() : LInstructionHelper(classOpcode) {}
2090 };
2091
2092 // Binary bitwise operation, taking two 32-bit integers as inputs and returning
2093 // a 32-bit integer result as an output.
2094 class LBitOpI : public LInstructionHelper<1, 2, 0> {
2095 JSOp op_;
2096
2097 public:
LIR_HEADER(BitOpI)2098 LIR_HEADER(BitOpI)
2099
2100 explicit LBitOpI(JSOp op) : LInstructionHelper(classOpcode), op_(op) {}
2101
extraName()2102 const char* extraName() const {
2103 if (bitop() == JSOp::Ursh && mir_->toUrsh()->bailoutsDisabled()) {
2104 return "ursh:BailoutsDisabled";
2105 }
2106 return CodeName(op_);
2107 }
2108
bitop()2109 JSOp bitop() const { return op_; }
2110 };
2111
2112 class LBitOpI64 : public LInstructionHelper<INT64_PIECES, 2 * INT64_PIECES, 0> {
2113 JSOp op_;
2114
2115 public:
2116 LIR_HEADER(BitOpI64)
2117
2118 static const size_t Lhs = 0;
2119 static const size_t Rhs = INT64_PIECES;
2120
LBitOpI64(JSOp op)2121 explicit LBitOpI64(JSOp op) : LInstructionHelper(classOpcode), op_(op) {}
2122
extraName()2123 const char* extraName() const { return CodeName(op_); }
2124
bitop()2125 JSOp bitop() const { return op_; }
2126 };
2127
2128 // Shift operation, taking two 32-bit integers as inputs and returning
2129 // a 32-bit integer result as an output.
2130 class LShiftI : public LBinaryMath<0> {
2131 JSOp op_;
2132
2133 public:
LIR_HEADER(ShiftI)2134 LIR_HEADER(ShiftI)
2135
2136 explicit LShiftI(JSOp op) : LBinaryMath(classOpcode), op_(op) {}
2137
bitop()2138 JSOp bitop() { return op_; }
2139
mir()2140 MInstruction* mir() { return mir_->toInstruction(); }
2141
extraName()2142 const char* extraName() const { return CodeName(op_); }
2143 };
2144
2145 class LShiftI64 : public LInstructionHelper<INT64_PIECES, INT64_PIECES + 1, 0> {
2146 JSOp op_;
2147
2148 public:
LIR_HEADER(ShiftI64)2149 LIR_HEADER(ShiftI64)
2150
2151 explicit LShiftI64(JSOp op) : LInstructionHelper(classOpcode), op_(op) {}
2152
2153 static const size_t Lhs = 0;
2154 static const size_t Rhs = INT64_PIECES;
2155
bitop()2156 JSOp bitop() { return op_; }
2157
mir()2158 MInstruction* mir() { return mir_->toInstruction(); }
2159
extraName()2160 const char* extraName() const { return CodeName(op_); }
2161 };
2162
2163 // Sign extension
2164 class LSignExtendInt32 : public LInstructionHelper<1, 1, 0> {
2165 MSignExtendInt32::Mode mode_;
2166
2167 public:
2168 LIR_HEADER(SignExtendInt32);
2169
LSignExtendInt32(const LAllocation & num,MSignExtendInt32::Mode mode)2170 explicit LSignExtendInt32(const LAllocation& num, MSignExtendInt32::Mode mode)
2171 : LInstructionHelper(classOpcode), mode_(mode) {
2172 setOperand(0, num);
2173 }
2174
mode()2175 MSignExtendInt32::Mode mode() { return mode_; }
2176 };
2177
2178 class LSignExtendInt64
2179 : public LInstructionHelper<INT64_PIECES, INT64_PIECES, 0> {
2180 public:
LIR_HEADER(SignExtendInt64)2181 LIR_HEADER(SignExtendInt64)
2182
2183 explicit LSignExtendInt64(const LInt64Allocation& input)
2184 : LInstructionHelper(classOpcode) {
2185 setInt64Operand(0, input);
2186 }
2187
mir()2188 const MSignExtendInt64* mir() const { return mir_->toSignExtendInt64(); }
2189
mode()2190 MSignExtendInt64::Mode mode() const { return mir()->mode(); }
2191 };
2192
2193 class LUrshD : public LBinaryMath<1> {
2194 public:
LIR_HEADER(UrshD)2195 LIR_HEADER(UrshD)
2196
2197 LUrshD(const LAllocation& lhs, const LAllocation& rhs,
2198 const LDefinition& temp)
2199 : LBinaryMath(classOpcode) {
2200 setOperand(0, lhs);
2201 setOperand(1, rhs);
2202 setTemp(0, temp);
2203 }
temp()2204 const LDefinition* temp() { return getTemp(0); }
2205 };
2206
2207 // Returns from the function being compiled (not used in inlined frames). The
2208 // input must be a box.
2209 class LReturn : public LInstructionHelper<0, BOX_PIECES, 0> {
2210 bool isGenerator_;
2211
2212 public:
LIR_HEADER(Return)2213 LIR_HEADER(Return)
2214
2215 explicit LReturn(bool isGenerator)
2216 : LInstructionHelper(classOpcode), isGenerator_(isGenerator) {}
2217
isGenerator()2218 bool isGenerator() { return isGenerator_; }
2219 };
2220
2221 class LThrow : public LCallInstructionHelper<0, BOX_PIECES, 0> {
2222 public:
2223 LIR_HEADER(Throw)
2224
2225 static const size_t Value = 0;
2226
LThrow(const LBoxAllocation & value)2227 explicit LThrow(const LBoxAllocation& value)
2228 : LCallInstructionHelper(classOpcode) {
2229 setBoxOperand(Value, value);
2230 }
2231 };
2232
2233 class LMinMaxBase : public LInstructionHelper<1, 2, 0> {
2234 protected:
LMinMaxBase(LNode::Opcode opcode,const LAllocation & first,const LAllocation & second)2235 LMinMaxBase(LNode::Opcode opcode, const LAllocation& first,
2236 const LAllocation& second)
2237 : LInstructionHelper(opcode) {
2238 setOperand(0, first);
2239 setOperand(1, second);
2240 }
2241
2242 public:
first()2243 const LAllocation* first() { return this->getOperand(0); }
second()2244 const LAllocation* second() { return this->getOperand(1); }
output()2245 const LDefinition* output() { return this->getDef(0); }
mir()2246 MMinMax* mir() const { return mir_->toMinMax(); }
extraName()2247 const char* extraName() const { return mir()->isMax() ? "Max" : "Min"; }
2248 };
2249
2250 class LMinMaxI : public LMinMaxBase {
2251 public:
LIR_HEADER(MinMaxI)2252 LIR_HEADER(MinMaxI)
2253 LMinMaxI(const LAllocation& first, const LAllocation& second)
2254 : LMinMaxBase(classOpcode, first, second) {}
2255 };
2256
2257 class LMinMaxD : public LMinMaxBase {
2258 public:
LIR_HEADER(MinMaxD)2259 LIR_HEADER(MinMaxD)
2260 LMinMaxD(const LAllocation& first, const LAllocation& second)
2261 : LMinMaxBase(classOpcode, first, second) {}
2262 };
2263
2264 class LMinMaxF : public LMinMaxBase {
2265 public:
LIR_HEADER(MinMaxF)2266 LIR_HEADER(MinMaxF)
2267 LMinMaxF(const LAllocation& first, const LAllocation& second)
2268 : LMinMaxBase(classOpcode, first, second) {}
2269 };
2270
2271 class LMinMaxArrayI : public LInstructionHelper<1, 1, 3> {
2272 public:
2273 LIR_HEADER(MinMaxArrayI);
LMinMaxArrayI(const LAllocation & array,const LDefinition & temp0,const LDefinition & temp1,const LDefinition & temp2)2274 LMinMaxArrayI(const LAllocation& array, const LDefinition& temp0,
2275 const LDefinition& temp1, const LDefinition& temp2)
2276 : LInstructionHelper(classOpcode) {
2277 setOperand(0, array);
2278 setTemp(0, temp0);
2279 setTemp(1, temp1);
2280 setTemp(2, temp2);
2281 }
2282
array()2283 const LAllocation* array() { return getOperand(0); }
temp1()2284 const LDefinition* temp1() { return getTemp(0); }
temp2()2285 const LDefinition* temp2() { return getTemp(1); }
temp3()2286 const LDefinition* temp3() { return getTemp(2); }
2287
isMax()2288 bool isMax() const { return mir_->toMinMaxArray()->isMax(); }
2289 };
2290
2291 class LMinMaxArrayD : public LInstructionHelper<1, 1, 3> {
2292 public:
2293 LIR_HEADER(MinMaxArrayD);
LMinMaxArrayD(const LAllocation & array,const LDefinition & floatTemp,const LDefinition & temp1,const LDefinition & temp2)2294 LMinMaxArrayD(const LAllocation& array, const LDefinition& floatTemp,
2295 const LDefinition& temp1, const LDefinition& temp2)
2296 : LInstructionHelper(classOpcode) {
2297 setOperand(0, array);
2298 setTemp(0, floatTemp);
2299 setTemp(1, temp1);
2300 setTemp(2, temp2);
2301 }
2302
array()2303 const LAllocation* array() { return getOperand(0); }
floatTemp()2304 const LDefinition* floatTemp() { return getTemp(0); }
temp1()2305 const LDefinition* temp1() { return getTemp(1); }
temp2()2306 const LDefinition* temp2() { return getTemp(2); }
2307
isMax()2308 bool isMax() const { return mir_->toMinMaxArray()->isMax(); }
2309 };
2310
2311 // Negative of an integer
2312 class LNegI : public LInstructionHelper<1, 1, 0> {
2313 public:
2314 LIR_HEADER(NegI);
LNegI(const LAllocation & num)2315 explicit LNegI(const LAllocation& num) : LInstructionHelper(classOpcode) {
2316 setOperand(0, num);
2317 }
2318 };
2319
2320 // Negative of an int64
2321 class LNegI64 : public LInstructionHelper<INT64_PIECES, INT64_PIECES, 0> {
2322 public:
2323 LIR_HEADER(NegI64);
LNegI64(const LInt64Allocation & num)2324 explicit LNegI64(const LInt64Allocation& num)
2325 : LInstructionHelper(classOpcode) {
2326 setInt64Operand(0, num);
2327 }
2328 };
2329
2330 // Negative of a double.
2331 class LNegD : public LInstructionHelper<1, 1, 0> {
2332 public:
LIR_HEADER(NegD)2333 LIR_HEADER(NegD)
2334 explicit LNegD(const LAllocation& num) : LInstructionHelper(classOpcode) {
2335 setOperand(0, num);
2336 }
2337 };
2338
2339 // Negative of a float32.
2340 class LNegF : public LInstructionHelper<1, 1, 0> {
2341 public:
LIR_HEADER(NegF)2342 LIR_HEADER(NegF)
2343 explicit LNegF(const LAllocation& num) : LInstructionHelper(classOpcode) {
2344 setOperand(0, num);
2345 }
2346 };
2347
2348 // Absolute value of an integer.
2349 class LAbsI : public LInstructionHelper<1, 1, 0> {
2350 public:
LIR_HEADER(AbsI)2351 LIR_HEADER(AbsI)
2352 explicit LAbsI(const LAllocation& num) : LInstructionHelper(classOpcode) {
2353 setOperand(0, num);
2354 }
2355
mir()2356 MAbs* mir() const { return mir_->toAbs(); }
2357 };
2358
2359 // Absolute value of a double.
2360 class LAbsD : public LInstructionHelper<1, 1, 0> {
2361 public:
LIR_HEADER(AbsD)2362 LIR_HEADER(AbsD)
2363 explicit LAbsD(const LAllocation& num) : LInstructionHelper(classOpcode) {
2364 setOperand(0, num);
2365 }
2366 };
2367
2368 // Absolute value of a float32.
2369 class LAbsF : public LInstructionHelper<1, 1, 0> {
2370 public:
LIR_HEADER(AbsF)2371 LIR_HEADER(AbsF)
2372 explicit LAbsF(const LAllocation& num) : LInstructionHelper(classOpcode) {
2373 setOperand(0, num);
2374 }
2375 };
2376
2377 // Copysign for doubles.
2378 class LCopySignD : public LInstructionHelper<1, 2, 2> {
2379 public:
LIR_HEADER(CopySignD)2380 LIR_HEADER(CopySignD)
2381 explicit LCopySignD() : LInstructionHelper(classOpcode) {}
2382 };
2383
2384 // Copysign for float32.
2385 class LCopySignF : public LInstructionHelper<1, 2, 2> {
2386 public:
LIR_HEADER(CopySignF)2387 LIR_HEADER(CopySignF)
2388 explicit LCopySignF() : LInstructionHelper(classOpcode) {}
2389 };
2390
2391 // Count leading zeroes on an int32.
2392 class LClzI : public LInstructionHelper<1, 1, 0> {
2393 public:
LIR_HEADER(ClzI)2394 LIR_HEADER(ClzI)
2395 explicit LClzI(const LAllocation& num) : LInstructionHelper(classOpcode) {
2396 setOperand(0, num);
2397 }
2398
mir()2399 MClz* mir() const { return mir_->toClz(); }
2400 };
2401
2402 // Count leading zeroes on an int64.
2403 class LClzI64 : public LInstructionHelper<INT64_PIECES, INT64_PIECES, 0> {
2404 public:
LIR_HEADER(ClzI64)2405 LIR_HEADER(ClzI64)
2406 explicit LClzI64(const LInt64Allocation& num)
2407 : LInstructionHelper(classOpcode) {
2408 setInt64Operand(0, num);
2409 }
2410
mir()2411 MClz* mir() const { return mir_->toClz(); }
2412 };
2413
2414 // Count trailing zeroes on an int32.
2415 class LCtzI : public LInstructionHelper<1, 1, 0> {
2416 public:
LIR_HEADER(CtzI)2417 LIR_HEADER(CtzI)
2418 explicit LCtzI(const LAllocation& num) : LInstructionHelper(classOpcode) {
2419 setOperand(0, num);
2420 }
2421
mir()2422 MCtz* mir() const { return mir_->toCtz(); }
2423 };
2424
2425 // Count trailing zeroes on an int64.
2426 class LCtzI64 : public LInstructionHelper<INT64_PIECES, INT64_PIECES, 0> {
2427 public:
LIR_HEADER(CtzI64)2428 LIR_HEADER(CtzI64)
2429 explicit LCtzI64(const LInt64Allocation& num)
2430 : LInstructionHelper(classOpcode) {
2431 setInt64Operand(0, num);
2432 }
2433
mir()2434 MCtz* mir() const { return mir_->toCtz(); }
2435 };
2436
2437 // Count population on an int32.
2438 class LPopcntI : public LInstructionHelper<1, 1, 1> {
2439 public:
LIR_HEADER(PopcntI)2440 LIR_HEADER(PopcntI)
2441 explicit LPopcntI(const LAllocation& num, const LDefinition& temp)
2442 : LInstructionHelper(classOpcode) {
2443 setOperand(0, num);
2444 setTemp(0, temp);
2445 }
2446
mir()2447 MPopcnt* mir() const { return mir_->toPopcnt(); }
2448
temp()2449 const LDefinition* temp() { return getTemp(0); }
2450 };
2451
2452 // Count population on an int64.
2453 class LPopcntI64 : public LInstructionHelper<INT64_PIECES, INT64_PIECES, 1> {
2454 public:
LIR_HEADER(PopcntI64)2455 LIR_HEADER(PopcntI64)
2456 explicit LPopcntI64(const LInt64Allocation& num, const LDefinition& temp)
2457 : LInstructionHelper(classOpcode) {
2458 setInt64Operand(0, num);
2459 setTemp(0, temp);
2460 }
2461
mir()2462 MPopcnt* mir() const { return mir_->toPopcnt(); }
2463 };
2464
2465 // Square root of a double.
2466 class LSqrtD : public LInstructionHelper<1, 1, 0> {
2467 public:
LIR_HEADER(SqrtD)2468 LIR_HEADER(SqrtD)
2469 explicit LSqrtD(const LAllocation& num) : LInstructionHelper(classOpcode) {
2470 setOperand(0, num);
2471 }
2472 };
2473
2474 // Square root of a float32.
2475 class LSqrtF : public LInstructionHelper<1, 1, 0> {
2476 public:
LIR_HEADER(SqrtF)2477 LIR_HEADER(SqrtF)
2478 explicit LSqrtF(const LAllocation& num) : LInstructionHelper(classOpcode) {
2479 setOperand(0, num);
2480 }
2481 };
2482
2483 class LAtan2D : public LCallInstructionHelper<1, 2, 1> {
2484 public:
LIR_HEADER(Atan2D)2485 LIR_HEADER(Atan2D)
2486 LAtan2D(const LAllocation& y, const LAllocation& x, const LDefinition& temp)
2487 : LCallInstructionHelper(classOpcode) {
2488 setOperand(0, y);
2489 setOperand(1, x);
2490 setTemp(0, temp);
2491 }
2492
y()2493 const LAllocation* y() { return getOperand(0); }
2494
x()2495 const LAllocation* x() { return getOperand(1); }
2496
temp()2497 const LDefinition* temp() { return getTemp(0); }
2498
output()2499 const LDefinition* output() { return getDef(0); }
2500 };
2501
2502 class LHypot : public LCallInstructionHelper<1, 4, 1> {
2503 uint32_t numOperands_;
2504
2505 public:
LIR_HEADER(Hypot)2506 LIR_HEADER(Hypot)
2507 LHypot(const LAllocation& x, const LAllocation& y, const LDefinition& temp)
2508 : LCallInstructionHelper(classOpcode), numOperands_(2) {
2509 setOperand(0, x);
2510 setOperand(1, y);
2511 setTemp(0, temp);
2512 }
2513
LHypot(const LAllocation & x,const LAllocation & y,const LAllocation & z,const LDefinition & temp)2514 LHypot(const LAllocation& x, const LAllocation& y, const LAllocation& z,
2515 const LDefinition& temp)
2516 : LCallInstructionHelper(classOpcode), numOperands_(3) {
2517 setOperand(0, x);
2518 setOperand(1, y);
2519 setOperand(2, z);
2520 setTemp(0, temp);
2521 }
2522
LHypot(const LAllocation & x,const LAllocation & y,const LAllocation & z,const LAllocation & w,const LDefinition & temp)2523 LHypot(const LAllocation& x, const LAllocation& y, const LAllocation& z,
2524 const LAllocation& w, const LDefinition& temp)
2525 : LCallInstructionHelper(classOpcode), numOperands_(4) {
2526 setOperand(0, x);
2527 setOperand(1, y);
2528 setOperand(2, z);
2529 setOperand(3, w);
2530 setTemp(0, temp);
2531 }
2532
numArgs()2533 uint32_t numArgs() const { return numOperands_; }
2534
x()2535 const LAllocation* x() { return getOperand(0); }
2536
y()2537 const LAllocation* y() { return getOperand(1); }
2538
temp()2539 const LDefinition* temp() { return getTemp(0); }
2540
output()2541 const LDefinition* output() { return getDef(0); }
2542 };
2543
2544 // Double raised to an integer power.
2545 class LPowI : public LCallInstructionHelper<1, 2, 1> {
2546 public:
LIR_HEADER(PowI)2547 LIR_HEADER(PowI)
2548 LPowI(const LAllocation& value, const LAllocation& power,
2549 const LDefinition& temp)
2550 : LCallInstructionHelper(classOpcode) {
2551 setOperand(0, value);
2552 setOperand(1, power);
2553 setTemp(0, temp);
2554 }
2555
value()2556 const LAllocation* value() { return getOperand(0); }
power()2557 const LAllocation* power() { return getOperand(1); }
temp()2558 const LDefinition* temp() { return getTemp(0); }
2559 };
2560
2561 // Integer raised to an integer power.
2562 class LPowII : public LInstructionHelper<1, 2, 2> {
2563 public:
LIR_HEADER(PowII)2564 LIR_HEADER(PowII)
2565 LPowII(const LAllocation& value, const LAllocation& power,
2566 const LDefinition& temp1, const LDefinition& temp2)
2567 : LInstructionHelper(classOpcode) {
2568 setOperand(0, value);
2569 setOperand(1, power);
2570 setTemp(0, temp1);
2571 setTemp(1, temp2);
2572 }
2573
value()2574 const LAllocation* value() { return getOperand(0); }
power()2575 const LAllocation* power() { return getOperand(1); }
temp1()2576 const LDefinition* temp1() { return getTemp(0); }
temp2()2577 const LDefinition* temp2() { return getTemp(1); }
2578
mir()2579 MPow* mir() const { return mir_->toPow(); }
2580 };
2581
2582 // Double raised to a double power.
2583 class LPowD : public LCallInstructionHelper<1, 2, 1> {
2584 public:
LIR_HEADER(PowD)2585 LIR_HEADER(PowD)
2586 LPowD(const LAllocation& value, const LAllocation& power,
2587 const LDefinition& temp)
2588 : LCallInstructionHelper(classOpcode) {
2589 setOperand(0, value);
2590 setOperand(1, power);
2591 setTemp(0, temp);
2592 }
2593
value()2594 const LAllocation* value() { return getOperand(0); }
power()2595 const LAllocation* power() { return getOperand(1); }
temp()2596 const LDefinition* temp() { return getTemp(0); }
2597 };
2598
2599 // Constant of a power of two raised to an integer power.
2600 class LPowOfTwoI : public LInstructionHelper<1, 1, 0> {
2601 uint32_t base_;
2602
2603 public:
LIR_HEADER(PowOfTwoI)2604 LIR_HEADER(PowOfTwoI)
2605 LPowOfTwoI(uint32_t base, const LAllocation& power)
2606 : LInstructionHelper(classOpcode), base_(base) {
2607 setOperand(0, power);
2608 }
2609
base()2610 uint32_t base() const { return base_; }
power()2611 const LAllocation* power() { return getOperand(0); }
2612 };
2613
2614 // Sign value of an integer.
2615 class LSignI : public LInstructionHelper<1, 1, 0> {
2616 public:
LIR_HEADER(SignI)2617 LIR_HEADER(SignI)
2618 explicit LSignI(const LAllocation& input) : LInstructionHelper(classOpcode) {
2619 setOperand(0, input);
2620 }
2621 };
2622
2623 // Sign value of a double.
2624 class LSignD : public LInstructionHelper<1, 1, 0> {
2625 public:
LIR_HEADER(SignD)2626 LIR_HEADER(SignD)
2627 explicit LSignD(const LAllocation& input) : LInstructionHelper(classOpcode) {
2628 setOperand(0, input);
2629 }
2630 };
2631
2632 // Sign value of a double with expected int32 result.
2633 class LSignDI : public LInstructionHelper<1, 1, 1> {
2634 public:
LIR_HEADER(SignDI)2635 LIR_HEADER(SignDI)
2636 explicit LSignDI(const LAllocation& input, const LDefinition& temp)
2637 : LInstructionHelper(classOpcode) {
2638 setOperand(0, input);
2639 setTemp(0, temp);
2640 }
2641
temp()2642 const LDefinition* temp() { return getTemp(0); }
2643 };
2644
2645 class LMathFunctionD : public LCallInstructionHelper<1, 1, 1> {
2646 public:
LIR_HEADER(MathFunctionD)2647 LIR_HEADER(MathFunctionD)
2648 LMathFunctionD(const LAllocation& input, const LDefinition& temp)
2649 : LCallInstructionHelper(classOpcode) {
2650 setOperand(0, input);
2651 setTemp(0, temp);
2652 }
2653
temp()2654 const LDefinition* temp() { return getTemp(0); }
mir()2655 MMathFunction* mir() const { return mir_->toMathFunction(); }
extraName()2656 const char* extraName() const {
2657 return MMathFunction::FunctionName(mir()->function());
2658 }
2659 };
2660
2661 class LMathFunctionF : public LCallInstructionHelper<1, 1, 1> {
2662 public:
LIR_HEADER(MathFunctionF)2663 LIR_HEADER(MathFunctionF)
2664 LMathFunctionF(const LAllocation& input, const LDefinition& temp)
2665 : LCallInstructionHelper(classOpcode) {
2666 setOperand(0, input);
2667 setTemp(0, temp);
2668 }
2669
temp()2670 const LDefinition* temp() { return getTemp(0); }
mir()2671 MMathFunction* mir() const { return mir_->toMathFunction(); }
extraName()2672 const char* extraName() const {
2673 return MMathFunction::FunctionName(mir()->function());
2674 }
2675 };
2676
2677 // Adds two integers, returning an integer value.
2678 class LAddI : public LBinaryMath<0> {
2679 bool recoversInput_;
2680
2681 public:
LIR_HEADER(AddI)2682 LIR_HEADER(AddI)
2683
2684 LAddI() : LBinaryMath(classOpcode), recoversInput_(false) {}
2685
extraName()2686 const char* extraName() const {
2687 return snapshot() ? "OverflowCheck" : nullptr;
2688 }
2689
recoversInput()2690 bool recoversInput() const { return recoversInput_; }
setRecoversInput()2691 void setRecoversInput() { recoversInput_ = true; }
2692
mir()2693 MAdd* mir() const { return mir_->toAdd(); }
2694 };
2695
2696 class LAddI64 : public LInstructionHelper<INT64_PIECES, 2 * INT64_PIECES, 0> {
2697 public:
LIR_HEADER(AddI64)2698 LIR_HEADER(AddI64)
2699
2700 LAddI64() : LInstructionHelper(classOpcode) {}
2701
2702 static const size_t Lhs = 0;
2703 static const size_t Rhs = INT64_PIECES;
2704 };
2705
2706 // Subtracts two integers, returning an integer value.
2707 class LSubI : public LBinaryMath<0> {
2708 bool recoversInput_;
2709
2710 public:
LIR_HEADER(SubI)2711 LIR_HEADER(SubI)
2712
2713 LSubI() : LBinaryMath(classOpcode), recoversInput_(false) {}
2714
extraName()2715 const char* extraName() const {
2716 return snapshot() ? "OverflowCheck" : nullptr;
2717 }
2718
recoversInput()2719 bool recoversInput() const { return recoversInput_; }
setRecoversInput()2720 void setRecoversInput() { recoversInput_ = true; }
mir()2721 MSub* mir() const { return mir_->toSub(); }
2722 };
2723
recoversInput()2724 inline bool LNode::recoversInput() const {
2725 switch (op()) {
2726 case Opcode::AddI:
2727 return toAddI()->recoversInput();
2728 case Opcode::SubI:
2729 return toSubI()->recoversInput();
2730 default:
2731 return false;
2732 }
2733 }
2734
2735 class LSubI64 : public LInstructionHelper<INT64_PIECES, 2 * INT64_PIECES, 0> {
2736 public:
2737 LIR_HEADER(SubI64)
2738
2739 static const size_t Lhs = 0;
2740 static const size_t Rhs = INT64_PIECES;
2741
LSubI64()2742 LSubI64() : LInstructionHelper(classOpcode) {}
2743 };
2744
2745 class LMulI64 : public LInstructionHelper<INT64_PIECES, 2 * INT64_PIECES, 1> {
2746 public:
LIR_HEADER(MulI64)2747 LIR_HEADER(MulI64)
2748
2749 explicit LMulI64() : LInstructionHelper(classOpcode) {
2750 setTemp(0, LDefinition());
2751 }
2752
temp()2753 const LDefinition* temp() { return getTemp(0); }
2754
2755 static const size_t Lhs = 0;
2756 static const size_t Rhs = INT64_PIECES;
2757 };
2758
2759 // Performs an add, sub, mul, or div on two double values.
2760 class LMathD : public LBinaryMath<0> {
2761 JSOp jsop_;
2762
2763 public:
LIR_HEADER(MathD)2764 LIR_HEADER(MathD)
2765
2766 explicit LMathD(JSOp jsop) : LBinaryMath(classOpcode), jsop_(jsop) {}
2767
jsop()2768 JSOp jsop() const { return jsop_; }
2769
extraName()2770 const char* extraName() const { return CodeName(jsop_); }
2771 };
2772
2773 // Performs an add, sub, mul, or div on two double values.
2774 class LMathF : public LBinaryMath<0> {
2775 JSOp jsop_;
2776
2777 public:
LIR_HEADER(MathF)2778 LIR_HEADER(MathF)
2779
2780 explicit LMathF(JSOp jsop) : LBinaryMath(classOpcode), jsop_(jsop) {}
2781
jsop()2782 JSOp jsop() const { return jsop_; }
2783
extraName()2784 const char* extraName() const { return CodeName(jsop_); }
2785 };
2786
2787 class LModD : public LBinaryMath<1> {
2788 public:
LIR_HEADER(ModD)2789 LIR_HEADER(ModD)
2790
2791 LModD(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp)
2792 : LBinaryMath(classOpcode) {
2793 setOperand(0, lhs);
2794 setOperand(1, rhs);
2795 setTemp(0, temp);
2796 setIsCall();
2797 }
temp()2798 const LDefinition* temp() { return getTemp(0); }
mir()2799 MMod* mir() const { return mir_->toMod(); }
2800 };
2801
2802 class LModPowTwoD : public LInstructionHelper<1, 1, 0> {
2803 const uint32_t divisor_;
2804
2805 public:
LIR_HEADER(ModPowTwoD)2806 LIR_HEADER(ModPowTwoD)
2807
2808 LModPowTwoD(const LAllocation& lhs, uint32_t divisor)
2809 : LInstructionHelper(classOpcode), divisor_(divisor) {
2810 setOperand(0, lhs);
2811 }
2812
divisor()2813 uint32_t divisor() const { return divisor_; }
lhs()2814 const LAllocation* lhs() { return getOperand(0); }
mir()2815 MMod* mir() const { return mir_->toMod(); }
2816 };
2817
2818 class LWasmBuiltinModD : public LInstructionHelper<1, 3, 0> {
2819 static const size_t LhsIndex = 0;
2820 static const size_t RhsIndex = 1;
2821 static const size_t TlsIndex = 2;
2822
2823 public:
LIR_HEADER(WasmBuiltinModD)2824 LIR_HEADER(WasmBuiltinModD)
2825
2826 LWasmBuiltinModD(const LAllocation& lhs, const LAllocation& rhs,
2827 const LAllocation& tls)
2828 : LInstructionHelper(classOpcode) {
2829 setOperand(LhsIndex, lhs);
2830 setOperand(RhsIndex, rhs);
2831 setOperand(TlsIndex, tls);
2832 setIsCall();
2833 }
2834
lhs()2835 const LAllocation* lhs() { return this->getOperand(LhsIndex); }
rhs()2836 const LAllocation* rhs() { return this->getOperand(RhsIndex); }
tls()2837 const LAllocation* tls() { return this->getOperand(TlsIndex); }
2838
mir()2839 MWasmBuiltinModD* mir() const { return mir_->toWasmBuiltinModD(); }
2840 };
2841
2842 class LBigIntAdd : public LBinaryMath<2> {
2843 public:
LIR_HEADER(BigIntAdd)2844 LIR_HEADER(BigIntAdd)
2845
2846 LBigIntAdd(const LAllocation& lhs, const LAllocation& rhs,
2847 const LDefinition& temp1, const LDefinition& temp2)
2848 : LBinaryMath(classOpcode) {
2849 setOperand(0, lhs);
2850 setOperand(1, rhs);
2851 setTemp(0, temp1);
2852 setTemp(1, temp2);
2853 }
2854
temp1()2855 const LDefinition* temp1() { return getTemp(0); }
temp2()2856 const LDefinition* temp2() { return getTemp(1); }
2857 };
2858
2859 class LBigIntSub : public LBinaryMath<2> {
2860 public:
LIR_HEADER(BigIntSub)2861 LIR_HEADER(BigIntSub)
2862
2863 LBigIntSub(const LAllocation& lhs, const LAllocation& rhs,
2864 const LDefinition& temp1, const LDefinition& temp2)
2865 : LBinaryMath(classOpcode) {
2866 setOperand(0, lhs);
2867 setOperand(1, rhs);
2868 setTemp(0, temp1);
2869 setTemp(1, temp2);
2870 }
2871
temp1()2872 const LDefinition* temp1() { return getTemp(0); }
temp2()2873 const LDefinition* temp2() { return getTemp(1); }
2874 };
2875
2876 class LBigIntMul : public LBinaryMath<2> {
2877 public:
LIR_HEADER(BigIntMul)2878 LIR_HEADER(BigIntMul)
2879
2880 LBigIntMul(const LAllocation& lhs, const LAllocation& rhs,
2881 const LDefinition& temp1, const LDefinition& temp2)
2882 : LBinaryMath(classOpcode) {
2883 setOperand(0, lhs);
2884 setOperand(1, rhs);
2885 setTemp(0, temp1);
2886 setTemp(1, temp2);
2887 }
2888
temp1()2889 const LDefinition* temp1() { return getTemp(0); }
temp2()2890 const LDefinition* temp2() { return getTemp(1); }
2891 };
2892
2893 class LBigIntDiv : public LBinaryMath<2> {
2894 public:
LIR_HEADER(BigIntDiv)2895 LIR_HEADER(BigIntDiv)
2896
2897 LBigIntDiv(const LAllocation& lhs, const LAllocation& rhs,
2898 const LDefinition& temp1, const LDefinition& temp2)
2899 : LBinaryMath(classOpcode) {
2900 setOperand(0, lhs);
2901 setOperand(1, rhs);
2902 setTemp(0, temp1);
2903 setTemp(1, temp2);
2904 }
2905
temp1()2906 const LDefinition* temp1() { return getTemp(0); }
temp2()2907 const LDefinition* temp2() { return getTemp(1); }
2908
mir()2909 const MBigIntDiv* mir() const { return mirRaw()->toBigIntDiv(); }
2910 };
2911
2912 class LBigIntMod : public LBinaryMath<2> {
2913 public:
LIR_HEADER(BigIntMod)2914 LIR_HEADER(BigIntMod)
2915
2916 LBigIntMod(const LAllocation& lhs, const LAllocation& rhs,
2917 const LDefinition& temp1, const LDefinition& temp2)
2918 : LBinaryMath(classOpcode) {
2919 setOperand(0, lhs);
2920 setOperand(1, rhs);
2921 setTemp(0, temp1);
2922 setTemp(1, temp2);
2923 }
2924
temp1()2925 const LDefinition* temp1() { return getTemp(0); }
temp2()2926 const LDefinition* temp2() { return getTemp(1); }
2927
mir()2928 const MBigIntMod* mir() const { return mirRaw()->toBigIntMod(); }
2929 };
2930
2931 class LBigIntPow : public LBinaryMath<2> {
2932 public:
LIR_HEADER(BigIntPow)2933 LIR_HEADER(BigIntPow)
2934
2935 LBigIntPow(const LAllocation& lhs, const LAllocation& rhs,
2936 const LDefinition& temp1, const LDefinition& temp2)
2937 : LBinaryMath(classOpcode) {
2938 setOperand(0, lhs);
2939 setOperand(1, rhs);
2940 setTemp(0, temp1);
2941 setTemp(1, temp2);
2942 }
2943
temp1()2944 const LDefinition* temp1() { return getTemp(0); }
temp2()2945 const LDefinition* temp2() { return getTemp(1); }
2946
mir()2947 const MBigIntPow* mir() const { return mirRaw()->toBigIntPow(); }
2948 };
2949
2950 class LBigIntBitAnd : public LBinaryMath<2> {
2951 public:
LIR_HEADER(BigIntBitAnd)2952 LIR_HEADER(BigIntBitAnd)
2953
2954 LBigIntBitAnd(const LAllocation& lhs, const LAllocation& rhs,
2955 const LDefinition& temp1, const LDefinition& temp2)
2956 : LBinaryMath(classOpcode) {
2957 setOperand(0, lhs);
2958 setOperand(1, rhs);
2959 setTemp(0, temp1);
2960 setTemp(1, temp2);
2961 }
2962
temp1()2963 const LDefinition* temp1() { return getTemp(0); }
temp2()2964 const LDefinition* temp2() { return getTemp(1); }
2965 };
2966
2967 class LBigIntBitOr : public LBinaryMath<2> {
2968 public:
LIR_HEADER(BigIntBitOr)2969 LIR_HEADER(BigIntBitOr)
2970
2971 LBigIntBitOr(const LAllocation& lhs, const LAllocation& rhs,
2972 const LDefinition& temp1, const LDefinition& temp2)
2973 : LBinaryMath(classOpcode) {
2974 setOperand(0, lhs);
2975 setOperand(1, rhs);
2976 setTemp(0, temp1);
2977 setTemp(1, temp2);
2978 }
2979
temp1()2980 const LDefinition* temp1() { return getTemp(0); }
temp2()2981 const LDefinition* temp2() { return getTemp(1); }
2982 };
2983
2984 class LBigIntBitXor : public LBinaryMath<2> {
2985 public:
LIR_HEADER(BigIntBitXor)2986 LIR_HEADER(BigIntBitXor)
2987
2988 LBigIntBitXor(const LAllocation& lhs, const LAllocation& rhs,
2989 const LDefinition& temp1, const LDefinition& temp2)
2990 : LBinaryMath(classOpcode) {
2991 setOperand(0, lhs);
2992 setOperand(1, rhs);
2993 setTemp(0, temp1);
2994 setTemp(1, temp2);
2995 }
2996
temp1()2997 const LDefinition* temp1() { return getTemp(0); }
temp2()2998 const LDefinition* temp2() { return getTemp(1); }
2999 };
3000
3001 class LBigIntLsh : public LBinaryMath<3> {
3002 public:
LIR_HEADER(BigIntLsh)3003 LIR_HEADER(BigIntLsh)
3004
3005 LBigIntLsh(const LAllocation& lhs, const LAllocation& rhs,
3006 const LDefinition& temp1, const LDefinition& temp2,
3007 const LDefinition& temp3)
3008 : LBinaryMath(classOpcode) {
3009 setOperand(0, lhs);
3010 setOperand(1, rhs);
3011 setTemp(0, temp1);
3012 setTemp(1, temp2);
3013 setTemp(2, temp3);
3014 }
3015
temp1()3016 const LDefinition* temp1() { return getTemp(0); }
temp2()3017 const LDefinition* temp2() { return getTemp(1); }
temp3()3018 const LDefinition* temp3() { return getTemp(2); }
3019 };
3020
3021 class LBigIntRsh : public LBinaryMath<3> {
3022 public:
LIR_HEADER(BigIntRsh)3023 LIR_HEADER(BigIntRsh)
3024
3025 LBigIntRsh(const LAllocation& lhs, const LAllocation& rhs,
3026 const LDefinition& temp1, const LDefinition& temp2,
3027 const LDefinition& temp3)
3028 : LBinaryMath(classOpcode) {
3029 setOperand(0, lhs);
3030 setOperand(1, rhs);
3031 setTemp(0, temp1);
3032 setTemp(1, temp2);
3033 setTemp(2, temp3);
3034 }
3035
temp1()3036 const LDefinition* temp1() { return getTemp(0); }
temp2()3037 const LDefinition* temp2() { return getTemp(1); }
temp3()3038 const LDefinition* temp3() { return getTemp(2); }
3039 };
3040
3041 class LBigIntIncrement : public LUnaryMath<2> {
3042 public:
LIR_HEADER(BigIntIncrement)3043 LIR_HEADER(BigIntIncrement)
3044
3045 LBigIntIncrement(const LAllocation& input, const LDefinition& temp1,
3046 const LDefinition& temp2)
3047 : LUnaryMath(classOpcode) {
3048 setOperand(0, input);
3049 setTemp(0, temp1);
3050 setTemp(1, temp2);
3051 }
3052
temp1()3053 const LDefinition* temp1() { return getTemp(0); }
temp2()3054 const LDefinition* temp2() { return getTemp(1); }
3055 };
3056
3057 class LBigIntDecrement : public LUnaryMath<2> {
3058 public:
LIR_HEADER(BigIntDecrement)3059 LIR_HEADER(BigIntDecrement)
3060
3061 LBigIntDecrement(const LAllocation& input, const LDefinition& temp1,
3062 const LDefinition& temp2)
3063 : LUnaryMath(classOpcode) {
3064 setOperand(0, input);
3065 setTemp(0, temp1);
3066 setTemp(1, temp2);
3067 }
3068
temp1()3069 const LDefinition* temp1() { return getTemp(0); }
temp2()3070 const LDefinition* temp2() { return getTemp(1); }
3071 };
3072
3073 class LBigIntNegate : public LUnaryMath<1> {
3074 public:
LIR_HEADER(BigIntNegate)3075 LIR_HEADER(BigIntNegate)
3076
3077 LBigIntNegate(const LAllocation& input, const LDefinition& temp)
3078 : LUnaryMath(classOpcode) {
3079 setOperand(0, input);
3080 setTemp(0, temp);
3081 }
3082
temp()3083 const LDefinition* temp() { return getTemp(0); }
3084 };
3085
3086 class LBigIntBitNot : public LUnaryMath<2> {
3087 public:
LIR_HEADER(BigIntBitNot)3088 LIR_HEADER(BigIntBitNot)
3089
3090 LBigIntBitNot(const LAllocation& input, const LDefinition& temp1,
3091 const LDefinition& temp2)
3092 : LUnaryMath(classOpcode) {
3093 setOperand(0, input);
3094 setTemp(0, temp1);
3095 setTemp(1, temp2);
3096 }
3097
temp1()3098 const LDefinition* temp1() { return getTemp(0); }
temp2()3099 const LDefinition* temp2() { return getTemp(1); }
3100 };
3101
3102 // Adds two string, returning a string.
3103 class LConcat : public LInstructionHelper<1, 2, 5> {
3104 public:
LIR_HEADER(Concat)3105 LIR_HEADER(Concat)
3106
3107 LConcat(const LAllocation& lhs, const LAllocation& rhs,
3108 const LDefinition& temp1, const LDefinition& temp2,
3109 const LDefinition& temp3, const LDefinition& temp4,
3110 const LDefinition& temp5)
3111 : LInstructionHelper(classOpcode) {
3112 setOperand(0, lhs);
3113 setOperand(1, rhs);
3114 setTemp(0, temp1);
3115 setTemp(1, temp2);
3116 setTemp(2, temp3);
3117 setTemp(3, temp4);
3118 setTemp(4, temp5);
3119 }
3120
lhs()3121 const LAllocation* lhs() { return this->getOperand(0); }
rhs()3122 const LAllocation* rhs() { return this->getOperand(1); }
temp1()3123 const LDefinition* temp1() { return this->getTemp(0); }
temp2()3124 const LDefinition* temp2() { return this->getTemp(1); }
temp3()3125 const LDefinition* temp3() { return this->getTemp(2); }
temp4()3126 const LDefinition* temp4() { return this->getTemp(3); }
temp5()3127 const LDefinition* temp5() { return this->getTemp(4); }
3128 };
3129
3130 // Get uint16 character code from a string.
3131 class LCharCodeAt : public LInstructionHelper<1, 2, 1> {
3132 public:
LIR_HEADER(CharCodeAt)3133 LIR_HEADER(CharCodeAt)
3134
3135 LCharCodeAt(const LAllocation& str, const LAllocation& index,
3136 const LDefinition& temp)
3137 : LInstructionHelper(classOpcode) {
3138 setOperand(0, str);
3139 setOperand(1, index);
3140 setTemp(0, temp);
3141 }
3142
str()3143 const LAllocation* str() { return this->getOperand(0); }
index()3144 const LAllocation* index() { return this->getOperand(1); }
temp()3145 const LDefinition* temp() { return getTemp(0); }
3146 };
3147
3148 // Convert uint16 character code to a string.
3149 class LFromCharCode : public LInstructionHelper<1, 1, 0> {
3150 public:
LIR_HEADER(FromCharCode)3151 LIR_HEADER(FromCharCode)
3152
3153 explicit LFromCharCode(const LAllocation& code)
3154 : LInstructionHelper(classOpcode) {
3155 setOperand(0, code);
3156 }
3157
code()3158 const LAllocation* code() { return this->getOperand(0); }
3159 };
3160
3161 // Convert uint32 code point to a string.
3162 class LFromCodePoint : public LInstructionHelper<1, 1, 2> {
3163 public:
LIR_HEADER(FromCodePoint)3164 LIR_HEADER(FromCodePoint)
3165
3166 explicit LFromCodePoint(const LAllocation& codePoint,
3167 const LDefinition& temp1, const LDefinition& temp2)
3168 : LInstructionHelper(classOpcode) {
3169 setOperand(0, codePoint);
3170 setTemp(0, temp1);
3171 setTemp(1, temp2);
3172 }
3173
codePoint()3174 const LAllocation* codePoint() { return this->getOperand(0); }
3175
temp1()3176 const LDefinition* temp1() { return this->getTemp(0); }
3177
temp2()3178 const LDefinition* temp2() { return this->getTemp(1); }
3179 };
3180
3181 // Calls the ToLowerCase or ToUpperCase case conversion function.
3182 class LStringConvertCase : public LCallInstructionHelper<1, 1, 0> {
3183 public:
LIR_HEADER(StringConvertCase)3184 LIR_HEADER(StringConvertCase)
3185
3186 explicit LStringConvertCase(const LAllocation& string)
3187 : LCallInstructionHelper(classOpcode) {
3188 setOperand(0, string);
3189 }
3190
mir()3191 const MStringConvertCase* mir() const { return mir_->toStringConvertCase(); }
3192
string()3193 const LAllocation* string() { return this->getOperand(0); }
3194 };
3195
3196 class LStringSplit : public LCallInstructionHelper<1, 2, 0> {
3197 public:
LIR_HEADER(StringSplit)3198 LIR_HEADER(StringSplit)
3199
3200 LStringSplit(const LAllocation& string, const LAllocation& separator)
3201 : LCallInstructionHelper(classOpcode) {
3202 setOperand(0, string);
3203 setOperand(1, separator);
3204 }
string()3205 const LAllocation* string() { return getOperand(0); }
separator()3206 const LAllocation* separator() { return getOperand(1); }
mir()3207 const MStringSplit* mir() const { return mir_->toStringSplit(); }
3208 };
3209
3210 class LSubstr : public LInstructionHelper<1, 3, 3> {
3211 public:
LIR_HEADER(Substr)3212 LIR_HEADER(Substr)
3213
3214 LSubstr(const LAllocation& string, const LAllocation& begin,
3215 const LAllocation& length, const LDefinition& temp,
3216 const LDefinition& temp2, const LDefinition& temp3)
3217 : LInstructionHelper(classOpcode) {
3218 setOperand(0, string);
3219 setOperand(1, begin);
3220 setOperand(2, length);
3221 setTemp(0, temp);
3222 setTemp(1, temp2);
3223 setTemp(2, temp3);
3224 }
string()3225 const LAllocation* string() { return getOperand(0); }
begin()3226 const LAllocation* begin() { return getOperand(1); }
length()3227 const LAllocation* length() { return getOperand(2); }
temp()3228 const LDefinition* temp() { return getTemp(0); }
temp2()3229 const LDefinition* temp2() { return getTemp(1); }
temp3()3230 const LDefinition* temp3() { return getTemp(2); }
mir()3231 const MStringSplit* mir() const { return mir_->toStringSplit(); }
3232 };
3233
3234 // Convert a 32-bit integer to a double.
3235 class LInt32ToDouble : public LInstructionHelper<1, 1, 0> {
3236 public:
LIR_HEADER(Int32ToDouble)3237 LIR_HEADER(Int32ToDouble)
3238
3239 explicit LInt32ToDouble(const LAllocation& input)
3240 : LInstructionHelper(classOpcode) {
3241 setOperand(0, input);
3242 }
3243 };
3244
3245 // Convert a 32-bit float to a double.
3246 class LFloat32ToDouble : public LInstructionHelper<1, 1, 0> {
3247 public:
LIR_HEADER(Float32ToDouble)3248 LIR_HEADER(Float32ToDouble)
3249
3250 explicit LFloat32ToDouble(const LAllocation& input)
3251 : LInstructionHelper(classOpcode) {
3252 setOperand(0, input);
3253 }
3254 };
3255
3256 // Convert a double to a 32-bit float.
3257 class LDoubleToFloat32 : public LInstructionHelper<1, 1, 0> {
3258 public:
LIR_HEADER(DoubleToFloat32)3259 LIR_HEADER(DoubleToFloat32)
3260
3261 explicit LDoubleToFloat32(const LAllocation& input)
3262 : LInstructionHelper(classOpcode) {
3263 setOperand(0, input);
3264 }
3265 };
3266
3267 // Convert a 32-bit integer to a float32.
3268 class LInt32ToFloat32 : public LInstructionHelper<1, 1, 0> {
3269 public:
LIR_HEADER(Int32ToFloat32)3270 LIR_HEADER(Int32ToFloat32)
3271
3272 explicit LInt32ToFloat32(const LAllocation& input)
3273 : LInstructionHelper(classOpcode) {
3274 setOperand(0, input);
3275 }
3276 };
3277
3278 // Convert a value to a double.
3279 class LValueToDouble : public LInstructionHelper<1, BOX_PIECES, 0> {
3280 public:
3281 LIR_HEADER(ValueToDouble)
3282 static const size_t Input = 0;
3283
LValueToDouble(const LBoxAllocation & input)3284 explicit LValueToDouble(const LBoxAllocation& input)
3285 : LInstructionHelper(classOpcode) {
3286 setBoxOperand(Input, input);
3287 }
3288
mir()3289 MToDouble* mir() { return mir_->toToDouble(); }
3290 };
3291
3292 // Convert a value to a float32.
3293 class LValueToFloat32 : public LInstructionHelper<1, BOX_PIECES, 0> {
3294 public:
3295 LIR_HEADER(ValueToFloat32)
3296 static const size_t Input = 0;
3297
LValueToFloat32(const LBoxAllocation & input)3298 explicit LValueToFloat32(const LBoxAllocation& input)
3299 : LInstructionHelper(classOpcode) {
3300 setBoxOperand(Input, input);
3301 }
3302
mir()3303 MToFloat32* mir() { return mir_->toToFloat32(); }
3304 };
3305
3306 // Convert a value to an int32.
3307 // Input: components of a Value
3308 // Output: 32-bit integer
3309 // Bailout: undefined, string, object, or non-int32 double
3310 // Temps: one float register, one GP register
3311 //
3312 // This instruction requires a temporary float register.
3313 class LValueToInt32 : public LInstructionHelper<1, BOX_PIECES, 2> {
3314 public:
3315 enum Mode { NORMAL, TRUNCATE, TRUNCATE_NOWRAP };
3316
3317 private:
3318 Mode mode_;
3319
3320 public:
LIR_HEADER(ValueToInt32)3321 LIR_HEADER(ValueToInt32)
3322
3323 LValueToInt32(const LBoxAllocation& input, const LDefinition& temp0,
3324 const LDefinition& temp1, Mode mode)
3325 : LInstructionHelper(classOpcode), mode_(mode) {
3326 setBoxOperand(Input, input);
3327 setTemp(0, temp0);
3328 setTemp(1, temp1);
3329 }
3330
extraName()3331 const char* extraName() const {
3332 return mode() == NORMAL ? "Normal"
3333 : mode() == TRUNCATE ? "Truncate"
3334 : "TruncateNoWrap";
3335 }
3336
3337 static const size_t Input = 0;
3338
mode()3339 Mode mode() const { return mode_; }
tempFloat()3340 const LDefinition* tempFloat() { return getTemp(0); }
temp()3341 const LDefinition* temp() { return getTemp(1); }
mirNormal()3342 MToNumberInt32* mirNormal() const {
3343 MOZ_ASSERT(mode_ == NORMAL);
3344 return mir_->toToNumberInt32();
3345 }
mirTruncate()3346 MTruncateToInt32* mirTruncate() const {
3347 MOZ_ASSERT(mode_ == TRUNCATE);
3348 return mir_->toTruncateToInt32();
3349 }
mirTruncateNoWrap()3350 MToIntegerInt32* mirTruncateNoWrap() const {
3351 MOZ_ASSERT(mode_ == TRUNCATE_NOWRAP);
3352 return mir_->toToIntegerInt32();
3353 }
mir()3354 MInstruction* mir() const { return mir_->toInstruction(); }
3355 };
3356
3357 // Convert a value to a BigInt.
3358 class LValueToBigInt : public LInstructionHelper<1, BOX_PIECES, 0> {
3359 public:
3360 LIR_HEADER(ValueToBigInt)
3361 static const size_t Input = 0;
3362
LValueToBigInt(const LBoxAllocation & input)3363 explicit LValueToBigInt(const LBoxAllocation& input)
3364 : LInstructionHelper(classOpcode) {
3365 setBoxOperand(Input, input);
3366 }
3367
mir()3368 MToBigInt* mir() const { return mir_->toToBigInt(); }
3369 };
3370
3371 // Convert a double to an int32.
3372 // Input: floating-point register
3373 // Output: 32-bit integer
3374 // Bailout: if the double cannot be converted to an integer.
3375 class LDoubleToInt32 : public LInstructionHelper<1, 1, 0> {
3376 public:
LIR_HEADER(DoubleToInt32)3377 LIR_HEADER(DoubleToInt32)
3378
3379 explicit LDoubleToInt32(const LAllocation& in)
3380 : LInstructionHelper(classOpcode) {
3381 setOperand(0, in);
3382 }
3383
mir()3384 MToNumberInt32* mir() const { return mir_->toToNumberInt32(); }
3385 };
3386
3387 // Convert a float32 to an int32.
3388 // Input: floating-point register
3389 // Output: 32-bit integer
3390 // Bailout: if the float32 cannot be converted to an integer.
3391 class LFloat32ToInt32 : public LInstructionHelper<1, 1, 0> {
3392 public:
LIR_HEADER(Float32ToInt32)3393 LIR_HEADER(Float32ToInt32)
3394
3395 explicit LFloat32ToInt32(const LAllocation& in)
3396 : LInstructionHelper(classOpcode) {
3397 setOperand(0, in);
3398 }
3399
mir()3400 MToNumberInt32* mir() const { return mir_->toToNumberInt32(); }
3401 };
3402
3403 // Truncates a double to an int32.
3404 // Input: floating-point register
3405 // Output: 32-bit integer
3406 // Bailout: if the double when converted to an integer exceeds the int32
3407 // bounds. No bailout for NaN or negative zero.
3408 class LDoubleToIntegerInt32 : public LInstructionHelper<1, 1, 0> {
3409 public:
LIR_HEADER(DoubleToIntegerInt32)3410 LIR_HEADER(DoubleToIntegerInt32)
3411
3412 explicit LDoubleToIntegerInt32(const LAllocation& in)
3413 : LInstructionHelper(classOpcode) {
3414 setOperand(0, in);
3415 }
3416
mir()3417 MToIntegerInt32* mir() const { return mir_->toToIntegerInt32(); }
3418 };
3419
3420 // Truncates a float to an int32.
3421 // Input: floating-point register
3422 // Output: 32-bit integer
3423 // Bailout: if the double when converted to an integer exceeds the int32
3424 // bounds. No bailout for NaN or negative zero.
3425 class LFloat32ToIntegerInt32 : public LInstructionHelper<1, 1, 0> {
3426 public:
LIR_HEADER(Float32ToIntegerInt32)3427 LIR_HEADER(Float32ToIntegerInt32)
3428
3429 explicit LFloat32ToIntegerInt32(const LAllocation& in)
3430 : LInstructionHelper(classOpcode) {
3431 setOperand(0, in);
3432 }
3433
mir()3434 MToIntegerInt32* mir() const { return mir_->toToIntegerInt32(); }
3435 };
3436
3437 // Convert a double to a truncated int32.
3438 // Input: floating-point register
3439 // Output: 32-bit integer
3440 class LTruncateDToInt32 : public LInstructionHelper<1, 1, 1> {
3441 public:
LIR_HEADER(TruncateDToInt32)3442 LIR_HEADER(TruncateDToInt32)
3443
3444 LTruncateDToInt32(const LAllocation& in, const LDefinition& temp)
3445 : LInstructionHelper(classOpcode) {
3446 setOperand(0, in);
3447 setTemp(0, temp);
3448 }
3449
tempFloat()3450 const LDefinition* tempFloat() { return getTemp(0); }
3451
mir()3452 MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); }
3453 };
3454
3455 // Convert a double to a truncated int32 with tls offset because we need it for
3456 // the slow ool path.
3457 class LWasmBuiltinTruncateDToInt32 : public LInstructionHelper<1, 2, 1> {
3458 public:
LIR_HEADER(WasmBuiltinTruncateDToInt32)3459 LIR_HEADER(WasmBuiltinTruncateDToInt32)
3460
3461 LWasmBuiltinTruncateDToInt32(const LAllocation& in, const LAllocation& tls,
3462 const LDefinition& temp)
3463 : LInstructionHelper(classOpcode) {
3464 setOperand(0, in);
3465 setOperand(1, tls);
3466 setTemp(0, temp);
3467 }
3468
tempFloat()3469 const LDefinition* tempFloat() { return getTemp(0); }
3470
mir()3471 MWasmBuiltinTruncateToInt32* mir() const {
3472 return mir_->toWasmBuiltinTruncateToInt32();
3473 }
3474 };
3475
3476 // Convert a float32 to a truncated int32.
3477 // Input: floating-point register
3478 // Output: 32-bit integer
3479 class LTruncateFToInt32 : public LInstructionHelper<1, 1, 1> {
3480 public:
LIR_HEADER(TruncateFToInt32)3481 LIR_HEADER(TruncateFToInt32)
3482
3483 LTruncateFToInt32(const LAllocation& in, const LDefinition& temp)
3484 : LInstructionHelper(classOpcode) {
3485 setOperand(0, in);
3486 setTemp(0, temp);
3487 }
3488
tempFloat()3489 const LDefinition* tempFloat() { return getTemp(0); }
3490
mir()3491 MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); }
3492 };
3493
3494 // Convert a float32 to a truncated int32 with tls offset because we need it for
3495 // the slow ool path.
3496 class LWasmBuiltinTruncateFToInt32 : public LInstructionHelper<1, 2, 1> {
3497 public:
LIR_HEADER(WasmBuiltinTruncateFToInt32)3498 LIR_HEADER(WasmBuiltinTruncateFToInt32)
3499
3500 LWasmBuiltinTruncateFToInt32(const LAllocation& in, const LAllocation& tls,
3501 const LDefinition& temp)
3502 : LInstructionHelper(classOpcode) {
3503 setOperand(0, in);
3504 setOperand(1, tls);
3505 setTemp(0, temp);
3506 }
3507
tempFloat()3508 const LDefinition* tempFloat() { return getTemp(0); }
3509
mir()3510 MWasmBuiltinTruncateToInt32* mir() const {
3511 return mir_->toWasmBuiltinTruncateToInt32();
3512 }
3513 };
3514
3515 class LWasmTruncateToInt32 : public LInstructionHelper<1, 1, 0> {
3516 public:
LIR_HEADER(WasmTruncateToInt32)3517 LIR_HEADER(WasmTruncateToInt32)
3518
3519 explicit LWasmTruncateToInt32(const LAllocation& in)
3520 : LInstructionHelper(classOpcode) {
3521 setOperand(0, in);
3522 }
3523
mir()3524 MWasmTruncateToInt32* mir() const { return mir_->toWasmTruncateToInt32(); }
3525 };
3526
3527 class LWrapInt64ToInt32 : public LInstructionHelper<1, INT64_PIECES, 0> {
3528 public:
3529 LIR_HEADER(WrapInt64ToInt32)
3530
3531 static const size_t Input = 0;
3532
LWrapInt64ToInt32(const LInt64Allocation & input)3533 explicit LWrapInt64ToInt32(const LInt64Allocation& input)
3534 : LInstructionHelper(classOpcode) {
3535 setInt64Operand(Input, input);
3536 }
3537
mir()3538 const MWrapInt64ToInt32* mir() { return mir_->toWrapInt64ToInt32(); }
3539 };
3540
3541 class LExtendInt32ToInt64 : public LInstructionHelper<INT64_PIECES, 1, 0> {
3542 public:
LIR_HEADER(ExtendInt32ToInt64)3543 LIR_HEADER(ExtendInt32ToInt64)
3544
3545 explicit LExtendInt32ToInt64(const LAllocation& input)
3546 : LInstructionHelper(classOpcode) {
3547 setOperand(0, input);
3548 }
3549
mir()3550 const MExtendInt32ToInt64* mir() { return mir_->toExtendInt32ToInt64(); }
3551 };
3552
3553 // Convert a boolean value to a string.
3554 class LBooleanToString : public LInstructionHelper<1, 1, 0> {
3555 public:
LIR_HEADER(BooleanToString)3556 LIR_HEADER(BooleanToString)
3557
3558 explicit LBooleanToString(const LAllocation& input)
3559 : LInstructionHelper(classOpcode) {
3560 setOperand(0, input);
3561 }
3562
mir()3563 const MToString* mir() { return mir_->toToString(); }
3564 };
3565
3566 // Convert an integer hosted on one definition to a string with a function call.
3567 class LIntToString : public LInstructionHelper<1, 1, 0> {
3568 public:
LIR_HEADER(IntToString)3569 LIR_HEADER(IntToString)
3570
3571 explicit LIntToString(const LAllocation& input)
3572 : LInstructionHelper(classOpcode) {
3573 setOperand(0, input);
3574 }
3575
mir()3576 const MToString* mir() { return mir_->toToString(); }
3577 };
3578
3579 // Convert a double hosted on one definition to a string with a function call.
3580 class LDoubleToString : public LInstructionHelper<1, 1, 1> {
3581 public:
LIR_HEADER(DoubleToString)3582 LIR_HEADER(DoubleToString)
3583
3584 LDoubleToString(const LAllocation& input, const LDefinition& temp)
3585 : LInstructionHelper(classOpcode) {
3586 setOperand(0, input);
3587 setTemp(0, temp);
3588 }
3589
tempInt()3590 const LDefinition* tempInt() { return getTemp(0); }
mir()3591 const MToString* mir() { return mir_->toToString(); }
3592 };
3593
3594 // Convert a primitive to a string with a function call.
3595 class LValueToString : public LInstructionHelper<1, BOX_PIECES, 1> {
3596 public:
LIR_HEADER(ValueToString)3597 LIR_HEADER(ValueToString)
3598
3599 LValueToString(const LBoxAllocation& input, const LDefinition& tempToUnbox)
3600 : LInstructionHelper(classOpcode) {
3601 setBoxOperand(Input, input);
3602 setTemp(0, tempToUnbox);
3603 }
3604
3605 static const size_t Input = 0;
3606
mir()3607 const MToString* mir() { return mir_->toToString(); }
3608
tempToUnbox()3609 const LDefinition* tempToUnbox() { return getTemp(0); }
3610 };
3611
3612 // Double raised to a half power.
3613 class LPowHalfD : public LInstructionHelper<1, 1, 0> {
3614 public:
3615 LIR_HEADER(PowHalfD);
LPowHalfD(const LAllocation & input)3616 explicit LPowHalfD(const LAllocation& input)
3617 : LInstructionHelper(classOpcode) {
3618 setOperand(0, input);
3619 }
3620
input()3621 const LAllocation* input() { return getOperand(0); }
output()3622 const LDefinition* output() { return getDef(0); }
mir()3623 MPowHalf* mir() const { return mir_->toPowHalf(); }
3624 };
3625
3626 class LNaNToZero : public LInstructionHelper<1, 1, 1> {
3627 public:
LIR_HEADER(NaNToZero)3628 LIR_HEADER(NaNToZero)
3629
3630 explicit LNaNToZero(const LAllocation& input, const LDefinition& tempDouble)
3631 : LInstructionHelper(classOpcode) {
3632 setOperand(0, input);
3633 setTemp(0, tempDouble);
3634 }
3635
mir()3636 const MNaNToZero* mir() { return mir_->toNaNToZero(); }
input()3637 const LAllocation* input() { return getOperand(0); }
output()3638 const LDefinition* output() { return getDef(0); }
tempDouble()3639 const LDefinition* tempDouble() { return getTemp(0); }
3640 };
3641
3642 // Passed the BaselineFrame address in the OsrFrameReg via the IonOsrTempData
3643 // populated by PrepareOsrTempData.
3644 //
3645 // Forwards this object to the LOsrValues for Value materialization.
3646 class LOsrEntry : public LInstructionHelper<1, 0, 1> {
3647 protected:
3648 Label label_;
3649 uint32_t frameDepth_;
3650
3651 public:
LIR_HEADER(OsrEntry)3652 LIR_HEADER(OsrEntry)
3653
3654 explicit LOsrEntry(const LDefinition& temp)
3655 : LInstructionHelper(classOpcode), frameDepth_(0) {
3656 setTemp(0, temp);
3657 }
3658
setFrameDepth(uint32_t depth)3659 void setFrameDepth(uint32_t depth) { frameDepth_ = depth; }
getFrameDepth()3660 uint32_t getFrameDepth() { return frameDepth_; }
label()3661 Label* label() { return &label_; }
temp()3662 const LDefinition* temp() { return getTemp(0); }
3663 };
3664
3665 // Materialize a Value stored in an interpreter frame for OSR.
3666 class LOsrValue : public LInstructionHelper<BOX_PIECES, 1, 0> {
3667 public:
LIR_HEADER(OsrValue)3668 LIR_HEADER(OsrValue)
3669
3670 explicit LOsrValue(const LAllocation& entry)
3671 : LInstructionHelper(classOpcode) {
3672 setOperand(0, entry);
3673 }
3674
mir()3675 const MOsrValue* mir() { return mir_->toOsrValue(); }
3676 };
3677
3678 // Materialize a JSObject env chain stored in an interpreter frame for OSR.
3679 class LOsrEnvironmentChain : public LInstructionHelper<1, 1, 0> {
3680 public:
LIR_HEADER(OsrEnvironmentChain)3681 LIR_HEADER(OsrEnvironmentChain)
3682
3683 explicit LOsrEnvironmentChain(const LAllocation& entry)
3684 : LInstructionHelper(classOpcode) {
3685 setOperand(0, entry);
3686 }
3687
mir()3688 const MOsrEnvironmentChain* mir() { return mir_->toOsrEnvironmentChain(); }
3689 };
3690
3691 // Materialize a JSObject env chain stored in an interpreter frame for OSR.
3692 class LOsrReturnValue : public LInstructionHelper<BOX_PIECES, 1, 0> {
3693 public:
LIR_HEADER(OsrReturnValue)3694 LIR_HEADER(OsrReturnValue)
3695
3696 explicit LOsrReturnValue(const LAllocation& entry)
3697 : LInstructionHelper(classOpcode) {
3698 setOperand(0, entry);
3699 }
3700
mir()3701 const MOsrReturnValue* mir() { return mir_->toOsrReturnValue(); }
3702 };
3703
3704 // Materialize a JSObject ArgumentsObject stored in an interpreter frame for
3705 // OSR.
3706 class LOsrArgumentsObject : public LInstructionHelper<1, 1, 0> {
3707 public:
LIR_HEADER(OsrArgumentsObject)3708 LIR_HEADER(OsrArgumentsObject)
3709
3710 explicit LOsrArgumentsObject(const LAllocation& entry)
3711 : LInstructionHelper(classOpcode) {
3712 setOperand(0, entry);
3713 }
3714
mir()3715 const MOsrArgumentsObject* mir() { return mir_->toOsrArgumentsObject(); }
3716 };
3717
3718 class LRegExp : public LInstructionHelper<1, 0, 1> {
3719 public:
LIR_HEADER(RegExp)3720 LIR_HEADER(RegExp)
3721
3722 explicit LRegExp(const LDefinition& temp) : LInstructionHelper(classOpcode) {
3723 setTemp(0, temp);
3724 }
temp()3725 const LDefinition* temp() { return getTemp(0); }
mir()3726 const MRegExp* mir() const { return mir_->toRegExp(); }
3727 };
3728
3729 class LRegExpMatcher : public LCallInstructionHelper<BOX_PIECES, 3, 0> {
3730 public:
LIR_HEADER(RegExpMatcher)3731 LIR_HEADER(RegExpMatcher)
3732
3733 LRegExpMatcher(const LAllocation& regexp, const LAllocation& string,
3734 const LAllocation& lastIndex)
3735 : LCallInstructionHelper(classOpcode) {
3736 setOperand(0, regexp);
3737 setOperand(1, string);
3738 setOperand(2, lastIndex);
3739 }
3740
regexp()3741 const LAllocation* regexp() { return getOperand(0); }
string()3742 const LAllocation* string() { return getOperand(1); }
lastIndex()3743 const LAllocation* lastIndex() { return getOperand(2); }
3744
mir()3745 const MRegExpMatcher* mir() const { return mir_->toRegExpMatcher(); }
3746 };
3747
3748 class LRegExpSearcher : public LCallInstructionHelper<1, 3, 0> {
3749 public:
LIR_HEADER(RegExpSearcher)3750 LIR_HEADER(RegExpSearcher)
3751
3752 LRegExpSearcher(const LAllocation& regexp, const LAllocation& string,
3753 const LAllocation& lastIndex)
3754 : LCallInstructionHelper(classOpcode) {
3755 setOperand(0, regexp);
3756 setOperand(1, string);
3757 setOperand(2, lastIndex);
3758 }
3759
regexp()3760 const LAllocation* regexp() { return getOperand(0); }
string()3761 const LAllocation* string() { return getOperand(1); }
lastIndex()3762 const LAllocation* lastIndex() { return getOperand(2); }
3763
mir()3764 const MRegExpSearcher* mir() const { return mir_->toRegExpSearcher(); }
3765 };
3766
3767 class LRegExpTester : public LCallInstructionHelper<1, 3, 0> {
3768 public:
LIR_HEADER(RegExpTester)3769 LIR_HEADER(RegExpTester)
3770
3771 LRegExpTester(const LAllocation& regexp, const LAllocation& string,
3772 const LAllocation& lastIndex)
3773 : LCallInstructionHelper(classOpcode) {
3774 setOperand(0, regexp);
3775 setOperand(1, string);
3776 setOperand(2, lastIndex);
3777 }
3778
regexp()3779 const LAllocation* regexp() { return getOperand(0); }
string()3780 const LAllocation* string() { return getOperand(1); }
lastIndex()3781 const LAllocation* lastIndex() { return getOperand(2); }
3782
mir()3783 const MRegExpTester* mir() const { return mir_->toRegExpTester(); }
3784 };
3785
3786 class LRegExpPrototypeOptimizable : public LInstructionHelper<1, 1, 1> {
3787 public:
3788 LIR_HEADER(RegExpPrototypeOptimizable);
LRegExpPrototypeOptimizable(const LAllocation & object,const LDefinition & temp)3789 LRegExpPrototypeOptimizable(const LAllocation& object,
3790 const LDefinition& temp)
3791 : LInstructionHelper(classOpcode) {
3792 setOperand(0, object);
3793 setTemp(0, temp);
3794 }
3795
object()3796 const LAllocation* object() { return getOperand(0); }
temp()3797 const LDefinition* temp() { return getTemp(0); }
mir()3798 MRegExpPrototypeOptimizable* mir() const {
3799 return mir_->toRegExpPrototypeOptimizable();
3800 }
3801 };
3802
3803 class LRegExpInstanceOptimizable : public LInstructionHelper<1, 2, 1> {
3804 public:
3805 LIR_HEADER(RegExpInstanceOptimizable);
LRegExpInstanceOptimizable(const LAllocation & object,const LAllocation & proto,const LDefinition & temp)3806 LRegExpInstanceOptimizable(const LAllocation& object,
3807 const LAllocation& proto, const LDefinition& temp)
3808 : LInstructionHelper(classOpcode) {
3809 setOperand(0, object);
3810 setOperand(1, proto);
3811 setTemp(0, temp);
3812 }
3813
object()3814 const LAllocation* object() { return getOperand(0); }
proto()3815 const LAllocation* proto() { return getOperand(1); }
temp()3816 const LDefinition* temp() { return getTemp(0); }
mir()3817 MRegExpInstanceOptimizable* mir() const {
3818 return mir_->toRegExpInstanceOptimizable();
3819 }
3820 };
3821
3822 class LGetFirstDollarIndex : public LInstructionHelper<1, 1, 3> {
3823 public:
3824 LIR_HEADER(GetFirstDollarIndex);
LGetFirstDollarIndex(const LAllocation & str,const LDefinition & temp0,const LDefinition & temp1,const LDefinition & temp2)3825 LGetFirstDollarIndex(const LAllocation& str, const LDefinition& temp0,
3826 const LDefinition& temp1, const LDefinition& temp2)
3827 : LInstructionHelper(classOpcode) {
3828 setOperand(0, str);
3829 setTemp(0, temp0);
3830 setTemp(1, temp1);
3831 setTemp(2, temp2);
3832 }
3833
str()3834 const LAllocation* str() { return getOperand(0); }
temp0()3835 const LDefinition* temp0() { return getTemp(0); }
temp1()3836 const LDefinition* temp1() { return getTemp(1); }
temp2()3837 const LDefinition* temp2() { return getTemp(2); }
3838 };
3839
3840 class LStringReplace : public LCallInstructionHelper<1, 3, 0> {
3841 public:
3842 LIR_HEADER(StringReplace);
3843
LStringReplace(const LAllocation & string,const LAllocation & pattern,const LAllocation & replacement)3844 LStringReplace(const LAllocation& string, const LAllocation& pattern,
3845 const LAllocation& replacement)
3846 : LCallInstructionHelper(classOpcode) {
3847 setOperand(0, string);
3848 setOperand(1, pattern);
3849 setOperand(2, replacement);
3850 }
3851
mir()3852 const MStringReplace* mir() const { return mir_->toStringReplace(); }
3853
string()3854 const LAllocation* string() { return getOperand(0); }
pattern()3855 const LAllocation* pattern() { return getOperand(1); }
replacement()3856 const LAllocation* replacement() { return getOperand(2); }
3857 };
3858
3859 class LBinaryValueCache
3860 : public LInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 2> {
3861 public:
LIR_HEADER(BinaryValueCache)3862 LIR_HEADER(BinaryValueCache)
3863
3864 // Takes two temps: these are intendend to be FloatReg0 and FloatReg1
3865 // To allow the actual cache code to safely clobber those values without
3866 // save and restore.
3867 LBinaryValueCache(const LBoxAllocation& lhs, const LBoxAllocation& rhs,
3868 const LDefinition& temp0, const LDefinition& temp1)
3869 : LInstructionHelper(classOpcode) {
3870 setBoxOperand(LhsInput, lhs);
3871 setBoxOperand(RhsInput, rhs);
3872 setTemp(0, temp0);
3873 setTemp(1, temp1);
3874 }
3875
mir()3876 const MBinaryCache* mir() const { return mir_->toBinaryCache(); }
3877
3878 static const size_t LhsInput = 0;
3879 static const size_t RhsInput = BOX_PIECES;
3880 };
3881
3882 class LBinaryBoolCache : public LInstructionHelper<1, 2 * BOX_PIECES, 2> {
3883 public:
LIR_HEADER(BinaryBoolCache)3884 LIR_HEADER(BinaryBoolCache)
3885
3886 // Takes two temps: these are intendend to be FloatReg0 and FloatReg1
3887 // To allow the actual cache code to safely clobber those values without
3888 // save and restore.
3889 LBinaryBoolCache(const LBoxAllocation& lhs, const LBoxAllocation& rhs,
3890 const LDefinition& temp0, const LDefinition& temp1)
3891 : LInstructionHelper(classOpcode) {
3892 setBoxOperand(LhsInput, lhs);
3893 setBoxOperand(RhsInput, rhs);
3894 setTemp(0, temp0);
3895 setTemp(1, temp1);
3896 }
3897
mir()3898 const MBinaryCache* mir() const { return mir_->toBinaryCache(); }
3899
3900 static const size_t LhsInput = 0;
3901 static const size_t RhsInput = BOX_PIECES;
3902 };
3903
3904 class LUnaryCache : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 0> {
3905 public:
LIR_HEADER(UnaryCache)3906 LIR_HEADER(UnaryCache)
3907
3908 explicit LUnaryCache(const LBoxAllocation& input)
3909 : LInstructionHelper(classOpcode) {
3910 setBoxOperand(Input, input);
3911 }
3912
mir()3913 const MUnaryCache* mir() const { return mir_->toUnaryCache(); }
3914
input()3915 const LAllocation* input() { return getOperand(Input); }
3916
3917 static const size_t Input = 0;
3918 };
3919
3920 class LModuleMetadata : public LCallInstructionHelper<1, 0, 0> {
3921 public:
LIR_HEADER(ModuleMetadata)3922 LIR_HEADER(ModuleMetadata)
3923
3924 const MModuleMetadata* mir() const { return mir_->toModuleMetadata(); }
3925
LModuleMetadata()3926 LModuleMetadata() : LCallInstructionHelper(classOpcode) {}
3927 };
3928
3929 class LDynamicImport : public LCallInstructionHelper<1, BOX_PIECES, 0> {
3930 public:
3931 LIR_HEADER(DynamicImport)
3932
3933 static const size_t SpecifierIndex = 0;
3934
LDynamicImport(const LBoxAllocation & specifier)3935 explicit LDynamicImport(const LBoxAllocation& specifier)
3936 : LCallInstructionHelper(classOpcode) {
3937 setBoxOperand(SpecifierIndex, specifier);
3938 }
3939
mir()3940 const MDynamicImport* mir() const { return mir_->toDynamicImport(); }
3941 };
3942
3943 class LLambda : public LInstructionHelper<1, 1, 1> {
3944 public:
LIR_HEADER(Lambda)3945 LIR_HEADER(Lambda)
3946
3947 LLambda(const LAllocation& envChain, const LDefinition& temp)
3948 : LInstructionHelper(classOpcode) {
3949 setOperand(0, envChain);
3950 setTemp(0, temp);
3951 }
environmentChain()3952 const LAllocation* environmentChain() { return getOperand(0); }
temp()3953 const LDefinition* temp() { return getTemp(0); }
mir()3954 const MLambda* mir() const { return mir_->toLambda(); }
3955 };
3956
3957 class LLambdaArrow : public LInstructionHelper<1, 1 + BOX_PIECES, 1> {
3958 public:
3959 LIR_HEADER(LambdaArrow)
3960
3961 static const size_t NewTargetValue = 1;
3962
LLambdaArrow(const LAllocation & envChain,const LBoxAllocation & newTarget,const LDefinition & temp)3963 LLambdaArrow(const LAllocation& envChain, const LBoxAllocation& newTarget,
3964 const LDefinition& temp)
3965 : LInstructionHelper(classOpcode) {
3966 setOperand(0, envChain);
3967 setBoxOperand(NewTargetValue, newTarget);
3968 setTemp(0, temp);
3969 }
environmentChain()3970 const LAllocation* environmentChain() { return getOperand(0); }
temp()3971 const LDefinition* temp() { return getTemp(0); }
mir()3972 const MLambdaArrow* mir() const { return mir_->toLambdaArrow(); }
3973 };
3974
3975 class LFunctionWithProto : public LCallInstructionHelper<1, 2, 0> {
3976 public:
LIR_HEADER(FunctionWithProto)3977 LIR_HEADER(FunctionWithProto)
3978
3979 LFunctionWithProto(const LAllocation& envChain, const LAllocation& prototype)
3980 : LCallInstructionHelper(classOpcode) {
3981 setOperand(0, envChain);
3982 setOperand(1, prototype);
3983 }
environmentChain()3984 const LAllocation* environmentChain() { return getOperand(0); }
prototype()3985 const LAllocation* prototype() { return getOperand(1); }
mir()3986 const MFunctionWithProto* mir() const { return mir_->toFunctionWithProto(); }
3987 };
3988
3989 class LSetFunName : public LCallInstructionHelper<1, 1 + BOX_PIECES, 0> {
3990 public:
3991 LIR_HEADER(SetFunName)
3992
3993 static const size_t NameValue = 1;
3994
LSetFunName(const LAllocation & fun,const LBoxAllocation & name)3995 LSetFunName(const LAllocation& fun, const LBoxAllocation& name)
3996 : LCallInstructionHelper(classOpcode) {
3997 setOperand(0, fun);
3998 setBoxOperand(NameValue, name);
3999 }
fun()4000 const LAllocation* fun() { return getOperand(0); }
mir()4001 const MSetFunName* mir() const { return mir_->toSetFunName(); }
4002 };
4003
4004 class LKeepAliveObject : public LInstructionHelper<0, 1, 0> {
4005 public:
LIR_HEADER(KeepAliveObject)4006 LIR_HEADER(KeepAliveObject)
4007
4008 explicit LKeepAliveObject(const LAllocation& object)
4009 : LInstructionHelper(classOpcode) {
4010 setOperand(0, object);
4011 }
4012
object()4013 const LAllocation* object() { return getOperand(0); }
4014 };
4015
4016 // Load the "slots" member out of a JSObject.
4017 // Input: JSObject pointer
4018 // Output: slots pointer
4019 class LSlots : public LInstructionHelper<1, 1, 0> {
4020 public:
LIR_HEADER(Slots)4021 LIR_HEADER(Slots)
4022
4023 explicit LSlots(const LAllocation& object) : LInstructionHelper(classOpcode) {
4024 setOperand(0, object);
4025 }
4026
object()4027 const LAllocation* object() { return getOperand(0); }
4028 };
4029
4030 // Load the "elements" member out of a JSObject.
4031 // Input: JSObject pointer
4032 // Output: elements pointer
4033 class LElements : public LInstructionHelper<1, 1, 0> {
4034 public:
LIR_HEADER(Elements)4035 LIR_HEADER(Elements)
4036
4037 explicit LElements(const LAllocation& object)
4038 : LInstructionHelper(classOpcode) {
4039 setOperand(0, object);
4040 }
4041
object()4042 const LAllocation* object() { return getOperand(0); }
4043
mir()4044 const MElements* mir() const { return mir_->toElements(); }
4045 };
4046
4047 // Load the initialized length from an elements header.
4048 class LInitializedLength : public LInstructionHelper<1, 1, 0> {
4049 public:
LIR_HEADER(InitializedLength)4050 LIR_HEADER(InitializedLength)
4051
4052 explicit LInitializedLength(const LAllocation& elements)
4053 : LInstructionHelper(classOpcode) {
4054 setOperand(0, elements);
4055 }
4056
elements()4057 const LAllocation* elements() { return getOperand(0); }
4058 };
4059
4060 // Store to the initialized length in an elements header. Note the input is an
4061 // *index*, one less than the desired initialized length.
4062 class LSetInitializedLength : public LInstructionHelper<0, 2, 0> {
4063 public:
LIR_HEADER(SetInitializedLength)4064 LIR_HEADER(SetInitializedLength)
4065
4066 LSetInitializedLength(const LAllocation& elements, const LAllocation& index)
4067 : LInstructionHelper(classOpcode) {
4068 setOperand(0, elements);
4069 setOperand(1, index);
4070 }
4071
elements()4072 const LAllocation* elements() { return getOperand(0); }
index()4073 const LAllocation* index() { return getOperand(1); }
4074 };
4075
4076 // Load the length from an elements header.
4077 class LArrayLength : public LInstructionHelper<1, 1, 0> {
4078 public:
LIR_HEADER(ArrayLength)4079 LIR_HEADER(ArrayLength)
4080
4081 explicit LArrayLength(const LAllocation& elements)
4082 : LInstructionHelper(classOpcode) {
4083 setOperand(0, elements);
4084 }
4085
elements()4086 const LAllocation* elements() { return getOperand(0); }
4087 };
4088
4089 // Store to the length in an elements header. Note the input is an *index*,
4090 // one less than the desired length.
4091 class LSetArrayLength : public LInstructionHelper<0, 2, 0> {
4092 public:
LIR_HEADER(SetArrayLength)4093 LIR_HEADER(SetArrayLength)
4094
4095 LSetArrayLength(const LAllocation& elements, const LAllocation& index)
4096 : LInstructionHelper(classOpcode) {
4097 setOperand(0, elements);
4098 setOperand(1, index);
4099 }
4100
elements()4101 const LAllocation* elements() { return getOperand(0); }
index()4102 const LAllocation* index() { return getOperand(1); }
4103 };
4104
4105 // Load the "length" property of a function.
4106 class LFunctionLength : public LInstructionHelper<1, 1, 0> {
4107 public:
LIR_HEADER(FunctionLength)4108 LIR_HEADER(FunctionLength)
4109
4110 explicit LFunctionLength(const LAllocation& function)
4111 : LInstructionHelper(classOpcode) {
4112 setOperand(0, function);
4113 }
4114
function()4115 const LAllocation* function() { return getOperand(0); }
4116 };
4117
4118 // Load the "name" property of a function.
4119 class LFunctionName : public LInstructionHelper<1, 1, 0> {
4120 public:
LIR_HEADER(FunctionName)4121 LIR_HEADER(FunctionName)
4122
4123 explicit LFunctionName(const LAllocation& function)
4124 : LInstructionHelper(classOpcode) {
4125 setOperand(0, function);
4126 }
4127
function()4128 const LAllocation* function() { return getOperand(0); }
4129 };
4130
4131 class LGetNextEntryForIterator : public LInstructionHelper<1, 2, 3> {
4132 public:
LIR_HEADER(GetNextEntryForIterator)4133 LIR_HEADER(GetNextEntryForIterator)
4134
4135 explicit LGetNextEntryForIterator(const LAllocation& iter,
4136 const LAllocation& result,
4137 const LDefinition& temp0,
4138 const LDefinition& temp1,
4139 const LDefinition& temp2)
4140 : LInstructionHelper(classOpcode) {
4141 setOperand(0, iter);
4142 setOperand(1, result);
4143 setTemp(0, temp0);
4144 setTemp(1, temp1);
4145 setTemp(2, temp2);
4146 }
4147
mir()4148 const MGetNextEntryForIterator* mir() const {
4149 return mir_->toGetNextEntryForIterator();
4150 }
iter()4151 const LAllocation* iter() { return getOperand(0); }
result()4152 const LAllocation* result() { return getOperand(1); }
temp0()4153 const LDefinition* temp0() { return getTemp(0); }
temp1()4154 const LDefinition* temp1() { return getTemp(1); }
temp2()4155