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