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