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