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