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