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