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