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