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