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