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