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