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