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