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