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