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