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