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