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