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