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