1// Copyright 2013 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_ARM64_LITHIUM_ARM64_H_
6#define V8_ARM64_LITHIUM_ARM64_H_
7
8#include "src/hydrogen.h"
9#include "src/lithium.h"
10#include "src/lithium-allocator.h"
11#include "src/safepoint-table.h"
12#include "src/utils.h"
13
14namespace v8 {
15namespace internal {
16
17// Forward declarations.
18class LCodeGen;
19
20#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \
21  V(AccessArgumentsAt)                       \
22  V(AddE)                                    \
23  V(AddI)                                    \
24  V(AddS)                                    \
25  V(Allocate)                                \
26  V(AllocateBlockContext)                    \
27  V(ApplyArguments)                          \
28  V(ArgumentsElements)                       \
29  V(ArgumentsLength)                         \
30  V(ArithmeticD)                             \
31  V(ArithmeticT)                             \
32  V(BitI)                                    \
33  V(BitS)                                    \
34  V(BoundsCheck)                             \
35  V(Branch)                                  \
36  V(CallFunction)                            \
37  V(CallJSFunction)                          \
38  V(CallNew)                                 \
39  V(CallNewArray)                            \
40  V(CallRuntime)                             \
41  V(CallStub)                                \
42  V(CallWithDescriptor)                      \
43  V(CheckInstanceType)                       \
44  V(CheckMapValue)                           \
45  V(CheckMaps)                               \
46  V(CheckNonSmi)                             \
47  V(CheckSmi)                                \
48  V(CheckValue)                              \
49  V(ClampDToUint8)                           \
50  V(ClampIToUint8)                           \
51  V(ClampTToUint8)                           \
52  V(ClassOfTestAndBranch)                    \
53  V(CmpHoleAndBranchD)                       \
54  V(CmpHoleAndBranchT)                       \
55  V(CmpMapAndBranch)                         \
56  V(CmpObjectEqAndBranch)                    \
57  V(CmpT)                                    \
58  V(CompareMinusZeroAndBranch)               \
59  V(CompareNumericAndBranch)                 \
60  V(ConstantD)                               \
61  V(ConstantE)                               \
62  V(ConstantI)                               \
63  V(ConstantS)                               \
64  V(ConstantT)                               \
65  V(ConstructDouble)                         \
66  V(Context)                                 \
67  V(DateField)                               \
68  V(DebugBreak)                              \
69  V(DeclareGlobals)                          \
70  V(Deoptimize)                              \
71  V(DivByConstI)                             \
72  V(DivByPowerOf2I)                          \
73  V(DivI)                                    \
74  V(DoubleBits)                              \
75  V(DoubleToIntOrSmi)                        \
76  V(Drop)                                    \
77  V(Dummy)                                   \
78  V(DummyUse)                                \
79  V(FlooringDivByConstI)                     \
80  V(FlooringDivByPowerOf2I)                  \
81  V(FlooringDivI)                            \
82  V(ForInCacheArray)                         \
83  V(ForInPrepareMap)                         \
84  V(FunctionLiteral)                         \
85  V(GetCachedArrayIndex)                     \
86  V(Goto)                                    \
87  V(HasCachedArrayIndexAndBranch)            \
88  V(HasInstanceTypeAndBranch)                \
89  V(InnerAllocatedObject)                    \
90  V(InstanceOf)                              \
91  V(InstanceOfKnownGlobal)                   \
92  V(InstructionGap)                          \
93  V(Integer32ToDouble)                       \
94  V(InvokeFunction)                          \
95  V(IsConstructCallAndBranch)                \
96  V(IsObjectAndBranch)                       \
97  V(IsSmiAndBranch)                          \
98  V(IsStringAndBranch)                       \
99  V(IsUndetectableAndBranch)                 \
100  V(Label)                                   \
101  V(LazyBailout)                             \
102  V(LoadContextSlot)                         \
103  V(LoadFieldByIndex)                        \
104  V(LoadFunctionPrototype)                   \
105  V(LoadGlobalCell)                          \
106  V(LoadGlobalGeneric)                       \
107  V(LoadKeyedExternal)                       \
108  V(LoadKeyedFixed)                          \
109  V(LoadKeyedFixedDouble)                    \
110  V(LoadKeyedGeneric)                        \
111  V(LoadNamedField)                          \
112  V(LoadNamedGeneric)                        \
113  V(LoadRoot)                                \
114  V(MapEnumLength)                           \
115  V(MathAbs)                                 \
116  V(MathAbsTagged)                           \
117  V(MathClz32)                               \
118  V(MathExp)                                 \
119  V(MathFloorD)                              \
120  V(MathFloorI)                              \
121  V(MathFround)                              \
122  V(MathLog)                                 \
123  V(MathMinMax)                              \
124  V(MathPowHalf)                             \
125  V(MathRoundD)                              \
126  V(MathRoundI)                              \
127  V(MathSqrt)                                \
128  V(ModByConstI)                             \
129  V(ModByPowerOf2I)                          \
130  V(ModI)                                    \
131  V(MulConstIS)                              \
132  V(MulI)                                    \
133  V(MulS)                                    \
134  V(NumberTagD)                              \
135  V(NumberTagU)                              \
136  V(NumberUntagD)                            \
137  V(OsrEntry)                                \
138  V(Parameter)                               \
139  V(Power)                                   \
140  V(PreparePushArguments)                    \
141  V(PushArguments)                           \
142  V(RegExpLiteral)                           \
143  V(Return)                                  \
144  V(SeqStringGetChar)                        \
145  V(SeqStringSetChar)                        \
146  V(ShiftI)                                  \
147  V(ShiftS)                                  \
148  V(SmiTag)                                  \
149  V(SmiUntag)                                \
150  V(StackCheck)                              \
151  V(StoreCodeEntry)                          \
152  V(StoreContextSlot)                        \
153  V(StoreFrameContext)                       \
154  V(StoreGlobalCell)                         \
155  V(StoreKeyedExternal)                      \
156  V(StoreKeyedFixed)                         \
157  V(StoreKeyedFixedDouble)                   \
158  V(StoreKeyedGeneric)                       \
159  V(StoreNamedField)                         \
160  V(StoreNamedGeneric)                       \
161  V(StringAdd)                               \
162  V(StringCharCodeAt)                        \
163  V(StringCharFromCode)                      \
164  V(StringCompareAndBranch)                  \
165  V(SubI)                                    \
166  V(SubS)                                    \
167  V(TaggedToI)                               \
168  V(TailCallThroughMegamorphicCache)         \
169  V(ThisFunction)                            \
170  V(ToFastProperties)                        \
171  V(TransitionElementsKind)                  \
172  V(TrapAllocationMemento)                   \
173  V(TruncateDoubleToIntOrSmi)                \
174  V(Typeof)                                  \
175  V(TypeofIsAndBranch)                       \
176  V(Uint32ToDouble)                          \
177  V(UnknownOSRValue)                         \
178  V(WrapReceiver)
179
180
181#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic)                        \
182  virtual Opcode opcode() const FINAL OVERRIDE {                      \
183    return LInstruction::k##type;                                           \
184  }                                                                         \
185  virtual void CompileToNative(LCodeGen* generator) FINAL OVERRIDE;   \
186  virtual const char* Mnemonic() const FINAL OVERRIDE {               \
187    return mnemonic;                                                        \
188  }                                                                         \
189  static L##type* cast(LInstruction* instr) {                               \
190    DCHECK(instr->Is##type());                                              \
191    return reinterpret_cast<L##type*>(instr);                               \
192  }
193
194
195#define DECLARE_HYDROGEN_ACCESSOR(type)           \
196  H##type* hydrogen() const {                     \
197    return H##type::cast(this->hydrogen_value()); \
198  }
199
200
201class LInstruction : public ZoneObject {
202 public:
203  LInstruction()
204      : environment_(NULL),
205        hydrogen_value_(NULL),
206        bit_field_(IsCallBits::encode(false)) { }
207
208  virtual ~LInstruction() { }
209
210  virtual void CompileToNative(LCodeGen* generator) = 0;
211  virtual const char* Mnemonic() const = 0;
212  virtual void PrintTo(StringStream* stream);
213  virtual void PrintDataTo(StringStream* stream);
214  virtual void PrintOutputOperandTo(StringStream* stream);
215
216  enum Opcode {
217    // Declare a unique enum value for each instruction.
218#define DECLARE_OPCODE(type) k##type,
219    LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
220    kNumberOfInstructions
221#undef DECLARE_OPCODE
222  };
223
224  virtual Opcode opcode() const = 0;
225
226  // Declare non-virtual type testers for all leaf IR classes.
227#define DECLARE_PREDICATE(type) \
228  bool Is##type() const { return opcode() == k##type; }
229  LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
230#undef DECLARE_PREDICATE
231
232  // Declare virtual predicates for instructions that don't have
233  // an opcode.
234  virtual bool IsGap() const { return false; }
235
236  virtual bool IsControl() const { return false; }
237
238  // Try deleting this instruction if possible.
239  virtual bool TryDelete() { return false; }
240
241  void set_environment(LEnvironment* env) { environment_ = env; }
242  LEnvironment* environment() const { return environment_; }
243  bool HasEnvironment() const { return environment_ != NULL; }
244
245  void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); }
246  LPointerMap* pointer_map() const { return pointer_map_.get(); }
247  bool HasPointerMap() const { return pointer_map_.is_set(); }
248
249  void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
250  HValue* hydrogen_value() const { return hydrogen_value_; }
251
252  virtual void SetDeferredLazyDeoptimizationEnvironment(LEnvironment* env) { }
253
254  void MarkAsCall() { bit_field_ = IsCallBits::update(bit_field_, true); }
255  bool IsCall() const { return IsCallBits::decode(bit_field_); }
256
257  // Interface to the register allocator and iterators.
258  bool ClobbersTemps() const { return IsCall(); }
259  bool ClobbersRegisters() const { return IsCall(); }
260  virtual bool ClobbersDoubleRegisters(Isolate* isolate) const {
261    return IsCall();
262  }
263  bool IsMarkedAsCall() const { return IsCall(); }
264
265  virtual bool HasResult() const = 0;
266  virtual LOperand* result() const = 0;
267
268  virtual int InputCount() = 0;
269  virtual LOperand* InputAt(int i) = 0;
270  virtual int TempCount() = 0;
271  virtual LOperand* TempAt(int i) = 0;
272
273  LOperand* FirstInput() { return InputAt(0); }
274  LOperand* Output() { return HasResult() ? result() : NULL; }
275
276  virtual bool HasInterestingComment(LCodeGen* gen) const { return true; }
277
278#ifdef DEBUG
279  void VerifyCall();
280#endif
281
282 private:
283  class IsCallBits: public BitField<bool, 0, 1> {};
284
285  LEnvironment* environment_;
286  SetOncePointer<LPointerMap> pointer_map_;
287  HValue* hydrogen_value_;
288  int32_t bit_field_;
289};
290
291
292// R = number of result operands (0 or 1).
293template<int R>
294class LTemplateResultInstruction : public LInstruction {
295 public:
296  // Allow 0 or 1 output operands.
297  STATIC_ASSERT(R == 0 || R == 1);
298  virtual bool HasResult() const FINAL OVERRIDE {
299    return (R != 0) && (result() != NULL);
300  }
301  void set_result(LOperand* operand) { results_[0] = operand; }
302  LOperand* result() const { return results_[0]; }
303
304 protected:
305  EmbeddedContainer<LOperand*, R> results_;
306};
307
308
309// R = number of result operands (0 or 1).
310// I = number of input operands.
311// T = number of temporary operands.
312template<int R, int I, int T>
313class LTemplateInstruction : public LTemplateResultInstruction<R> {
314 protected:
315  EmbeddedContainer<LOperand*, I> inputs_;
316  EmbeddedContainer<LOperand*, T> temps_;
317
318 private:
319  // Iterator support.
320  virtual int InputCount() FINAL OVERRIDE { return I; }
321  virtual LOperand* InputAt(int i) FINAL OVERRIDE { return inputs_[i]; }
322
323  virtual int TempCount() FINAL OVERRIDE { return T; }
324  virtual LOperand* TempAt(int i) FINAL OVERRIDE { return temps_[i]; }
325};
326
327
328class LTailCallThroughMegamorphicCache FINAL
329    : public LTemplateInstruction<0, 3, 0> {
330 public:
331  explicit LTailCallThroughMegamorphicCache(LOperand* context,
332                                            LOperand* receiver,
333                                            LOperand* name) {
334    inputs_[0] = context;
335    inputs_[1] = receiver;
336    inputs_[2] = name;
337  }
338
339  LOperand* context() { return inputs_[0]; }
340  LOperand* receiver() { return inputs_[1]; }
341  LOperand* name() { return inputs_[2]; }
342
343  DECLARE_CONCRETE_INSTRUCTION(TailCallThroughMegamorphicCache,
344                               "tail-call-through-megamorphic-cache")
345  DECLARE_HYDROGEN_ACCESSOR(TailCallThroughMegamorphicCache)
346};
347
348
349class LUnknownOSRValue FINAL : public LTemplateInstruction<1, 0, 0> {
350 public:
351  virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
352    return false;
353  }
354  DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value")
355};
356
357
358template<int I, int T>
359class LControlInstruction : public LTemplateInstruction<0, I, T> {
360 public:
361  LControlInstruction() : false_label_(NULL), true_label_(NULL) { }
362
363  virtual bool IsControl() const FINAL OVERRIDE { return true; }
364
365  int SuccessorCount() { return hydrogen()->SuccessorCount(); }
366  HBasicBlock* SuccessorAt(int i) { return hydrogen()->SuccessorAt(i); }
367
368  int TrueDestination(LChunk* chunk) {
369    return chunk->LookupDestination(true_block_id());
370  }
371
372  int FalseDestination(LChunk* chunk) {
373    return chunk->LookupDestination(false_block_id());
374  }
375
376  Label* TrueLabel(LChunk* chunk) {
377    if (true_label_ == NULL) {
378      true_label_ = chunk->GetAssemblyLabel(TrueDestination(chunk));
379    }
380    return true_label_;
381  }
382
383  Label* FalseLabel(LChunk* chunk) {
384    if (false_label_ == NULL) {
385      false_label_ = chunk->GetAssemblyLabel(FalseDestination(chunk));
386    }
387    return false_label_;
388  }
389
390 protected:
391  int true_block_id() { return SuccessorAt(0)->block_id(); }
392  int false_block_id() { return SuccessorAt(1)->block_id(); }
393
394 private:
395  DECLARE_HYDROGEN_ACCESSOR(ControlInstruction);
396
397  Label* false_label_;
398  Label* true_label_;
399};
400
401
402class LGap : public LTemplateInstruction<0, 0, 0> {
403 public:
404  explicit LGap(HBasicBlock* block)
405      : block_(block) {
406    parallel_moves_[BEFORE] = NULL;
407    parallel_moves_[START] = NULL;
408    parallel_moves_[END] = NULL;
409    parallel_moves_[AFTER] = NULL;
410  }
411
412  // Can't use the DECLARE-macro here because of sub-classes.
413  virtual bool IsGap() const OVERRIDE { return true; }
414  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
415  static LGap* cast(LInstruction* instr) {
416    DCHECK(instr->IsGap());
417    return reinterpret_cast<LGap*>(instr);
418  }
419
420  bool IsRedundant() const;
421
422  HBasicBlock* block() const { return block_; }
423
424  enum InnerPosition {
425    BEFORE,
426    START,
427    END,
428    AFTER,
429    FIRST_INNER_POSITION = BEFORE,
430    LAST_INNER_POSITION = AFTER
431  };
432
433  LParallelMove* GetOrCreateParallelMove(InnerPosition pos, Zone* zone)  {
434    if (parallel_moves_[pos] == NULL) {
435      parallel_moves_[pos] = new(zone) LParallelMove(zone);
436    }
437    return parallel_moves_[pos];
438  }
439
440  LParallelMove* GetParallelMove(InnerPosition pos)  {
441    return parallel_moves_[pos];
442  }
443
444 private:
445  LParallelMove* parallel_moves_[LAST_INNER_POSITION + 1];
446  HBasicBlock* block_;
447};
448
449
450class LInstructionGap FINAL : public LGap {
451 public:
452  explicit LInstructionGap(HBasicBlock* block) : LGap(block) { }
453
454  virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
455    return !IsRedundant();
456  }
457
458  DECLARE_CONCRETE_INSTRUCTION(InstructionGap, "gap")
459};
460
461
462class LDrop FINAL : public LTemplateInstruction<0, 0, 0> {
463 public:
464  explicit LDrop(int count) : count_(count) { }
465
466  int count() const { return count_; }
467
468  DECLARE_CONCRETE_INSTRUCTION(Drop, "drop")
469
470 private:
471  int count_;
472};
473
474
475class LDummy FINAL : public LTemplateInstruction<1, 0, 0> {
476 public:
477  LDummy() {}
478  DECLARE_CONCRETE_INSTRUCTION(Dummy, "dummy")
479};
480
481
482class LDummyUse FINAL : public LTemplateInstruction<1, 1, 0> {
483 public:
484  explicit LDummyUse(LOperand* value) {
485    inputs_[0] = value;
486  }
487  DECLARE_CONCRETE_INSTRUCTION(DummyUse, "dummy-use")
488};
489
490
491class LGoto FINAL : public LTemplateInstruction<0, 0, 0> {
492 public:
493  explicit LGoto(HBasicBlock* block) : block_(block) { }
494
495  virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE;
496  DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
497  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
498  virtual bool IsControl() const OVERRIDE { return true; }
499
500  int block_id() const { return block_->block_id(); }
501
502 private:
503  HBasicBlock* block_;
504};
505
506
507class LLazyBailout FINAL : public LTemplateInstruction<0, 0, 0> {
508 public:
509  LLazyBailout() : gap_instructions_size_(0) { }
510
511  DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout")
512
513  void set_gap_instructions_size(int gap_instructions_size) {
514    gap_instructions_size_ = gap_instructions_size;
515  }
516  int gap_instructions_size() { return gap_instructions_size_; }
517
518 private:
519  int gap_instructions_size_;
520};
521
522
523class LLabel FINAL : public LGap {
524 public:
525  explicit LLabel(HBasicBlock* block)
526      : LGap(block), replacement_(NULL) { }
527
528  virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
529    return false;
530  }
531  DECLARE_CONCRETE_INSTRUCTION(Label, "label")
532
533  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
534
535  int block_id() const { return block()->block_id(); }
536  bool is_loop_header() const { return block()->IsLoopHeader(); }
537  bool is_osr_entry() const { return block()->is_osr_entry(); }
538  Label* label() { return &label_; }
539  LLabel* replacement() const { return replacement_; }
540  void set_replacement(LLabel* label) { replacement_ = label; }
541  bool HasReplacement() const { return replacement_ != NULL; }
542
543 private:
544  Label label_;
545  LLabel* replacement_;
546};
547
548
549class LOsrEntry FINAL : public LTemplateInstruction<0, 0, 0> {
550 public:
551  LOsrEntry() {}
552
553  virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
554    return false;
555  }
556  DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry")
557};
558
559
560class LAccessArgumentsAt FINAL : public LTemplateInstruction<1, 3, 0> {
561 public:
562  LAccessArgumentsAt(LOperand* arguments,
563                     LOperand* length,
564                     LOperand* index) {
565    inputs_[0] = arguments;
566    inputs_[1] = length;
567    inputs_[2] = index;
568  }
569
570  DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at")
571
572  LOperand* arguments() { return inputs_[0]; }
573  LOperand* length() { return inputs_[1]; }
574  LOperand* index() { return inputs_[2]; }
575
576  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
577};
578
579
580class LAddE FINAL : public LTemplateInstruction<1, 2, 0> {
581 public:
582  LAddE(LOperand* left, LOperand* right) {
583    inputs_[0] = left;
584    inputs_[1] = right;
585  }
586
587  LOperand* left() { return inputs_[0]; }
588  LOperand* right() { return inputs_[1]; }
589
590  DECLARE_CONCRETE_INSTRUCTION(AddE, "add-e")
591  DECLARE_HYDROGEN_ACCESSOR(Add)
592};
593
594
595class LAddI FINAL : public LTemplateInstruction<1, 2, 0> {
596 public:
597  LAddI(LOperand* left, LOperand* right)
598      : shift_(NO_SHIFT), shift_amount_(0)  {
599    inputs_[0] = left;
600    inputs_[1] = right;
601  }
602
603  LAddI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount)
604      : shift_(shift), shift_amount_(shift_amount)  {
605    inputs_[0] = left;
606    inputs_[1] = right;
607  }
608
609  LOperand* left() { return inputs_[0]; }
610  LOperand* right() { return inputs_[1]; }
611
612  Shift shift() const { return shift_; }
613  LOperand* shift_amount() const { return shift_amount_; }
614
615  DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i")
616  DECLARE_HYDROGEN_ACCESSOR(Add)
617
618 protected:
619  Shift shift_;
620  LOperand* shift_amount_;
621};
622
623
624class LAddS FINAL : public LTemplateInstruction<1, 2, 0> {
625 public:
626  LAddS(LOperand* left, LOperand* right) {
627    inputs_[0] = left;
628    inputs_[1] = right;
629  }
630
631  LOperand* left() { return inputs_[0]; }
632  LOperand* right() { return inputs_[1]; }
633
634  DECLARE_CONCRETE_INSTRUCTION(AddS, "add-s")
635  DECLARE_HYDROGEN_ACCESSOR(Add)
636};
637
638
639class LAllocate FINAL : public LTemplateInstruction<1, 2, 3> {
640 public:
641  LAllocate(LOperand* context,
642            LOperand* size,
643            LOperand* temp1,
644            LOperand* temp2,
645            LOperand* temp3) {
646    inputs_[0] = context;
647    inputs_[1] = size;
648    temps_[0] = temp1;
649    temps_[1] = temp2;
650    temps_[2] = temp3;
651  }
652
653  LOperand* context() { return inputs_[0]; }
654  LOperand* size() { return inputs_[1]; }
655  LOperand* temp1() { return temps_[0]; }
656  LOperand* temp2() { return temps_[1]; }
657  LOperand* temp3() { return temps_[2]; }
658
659  DECLARE_CONCRETE_INSTRUCTION(Allocate, "allocate")
660  DECLARE_HYDROGEN_ACCESSOR(Allocate)
661};
662
663
664class LApplyArguments FINAL : public LTemplateInstruction<1, 4, 0> {
665 public:
666  LApplyArguments(LOperand* function,
667                  LOperand* receiver,
668                  LOperand* length,
669                  LOperand* elements) {
670    inputs_[0] = function;
671    inputs_[1] = receiver;
672    inputs_[2] = length;
673    inputs_[3] = elements;
674  }
675
676  DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply-arguments")
677
678  LOperand* function() { return inputs_[0]; }
679  LOperand* receiver() { return inputs_[1]; }
680  LOperand* length() { return inputs_[2]; }
681  LOperand* elements() { return inputs_[3]; }
682};
683
684
685class LArgumentsElements FINAL : public LTemplateInstruction<1, 0, 1> {
686 public:
687  explicit LArgumentsElements(LOperand* temp) {
688    temps_[0] = temp;
689  }
690
691  LOperand* temp() { return temps_[0]; }
692
693  DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments-elements")
694  DECLARE_HYDROGEN_ACCESSOR(ArgumentsElements)
695};
696
697
698class LArgumentsLength FINAL : public LTemplateInstruction<1, 1, 0> {
699 public:
700  explicit LArgumentsLength(LOperand* elements) {
701    inputs_[0] = elements;
702  }
703
704  LOperand* elements() { return inputs_[0]; }
705
706  DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments-length")
707};
708
709
710class LArithmeticD FINAL : public LTemplateInstruction<1, 2, 0> {
711 public:
712  LArithmeticD(Token::Value op,
713               LOperand* left,
714               LOperand* right)
715      : op_(op) {
716    inputs_[0] = left;
717    inputs_[1] = right;
718  }
719
720  Token::Value op() const { return op_; }
721  LOperand* left() { return inputs_[0]; }
722  LOperand* right() { return inputs_[1]; }
723
724  virtual Opcode opcode() const OVERRIDE {
725    return LInstruction::kArithmeticD;
726  }
727  virtual void CompileToNative(LCodeGen* generator) OVERRIDE;
728  virtual const char* Mnemonic() const OVERRIDE;
729
730 private:
731  Token::Value op_;
732};
733
734
735class LArithmeticT FINAL : public LTemplateInstruction<1, 3, 0> {
736 public:
737  LArithmeticT(Token::Value op,
738               LOperand* context,
739               LOperand* left,
740               LOperand* right)
741      : op_(op) {
742    inputs_[0] = context;
743    inputs_[1] = left;
744    inputs_[2] = right;
745  }
746
747  LOperand* context() { return inputs_[0]; }
748  LOperand* left() { return inputs_[1]; }
749  LOperand* right() { return inputs_[2]; }
750  Token::Value op() const { return op_; }
751
752  virtual Opcode opcode() const OVERRIDE {
753    return LInstruction::kArithmeticT;
754  }
755  virtual void CompileToNative(LCodeGen* generator) OVERRIDE;
756  virtual const char* Mnemonic() const OVERRIDE;
757
758 private:
759  Token::Value op_;
760};
761
762
763class LBoundsCheck FINAL : public LTemplateInstruction<0, 2, 0> {
764 public:
765  explicit LBoundsCheck(LOperand* index, LOperand* length) {
766    inputs_[0] = index;
767    inputs_[1] = length;
768  }
769
770  LOperand* index() { return inputs_[0]; }
771  LOperand* length() { return inputs_[1]; }
772
773  DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
774  DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
775};
776
777
778class LBitI FINAL : public LTemplateInstruction<1, 2, 0> {
779 public:
780  LBitI(LOperand* left, LOperand* right)
781      : shift_(NO_SHIFT), shift_amount_(0)  {
782    inputs_[0] = left;
783    inputs_[1] = right;
784  }
785
786  LBitI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount)
787      : shift_(shift), shift_amount_(shift_amount)  {
788    inputs_[0] = left;
789    inputs_[1] = right;
790  }
791
792  LOperand* left() { return inputs_[0]; }
793  LOperand* right() { return inputs_[1]; }
794
795  Shift shift() const { return shift_; }
796  LOperand* shift_amount() const { return shift_amount_; }
797
798  Token::Value op() const { return hydrogen()->op(); }
799
800  DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i")
801  DECLARE_HYDROGEN_ACCESSOR(Bitwise)
802
803 protected:
804  Shift shift_;
805  LOperand* shift_amount_;
806};
807
808
809class LBitS FINAL : public LTemplateInstruction<1, 2, 0> {
810 public:
811  LBitS(LOperand* left, LOperand* right) {
812    inputs_[0] = left;
813    inputs_[1] = right;
814  }
815
816  LOperand* left() { return inputs_[0]; }
817  LOperand* right() { return inputs_[1]; }
818
819  Token::Value op() const { return hydrogen()->op(); }
820
821  DECLARE_CONCRETE_INSTRUCTION(BitS, "bit-s")
822  DECLARE_HYDROGEN_ACCESSOR(Bitwise)
823};
824
825
826class LBranch FINAL : public LControlInstruction<1, 2> {
827 public:
828  explicit LBranch(LOperand* value, LOperand *temp1, LOperand *temp2) {
829    inputs_[0] = value;
830    temps_[0] = temp1;
831    temps_[1] = temp2;
832  }
833
834  LOperand* value() { return inputs_[0]; }
835  LOperand* temp1() { return temps_[0]; }
836  LOperand* temp2() { return temps_[1]; }
837
838  DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
839  DECLARE_HYDROGEN_ACCESSOR(Branch)
840
841  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
842};
843
844
845class LCallJSFunction FINAL : public LTemplateInstruction<1, 1, 0> {
846 public:
847  explicit LCallJSFunction(LOperand* function) {
848    inputs_[0] = function;
849  }
850
851  LOperand* function() { return inputs_[0]; }
852
853  DECLARE_CONCRETE_INSTRUCTION(CallJSFunction, "call-js-function")
854  DECLARE_HYDROGEN_ACCESSOR(CallJSFunction)
855
856  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
857
858  int arity() const { return hydrogen()->argument_count() - 1; }
859};
860
861
862class LCallFunction FINAL : public LTemplateInstruction<1, 2, 0> {
863 public:
864  LCallFunction(LOperand* context, LOperand* function) {
865    inputs_[0] = context;
866    inputs_[1] = function;
867  }
868
869  LOperand* context() { return inputs_[0]; }
870  LOperand* function() { return inputs_[1]; }
871
872  DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call-function")
873  DECLARE_HYDROGEN_ACCESSOR(CallFunction)
874
875  int arity() const { return hydrogen()->argument_count() - 1; }
876};
877
878
879class LCallNew FINAL : public LTemplateInstruction<1, 2, 0> {
880 public:
881  LCallNew(LOperand* context, LOperand* constructor) {
882    inputs_[0] = context;
883    inputs_[1] = constructor;
884  }
885
886  LOperand* context() { return inputs_[0]; }
887  LOperand* constructor() { return inputs_[1]; }
888
889  DECLARE_CONCRETE_INSTRUCTION(CallNew, "call-new")
890  DECLARE_HYDROGEN_ACCESSOR(CallNew)
891
892  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
893
894  int arity() const { return hydrogen()->argument_count() - 1; }
895};
896
897
898class LCallNewArray FINAL : public LTemplateInstruction<1, 2, 0> {
899 public:
900  LCallNewArray(LOperand* context, LOperand* constructor) {
901    inputs_[0] = context;
902    inputs_[1] = constructor;
903  }
904
905  LOperand* context() { return inputs_[0]; }
906  LOperand* constructor() { return inputs_[1]; }
907
908  DECLARE_CONCRETE_INSTRUCTION(CallNewArray, "call-new-array")
909  DECLARE_HYDROGEN_ACCESSOR(CallNewArray)
910
911  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
912
913  int arity() const { return hydrogen()->argument_count() - 1; }
914};
915
916
917class LCallRuntime FINAL : public LTemplateInstruction<1, 1, 0> {
918 public:
919  explicit LCallRuntime(LOperand* context) {
920    inputs_[0] = context;
921  }
922
923  LOperand* context() { return inputs_[0]; }
924
925  DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
926  DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
927
928  virtual bool ClobbersDoubleRegisters(Isolate* isolate) const OVERRIDE {
929    return save_doubles() == kDontSaveFPRegs;
930  }
931
932  const Runtime::Function* function() const { return hydrogen()->function(); }
933  int arity() const { return hydrogen()->argument_count(); }
934  SaveFPRegsMode save_doubles() const { return hydrogen()->save_doubles(); }
935};
936
937
938class LCallStub FINAL : public LTemplateInstruction<1, 1, 0> {
939 public:
940  explicit LCallStub(LOperand* context) {
941    inputs_[0] = context;
942  }
943
944  LOperand* context() { return inputs_[0]; }
945
946  DECLARE_CONCRETE_INSTRUCTION(CallStub, "call-stub")
947  DECLARE_HYDROGEN_ACCESSOR(CallStub)
948};
949
950
951class LCheckInstanceType FINAL : public LTemplateInstruction<0, 1, 1> {
952 public:
953  explicit LCheckInstanceType(LOperand* value, LOperand* temp) {
954    inputs_[0] = value;
955    temps_[0] = temp;
956  }
957
958  LOperand* value() { return inputs_[0]; }
959  LOperand* temp() { return temps_[0]; }
960
961  DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type")
962  DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType)
963};
964
965
966class LCheckMaps FINAL : public LTemplateInstruction<0, 1, 1> {
967 public:
968  explicit LCheckMaps(LOperand* value = NULL, LOperand* temp = NULL) {
969    inputs_[0] = value;
970    temps_[0] = temp;
971  }
972
973  LOperand* value() { return inputs_[0]; }
974  LOperand* temp() { return temps_[0]; }
975
976  DECLARE_CONCRETE_INSTRUCTION(CheckMaps, "check-maps")
977  DECLARE_HYDROGEN_ACCESSOR(CheckMaps)
978};
979
980
981class LCheckNonSmi FINAL : public LTemplateInstruction<0, 1, 0> {
982 public:
983  explicit LCheckNonSmi(LOperand* value) {
984    inputs_[0] = value;
985  }
986
987  LOperand* value() { return inputs_[0]; }
988
989  DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi")
990  DECLARE_HYDROGEN_ACCESSOR(CheckHeapObject)
991};
992
993
994class LCheckSmi FINAL : public LTemplateInstruction<1, 1, 0> {
995 public:
996  explicit LCheckSmi(LOperand* value) {
997    inputs_[0] = value;
998  }
999
1000  LOperand* value() { return inputs_[0]; }
1001
1002  DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi")
1003};
1004
1005
1006class LCheckValue FINAL : public LTemplateInstruction<0, 1, 0> {
1007 public:
1008  explicit LCheckValue(LOperand* value) {
1009    inputs_[0] = value;
1010  }
1011
1012  LOperand* value() { return inputs_[0]; }
1013
1014  DECLARE_CONCRETE_INSTRUCTION(CheckValue, "check-value")
1015  DECLARE_HYDROGEN_ACCESSOR(CheckValue)
1016};
1017
1018
1019class LClampDToUint8 FINAL : public LTemplateInstruction<1, 1, 0> {
1020 public:
1021  explicit LClampDToUint8(LOperand* unclamped) {
1022    inputs_[0] = unclamped;
1023  }
1024
1025  LOperand* unclamped() { return inputs_[0]; }
1026
1027  DECLARE_CONCRETE_INSTRUCTION(ClampDToUint8, "clamp-d-to-uint8")
1028};
1029
1030
1031class LClampIToUint8 FINAL : public LTemplateInstruction<1, 1, 0> {
1032 public:
1033  explicit LClampIToUint8(LOperand* unclamped) {
1034    inputs_[0] = unclamped;
1035  }
1036
1037  LOperand* unclamped() { return inputs_[0]; }
1038
1039  DECLARE_CONCRETE_INSTRUCTION(ClampIToUint8, "clamp-i-to-uint8")
1040};
1041
1042
1043class LClampTToUint8 FINAL : public LTemplateInstruction<1, 1, 1> {
1044 public:
1045  LClampTToUint8(LOperand* unclamped, LOperand* temp1) {
1046    inputs_[0] = unclamped;
1047    temps_[0] = temp1;
1048  }
1049
1050  LOperand* unclamped() { return inputs_[0]; }
1051  LOperand* temp1() { return temps_[0]; }
1052
1053  DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8, "clamp-t-to-uint8")
1054};
1055
1056
1057class LDoubleBits FINAL : public LTemplateInstruction<1, 1, 0> {
1058 public:
1059  explicit LDoubleBits(LOperand* value) {
1060    inputs_[0] = value;
1061  }
1062
1063  LOperand* value() { return inputs_[0]; }
1064
1065  DECLARE_CONCRETE_INSTRUCTION(DoubleBits, "double-bits")
1066  DECLARE_HYDROGEN_ACCESSOR(DoubleBits)
1067};
1068
1069
1070class LConstructDouble FINAL : public LTemplateInstruction<1, 2, 0> {
1071 public:
1072  LConstructDouble(LOperand* hi, LOperand* lo) {
1073    inputs_[0] = hi;
1074    inputs_[1] = lo;
1075  }
1076
1077  LOperand* hi() { return inputs_[0]; }
1078  LOperand* lo() { return inputs_[1]; }
1079
1080  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
1081};
1082
1083
1084class LClassOfTestAndBranch FINAL : public LControlInstruction<1, 2> {
1085 public:
1086  LClassOfTestAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) {
1087    inputs_[0] = value;
1088    temps_[0] = temp1;
1089    temps_[1] = temp2;
1090  }
1091
1092  LOperand* value() { return inputs_[0]; }
1093  LOperand* temp1() { return temps_[0]; }
1094  LOperand* temp2() { return temps_[1]; }
1095
1096  DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch,
1097                               "class-of-test-and-branch")
1098  DECLARE_HYDROGEN_ACCESSOR(ClassOfTestAndBranch)
1099
1100  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1101};
1102
1103
1104class LCmpHoleAndBranchD FINAL : public LControlInstruction<1, 1> {
1105 public:
1106  explicit LCmpHoleAndBranchD(LOperand* object, LOperand* temp) {
1107    inputs_[0] = object;
1108    temps_[0] = temp;
1109  }
1110
1111  LOperand* object() { return inputs_[0]; }
1112  LOperand* temp() { return temps_[0]; }
1113
1114  DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranchD, "cmp-hole-and-branch-d")
1115  DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch)
1116};
1117
1118
1119class LCmpHoleAndBranchT FINAL : public LControlInstruction<1, 0> {
1120 public:
1121  explicit LCmpHoleAndBranchT(LOperand* object) {
1122    inputs_[0] = object;
1123  }
1124
1125  LOperand* object() { return inputs_[0]; }
1126
1127  DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranchT, "cmp-hole-and-branch-t")
1128  DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch)
1129};
1130
1131
1132class LCmpMapAndBranch FINAL : public LControlInstruction<1, 1> {
1133 public:
1134  LCmpMapAndBranch(LOperand* value, LOperand* temp) {
1135    inputs_[0] = value;
1136    temps_[0] = temp;
1137  }
1138
1139  LOperand* value() { return inputs_[0]; }
1140  LOperand* temp() { return temps_[0]; }
1141
1142  DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
1143  DECLARE_HYDROGEN_ACCESSOR(CompareMap)
1144
1145  Handle<Map> map() const { return hydrogen()->map().handle(); }
1146};
1147
1148
1149class LCmpObjectEqAndBranch FINAL : public LControlInstruction<2, 0> {
1150 public:
1151  LCmpObjectEqAndBranch(LOperand* left, LOperand* right) {
1152    inputs_[0] = left;
1153    inputs_[1] = right;
1154  }
1155
1156  LOperand* left() { return inputs_[0]; }
1157  LOperand* right() { return inputs_[1]; }
1158
1159  DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch, "cmp-object-eq-and-branch")
1160  DECLARE_HYDROGEN_ACCESSOR(CompareObjectEqAndBranch)
1161};
1162
1163
1164class LCmpT FINAL : public LTemplateInstruction<1, 3, 0> {
1165 public:
1166  LCmpT(LOperand* context, LOperand* left, LOperand* right) {
1167    inputs_[0] = context;
1168    inputs_[1] = left;
1169    inputs_[2] = right;
1170  }
1171
1172  LOperand* context() { return inputs_[0]; }
1173  LOperand* left() { return inputs_[1]; }
1174  LOperand* right() { return inputs_[2]; }
1175
1176  DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t")
1177  DECLARE_HYDROGEN_ACCESSOR(CompareGeneric)
1178
1179  Token::Value op() const { return hydrogen()->token(); }
1180};
1181
1182
1183class LCompareMinusZeroAndBranch FINAL : public LControlInstruction<1, 1> {
1184 public:
1185  LCompareMinusZeroAndBranch(LOperand* value, LOperand* temp) {
1186    inputs_[0] = value;
1187    temps_[0] = temp;
1188  }
1189
1190  LOperand* value() { return inputs_[0]; }
1191  LOperand* temp() { return temps_[0]; }
1192
1193  DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch,
1194                               "cmp-minus-zero-and-branch")
1195  DECLARE_HYDROGEN_ACCESSOR(CompareMinusZeroAndBranch)
1196};
1197
1198
1199class LCompareNumericAndBranch FINAL : public LControlInstruction<2, 0> {
1200 public:
1201  LCompareNumericAndBranch(LOperand* left, LOperand* right) {
1202    inputs_[0] = left;
1203    inputs_[1] = right;
1204  }
1205
1206  LOperand* left() { return inputs_[0]; }
1207  LOperand* right() { return inputs_[1]; }
1208
1209  DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch,
1210                               "compare-numeric-and-branch")
1211  DECLARE_HYDROGEN_ACCESSOR(CompareNumericAndBranch)
1212
1213  Token::Value op() const { return hydrogen()->token(); }
1214  bool is_double() const {
1215    return hydrogen()->representation().IsDouble();
1216  }
1217
1218  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1219};
1220
1221
1222class LConstantD FINAL : public LTemplateInstruction<1, 0, 0> {
1223 public:
1224  DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
1225  DECLARE_HYDROGEN_ACCESSOR(Constant)
1226
1227  double value() const { return hydrogen()->DoubleValue(); }
1228};
1229
1230
1231class LConstantE FINAL : public LTemplateInstruction<1, 0, 0> {
1232 public:
1233  DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e")
1234  DECLARE_HYDROGEN_ACCESSOR(Constant)
1235
1236  ExternalReference value() const {
1237    return hydrogen()->ExternalReferenceValue();
1238  }
1239};
1240
1241
1242class LConstantI FINAL : public LTemplateInstruction<1, 0, 0> {
1243 public:
1244  DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i")
1245  DECLARE_HYDROGEN_ACCESSOR(Constant)
1246
1247  int32_t value() const { return hydrogen()->Integer32Value(); }
1248};
1249
1250
1251class LConstantS FINAL : public LTemplateInstruction<1, 0, 0> {
1252 public:
1253  DECLARE_CONCRETE_INSTRUCTION(ConstantS, "constant-s")
1254  DECLARE_HYDROGEN_ACCESSOR(Constant)
1255
1256  Smi* value() const { return Smi::FromInt(hydrogen()->Integer32Value()); }
1257};
1258
1259
1260class LConstantT FINAL : public LTemplateInstruction<1, 0, 0> {
1261 public:
1262  DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
1263  DECLARE_HYDROGEN_ACCESSOR(Constant)
1264
1265  Handle<Object> value(Isolate* isolate) const {
1266    return hydrogen()->handle(isolate);
1267  }
1268};
1269
1270
1271class LContext FINAL : public LTemplateInstruction<1, 0, 0> {
1272 public:
1273  DECLARE_CONCRETE_INSTRUCTION(Context, "context")
1274  DECLARE_HYDROGEN_ACCESSOR(Context)
1275};
1276
1277
1278class LDateField FINAL : public LTemplateInstruction<1, 1, 0> {
1279 public:
1280  LDateField(LOperand* date, Smi* index) : index_(index) {
1281    inputs_[0] = date;
1282  }
1283
1284  LOperand* date() { return inputs_[0]; }
1285  Smi* index() const { return index_; }
1286
1287  DECLARE_CONCRETE_INSTRUCTION(DateField, "date-field")
1288  DECLARE_HYDROGEN_ACCESSOR(DateField)
1289
1290 private:
1291  Smi* index_;
1292};
1293
1294
1295class LDebugBreak FINAL : public LTemplateInstruction<0, 0, 0> {
1296 public:
1297  DECLARE_CONCRETE_INSTRUCTION(DebugBreak, "break")
1298};
1299
1300
1301class LDeclareGlobals FINAL : public LTemplateInstruction<0, 1, 0> {
1302 public:
1303  explicit LDeclareGlobals(LOperand* context) {
1304    inputs_[0] = context;
1305  }
1306
1307  LOperand* context() { return inputs_[0]; }
1308
1309  DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals, "declare-globals")
1310  DECLARE_HYDROGEN_ACCESSOR(DeclareGlobals)
1311};
1312
1313
1314class LDeoptimize FINAL : public LTemplateInstruction<0, 0, 0> {
1315 public:
1316  virtual bool IsControl() const OVERRIDE { return true; }
1317  DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
1318  DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
1319};
1320
1321
1322class LDivByPowerOf2I FINAL : public LTemplateInstruction<1, 1, 0> {
1323 public:
1324  LDivByPowerOf2I(LOperand* dividend, int32_t divisor) {
1325    inputs_[0] = dividend;
1326    divisor_ = divisor;
1327  }
1328
1329  LOperand* dividend() { return inputs_[0]; }
1330  int32_t divisor() const { return divisor_; }
1331
1332  DECLARE_CONCRETE_INSTRUCTION(DivByPowerOf2I, "div-by-power-of-2-i")
1333  DECLARE_HYDROGEN_ACCESSOR(Div)
1334
1335 private:
1336  int32_t divisor_;
1337};
1338
1339
1340class LDivByConstI FINAL : public LTemplateInstruction<1, 1, 1> {
1341 public:
1342  LDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
1343    inputs_[0] = dividend;
1344    divisor_ = divisor;
1345    temps_[0] = temp;
1346  }
1347
1348  LOperand* dividend() { return inputs_[0]; }
1349  int32_t divisor() const { return divisor_; }
1350  LOperand* temp() { return temps_[0]; }
1351
1352  DECLARE_CONCRETE_INSTRUCTION(DivByConstI, "div-by-const-i")
1353  DECLARE_HYDROGEN_ACCESSOR(Div)
1354
1355 private:
1356  int32_t divisor_;
1357};
1358
1359
1360class LDivI FINAL : public LTemplateInstruction<1, 2, 1> {
1361 public:
1362  LDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
1363    inputs_[0] = dividend;
1364    inputs_[1] = divisor;
1365    temps_[0] = temp;
1366  }
1367
1368  LOperand* dividend() { return inputs_[0]; }
1369  LOperand* divisor() { return inputs_[1]; }
1370  LOperand* temp() { return temps_[0]; }
1371
1372  DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
1373  DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)
1374};
1375
1376
1377class LDoubleToIntOrSmi FINAL : public LTemplateInstruction<1, 1, 0> {
1378 public:
1379  explicit LDoubleToIntOrSmi(LOperand* value) {
1380    inputs_[0] = value;
1381  }
1382
1383  LOperand* value() { return inputs_[0]; }
1384
1385  DECLARE_CONCRETE_INSTRUCTION(DoubleToIntOrSmi, "double-to-int-or-smi")
1386  DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
1387
1388  bool tag_result() { return hydrogen()->representation().IsSmi(); }
1389};
1390
1391
1392class LForInCacheArray FINAL : public LTemplateInstruction<1, 1, 0> {
1393 public:
1394  explicit LForInCacheArray(LOperand* map) {
1395    inputs_[0] = map;
1396  }
1397
1398  LOperand* map() { return inputs_[0]; }
1399
1400  DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray, "for-in-cache-array")
1401
1402  int idx() {
1403    return HForInCacheArray::cast(this->hydrogen_value())->idx();
1404  }
1405};
1406
1407
1408class LForInPrepareMap FINAL : public LTemplateInstruction<1, 2, 0> {
1409 public:
1410  LForInPrepareMap(LOperand* context, LOperand* object) {
1411    inputs_[0] = context;
1412    inputs_[1] = object;
1413  }
1414
1415  LOperand* context() { return inputs_[0]; }
1416  LOperand* object() { return inputs_[1]; }
1417
1418  DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap, "for-in-prepare-map")
1419};
1420
1421
1422class LGetCachedArrayIndex FINAL : public LTemplateInstruction<1, 1, 0> {
1423 public:
1424  explicit LGetCachedArrayIndex(LOperand* value) {
1425    inputs_[0] = value;
1426  }
1427
1428  LOperand* value() { return inputs_[0]; }
1429
1430  DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get-cached-array-index")
1431  DECLARE_HYDROGEN_ACCESSOR(GetCachedArrayIndex)
1432};
1433
1434
1435class LHasCachedArrayIndexAndBranch FINAL
1436    : public LControlInstruction<1, 1> {
1437 public:
1438  LHasCachedArrayIndexAndBranch(LOperand* value, LOperand* temp) {
1439    inputs_[0] = value;
1440    temps_[0] = temp;
1441  }
1442
1443  LOperand* value() { return inputs_[0]; }
1444  LOperand* temp() { return temps_[0]; }
1445
1446  DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch,
1447                               "has-cached-array-index-and-branch")
1448  DECLARE_HYDROGEN_ACCESSOR(HasCachedArrayIndexAndBranch)
1449
1450  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1451};
1452
1453
1454class LHasInstanceTypeAndBranch FINAL : public LControlInstruction<1, 1> {
1455 public:
1456  LHasInstanceTypeAndBranch(LOperand* value, LOperand* temp) {
1457    inputs_[0] = value;
1458    temps_[0] = temp;
1459  }
1460
1461  LOperand* value() { return inputs_[0]; }
1462  LOperand* temp() { return temps_[0]; }
1463
1464  DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch,
1465                               "has-instance-type-and-branch")
1466  DECLARE_HYDROGEN_ACCESSOR(HasInstanceTypeAndBranch)
1467
1468  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1469};
1470
1471
1472class LInnerAllocatedObject FINAL : public LTemplateInstruction<1, 2, 0> {
1473 public:
1474  LInnerAllocatedObject(LOperand* base_object, LOperand* offset) {
1475    inputs_[0] = base_object;
1476    inputs_[1] = offset;
1477  }
1478
1479  LOperand* base_object() const { return inputs_[0]; }
1480  LOperand* offset() const { return inputs_[1]; }
1481
1482  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1483
1484  DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "inner-allocated-object")
1485};
1486
1487
1488class LInstanceOf FINAL : public LTemplateInstruction<1, 3, 0> {
1489 public:
1490  LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
1491    inputs_[0] = context;
1492    inputs_[1] = left;
1493    inputs_[2] = right;
1494  }
1495
1496  LOperand* context() { return inputs_[0]; }
1497  LOperand* left() { return inputs_[1]; }
1498  LOperand* right() { return inputs_[2]; }
1499
1500  DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
1501};
1502
1503
1504class LInstanceOfKnownGlobal FINAL : public LTemplateInstruction<1, 2, 0> {
1505 public:
1506  LInstanceOfKnownGlobal(LOperand* context, LOperand* value) {
1507    inputs_[0] = context;
1508    inputs_[1] = value;
1509  }
1510
1511  LOperand* context() { return inputs_[0]; }
1512  LOperand* value() { return inputs_[1]; }
1513
1514  DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
1515                               "instance-of-known-global")
1516  DECLARE_HYDROGEN_ACCESSOR(InstanceOfKnownGlobal)
1517
1518  Handle<JSFunction> function() const { return hydrogen()->function(); }
1519  LEnvironment* GetDeferredLazyDeoptimizationEnvironment() {
1520    return lazy_deopt_env_;
1521  }
1522  virtual void SetDeferredLazyDeoptimizationEnvironment(
1523      LEnvironment* env) OVERRIDE {
1524    lazy_deopt_env_ = env;
1525  }
1526
1527 private:
1528  LEnvironment* lazy_deopt_env_;
1529};
1530
1531
1532class LInteger32ToDouble FINAL : public LTemplateInstruction<1, 1, 0> {
1533 public:
1534  explicit LInteger32ToDouble(LOperand* value) {
1535    inputs_[0] = value;
1536  }
1537
1538  LOperand* value() { return inputs_[0]; }
1539
1540  DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double")
1541};
1542
1543
1544class LCallWithDescriptor FINAL : public LTemplateResultInstruction<1> {
1545 public:
1546  LCallWithDescriptor(CallInterfaceDescriptor descriptor,
1547                      const ZoneList<LOperand*>& operands, Zone* zone)
1548      : descriptor_(descriptor),
1549        inputs_(descriptor.GetRegisterParameterCount() + 1, zone) {
1550    DCHECK(descriptor.GetRegisterParameterCount() + 1 == operands.length());
1551    inputs_.AddAll(operands, zone);
1552  }
1553
1554  LOperand* target() const { return inputs_[0]; }
1555
1556  CallInterfaceDescriptor descriptor() { return descriptor_; }
1557
1558 private:
1559  DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor, "call-with-descriptor")
1560  DECLARE_HYDROGEN_ACCESSOR(CallWithDescriptor)
1561
1562  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1563
1564  int arity() const { return hydrogen()->argument_count() - 1; }
1565
1566  CallInterfaceDescriptor descriptor_;
1567  ZoneList<LOperand*> inputs_;
1568
1569  // Iterator support.
1570  virtual int InputCount() FINAL OVERRIDE { return inputs_.length(); }
1571  virtual LOperand* InputAt(int i) FINAL OVERRIDE { return inputs_[i]; }
1572
1573  virtual int TempCount() FINAL OVERRIDE { return 0; }
1574  virtual LOperand* TempAt(int i) FINAL OVERRIDE { return NULL; }
1575};
1576
1577
1578class LInvokeFunction FINAL : public LTemplateInstruction<1, 2, 0> {
1579 public:
1580  LInvokeFunction(LOperand* context, LOperand* function) {
1581    inputs_[0] = context;
1582    inputs_[1] = function;
1583  }
1584
1585  LOperand* context() { return inputs_[0]; }
1586  LOperand* function() { return inputs_[1]; }
1587
1588  DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
1589  DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
1590
1591  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1592
1593  int arity() const { return hydrogen()->argument_count() - 1; }
1594};
1595
1596
1597class LIsConstructCallAndBranch FINAL : public LControlInstruction<0, 2> {
1598 public:
1599  LIsConstructCallAndBranch(LOperand* temp1, LOperand* temp2) {
1600    temps_[0] = temp1;
1601    temps_[1] = temp2;
1602  }
1603
1604  LOperand* temp1() { return temps_[0]; }
1605  LOperand* temp2() { return temps_[1]; }
1606
1607  DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch,
1608                               "is-construct-call-and-branch")
1609};
1610
1611
1612class LIsObjectAndBranch FINAL : public LControlInstruction<1, 2> {
1613 public:
1614  LIsObjectAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) {
1615    inputs_[0] = value;
1616    temps_[0] = temp1;
1617    temps_[1] = temp2;
1618  }
1619
1620  LOperand* value() { return inputs_[0]; }
1621  LOperand* temp1() { return temps_[0]; }
1622  LOperand* temp2() { return temps_[1]; }
1623
1624  DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
1625  DECLARE_HYDROGEN_ACCESSOR(IsObjectAndBranch)
1626
1627  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1628};
1629
1630
1631class LIsStringAndBranch FINAL : public LControlInstruction<1, 1> {
1632 public:
1633  LIsStringAndBranch(LOperand* value, LOperand* temp) {
1634    inputs_[0] = value;
1635    temps_[0] = temp;
1636  }
1637
1638  LOperand* value() { return inputs_[0]; }
1639  LOperand* temp() { return temps_[0]; }
1640
1641  DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch")
1642  DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch)
1643
1644  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1645};
1646
1647
1648class LIsSmiAndBranch FINAL : public LControlInstruction<1, 0> {
1649 public:
1650  explicit LIsSmiAndBranch(LOperand* value) {
1651    inputs_[0] = value;
1652  }
1653
1654  LOperand* value() { return inputs_[0]; }
1655
1656  DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch")
1657  DECLARE_HYDROGEN_ACCESSOR(IsSmiAndBranch)
1658
1659  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1660};
1661
1662
1663class LIsUndetectableAndBranch FINAL : public LControlInstruction<1, 1> {
1664 public:
1665  explicit LIsUndetectableAndBranch(LOperand* value, LOperand* temp) {
1666    inputs_[0] = value;
1667    temps_[0] = temp;
1668  }
1669
1670  LOperand* value() { return inputs_[0]; }
1671  LOperand* temp() { return temps_[0]; }
1672
1673  DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch,
1674                               "is-undetectable-and-branch")
1675  DECLARE_HYDROGEN_ACCESSOR(IsUndetectableAndBranch)
1676
1677  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1678};
1679
1680
1681class LLoadContextSlot FINAL : public LTemplateInstruction<1, 1, 0> {
1682 public:
1683  explicit LLoadContextSlot(LOperand* context) {
1684    inputs_[0] = context;
1685  }
1686
1687  LOperand* context() { return inputs_[0]; }
1688
1689  DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot")
1690  DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot)
1691
1692  int slot_index() const { return hydrogen()->slot_index(); }
1693
1694  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1695};
1696
1697
1698class LLoadNamedField FINAL : public LTemplateInstruction<1, 1, 0> {
1699 public:
1700  explicit LLoadNamedField(LOperand* object) {
1701    inputs_[0] = object;
1702  }
1703
1704  LOperand* object() { return inputs_[0]; }
1705
1706  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field")
1707  DECLARE_HYDROGEN_ACCESSOR(LoadNamedField)
1708};
1709
1710
1711class LFunctionLiteral FINAL : public LTemplateInstruction<1, 1, 0> {
1712 public:
1713  explicit LFunctionLiteral(LOperand* context) {
1714    inputs_[0] = context;
1715  }
1716
1717  LOperand* context() { return inputs_[0]; }
1718
1719  DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function-literal")
1720  DECLARE_HYDROGEN_ACCESSOR(FunctionLiteral)
1721};
1722
1723
1724class LLoadFunctionPrototype FINAL : public LTemplateInstruction<1, 1, 1> {
1725 public:
1726  LLoadFunctionPrototype(LOperand* function, LOperand* temp) {
1727    inputs_[0] = function;
1728    temps_[0] = temp;
1729  }
1730
1731  LOperand* function() { return inputs_[0]; }
1732  LOperand* temp() { return temps_[0]; }
1733
1734  DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
1735  DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
1736};
1737
1738
1739class LLoadGlobalCell FINAL : public LTemplateInstruction<1, 0, 0> {
1740 public:
1741  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell, "load-global-cell")
1742  DECLARE_HYDROGEN_ACCESSOR(LoadGlobalCell)
1743};
1744
1745
1746class LLoadGlobalGeneric FINAL : public LTemplateInstruction<1, 2, 1> {
1747 public:
1748  LLoadGlobalGeneric(LOperand* context, LOperand* global_object,
1749                     LOperand* vector) {
1750    inputs_[0] = context;
1751    inputs_[1] = global_object;
1752    temps_[0] = vector;
1753  }
1754
1755  LOperand* context() { return inputs_[0]; }
1756  LOperand* global_object() { return inputs_[1]; }
1757  LOperand* temp_vector() { return temps_[0]; }
1758
1759  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
1760  DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)
1761
1762  Handle<Object> name() const { return hydrogen()->name(); }
1763  bool for_typeof() const { return hydrogen()->for_typeof(); }
1764};
1765
1766
1767template<int T>
1768class LLoadKeyed : public LTemplateInstruction<1, 2, T> {
1769 public:
1770  LLoadKeyed(LOperand* elements, LOperand* key) {
1771    this->inputs_[0] = elements;
1772    this->inputs_[1] = key;
1773  }
1774
1775  LOperand* elements() { return this->inputs_[0]; }
1776  LOperand* key() { return this->inputs_[1]; }
1777  ElementsKind elements_kind() const {
1778    return this->hydrogen()->elements_kind();
1779  }
1780  bool is_external() const {
1781    return this->hydrogen()->is_external();
1782  }
1783  bool is_fixed_typed_array() const {
1784    return hydrogen()->is_fixed_typed_array();
1785  }
1786  bool is_typed_elements() const {
1787    return is_external() || is_fixed_typed_array();
1788  }
1789  uint32_t base_offset() const {
1790    return this->hydrogen()->base_offset();
1791  }
1792  void PrintDataTo(StringStream* stream) OVERRIDE {
1793    this->elements()->PrintTo(stream);
1794    stream->Add("[");
1795    this->key()->PrintTo(stream);
1796    if (this->base_offset() != 0) {
1797      stream->Add(" + %d]", this->base_offset());
1798    } else {
1799      stream->Add("]");
1800    }
1801  }
1802
1803  DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
1804};
1805
1806
1807class LLoadKeyedExternal: public LLoadKeyed<1> {
1808 public:
1809  LLoadKeyedExternal(LOperand* elements, LOperand* key, LOperand* temp) :
1810      LLoadKeyed<1>(elements, key) {
1811    temps_[0] = temp;
1812  }
1813
1814  LOperand* temp() { return temps_[0]; }
1815
1816  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedExternal, "load-keyed-external");
1817};
1818
1819
1820class LLoadKeyedFixed: public LLoadKeyed<1> {
1821 public:
1822  LLoadKeyedFixed(LOperand* elements, LOperand* key, LOperand* temp) :
1823      LLoadKeyed<1>(elements, key) {
1824    temps_[0] = temp;
1825  }
1826
1827  LOperand* temp() { return temps_[0]; }
1828
1829  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFixed, "load-keyed-fixed");
1830};
1831
1832
1833class LLoadKeyedFixedDouble: public LLoadKeyed<1> {
1834 public:
1835  LLoadKeyedFixedDouble(LOperand* elements, LOperand* key, LOperand* temp) :
1836      LLoadKeyed<1>(elements, key) {
1837    temps_[0] = temp;
1838  }
1839
1840  LOperand* temp() { return temps_[0]; }
1841
1842  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFixedDouble, "load-keyed-fixed-double");
1843};
1844
1845
1846class LLoadKeyedGeneric FINAL : public LTemplateInstruction<1, 3, 1> {
1847 public:
1848  LLoadKeyedGeneric(LOperand* context, LOperand* object, LOperand* key,
1849                    LOperand* vector) {
1850    inputs_[0] = context;
1851    inputs_[1] = object;
1852    inputs_[2] = key;
1853    temps_[0] = vector;
1854  }
1855
1856  LOperand* context() { return inputs_[0]; }
1857  LOperand* object() { return inputs_[1]; }
1858  LOperand* key() { return inputs_[2]; }
1859  LOperand* temp_vector() { return temps_[0]; }
1860
1861  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic")
1862  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedGeneric)
1863};
1864
1865
1866class LLoadNamedGeneric FINAL : public LTemplateInstruction<1, 2, 1> {
1867 public:
1868  LLoadNamedGeneric(LOperand* context, LOperand* object, LOperand* vector) {
1869    inputs_[0] = context;
1870    inputs_[1] = object;
1871    temps_[0] = vector;
1872  }
1873
1874  LOperand* context() { return inputs_[0]; }
1875  LOperand* object() { return inputs_[1]; }
1876  LOperand* temp_vector() { return temps_[0]; }
1877
1878  DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic")
1879  DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric)
1880
1881  Handle<Object> name() const { return hydrogen()->name(); }
1882};
1883
1884
1885class LLoadRoot FINAL : public LTemplateInstruction<1, 0, 0> {
1886 public:
1887  DECLARE_CONCRETE_INSTRUCTION(LoadRoot, "load-root")
1888  DECLARE_HYDROGEN_ACCESSOR(LoadRoot)
1889
1890  Heap::RootListIndex index() const { return hydrogen()->index(); }
1891};
1892
1893
1894class LMapEnumLength FINAL : public LTemplateInstruction<1, 1, 0> {
1895 public:
1896  explicit LMapEnumLength(LOperand* value) {
1897    inputs_[0] = value;
1898  }
1899
1900  LOperand* value() { return inputs_[0]; }
1901
1902  DECLARE_CONCRETE_INSTRUCTION(MapEnumLength, "map-enum-length")
1903};
1904
1905
1906template<int T>
1907class LUnaryMathOperation : public LTemplateInstruction<1, 1, T> {
1908 public:
1909  explicit LUnaryMathOperation(LOperand* value) {
1910    this->inputs_[0] = value;
1911  }
1912
1913  LOperand* value() { return this->inputs_[0]; }
1914  BuiltinFunctionId op() const { return this->hydrogen()->op(); }
1915
1916  void PrintDataTo(StringStream* stream) OVERRIDE;
1917
1918  DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
1919};
1920
1921
1922class LMathAbs FINAL : public LUnaryMathOperation<0> {
1923 public:
1924  explicit LMathAbs(LOperand* value) : LUnaryMathOperation<0>(value) {}
1925
1926  DECLARE_CONCRETE_INSTRUCTION(MathAbs, "math-abs")
1927};
1928
1929
1930class LMathAbsTagged: public LTemplateInstruction<1, 2, 3> {
1931 public:
1932  LMathAbsTagged(LOperand* context, LOperand* value,
1933                 LOperand* temp1, LOperand* temp2, LOperand* temp3) {
1934    inputs_[0] = context;
1935    inputs_[1] = value;
1936    temps_[0] = temp1;
1937    temps_[1] = temp2;
1938    temps_[2] = temp3;
1939  }
1940
1941  LOperand* context() { return inputs_[0]; }
1942  LOperand* value() { return inputs_[1]; }
1943  LOperand* temp1() { return temps_[0]; }
1944  LOperand* temp2() { return temps_[1]; }
1945  LOperand* temp3() { return temps_[2]; }
1946
1947  DECLARE_CONCRETE_INSTRUCTION(MathAbsTagged, "math-abs-tagged")
1948  DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
1949};
1950
1951
1952class LMathExp FINAL : public LUnaryMathOperation<4> {
1953 public:
1954  LMathExp(LOperand* value,
1955                LOperand* double_temp1,
1956                LOperand* temp1,
1957                LOperand* temp2,
1958                LOperand* temp3)
1959      : LUnaryMathOperation<4>(value) {
1960    temps_[0] = double_temp1;
1961    temps_[1] = temp1;
1962    temps_[2] = temp2;
1963    temps_[3] = temp3;
1964    ExternalReference::InitializeMathExpData();
1965  }
1966
1967  LOperand* double_temp1() { return temps_[0]; }
1968  LOperand* temp1() { return temps_[1]; }
1969  LOperand* temp2() { return temps_[2]; }
1970  LOperand* temp3() { return temps_[3]; }
1971
1972  DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
1973};
1974
1975
1976// Math.floor with a double result.
1977class LMathFloorD FINAL : public LUnaryMathOperation<0> {
1978 public:
1979  explicit LMathFloorD(LOperand* value) : LUnaryMathOperation<0>(value) { }
1980  DECLARE_CONCRETE_INSTRUCTION(MathFloorD, "math-floor-d")
1981};
1982
1983
1984// Math.floor with an integer result.
1985class LMathFloorI FINAL : public LUnaryMathOperation<0> {
1986 public:
1987  explicit LMathFloorI(LOperand* value) : LUnaryMathOperation<0>(value) { }
1988  DECLARE_CONCRETE_INSTRUCTION(MathFloorI, "math-floor-i")
1989};
1990
1991
1992class LFlooringDivByPowerOf2I FINAL : public LTemplateInstruction<1, 1, 0> {
1993 public:
1994  LFlooringDivByPowerOf2I(LOperand* dividend, int32_t divisor) {
1995    inputs_[0] = dividend;
1996    divisor_ = divisor;
1997  }
1998
1999  LOperand* dividend() { return inputs_[0]; }
2000  int32_t divisor() const { return divisor_; }
2001
2002  DECLARE_CONCRETE_INSTRUCTION(FlooringDivByPowerOf2I,
2003                               "flooring-div-by-power-of-2-i")
2004  DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
2005
2006 private:
2007  int32_t divisor_;
2008};
2009
2010
2011class LFlooringDivByConstI FINAL : public LTemplateInstruction<1, 1, 2> {
2012 public:
2013  LFlooringDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
2014    inputs_[0] = dividend;
2015    divisor_ = divisor;
2016    temps_[0] = temp;
2017  }
2018
2019  LOperand* dividend() { return inputs_[0]; }
2020  int32_t divisor() const { return divisor_; }
2021  LOperand* temp() { return temps_[0]; }
2022
2023  DECLARE_CONCRETE_INSTRUCTION(FlooringDivByConstI, "flooring-div-by-const-i")
2024  DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
2025
2026 private:
2027  int32_t divisor_;
2028};
2029
2030
2031class LFlooringDivI FINAL : public LTemplateInstruction<1, 2, 1> {
2032 public:
2033  LFlooringDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
2034    inputs_[0] = dividend;
2035    inputs_[1] = divisor;
2036    temps_[0] = temp;
2037  }
2038
2039  LOperand* dividend() { return inputs_[0]; }
2040  LOperand* divisor() { return inputs_[1]; }
2041  LOperand* temp() { return temps_[0]; }
2042
2043  DECLARE_CONCRETE_INSTRUCTION(FlooringDivI, "flooring-div-i")
2044  DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
2045};
2046
2047
2048class LMathLog FINAL : public LUnaryMathOperation<0> {
2049 public:
2050  explicit LMathLog(LOperand* value) : LUnaryMathOperation<0>(value) { }
2051  DECLARE_CONCRETE_INSTRUCTION(MathLog, "math-log")
2052};
2053
2054
2055class LMathClz32 FINAL : public LUnaryMathOperation<0> {
2056 public:
2057  explicit LMathClz32(LOperand* value) : LUnaryMathOperation<0>(value) { }
2058  DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
2059};
2060
2061
2062class LMathMinMax FINAL : public LTemplateInstruction<1, 2, 0> {
2063 public:
2064  LMathMinMax(LOperand* left, LOperand* right) {
2065    inputs_[0] = left;
2066    inputs_[1] = right;
2067  }
2068
2069  LOperand* left() { return inputs_[0]; }
2070  LOperand* right() { return inputs_[1]; }
2071
2072  DECLARE_CONCRETE_INSTRUCTION(MathMinMax, "math-min-max")
2073  DECLARE_HYDROGEN_ACCESSOR(MathMinMax)
2074};
2075
2076
2077class LMathPowHalf FINAL : public LUnaryMathOperation<0> {
2078 public:
2079  explicit LMathPowHalf(LOperand* value) : LUnaryMathOperation<0>(value) { }
2080  DECLARE_CONCRETE_INSTRUCTION(MathPowHalf, "math-pow-half")
2081};
2082
2083
2084// Math.round with an integer result.
2085class LMathRoundD FINAL : public LUnaryMathOperation<0> {
2086 public:
2087  explicit LMathRoundD(LOperand* value)
2088      : LUnaryMathOperation<0>(value) {
2089  }
2090
2091  DECLARE_CONCRETE_INSTRUCTION(MathRoundD, "math-round-d")
2092};
2093
2094
2095// Math.round with an integer result.
2096class LMathRoundI FINAL : public LUnaryMathOperation<1> {
2097 public:
2098  LMathRoundI(LOperand* value, LOperand* temp1)
2099      : LUnaryMathOperation<1>(value) {
2100    temps_[0] = temp1;
2101  }
2102
2103  LOperand* temp1() { return temps_[0]; }
2104
2105  DECLARE_CONCRETE_INSTRUCTION(MathRoundI, "math-round-i")
2106};
2107
2108
2109class LMathFround FINAL : public LUnaryMathOperation<0> {
2110 public:
2111  explicit LMathFround(LOperand* value) : LUnaryMathOperation<0>(value) {}
2112
2113  DECLARE_CONCRETE_INSTRUCTION(MathFround, "math-fround")
2114};
2115
2116
2117class LMathSqrt FINAL : public LUnaryMathOperation<0> {
2118 public:
2119  explicit LMathSqrt(LOperand* value) : LUnaryMathOperation<0>(value) { }
2120  DECLARE_CONCRETE_INSTRUCTION(MathSqrt, "math-sqrt")
2121};
2122
2123
2124class LModByPowerOf2I FINAL : public LTemplateInstruction<1, 1, 0> {
2125 public:
2126  LModByPowerOf2I(LOperand* dividend, int32_t divisor) {
2127    inputs_[0] = dividend;
2128    divisor_ = divisor;
2129  }
2130
2131  LOperand* dividend() { return inputs_[0]; }
2132  int32_t divisor() const { return divisor_; }
2133
2134  DECLARE_CONCRETE_INSTRUCTION(ModByPowerOf2I, "mod-by-power-of-2-i")
2135  DECLARE_HYDROGEN_ACCESSOR(Mod)
2136
2137 private:
2138  int32_t divisor_;
2139};
2140
2141
2142class LModByConstI FINAL : public LTemplateInstruction<1, 1, 1> {
2143 public:
2144  LModByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
2145    inputs_[0] = dividend;
2146    divisor_ = divisor;
2147    temps_[0] = temp;
2148  }
2149
2150  LOperand* dividend() { return inputs_[0]; }
2151  int32_t divisor() const { return divisor_; }
2152  LOperand* temp() { return temps_[0]; }
2153
2154  DECLARE_CONCRETE_INSTRUCTION(ModByConstI, "mod-by-const-i")
2155  DECLARE_HYDROGEN_ACCESSOR(Mod)
2156
2157 private:
2158  int32_t divisor_;
2159};
2160
2161
2162class LModI FINAL : public LTemplateInstruction<1, 2, 0> {
2163 public:
2164  LModI(LOperand* left, LOperand* right) {
2165    inputs_[0] = left;
2166    inputs_[1] = right;
2167  }
2168
2169  LOperand* left() { return inputs_[0]; }
2170  LOperand* right() { return inputs_[1]; }
2171
2172  DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i")
2173  DECLARE_HYDROGEN_ACCESSOR(Mod)
2174};
2175
2176
2177class LMulConstIS FINAL : public LTemplateInstruction<1, 2, 0> {
2178 public:
2179  LMulConstIS(LOperand* left, LConstantOperand* right) {
2180    inputs_[0] = left;
2181    inputs_[1] = right;
2182  }
2183
2184  LOperand* left() { return inputs_[0]; }
2185  LConstantOperand* right() { return LConstantOperand::cast(inputs_[1]); }
2186
2187  DECLARE_CONCRETE_INSTRUCTION(MulConstIS, "mul-const-i-s")
2188  DECLARE_HYDROGEN_ACCESSOR(Mul)
2189};
2190
2191
2192class LMulI FINAL : public LTemplateInstruction<1, 2, 0> {
2193 public:
2194  LMulI(LOperand* left, LOperand* right) {
2195    inputs_[0] = left;
2196    inputs_[1] = right;
2197  }
2198
2199  LOperand* left() { return inputs_[0]; }
2200  LOperand* right() { return inputs_[1]; }
2201
2202  DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i")
2203  DECLARE_HYDROGEN_ACCESSOR(Mul)
2204};
2205
2206
2207class LMulS FINAL : public LTemplateInstruction<1, 2, 0> {
2208 public:
2209  LMulS(LOperand* left, LOperand* right) {
2210    inputs_[0] = left;
2211    inputs_[1] = right;
2212  }
2213
2214  LOperand* left() { return inputs_[0]; }
2215  LOperand* right() { return inputs_[1]; }
2216
2217  DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-s")
2218  DECLARE_HYDROGEN_ACCESSOR(Mul)
2219};
2220
2221
2222class LNumberTagD FINAL : public LTemplateInstruction<1, 1, 2> {
2223 public:
2224  LNumberTagD(LOperand* value, LOperand* temp1, LOperand* temp2) {
2225    inputs_[0] = value;
2226    temps_[0] = temp1;
2227    temps_[1] = temp2;
2228  }
2229
2230  LOperand* value() { return inputs_[0]; }
2231  LOperand* temp1() { return temps_[0]; }
2232  LOperand* temp2() { return temps_[1]; }
2233
2234  DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d")
2235  DECLARE_HYDROGEN_ACCESSOR(Change)
2236};
2237
2238
2239class LNumberTagU FINAL : public LTemplateInstruction<1, 1, 2> {
2240 public:
2241  explicit LNumberTagU(LOperand* value,
2242                       LOperand* temp1,
2243                       LOperand* temp2) {
2244    inputs_[0] = value;
2245    temps_[0] = temp1;
2246    temps_[1] = temp2;
2247  }
2248
2249  LOperand* value() { return inputs_[0]; }
2250  LOperand* temp1() { return temps_[0]; }
2251  LOperand* temp2() { return temps_[1]; }
2252
2253  DECLARE_CONCRETE_INSTRUCTION(NumberTagU, "number-tag-u")
2254};
2255
2256
2257class LNumberUntagD FINAL : public LTemplateInstruction<1, 1, 1> {
2258 public:
2259  LNumberUntagD(LOperand* value, LOperand* temp) {
2260    inputs_[0] = value;
2261    temps_[0] = temp;
2262  }
2263
2264  LOperand* value() { return inputs_[0]; }
2265
2266  LOperand* temp() { return temps_[0]; }
2267
2268  DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
2269  DECLARE_HYDROGEN_ACCESSOR(Change)
2270};
2271
2272
2273class LParameter FINAL : public LTemplateInstruction<1, 0, 0> {
2274 public:
2275  virtual bool HasInterestingComment(LCodeGen* gen) const { return false; }
2276  DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
2277};
2278
2279
2280class LPower FINAL : public LTemplateInstruction<1, 2, 0> {
2281 public:
2282  LPower(LOperand* left, LOperand* right) {
2283    inputs_[0] = left;
2284    inputs_[1] = right;
2285  }
2286
2287  LOperand* left() { return inputs_[0]; }
2288  LOperand* right() { return inputs_[1]; }
2289
2290  DECLARE_CONCRETE_INSTRUCTION(Power, "power")
2291  DECLARE_HYDROGEN_ACCESSOR(Power)
2292};
2293
2294
2295class LPreparePushArguments FINAL : public LTemplateInstruction<0, 0, 0> {
2296 public:
2297  explicit LPreparePushArguments(int argc) : argc_(argc) {}
2298
2299  inline int argc() const { return argc_; }
2300
2301  DECLARE_CONCRETE_INSTRUCTION(PreparePushArguments, "prepare-push-arguments")
2302
2303 protected:
2304  int argc_;
2305};
2306
2307
2308class LPushArguments FINAL : public LTemplateResultInstruction<0> {
2309 public:
2310  explicit LPushArguments(Zone* zone,
2311                          int capacity = kRecommendedMaxPushedArgs)
2312      : zone_(zone), inputs_(capacity, zone) {}
2313
2314  LOperand* argument(int i) { return inputs_[i]; }
2315  int ArgumentCount() const { return inputs_.length(); }
2316
2317  void AddArgument(LOperand* arg) { inputs_.Add(arg, zone_); }
2318
2319  DECLARE_CONCRETE_INSTRUCTION(PushArguments, "push-arguments")
2320
2321  // It is better to limit the number of arguments pushed simultaneously to
2322  // avoid pressure on the register allocator.
2323  static const int kRecommendedMaxPushedArgs = 4;
2324  bool ShouldSplitPush() const {
2325    return inputs_.length() >= kRecommendedMaxPushedArgs;
2326  }
2327
2328 protected:
2329  Zone* zone_;
2330  ZoneList<LOperand*> inputs_;
2331
2332 private:
2333  // Iterator support.
2334  virtual int InputCount() FINAL OVERRIDE { return inputs_.length(); }
2335  virtual LOperand* InputAt(int i) FINAL OVERRIDE { return inputs_[i]; }
2336
2337  virtual int TempCount() FINAL OVERRIDE { return 0; }
2338  virtual LOperand* TempAt(int i) FINAL OVERRIDE { return NULL; }
2339};
2340
2341
2342class LRegExpLiteral FINAL : public LTemplateInstruction<1, 1, 0> {
2343 public:
2344  explicit LRegExpLiteral(LOperand* context) {
2345    inputs_[0] = context;
2346  }
2347
2348  LOperand* context() { return inputs_[0]; }
2349
2350  DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp-literal")
2351  DECLARE_HYDROGEN_ACCESSOR(RegExpLiteral)
2352};
2353
2354
2355class LReturn FINAL : public LTemplateInstruction<0, 3, 0> {
2356 public:
2357  LReturn(LOperand* value, LOperand* context, LOperand* parameter_count) {
2358    inputs_[0] = value;
2359    inputs_[1] = context;
2360    inputs_[2] = parameter_count;
2361  }
2362
2363  LOperand* value() { return inputs_[0]; }
2364  LOperand* parameter_count() { return inputs_[2]; }
2365
2366  bool has_constant_parameter_count() {
2367    return parameter_count()->IsConstantOperand();
2368  }
2369  LConstantOperand* constant_parameter_count() {
2370    DCHECK(has_constant_parameter_count());
2371    return LConstantOperand::cast(parameter_count());
2372  }
2373
2374  DECLARE_CONCRETE_INSTRUCTION(Return, "return")
2375};
2376
2377
2378class LSeqStringGetChar FINAL : public LTemplateInstruction<1, 2, 1> {
2379 public:
2380  LSeqStringGetChar(LOperand* string,
2381                    LOperand* index,
2382                    LOperand* temp) {
2383    inputs_[0] = string;
2384    inputs_[1] = index;
2385    temps_[0] = temp;
2386  }
2387
2388  LOperand* string() { return inputs_[0]; }
2389  LOperand* index() { return inputs_[1]; }
2390  LOperand* temp() { return temps_[0]; }
2391
2392  DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar, "seq-string-get-char")
2393  DECLARE_HYDROGEN_ACCESSOR(SeqStringGetChar)
2394};
2395
2396
2397class LSeqStringSetChar FINAL : public LTemplateInstruction<1, 4, 1> {
2398 public:
2399  LSeqStringSetChar(LOperand* context,
2400                    LOperand* string,
2401                    LOperand* index,
2402                    LOperand* value,
2403                    LOperand* temp) {
2404    inputs_[0] = context;
2405    inputs_[1] = string;
2406    inputs_[2] = index;
2407    inputs_[3] = value;
2408    temps_[0] = temp;
2409  }
2410
2411  LOperand* context() { return inputs_[0]; }
2412  LOperand* string() { return inputs_[1]; }
2413  LOperand* index() { return inputs_[2]; }
2414  LOperand* value() { return inputs_[3]; }
2415  LOperand* temp() { return temps_[0]; }
2416
2417  DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char")
2418  DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar)
2419};
2420
2421
2422class LSmiTag FINAL : public LTemplateInstruction<1, 1, 0> {
2423 public:
2424  explicit LSmiTag(LOperand* value) {
2425    inputs_[0] = value;
2426  }
2427
2428  LOperand* value() { return inputs_[0]; }
2429
2430  DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag")
2431  DECLARE_HYDROGEN_ACCESSOR(Change)
2432};
2433
2434
2435class LSmiUntag FINAL : public LTemplateInstruction<1, 1, 0> {
2436 public:
2437  LSmiUntag(LOperand* value, bool needs_check)
2438      : needs_check_(needs_check) {
2439    inputs_[0] = value;
2440  }
2441
2442  LOperand* value() { return inputs_[0]; }
2443  bool needs_check() const { return needs_check_; }
2444
2445  DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
2446
2447 private:
2448  bool needs_check_;
2449};
2450
2451
2452class LStackCheck FINAL : public LTemplateInstruction<0, 1, 0> {
2453 public:
2454  explicit LStackCheck(LOperand* context) {
2455    inputs_[0] = context;
2456  }
2457
2458  LOperand* context() { return inputs_[0]; }
2459
2460  DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check")
2461  DECLARE_HYDROGEN_ACCESSOR(StackCheck)
2462
2463  Label* done_label() { return &done_label_; }
2464
2465 private:
2466  Label done_label_;
2467};
2468
2469
2470template<int T>
2471class LStoreKeyed : public LTemplateInstruction<0, 3, T> {
2472 public:
2473  LStoreKeyed(LOperand* elements, LOperand* key, LOperand* value) {
2474    this->inputs_[0] = elements;
2475    this->inputs_[1] = key;
2476    this->inputs_[2] = value;
2477  }
2478
2479  bool is_external() const { return this->hydrogen()->is_external(); }
2480  bool is_fixed_typed_array() const {
2481    return hydrogen()->is_fixed_typed_array();
2482  }
2483  bool is_typed_elements() const {
2484    return is_external() || is_fixed_typed_array();
2485  }
2486  LOperand* elements() { return this->inputs_[0]; }
2487  LOperand* key() { return this->inputs_[1]; }
2488  LOperand* value() { return this->inputs_[2]; }
2489  ElementsKind elements_kind() const {
2490    return this->hydrogen()->elements_kind();
2491  }
2492
2493  bool NeedsCanonicalization() {
2494    if (hydrogen()->value()->IsAdd() || hydrogen()->value()->IsSub() ||
2495        hydrogen()->value()->IsMul() || hydrogen()->value()->IsDiv()) {
2496      return false;
2497    }
2498    return this->hydrogen()->NeedsCanonicalization();
2499  }
2500  uint32_t base_offset() const { return this->hydrogen()->base_offset(); }
2501
2502  void PrintDataTo(StringStream* stream) OVERRIDE {
2503    this->elements()->PrintTo(stream);
2504    stream->Add("[");
2505    this->key()->PrintTo(stream);
2506    if (this->base_offset() != 0) {
2507      stream->Add(" + %d] <-", this->base_offset());
2508    } else {
2509      stream->Add("] <- ");
2510    }
2511
2512    if (this->value() == NULL) {
2513      DCHECK(hydrogen()->IsConstantHoleStore() &&
2514             hydrogen()->value()->representation().IsDouble());
2515      stream->Add("<the hole(nan)>");
2516    } else {
2517      this->value()->PrintTo(stream);
2518    }
2519  }
2520
2521  DECLARE_HYDROGEN_ACCESSOR(StoreKeyed)
2522};
2523
2524
2525class LStoreKeyedExternal FINAL : public LStoreKeyed<1> {
2526 public:
2527  LStoreKeyedExternal(LOperand* elements, LOperand* key, LOperand* value,
2528                      LOperand* temp) :
2529      LStoreKeyed<1>(elements, key, value) {
2530    temps_[0] = temp;
2531  }
2532
2533  LOperand* temp() { return temps_[0]; }
2534
2535  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedExternal, "store-keyed-external")
2536};
2537
2538
2539class LStoreKeyedFixed FINAL : public LStoreKeyed<1> {
2540 public:
2541  LStoreKeyedFixed(LOperand* elements, LOperand* key, LOperand* value,
2542                   LOperand* temp) :
2543      LStoreKeyed<1>(elements, key, value) {
2544    temps_[0] = temp;
2545  }
2546
2547  LOperand* temp() { return temps_[0]; }
2548
2549  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFixed, "store-keyed-fixed")
2550};
2551
2552
2553class LStoreKeyedFixedDouble FINAL : public LStoreKeyed<1> {
2554 public:
2555  LStoreKeyedFixedDouble(LOperand* elements, LOperand* key, LOperand* value,
2556                         LOperand* temp) :
2557      LStoreKeyed<1>(elements, key, value) {
2558    temps_[0] = temp;
2559  }
2560
2561  LOperand* temp() { return temps_[0]; }
2562
2563  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFixedDouble,
2564                               "store-keyed-fixed-double")
2565};
2566
2567
2568class LStoreKeyedGeneric FINAL : public LTemplateInstruction<0, 4, 0> {
2569 public:
2570  LStoreKeyedGeneric(LOperand* context,
2571                     LOperand* obj,
2572                     LOperand* key,
2573                     LOperand* value) {
2574    inputs_[0] = context;
2575    inputs_[1] = obj;
2576    inputs_[2] = key;
2577    inputs_[3] = value;
2578  }
2579
2580  LOperand* context() { return inputs_[0]; }
2581  LOperand* object() { return inputs_[1]; }
2582  LOperand* key() { return inputs_[2]; }
2583  LOperand* value() { return inputs_[3]; }
2584
2585  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
2586  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
2587
2588  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
2589
2590  StrictMode strict_mode() { return hydrogen()->strict_mode(); }
2591};
2592
2593
2594class LStoreNamedField FINAL : public LTemplateInstruction<0, 2, 2> {
2595 public:
2596  LStoreNamedField(LOperand* object, LOperand* value,
2597                   LOperand* temp0, LOperand* temp1) {
2598    inputs_[0] = object;
2599    inputs_[1] = value;
2600    temps_[0] = temp0;
2601    temps_[1] = temp1;
2602  }
2603
2604  LOperand* object() { return inputs_[0]; }
2605  LOperand* value() { return inputs_[1]; }
2606  LOperand* temp0() { return temps_[0]; }
2607  LOperand* temp1() { return temps_[1]; }
2608
2609  DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
2610  DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
2611
2612  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
2613
2614  Representation representation() const {
2615    return hydrogen()->field_representation();
2616  }
2617};
2618
2619
2620class LStoreNamedGeneric FINAL: public LTemplateInstruction<0, 3, 0> {
2621 public:
2622  LStoreNamedGeneric(LOperand* context, LOperand* object, LOperand* value) {
2623    inputs_[0] = context;
2624    inputs_[1] = object;
2625    inputs_[2] = value;
2626  }
2627
2628  LOperand* context() { return inputs_[0]; }
2629  LOperand* object() { return inputs_[1]; }
2630  LOperand* value() { return inputs_[2]; }
2631
2632  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
2633  DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
2634
2635  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
2636
2637  Handle<Object> name() const { return hydrogen()->name(); }
2638  StrictMode strict_mode() { return hydrogen()->strict_mode(); }
2639};
2640
2641
2642class LStringAdd FINAL : public LTemplateInstruction<1, 3, 0> {
2643 public:
2644  LStringAdd(LOperand* context, LOperand* left, LOperand* right) {
2645    inputs_[0] = context;
2646    inputs_[1] = left;
2647    inputs_[2] = right;
2648  }
2649
2650  LOperand* context() { return inputs_[0]; }
2651  LOperand* left() { return inputs_[1]; }
2652  LOperand* right() { return inputs_[2]; }
2653
2654  DECLARE_CONCRETE_INSTRUCTION(StringAdd, "string-add")
2655  DECLARE_HYDROGEN_ACCESSOR(StringAdd)
2656};
2657
2658
2659
2660class LStringCharCodeAt FINAL : public LTemplateInstruction<1, 3, 0> {
2661 public:
2662  LStringCharCodeAt(LOperand* context, LOperand* string, LOperand* index) {
2663    inputs_[0] = context;
2664    inputs_[1] = string;
2665    inputs_[2] = index;
2666  }
2667
2668  LOperand* context() { return inputs_[0]; }
2669  LOperand* string() { return inputs_[1]; }
2670  LOperand* index() { return inputs_[2]; }
2671
2672  DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at")
2673  DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt)
2674};
2675
2676
2677class LStringCharFromCode FINAL : public LTemplateInstruction<1, 2, 0> {
2678 public:
2679  LStringCharFromCode(LOperand* context, LOperand* char_code) {
2680    inputs_[0] = context;
2681    inputs_[1] = char_code;
2682  }
2683
2684  LOperand* context() { return inputs_[0]; }
2685  LOperand* char_code() { return inputs_[1]; }
2686
2687  DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code")
2688  DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode)
2689};
2690
2691
2692class LStringCompareAndBranch FINAL : public LControlInstruction<3, 0> {
2693 public:
2694  LStringCompareAndBranch(LOperand* context, LOperand* left, LOperand* right) {
2695    inputs_[0] = context;
2696    inputs_[1] = left;
2697    inputs_[2] = right;
2698  }
2699
2700  LOperand* context() { return inputs_[0]; }
2701  LOperand* left() { return inputs_[1]; }
2702  LOperand* right() { return inputs_[2]; }
2703
2704  DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch,
2705                               "string-compare-and-branch")
2706  DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch)
2707
2708  Token::Value op() const { return hydrogen()->token(); }
2709
2710  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
2711};
2712
2713
2714// Truncating conversion from a tagged value to an int32.
2715class LTaggedToI FINAL : public LTemplateInstruction<1, 1, 2> {
2716 public:
2717  explicit LTaggedToI(LOperand* value, LOperand* temp1, LOperand* temp2) {
2718    inputs_[0] = value;
2719    temps_[0] = temp1;
2720    temps_[1] = temp2;
2721  }
2722
2723  LOperand* value() { return inputs_[0]; }
2724  LOperand* temp1() { return temps_[0]; }
2725  LOperand* temp2() { return temps_[1]; }
2726
2727  DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
2728  DECLARE_HYDROGEN_ACCESSOR(Change)
2729
2730  bool truncating() { return hydrogen()->CanTruncateToInt32(); }
2731};
2732
2733
2734class LShiftI FINAL : public LTemplateInstruction<1, 2, 0> {
2735 public:
2736  LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
2737      : op_(op), can_deopt_(can_deopt) {
2738    inputs_[0] = left;
2739    inputs_[1] = right;
2740  }
2741
2742  Token::Value op() const { return op_; }
2743  LOperand* left() { return inputs_[0]; }
2744  LOperand* right() { return inputs_[1]; }
2745  bool can_deopt() const { return can_deopt_; }
2746
2747  DECLARE_CONCRETE_INSTRUCTION(ShiftI, "shift-i")
2748
2749 private:
2750  Token::Value op_;
2751  bool can_deopt_;
2752};
2753
2754
2755class LShiftS FINAL : public LTemplateInstruction<1, 2, 0> {
2756 public:
2757  LShiftS(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
2758      : op_(op), can_deopt_(can_deopt) {
2759    inputs_[0] = left;
2760    inputs_[1] = right;
2761  }
2762
2763  Token::Value op() const { return op_; }
2764  LOperand* left() { return inputs_[0]; }
2765  LOperand* right() { return inputs_[1]; }
2766  bool can_deopt() const { return can_deopt_; }
2767
2768  DECLARE_CONCRETE_INSTRUCTION(ShiftS, "shift-s")
2769
2770 private:
2771  Token::Value op_;
2772  bool can_deopt_;
2773};
2774
2775
2776class LStoreCodeEntry FINAL: public LTemplateInstruction<0, 2, 1> {
2777 public:
2778  LStoreCodeEntry(LOperand* function, LOperand* code_object,
2779                  LOperand* temp) {
2780    inputs_[0] = function;
2781    inputs_[1] = code_object;
2782    temps_[0] = temp;
2783  }
2784
2785  LOperand* function() { return inputs_[0]; }
2786  LOperand* code_object() { return inputs_[1]; }
2787  LOperand* temp() { return temps_[0]; }
2788
2789  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
2790
2791  DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry, "store-code-entry")
2792  DECLARE_HYDROGEN_ACCESSOR(StoreCodeEntry)
2793};
2794
2795
2796class LStoreContextSlot FINAL : public LTemplateInstruction<0, 2, 1> {
2797 public:
2798  LStoreContextSlot(LOperand* context, LOperand* value, LOperand* temp) {
2799    inputs_[0] = context;
2800    inputs_[1] = value;
2801    temps_[0] = temp;
2802  }
2803
2804  LOperand* context() { return inputs_[0]; }
2805  LOperand* value() { return inputs_[1]; }
2806  LOperand* temp() { return temps_[0]; }
2807
2808  DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot")
2809  DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot)
2810
2811  int slot_index() { return hydrogen()->slot_index(); }
2812
2813  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
2814};
2815
2816
2817class LStoreGlobalCell FINAL : public LTemplateInstruction<0, 1, 2> {
2818 public:
2819  LStoreGlobalCell(LOperand* value, LOperand* temp1, LOperand* temp2) {
2820    inputs_[0] = value;
2821    temps_[0] = temp1;
2822    temps_[1] = temp2;
2823  }
2824
2825  LOperand* value() { return inputs_[0]; }
2826  LOperand* temp1() { return temps_[0]; }
2827  LOperand* temp2() { return temps_[1]; }
2828
2829  DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell")
2830  DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell)
2831};
2832
2833
2834class LSubI FINAL : public LTemplateInstruction<1, 2, 0> {
2835 public:
2836  LSubI(LOperand* left, LOperand* right)
2837      : shift_(NO_SHIFT), shift_amount_(0)  {
2838    inputs_[0] = left;
2839    inputs_[1] = right;
2840  }
2841
2842  LSubI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount)
2843      : shift_(shift), shift_amount_(shift_amount)  {
2844    inputs_[0] = left;
2845    inputs_[1] = right;
2846  }
2847
2848  LOperand* left() { return inputs_[0]; }
2849  LOperand* right() { return inputs_[1]; }
2850
2851  Shift shift() const { return shift_; }
2852  LOperand* shift_amount() const { return shift_amount_; }
2853
2854  DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i")
2855  DECLARE_HYDROGEN_ACCESSOR(Sub)
2856
2857 protected:
2858  Shift shift_;
2859  LOperand* shift_amount_;
2860};
2861
2862
2863class LSubS: public LTemplateInstruction<1, 2, 0> {
2864 public:
2865  LSubS(LOperand* left, LOperand* right) {
2866    inputs_[0] = left;
2867    inputs_[1] = right;
2868  }
2869
2870  LOperand* left() { return inputs_[0]; }
2871  LOperand* right() { return inputs_[1]; }
2872
2873  DECLARE_CONCRETE_INSTRUCTION(SubS, "sub-s")
2874  DECLARE_HYDROGEN_ACCESSOR(Sub)
2875};
2876
2877
2878class LThisFunction FINAL : public LTemplateInstruction<1, 0, 0> {
2879 public:
2880  DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
2881  DECLARE_HYDROGEN_ACCESSOR(ThisFunction)
2882};
2883
2884
2885class LToFastProperties FINAL : public LTemplateInstruction<1, 1, 0> {
2886 public:
2887  explicit LToFastProperties(LOperand* value) {
2888    inputs_[0] = value;
2889  }
2890
2891  LOperand* value() { return inputs_[0]; }
2892
2893  DECLARE_CONCRETE_INSTRUCTION(ToFastProperties, "to-fast-properties")
2894  DECLARE_HYDROGEN_ACCESSOR(ToFastProperties)
2895};
2896
2897
2898class LTransitionElementsKind FINAL : public LTemplateInstruction<0, 2, 2> {
2899 public:
2900  LTransitionElementsKind(LOperand* object,
2901                          LOperand* context,
2902                          LOperand* temp1,
2903                          LOperand* temp2) {
2904    inputs_[0] = object;
2905    inputs_[1] = context;
2906    temps_[0] = temp1;
2907    temps_[1] = temp2;
2908  }
2909
2910  LOperand* object() { return inputs_[0]; }
2911  LOperand* context() { return inputs_[1]; }
2912  LOperand* temp1() { return temps_[0]; }
2913  LOperand* temp2() { return temps_[1]; }
2914
2915  DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind,
2916                               "transition-elements-kind")
2917  DECLARE_HYDROGEN_ACCESSOR(TransitionElementsKind)
2918
2919  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
2920
2921  Handle<Map> original_map() { return hydrogen()->original_map().handle(); }
2922  Handle<Map> transitioned_map() {
2923    return hydrogen()->transitioned_map().handle();
2924  }
2925  ElementsKind from_kind() const { return hydrogen()->from_kind(); }
2926  ElementsKind to_kind() const { return hydrogen()->to_kind(); }
2927};
2928
2929
2930class LTrapAllocationMemento FINAL : public LTemplateInstruction<0, 1, 2> {
2931 public:
2932  LTrapAllocationMemento(LOperand* object, LOperand* temp1, LOperand* temp2) {
2933    inputs_[0] = object;
2934    temps_[0] = temp1;
2935    temps_[1] = temp2;
2936  }
2937
2938  LOperand* object() { return inputs_[0]; }
2939  LOperand* temp1() { return temps_[0]; }
2940  LOperand* temp2() { return temps_[1]; }
2941
2942  DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento, "trap-allocation-memento")
2943};
2944
2945
2946class LTruncateDoubleToIntOrSmi FINAL
2947    : public LTemplateInstruction<1, 1, 0> {
2948 public:
2949  explicit LTruncateDoubleToIntOrSmi(LOperand* value) {
2950    inputs_[0] = value;
2951  }
2952
2953  LOperand* value() { return inputs_[0]; }
2954
2955  DECLARE_CONCRETE_INSTRUCTION(TruncateDoubleToIntOrSmi,
2956                               "truncate-double-to-int-or-smi")
2957  DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
2958
2959  bool tag_result() { return hydrogen()->representation().IsSmi(); }
2960};
2961
2962
2963class LTypeof FINAL : public LTemplateInstruction<1, 2, 0> {
2964 public:
2965  LTypeof(LOperand* context, LOperand* value) {
2966    inputs_[0] = context;
2967    inputs_[1] = value;
2968  }
2969
2970  LOperand* context() { return inputs_[0]; }
2971  LOperand* value() { return inputs_[1]; }
2972
2973  DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
2974};
2975
2976
2977class LTypeofIsAndBranch FINAL : public LControlInstruction<1, 2> {
2978 public:
2979  LTypeofIsAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) {
2980    inputs_[0] = value;
2981    temps_[0] = temp1;
2982    temps_[1] = temp2;
2983  }
2984
2985  LOperand* value() { return inputs_[0]; }
2986  LOperand* temp1() { return temps_[0]; }
2987  LOperand* temp2() { return temps_[1]; }
2988
2989  DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch")
2990  DECLARE_HYDROGEN_ACCESSOR(TypeofIsAndBranch)
2991
2992  Handle<String> type_literal() const { return hydrogen()->type_literal(); }
2993
2994  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
2995};
2996
2997
2998class LUint32ToDouble FINAL : public LTemplateInstruction<1, 1, 0> {
2999 public:
3000  explicit LUint32ToDouble(LOperand* value) {
3001    inputs_[0] = value;
3002  }
3003
3004  LOperand* value() { return inputs_[0]; }
3005
3006  DECLARE_CONCRETE_INSTRUCTION(Uint32ToDouble, "uint32-to-double")
3007};
3008
3009
3010class LCheckMapValue FINAL : public LTemplateInstruction<0, 2, 1> {
3011 public:
3012  LCheckMapValue(LOperand* value, LOperand* map, LOperand* temp) {
3013    inputs_[0] = value;
3014    inputs_[1] = map;
3015    temps_[0] = temp;
3016  }
3017
3018  LOperand* value() { return inputs_[0]; }
3019  LOperand* map() { return inputs_[1]; }
3020  LOperand* temp() { return temps_[0]; }
3021
3022  DECLARE_CONCRETE_INSTRUCTION(CheckMapValue, "check-map-value")
3023};
3024
3025
3026class LLoadFieldByIndex FINAL : public LTemplateInstruction<1, 2, 0> {
3027 public:
3028  LLoadFieldByIndex(LOperand* object, LOperand* index) {
3029    inputs_[0] = object;
3030    inputs_[1] = index;
3031  }
3032
3033  LOperand* object() { return inputs_[0]; }
3034  LOperand* index() { return inputs_[1]; }
3035
3036  DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex, "load-field-by-index")
3037};
3038
3039
3040class LStoreFrameContext: public LTemplateInstruction<0, 1, 0> {
3041 public:
3042  explicit LStoreFrameContext(LOperand* context) {
3043    inputs_[0] = context;
3044  }
3045
3046  LOperand* context() { return inputs_[0]; }
3047
3048  DECLARE_CONCRETE_INSTRUCTION(StoreFrameContext, "store-frame-context")
3049};
3050
3051
3052class LAllocateBlockContext: public LTemplateInstruction<1, 2, 0> {
3053 public:
3054  LAllocateBlockContext(LOperand* context, LOperand* function) {
3055    inputs_[0] = context;
3056    inputs_[1] = function;
3057  }
3058
3059  LOperand* context() { return inputs_[0]; }
3060  LOperand* function() { return inputs_[1]; }
3061
3062  Handle<ScopeInfo> scope_info() { return hydrogen()->scope_info(); }
3063
3064  DECLARE_CONCRETE_INSTRUCTION(AllocateBlockContext, "allocate-block-context")
3065  DECLARE_HYDROGEN_ACCESSOR(AllocateBlockContext)
3066};
3067
3068
3069class LWrapReceiver FINAL : public LTemplateInstruction<1, 2, 0> {
3070 public:
3071  LWrapReceiver(LOperand* receiver, LOperand* function) {
3072    inputs_[0] = receiver;
3073    inputs_[1] = function;
3074  }
3075
3076  DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
3077  DECLARE_HYDROGEN_ACCESSOR(WrapReceiver)
3078
3079  LOperand* receiver() { return inputs_[0]; }
3080  LOperand* function() { return inputs_[1]; }
3081};
3082
3083
3084class LChunkBuilder;
3085class LPlatformChunk FINAL : public LChunk {
3086 public:
3087  LPlatformChunk(CompilationInfo* info, HGraph* graph)
3088      : LChunk(info, graph) { }
3089
3090  int GetNextSpillIndex();
3091  LOperand* GetNextSpillSlot(RegisterKind kind);
3092};
3093
3094
3095class LChunkBuilder FINAL : public LChunkBuilderBase {
3096 public:
3097  LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator)
3098      : LChunkBuilderBase(info, graph),
3099        current_instruction_(NULL),
3100        current_block_(NULL),
3101        allocator_(allocator) {}
3102
3103  // Build the sequence for the graph.
3104  LPlatformChunk* Build();
3105
3106  // Declare methods that deal with the individual node types.
3107#define DECLARE_DO(type) LInstruction* Do##type(H##type* node);
3108  HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
3109#undef DECLARE_DO
3110
3111  LInstruction* DoDivByPowerOf2I(HDiv* instr);
3112  LInstruction* DoDivByConstI(HDiv* instr);
3113  LInstruction* DoDivI(HBinaryOperation* instr);
3114  LInstruction* DoModByPowerOf2I(HMod* instr);
3115  LInstruction* DoModByConstI(HMod* instr);
3116  LInstruction* DoModI(HMod* instr);
3117  LInstruction* DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr);
3118  LInstruction* DoFlooringDivByConstI(HMathFloorOfDiv* instr);
3119  LInstruction* DoFlooringDivI(HMathFloorOfDiv* instr);
3120
3121  static bool HasMagicNumberForDivision(int32_t divisor);
3122
3123 private:
3124  // Methods for getting operands for Use / Define / Temp.
3125  LUnallocated* ToUnallocated(Register reg);
3126  LUnallocated* ToUnallocated(DoubleRegister reg);
3127
3128  // Methods for setting up define-use relationships.
3129  MUST_USE_RESULT LOperand* Use(HValue* value, LUnallocated* operand);
3130  MUST_USE_RESULT LOperand* UseFixed(HValue* value, Register fixed_register);
3131  MUST_USE_RESULT LOperand* UseFixedDouble(HValue* value,
3132                                           DoubleRegister fixed_register);
3133
3134  // A value that is guaranteed to be allocated to a register.
3135  // The operand created by UseRegister is guaranteed to be live until the end
3136  // of the instruction. This means that register allocator will not reuse its
3137  // register for any other operand inside instruction.
3138  MUST_USE_RESULT LOperand* UseRegister(HValue* value);
3139
3140  // The operand created by UseRegisterAndClobber is guaranteed to be live until
3141  // the end of the end of the instruction, and it may also be used as a scratch
3142  // register by the instruction implementation.
3143  //
3144  // This behaves identically to ARM's UseTempRegister. However, it is renamed
3145  // to discourage its use in ARM64, since in most cases it is better to
3146  // allocate a temporary register for the Lithium instruction.
3147  MUST_USE_RESULT LOperand* UseRegisterAndClobber(HValue* value);
3148
3149  // The operand created by UseRegisterAtStart is guaranteed to be live only at
3150  // instruction start. The register allocator is free to assign the same
3151  // register to some other operand used inside instruction (i.e. temporary or
3152  // output).
3153  MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value);
3154
3155  // An input operand in a register or a constant operand.
3156  MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value);
3157  MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value);
3158
3159  // A constant operand.
3160  MUST_USE_RESULT LConstantOperand* UseConstant(HValue* value);
3161
3162  // An input operand in register, stack slot or a constant operand.
3163  // Will not be moved to a register even if one is freely available.
3164  virtual MUST_USE_RESULT LOperand* UseAny(HValue* value);
3165
3166  // Temporary operand that must be in a register.
3167  MUST_USE_RESULT LUnallocated* TempRegister();
3168
3169  // Temporary operand that must be in a double register.
3170  MUST_USE_RESULT LUnallocated* TempDoubleRegister();
3171
3172  MUST_USE_RESULT LOperand* FixedTemp(Register reg);
3173
3174  // Temporary operand that must be in a fixed double register.
3175  MUST_USE_RESULT LOperand* FixedTemp(DoubleRegister reg);
3176
3177  // Methods for setting up define-use relationships.
3178  // Return the same instruction that they are passed.
3179  LInstruction* Define(LTemplateResultInstruction<1>* instr,
3180                       LUnallocated* result);
3181  LInstruction* DefineAsRegister(LTemplateResultInstruction<1>* instr);
3182  LInstruction* DefineAsSpilled(LTemplateResultInstruction<1>* instr,
3183                                int index);
3184
3185  LInstruction* DefineSameAsFirst(LTemplateResultInstruction<1>* instr);
3186  LInstruction* DefineFixed(LTemplateResultInstruction<1>* instr,
3187                            Register reg);
3188  LInstruction* DefineFixedDouble(LTemplateResultInstruction<1>* instr,
3189                                  DoubleRegister reg);
3190
3191  enum CanDeoptimize { CAN_DEOPTIMIZE_EAGERLY, CANNOT_DEOPTIMIZE_EAGERLY };
3192
3193  // By default we assume that instruction sequences generated for calls
3194  // cannot deoptimize eagerly and we do not attach environment to this
3195  // instruction.
3196  LInstruction* MarkAsCall(
3197      LInstruction* instr,
3198      HInstruction* hinstr,
3199      CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY);
3200
3201  LInstruction* AssignPointerMap(LInstruction* instr);
3202  LInstruction* AssignEnvironment(LInstruction* instr);
3203
3204  void VisitInstruction(HInstruction* current);
3205  void AddInstruction(LInstruction* instr, HInstruction* current);
3206  void DoBasicBlock(HBasicBlock* block);
3207
3208  int JSShiftAmountFromHConstant(HValue* constant) {
3209    return HConstant::cast(constant)->Integer32Value() & 0x1f;
3210  }
3211  bool LikelyFitsImmField(HInstruction* instr, int imm) {
3212    if (instr->IsAdd() || instr->IsSub()) {
3213      return Assembler::IsImmAddSub(imm) || Assembler::IsImmAddSub(-imm);
3214    } else {
3215      DCHECK(instr->IsBitwise());
3216      unsigned unused_n, unused_imm_s, unused_imm_r;
3217      return Assembler::IsImmLogical(imm, kWRegSizeInBits,
3218                                     &unused_n, &unused_imm_s, &unused_imm_r);
3219    }
3220  }
3221
3222  // Indicates if a sequence of the form
3223  //   lsl x8, x9, #imm
3224  //   add x0, x1, x8
3225  // can be replaced with:
3226  //   add x0, x1, x9 LSL #imm
3227  // If this is not possible, the function returns NULL. Otherwise it returns a
3228  // pointer to the shift instruction that would be optimized away.
3229  HBitwiseBinaryOperation* CanTransformToShiftedOp(HValue* val,
3230                                                   HValue** left = NULL);
3231  // Checks if all uses of the shift operation can optimize it away.
3232  bool ShiftCanBeOptimizedAway(HBitwiseBinaryOperation* shift);
3233  // Attempts to merge the binary operation and an eventual previous shift
3234  // operation into a single operation. Returns the merged instruction on
3235  // success, and NULL otherwise.
3236  LInstruction* TryDoOpWithShiftedRightOperand(HBinaryOperation* op);
3237  LInstruction* DoShiftedBinaryOp(HBinaryOperation* instr,
3238                                  HValue* left,
3239                                  HBitwiseBinaryOperation* shift);
3240
3241  LInstruction* DoShift(Token::Value op, HBitwiseBinaryOperation* instr);
3242  LInstruction* DoArithmeticD(Token::Value op,
3243                              HArithmeticBinaryOperation* instr);
3244  LInstruction* DoArithmeticT(Token::Value op,
3245                              HBinaryOperation* instr);
3246
3247  HInstruction* current_instruction_;
3248  HBasicBlock* current_block_;
3249  LAllocator* allocator_;
3250
3251  DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
3252};
3253
3254#undef DECLARE_HYDROGEN_ACCESSOR
3255#undef DECLARE_CONCRETE_INSTRUCTION
3256
3257} }  // namespace v8::internal
3258
3259#endif  // V8_ARM64_LITHIUM_ARM64_H_
3260