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