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