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