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