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