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