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