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