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