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