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