blob: 237487ff884d6ef284ab1ebf38de7efa80e4e90b [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2013 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_CRANKSHAFT_ARM64_LITHIUM_ARM64_H_
6#define V8_CRANKSHAFT_ARM64_LITHIUM_ARM64_H_
7
8#include "src/crankshaft/hydrogen.h"
9#include "src/crankshaft/lithium.h"
10#include "src/crankshaft/lithium-allocator.h"
11#include "src/safepoint-table.h"
12#include "src/utils.h"
13
14namespace v8 {
15namespace internal {
16
17// Forward declarations.
18class LCodeGen;
19
20#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \
21 V(AccessArgumentsAt) \
22 V(AddE) \
23 V(AddI) \
24 V(AddS) \
25 V(Allocate) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000026 V(ApplyArguments) \
27 V(ArgumentsElements) \
28 V(ArgumentsLength) \
29 V(ArithmeticD) \
30 V(ArithmeticT) \
31 V(BitI) \
32 V(BitS) \
33 V(BoundsCheck) \
34 V(Branch) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035 V(CallNewArray) \
36 V(CallRuntime) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000037 V(CallWithDescriptor) \
38 V(CheckArrayBufferNotNeutered) \
39 V(CheckInstanceType) \
40 V(CheckMapValue) \
41 V(CheckMaps) \
42 V(CheckNonSmi) \
43 V(CheckSmi) \
44 V(CheckValue) \
45 V(ClampDToUint8) \
46 V(ClampIToUint8) \
47 V(ClampTToUint8) \
48 V(ClassOfTestAndBranch) \
49 V(CmpHoleAndBranchD) \
50 V(CmpHoleAndBranchT) \
51 V(CmpMapAndBranch) \
52 V(CmpObjectEqAndBranch) \
53 V(CmpT) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000054 V(CompareNumericAndBranch) \
55 V(ConstantD) \
56 V(ConstantE) \
57 V(ConstantI) \
58 V(ConstantS) \
59 V(ConstantT) \
60 V(ConstructDouble) \
61 V(Context) \
62 V(DebugBreak) \
63 V(DeclareGlobals) \
64 V(Deoptimize) \
65 V(DivByConstI) \
66 V(DivByPowerOf2I) \
67 V(DivI) \
68 V(DoubleBits) \
69 V(DoubleToIntOrSmi) \
70 V(Drop) \
71 V(Dummy) \
72 V(DummyUse) \
73 V(FlooringDivByConstI) \
74 V(FlooringDivByPowerOf2I) \
75 V(FlooringDivI) \
76 V(ForInCacheArray) \
77 V(ForInPrepareMap) \
78 V(GetCachedArrayIndex) \
79 V(Goto) \
80 V(HasCachedArrayIndexAndBranch) \
81 V(HasInPrototypeChainAndBranch) \
82 V(HasInstanceTypeAndBranch) \
83 V(InnerAllocatedObject) \
84 V(InstanceOf) \
85 V(InstructionGap) \
86 V(Integer32ToDouble) \
87 V(InvokeFunction) \
88 V(IsSmiAndBranch) \
89 V(IsStringAndBranch) \
90 V(IsUndetectableAndBranch) \
91 V(Label) \
92 V(LazyBailout) \
93 V(LoadContextSlot) \
94 V(LoadFieldByIndex) \
95 V(LoadFunctionPrototype) \
96 V(LoadGlobalGeneric) \
97 V(LoadKeyedExternal) \
98 V(LoadKeyedFixed) \
99 V(LoadKeyedFixedDouble) \
100 V(LoadKeyedGeneric) \
101 V(LoadNamedField) \
102 V(LoadNamedGeneric) \
103 V(LoadRoot) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000104 V(MathAbs) \
105 V(MathAbsTagged) \
106 V(MathClz32) \
107 V(MathExp) \
108 V(MathFloorD) \
109 V(MathFloorI) \
110 V(MathFround) \
111 V(MathLog) \
112 V(MathMinMax) \
113 V(MathPowHalf) \
114 V(MathRoundD) \
115 V(MathRoundI) \
116 V(MathSqrt) \
117 V(MaybeGrowElements) \
118 V(ModByConstI) \
119 V(ModByPowerOf2I) \
120 V(ModI) \
121 V(MulConstIS) \
122 V(MulI) \
123 V(MulS) \
124 V(NumberTagD) \
125 V(NumberTagU) \
126 V(NumberUntagD) \
127 V(OsrEntry) \
128 V(Parameter) \
129 V(Power) \
130 V(Prologue) \
131 V(PreparePushArguments) \
132 V(PushArguments) \
133 V(Return) \
134 V(SeqStringGetChar) \
135 V(SeqStringSetChar) \
136 V(ShiftI) \
137 V(ShiftS) \
138 V(SmiTag) \
139 V(SmiUntag) \
140 V(StackCheck) \
141 V(StoreCodeEntry) \
142 V(StoreContextSlot) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000143 V(StoreKeyedExternal) \
144 V(StoreKeyedFixed) \
145 V(StoreKeyedFixedDouble) \
146 V(StoreKeyedGeneric) \
147 V(StoreNamedField) \
148 V(StoreNamedGeneric) \
149 V(StringAdd) \
150 V(StringCharCodeAt) \
151 V(StringCharFromCode) \
152 V(StringCompareAndBranch) \
153 V(SubI) \
154 V(SubS) \
155 V(TaggedToI) \
156 V(ThisFunction) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157 V(TransitionElementsKind) \
158 V(TrapAllocationMemento) \
159 V(TruncateDoubleToIntOrSmi) \
160 V(Typeof) \
161 V(TypeofIsAndBranch) \
162 V(Uint32ToDouble) \
163 V(UnknownOSRValue) \
164 V(WrapReceiver)
165
166
167#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
168 Opcode opcode() const final { return LInstruction::k##type; } \
169 void CompileToNative(LCodeGen* generator) final; \
170 const char* Mnemonic() const final { return mnemonic; } \
171 static L##type* cast(LInstruction* instr) { \
172 DCHECK(instr->Is##type()); \
173 return reinterpret_cast<L##type*>(instr); \
174 }
175
176
177#define DECLARE_HYDROGEN_ACCESSOR(type) \
178 H##type* hydrogen() const { \
179 return H##type::cast(this->hydrogen_value()); \
180 }
181
182
183class LInstruction : public ZoneObject {
184 public:
185 LInstruction()
186 : environment_(NULL),
187 hydrogen_value_(NULL),
188 bit_field_(IsCallBits::encode(false)) { }
189
190 virtual ~LInstruction() { }
191
192 virtual void CompileToNative(LCodeGen* generator) = 0;
193 virtual const char* Mnemonic() const = 0;
194 virtual void PrintTo(StringStream* stream);
195 virtual void PrintDataTo(StringStream* stream);
196 virtual void PrintOutputOperandTo(StringStream* stream);
197
198 enum Opcode {
199 // Declare a unique enum value for each instruction.
200#define DECLARE_OPCODE(type) k##type,
201 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
202 kNumberOfInstructions
203#undef DECLARE_OPCODE
204 };
205
206 virtual Opcode opcode() const = 0;
207
208 // Declare non-virtual type testers for all leaf IR classes.
209#define DECLARE_PREDICATE(type) \
210 bool Is##type() const { return opcode() == k##type; }
211 LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
212#undef DECLARE_PREDICATE
213
214 // Declare virtual predicates for instructions that don't have
215 // an opcode.
216 virtual bool IsGap() const { return false; }
217
218 virtual bool IsControl() const { return false; }
219
220 // Try deleting this instruction if possible.
221 virtual bool TryDelete() { return false; }
222
223 void set_environment(LEnvironment* env) { environment_ = env; }
224 LEnvironment* environment() const { return environment_; }
225 bool HasEnvironment() const { return environment_ != NULL; }
226
227 void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); }
228 LPointerMap* pointer_map() const { return pointer_map_.get(); }
229 bool HasPointerMap() const { return pointer_map_.is_set(); }
230
231 void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
232 HValue* hydrogen_value() const { return hydrogen_value_; }
233
234 void MarkAsCall() { bit_field_ = IsCallBits::update(bit_field_, true); }
235 bool IsCall() const { return IsCallBits::decode(bit_field_); }
236
Ben Murdochda12d292016-06-02 14:46:10 +0100237 void MarkAsSyntacticTailCall() {
238 bit_field_ = IsSyntacticTailCallBits::update(bit_field_, true);
239 }
240 bool IsSyntacticTailCall() const {
241 return IsSyntacticTailCallBits::decode(bit_field_);
242 }
243
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000244 // Interface to the register allocator and iterators.
245 bool ClobbersTemps() const { return IsCall(); }
246 bool ClobbersRegisters() const { return IsCall(); }
247 virtual bool ClobbersDoubleRegisters(Isolate* isolate) const {
248 return IsCall();
249 }
250 bool IsMarkedAsCall() const { return IsCall(); }
251
252 virtual bool HasResult() const = 0;
253 virtual LOperand* result() const = 0;
254
255 virtual int InputCount() = 0;
256 virtual LOperand* InputAt(int i) = 0;
257 virtual int TempCount() = 0;
258 virtual LOperand* TempAt(int i) = 0;
259
260 LOperand* FirstInput() { return InputAt(0); }
261 LOperand* Output() { return HasResult() ? result() : NULL; }
262
263 virtual bool HasInterestingComment(LCodeGen* gen) const { return true; }
264
265#ifdef DEBUG
266 void VerifyCall();
267#endif
268
269 private:
270 class IsCallBits: public BitField<bool, 0, 1> {};
Ben Murdochda12d292016-06-02 14:46:10 +0100271 class IsSyntacticTailCallBits : public BitField<bool, IsCallBits::kNext, 1> {
272 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000273
274 LEnvironment* environment_;
275 SetOncePointer<LPointerMap> pointer_map_;
276 HValue* hydrogen_value_;
277 int32_t bit_field_;
278};
279
280
281// R = number of result operands (0 or 1).
282template<int R>
283class LTemplateResultInstruction : public LInstruction {
284 public:
285 // Allow 0 or 1 output operands.
286 STATIC_ASSERT(R == 0 || R == 1);
287 bool HasResult() const final { return (R != 0) && (result() != NULL); }
288 void set_result(LOperand* operand) { results_[0] = operand; }
289 LOperand* result() const override { return results_[0]; }
290
291 protected:
292 EmbeddedContainer<LOperand*, R> results_;
293};
294
295
296// R = number of result operands (0 or 1).
297// I = number of input operands.
298// T = number of temporary operands.
299template<int R, int I, int T>
300class LTemplateInstruction : public LTemplateResultInstruction<R> {
301 protected:
302 EmbeddedContainer<LOperand*, I> inputs_;
303 EmbeddedContainer<LOperand*, T> temps_;
304
305 private:
306 // Iterator support.
307 int InputCount() final { return I; }
308 LOperand* InputAt(int i) final { return inputs_[i]; }
309
310 int TempCount() final { return T; }
311 LOperand* TempAt(int i) final { return temps_[i]; }
312};
313
314
315class LUnknownOSRValue final : public LTemplateInstruction<1, 0, 0> {
316 public:
317 bool HasInterestingComment(LCodeGen* gen) const override { return false; }
318 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value")
319};
320
321
322template<int I, int T>
323class LControlInstruction : public LTemplateInstruction<0, I, T> {
324 public:
325 LControlInstruction() : false_label_(NULL), true_label_(NULL) { }
326
327 bool IsControl() const final { return true; }
328
329 int SuccessorCount() { return hydrogen()->SuccessorCount(); }
330 HBasicBlock* SuccessorAt(int i) { return hydrogen()->SuccessorAt(i); }
331
332 int TrueDestination(LChunk* chunk) {
333 return chunk->LookupDestination(true_block_id());
334 }
335
336 int FalseDestination(LChunk* chunk) {
337 return chunk->LookupDestination(false_block_id());
338 }
339
340 Label* TrueLabel(LChunk* chunk) {
341 if (true_label_ == NULL) {
342 true_label_ = chunk->GetAssemblyLabel(TrueDestination(chunk));
343 }
344 return true_label_;
345 }
346
347 Label* FalseLabel(LChunk* chunk) {
348 if (false_label_ == NULL) {
349 false_label_ = chunk->GetAssemblyLabel(FalseDestination(chunk));
350 }
351 return false_label_;
352 }
353
354 protected:
355 int true_block_id() { return SuccessorAt(0)->block_id(); }
356 int false_block_id() { return SuccessorAt(1)->block_id(); }
357
358 private:
359 DECLARE_HYDROGEN_ACCESSOR(ControlInstruction);
360
361 Label* false_label_;
362 Label* true_label_;
363};
364
365
366class LGap : public LTemplateInstruction<0, 0, 0> {
367 public:
368 explicit LGap(HBasicBlock* block)
369 : block_(block) {
370 parallel_moves_[BEFORE] = NULL;
371 parallel_moves_[START] = NULL;
372 parallel_moves_[END] = NULL;
373 parallel_moves_[AFTER] = NULL;
374 }
375
376 // Can't use the DECLARE-macro here because of sub-classes.
377 bool IsGap() const override { return true; }
378 void PrintDataTo(StringStream* stream) override;
379 static LGap* cast(LInstruction* instr) {
380 DCHECK(instr->IsGap());
381 return reinterpret_cast<LGap*>(instr);
382 }
383
384 bool IsRedundant() const;
385
386 HBasicBlock* block() const { return block_; }
387
388 enum InnerPosition {
389 BEFORE,
390 START,
391 END,
392 AFTER,
393 FIRST_INNER_POSITION = BEFORE,
394 LAST_INNER_POSITION = AFTER
395 };
396
397 LParallelMove* GetOrCreateParallelMove(InnerPosition pos, Zone* zone) {
398 if (parallel_moves_[pos] == NULL) {
399 parallel_moves_[pos] = new(zone) LParallelMove(zone);
400 }
401 return parallel_moves_[pos];
402 }
403
404 LParallelMove* GetParallelMove(InnerPosition pos) {
405 return parallel_moves_[pos];
406 }
407
408 private:
409 LParallelMove* parallel_moves_[LAST_INNER_POSITION + 1];
410 HBasicBlock* block_;
411};
412
413
414class LInstructionGap final : public LGap {
415 public:
416 explicit LInstructionGap(HBasicBlock* block) : LGap(block) { }
417
418 bool HasInterestingComment(LCodeGen* gen) const override {
419 return !IsRedundant();
420 }
421
422 DECLARE_CONCRETE_INSTRUCTION(InstructionGap, "gap")
423};
424
425
426class LDrop final : public LTemplateInstruction<0, 0, 0> {
427 public:
428 explicit LDrop(int count) : count_(count) { }
429
430 int count() const { return count_; }
431
432 DECLARE_CONCRETE_INSTRUCTION(Drop, "drop")
433
434 private:
435 int count_;
436};
437
438
439class LDummy final : public LTemplateInstruction<1, 0, 0> {
440 public:
441 LDummy() {}
442 DECLARE_CONCRETE_INSTRUCTION(Dummy, "dummy")
443};
444
445
446class LDummyUse final : public LTemplateInstruction<1, 1, 0> {
447 public:
448 explicit LDummyUse(LOperand* value) {
449 inputs_[0] = value;
450 }
451 DECLARE_CONCRETE_INSTRUCTION(DummyUse, "dummy-use")
452};
453
454
455class LGoto final : public LTemplateInstruction<0, 0, 0> {
456 public:
457 explicit LGoto(HBasicBlock* block) : block_(block) { }
458
459 bool HasInterestingComment(LCodeGen* gen) const override;
460 DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
461 void PrintDataTo(StringStream* stream) override;
462 bool IsControl() const override { return true; }
463
464 int block_id() const { return block_->block_id(); }
465
466 private:
467 HBasicBlock* block_;
468};
469
470
471class LPrologue final : public LTemplateInstruction<0, 0, 0> {
472 public:
473 DECLARE_CONCRETE_INSTRUCTION(Prologue, "prologue")
474};
475
476
477class LLazyBailout final : public LTemplateInstruction<0, 0, 0> {
478 public:
479 LLazyBailout() : gap_instructions_size_(0) { }
480
481 DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout")
482
483 void set_gap_instructions_size(int gap_instructions_size) {
484 gap_instructions_size_ = gap_instructions_size;
485 }
486 int gap_instructions_size() { return gap_instructions_size_; }
487
488 private:
489 int gap_instructions_size_;
490};
491
492
493class LLabel final : public LGap {
494 public:
495 explicit LLabel(HBasicBlock* block)
496 : LGap(block), replacement_(NULL) { }
497
498 bool HasInterestingComment(LCodeGen* gen) const override { return false; }
499 DECLARE_CONCRETE_INSTRUCTION(Label, "label")
500
501 void PrintDataTo(StringStream* stream) override;
502
503 int block_id() const { return block()->block_id(); }
504 bool is_loop_header() const { return block()->IsLoopHeader(); }
505 bool is_osr_entry() const { return block()->is_osr_entry(); }
506 Label* label() { return &label_; }
507 LLabel* replacement() const { return replacement_; }
508 void set_replacement(LLabel* label) { replacement_ = label; }
509 bool HasReplacement() const { return replacement_ != NULL; }
510
511 private:
512 Label label_;
513 LLabel* replacement_;
514};
515
516
517class LOsrEntry final : public LTemplateInstruction<0, 0, 0> {
518 public:
519 LOsrEntry() {}
520
521 bool HasInterestingComment(LCodeGen* gen) const override { return false; }
522 DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry")
523};
524
525
526class LAccessArgumentsAt final : public LTemplateInstruction<1, 3, 0> {
527 public:
528 LAccessArgumentsAt(LOperand* arguments,
529 LOperand* length,
530 LOperand* index) {
531 inputs_[0] = arguments;
532 inputs_[1] = length;
533 inputs_[2] = index;
534 }
535
536 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at")
537
538 LOperand* arguments() { return inputs_[0]; }
539 LOperand* length() { return inputs_[1]; }
540 LOperand* index() { return inputs_[2]; }
541
542 void PrintDataTo(StringStream* stream) override;
543};
544
545
546class LAddE final : public LTemplateInstruction<1, 2, 0> {
547 public:
548 LAddE(LOperand* left, LOperand* right) {
549 inputs_[0] = left;
550 inputs_[1] = right;
551 }
552
553 LOperand* left() { return inputs_[0]; }
554 LOperand* right() { return inputs_[1]; }
555
556 DECLARE_CONCRETE_INSTRUCTION(AddE, "add-e")
557 DECLARE_HYDROGEN_ACCESSOR(Add)
558};
559
560
561class LAddI final : public LTemplateInstruction<1, 2, 0> {
562 public:
563 LAddI(LOperand* left, LOperand* right)
564 : shift_(NO_SHIFT), shift_amount_(0) {
565 inputs_[0] = left;
566 inputs_[1] = right;
567 }
568
569 LAddI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount)
570 : shift_(shift), shift_amount_(shift_amount) {
571 inputs_[0] = left;
572 inputs_[1] = right;
573 }
574
575 LOperand* left() { return inputs_[0]; }
576 LOperand* right() { return inputs_[1]; }
577
578 Shift shift() const { return shift_; }
579 LOperand* shift_amount() const { return shift_amount_; }
580
581 DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i")
582 DECLARE_HYDROGEN_ACCESSOR(Add)
583
584 protected:
585 Shift shift_;
586 LOperand* shift_amount_;
587};
588
589
590class LAddS final : public LTemplateInstruction<1, 2, 0> {
591 public:
592 LAddS(LOperand* left, LOperand* right) {
593 inputs_[0] = left;
594 inputs_[1] = right;
595 }
596
597 LOperand* left() { return inputs_[0]; }
598 LOperand* right() { return inputs_[1]; }
599
600 DECLARE_CONCRETE_INSTRUCTION(AddS, "add-s")
601 DECLARE_HYDROGEN_ACCESSOR(Add)
602};
603
604
605class LAllocate final : public LTemplateInstruction<1, 2, 3> {
606 public:
607 LAllocate(LOperand* context,
608 LOperand* size,
609 LOperand* temp1,
610 LOperand* temp2,
611 LOperand* temp3) {
612 inputs_[0] = context;
613 inputs_[1] = size;
614 temps_[0] = temp1;
615 temps_[1] = temp2;
616 temps_[2] = temp3;
617 }
618
619 LOperand* context() { return inputs_[0]; }
620 LOperand* size() { return inputs_[1]; }
621 LOperand* temp1() { return temps_[0]; }
622 LOperand* temp2() { return temps_[1]; }
623 LOperand* temp3() { return temps_[2]; }
624
625 DECLARE_CONCRETE_INSTRUCTION(Allocate, "allocate")
626 DECLARE_HYDROGEN_ACCESSOR(Allocate)
627};
628
629
630class LApplyArguments final : public LTemplateInstruction<1, 4, 0> {
631 public:
632 LApplyArguments(LOperand* function,
633 LOperand* receiver,
634 LOperand* length,
635 LOperand* elements) {
636 inputs_[0] = function;
637 inputs_[1] = receiver;
638 inputs_[2] = length;
639 inputs_[3] = elements;
640 }
641
642 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply-arguments")
Ben Murdochda12d292016-06-02 14:46:10 +0100643 DECLARE_HYDROGEN_ACCESSOR(ApplyArguments)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000644
645 LOperand* function() { return inputs_[0]; }
646 LOperand* receiver() { return inputs_[1]; }
647 LOperand* length() { return inputs_[2]; }
648 LOperand* elements() { return inputs_[3]; }
649};
650
651
652class LArgumentsElements final : public LTemplateInstruction<1, 0, 1> {
653 public:
654 explicit LArgumentsElements(LOperand* temp) {
655 temps_[0] = temp;
656 }
657
658 LOperand* temp() { return temps_[0]; }
659
660 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments-elements")
661 DECLARE_HYDROGEN_ACCESSOR(ArgumentsElements)
662};
663
664
665class LArgumentsLength final : public LTemplateInstruction<1, 1, 0> {
666 public:
667 explicit LArgumentsLength(LOperand* elements) {
668 inputs_[0] = elements;
669 }
670
671 LOperand* elements() { return inputs_[0]; }
672
673 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments-length")
674};
675
676
677class LArithmeticD final : public LTemplateInstruction<1, 2, 0> {
678 public:
679 LArithmeticD(Token::Value op,
680 LOperand* left,
681 LOperand* right)
682 : op_(op) {
683 inputs_[0] = left;
684 inputs_[1] = right;
685 }
686
687 Token::Value op() const { return op_; }
688 LOperand* left() { return inputs_[0]; }
689 LOperand* right() { return inputs_[1]; }
690
691 Opcode opcode() const override { return LInstruction::kArithmeticD; }
692 void CompileToNative(LCodeGen* generator) override;
693 const char* Mnemonic() const override;
694
695 private:
696 Token::Value op_;
697};
698
699
700class LArithmeticT final : public LTemplateInstruction<1, 3, 0> {
701 public:
702 LArithmeticT(Token::Value op,
703 LOperand* context,
704 LOperand* left,
705 LOperand* right)
706 : op_(op) {
707 inputs_[0] = context;
708 inputs_[1] = left;
709 inputs_[2] = right;
710 }
711
712 LOperand* context() { return inputs_[0]; }
713 LOperand* left() { return inputs_[1]; }
714 LOperand* right() { return inputs_[2]; }
715 Token::Value op() const { return op_; }
716
717 Opcode opcode() const override { return LInstruction::kArithmeticT; }
718 void CompileToNative(LCodeGen* generator) override;
719 const char* Mnemonic() const override;
720
721 DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)
722
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000723 private:
724 Token::Value op_;
725};
726
727
728class LBoundsCheck final : public LTemplateInstruction<0, 2, 0> {
729 public:
730 explicit LBoundsCheck(LOperand* index, LOperand* length) {
731 inputs_[0] = index;
732 inputs_[1] = length;
733 }
734
735 LOperand* index() { return inputs_[0]; }
736 LOperand* length() { return inputs_[1]; }
737
738 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
739 DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
740};
741
742
743class LBitI final : public LTemplateInstruction<1, 2, 0> {
744 public:
745 LBitI(LOperand* left, LOperand* right)
746 : shift_(NO_SHIFT), shift_amount_(0) {
747 inputs_[0] = left;
748 inputs_[1] = right;
749 }
750
751 LBitI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount)
752 : shift_(shift), shift_amount_(shift_amount) {
753 inputs_[0] = left;
754 inputs_[1] = right;
755 }
756
757 LOperand* left() { return inputs_[0]; }
758 LOperand* right() { return inputs_[1]; }
759
760 Shift shift() const { return shift_; }
761 LOperand* shift_amount() const { return shift_amount_; }
762
763 Token::Value op() const { return hydrogen()->op(); }
764
765 DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i")
766 DECLARE_HYDROGEN_ACCESSOR(Bitwise)
767
768 protected:
769 Shift shift_;
770 LOperand* shift_amount_;
771};
772
773
774class LBitS final : public LTemplateInstruction<1, 2, 0> {
775 public:
776 LBitS(LOperand* left, LOperand* right) {
777 inputs_[0] = left;
778 inputs_[1] = right;
779 }
780
781 LOperand* left() { return inputs_[0]; }
782 LOperand* right() { return inputs_[1]; }
783
784 Token::Value op() const { return hydrogen()->op(); }
785
786 DECLARE_CONCRETE_INSTRUCTION(BitS, "bit-s")
787 DECLARE_HYDROGEN_ACCESSOR(Bitwise)
788};
789
790
791class LBranch final : public LControlInstruction<1, 2> {
792 public:
793 explicit LBranch(LOperand* value, LOperand *temp1, LOperand *temp2) {
794 inputs_[0] = value;
795 temps_[0] = temp1;
796 temps_[1] = temp2;
797 }
798
799 LOperand* value() { return inputs_[0]; }
800 LOperand* temp1() { return temps_[0]; }
801 LOperand* temp2() { return temps_[1]; }
802
803 DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
804 DECLARE_HYDROGEN_ACCESSOR(Branch)
805
806 void PrintDataTo(StringStream* stream) override;
807};
808
809
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000810class LCallNewArray final : public LTemplateInstruction<1, 2, 0> {
811 public:
812 LCallNewArray(LOperand* context, LOperand* constructor) {
813 inputs_[0] = context;
814 inputs_[1] = constructor;
815 }
816
817 LOperand* context() { return inputs_[0]; }
818 LOperand* constructor() { return inputs_[1]; }
819
820 DECLARE_CONCRETE_INSTRUCTION(CallNewArray, "call-new-array")
821 DECLARE_HYDROGEN_ACCESSOR(CallNewArray)
822
823 void PrintDataTo(StringStream* stream) override;
824
825 int arity() const { return hydrogen()->argument_count() - 1; }
826};
827
828
829class LCallRuntime final : public LTemplateInstruction<1, 1, 0> {
830 public:
831 explicit LCallRuntime(LOperand* context) {
832 inputs_[0] = context;
833 }
834
835 LOperand* context() { return inputs_[0]; }
836
837 DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
838 DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
839
840 bool ClobbersDoubleRegisters(Isolate* isolate) const override {
841 return save_doubles() == kDontSaveFPRegs;
842 }
843
844 const Runtime::Function* function() const { return hydrogen()->function(); }
845 int arity() const { return hydrogen()->argument_count(); }
846 SaveFPRegsMode save_doubles() const { return hydrogen()->save_doubles(); }
847};
848
849
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000850class LCheckArrayBufferNotNeutered final
851 : public LTemplateInstruction<0, 1, 0> {
852 public:
853 explicit LCheckArrayBufferNotNeutered(LOperand* view) { inputs_[0] = view; }
854
855 LOperand* view() { return inputs_[0]; }
856
857 DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered,
858 "check-array-buffer-not-neutered")
859 DECLARE_HYDROGEN_ACCESSOR(CheckArrayBufferNotNeutered)
860};
861
862
863class LCheckInstanceType final : public LTemplateInstruction<0, 1, 1> {
864 public:
865 explicit LCheckInstanceType(LOperand* value, LOperand* temp) {
866 inputs_[0] = value;
867 temps_[0] = temp;
868 }
869
870 LOperand* value() { return inputs_[0]; }
871 LOperand* temp() { return temps_[0]; }
872
873 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type")
874 DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType)
875};
876
877
878class LCheckMaps final : public LTemplateInstruction<0, 1, 1> {
879 public:
880 explicit LCheckMaps(LOperand* value = NULL, LOperand* temp = NULL) {
881 inputs_[0] = value;
882 temps_[0] = temp;
883 }
884
885 LOperand* value() { return inputs_[0]; }
886 LOperand* temp() { return temps_[0]; }
887
888 DECLARE_CONCRETE_INSTRUCTION(CheckMaps, "check-maps")
889 DECLARE_HYDROGEN_ACCESSOR(CheckMaps)
890};
891
892
893class LCheckNonSmi final : public LTemplateInstruction<0, 1, 0> {
894 public:
895 explicit LCheckNonSmi(LOperand* value) {
896 inputs_[0] = value;
897 }
898
899 LOperand* value() { return inputs_[0]; }
900
901 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi")
902 DECLARE_HYDROGEN_ACCESSOR(CheckHeapObject)
903};
904
905
906class LCheckSmi final : public LTemplateInstruction<1, 1, 0> {
907 public:
908 explicit LCheckSmi(LOperand* value) {
909 inputs_[0] = value;
910 }
911
912 LOperand* value() { return inputs_[0]; }
913
914 DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi")
915};
916
917
918class LCheckValue final : public LTemplateInstruction<0, 1, 0> {
919 public:
920 explicit LCheckValue(LOperand* value) {
921 inputs_[0] = value;
922 }
923
924 LOperand* value() { return inputs_[0]; }
925
926 DECLARE_CONCRETE_INSTRUCTION(CheckValue, "check-value")
927 DECLARE_HYDROGEN_ACCESSOR(CheckValue)
928};
929
930
931class LClampDToUint8 final : public LTemplateInstruction<1, 1, 0> {
932 public:
933 explicit LClampDToUint8(LOperand* unclamped) {
934 inputs_[0] = unclamped;
935 }
936
937 LOperand* unclamped() { return inputs_[0]; }
938
939 DECLARE_CONCRETE_INSTRUCTION(ClampDToUint8, "clamp-d-to-uint8")
940};
941
942
943class LClampIToUint8 final : public LTemplateInstruction<1, 1, 0> {
944 public:
945 explicit LClampIToUint8(LOperand* unclamped) {
946 inputs_[0] = unclamped;
947 }
948
949 LOperand* unclamped() { return inputs_[0]; }
950
951 DECLARE_CONCRETE_INSTRUCTION(ClampIToUint8, "clamp-i-to-uint8")
952};
953
954
955class LClampTToUint8 final : public LTemplateInstruction<1, 1, 1> {
956 public:
957 LClampTToUint8(LOperand* unclamped, LOperand* temp1) {
958 inputs_[0] = unclamped;
959 temps_[0] = temp1;
960 }
961
962 LOperand* unclamped() { return inputs_[0]; }
963 LOperand* temp1() { return temps_[0]; }
964
965 DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8, "clamp-t-to-uint8")
966};
967
968
969class LDoubleBits final : public LTemplateInstruction<1, 1, 0> {
970 public:
971 explicit LDoubleBits(LOperand* value) {
972 inputs_[0] = value;
973 }
974
975 LOperand* value() { return inputs_[0]; }
976
977 DECLARE_CONCRETE_INSTRUCTION(DoubleBits, "double-bits")
978 DECLARE_HYDROGEN_ACCESSOR(DoubleBits)
979};
980
981
982class LConstructDouble final : public LTemplateInstruction<1, 2, 0> {
983 public:
984 LConstructDouble(LOperand* hi, LOperand* lo) {
985 inputs_[0] = hi;
986 inputs_[1] = lo;
987 }
988
989 LOperand* hi() { return inputs_[0]; }
990 LOperand* lo() { return inputs_[1]; }
991
992 DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
993};
994
995
996class LClassOfTestAndBranch final : public LControlInstruction<1, 2> {
997 public:
998 LClassOfTestAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) {
999 inputs_[0] = value;
1000 temps_[0] = temp1;
1001 temps_[1] = temp2;
1002 }
1003
1004 LOperand* value() { return inputs_[0]; }
1005 LOperand* temp1() { return temps_[0]; }
1006 LOperand* temp2() { return temps_[1]; }
1007
1008 DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch,
1009 "class-of-test-and-branch")
1010 DECLARE_HYDROGEN_ACCESSOR(ClassOfTestAndBranch)
1011
1012 void PrintDataTo(StringStream* stream) override;
1013};
1014
1015
1016class LCmpHoleAndBranchD final : public LControlInstruction<1, 1> {
1017 public:
1018 explicit LCmpHoleAndBranchD(LOperand* object, LOperand* temp) {
1019 inputs_[0] = object;
1020 temps_[0] = temp;
1021 }
1022
1023 LOperand* object() { return inputs_[0]; }
1024 LOperand* temp() { return temps_[0]; }
1025
1026 DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranchD, "cmp-hole-and-branch-d")
1027 DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch)
1028};
1029
1030
1031class LCmpHoleAndBranchT final : public LControlInstruction<1, 0> {
1032 public:
1033 explicit LCmpHoleAndBranchT(LOperand* object) {
1034 inputs_[0] = object;
1035 }
1036
1037 LOperand* object() { return inputs_[0]; }
1038
1039 DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranchT, "cmp-hole-and-branch-t")
1040 DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch)
1041};
1042
1043
1044class LCmpMapAndBranch final : public LControlInstruction<1, 1> {
1045 public:
1046 LCmpMapAndBranch(LOperand* value, LOperand* temp) {
1047 inputs_[0] = value;
1048 temps_[0] = temp;
1049 }
1050
1051 LOperand* value() { return inputs_[0]; }
1052 LOperand* temp() { return temps_[0]; }
1053
1054 DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
1055 DECLARE_HYDROGEN_ACCESSOR(CompareMap)
1056
1057 Handle<Map> map() const { return hydrogen()->map().handle(); }
1058};
1059
1060
1061class LCmpObjectEqAndBranch final : public LControlInstruction<2, 0> {
1062 public:
1063 LCmpObjectEqAndBranch(LOperand* left, LOperand* right) {
1064 inputs_[0] = left;
1065 inputs_[1] = right;
1066 }
1067
1068 LOperand* left() { return inputs_[0]; }
1069 LOperand* right() { return inputs_[1]; }
1070
1071 DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch, "cmp-object-eq-and-branch")
1072 DECLARE_HYDROGEN_ACCESSOR(CompareObjectEqAndBranch)
1073};
1074
1075
1076class LCmpT final : public LTemplateInstruction<1, 3, 0> {
1077 public:
1078 LCmpT(LOperand* context, LOperand* left, LOperand* right) {
1079 inputs_[0] = context;
1080 inputs_[1] = left;
1081 inputs_[2] = right;
1082 }
1083
1084 LOperand* context() { return inputs_[0]; }
1085 LOperand* left() { return inputs_[1]; }
1086 LOperand* right() { return inputs_[2]; }
1087
1088 DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t")
1089 DECLARE_HYDROGEN_ACCESSOR(CompareGeneric)
1090
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001091 Token::Value op() const { return hydrogen()->token(); }
1092};
1093
1094
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001095class LCompareNumericAndBranch final : public LControlInstruction<2, 0> {
1096 public:
1097 LCompareNumericAndBranch(LOperand* left, LOperand* right) {
1098 inputs_[0] = left;
1099 inputs_[1] = right;
1100 }
1101
1102 LOperand* left() { return inputs_[0]; }
1103 LOperand* right() { return inputs_[1]; }
1104
1105 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch,
1106 "compare-numeric-and-branch")
1107 DECLARE_HYDROGEN_ACCESSOR(CompareNumericAndBranch)
1108
1109 Token::Value op() const { return hydrogen()->token(); }
1110 bool is_double() const {
1111 return hydrogen()->representation().IsDouble();
1112 }
1113
1114 void PrintDataTo(StringStream* stream) override;
1115};
1116
1117
1118class LConstantD final : public LTemplateInstruction<1, 0, 0> {
1119 public:
1120 DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
1121 DECLARE_HYDROGEN_ACCESSOR(Constant)
1122
1123 double value() const { return hydrogen()->DoubleValue(); }
1124};
1125
1126
1127class LConstantE final : public LTemplateInstruction<1, 0, 0> {
1128 public:
1129 DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e")
1130 DECLARE_HYDROGEN_ACCESSOR(Constant)
1131
1132 ExternalReference value() const {
1133 return hydrogen()->ExternalReferenceValue();
1134 }
1135};
1136
1137
1138class LConstantI final : public LTemplateInstruction<1, 0, 0> {
1139 public:
1140 DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i")
1141 DECLARE_HYDROGEN_ACCESSOR(Constant)
1142
1143 int32_t value() const { return hydrogen()->Integer32Value(); }
1144};
1145
1146
1147class LConstantS final : public LTemplateInstruction<1, 0, 0> {
1148 public:
1149 DECLARE_CONCRETE_INSTRUCTION(ConstantS, "constant-s")
1150 DECLARE_HYDROGEN_ACCESSOR(Constant)
1151
1152 Smi* value() const { return Smi::FromInt(hydrogen()->Integer32Value()); }
1153};
1154
1155
1156class LConstantT final : public LTemplateInstruction<1, 0, 0> {
1157 public:
1158 DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
1159 DECLARE_HYDROGEN_ACCESSOR(Constant)
1160
1161 Handle<Object> value(Isolate* isolate) const {
1162 return hydrogen()->handle(isolate);
1163 }
1164};
1165
1166
1167class LContext final : public LTemplateInstruction<1, 0, 0> {
1168 public:
1169 DECLARE_CONCRETE_INSTRUCTION(Context, "context")
1170 DECLARE_HYDROGEN_ACCESSOR(Context)
1171};
1172
1173
1174class LDebugBreak final : public LTemplateInstruction<0, 0, 0> {
1175 public:
1176 DECLARE_CONCRETE_INSTRUCTION(DebugBreak, "break")
1177};
1178
1179
1180class LDeclareGlobals final : public LTemplateInstruction<0, 1, 0> {
1181 public:
1182 explicit LDeclareGlobals(LOperand* context) {
1183 inputs_[0] = context;
1184 }
1185
1186 LOperand* context() { return inputs_[0]; }
1187
1188 DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals, "declare-globals")
1189 DECLARE_HYDROGEN_ACCESSOR(DeclareGlobals)
1190};
1191
1192
1193class LDeoptimize final : public LTemplateInstruction<0, 0, 0> {
1194 public:
1195 bool IsControl() const override { return true; }
1196 DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
1197 DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
1198};
1199
1200
1201class LDivByPowerOf2I final : public LTemplateInstruction<1, 1, 0> {
1202 public:
1203 LDivByPowerOf2I(LOperand* dividend, int32_t divisor) {
1204 inputs_[0] = dividend;
1205 divisor_ = divisor;
1206 }
1207
1208 LOperand* dividend() { return inputs_[0]; }
1209 int32_t divisor() const { return divisor_; }
1210
1211 DECLARE_CONCRETE_INSTRUCTION(DivByPowerOf2I, "div-by-power-of-2-i")
1212 DECLARE_HYDROGEN_ACCESSOR(Div)
1213
1214 private:
1215 int32_t divisor_;
1216};
1217
1218
1219class LDivByConstI final : public LTemplateInstruction<1, 1, 1> {
1220 public:
1221 LDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
1222 inputs_[0] = dividend;
1223 divisor_ = divisor;
1224 temps_[0] = temp;
1225 }
1226
1227 LOperand* dividend() { return inputs_[0]; }
1228 int32_t divisor() const { return divisor_; }
1229 LOperand* temp() { return temps_[0]; }
1230
1231 DECLARE_CONCRETE_INSTRUCTION(DivByConstI, "div-by-const-i")
1232 DECLARE_HYDROGEN_ACCESSOR(Div)
1233
1234 private:
1235 int32_t divisor_;
1236};
1237
1238
1239class LDivI final : public LTemplateInstruction<1, 2, 1> {
1240 public:
1241 LDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
1242 inputs_[0] = dividend;
1243 inputs_[1] = divisor;
1244 temps_[0] = temp;
1245 }
1246
1247 LOperand* dividend() { return inputs_[0]; }
1248 LOperand* divisor() { return inputs_[1]; }
1249 LOperand* temp() { return temps_[0]; }
1250
1251 DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
1252 DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)
1253};
1254
1255
1256class LDoubleToIntOrSmi final : public LTemplateInstruction<1, 1, 0> {
1257 public:
1258 explicit LDoubleToIntOrSmi(LOperand* value) {
1259 inputs_[0] = value;
1260 }
1261
1262 LOperand* value() { return inputs_[0]; }
1263
1264 DECLARE_CONCRETE_INSTRUCTION(DoubleToIntOrSmi, "double-to-int-or-smi")
1265 DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
1266
1267 bool tag_result() { return hydrogen()->representation().IsSmi(); }
1268};
1269
1270
1271class LForInCacheArray final : public LTemplateInstruction<1, 1, 0> {
1272 public:
1273 explicit LForInCacheArray(LOperand* map) {
1274 inputs_[0] = map;
1275 }
1276
1277 LOperand* map() { return inputs_[0]; }
1278
1279 DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray, "for-in-cache-array")
1280
1281 int idx() {
1282 return HForInCacheArray::cast(this->hydrogen_value())->idx();
1283 }
1284};
1285
1286
1287class LForInPrepareMap final : public LTemplateInstruction<1, 2, 0> {
1288 public:
1289 LForInPrepareMap(LOperand* context, LOperand* object) {
1290 inputs_[0] = context;
1291 inputs_[1] = object;
1292 }
1293
1294 LOperand* context() { return inputs_[0]; }
1295 LOperand* object() { return inputs_[1]; }
1296
1297 DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap, "for-in-prepare-map")
1298};
1299
1300
1301class LGetCachedArrayIndex final : public LTemplateInstruction<1, 1, 0> {
1302 public:
1303 explicit LGetCachedArrayIndex(LOperand* value) {
1304 inputs_[0] = value;
1305 }
1306
1307 LOperand* value() { return inputs_[0]; }
1308
1309 DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get-cached-array-index")
1310 DECLARE_HYDROGEN_ACCESSOR(GetCachedArrayIndex)
1311};
1312
1313
1314class LHasCachedArrayIndexAndBranch final : public LControlInstruction<1, 1> {
1315 public:
1316 LHasCachedArrayIndexAndBranch(LOperand* value, LOperand* temp) {
1317 inputs_[0] = value;
1318 temps_[0] = temp;
1319 }
1320
1321 LOperand* value() { return inputs_[0]; }
1322 LOperand* temp() { return temps_[0]; }
1323
1324 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch,
1325 "has-cached-array-index-and-branch")
1326 DECLARE_HYDROGEN_ACCESSOR(HasCachedArrayIndexAndBranch)
1327
1328 void PrintDataTo(StringStream* stream) override;
1329};
1330
1331
1332class LHasInstanceTypeAndBranch final : public LControlInstruction<1, 1> {
1333 public:
1334 LHasInstanceTypeAndBranch(LOperand* value, LOperand* temp) {
1335 inputs_[0] = value;
1336 temps_[0] = temp;
1337 }
1338
1339 LOperand* value() { return inputs_[0]; }
1340 LOperand* temp() { return temps_[0]; }
1341
1342 DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch,
1343 "has-instance-type-and-branch")
1344 DECLARE_HYDROGEN_ACCESSOR(HasInstanceTypeAndBranch)
1345
1346 void PrintDataTo(StringStream* stream) override;
1347};
1348
1349
1350class LInnerAllocatedObject final : public LTemplateInstruction<1, 2, 0> {
1351 public:
1352 LInnerAllocatedObject(LOperand* base_object, LOperand* offset) {
1353 inputs_[0] = base_object;
1354 inputs_[1] = offset;
1355 }
1356
1357 LOperand* base_object() const { return inputs_[0]; }
1358 LOperand* offset() const { return inputs_[1]; }
1359
1360 void PrintDataTo(StringStream* stream) override;
1361
1362 DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "inner-allocated-object")
1363};
1364
1365
1366class LInstanceOf final : public LTemplateInstruction<1, 3, 0> {
1367 public:
1368 LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
1369 inputs_[0] = context;
1370 inputs_[1] = left;
1371 inputs_[2] = right;
1372 }
1373
1374 LOperand* context() const { return inputs_[0]; }
1375 LOperand* left() const { return inputs_[1]; }
1376 LOperand* right() const { return inputs_[2]; }
1377
1378 DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
1379};
1380
1381
1382class LHasInPrototypeChainAndBranch final : public LControlInstruction<2, 2> {
1383 public:
1384 LHasInPrototypeChainAndBranch(LOperand* object, LOperand* prototype,
1385 LOperand* scratch1, LOperand* scratch2) {
1386 inputs_[0] = object;
1387 inputs_[1] = prototype;
1388 temps_[0] = scratch1;
1389 temps_[1] = scratch2;
1390 }
1391
1392 LOperand* object() const { return inputs_[0]; }
1393 LOperand* prototype() const { return inputs_[1]; }
1394 LOperand* scratch1() const { return temps_[0]; }
1395 LOperand* scratch2() const { return temps_[1]; }
1396
1397 DECLARE_CONCRETE_INSTRUCTION(HasInPrototypeChainAndBranch,
1398 "has-in-prototype-chain-and-branch")
1399 DECLARE_HYDROGEN_ACCESSOR(HasInPrototypeChainAndBranch)
1400};
1401
1402
1403class LInteger32ToDouble final : public LTemplateInstruction<1, 1, 0> {
1404 public:
1405 explicit LInteger32ToDouble(LOperand* value) {
1406 inputs_[0] = value;
1407 }
1408
1409 LOperand* value() { return inputs_[0]; }
1410
1411 DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double")
1412};
1413
1414
1415class LCallWithDescriptor final : public LTemplateResultInstruction<1> {
1416 public:
1417 LCallWithDescriptor(CallInterfaceDescriptor descriptor,
1418 const ZoneList<LOperand*>& operands, Zone* zone)
1419 : descriptor_(descriptor),
1420 inputs_(descriptor.GetRegisterParameterCount() +
1421 kImplicitRegisterParameterCount,
1422 zone) {
1423 DCHECK(descriptor.GetRegisterParameterCount() +
1424 kImplicitRegisterParameterCount ==
1425 operands.length());
1426 inputs_.AddAll(operands, zone);
1427 }
1428
1429 LOperand* target() const { return inputs_[0]; }
1430
1431 CallInterfaceDescriptor descriptor() { return descriptor_; }
1432
1433 DECLARE_HYDROGEN_ACCESSOR(CallWithDescriptor)
1434
1435 // The target and context are passed as implicit parameters that are not
1436 // explicitly listed in the descriptor.
1437 static const int kImplicitRegisterParameterCount = 2;
1438
1439 private:
1440 DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor, "call-with-descriptor")
1441
1442 void PrintDataTo(StringStream* stream) override;
1443
1444 int arity() const { return hydrogen()->argument_count() - 1; }
1445
1446 CallInterfaceDescriptor descriptor_;
1447 ZoneList<LOperand*> inputs_;
1448
1449 // Iterator support.
1450 int InputCount() final { return inputs_.length(); }
1451 LOperand* InputAt(int i) final { return inputs_[i]; }
1452
1453 int TempCount() final { return 0; }
1454 LOperand* TempAt(int i) final { return NULL; }
1455};
1456
1457
1458class LInvokeFunction final : public LTemplateInstruction<1, 2, 0> {
1459 public:
1460 LInvokeFunction(LOperand* context, LOperand* function) {
1461 inputs_[0] = context;
1462 inputs_[1] = function;
1463 }
1464
1465 LOperand* context() { return inputs_[0]; }
1466 LOperand* function() { return inputs_[1]; }
1467
1468 DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
1469 DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
1470
1471 void PrintDataTo(StringStream* stream) override;
1472
1473 int arity() const { return hydrogen()->argument_count() - 1; }
1474};
1475
1476
1477class LIsStringAndBranch final : public LControlInstruction<1, 1> {
1478 public:
1479 LIsStringAndBranch(LOperand* value, LOperand* temp) {
1480 inputs_[0] = value;
1481 temps_[0] = temp;
1482 }
1483
1484 LOperand* value() { return inputs_[0]; }
1485 LOperand* temp() { return temps_[0]; }
1486
1487 DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch")
1488 DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch)
1489
1490 void PrintDataTo(StringStream* stream) override;
1491};
1492
1493
1494class LIsSmiAndBranch final : public LControlInstruction<1, 0> {
1495 public:
1496 explicit LIsSmiAndBranch(LOperand* value) {
1497 inputs_[0] = value;
1498 }
1499
1500 LOperand* value() { return inputs_[0]; }
1501
1502 DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch")
1503 DECLARE_HYDROGEN_ACCESSOR(IsSmiAndBranch)
1504
1505 void PrintDataTo(StringStream* stream) override;
1506};
1507
1508
1509class LIsUndetectableAndBranch final : public LControlInstruction<1, 1> {
1510 public:
1511 explicit LIsUndetectableAndBranch(LOperand* value, LOperand* temp) {
1512 inputs_[0] = value;
1513 temps_[0] = temp;
1514 }
1515
1516 LOperand* value() { return inputs_[0]; }
1517 LOperand* temp() { return temps_[0]; }
1518
1519 DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch,
1520 "is-undetectable-and-branch")
1521 DECLARE_HYDROGEN_ACCESSOR(IsUndetectableAndBranch)
1522
1523 void PrintDataTo(StringStream* stream) override;
1524};
1525
1526
1527class LLoadContextSlot final : public LTemplateInstruction<1, 1, 0> {
1528 public:
1529 explicit LLoadContextSlot(LOperand* context) {
1530 inputs_[0] = context;
1531 }
1532
1533 LOperand* context() { return inputs_[0]; }
1534
1535 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot")
1536 DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot)
1537
1538 int slot_index() const { return hydrogen()->slot_index(); }
1539
1540 void PrintDataTo(StringStream* stream) override;
1541};
1542
1543
1544class LLoadNamedField final : public LTemplateInstruction<1, 1, 0> {
1545 public:
1546 explicit LLoadNamedField(LOperand* object) {
1547 inputs_[0] = object;
1548 }
1549
1550 LOperand* object() { return inputs_[0]; }
1551
1552 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field")
1553 DECLARE_HYDROGEN_ACCESSOR(LoadNamedField)
1554};
1555
1556
1557class LLoadFunctionPrototype final : public LTemplateInstruction<1, 1, 1> {
1558 public:
1559 LLoadFunctionPrototype(LOperand* function, LOperand* temp) {
1560 inputs_[0] = function;
1561 temps_[0] = temp;
1562 }
1563
1564 LOperand* function() { return inputs_[0]; }
1565 LOperand* temp() { return temps_[0]; }
1566
1567 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
1568 DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
1569};
1570
1571
1572class LLoadGlobalGeneric final : public LTemplateInstruction<1, 2, 1> {
1573 public:
1574 LLoadGlobalGeneric(LOperand* context, LOperand* global_object,
1575 LOperand* vector) {
1576 inputs_[0] = context;
1577 inputs_[1] = global_object;
1578 temps_[0] = vector;
1579 }
1580
1581 LOperand* context() { return inputs_[0]; }
1582 LOperand* global_object() { return inputs_[1]; }
1583 LOperand* temp_vector() { return temps_[0]; }
1584
1585 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
1586 DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)
1587
1588 Handle<Object> name() const { return hydrogen()->name(); }
1589 TypeofMode typeof_mode() const { return hydrogen()->typeof_mode(); }
1590};
1591
1592
1593template <int T>
1594class LLoadKeyed : public LTemplateInstruction<1, 3, T> {
1595 public:
1596 LLoadKeyed(LOperand* elements, LOperand* key, LOperand* backing_store_owner) {
1597 this->inputs_[0] = elements;
1598 this->inputs_[1] = key;
1599 this->inputs_[2] = backing_store_owner;
1600 }
1601
1602 LOperand* elements() { return this->inputs_[0]; }
1603 LOperand* key() { return this->inputs_[1]; }
1604 LOperand* backing_store_owner() { return this->inputs_[2]; }
1605 ElementsKind elements_kind() const {
1606 return this->hydrogen()->elements_kind();
1607 }
1608 bool is_external() const {
1609 return this->hydrogen()->is_external();
1610 }
1611 bool is_fixed_typed_array() const {
1612 return hydrogen()->is_fixed_typed_array();
1613 }
1614 bool is_typed_elements() const {
1615 return is_external() || is_fixed_typed_array();
1616 }
1617 uint32_t base_offset() const {
1618 return this->hydrogen()->base_offset();
1619 }
1620 void PrintDataTo(StringStream* stream) override {
1621 this->elements()->PrintTo(stream);
1622 stream->Add("[");
1623 this->key()->PrintTo(stream);
1624 if (this->base_offset() != 0) {
1625 stream->Add(" + %d]", this->base_offset());
1626 } else {
1627 stream->Add("]");
1628 }
1629 }
1630
1631 DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
1632};
1633
1634
1635class LLoadKeyedExternal: public LLoadKeyed<1> {
1636 public:
1637 LLoadKeyedExternal(LOperand* elements, LOperand* key,
1638 LOperand* backing_store_owner, LOperand* temp)
1639 : LLoadKeyed<1>(elements, key, backing_store_owner) {
1640 temps_[0] = temp;
1641 }
1642
1643 LOperand* temp() { return temps_[0]; }
1644
1645 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedExternal, "load-keyed-external");
1646};
1647
1648
1649class LLoadKeyedFixed: public LLoadKeyed<1> {
1650 public:
1651 LLoadKeyedFixed(LOperand* elements, LOperand* key, LOperand* temp)
1652 : LLoadKeyed<1>(elements, key, nullptr) {
1653 temps_[0] = temp;
1654 }
1655
1656 LOperand* temp() { return temps_[0]; }
1657
1658 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFixed, "load-keyed-fixed");
1659};
1660
1661
1662class LLoadKeyedFixedDouble: public LLoadKeyed<1> {
1663 public:
1664 LLoadKeyedFixedDouble(LOperand* elements, LOperand* key, LOperand* temp)
1665 : LLoadKeyed<1>(elements, key, nullptr) {
1666 temps_[0] = temp;
1667 }
1668
1669 LOperand* temp() { return temps_[0]; }
1670
1671 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFixedDouble, "load-keyed-fixed-double");
1672};
1673
1674
1675class LLoadKeyedGeneric final : public LTemplateInstruction<1, 3, 1> {
1676 public:
1677 LLoadKeyedGeneric(LOperand* context, LOperand* object, LOperand* key,
1678 LOperand* vector) {
1679 inputs_[0] = context;
1680 inputs_[1] = object;
1681 inputs_[2] = key;
1682 temps_[0] = vector;
1683 }
1684
1685 LOperand* context() { return inputs_[0]; }
1686 LOperand* object() { return inputs_[1]; }
1687 LOperand* key() { return inputs_[2]; }
1688 LOperand* temp_vector() { return temps_[0]; }
1689
1690 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic")
1691 DECLARE_HYDROGEN_ACCESSOR(LoadKeyedGeneric)
1692};
1693
1694
1695class LLoadNamedGeneric final : public LTemplateInstruction<1, 2, 1> {
1696 public:
1697 LLoadNamedGeneric(LOperand* context, LOperand* object, LOperand* vector) {
1698 inputs_[0] = context;
1699 inputs_[1] = object;
1700 temps_[0] = vector;
1701 }
1702
1703 LOperand* context() { return inputs_[0]; }
1704 LOperand* object() { return inputs_[1]; }
1705 LOperand* temp_vector() { return temps_[0]; }
1706
1707 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic")
1708 DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric)
1709
1710 Handle<Object> name() const { return hydrogen()->name(); }
1711};
1712
1713
1714class LLoadRoot final : public LTemplateInstruction<1, 0, 0> {
1715 public:
1716 DECLARE_CONCRETE_INSTRUCTION(LoadRoot, "load-root")
1717 DECLARE_HYDROGEN_ACCESSOR(LoadRoot)
1718
1719 Heap::RootListIndex index() const { return hydrogen()->index(); }
1720};
1721
1722
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001723template<int T>
1724class LUnaryMathOperation : public LTemplateInstruction<1, 1, T> {
1725 public:
1726 explicit LUnaryMathOperation(LOperand* value) {
1727 this->inputs_[0] = value;
1728 }
1729
1730 LOperand* value() { return this->inputs_[0]; }
1731 BuiltinFunctionId op() const { return this->hydrogen()->op(); }
1732
1733 void PrintDataTo(StringStream* stream) override;
1734
1735 DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
1736};
1737
1738
1739class LMathAbs final : public LUnaryMathOperation<0> {
1740 public:
1741 explicit LMathAbs(LOperand* value) : LUnaryMathOperation<0>(value) {}
1742
1743 DECLARE_CONCRETE_INSTRUCTION(MathAbs, "math-abs")
1744};
1745
1746
1747class LMathAbsTagged: public LTemplateInstruction<1, 2, 3> {
1748 public:
1749 LMathAbsTagged(LOperand* context, LOperand* value,
1750 LOperand* temp1, LOperand* temp2, LOperand* temp3) {
1751 inputs_[0] = context;
1752 inputs_[1] = value;
1753 temps_[0] = temp1;
1754 temps_[1] = temp2;
1755 temps_[2] = temp3;
1756 }
1757
1758 LOperand* context() { return inputs_[0]; }
1759 LOperand* value() { return inputs_[1]; }
1760 LOperand* temp1() { return temps_[0]; }
1761 LOperand* temp2() { return temps_[1]; }
1762 LOperand* temp3() { return temps_[2]; }
1763
1764 DECLARE_CONCRETE_INSTRUCTION(MathAbsTagged, "math-abs-tagged")
1765 DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
1766};
1767
1768
1769class LMathExp final : public LUnaryMathOperation<4> {
1770 public:
1771 LMathExp(LOperand* value,
1772 LOperand* double_temp1,
1773 LOperand* temp1,
1774 LOperand* temp2,
1775 LOperand* temp3)
1776 : LUnaryMathOperation<4>(value) {
1777 temps_[0] = double_temp1;
1778 temps_[1] = temp1;
1779 temps_[2] = temp2;
1780 temps_[3] = temp3;
1781 ExternalReference::InitializeMathExpData();
1782 }
1783
1784 LOperand* double_temp1() { return temps_[0]; }
1785 LOperand* temp1() { return temps_[1]; }
1786 LOperand* temp2() { return temps_[2]; }
1787 LOperand* temp3() { return temps_[3]; }
1788
1789 DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
1790};
1791
1792
1793// Math.floor with a double result.
1794class LMathFloorD final : public LUnaryMathOperation<0> {
1795 public:
1796 explicit LMathFloorD(LOperand* value) : LUnaryMathOperation<0>(value) { }
1797 DECLARE_CONCRETE_INSTRUCTION(MathFloorD, "math-floor-d")
1798};
1799
1800
1801// Math.floor with an integer result.
1802class LMathFloorI final : public LUnaryMathOperation<0> {
1803 public:
1804 explicit LMathFloorI(LOperand* value) : LUnaryMathOperation<0>(value) { }
1805 DECLARE_CONCRETE_INSTRUCTION(MathFloorI, "math-floor-i")
1806};
1807
1808
1809class LFlooringDivByPowerOf2I final : public LTemplateInstruction<1, 1, 0> {
1810 public:
1811 LFlooringDivByPowerOf2I(LOperand* dividend, int32_t divisor) {
1812 inputs_[0] = dividend;
1813 divisor_ = divisor;
1814 }
1815
1816 LOperand* dividend() { return inputs_[0]; }
1817 int32_t divisor() const { return divisor_; }
1818
1819 DECLARE_CONCRETE_INSTRUCTION(FlooringDivByPowerOf2I,
1820 "flooring-div-by-power-of-2-i")
1821 DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
1822
1823 private:
1824 int32_t divisor_;
1825};
1826
1827
1828class LFlooringDivByConstI final : public LTemplateInstruction<1, 1, 2> {
1829 public:
1830 LFlooringDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
1831 inputs_[0] = dividend;
1832 divisor_ = divisor;
1833 temps_[0] = temp;
1834 }
1835
1836 LOperand* dividend() { return inputs_[0]; }
1837 int32_t divisor() const { return divisor_; }
1838 LOperand* temp() { return temps_[0]; }
1839
1840 DECLARE_CONCRETE_INSTRUCTION(FlooringDivByConstI, "flooring-div-by-const-i")
1841 DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
1842
1843 private:
1844 int32_t divisor_;
1845};
1846
1847
1848class LFlooringDivI final : public LTemplateInstruction<1, 2, 1> {
1849 public:
1850 LFlooringDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
1851 inputs_[0] = dividend;
1852 inputs_[1] = divisor;
1853 temps_[0] = temp;
1854 }
1855
1856 LOperand* dividend() { return inputs_[0]; }
1857 LOperand* divisor() { return inputs_[1]; }
1858 LOperand* temp() { return temps_[0]; }
1859
1860 DECLARE_CONCRETE_INSTRUCTION(FlooringDivI, "flooring-div-i")
1861 DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
1862};
1863
1864
1865class LMathLog final : public LUnaryMathOperation<0> {
1866 public:
1867 explicit LMathLog(LOperand* value) : LUnaryMathOperation<0>(value) { }
1868 DECLARE_CONCRETE_INSTRUCTION(MathLog, "math-log")
1869};
1870
1871
1872class LMathClz32 final : public LUnaryMathOperation<0> {
1873 public:
1874 explicit LMathClz32(LOperand* value) : LUnaryMathOperation<0>(value) { }
1875 DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
1876};
1877
1878
1879class LMathMinMax final : public LTemplateInstruction<1, 2, 0> {
1880 public:
1881 LMathMinMax(LOperand* left, LOperand* right) {
1882 inputs_[0] = left;
1883 inputs_[1] = right;
1884 }
1885
1886 LOperand* left() { return inputs_[0]; }
1887 LOperand* right() { return inputs_[1]; }
1888
1889 DECLARE_CONCRETE_INSTRUCTION(MathMinMax, "math-min-max")
1890 DECLARE_HYDROGEN_ACCESSOR(MathMinMax)
1891};
1892
1893
1894class LMathPowHalf final : public LUnaryMathOperation<0> {
1895 public:
1896 explicit LMathPowHalf(LOperand* value) : LUnaryMathOperation<0>(value) { }
1897 DECLARE_CONCRETE_INSTRUCTION(MathPowHalf, "math-pow-half")
1898};
1899
1900
1901// Math.round with an integer result.
1902class LMathRoundD final : public LUnaryMathOperation<0> {
1903 public:
1904 explicit LMathRoundD(LOperand* value)
1905 : LUnaryMathOperation<0>(value) {
1906 }
1907
1908 DECLARE_CONCRETE_INSTRUCTION(MathRoundD, "math-round-d")
1909};
1910
1911
1912// Math.round with an integer result.
1913class LMathRoundI final : public LUnaryMathOperation<1> {
1914 public:
1915 LMathRoundI(LOperand* value, LOperand* temp1)
1916 : LUnaryMathOperation<1>(value) {
1917 temps_[0] = temp1;
1918 }
1919
1920 LOperand* temp1() { return temps_[0]; }
1921
1922 DECLARE_CONCRETE_INSTRUCTION(MathRoundI, "math-round-i")
1923};
1924
1925
1926class LMathFround final : public LUnaryMathOperation<0> {
1927 public:
1928 explicit LMathFround(LOperand* value) : LUnaryMathOperation<0>(value) {}
1929
1930 DECLARE_CONCRETE_INSTRUCTION(MathFround, "math-fround")
1931};
1932
1933
1934class LMathSqrt final : public LUnaryMathOperation<0> {
1935 public:
1936 explicit LMathSqrt(LOperand* value) : LUnaryMathOperation<0>(value) { }
1937 DECLARE_CONCRETE_INSTRUCTION(MathSqrt, "math-sqrt")
1938};
1939
1940
1941class LModByPowerOf2I final : public LTemplateInstruction<1, 1, 0> {
1942 public:
1943 LModByPowerOf2I(LOperand* dividend, int32_t divisor) {
1944 inputs_[0] = dividend;
1945 divisor_ = divisor;
1946 }
1947
1948 LOperand* dividend() { return inputs_[0]; }
1949 int32_t divisor() const { return divisor_; }
1950
1951 DECLARE_CONCRETE_INSTRUCTION(ModByPowerOf2I, "mod-by-power-of-2-i")
1952 DECLARE_HYDROGEN_ACCESSOR(Mod)
1953
1954 private:
1955 int32_t divisor_;
1956};
1957
1958
1959class LModByConstI final : public LTemplateInstruction<1, 1, 1> {
1960 public:
1961 LModByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
1962 inputs_[0] = dividend;
1963 divisor_ = divisor;
1964 temps_[0] = temp;
1965 }
1966
1967 LOperand* dividend() { return inputs_[0]; }
1968 int32_t divisor() const { return divisor_; }
1969 LOperand* temp() { return temps_[0]; }
1970
1971 DECLARE_CONCRETE_INSTRUCTION(ModByConstI, "mod-by-const-i")
1972 DECLARE_HYDROGEN_ACCESSOR(Mod)
1973
1974 private:
1975 int32_t divisor_;
1976};
1977
1978
1979class LModI final : public LTemplateInstruction<1, 2, 0> {
1980 public:
1981 LModI(LOperand* left, LOperand* right) {
1982 inputs_[0] = left;
1983 inputs_[1] = right;
1984 }
1985
1986 LOperand* left() { return inputs_[0]; }
1987 LOperand* right() { return inputs_[1]; }
1988
1989 DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i")
1990 DECLARE_HYDROGEN_ACCESSOR(Mod)
1991};
1992
1993
1994class LMulConstIS final : public LTemplateInstruction<1, 2, 0> {
1995 public:
1996 LMulConstIS(LOperand* left, LConstantOperand* right) {
1997 inputs_[0] = left;
1998 inputs_[1] = right;
1999 }
2000
2001 LOperand* left() { return inputs_[0]; }
2002 LConstantOperand* right() { return LConstantOperand::cast(inputs_[1]); }
2003
2004 DECLARE_CONCRETE_INSTRUCTION(MulConstIS, "mul-const-i-s")
2005 DECLARE_HYDROGEN_ACCESSOR(Mul)
2006};
2007
2008
2009class LMulI final : public LTemplateInstruction<1, 2, 0> {
2010 public:
2011 LMulI(LOperand* left, LOperand* right) {
2012 inputs_[0] = left;
2013 inputs_[1] = right;
2014 }
2015
2016 LOperand* left() { return inputs_[0]; }
2017 LOperand* right() { return inputs_[1]; }
2018
2019 DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i")
2020 DECLARE_HYDROGEN_ACCESSOR(Mul)
2021};
2022
2023
2024class LMulS final : public LTemplateInstruction<1, 2, 0> {
2025 public:
2026 LMulS(LOperand* left, LOperand* right) {
2027 inputs_[0] = left;
2028 inputs_[1] = right;
2029 }
2030
2031 LOperand* left() { return inputs_[0]; }
2032 LOperand* right() { return inputs_[1]; }
2033
2034 DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-s")
2035 DECLARE_HYDROGEN_ACCESSOR(Mul)
2036};
2037
2038
2039class LNumberTagD final : public LTemplateInstruction<1, 1, 2> {
2040 public:
2041 LNumberTagD(LOperand* value, LOperand* temp1, LOperand* temp2) {
2042 inputs_[0] = value;
2043 temps_[0] = temp1;
2044 temps_[1] = temp2;
2045 }
2046
2047 LOperand* value() { return inputs_[0]; }
2048 LOperand* temp1() { return temps_[0]; }
2049 LOperand* temp2() { return temps_[1]; }
2050
2051 DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d")
2052 DECLARE_HYDROGEN_ACCESSOR(Change)
2053};
2054
2055
2056class LNumberTagU final : public LTemplateInstruction<1, 1, 2> {
2057 public:
2058 explicit LNumberTagU(LOperand* value,
2059 LOperand* temp1,
2060 LOperand* temp2) {
2061 inputs_[0] = value;
2062 temps_[0] = temp1;
2063 temps_[1] = temp2;
2064 }
2065
2066 LOperand* value() { return inputs_[0]; }
2067 LOperand* temp1() { return temps_[0]; }
2068 LOperand* temp2() { return temps_[1]; }
2069
2070 DECLARE_CONCRETE_INSTRUCTION(NumberTagU, "number-tag-u")
2071};
2072
2073
2074class LNumberUntagD final : public LTemplateInstruction<1, 1, 1> {
2075 public:
2076 LNumberUntagD(LOperand* value, LOperand* temp) {
2077 inputs_[0] = value;
2078 temps_[0] = temp;
2079 }
2080
2081 LOperand* value() { return inputs_[0]; }
2082
2083 LOperand* temp() { return temps_[0]; }
2084
2085 DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
2086 DECLARE_HYDROGEN_ACCESSOR(Change)
2087};
2088
2089
2090class LParameter final : public LTemplateInstruction<1, 0, 0> {
2091 public:
2092 bool HasInterestingComment(LCodeGen* gen) const override { return false; }
2093 DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
2094};
2095
2096
2097class LPower final : public LTemplateInstruction<1, 2, 0> {
2098 public:
2099 LPower(LOperand* left, LOperand* right) {
2100 inputs_[0] = left;
2101 inputs_[1] = right;
2102 }
2103
2104 LOperand* left() { return inputs_[0]; }
2105 LOperand* right() { return inputs_[1]; }
2106
2107 DECLARE_CONCRETE_INSTRUCTION(Power, "power")
2108 DECLARE_HYDROGEN_ACCESSOR(Power)
2109};
2110
2111
2112class LPreparePushArguments final : public LTemplateInstruction<0, 0, 0> {
2113 public:
2114 explicit LPreparePushArguments(int argc) : argc_(argc) {}
2115
2116 inline int argc() const { return argc_; }
2117
2118 DECLARE_CONCRETE_INSTRUCTION(PreparePushArguments, "prepare-push-arguments")
2119
2120 protected:
2121 int argc_;
2122};
2123
2124
2125class LPushArguments final : public LTemplateResultInstruction<0> {
2126 public:
2127 explicit LPushArguments(Zone* zone,
2128 int capacity = kRecommendedMaxPushedArgs)
2129 : zone_(zone), inputs_(capacity, zone) {}
2130
2131 LOperand* argument(int i) { return inputs_[i]; }
2132 int ArgumentCount() const { return inputs_.length(); }
2133
2134 void AddArgument(LOperand* arg) { inputs_.Add(arg, zone_); }
2135
2136 DECLARE_CONCRETE_INSTRUCTION(PushArguments, "push-arguments")
2137
2138 // It is better to limit the number of arguments pushed simultaneously to
2139 // avoid pressure on the register allocator.
2140 static const int kRecommendedMaxPushedArgs = 4;
2141 bool ShouldSplitPush() const {
2142 return inputs_.length() >= kRecommendedMaxPushedArgs;
2143 }
2144
2145 protected:
2146 Zone* zone_;
2147 ZoneList<LOperand*> inputs_;
2148
2149 private:
2150 // Iterator support.
2151 int InputCount() final { return inputs_.length(); }
2152 LOperand* InputAt(int i) final { return inputs_[i]; }
2153
2154 int TempCount() final { return 0; }
2155 LOperand* TempAt(int i) final { return NULL; }
2156};
2157
2158
2159class LReturn final : public LTemplateInstruction<0, 3, 0> {
2160 public:
2161 LReturn(LOperand* value, LOperand* context, LOperand* parameter_count) {
2162 inputs_[0] = value;
2163 inputs_[1] = context;
2164 inputs_[2] = parameter_count;
2165 }
2166
2167 LOperand* value() { return inputs_[0]; }
2168 LOperand* parameter_count() { return inputs_[2]; }
2169
2170 bool has_constant_parameter_count() {
2171 return parameter_count()->IsConstantOperand();
2172 }
2173 LConstantOperand* constant_parameter_count() {
2174 DCHECK(has_constant_parameter_count());
2175 return LConstantOperand::cast(parameter_count());
2176 }
2177
2178 DECLARE_CONCRETE_INSTRUCTION(Return, "return")
2179};
2180
2181
2182class LSeqStringGetChar final : public LTemplateInstruction<1, 2, 1> {
2183 public:
2184 LSeqStringGetChar(LOperand* string,
2185 LOperand* index,
2186 LOperand* temp) {
2187 inputs_[0] = string;
2188 inputs_[1] = index;
2189 temps_[0] = temp;
2190 }
2191
2192 LOperand* string() { return inputs_[0]; }
2193 LOperand* index() { return inputs_[1]; }
2194 LOperand* temp() { return temps_[0]; }
2195
2196 DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar, "seq-string-get-char")
2197 DECLARE_HYDROGEN_ACCESSOR(SeqStringGetChar)
2198};
2199
2200
2201class LSeqStringSetChar final : public LTemplateInstruction<1, 4, 1> {
2202 public:
2203 LSeqStringSetChar(LOperand* context,
2204 LOperand* string,
2205 LOperand* index,
2206 LOperand* value,
2207 LOperand* temp) {
2208 inputs_[0] = context;
2209 inputs_[1] = string;
2210 inputs_[2] = index;
2211 inputs_[3] = value;
2212 temps_[0] = temp;
2213 }
2214
2215 LOperand* context() { return inputs_[0]; }
2216 LOperand* string() { return inputs_[1]; }
2217 LOperand* index() { return inputs_[2]; }
2218 LOperand* value() { return inputs_[3]; }
2219 LOperand* temp() { return temps_[0]; }
2220
2221 DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char")
2222 DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar)
2223};
2224
2225
2226class LSmiTag final : public LTemplateInstruction<1, 1, 0> {
2227 public:
2228 explicit LSmiTag(LOperand* value) {
2229 inputs_[0] = value;
2230 }
2231
2232 LOperand* value() { return inputs_[0]; }
2233
2234 DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag")
2235 DECLARE_HYDROGEN_ACCESSOR(Change)
2236};
2237
2238
2239class LSmiUntag final : public LTemplateInstruction<1, 1, 0> {
2240 public:
2241 LSmiUntag(LOperand* value, bool needs_check)
2242 : needs_check_(needs_check) {
2243 inputs_[0] = value;
2244 }
2245
2246 LOperand* value() { return inputs_[0]; }
2247 bool needs_check() const { return needs_check_; }
2248
2249 DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
2250
2251 private:
2252 bool needs_check_;
2253};
2254
2255
2256class LStackCheck final : public LTemplateInstruction<0, 1, 0> {
2257 public:
2258 explicit LStackCheck(LOperand* context) {
2259 inputs_[0] = context;
2260 }
2261
2262 LOperand* context() { return inputs_[0]; }
2263
2264 DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check")
2265 DECLARE_HYDROGEN_ACCESSOR(StackCheck)
2266
2267 Label* done_label() { return &done_label_; }
2268
2269 private:
2270 Label done_label_;
2271};
2272
2273
2274template <int T>
2275class LStoreKeyed : public LTemplateInstruction<0, 4, T> {
2276 public:
2277 LStoreKeyed(LOperand* elements, LOperand* key, LOperand* value,
2278 LOperand* backing_store_owner) {
2279 this->inputs_[0] = elements;
2280 this->inputs_[1] = key;
2281 this->inputs_[2] = value;
2282 this->inputs_[3] = backing_store_owner;
2283 }
2284
2285 bool is_external() const { return this->hydrogen()->is_external(); }
2286 bool is_fixed_typed_array() const {
2287 return hydrogen()->is_fixed_typed_array();
2288 }
2289 bool is_typed_elements() const {
2290 return is_external() || is_fixed_typed_array();
2291 }
2292 LOperand* elements() { return this->inputs_[0]; }
2293 LOperand* key() { return this->inputs_[1]; }
2294 LOperand* value() { return this->inputs_[2]; }
2295 LOperand* backing_store_owner() { return this->inputs_[3]; }
2296 ElementsKind elements_kind() const {
2297 return this->hydrogen()->elements_kind();
2298 }
2299
2300 bool NeedsCanonicalization() {
2301 if (hydrogen()->value()->IsAdd() || hydrogen()->value()->IsSub() ||
2302 hydrogen()->value()->IsMul() || hydrogen()->value()->IsDiv()) {
2303 return false;
2304 }
2305 return this->hydrogen()->NeedsCanonicalization();
2306 }
2307 uint32_t base_offset() const { return this->hydrogen()->base_offset(); }
2308
2309 void PrintDataTo(StringStream* stream) override {
2310 this->elements()->PrintTo(stream);
2311 stream->Add("[");
2312 this->key()->PrintTo(stream);
2313 if (this->base_offset() != 0) {
2314 stream->Add(" + %d] <-", this->base_offset());
2315 } else {
2316 stream->Add("] <- ");
2317 }
2318
2319 if (this->value() == NULL) {
2320 DCHECK(hydrogen()->IsConstantHoleStore() &&
2321 hydrogen()->value()->representation().IsDouble());
2322 stream->Add("<the hole(nan)>");
2323 } else {
2324 this->value()->PrintTo(stream);
2325 }
2326 }
2327
2328 DECLARE_HYDROGEN_ACCESSOR(StoreKeyed)
2329};
2330
2331
2332class LStoreKeyedExternal final : public LStoreKeyed<1> {
2333 public:
2334 LStoreKeyedExternal(LOperand* elements, LOperand* key, LOperand* value,
2335 LOperand* backing_store_owner, LOperand* temp)
2336 : LStoreKeyed<1>(elements, key, value, backing_store_owner) {
2337 temps_[0] = temp;
2338 }
2339
2340 LOperand* temp() { return temps_[0]; }
2341
2342 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedExternal, "store-keyed-external")
2343};
2344
2345
2346class LStoreKeyedFixed final : public LStoreKeyed<1> {
2347 public:
2348 LStoreKeyedFixed(LOperand* elements, LOperand* key, LOperand* value,
2349 LOperand* temp)
2350 : LStoreKeyed<1>(elements, key, value, nullptr) {
2351 temps_[0] = temp;
2352 }
2353
2354 LOperand* temp() { return temps_[0]; }
2355
2356 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFixed, "store-keyed-fixed")
2357};
2358
2359
2360class LStoreKeyedFixedDouble final : public LStoreKeyed<1> {
2361 public:
2362 LStoreKeyedFixedDouble(LOperand* elements, LOperand* key, LOperand* value,
2363 LOperand* temp)
2364 : LStoreKeyed<1>(elements, key, value, nullptr) {
2365 temps_[0] = temp;
2366 }
2367
2368 LOperand* temp() { return temps_[0]; }
2369
2370 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFixedDouble,
2371 "store-keyed-fixed-double")
2372};
2373
2374
2375class LStoreKeyedGeneric final : public LTemplateInstruction<0, 4, 2> {
2376 public:
2377 LStoreKeyedGeneric(LOperand* context, LOperand* object, LOperand* key,
2378 LOperand* value, LOperand* slot, LOperand* vector) {
2379 inputs_[0] = context;
2380 inputs_[1] = object;
2381 inputs_[2] = key;
2382 inputs_[3] = value;
2383 temps_[0] = slot;
2384 temps_[1] = vector;
2385 }
2386
2387 LOperand* context() { return inputs_[0]; }
2388 LOperand* object() { return inputs_[1]; }
2389 LOperand* key() { return inputs_[2]; }
2390 LOperand* value() { return inputs_[3]; }
2391 LOperand* temp_slot() { return temps_[0]; }
2392 LOperand* temp_vector() { return temps_[1]; }
2393
2394 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
2395 DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
2396
2397 void PrintDataTo(StringStream* stream) override;
2398
2399 LanguageMode language_mode() { return hydrogen()->language_mode(); }
2400};
2401
2402
2403class LStoreNamedField final : public LTemplateInstruction<0, 2, 2> {
2404 public:
2405 LStoreNamedField(LOperand* object, LOperand* value,
2406 LOperand* temp0, LOperand* temp1) {
2407 inputs_[0] = object;
2408 inputs_[1] = value;
2409 temps_[0] = temp0;
2410 temps_[1] = temp1;
2411 }
2412
2413 LOperand* object() { return inputs_[0]; }
2414 LOperand* value() { return inputs_[1]; }
2415 LOperand* temp0() { return temps_[0]; }
2416 LOperand* temp1() { return temps_[1]; }
2417
2418 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
2419 DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
2420
2421 void PrintDataTo(StringStream* stream) override;
2422
2423 Representation representation() const {
2424 return hydrogen()->field_representation();
2425 }
2426};
2427
2428
2429class LStoreNamedGeneric final : public LTemplateInstruction<0, 3, 2> {
2430 public:
2431 LStoreNamedGeneric(LOperand* context, LOperand* object, LOperand* value,
2432 LOperand* slot, LOperand* vector) {
2433 inputs_[0] = context;
2434 inputs_[1] = object;
2435 inputs_[2] = value;
2436 temps_[0] = slot;
2437 temps_[1] = vector;
2438 }
2439
2440 LOperand* context() { return inputs_[0]; }
2441 LOperand* object() { return inputs_[1]; }
2442 LOperand* value() { return inputs_[2]; }
2443 LOperand* temp_slot() { return temps_[0]; }
2444 LOperand* temp_vector() { return temps_[1]; }
2445
2446 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
2447 DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
2448
2449 void PrintDataTo(StringStream* stream) override;
2450
2451 Handle<Object> name() const { return hydrogen()->name(); }
2452 LanguageMode language_mode() { return hydrogen()->language_mode(); }
2453};
2454
2455
2456class LMaybeGrowElements final : public LTemplateInstruction<1, 5, 0> {
2457 public:
2458 LMaybeGrowElements(LOperand* context, LOperand* object, LOperand* elements,
2459 LOperand* key, LOperand* current_capacity) {
2460 inputs_[0] = context;
2461 inputs_[1] = object;
2462 inputs_[2] = elements;
2463 inputs_[3] = key;
2464 inputs_[4] = current_capacity;
2465 }
2466
2467 LOperand* context() { return inputs_[0]; }
2468 LOperand* object() { return inputs_[1]; }
2469 LOperand* elements() { return inputs_[2]; }
2470 LOperand* key() { return inputs_[3]; }
2471 LOperand* current_capacity() { return inputs_[4]; }
2472
2473 DECLARE_HYDROGEN_ACCESSOR(MaybeGrowElements)
2474 DECLARE_CONCRETE_INSTRUCTION(MaybeGrowElements, "maybe-grow-elements")
2475};
2476
2477
2478class LStringAdd final : public LTemplateInstruction<1, 3, 0> {
2479 public:
2480 LStringAdd(LOperand* context, LOperand* left, LOperand* right) {
2481 inputs_[0] = context;
2482 inputs_[1] = left;
2483 inputs_[2] = right;
2484 }
2485
2486 LOperand* context() { return inputs_[0]; }
2487 LOperand* left() { return inputs_[1]; }
2488 LOperand* right() { return inputs_[2]; }
2489
2490 DECLARE_CONCRETE_INSTRUCTION(StringAdd, "string-add")
2491 DECLARE_HYDROGEN_ACCESSOR(StringAdd)
2492};
2493
2494
2495class LStringCharCodeAt final : public LTemplateInstruction<1, 3, 0> {
2496 public:
2497 LStringCharCodeAt(LOperand* context, LOperand* string, LOperand* index) {
2498 inputs_[0] = context;
2499 inputs_[1] = string;
2500 inputs_[2] = index;
2501 }
2502
2503 LOperand* context() { return inputs_[0]; }
2504 LOperand* string() { return inputs_[1]; }
2505 LOperand* index() { return inputs_[2]; }
2506
2507 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at")
2508 DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt)
2509};
2510
2511
2512class LStringCharFromCode final : public LTemplateInstruction<1, 2, 0> {
2513 public:
2514 LStringCharFromCode(LOperand* context, LOperand* char_code) {
2515 inputs_[0] = context;
2516 inputs_[1] = char_code;
2517 }
2518
2519 LOperand* context() { return inputs_[0]; }
2520 LOperand* char_code() { return inputs_[1]; }
2521
2522 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code")
2523 DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode)
2524};
2525
2526
2527class LStringCompareAndBranch final : public LControlInstruction<3, 0> {
2528 public:
2529 LStringCompareAndBranch(LOperand* context, LOperand* left, LOperand* right) {
2530 inputs_[0] = context;
2531 inputs_[1] = left;
2532 inputs_[2] = right;
2533 }
2534
2535 LOperand* context() { return inputs_[0]; }
2536 LOperand* left() { return inputs_[1]; }
2537 LOperand* right() { return inputs_[2]; }
2538
2539 DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch,
2540 "string-compare-and-branch")
2541 DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch)
2542
2543 Token::Value op() const { return hydrogen()->token(); }
2544
2545 void PrintDataTo(StringStream* stream) override;
2546};
2547
2548
2549// Truncating conversion from a tagged value to an int32.
2550class LTaggedToI final : public LTemplateInstruction<1, 1, 2> {
2551 public:
2552 explicit LTaggedToI(LOperand* value, LOperand* temp1, LOperand* temp2) {
2553 inputs_[0] = value;
2554 temps_[0] = temp1;
2555 temps_[1] = temp2;
2556 }
2557
2558 LOperand* value() { return inputs_[0]; }
2559 LOperand* temp1() { return temps_[0]; }
2560 LOperand* temp2() { return temps_[1]; }
2561
2562 DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
2563 DECLARE_HYDROGEN_ACCESSOR(Change)
2564
2565 bool truncating() { return hydrogen()->CanTruncateToInt32(); }
2566};
2567
2568
2569class LShiftI final : public LTemplateInstruction<1, 2, 0> {
2570 public:
2571 LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
2572 : op_(op), can_deopt_(can_deopt) {
2573 inputs_[0] = left;
2574 inputs_[1] = right;
2575 }
2576
2577 Token::Value op() const { return op_; }
2578 LOperand* left() { return inputs_[0]; }
2579 LOperand* right() { return inputs_[1]; }
2580 bool can_deopt() const { return can_deopt_; }
2581
2582 DECLARE_CONCRETE_INSTRUCTION(ShiftI, "shift-i")
2583
2584 private:
2585 Token::Value op_;
2586 bool can_deopt_;
2587};
2588
2589
2590class LShiftS final : public LTemplateInstruction<1, 2, 0> {
2591 public:
2592 LShiftS(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
2593 : op_(op), can_deopt_(can_deopt) {
2594 inputs_[0] = left;
2595 inputs_[1] = right;
2596 }
2597
2598 Token::Value op() const { return op_; }
2599 LOperand* left() { return inputs_[0]; }
2600 LOperand* right() { return inputs_[1]; }
2601 bool can_deopt() const { return can_deopt_; }
2602
2603 DECLARE_CONCRETE_INSTRUCTION(ShiftS, "shift-s")
2604
2605 private:
2606 Token::Value op_;
2607 bool can_deopt_;
2608};
2609
2610
2611class LStoreCodeEntry final : public LTemplateInstruction<0, 2, 1> {
2612 public:
2613 LStoreCodeEntry(LOperand* function, LOperand* code_object,
2614 LOperand* temp) {
2615 inputs_[0] = function;
2616 inputs_[1] = code_object;
2617 temps_[0] = temp;
2618 }
2619
2620 LOperand* function() { return inputs_[0]; }
2621 LOperand* code_object() { return inputs_[1]; }
2622 LOperand* temp() { return temps_[0]; }
2623
2624 void PrintDataTo(StringStream* stream) override;
2625
2626 DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry, "store-code-entry")
2627 DECLARE_HYDROGEN_ACCESSOR(StoreCodeEntry)
2628};
2629
2630
2631class LStoreContextSlot final : public LTemplateInstruction<0, 2, 1> {
2632 public:
2633 LStoreContextSlot(LOperand* context, LOperand* value, LOperand* temp) {
2634 inputs_[0] = context;
2635 inputs_[1] = value;
2636 temps_[0] = temp;
2637 }
2638
2639 LOperand* context() { return inputs_[0]; }
2640 LOperand* value() { return inputs_[1]; }
2641 LOperand* temp() { return temps_[0]; }
2642
2643 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot")
2644 DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot)
2645
2646 int slot_index() { return hydrogen()->slot_index(); }
2647
2648 void PrintDataTo(StringStream* stream) override;
2649};
2650
2651
2652class LSubI final : public LTemplateInstruction<1, 2, 0> {
2653 public:
2654 LSubI(LOperand* left, LOperand* right)
2655 : shift_(NO_SHIFT), shift_amount_(0) {
2656 inputs_[0] = left;
2657 inputs_[1] = right;
2658 }
2659
2660 LSubI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount)
2661 : shift_(shift), shift_amount_(shift_amount) {
2662 inputs_[0] = left;
2663 inputs_[1] = right;
2664 }
2665
2666 LOperand* left() { return inputs_[0]; }
2667 LOperand* right() { return inputs_[1]; }
2668
2669 Shift shift() const { return shift_; }
2670 LOperand* shift_amount() const { return shift_amount_; }
2671
2672 DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i")
2673 DECLARE_HYDROGEN_ACCESSOR(Sub)
2674
2675 protected:
2676 Shift shift_;
2677 LOperand* shift_amount_;
2678};
2679
2680
2681class LSubS: public LTemplateInstruction<1, 2, 0> {
2682 public:
2683 LSubS(LOperand* left, LOperand* right) {
2684 inputs_[0] = left;
2685 inputs_[1] = right;
2686 }
2687
2688 LOperand* left() { return inputs_[0]; }
2689 LOperand* right() { return inputs_[1]; }
2690
2691 DECLARE_CONCRETE_INSTRUCTION(SubS, "sub-s")
2692 DECLARE_HYDROGEN_ACCESSOR(Sub)
2693};
2694
2695
2696class LThisFunction final : public LTemplateInstruction<1, 0, 0> {
2697 public:
2698 DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
2699 DECLARE_HYDROGEN_ACCESSOR(ThisFunction)
2700};
2701
2702
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002703class LTransitionElementsKind final : public LTemplateInstruction<0, 2, 2> {
2704 public:
2705 LTransitionElementsKind(LOperand* object,
2706 LOperand* context,
2707 LOperand* temp1,
2708 LOperand* temp2) {
2709 inputs_[0] = object;
2710 inputs_[1] = context;
2711 temps_[0] = temp1;
2712 temps_[1] = temp2;
2713 }
2714
2715 LOperand* object() { return inputs_[0]; }
2716 LOperand* context() { return inputs_[1]; }
2717 LOperand* temp1() { return temps_[0]; }
2718 LOperand* temp2() { return temps_[1]; }
2719
2720 DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind,
2721 "transition-elements-kind")
2722 DECLARE_HYDROGEN_ACCESSOR(TransitionElementsKind)
2723
2724 void PrintDataTo(StringStream* stream) override;
2725
2726 Handle<Map> original_map() { return hydrogen()->original_map().handle(); }
2727 Handle<Map> transitioned_map() {
2728 return hydrogen()->transitioned_map().handle();
2729 }
2730 ElementsKind from_kind() const { return hydrogen()->from_kind(); }
2731 ElementsKind to_kind() const { return hydrogen()->to_kind(); }
2732};
2733
2734
2735class LTrapAllocationMemento final : public LTemplateInstruction<0, 1, 2> {
2736 public:
2737 LTrapAllocationMemento(LOperand* object, LOperand* temp1, LOperand* temp2) {
2738 inputs_[0] = object;
2739 temps_[0] = temp1;
2740 temps_[1] = temp2;
2741 }
2742
2743 LOperand* object() { return inputs_[0]; }
2744 LOperand* temp1() { return temps_[0]; }
2745 LOperand* temp2() { return temps_[1]; }
2746
2747 DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento, "trap-allocation-memento")
2748};
2749
2750
2751class LTruncateDoubleToIntOrSmi final : public LTemplateInstruction<1, 1, 0> {
2752 public:
2753 explicit LTruncateDoubleToIntOrSmi(LOperand* value) {
2754 inputs_[0] = value;
2755 }
2756
2757 LOperand* value() { return inputs_[0]; }
2758
2759 DECLARE_CONCRETE_INSTRUCTION(TruncateDoubleToIntOrSmi,
2760 "truncate-double-to-int-or-smi")
2761 DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
2762
2763 bool tag_result() { return hydrogen()->representation().IsSmi(); }
2764};
2765
2766
2767class LTypeof final : public LTemplateInstruction<1, 2, 0> {
2768 public:
2769 LTypeof(LOperand* context, LOperand* value) {
2770 inputs_[0] = context;
2771 inputs_[1] = value;
2772 }
2773
2774 LOperand* context() { return inputs_[0]; }
2775 LOperand* value() { return inputs_[1]; }
2776
2777 DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
2778};
2779
2780
2781class LTypeofIsAndBranch final : public LControlInstruction<1, 2> {
2782 public:
2783 LTypeofIsAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) {
2784 inputs_[0] = value;
2785 temps_[0] = temp1;
2786 temps_[1] = temp2;
2787 }
2788
2789 LOperand* value() { return inputs_[0]; }
2790 LOperand* temp1() { return temps_[0]; }
2791 LOperand* temp2() { return temps_[1]; }
2792
2793 DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch")
2794 DECLARE_HYDROGEN_ACCESSOR(TypeofIsAndBranch)
2795
2796 Handle<String> type_literal() const { return hydrogen()->type_literal(); }
2797
2798 void PrintDataTo(StringStream* stream) override;
2799};
2800
2801
2802class LUint32ToDouble final : public LTemplateInstruction<1, 1, 0> {
2803 public:
2804 explicit LUint32ToDouble(LOperand* value) {
2805 inputs_[0] = value;
2806 }
2807
2808 LOperand* value() { return inputs_[0]; }
2809
2810 DECLARE_CONCRETE_INSTRUCTION(Uint32ToDouble, "uint32-to-double")
2811};
2812
2813
2814class LCheckMapValue final : public LTemplateInstruction<0, 2, 1> {
2815 public:
2816 LCheckMapValue(LOperand* value, LOperand* map, LOperand* temp) {
2817 inputs_[0] = value;
2818 inputs_[1] = map;
2819 temps_[0] = temp;
2820 }
2821
2822 LOperand* value() { return inputs_[0]; }
2823 LOperand* map() { return inputs_[1]; }
2824 LOperand* temp() { return temps_[0]; }
2825
2826 DECLARE_CONCRETE_INSTRUCTION(CheckMapValue, "check-map-value")
2827};
2828
2829
2830class LLoadFieldByIndex final : public LTemplateInstruction<1, 2, 0> {
2831 public:
2832 LLoadFieldByIndex(LOperand* object, LOperand* index) {
2833 inputs_[0] = object;
2834 inputs_[1] = index;
2835 }
2836
2837 LOperand* object() { return inputs_[0]; }
2838 LOperand* index() { return inputs_[1]; }
2839
2840 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex, "load-field-by-index")
2841};
2842
2843
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002844class LWrapReceiver final : public LTemplateInstruction<1, 2, 0> {
2845 public:
2846 LWrapReceiver(LOperand* receiver, LOperand* function) {
2847 inputs_[0] = receiver;
2848 inputs_[1] = function;
2849 }
2850
2851 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
2852 DECLARE_HYDROGEN_ACCESSOR(WrapReceiver)
2853
2854 LOperand* receiver() { return inputs_[0]; }
2855 LOperand* function() { return inputs_[1]; }
2856};
2857
2858
2859class LChunkBuilder;
2860class LPlatformChunk final : public LChunk {
2861 public:
2862 LPlatformChunk(CompilationInfo* info, HGraph* graph)
2863 : LChunk(info, graph) { }
2864
2865 int GetNextSpillIndex();
2866 LOperand* GetNextSpillSlot(RegisterKind kind);
2867};
2868
2869
2870class LChunkBuilder final : public LChunkBuilderBase {
2871 public:
2872 LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator)
2873 : LChunkBuilderBase(info, graph),
2874 current_instruction_(NULL),
2875 current_block_(NULL),
2876 allocator_(allocator) {}
2877
2878 // Build the sequence for the graph.
2879 LPlatformChunk* Build();
2880
2881 // Declare methods that deal with the individual node types.
2882#define DECLARE_DO(type) LInstruction* Do##type(H##type* node);
2883 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
2884#undef DECLARE_DO
2885
2886 LInstruction* DoDivByPowerOf2I(HDiv* instr);
2887 LInstruction* DoDivByConstI(HDiv* instr);
2888 LInstruction* DoDivI(HBinaryOperation* instr);
2889 LInstruction* DoModByPowerOf2I(HMod* instr);
2890 LInstruction* DoModByConstI(HMod* instr);
2891 LInstruction* DoModI(HMod* instr);
2892 LInstruction* DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr);
2893 LInstruction* DoFlooringDivByConstI(HMathFloorOfDiv* instr);
2894 LInstruction* DoFlooringDivI(HMathFloorOfDiv* instr);
2895
2896 static bool HasMagicNumberForDivision(int32_t divisor);
2897
2898 private:
2899 // Methods for getting operands for Use / Define / Temp.
2900 LUnallocated* ToUnallocated(Register reg);
2901 LUnallocated* ToUnallocated(DoubleRegister reg);
2902
2903 // Methods for setting up define-use relationships.
2904 MUST_USE_RESULT LOperand* Use(HValue* value, LUnallocated* operand);
2905 MUST_USE_RESULT LOperand* UseFixed(HValue* value, Register fixed_register);
2906 MUST_USE_RESULT LOperand* UseFixedDouble(HValue* value,
2907 DoubleRegister fixed_register);
2908
2909 // A value that is guaranteed to be allocated to a register.
2910 // The operand created by UseRegister is guaranteed to be live until the end
2911 // of the instruction. This means that register allocator will not reuse its
2912 // register for any other operand inside instruction.
2913 MUST_USE_RESULT LOperand* UseRegister(HValue* value);
2914
2915 // The operand created by UseRegisterAndClobber is guaranteed to be live until
2916 // the end of the end of the instruction, and it may also be used as a scratch
2917 // register by the instruction implementation.
2918 //
2919 // This behaves identically to ARM's UseTempRegister. However, it is renamed
2920 // to discourage its use in ARM64, since in most cases it is better to
2921 // allocate a temporary register for the Lithium instruction.
2922 MUST_USE_RESULT LOperand* UseRegisterAndClobber(HValue* value);
2923
2924 // The operand created by UseRegisterAtStart is guaranteed to be live only at
2925 // instruction start. The register allocator is free to assign the same
2926 // register to some other operand used inside instruction (i.e. temporary or
2927 // output).
2928 MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value);
2929
2930 // An input operand in a register or a constant operand.
2931 MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value);
2932 MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value);
2933
2934 // A constant operand.
2935 MUST_USE_RESULT LConstantOperand* UseConstant(HValue* value);
2936
2937 // An input operand in register, stack slot or a constant operand.
2938 // Will not be moved to a register even if one is freely available.
2939 virtual MUST_USE_RESULT LOperand* UseAny(HValue* value);
2940
2941 // Temporary operand that must be in a register.
2942 MUST_USE_RESULT LUnallocated* TempRegister();
2943
2944 // Temporary operand that must be in a double register.
2945 MUST_USE_RESULT LUnallocated* TempDoubleRegister();
2946
2947 MUST_USE_RESULT LOperand* FixedTemp(Register reg);
2948
2949 // Temporary operand that must be in a fixed double register.
2950 MUST_USE_RESULT LOperand* FixedTemp(DoubleRegister reg);
2951
2952 // Methods for setting up define-use relationships.
2953 // Return the same instruction that they are passed.
2954 LInstruction* Define(LTemplateResultInstruction<1>* instr,
2955 LUnallocated* result);
2956 LInstruction* DefineAsRegister(LTemplateResultInstruction<1>* instr);
2957 LInstruction* DefineAsSpilled(LTemplateResultInstruction<1>* instr,
2958 int index);
2959
2960 LInstruction* DefineSameAsFirst(LTemplateResultInstruction<1>* instr);
2961 LInstruction* DefineFixed(LTemplateResultInstruction<1>* instr,
2962 Register reg);
2963 LInstruction* DefineFixedDouble(LTemplateResultInstruction<1>* instr,
2964 DoubleRegister reg);
2965
2966 enum CanDeoptimize { CAN_DEOPTIMIZE_EAGERLY, CANNOT_DEOPTIMIZE_EAGERLY };
2967
2968 // By default we assume that instruction sequences generated for calls
2969 // cannot deoptimize eagerly and we do not attach environment to this
2970 // instruction.
2971 LInstruction* MarkAsCall(
2972 LInstruction* instr,
2973 HInstruction* hinstr,
2974 CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY);
2975
2976 LInstruction* AssignPointerMap(LInstruction* instr);
2977 LInstruction* AssignEnvironment(LInstruction* instr);
2978
2979 void VisitInstruction(HInstruction* current);
2980 void AddInstruction(LInstruction* instr, HInstruction* current);
2981 void DoBasicBlock(HBasicBlock* block);
2982
2983 int JSShiftAmountFromHConstant(HValue* constant) {
2984 return HConstant::cast(constant)->Integer32Value() & 0x1f;
2985 }
2986 bool LikelyFitsImmField(HInstruction* instr, int imm) {
2987 if (instr->IsAdd() || instr->IsSub()) {
2988 return Assembler::IsImmAddSub(imm) || Assembler::IsImmAddSub(-imm);
2989 } else {
2990 DCHECK(instr->IsBitwise());
2991 unsigned unused_n, unused_imm_s, unused_imm_r;
2992 return Assembler::IsImmLogical(imm, kWRegSizeInBits,
2993 &unused_n, &unused_imm_s, &unused_imm_r);
2994 }
2995 }
2996
2997 // Indicates if a sequence of the form
2998 // lsl x8, x9, #imm
2999 // add x0, x1, x8
3000 // can be replaced with:
3001 // add x0, x1, x9 LSL #imm
3002 // If this is not possible, the function returns NULL. Otherwise it returns a
3003 // pointer to the shift instruction that would be optimized away.
3004 HBitwiseBinaryOperation* CanTransformToShiftedOp(HValue* val,
3005 HValue** left = NULL);
3006 // Checks if all uses of the shift operation can optimize it away.
3007 bool ShiftCanBeOptimizedAway(HBitwiseBinaryOperation* shift);
3008 // Attempts to merge the binary operation and an eventual previous shift
3009 // operation into a single operation. Returns the merged instruction on
3010 // success, and NULL otherwise.
3011 LInstruction* TryDoOpWithShiftedRightOperand(HBinaryOperation* op);
3012 LInstruction* DoShiftedBinaryOp(HBinaryOperation* instr,
3013 HValue* left,
3014 HBitwiseBinaryOperation* shift);
3015
3016 LInstruction* DoShift(Token::Value op, HBitwiseBinaryOperation* instr);
3017 LInstruction* DoArithmeticD(Token::Value op,
3018 HArithmeticBinaryOperation* instr);
3019 LInstruction* DoArithmeticT(Token::Value op,
3020 HBinaryOperation* instr);
3021
3022 HInstruction* current_instruction_;
3023 HBasicBlock* current_block_;
3024 LAllocator* allocator_;
3025
3026 DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
3027};
3028
3029#undef DECLARE_HYDROGEN_ACCESSOR
3030#undef DECLARE_CONCRETE_INSTRUCTION
3031
3032} // namespace internal
3033} // namespace v8
3034
3035#endif // V8_CRANKSHAFT_ARM64_LITHIUM_ARM64_H_