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