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