Upstream version 7.35.139.0
[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   bool IsInteger32() const {
1387     return hydrogen()->representation().IsInteger32();
1388   }
1389
1390   DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i")
1391   DECLARE_HYDROGEN_ACCESSOR(Bitwise)
1392 };
1393
1394
1395 class LShiftI V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1396  public:
1397   LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
1398       : op_(op), can_deopt_(can_deopt) {
1399     inputs_[0] = left;
1400     inputs_[1] = right;
1401   }
1402
1403   Token::Value op() const { return op_; }
1404   LOperand* left() { return inputs_[0]; }
1405   LOperand* right() { return inputs_[1]; }
1406   bool can_deopt() const { return can_deopt_; }
1407
1408   DECLARE_CONCRETE_INSTRUCTION(ShiftI, "shift-i")
1409
1410  private:
1411   Token::Value op_;
1412   bool can_deopt_;
1413 };
1414
1415
1416 class LSubI V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1417  public:
1418   LSubI(LOperand* left, LOperand* right) {
1419     inputs_[0] = left;
1420     inputs_[1] = right;
1421   }
1422
1423   LOperand* left() { return inputs_[0]; }
1424   LOperand* right() { return inputs_[1]; }
1425
1426   DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i")
1427   DECLARE_HYDROGEN_ACCESSOR(Sub)
1428 };
1429
1430
1431 class LConstantI V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1432  public:
1433   DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i")
1434   DECLARE_HYDROGEN_ACCESSOR(Constant)
1435
1436   int32_t value() const { return hydrogen()->Integer32Value(); }
1437 };
1438
1439
1440 class LConstantS V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1441  public:
1442   DECLARE_CONCRETE_INSTRUCTION(ConstantS, "constant-s")
1443   DECLARE_HYDROGEN_ACCESSOR(Constant)
1444
1445   Smi* value() const { return Smi::FromInt(hydrogen()->Integer32Value()); }
1446 };
1447
1448
1449 class LConstantD V8_FINAL : public LTemplateInstruction<1, 0, 1> {
1450  public:
1451   explicit LConstantD(LOperand* temp) {
1452     temps_[0] = temp;
1453   }
1454
1455   LOperand* temp() { return temps_[0]; }
1456
1457   DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
1458   DECLARE_HYDROGEN_ACCESSOR(Constant)
1459
1460   double value() const { return hydrogen()->DoubleValue(); }
1461 };
1462
1463
1464 class LConstantE V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1465  public:
1466   DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e")
1467   DECLARE_HYDROGEN_ACCESSOR(Constant)
1468
1469   ExternalReference value() const {
1470     return hydrogen()->ExternalReferenceValue();
1471   }
1472 };
1473
1474
1475 class LConstantT V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1476  public:
1477   DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
1478   DECLARE_HYDROGEN_ACCESSOR(Constant)
1479
1480   Handle<Object> value(Isolate* isolate) const {
1481     return hydrogen()->handle(isolate);
1482   }
1483 };
1484
1485
1486 class LBranch V8_FINAL : public LControlInstruction<1, 0> {
1487  public:
1488   explicit LBranch(LOperand* value) {
1489     inputs_[0] = value;
1490   }
1491
1492   LOperand* value() { return inputs_[0]; }
1493
1494   DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
1495   DECLARE_HYDROGEN_ACCESSOR(Branch)
1496
1497   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1498 };
1499
1500
1501 class LDebugBreak V8_FINAL : public LTemplateInstruction<0, 0, 0> {
1502  public:
1503   DECLARE_CONCRETE_INSTRUCTION(DebugBreak, "break")
1504 };
1505
1506
1507 class LCmpMapAndBranch V8_FINAL : public LControlInstruction<1, 0> {
1508  public:
1509   explicit LCmpMapAndBranch(LOperand* value) {
1510     inputs_[0] = value;
1511   }
1512
1513   LOperand* value() { return inputs_[0]; }
1514
1515   DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
1516   DECLARE_HYDROGEN_ACCESSOR(CompareMap)
1517
1518   Handle<Map> map() const { return hydrogen()->map().handle(); }
1519 };
1520
1521
1522 class LMapEnumLength V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1523  public:
1524   explicit LMapEnumLength(LOperand* value) {
1525     inputs_[0] = value;
1526   }
1527
1528   LOperand* value() { return inputs_[0]; }
1529
1530   DECLARE_CONCRETE_INSTRUCTION(MapEnumLength, "map-enum-length")
1531 };
1532
1533
1534 class LDateField V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1535  public:
1536   LDateField(LOperand* date, Smi* index) : index_(index) {
1537     inputs_[0] = date;
1538   }
1539
1540   LOperand* date() { return inputs_[0]; }
1541   Smi* index() const { return index_; }
1542
1543   DECLARE_CONCRETE_INSTRUCTION(DateField, "date-field")
1544   DECLARE_HYDROGEN_ACCESSOR(DateField)
1545
1546  private:
1547   Smi* index_;
1548 };
1549
1550
1551 class LSeqStringGetChar V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1552  public:
1553   LSeqStringGetChar(LOperand* string, LOperand* index) {
1554     inputs_[0] = string;
1555     inputs_[1] = index;
1556   }
1557
1558   LOperand* string() const { return inputs_[0]; }
1559   LOperand* index() const { return inputs_[1]; }
1560
1561   DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar, "seq-string-get-char")
1562   DECLARE_HYDROGEN_ACCESSOR(SeqStringGetChar)
1563 };
1564
1565
1566 class LSeqStringSetChar V8_FINAL : public LTemplateInstruction<1, 4, 0> {
1567  public:
1568   LSeqStringSetChar(LOperand* context,
1569                     LOperand* string,
1570                     LOperand* index,
1571                     LOperand* value) {
1572     inputs_[0] = context;
1573     inputs_[1] = string;
1574     inputs_[2] = index;
1575     inputs_[3] = value;
1576   }
1577
1578   LOperand* string() { return inputs_[1]; }
1579   LOperand* index() { return inputs_[2]; }
1580   LOperand* value() { return inputs_[3]; }
1581
1582   DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char")
1583   DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar)
1584 };
1585
1586
1587 class LAddI V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1588  public:
1589   LAddI(LOperand* left, LOperand* right) {
1590     inputs_[0] = left;
1591     inputs_[1] = right;
1592   }
1593
1594   LOperand* left() { return inputs_[0]; }
1595   LOperand* right() { return inputs_[1]; }
1596
1597   static bool UseLea(HAdd* add) {
1598     return !add->CheckFlag(HValue::kCanOverflow) &&
1599         add->BetterLeftOperand()->UseCount() > 1;
1600   }
1601
1602   DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i")
1603   DECLARE_HYDROGEN_ACCESSOR(Add)
1604 };
1605
1606
1607 class LMathMinMax V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1608  public:
1609   LMathMinMax(LOperand* left, LOperand* right) {
1610     inputs_[0] = left;
1611     inputs_[1] = right;
1612   }
1613
1614   LOperand* left() { return inputs_[0]; }
1615   LOperand* right() { return inputs_[1]; }
1616
1617   DECLARE_CONCRETE_INSTRUCTION(MathMinMax, "math-min-max")
1618   DECLARE_HYDROGEN_ACCESSOR(MathMinMax)
1619 };
1620
1621
1622 class LPower V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1623  public:
1624   LPower(LOperand* left, LOperand* right) {
1625     inputs_[0] = left;
1626     inputs_[1] = right;
1627   }
1628
1629   LOperand* left() { return inputs_[0]; }
1630   LOperand* right() { return inputs_[1]; }
1631
1632   DECLARE_CONCRETE_INSTRUCTION(Power, "power")
1633   DECLARE_HYDROGEN_ACCESSOR(Power)
1634 };
1635
1636
1637 class LArithmeticD V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1638  public:
1639   LArithmeticD(Token::Value op, LOperand* left, LOperand* right)
1640       : op_(op) {
1641     inputs_[0] = left;
1642     inputs_[1] = right;
1643   }
1644
1645   Token::Value op() const { return op_; }
1646   LOperand* left() { return inputs_[0]; }
1647   LOperand* right() { return inputs_[1]; }
1648
1649   virtual Opcode opcode() const V8_OVERRIDE {
1650     return LInstruction::kArithmeticD;
1651   }
1652   virtual void CompileToNative(LCodeGen* generator) V8_OVERRIDE;
1653   virtual const char* Mnemonic() const V8_OVERRIDE;
1654
1655  private:
1656   Token::Value op_;
1657 };
1658
1659
1660 class LArithmeticT V8_FINAL : public LTemplateInstruction<1, 3, 0> {
1661  public:
1662   LArithmeticT(Token::Value op,
1663                LOperand* context,
1664                LOperand* left,
1665                LOperand* right)
1666       : op_(op) {
1667     inputs_[0] = context;
1668     inputs_[1] = left;
1669     inputs_[2] = right;
1670   }
1671
1672   Token::Value op() const { return op_; }
1673   LOperand* context() { return inputs_[0]; }
1674   LOperand* left() { return inputs_[1]; }
1675   LOperand* right() { return inputs_[2]; }
1676
1677   virtual Opcode opcode() const V8_OVERRIDE {
1678     return LInstruction::kArithmeticT;
1679   }
1680   virtual void CompileToNative(LCodeGen* generator) V8_OVERRIDE;
1681   virtual const char* Mnemonic() const V8_OVERRIDE;
1682
1683  private:
1684   Token::Value op_;
1685 };
1686
1687
1688 class LReturn V8_FINAL : public LTemplateInstruction<0, 3, 0> {
1689  public:
1690   explicit LReturn(LOperand* value,
1691                    LOperand* context,
1692                    LOperand* parameter_count) {
1693     inputs_[0] = value;
1694     inputs_[1] = context;
1695     inputs_[2] = parameter_count;
1696   }
1697
1698   LOperand* value() { return inputs_[0]; }
1699   LOperand* context() { return inputs_[1]; }
1700
1701   bool has_constant_parameter_count() {
1702     return parameter_count()->IsConstantOperand();
1703   }
1704   LConstantOperand* constant_parameter_count() {
1705     ASSERT(has_constant_parameter_count());
1706     return LConstantOperand::cast(parameter_count());
1707   }
1708   LOperand* parameter_count() { return inputs_[2]; }
1709
1710   DECLARE_CONCRETE_INSTRUCTION(Return, "return")
1711   DECLARE_HYDROGEN_ACCESSOR(Return)
1712 };
1713
1714
1715 class LLoadNamedField V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1716  public:
1717   explicit LLoadNamedField(LOperand* object) {
1718     inputs_[0] = object;
1719   }
1720
1721   LOperand* object() { return inputs_[0]; }
1722
1723   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field")
1724   DECLARE_HYDROGEN_ACCESSOR(LoadNamedField)
1725 };
1726
1727
1728 class LLoadNamedGeneric V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1729  public:
1730   explicit LLoadNamedGeneric(LOperand* context, LOperand* object) {
1731     inputs_[0] = context;
1732     inputs_[1] = object;
1733   }
1734
1735   DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic")
1736   DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric)
1737
1738   LOperand* context() { return inputs_[0]; }
1739   LOperand* object() { return inputs_[1]; }
1740   Handle<Object> name() const { return hydrogen()->name(); }
1741 };
1742
1743
1744 class LLoadFunctionPrototype V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1745  public:
1746   explicit LLoadFunctionPrototype(LOperand* function) {
1747     inputs_[0] = function;
1748   }
1749
1750   DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
1751   DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
1752
1753   LOperand* function() { return inputs_[0]; }
1754 };
1755
1756
1757 class LLoadRoot V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1758  public:
1759   DECLARE_CONCRETE_INSTRUCTION(LoadRoot, "load-root")
1760   DECLARE_HYDROGEN_ACCESSOR(LoadRoot)
1761
1762   Heap::RootListIndex index() const { return hydrogen()->index(); }
1763 };
1764
1765
1766 class LLoadKeyed V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1767  public:
1768   LLoadKeyed(LOperand* elements, LOperand* key) {
1769     inputs_[0] = elements;
1770     inputs_[1] = key;
1771   }
1772
1773   DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
1774   DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
1775
1776   bool is_external() const {
1777     return hydrogen()->is_external();
1778   }
1779   bool is_fixed_typed_array() const {
1780     return hydrogen()->is_fixed_typed_array();
1781   }
1782   bool is_typed_elements() const {
1783     return is_external() || is_fixed_typed_array();
1784   }
1785   LOperand* elements() { return inputs_[0]; }
1786   LOperand* key() { return inputs_[1]; }
1787   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1788   uint32_t additional_index() const { return hydrogen()->index_offset(); }
1789   ElementsKind elements_kind() const {
1790     return hydrogen()->elements_kind();
1791   }
1792 };
1793
1794
1795 inline static bool ExternalArrayOpRequiresPreScale(ElementsKind kind) {
1796   return ElementsKindToShiftSize(kind) > static_cast<int>(maximal_scale_factor);
1797 }
1798
1799
1800 class LLoadKeyedGeneric V8_FINAL : public LTemplateInstruction<1, 3, 0> {
1801  public:
1802   LLoadKeyedGeneric(LOperand* context, LOperand* obj, LOperand* key) {
1803     inputs_[0] = context;
1804     inputs_[1] = obj;
1805     inputs_[2] = key;
1806   }
1807
1808   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic")
1809
1810   LOperand* context() { return inputs_[0]; }
1811   LOperand* object() { return inputs_[1]; }
1812   LOperand* key() { return inputs_[2]; }
1813 };
1814
1815
1816 class LLoadGlobalCell V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1817  public:
1818   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell, "load-global-cell")
1819   DECLARE_HYDROGEN_ACCESSOR(LoadGlobalCell)
1820 };
1821
1822
1823 class LLoadGlobalGeneric V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1824  public:
1825   explicit LLoadGlobalGeneric(LOperand* context, LOperand* global_object) {
1826     inputs_[0] = context;
1827     inputs_[1] = global_object;
1828   }
1829
1830   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
1831   DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)
1832
1833   LOperand* context() { return inputs_[0]; }
1834   LOperand* global_object() { return inputs_[1]; }
1835   Handle<Object> name() const { return hydrogen()->name(); }
1836   bool for_typeof() const { return hydrogen()->for_typeof(); }
1837 };
1838
1839
1840 class LStoreGlobalCell V8_FINAL : public LTemplateInstruction<0, 1, 1> {
1841  public:
1842   explicit LStoreGlobalCell(LOperand* value, LOperand* temp) {
1843     inputs_[0] = value;
1844     temps_[0] = temp;
1845   }
1846
1847   LOperand* value() { return inputs_[0]; }
1848   LOperand* temp() { return temps_[0]; }
1849
1850   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell")
1851   DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell)
1852 };
1853
1854
1855 class LLoadContextSlot V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1856  public:
1857   explicit LLoadContextSlot(LOperand* context) {
1858     inputs_[0] = context;
1859   }
1860
1861   LOperand* context() { return inputs_[0]; }
1862
1863   DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot")
1864   DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot)
1865
1866   int slot_index() { return hydrogen()->slot_index(); }
1867
1868   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1869 };
1870
1871
1872 class LStoreContextSlot V8_FINAL : public LTemplateInstruction<0, 2, 1> {
1873  public:
1874   LStoreContextSlot(LOperand* context, LOperand* value, LOperand* temp) {
1875     inputs_[0] = context;
1876     inputs_[1] = value;
1877     temps_[0] = temp;
1878   }
1879
1880   LOperand* context() { return inputs_[0]; }
1881   LOperand* value() { return inputs_[1]; }
1882   LOperand* temp() { return temps_[0]; }
1883
1884   DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot")
1885   DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot)
1886
1887   int slot_index() { return hydrogen()->slot_index(); }
1888
1889   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1890 };
1891
1892
1893 class LPushArgument V8_FINAL : public LTemplateInstruction<0, 1, 0> {
1894  public:
1895   explicit LPushArgument(LOperand* value) {
1896     inputs_[0] = value;
1897   }
1898
1899   LOperand* value() { return inputs_[0]; }
1900
1901   DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push-argument")
1902 };
1903
1904
1905 class LDrop V8_FINAL : public LTemplateInstruction<0, 0, 0> {
1906  public:
1907   explicit LDrop(int count) : count_(count) { }
1908
1909   int count() const { return count_; }
1910
1911   DECLARE_CONCRETE_INSTRUCTION(Drop, "drop")
1912
1913  private:
1914   int count_;
1915 };
1916
1917
1918 class LStoreCodeEntry V8_FINAL: public LTemplateInstruction<0, 1, 1> {
1919  public:
1920   LStoreCodeEntry(LOperand* function, LOperand* code_object) {
1921     inputs_[0] = function;
1922     temps_[0] = code_object;
1923   }
1924
1925   LOperand* function() { return inputs_[0]; }
1926   LOperand* code_object() { return temps_[0]; }
1927
1928   virtual void PrintDataTo(StringStream* stream);
1929
1930   DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry, "store-code-entry")
1931   DECLARE_HYDROGEN_ACCESSOR(StoreCodeEntry)
1932 };
1933
1934
1935 class LInnerAllocatedObject V8_FINAL: public LTemplateInstruction<1, 2, 0> {
1936  public:
1937   LInnerAllocatedObject(LOperand* base_object, LOperand* offset) {
1938     inputs_[0] = base_object;
1939     inputs_[1] = offset;
1940   }
1941
1942   LOperand* base_object() const { return inputs_[0]; }
1943   LOperand* offset() const { return inputs_[1]; }
1944
1945   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1946
1947   DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "inner-allocated-object")
1948 };
1949
1950
1951 class LThisFunction V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1952  public:
1953   DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
1954   DECLARE_HYDROGEN_ACCESSOR(ThisFunction)
1955 };
1956
1957
1958 class LContext V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1959  public:
1960   DECLARE_CONCRETE_INSTRUCTION(Context, "context")
1961   DECLARE_HYDROGEN_ACCESSOR(Context)
1962 };
1963
1964
1965 class LDeclareGlobals V8_FINAL : public LTemplateInstruction<0, 1, 0> {
1966  public:
1967   explicit LDeclareGlobals(LOperand* context) {
1968     inputs_[0] = context;
1969   }
1970
1971   LOperand* context() { return inputs_[0]; }
1972
1973   DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals, "declare-globals")
1974   DECLARE_HYDROGEN_ACCESSOR(DeclareGlobals)
1975 };
1976
1977
1978 class LCallJSFunction V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1979  public:
1980   explicit LCallJSFunction(LOperand* function) {
1981     inputs_[0] = function;
1982   }
1983
1984   LOperand* function() { return inputs_[0]; }
1985
1986   DECLARE_CONCRETE_INSTRUCTION(CallJSFunction, "call-js-function")
1987   DECLARE_HYDROGEN_ACCESSOR(CallJSFunction)
1988
1989   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1990
1991   int arity() const { return hydrogen()->argument_count() - 1; }
1992 };
1993
1994
1995 class LCallWithDescriptor V8_FINAL : public LTemplateResultInstruction<1> {
1996  public:
1997   LCallWithDescriptor(const CallInterfaceDescriptor* descriptor,
1998                       ZoneList<LOperand*>& operands,
1999                       Zone* zone)
2000     : inputs_(descriptor->environment_length() + 1, zone) {
2001     ASSERT(descriptor->environment_length() + 1 == operands.length());
2002     inputs_.AddAll(operands, zone);
2003   }
2004
2005   LOperand* target() const { return inputs_[0]; }
2006
2007  private:
2008   DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor, "call-with-descriptor")
2009   DECLARE_HYDROGEN_ACCESSOR(CallWithDescriptor)
2010
2011   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2012
2013   int arity() const { return hydrogen()->argument_count() - 1; }
2014
2015   ZoneList<LOperand*> inputs_;
2016
2017   // Iterator support.
2018   virtual int InputCount() V8_FINAL V8_OVERRIDE { return inputs_.length(); }
2019   virtual LOperand* InputAt(int i) V8_FINAL V8_OVERRIDE { return inputs_[i]; }
2020
2021   virtual int TempCount() V8_FINAL V8_OVERRIDE { return 0; }
2022   virtual LOperand* TempAt(int i) V8_FINAL V8_OVERRIDE { return NULL; }
2023 };
2024
2025
2026 class LInvokeFunction V8_FINAL : public LTemplateInstruction<1, 2, 0> {
2027  public:
2028   LInvokeFunction(LOperand* context, LOperand* function) {
2029     inputs_[0] = context;
2030     inputs_[1] = function;
2031   }
2032
2033   LOperand* context() { return inputs_[0]; }
2034   LOperand* function() { return inputs_[1]; }
2035
2036   DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
2037   DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
2038
2039   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2040
2041   int arity() const { return hydrogen()->argument_count() - 1; }
2042 };
2043
2044
2045 class LCallFunction V8_FINAL : public LTemplateInstruction<1, 2, 0> {
2046  public:
2047   LCallFunction(LOperand* context, LOperand* function) {
2048     inputs_[0] = context;
2049     inputs_[1] = function;
2050   }
2051
2052   DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call-function")
2053   DECLARE_HYDROGEN_ACCESSOR(CallFunction)
2054
2055   LOperand* context() { return inputs_[0]; }
2056   LOperand* function() { return inputs_[1]; }
2057   int arity() const { return hydrogen()->argument_count() - 1; }
2058 };
2059
2060
2061 class LCallNew V8_FINAL : public LTemplateInstruction<1, 2, 0> {
2062  public:
2063   LCallNew(LOperand* context, LOperand* constructor) {
2064     inputs_[0] = context;
2065     inputs_[1] = constructor;
2066   }
2067
2068   LOperand* context() { return inputs_[0]; }
2069   LOperand* constructor() { return inputs_[1]; }
2070
2071   DECLARE_CONCRETE_INSTRUCTION(CallNew, "call-new")
2072   DECLARE_HYDROGEN_ACCESSOR(CallNew)
2073
2074   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2075
2076   int arity() const { return hydrogen()->argument_count() - 1; }
2077 };
2078
2079
2080 class LCallNewArray V8_FINAL : public LTemplateInstruction<1, 2, 0> {
2081  public:
2082   LCallNewArray(LOperand* context, LOperand* constructor) {
2083     inputs_[0] = context;
2084     inputs_[1] = constructor;
2085   }
2086
2087   LOperand* context() { return inputs_[0]; }
2088   LOperand* constructor() { return inputs_[1]; }
2089
2090   DECLARE_CONCRETE_INSTRUCTION(CallNewArray, "call-new-array")
2091   DECLARE_HYDROGEN_ACCESSOR(CallNewArray)
2092
2093   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2094
2095   int arity() const { return hydrogen()->argument_count() - 1; }
2096 };
2097
2098
2099 class LCallRuntime V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2100  public:
2101   explicit LCallRuntime(LOperand* context) {
2102     inputs_[0] = context;
2103   }
2104
2105   LOperand* context() { return inputs_[0]; }
2106
2107   DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
2108   DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
2109
2110   virtual bool ClobbersDoubleRegisters() const V8_OVERRIDE {
2111     return save_doubles() == kDontSaveFPRegs;
2112   }
2113
2114   const Runtime::Function* function() const { return hydrogen()->function(); }
2115   int arity() const { return hydrogen()->argument_count(); }
2116   SaveFPRegsMode save_doubles() const { return hydrogen()->save_doubles(); }
2117 };
2118
2119
2120 class LInteger32ToDouble V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2121  public:
2122   explicit LInteger32ToDouble(LOperand* value) {
2123     inputs_[0] = value;
2124   }
2125
2126   LOperand* value() { return inputs_[0]; }
2127
2128   DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double")
2129 };
2130
2131
2132 class LUint32ToDouble V8_FINAL : public LTemplateInstruction<1, 1, 1> {
2133  public:
2134   explicit LUint32ToDouble(LOperand* value, LOperand* temp) {
2135     inputs_[0] = value;
2136     temps_[0] = temp;
2137   }
2138
2139   LOperand* value() { return inputs_[0]; }
2140   LOperand* temp() { return temps_[0]; }
2141
2142   DECLARE_CONCRETE_INSTRUCTION(Uint32ToDouble, "uint32-to-double")
2143 };
2144
2145
2146 class LNumberTagI V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2147  public:
2148   explicit LNumberTagI(LOperand* value) {
2149     inputs_[0] = value;
2150   }
2151
2152   LOperand* value() { return inputs_[0]; }
2153
2154   DECLARE_CONCRETE_INSTRUCTION(NumberTagI, "number-tag-i")
2155 };
2156
2157
2158 class LNumberTagU V8_FINAL : public LTemplateInstruction<1, 1, 2> {
2159  public:
2160   LNumberTagU(LOperand* value, LOperand* temp1, LOperand* temp2) {
2161     inputs_[0] = value;
2162     temps_[0] = temp1;
2163     temps_[1] = temp2;
2164   }
2165
2166   LOperand* value() { return inputs_[0]; }
2167   LOperand* temp1() { return temps_[0]; }
2168   LOperand* temp2() { return temps_[1]; }
2169
2170   DECLARE_CONCRETE_INSTRUCTION(NumberTagU, "number-tag-u")
2171 };
2172
2173
2174 class LNumberTagD V8_FINAL : public LTemplateInstruction<1, 1, 1> {
2175  public:
2176   explicit LNumberTagD(LOperand* value, LOperand* temp) {
2177     inputs_[0] = value;
2178     temps_[0] = temp;
2179   }
2180
2181   LOperand* value() { return inputs_[0]; }
2182   LOperand* temp() { return temps_[0]; }
2183
2184   DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d")
2185   DECLARE_HYDROGEN_ACCESSOR(Change)
2186 };
2187
2188
2189 class LSIMD128ToTagged V8_FINAL : public LTemplateInstruction<1, 1, 1> {
2190  public:
2191   explicit LSIMD128ToTagged(LOperand* value, LOperand* temp) {
2192     inputs_[0] = value;
2193     temps_[0] = temp;
2194   }
2195
2196   LOperand* value() { return inputs_[0]; }
2197   LOperand* temp() { return temps_[0]; }
2198
2199   DECLARE_CONCRETE_INSTRUCTION(SIMD128ToTagged, "simd128-tag")
2200   DECLARE_HYDROGEN_ACCESSOR(Change)
2201 };
2202
2203
2204 // Sometimes truncating conversion from a tagged value to an int32.
2205 class LDoubleToI V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2206  public:
2207   explicit LDoubleToI(LOperand* value) {
2208     inputs_[0] = value;
2209   }
2210
2211   LOperand* value() { return inputs_[0]; }
2212
2213   DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i")
2214   DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
2215
2216   bool truncating() { return hydrogen()->CanTruncateToInt32(); }
2217 };
2218
2219
2220 class LDoubleToSmi V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2221  public:
2222   explicit LDoubleToSmi(LOperand* value) {
2223     inputs_[0] = value;
2224   }
2225
2226   LOperand* value() { return inputs_[0]; }
2227
2228   DECLARE_CONCRETE_INSTRUCTION(DoubleToSmi, "double-to-smi")
2229   DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
2230 };
2231
2232
2233 // Truncating conversion from a tagged value to an int32.
2234 class LTaggedToI V8_FINAL : public LTemplateInstruction<1, 1, 1> {
2235  public:
2236   LTaggedToI(LOperand* value, LOperand* temp) {
2237     inputs_[0] = value;
2238     temps_[0] = temp;
2239   }
2240
2241   LOperand* value() { return inputs_[0]; }
2242   LOperand* temp() { return temps_[0]; }
2243
2244   DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
2245   DECLARE_HYDROGEN_ACCESSOR(Change)
2246
2247   bool truncating() { return hydrogen()->CanTruncateToInt32(); }
2248 };
2249
2250
2251 class LSmiTag V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2252  public:
2253   explicit LSmiTag(LOperand* value) {
2254     inputs_[0] = value;
2255   }
2256
2257   LOperand* value() { return inputs_[0]; }
2258
2259   DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag")
2260   DECLARE_HYDROGEN_ACCESSOR(Change)
2261 };
2262
2263
2264 class LNumberUntagD V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2265  public:
2266   explicit LNumberUntagD(LOperand* value) {
2267     inputs_[0] = value;
2268   }
2269
2270   LOperand* value() { return inputs_[0]; }
2271
2272   DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
2273   DECLARE_HYDROGEN_ACCESSOR(Change);
2274 };
2275
2276
2277 class LTaggedToSIMD128 V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2278  public:
2279   explicit LTaggedToSIMD128(LOperand* value, Representation representation)
2280       : representation_(representation) {
2281     inputs_[0] = value;
2282   }
2283
2284   LOperand* value() { return inputs_[0]; }
2285   Representation representation() const { return representation_; }
2286
2287   DECLARE_CONCRETE_INSTRUCTION(TaggedToSIMD128, "simd128-untag")
2288   DECLARE_HYDROGEN_ACCESSOR(Change);
2289  private:
2290   Representation representation_;
2291 };
2292
2293
2294 class LSmiUntag V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2295  public:
2296   LSmiUntag(LOperand* value, bool needs_check)
2297       : needs_check_(needs_check) {
2298     inputs_[0] = value;
2299   }
2300
2301   LOperand* value() { return inputs_[0]; }
2302   bool needs_check() const { return needs_check_; }
2303
2304   DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
2305
2306  private:
2307   bool needs_check_;
2308 };
2309
2310
2311 class LStoreNamedField V8_FINAL : public LTemplateInstruction<0, 2, 1> {
2312  public:
2313   LStoreNamedField(LOperand* object, LOperand* value, LOperand* temp) {
2314     inputs_[0] = object;
2315     inputs_[1] = value;
2316     temps_[0] = temp;
2317   }
2318
2319   LOperand* object() { return inputs_[0]; }
2320   LOperand* value() { return inputs_[1]; }
2321   LOperand* temp() { return temps_[0]; }
2322
2323   DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
2324   DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
2325
2326   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2327
2328   Handle<Map> transition() const { return hydrogen()->transition_map(); }
2329   Representation representation() const {
2330     return hydrogen()->field_representation();
2331   }
2332 };
2333
2334
2335 class LStoreNamedGeneric V8_FINAL : public LTemplateInstruction<0, 3, 0> {
2336  public:
2337   LStoreNamedGeneric(LOperand* context, LOperand* object, LOperand* value) {
2338     inputs_[0] = context;
2339     inputs_[1] = object;
2340     inputs_[2] = value;
2341   }
2342
2343   LOperand* context() { return inputs_[0]; }
2344   LOperand* object() { return inputs_[1]; }
2345   LOperand* value() { return inputs_[2]; }
2346
2347   DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
2348   DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
2349
2350   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2351
2352   Handle<Object> name() const { return hydrogen()->name(); }
2353   StrictMode strict_mode() { return hydrogen()->strict_mode(); }
2354 };
2355
2356
2357 class LStoreKeyed V8_FINAL : public LTemplateInstruction<0, 3, 0> {
2358  public:
2359   LStoreKeyed(LOperand* object, LOperand* key, LOperand* value) {
2360     inputs_[0] = object;
2361     inputs_[1] = key;
2362     inputs_[2] = value;
2363   }
2364
2365   bool is_external() const { return hydrogen()->is_external(); }
2366   bool is_fixed_typed_array() const {
2367     return hydrogen()->is_fixed_typed_array();
2368   }
2369   bool is_typed_elements() const {
2370     return is_external() || is_fixed_typed_array();
2371   }
2372   LOperand* elements() { return inputs_[0]; }
2373   LOperand* key() { return inputs_[1]; }
2374   LOperand* value() { return inputs_[2]; }
2375   ElementsKind elements_kind() const { return hydrogen()->elements_kind(); }
2376
2377   DECLARE_CONCRETE_INSTRUCTION(StoreKeyed, "store-keyed")
2378   DECLARE_HYDROGEN_ACCESSOR(StoreKeyed)
2379
2380   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2381   bool NeedsCanonicalization() { return hydrogen()->NeedsCanonicalization(); }
2382   uint32_t additional_index() const { return hydrogen()->index_offset(); }
2383 };
2384
2385
2386 class LStoreKeyedGeneric V8_FINAL : public LTemplateInstruction<0, 4, 0> {
2387  public:
2388   LStoreKeyedGeneric(LOperand* context,
2389                      LOperand* object,
2390                      LOperand* key,
2391                      LOperand* value) {
2392     inputs_[0] = context;
2393     inputs_[1] = object;
2394     inputs_[2] = key;
2395     inputs_[3] = value;
2396   }
2397
2398   LOperand* context() { return inputs_[0]; }
2399   LOperand* object() { return inputs_[1]; }
2400   LOperand* key() { return inputs_[2]; }
2401   LOperand* value() { return inputs_[3]; }
2402
2403   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
2404   DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
2405
2406   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2407
2408   StrictMode strict_mode() { return hydrogen()->strict_mode(); }
2409 };
2410
2411
2412 class LTransitionElementsKind V8_FINAL : public LTemplateInstruction<0, 2, 2> {
2413  public:
2414   LTransitionElementsKind(LOperand* object,
2415                           LOperand* context,
2416                           LOperand* new_map_temp,
2417                           LOperand* temp) {
2418     inputs_[0] = object;
2419     inputs_[1] = context;
2420     temps_[0] = new_map_temp;
2421     temps_[1] = temp;
2422   }
2423
2424   LOperand* object() { return inputs_[0]; }
2425   LOperand* context() { return inputs_[1]; }
2426   LOperand* new_map_temp() { return temps_[0]; }
2427   LOperand* temp() { return temps_[1]; }
2428
2429   DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind,
2430                                "transition-elements-kind")
2431   DECLARE_HYDROGEN_ACCESSOR(TransitionElementsKind)
2432
2433   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2434
2435   Handle<Map> original_map() { return hydrogen()->original_map().handle(); }
2436   Handle<Map> transitioned_map() {
2437     return hydrogen()->transitioned_map().handle();
2438   }
2439   ElementsKind from_kind() { return hydrogen()->from_kind(); }
2440   ElementsKind to_kind() { return hydrogen()->to_kind(); }
2441 };
2442
2443
2444 class LTrapAllocationMemento V8_FINAL : public LTemplateInstruction<0, 1, 1> {
2445  public:
2446   LTrapAllocationMemento(LOperand* object,
2447                          LOperand* temp) {
2448     inputs_[0] = object;
2449     temps_[0] = temp;
2450   }
2451
2452   LOperand* object() { return inputs_[0]; }
2453   LOperand* temp() { return temps_[0]; }
2454
2455   DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento,
2456                                "trap-allocation-memento")
2457 };
2458
2459
2460 class LStringAdd V8_FINAL : public LTemplateInstruction<1, 3, 0> {
2461  public:
2462   LStringAdd(LOperand* context, LOperand* left, LOperand* right) {
2463     inputs_[0] = context;
2464     inputs_[1] = left;
2465     inputs_[2] = right;
2466   }
2467
2468   LOperand* context() { return inputs_[0]; }
2469   LOperand* left() { return inputs_[1]; }
2470   LOperand* right() { return inputs_[2]; }
2471
2472   DECLARE_CONCRETE_INSTRUCTION(StringAdd, "string-add")
2473   DECLARE_HYDROGEN_ACCESSOR(StringAdd)
2474 };
2475
2476
2477 class LStringCharCodeAt V8_FINAL : public LTemplateInstruction<1, 3, 0> {
2478  public:
2479   LStringCharCodeAt(LOperand* context, LOperand* string, LOperand* index) {
2480     inputs_[0] = context;
2481     inputs_[1] = string;
2482     inputs_[2] = index;
2483   }
2484
2485   LOperand* context() { return inputs_[0]; }
2486   LOperand* string() { return inputs_[1]; }
2487   LOperand* index() { return inputs_[2]; }
2488
2489   DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at")
2490   DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt)
2491 };
2492
2493
2494 class LStringCharFromCode V8_FINAL : public LTemplateInstruction<1, 2, 0> {
2495  public:
2496   explicit LStringCharFromCode(LOperand* context, LOperand* char_code) {
2497     inputs_[0] = context;
2498     inputs_[1] = char_code;
2499   }
2500
2501   LOperand* context() { return inputs_[0]; }
2502   LOperand* char_code() { return inputs_[1]; }
2503
2504   DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code")
2505   DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode)
2506 };
2507
2508
2509 class LCheckValue V8_FINAL : public LTemplateInstruction<0, 1, 0> {
2510  public:
2511   explicit LCheckValue(LOperand* value) {
2512     inputs_[0] = value;
2513   }
2514
2515   LOperand* value() { return inputs_[0]; }
2516
2517   DECLARE_CONCRETE_INSTRUCTION(CheckValue, "check-value")
2518   DECLARE_HYDROGEN_ACCESSOR(CheckValue)
2519 };
2520
2521
2522 class LCheckInstanceType V8_FINAL : public LTemplateInstruction<0, 1, 0> {
2523  public:
2524   explicit LCheckInstanceType(LOperand* value) {
2525     inputs_[0] = value;
2526   }
2527
2528   LOperand* value() { return inputs_[0]; }
2529
2530   DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type")
2531   DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType)
2532 };
2533
2534
2535 class LCheckMaps V8_FINAL : public LTemplateInstruction<0, 1, 0> {
2536  public:
2537   explicit LCheckMaps(LOperand* value) {
2538     inputs_[0] = value;
2539   }
2540
2541   LOperand* value() { return inputs_[0]; }
2542
2543   DECLARE_CONCRETE_INSTRUCTION(CheckMaps, "check-maps")
2544   DECLARE_HYDROGEN_ACCESSOR(CheckMaps)
2545 };
2546
2547
2548 class LCheckSmi V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2549  public:
2550   explicit LCheckSmi(LOperand* value) {
2551     inputs_[0] = value;
2552   }
2553
2554   LOperand* value() { return inputs_[0]; }
2555
2556   DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi")
2557 };
2558
2559
2560 class LClampDToUint8 V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2561  public:
2562   explicit LClampDToUint8(LOperand* unclamped) {
2563     inputs_[0] = unclamped;
2564   }
2565
2566   LOperand* unclamped() { return inputs_[0]; }
2567
2568   DECLARE_CONCRETE_INSTRUCTION(ClampDToUint8, "clamp-d-to-uint8")
2569 };
2570
2571
2572 class LClampIToUint8 V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2573  public:
2574   explicit LClampIToUint8(LOperand* unclamped) {
2575     inputs_[0] = unclamped;
2576   }
2577
2578   LOperand* unclamped() { return inputs_[0]; }
2579
2580   DECLARE_CONCRETE_INSTRUCTION(ClampIToUint8, "clamp-i-to-uint8")
2581 };
2582
2583
2584 class LClampTToUint8 V8_FINAL : public LTemplateInstruction<1, 1, 1> {
2585  public:
2586   LClampTToUint8(LOperand* unclamped,
2587                  LOperand* temp_xmm) {
2588     inputs_[0] = unclamped;
2589     temps_[0] = temp_xmm;
2590   }
2591
2592   LOperand* unclamped() { return inputs_[0]; }
2593   LOperand* temp_xmm() { return temps_[0]; }
2594
2595   DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8, "clamp-t-to-uint8")
2596 };
2597
2598
2599 class LCheckNonSmi V8_FINAL : public LTemplateInstruction<0, 1, 0> {
2600  public:
2601   explicit LCheckNonSmi(LOperand* value) {
2602     inputs_[0] = value;
2603   }
2604
2605   LOperand* value() { return inputs_[0]; }
2606
2607   DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi")
2608   DECLARE_HYDROGEN_ACCESSOR(CheckHeapObject)
2609 };
2610
2611
2612 class LDoubleBits V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2613  public:
2614   explicit LDoubleBits(LOperand* value) {
2615     inputs_[0] = value;
2616   }
2617
2618   LOperand* value() { return inputs_[0]; }
2619
2620   DECLARE_CONCRETE_INSTRUCTION(DoubleBits, "double-bits")
2621   DECLARE_HYDROGEN_ACCESSOR(DoubleBits)
2622 };
2623
2624
2625 class LConstructDouble V8_FINAL : public LTemplateInstruction<1, 2, 0> {
2626  public:
2627   LConstructDouble(LOperand* hi, LOperand* lo) {
2628     inputs_[0] = hi;
2629     inputs_[1] = lo;
2630   }
2631
2632   LOperand* hi() { return inputs_[0]; }
2633   LOperand* lo() { return inputs_[1]; }
2634
2635   DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
2636 };
2637
2638
2639 class LAllocate V8_FINAL : public LTemplateInstruction<1, 2, 1> {
2640  public:
2641   LAllocate(LOperand* context, LOperand* size, LOperand* temp) {
2642     inputs_[0] = context;
2643     inputs_[1] = size;
2644     temps_[0] = temp;
2645   }
2646
2647   LOperand* context() { return inputs_[0]; }
2648   LOperand* size() { return inputs_[1]; }
2649   LOperand* temp() { return temps_[0]; }
2650
2651   DECLARE_CONCRETE_INSTRUCTION(Allocate, "allocate")
2652   DECLARE_HYDROGEN_ACCESSOR(Allocate)
2653 };
2654
2655
2656 class LRegExpLiteral V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2657  public:
2658   explicit LRegExpLiteral(LOperand* context) {
2659     inputs_[0] = context;
2660   }
2661
2662   LOperand* context() { return inputs_[0]; }
2663
2664   DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp-literal")
2665   DECLARE_HYDROGEN_ACCESSOR(RegExpLiteral)
2666 };
2667
2668
2669 class LFunctionLiteral V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2670  public:
2671   explicit LFunctionLiteral(LOperand* context) {
2672     inputs_[0] = context;
2673   }
2674
2675   LOperand* context() { return inputs_[0]; }
2676
2677   DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function-literal")
2678   DECLARE_HYDROGEN_ACCESSOR(FunctionLiteral)
2679 };
2680
2681
2682 class LToFastProperties V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2683  public:
2684   explicit LToFastProperties(LOperand* value) {
2685     inputs_[0] = value;
2686   }
2687
2688   LOperand* value() { return inputs_[0]; }
2689
2690   DECLARE_CONCRETE_INSTRUCTION(ToFastProperties, "to-fast-properties")
2691   DECLARE_HYDROGEN_ACCESSOR(ToFastProperties)
2692 };
2693
2694
2695 class LTypeof V8_FINAL : public LTemplateInstruction<1, 2, 0> {
2696  public:
2697   LTypeof(LOperand* context, LOperand* value) {
2698     inputs_[0] = context;
2699     inputs_[1] = value;
2700   }
2701
2702   LOperand* context() { return inputs_[0]; }
2703   LOperand* value() { return inputs_[1]; }
2704
2705   DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
2706 };
2707
2708
2709 class LTypeofIsAndBranch V8_FINAL : public LControlInstruction<1, 0> {
2710  public:
2711   explicit LTypeofIsAndBranch(LOperand* value) {
2712     inputs_[0] = value;
2713   }
2714
2715   LOperand* value() { return inputs_[0]; }
2716
2717   DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch")
2718   DECLARE_HYDROGEN_ACCESSOR(TypeofIsAndBranch)
2719
2720   Handle<String> type_literal() { return hydrogen()->type_literal(); }
2721
2722   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2723 };
2724
2725
2726 class LIsConstructCallAndBranch V8_FINAL : public LControlInstruction<0, 1> {
2727  public:
2728   explicit LIsConstructCallAndBranch(LOperand* temp) {
2729     temps_[0] = temp;
2730   }
2731
2732   LOperand* temp() { return temps_[0]; }
2733
2734   DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch,
2735                                "is-construct-call-and-branch")
2736   DECLARE_HYDROGEN_ACCESSOR(IsConstructCallAndBranch)
2737 };
2738
2739
2740 class LOsrEntry V8_FINAL : public LTemplateInstruction<0, 0, 0> {
2741  public:
2742   LOsrEntry() {}
2743
2744   virtual bool HasInterestingComment(LCodeGen* gen) const V8_OVERRIDE {
2745     return false;
2746   }
2747   DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry")
2748 };
2749
2750
2751 class LStackCheck V8_FINAL : public LTemplateInstruction<0, 1, 0> {
2752  public:
2753   explicit LStackCheck(LOperand* context) {
2754     inputs_[0] = context;
2755   }
2756
2757   LOperand* context() { return inputs_[0]; }
2758
2759   DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check")
2760   DECLARE_HYDROGEN_ACCESSOR(StackCheck)
2761
2762   Label* done_label() { return &done_label_; }
2763
2764  private:
2765   Label done_label_;
2766 };
2767
2768
2769 class LForInPrepareMap V8_FINAL : public LTemplateInstruction<1, 2, 0> {
2770  public:
2771   LForInPrepareMap(LOperand* context, LOperand* object) {
2772     inputs_[0] = context;
2773     inputs_[1] = object;
2774   }
2775
2776   LOperand* context() { return inputs_[0]; }
2777   LOperand* object() { return inputs_[1]; }
2778
2779   DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap, "for-in-prepare-map")
2780 };
2781
2782
2783 class LForInCacheArray V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2784  public:
2785   explicit LForInCacheArray(LOperand* map) {
2786     inputs_[0] = map;
2787   }
2788
2789   LOperand* map() { return inputs_[0]; }
2790
2791   DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray, "for-in-cache-array")
2792
2793   int idx() {
2794     return HForInCacheArray::cast(this->hydrogen_value())->idx();
2795   }
2796 };
2797
2798
2799 class LCheckMapValue V8_FINAL : public LTemplateInstruction<0, 2, 0> {
2800  public:
2801   LCheckMapValue(LOperand* value, LOperand* map) {
2802     inputs_[0] = value;
2803     inputs_[1] = map;
2804   }
2805
2806   LOperand* value() { return inputs_[0]; }
2807   LOperand* map() { return inputs_[1]; }
2808
2809   DECLARE_CONCRETE_INSTRUCTION(CheckMapValue, "check-map-value")
2810 };
2811
2812
2813 class LLoadFieldByIndex V8_FINAL : public LTemplateInstruction<1, 2, 0> {
2814  public:
2815   LLoadFieldByIndex(LOperand* object, LOperand* index) {
2816     inputs_[0] = object;
2817     inputs_[1] = index;
2818   }
2819
2820   LOperand* object() { return inputs_[0]; }
2821   LOperand* index() { return inputs_[1]; }
2822
2823   DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex, "load-field-by-index")
2824 };
2825
2826
2827 class LChunkBuilder;
2828 class LPlatformChunk V8_FINAL : public LChunk {
2829  public:
2830   LPlatformChunk(CompilationInfo* info, HGraph* graph)
2831       : LChunk(info, graph),
2832         dehoisted_key_ids_(graph->GetMaximumValueID(), graph->zone()) { }
2833
2834   int GetNextSpillIndex(RegisterKind kind);
2835   LOperand* GetNextSpillSlot(RegisterKind kind);
2836   BitVector* GetDehoistedKeyIds() { return &dehoisted_key_ids_; }
2837   bool IsDehoistedKey(HValue* value) {
2838     return dehoisted_key_ids_.Contains(value->id());
2839   }
2840
2841  private:
2842   BitVector dehoisted_key_ids_;
2843 };
2844
2845
2846 class LChunkBuilder V8_FINAL : public LChunkBuilderBase {
2847  public:
2848   LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator)
2849       : LChunkBuilderBase(graph->zone()),
2850         chunk_(NULL),
2851         info_(info),
2852         graph_(graph),
2853         status_(UNUSED),
2854         current_instruction_(NULL),
2855         current_block_(NULL),
2856         next_block_(NULL),
2857         allocator_(allocator) { }
2858
2859   // Build the sequence for the graph.
2860   LPlatformChunk* Build();
2861
2862   LInstruction* CheckElideControlInstruction(HControlInstruction* instr);
2863
2864   // Declare methods that deal with the individual node types.
2865 #define DECLARE_DO(type) LInstruction* Do##type(H##type* node);
2866   HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
2867 #undef DECLARE_DO
2868
2869   LInstruction* DoMathFloor(HUnaryMathOperation* instr);
2870   LInstruction* DoMathRound(HUnaryMathOperation* instr);
2871   LInstruction* DoMathAbs(HUnaryMathOperation* instr);
2872   LInstruction* DoMathLog(HUnaryMathOperation* instr);
2873   LInstruction* DoMathExp(HUnaryMathOperation* instr);
2874   LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
2875   LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);
2876   LInstruction* DoMathClz32(HUnaryMathOperation* instr);
2877   LInstruction* DoDivByPowerOf2I(HDiv* instr);
2878   LInstruction* DoDivByConstI(HDiv* instr);
2879   LInstruction* DoDivI(HBinaryOperation* instr);
2880   LInstruction* DoModByPowerOf2I(HMod* instr);
2881   LInstruction* DoModByConstI(HMod* instr);
2882   LInstruction* DoModI(HMod* instr);
2883   LInstruction* DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr);
2884   LInstruction* DoFlooringDivByConstI(HMathFloorOfDiv* instr);
2885
2886  private:
2887   enum Status {
2888     UNUSED,
2889     BUILDING,
2890     DONE,
2891     ABORTED
2892   };
2893
2894   LPlatformChunk* chunk() const { return chunk_; }
2895   CompilationInfo* info() const { return info_; }
2896   HGraph* graph() const { return graph_; }
2897
2898   bool is_unused() const { return status_ == UNUSED; }
2899   bool is_building() const { return status_ == BUILDING; }
2900   bool is_done() const { return status_ == DONE; }
2901   bool is_aborted() const { return status_ == ABORTED; }
2902
2903   void Abort(BailoutReason reason);
2904
2905   // Methods for getting operands for Use / Define / Temp.
2906   LUnallocated* ToUnallocated(Register reg);
2907   LUnallocated* ToUnallocated(XMMRegister reg);
2908
2909   // Methods for setting up define-use relationships.
2910   MUST_USE_RESULT LOperand* Use(HValue* value, LUnallocated* operand);
2911   MUST_USE_RESULT LOperand* UseFixed(HValue* value, Register fixed_register);
2912   MUST_USE_RESULT LOperand* UseFixedDouble(HValue* value,
2913                                            XMMRegister fixed_register);
2914
2915   // A value that is guaranteed to be allocated to a register.
2916   // Operand created by UseRegister is guaranteed to be live until the end of
2917   // instruction. This means that register allocator will not reuse it's
2918   // register for any other operand inside instruction.
2919   // Operand created by UseRegisterAtStart is guaranteed to be live only at
2920   // instruction start. Register allocator is free to assign the same register
2921   // to some other operand used inside instruction (i.e. temporary or
2922   // output).
2923   MUST_USE_RESULT LOperand* UseRegister(HValue* value);
2924   MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value);
2925
2926   // An input operand in a register that may be trashed.
2927   MUST_USE_RESULT LOperand* UseTempRegister(HValue* value);
2928
2929   // An input operand in a register that may be trashed or a constant operand.
2930   MUST_USE_RESULT LOperand* UseTempRegisterOrConstant(HValue* value);
2931
2932   // An input operand in a register or stack slot.
2933   MUST_USE_RESULT LOperand* Use(HValue* value);
2934   MUST_USE_RESULT LOperand* UseAtStart(HValue* value);
2935
2936   // An input operand in a register, stack slot or a constant operand.
2937   MUST_USE_RESULT LOperand* UseOrConstant(HValue* value);
2938   MUST_USE_RESULT LOperand* UseOrConstantAtStart(HValue* value);
2939
2940   // An input operand in a register or a constant operand.
2941   MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value);
2942   MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value);
2943
2944   // An input operand in a constant operand.
2945   MUST_USE_RESULT LOperand* UseConstant(HValue* value);
2946
2947   // An input operand in register, stack slot or a constant operand.
2948   // Will not be moved to a register even if one is freely available.
2949   virtual MUST_USE_RESULT LOperand* UseAny(HValue* value) V8_OVERRIDE;
2950
2951   // Temporary operand that must be in a register.
2952   MUST_USE_RESULT LUnallocated* TempRegister();
2953   MUST_USE_RESULT LOperand* FixedTemp(Register reg);
2954   MUST_USE_RESULT LOperand* FixedTemp(XMMRegister reg);
2955
2956   // Methods for setting up define-use relationships.
2957   // Return the same instruction that they are passed.
2958   LInstruction* Define(LTemplateResultInstruction<1>* instr,
2959                        LUnallocated* result);
2960   LInstruction* DefineAsRegister(LTemplateResultInstruction<1>* instr);
2961   LInstruction* DefineAsSpilled(LTemplateResultInstruction<1>* instr,
2962                                 int index);
2963   LInstruction* DefineSameAsFirst(LTemplateResultInstruction<1>* instr);
2964   LInstruction* DefineFixed(LTemplateResultInstruction<1>* instr,
2965                             Register reg);
2966   LInstruction* DefineFixedDouble(LTemplateResultInstruction<1>* instr,
2967                                   XMMRegister reg);
2968   // Assigns an environment to an instruction.  An instruction which can
2969   // deoptimize must have an environment.
2970   LInstruction* AssignEnvironment(LInstruction* instr);
2971   // Assigns a pointer map to an instruction.  An instruction which can
2972   // trigger a GC or a lazy deoptimization must have a pointer map.
2973   LInstruction* AssignPointerMap(LInstruction* instr);
2974
2975   enum CanDeoptimize { CAN_DEOPTIMIZE_EAGERLY, CANNOT_DEOPTIMIZE_EAGERLY };
2976
2977   // Marks a call for the register allocator.  Assigns a pointer map to
2978   // support GC and lazy deoptimization.  Assigns an environment to support
2979   // eager deoptimization if CAN_DEOPTIMIZE_EAGERLY.
2980   LInstruction* MarkAsCall(
2981       LInstruction* instr,
2982       HInstruction* hinstr,
2983       CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY);
2984
2985   void VisitInstruction(HInstruction* current);
2986
2987   void DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block);
2988   LInstruction* DoShift(Token::Value op, HBitwiseBinaryOperation* instr);
2989   LInstruction* DoArithmeticD(Token::Value op,
2990                               HArithmeticBinaryOperation* instr);
2991   LInstruction* DoArithmeticT(Token::Value op,
2992                               HBinaryOperation* instr);
2993   void FindDehoistedKeyDefinitions(HValue* candidate);
2994
2995   LPlatformChunk* chunk_;
2996   CompilationInfo* info_;
2997   HGraph* const graph_;
2998   Status status_;
2999   HInstruction* current_instruction_;
3000   HBasicBlock* current_block_;
3001   HBasicBlock* next_block_;
3002   LAllocator* allocator_;
3003
3004   DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
3005 };
3006
3007 #undef DECLARE_HYDROGEN_ACCESSOR
3008 #undef DECLARE_CONCRETE_INSTRUCTION
3009
3010 } }  // namespace v8::int
3011
3012 #endif  // V8_X64_LITHIUM_X64_H_