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