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