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