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