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