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