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