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