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