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