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