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