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