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