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