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