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