Home | History | Annotate | Download | only in arm64
      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:
    203   LInstruction()
    204       : environment_(NULL),
    205         hydrogen_value_(NULL),
    206         bit_field_(IsCallBits::encode(false)) { }
    207 
    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; }
    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 
    236   virtual bool IsControl() const { return false; }
    237 
    238   // Try deleting this instruction if possible.
    239   virtual bool TryDelete() { return false; }
    240 
    241   void set_environment(LEnvironment* env) { environment_ = env; }
    242   LEnvironment* environment() const { return environment_; }
    243   bool HasEnvironment() const { return environment_ != NULL; }
    244 
    245   void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); }
    246   LPointerMap* pointer_map() const { return pointer_map_.get(); }
    247   bool HasPointerMap() const { return pointer_map_.is_set(); }
    248 
    249   void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
    250   HValue* hydrogen_value() const { return hydrogen_value_; }
    251 
    252   virtual void SetDeferredLazyDeoptimizationEnvironment(LEnvironment* env) { }
    253 
    254   void MarkAsCall() { bit_field_ = IsCallBits::update(bit_field_, true); }
    255   bool IsCall() const { return IsCallBits::decode(bit_field_); }
    256 
    257   // Interface to the register allocator and iterators.
    258   bool ClobbersTemps() const { return IsCall(); }
    259   bool ClobbersRegisters() const { return IsCall(); }
    260   virtual bool ClobbersDoubleRegisters(Isolate* isolate) const {
    261     return IsCall();
    262   }
    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 
    273   LOperand* FirstInput() { return InputAt(0); }
    274   LOperand* Output() { return HasResult() ? result() : NULL; }
    275 
    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);
    298   virtual bool HasResult() const FINAL OVERRIDE {
    299     return (R != 0) && (result() != NULL);
    300   }
    301   void set_result(LOperand* operand) { results_[0] = operand; }
    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.
    320   virtual int InputCount() FINAL OVERRIDE { return I; }
    321   virtual LOperand* InputAt(int i) FINAL OVERRIDE { return inputs_[i]; }
    322 
    323   virtual int TempCount() FINAL OVERRIDE { return T; }
    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:
    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 
    339   LOperand* context() { return inputs_[0]; }
    340   LOperand* receiver() { return inputs_[1]; }
    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:
    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:
    361   LControlInstruction() : false_label_(NULL), true_label_(NULL) { }
    362 
    363   virtual bool IsControl() const FINAL OVERRIDE { return true; }
    364 
    365   int SuccessorCount() { return hydrogen()->SuccessorCount(); }
    366   HBasicBlock* SuccessorAt(int i) { return hydrogen()->SuccessorAt(i); }
    367 
    368   int TrueDestination(LChunk* chunk) {
    369     return chunk->LookupDestination(true_block_id());
    370   }
    371 
    372   int FalseDestination(LChunk* chunk) {
    373     return chunk->LookupDestination(false_block_id());
    374   }
    375 
    376   Label* TrueLabel(LChunk* chunk) {
    377     if (true_label_ == NULL) {
    378       true_label_ = chunk->GetAssemblyLabel(TrueDestination(chunk));
    379     }
    380     return true_label_;
    381   }
    382 
    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:
    391   int true_block_id() { return SuccessorAt(0)->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:
    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.
    413   virtual bool IsGap() const OVERRIDE { return true; }
    414   virtual void PrintDataTo(StringStream* stream) OVERRIDE;
    415   static LGap* cast(LInstruction* instr) {
    416     DCHECK(instr->IsGap());
    417     return reinterpret_cast<LGap*>(instr);
    418   }
    419 
    420   bool IsRedundant() const;
    421 
    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 
    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 
    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:
    452   explicit LInstructionGap(HBasicBlock* block) : LGap(block) { }
    453 
    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:
    464   explicit LDrop(int count) : count_(count) { }
    465 
    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:
    477   LDummy() {}
    478   DECLARE_CONCRETE_INSTRUCTION(Dummy, "dummy")
    479 };
    480 
    481 
    482 class LDummyUse FINAL : public LTemplateInstruction<1, 1, 0> {
    483  public:
    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:
    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;
    498   virtual bool IsControl() const OVERRIDE { return true; }
    499 
    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:
    509   LLazyBailout() : gap_instructions_size_(0) { }
    510 
    511   DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout")
    512 
    513   void set_gap_instructions_size(int gap_instructions_size) {
    514     gap_instructions_size_ = gap_instructions_size;
    515   }
    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:
    525   explicit LLabel(HBasicBlock* block)
    526       : LGap(block), replacement_(NULL) { }
    527 
    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 
    535   int block_id() const { return block()->block_id(); }
    536   bool is_loop_header() const { return block()->IsLoopHeader(); }
    537   bool is_osr_entry() const { return block()->is_osr_entry(); }
    538   Label* label() { return &label_; }
    539   LLabel* replacement() const { return replacement_; }
    540   void set_replacement(LLabel* label) { replacement_ = label; }
    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:
    551   LOsrEntry() {}
    552 
    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:
    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 
    572   LOperand* arguments() { return inputs_[0]; }
    573   LOperand* length() { return inputs_[1]; }
    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:
    582   LAddE(LOperand* left, LOperand* right) {
    583     inputs_[0] = left;
    584     inputs_[1] = right;
    585   }
    586 
    587   LOperand* left() { return inputs_[0]; }
    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:
    597   LAddI(LOperand* left, LOperand* right)
    598       : shift_(NO_SHIFT), shift_amount_(0)  {
    599     inputs_[0] = left;
    600     inputs_[1] = right;
    601   }
    602 
    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 
    609   LOperand* left() { return inputs_[0]; }
    610   LOperand* right() { return inputs_[1]; }
    611 
    612   Shift shift() const { return shift_; }
    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:
    626   LAddS(LOperand* left, LOperand* right) {
    627     inputs_[0] = left;
    628     inputs_[1] = right;
    629   }
    630 
    631   LOperand* left() { return inputs_[0]; }
    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:
    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 
    653   LOperand* context() { return inputs_[0]; }
    654   LOperand* size() { return inputs_[1]; }
    655   LOperand* temp1() { return temps_[0]; }
    656   LOperand* temp2() { return temps_[1]; }
    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:
    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 
    678   LOperand* function() { return inputs_[0]; }
    679   LOperand* receiver() { return inputs_[1]; }
    680   LOperand* length() { return inputs_[2]; }
    681   LOperand* elements() { return inputs_[3]; }
    682 };
    683 
    684 
    685 class LArgumentsElements FINAL : public LTemplateInstruction<1, 0, 1> {
    686  public:
    687   explicit LArgumentsElements(LOperand* temp) {
    688     temps_[0] = temp;
    689   }
    690 
    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:
    700   explicit LArgumentsLength(LOperand* elements) {
    701     inputs_[0] = elements;
    702   }
    703 
    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:
    712   LArithmeticD(Token::Value op,
    713                LOperand* left,
    714                LOperand* right)
    715       : op_(op) {
    716     inputs_[0] = left;
    717     inputs_[1] = right;
    718   }
    719 
    720   Token::Value op() const { return op_; }
    721   LOperand* left() { return inputs_[0]; }
    722   LOperand* right() { return inputs_[1]; }
    723 
    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:
    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 
    747   LOperand* context() { return inputs_[0]; }
    748   LOperand* left() { return inputs_[1]; }
    749   LOperand* right() { return inputs_[2]; }
    750   Token::Value op() const { return op_; }
    751 
    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:
    765   explicit LBoundsCheck(LOperand* index, LOperand* length) {
    766     inputs_[0] = index;
    767     inputs_[1] = length;
    768   }
    769 
    770   LOperand* index() { return inputs_[0]; }
    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:
    780   LBitI(LOperand* left, LOperand* right)
    781       : shift_(NO_SHIFT), shift_amount_(0)  {
    782     inputs_[0] = left;
    783     inputs_[1] = right;
    784   }
    785 
    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 
    792   LOperand* left() { return inputs_[0]; }
    793   LOperand* right() { return inputs_[1]; }
    794 
    795   Shift shift() const { return shift_; }
    796   LOperand* shift_amount() const { return shift_amount_; }
    797 
    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:
    811   LBitS(LOperand* left, LOperand* right) {
    812     inputs_[0] = left;
    813     inputs_[1] = right;
    814   }
    815 
    816   LOperand* left() { return inputs_[0]; }
    817   LOperand* right() { return inputs_[1]; }
    818 
    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:
    828   explicit LBranch(LOperand* value, LOperand *temp1, LOperand *temp2) {
    829     inputs_[0] = value;
    830     temps_[0] = temp1;
    831     temps_[1] = temp2;
    832   }
    833 
    834   LOperand* value() { return inputs_[0]; }
    835   LOperand* temp1() { return temps_[0]; }
    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:
    847   explicit LCallJSFunction(LOperand* function) {
    848     inputs_[0] = function;
    849   }
    850 
    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 
    858   int arity() const { return hydrogen()->argument_count() - 1; }
    859 };
    860 
    861 
    862 class LCallFunction FINAL : public LTemplateInstruction<1, 2, 0> {
    863  public:
    864   LCallFunction(LOperand* context, LOperand* function) {
    865     inputs_[0] = context;
    866     inputs_[1] = function;
    867   }
    868 
    869   LOperand* context() { return inputs_[0]; }
    870   LOperand* function() { return inputs_[1]; }
    871 
    872   DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call-function")
    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:
    881   LCallNew(LOperand* context, LOperand* constructor) {
    882     inputs_[0] = context;
    883     inputs_[1] = constructor;
    884   }
    885 
    886   LOperand* context() { return inputs_[0]; }
    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 
    894   int arity() const { return hydrogen()->argument_count() - 1; }
    895 };
    896 
    897 
    898 class LCallNewArray FINAL : public LTemplateInstruction<1, 2, 0> {
    899  public:
    900   LCallNewArray(LOperand* context, LOperand* constructor) {
    901     inputs_[0] = context;
    902     inputs_[1] = constructor;
    903   }
    904 
    905   LOperand* context() { return inputs_[0]; }
    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 
    913   int arity() const { return hydrogen()->argument_count() - 1; }
    914 };
    915 
    916 
    917 class LCallRuntime FINAL : public LTemplateInstruction<1, 1, 0> {
    918  public:
    919   explicit LCallRuntime(LOperand* context) {
    920     inputs_[0] = context;
    921   }
    922 
    923   LOperand* context() { return inputs_[0]; }
    924 
    925   DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
    926   DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
    927 
    928   virtual bool ClobbersDoubleRegisters(Isolate* isolate) const OVERRIDE {
    929     return save_doubles() == kDontSaveFPRegs;
    930   }
    931 
    932   const Runtime::Function* function() const { return hydrogen()->function(); }
    933   int arity() const { return hydrogen()->argument_count(); }
    934   SaveFPRegsMode save_doubles() const { return hydrogen()->save_doubles(); }
    935 };
    936 
    937 
    938 class LCallStub FINAL : public LTemplateInstruction<1, 1, 0> {
    939  public:
    940   explicit LCallStub(LOperand* context) {
    941     inputs_[0] = context;
    942   }
    943 
    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:
    953   explicit LCheckInstanceType(LOperand* value, LOperand* temp) {
    954     inputs_[0] = value;
    955     temps_[0] = temp;
    956   }
    957 
    958   LOperand* value() { return inputs_[0]; }
    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 
    973   LOperand* value() { return inputs_[0]; }
    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:
    983   explicit LCheckNonSmi(LOperand* value) {
    984     inputs_[0] = value;
    985   }
    986 
    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:
    996   explicit LCheckSmi(LOperand* value) {
    997     inputs_[0] = value;
    998   }
    999 
   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:
   1008   explicit LCheckValue(LOperand* value) {
   1009     inputs_[0] = value;
   1010   }
   1011 
   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:
   1021   explicit LClampDToUint8(LOperand* unclamped) {
   1022     inputs_[0] = unclamped;
   1023   }
   1024 
   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:
   1033   explicit LClampIToUint8(LOperand* unclamped) {
   1034     inputs_[0] = unclamped;
   1035   }
   1036 
   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:
   1045   LClampTToUint8(LOperand* unclamped, LOperand* temp1) {
   1046     inputs_[0] = unclamped;
   1047     temps_[0] = temp1;
   1048   }
   1049 
   1050   LOperand* unclamped() { return inputs_[0]; }
   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:
   1059   explicit LDoubleBits(LOperand* value) {
   1060     inputs_[0] = value;
   1061   }
   1062 
   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:
   1072   LConstructDouble(LOperand* hi, LOperand* lo) {
   1073     inputs_[0] = hi;
   1074     inputs_[1] = lo;
   1075   }
   1076 
   1077   LOperand* hi() { return inputs_[0]; }
   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:
   1086   LClassOfTestAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) {
   1087     inputs_[0] = value;
   1088     temps_[0] = temp1;
   1089     temps_[1] = temp2;
   1090   }
   1091 
   1092   LOperand* value() { return inputs_[0]; }
   1093   LOperand* temp1() { return temps_[0]; }
   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:
   1106   explicit LCmpHoleAndBranchD(LOperand* object, LOperand* temp) {
   1107     inputs_[0] = object;
   1108     temps_[0] = temp;
   1109   }
   1110 
   1111   LOperand* object() { return inputs_[0]; }
   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:
   1121   explicit LCmpHoleAndBranchT(LOperand* object) {
   1122     inputs_[0] = object;
   1123   }
   1124 
   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:
   1134   LCmpMapAndBranch(LOperand* value, LOperand* temp) {
   1135     inputs_[0] = value;
   1136     temps_[0] = temp;
   1137   }
   1138 
   1139   LOperand* value() { return inputs_[0]; }
   1140   LOperand* temp() { return temps_[0]; }
   1141 
   1142   DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
   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:
   1151   LCmpObjectEqAndBranch(LOperand* left, LOperand* right) {
   1152     inputs_[0] = left;
   1153     inputs_[1] = right;
   1154   }
   1155 
   1156   LOperand* left() { return inputs_[0]; }
   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:
   1166   LCmpT(LOperand* context, LOperand* left, LOperand* right) {
   1167     inputs_[0] = context;
   1168     inputs_[1] = left;
   1169     inputs_[2] = right;
   1170   }
   1171 
   1172   LOperand* context() { return inputs_[0]; }
   1173   LOperand* left() { return inputs_[1]; }
   1174   LOperand* right() { return inputs_[2]; }
   1175 
   1176   DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t")
   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:
   1185   LCompareMinusZeroAndBranch(LOperand* value, LOperand* temp) {
   1186     inputs_[0] = value;
   1187     temps_[0] = temp;
   1188   }
   1189 
   1190   LOperand* value() { return inputs_[0]; }
   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:
   1201   LCompareNumericAndBranch(LOperand* left, LOperand* right) {
   1202     inputs_[0] = left;
   1203     inputs_[1] = right;
   1204   }
   1205 
   1206   LOperand* left() { return inputs_[0]; }
   1207   LOperand* right() { return inputs_[1]; }
   1208 
   1209   DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch,
   1210                                "compare-numeric-and-branch")
   1211   DECLARE_HYDROGEN_ACCESSOR(CompareNumericAndBranch)
   1212 
   1213   Token::Value op() const { return hydrogen()->token(); }
   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")
   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")
   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")
   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")
   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")
   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:
   1280   LDateField(LOperand* date, Smi* index) : index_(index) {
   1281     inputs_[0] = date;
   1282   }
   1283 
   1284   LOperand* date() { return inputs_[0]; }
   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:
   1303   explicit LDeclareGlobals(LOperand* context) {
   1304     inputs_[0] = context;
   1305   }
   1306 
   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:
   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:
   1324   LDivByPowerOf2I(LOperand* dividend, int32_t divisor) {
   1325     inputs_[0] = dividend;
   1326     divisor_ = divisor;
   1327   }
   1328 
   1329   LOperand* dividend() { return inputs_[0]; }
   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:
   1342   LDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
   1343     inputs_[0] = dividend;
   1344     divisor_ = divisor;
   1345     temps_[0] = temp;
   1346   }
   1347 
   1348   LOperand* dividend() { return inputs_[0]; }
   1349   int32_t divisor() const { return divisor_; }
   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:
   1362   LDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
   1363     inputs_[0] = dividend;
   1364     inputs_[1] = divisor;
   1365     temps_[0] = temp;
   1366   }
   1367 
   1368   LOperand* dividend() { return inputs_[0]; }
   1369   LOperand* divisor() { return inputs_[1]; }
   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:
   1379   explicit LDoubleToIntOrSmi(LOperand* value) {
   1380     inputs_[0] = value;
   1381   }
   1382 
   1383   LOperand* value() { return inputs_[0]; }
   1384 
   1385   DECLARE_CONCRETE_INSTRUCTION(DoubleToIntOrSmi, "double-to-int-or-smi")
   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:
   1394   explicit LForInCacheArray(LOperand* map) {
   1395     inputs_[0] = map;
   1396   }
   1397 
   1398   LOperand* map() { return inputs_[0]; }
   1399 
   1400   DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray, "for-in-cache-array")
   1401 
   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:
   1410   LForInPrepareMap(LOperand* context, LOperand* object) {
   1411     inputs_[0] = context;
   1412     inputs_[1] = object;
   1413   }
   1414 
   1415   LOperand* context() { return inputs_[0]; }
   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:
   1424   explicit LGetCachedArrayIndex(LOperand* value) {
   1425     inputs_[0] = value;
   1426   }
   1427 
   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:
   1438   LHasCachedArrayIndexAndBranch(LOperand* value, LOperand* temp) {
   1439     inputs_[0] = value;
   1440     temps_[0] = temp;
   1441   }
   1442 
   1443   LOperand* value() { return inputs_[0]; }
   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:
   1456   LHasInstanceTypeAndBranch(LOperand* value, LOperand* temp) {
   1457     inputs_[0] = value;
   1458     temps_[0] = temp;
   1459   }
   1460 
   1461   LOperand* value() { return inputs_[0]; }
   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:
   1474   LInnerAllocatedObject(LOperand* base_object, LOperand* offset) {
   1475     inputs_[0] = base_object;
   1476     inputs_[1] = offset;
   1477   }
   1478 
   1479   LOperand* base_object() const { return inputs_[0]; }
   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:
   1490   LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
   1491     inputs_[0] = context;
   1492     inputs_[1] = left;
   1493     inputs_[2] = right;
   1494   }
   1495 
   1496   LOperand* context() { return inputs_[0]; }
   1497   LOperand* left() { return inputs_[1]; }
   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:
   1506   LInstanceOfKnownGlobal(LOperand* context, LOperand* value) {
   1507     inputs_[0] = context;
   1508     inputs_[1] = value;
   1509   }
   1510 
   1511   LOperand* context() { return inputs_[0]; }
   1512   LOperand* value() { return inputs_[1]; }
   1513 
   1514   DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
   1515                                "instance-of-known-global")
   1516   DECLARE_HYDROGEN_ACCESSOR(InstanceOfKnownGlobal)
   1517 
   1518   Handle<JSFunction> function() const { return hydrogen()->function(); }
   1519   LEnvironment* GetDeferredLazyDeoptimizationEnvironment() {
   1520     return lazy_deopt_env_;
   1521   }
   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:
   1534   explicit LInteger32ToDouble(LOperand* value) {
   1535     inputs_[0] = value;
   1536   }
   1537 
   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:
   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 
   1554   LOperand* target() const { return inputs_[0]; }
   1555 
   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 
   1564   int arity() const { return hydrogen()->argument_count() - 1; }
   1565 
   1566   CallInterfaceDescriptor descriptor_;
   1567   ZoneList<LOperand*> inputs_;
   1568 
   1569   // Iterator support.
   1570   virtual int InputCount() FINAL OVERRIDE { return inputs_.length(); }
   1571   virtual LOperand* InputAt(int i) FINAL OVERRIDE { return inputs_[i]; }
   1572 
   1573   virtual int TempCount() FINAL OVERRIDE { return 0; }
   1574   virtual LOperand* TempAt(int i) FINAL OVERRIDE { return NULL; }
   1575 };
   1576 
   1577 
   1578 class LInvokeFunction FINAL : public LTemplateInstruction<1, 2, 0> {
   1579  public:
   1580   LInvokeFunction(LOperand* context, LOperand* function) {
   1581     inputs_[0] = context;
   1582     inputs_[1] = function;
   1583   }
   1584 
   1585   LOperand* context() { return inputs_[0]; }
   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 
   1593   int arity() const { return hydrogen()->argument_count() - 1; }
   1594 };
   1595 
   1596 
   1597 class LIsConstructCallAndBranch FINAL : public LControlInstruction<0, 2> {
   1598  public:
   1599   LIsConstructCallAndBranch(LOperand* temp1, LOperand* temp2) {
   1600     temps_[0] = temp1;
   1601     temps_[1] = temp2;
   1602   }
   1603 
   1604   LOperand* temp1() { return temps_[0]; }
   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:
   1614   LIsObjectAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) {
   1615     inputs_[0] = value;
   1616     temps_[0] = temp1;
   1617     temps_[1] = temp2;
   1618   }
   1619 
   1620   LOperand* value() { return inputs_[0]; }
   1621   LOperand* temp1() { return temps_[0]; }
   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:
   1633   LIsStringAndBranch(LOperand* value, LOperand* temp) {
   1634     inputs_[0] = value;
   1635     temps_[0] = temp;
   1636   }
   1637 
   1638   LOperand* value() { return inputs_[0]; }
   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:
   1650   explicit LIsSmiAndBranch(LOperand* value) {
   1651     inputs_[0] = value;
   1652   }
   1653 
   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:
   1665   explicit LIsUndetectableAndBranch(LOperand* value, LOperand* temp) {
   1666     inputs_[0] = value;
   1667     temps_[0] = temp;
   1668   }
   1669 
   1670   LOperand* value() { return inputs_[0]; }
   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:
   1683   explicit LLoadContextSlot(LOperand* context) {
   1684     inputs_[0] = context;
   1685   }
   1686 
   1687   LOperand* context() { return inputs_[0]; }
   1688 
   1689   DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot")
   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:
   1700   explicit LLoadNamedField(LOperand* object) {
   1701     inputs_[0] = object;
   1702   }
   1703 
   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:
   1713   explicit LFunctionLiteral(LOperand* context) {
   1714     inputs_[0] = context;
   1715   }
   1716 
   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:
   1726   LLoadFunctionPrototype(LOperand* function, LOperand* temp) {
   1727     inputs_[0] = function;
   1728     temps_[0] = temp;
   1729   }
   1730 
   1731   LOperand* function() { return inputs_[0]; }
   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:
   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 
   1755   LOperand* context() { return inputs_[0]; }
   1756   LOperand* global_object() { return inputs_[1]; }
   1757   LOperand* temp_vector() { return temps_[0]; }
   1758 
   1759   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
   1760   DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)
   1761 
   1762   Handle<Object> name() const { return hydrogen()->name(); }
   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:
   1770   LLoadKeyed(LOperand* elements, LOperand* key) {
   1771     this->inputs_[0] = elements;
   1772     this->inputs_[1] = key;
   1773   }
   1774 
   1775   LOperand* elements() { return this->inputs_[0]; }
   1776   LOperand* key() { return this->inputs_[1]; }
   1777   ElementsKind elements_kind() const {
   1778     return this->hydrogen()->elements_kind();
   1779   }
   1780   bool is_external() const {
   1781     return this->hydrogen()->is_external();
   1782   }
   1783   bool is_fixed_typed_array() const {
   1784     return hydrogen()->is_fixed_typed_array();
   1785   }
   1786   bool is_typed_elements() const {
   1787     return is_external() || is_fixed_typed_array();
   1788   }
   1789   uint32_t base_offset() const {
   1790     return this->hydrogen()->base_offset();
   1791   }
   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:
   1809   LLoadKeyedExternal(LOperand* elements, LOperand* key, LOperand* temp) :
   1810       LLoadKeyed<1>(elements, key) {
   1811     temps_[0] = temp;
   1812   }
   1813 
   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:
   1822   LLoadKeyedFixed(LOperand* elements, LOperand* key, LOperand* temp) :
   1823       LLoadKeyed<1>(elements, key) {
   1824     temps_[0] = temp;
   1825   }
   1826 
   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:
   1835   LLoadKeyedFixedDouble(LOperand* elements, LOperand* key, LOperand* temp) :
   1836       LLoadKeyed<1>(elements, key) {
   1837     temps_[0] = temp;
   1838   }
   1839 
   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:
   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 
   1856   LOperand* context() { return inputs_[0]; }
   1857   LOperand* object() { return inputs_[1]; }
   1858   LOperand* key() { return inputs_[2]; }
   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:
   1868   LLoadNamedGeneric(LOperand* context, LOperand* object, LOperand* vector) {
   1869     inputs_[0] = context;
   1870     inputs_[1] = object;
   1871     temps_[0] = vector;
   1872   }
   1873 
   1874   LOperand* context() { return inputs_[0]; }
   1875   LOperand* object() { return inputs_[1]; }
   1876   LOperand* temp_vector() { return temps_[0]; }
   1877 
   1878   DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic")
   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")
   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:
   1896   explicit LMapEnumLength(LOperand* value) {
   1897     inputs_[0] = value;
   1898   }
   1899 
   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:
   1909   explicit LUnaryMathOperation(LOperand* value) {
   1910     this->inputs_[0] = value;
   1911   }
   1912 
   1913   LOperand* value() { return this->inputs_[0]; }
   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:
   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:
   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 
   1941   LOperand* context() { return inputs_[0]; }
   1942   LOperand* value() { return inputs_[1]; }
   1943   LOperand* temp1() { return temps_[0]; }
   1944   LOperand* temp2() { return temps_[1]; }
   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:
   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 
   1967   LOperand* double_temp1() { return temps_[0]; }
   1968   LOperand* temp1() { return temps_[1]; }
   1969   LOperand* temp2() { return temps_[2]; }
   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:
   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:
   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:
   1994   LFlooringDivByPowerOf2I(LOperand* dividend, int32_t divisor) {
   1995     inputs_[0] = dividend;
   1996     divisor_ = divisor;
   1997   }
   1998 
   1999   LOperand* dividend() { return inputs_[0]; }
   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:
   2013   LFlooringDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
   2014     inputs_[0] = dividend;
   2015     divisor_ = divisor;
   2016     temps_[0] = temp;
   2017   }
   2018 
   2019   LOperand* dividend() { return inputs_[0]; }
   2020   int32_t divisor() const { return divisor_; }
   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:
   2033   LFlooringDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
   2034     inputs_[0] = dividend;
   2035     inputs_[1] = divisor;
   2036     temps_[0] = temp;
   2037   }
   2038 
   2039   LOperand* dividend() { return inputs_[0]; }
   2040   LOperand* divisor() { return inputs_[1]; }
   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:
   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:
   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:
   2064   LMathMinMax(LOperand* left, LOperand* right) {
   2065     inputs_[0] = left;
   2066     inputs_[1] = right;
   2067   }
   2068 
   2069   LOperand* left() { return inputs_[0]; }
   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:
   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:
   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:
   2098   LMathRoundI(LOperand* value, LOperand* temp1)
   2099       : LUnaryMathOperation<1>(value) {
   2100     temps_[0] = temp1;
   2101   }
   2102 
   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:
   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:
   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:
   2126   LModByPowerOf2I(LOperand* dividend, int32_t divisor) {
   2127     inputs_[0] = dividend;
   2128     divisor_ = divisor;
   2129   }
   2130 
   2131   LOperand* dividend() { return inputs_[0]; }
   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:
   2144   LModByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
   2145     inputs_[0] = dividend;
   2146     divisor_ = divisor;
   2147     temps_[0] = temp;
   2148   }
   2149 
   2150   LOperand* dividend() { return inputs_[0]; }
   2151   int32_t divisor() const { return divisor_; }
   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:
   2164   LModI(LOperand* left, LOperand* right) {
   2165     inputs_[0] = left;
   2166     inputs_[1] = right;
   2167   }
   2168 
   2169   LOperand* left() { return inputs_[0]; }
   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:
   2179   LMulConstIS(LOperand* left, LConstantOperand* right) {
   2180     inputs_[0] = left;
   2181     inputs_[1] = right;
   2182   }
   2183 
   2184   LOperand* left() { return inputs_[0]; }
   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:
   2194   LMulI(LOperand* left, LOperand* right) {
   2195     inputs_[0] = left;
   2196     inputs_[1] = right;
   2197   }
   2198 
   2199   LOperand* left() { return inputs_[0]; }
   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:
   2209   LMulS(LOperand* left, LOperand* right) {
   2210     inputs_[0] = left;
   2211     inputs_[1] = right;
   2212   }
   2213 
   2214   LOperand* left() { return inputs_[0]; }
   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:
   2224   LNumberTagD(LOperand* value, LOperand* temp1, LOperand* temp2) {
   2225     inputs_[0] = value;
   2226     temps_[0] = temp1;
   2227     temps_[1] = temp2;
   2228   }
   2229 
   2230   LOperand* value() { return inputs_[0]; }
   2231   LOperand* temp1() { return temps_[0]; }
   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:
   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 
   2249   LOperand* value() { return inputs_[0]; }
   2250   LOperand* temp1() { return temps_[0]; }
   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:
   2259   LNumberUntagD(LOperand* value, LOperand* temp) {
   2260     inputs_[0] = value;
   2261     temps_[0] = temp;
   2262   }
   2263 
   2264   LOperand* value() { return inputs_[0]; }
   2265 
   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:
   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:
   2282   LPower(LOperand* left, LOperand* right) {
   2283     inputs_[0] = left;
   2284     inputs_[1] = right;
   2285   }
   2286 
   2287   LOperand* left() { return inputs_[0]; }
   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:
   2297   explicit LPreparePushArguments(int argc) : argc_(argc) {}
   2298 
   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)
   2312       : zone_(zone), inputs_(capacity, zone) {}
   2313 
   2314   LOperand* argument(int i) { return inputs_[i]; }
   2315   int ArgumentCount() const { return inputs_.length(); }
   2316 
   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;
   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.
   2334   virtual int InputCount() FINAL OVERRIDE { return inputs_.length(); }
   2335   virtual LOperand* InputAt(int i) FINAL OVERRIDE { return inputs_[i]; }
   2336 
   2337   virtual int TempCount() FINAL OVERRIDE { return 0; }
   2338   virtual LOperand* TempAt(int i) FINAL OVERRIDE { return NULL; }
   2339 };
   2340 
   2341 
   2342 class LRegExpLiteral FINAL : public LTemplateInstruction<1, 1, 0> {
   2343  public:
   2344   explicit LRegExpLiteral(LOperand* context) {
   2345     inputs_[0] = context;
   2346   }
   2347 
   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:
   2357   LReturn(LOperand* value, LOperand* context, LOperand* parameter_count) {
   2358     inputs_[0] = value;
   2359     inputs_[1] = context;
   2360     inputs_[2] = parameter_count;
   2361   }
   2362 
   2363   LOperand* value() { return inputs_[0]; }
   2364   LOperand* parameter_count() { return inputs_[2]; }
   2365 
   2366   bool has_constant_parameter_count() {
   2367     return parameter_count()->IsConstantOperand();
   2368   }
   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:
   2380   LSeqStringGetChar(LOperand* string,
   2381                     LOperand* index,
   2382                     LOperand* temp) {
   2383     inputs_[0] = string;
   2384     inputs_[1] = index;
   2385     temps_[0] = temp;
   2386   }
   2387 
   2388   LOperand* string() { return inputs_[0]; }
   2389   LOperand* index() { return inputs_[1]; }
   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:
   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 
   2411   LOperand* context() { return inputs_[0]; }
   2412   LOperand* string() { return inputs_[1]; }
   2413   LOperand* index() { return inputs_[2]; }
   2414   LOperand* value() { return inputs_[3]; }
   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:
   2424   explicit LSmiTag(LOperand* value) {
   2425     inputs_[0] = value;
   2426   }
   2427 
   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:
   2437   LSmiUntag(LOperand* value, bool needs_check)
   2438       : needs_check_(needs_check) {
   2439     inputs_[0] = value;
   2440   }
   2441 
   2442   LOperand* value() { return inputs_[0]; }
   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:
   2454   explicit LStackCheck(LOperand* context) {
   2455     inputs_[0] = context;
   2456   }
   2457 
   2458   LOperand* context() { return inputs_[0]; }
   2459 
   2460   DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check")
   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:
   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 
   2479   bool is_external() const { return this->hydrogen()->is_external(); }
   2480   bool is_fixed_typed_array() const {
   2481     return hydrogen()->is_fixed_typed_array();
   2482   }
   2483   bool is_typed_elements() const {
   2484     return is_external() || is_fixed_typed_array();
   2485   }
   2486   LOperand* elements() { return this->inputs_[0]; }
   2487   LOperand* key() { return this->inputs_[1]; }
   2488   LOperand* value() { return this->inputs_[2]; }
   2489   ElementsKind elements_kind() const {
   2490     return this->hydrogen()->elements_kind();
   2491   }
   2492 
   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   }
   2500   uint32_t base_offset() const { return this->hydrogen()->base_offset(); }
   2501 
   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:
   2527   LStoreKeyedExternal(LOperand* elements, LOperand* key, LOperand* value,
   2528                       LOperand* temp) :
   2529       LStoreKeyed<1>(elements, key, value) {
   2530     temps_[0] = temp;
   2531   }
   2532 
   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:
   2541   LStoreKeyedFixed(LOperand* elements, LOperand* key, LOperand* value,
   2542                    LOperand* temp) :
   2543       LStoreKeyed<1>(elements, key, value) {
   2544     temps_[0] = temp;
   2545   }
   2546 
   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:
   2555   LStoreKeyedFixedDouble(LOperand* elements, LOperand* key, LOperand* value,
   2556                          LOperand* temp) :
   2557       LStoreKeyed<1>(elements, key, value) {
   2558     temps_[0] = temp;
   2559   }
   2560 
   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:
   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 
   2580   LOperand* context() { return inputs_[0]; }
   2581   LOperand* object() { return inputs_[1]; }
   2582   LOperand* key() { return inputs_[2]; }
   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 
   2590   StrictMode strict_mode() { return hydrogen()->strict_mode(); }
   2591 };
   2592 
   2593 
   2594 class LStoreNamedField FINAL : public LTemplateInstruction<0, 2, 2> {
   2595  public:
   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 
   2604   LOperand* object() { return inputs_[0]; }
   2605   LOperand* value() { return inputs_[1]; }
   2606   LOperand* temp0() { return temps_[0]; }
   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 
   2614   Representation representation() const {
   2615     return hydrogen()->field_representation();
   2616   }
   2617 };
   2618 
   2619 
   2620 class LStoreNamedGeneric FINAL: public LTemplateInstruction<0, 3, 0> {
   2621  public:
   2622   LStoreNamedGeneric(LOperand* context, LOperand* object, LOperand* value) {
   2623     inputs_[0] = context;
   2624     inputs_[1] = object;
   2625     inputs_[2] = value;
   2626   }
   2627 
   2628   LOperand* context() { return inputs_[0]; }
   2629   LOperand* object() { return inputs_[1]; }
   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 
   2637   Handle<Object> name() const { return hydrogen()->name(); }
   2638   StrictMode strict_mode() { return hydrogen()->strict_mode(); }
   2639 };
   2640 
   2641 
   2642 class LStringAdd FINAL : public LTemplateInstruction<1, 3, 0> {
   2643  public:
   2644   LStringAdd(LOperand* context, LOperand* left, LOperand* right) {
   2645     inputs_[0] = context;
   2646     inputs_[1] = left;
   2647     inputs_[2] = right;
   2648   }
   2649 
   2650   LOperand* context() { return inputs_[0]; }
   2651   LOperand* left() { return inputs_[1]; }
   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:
   2662   LStringCharCodeAt(LOperand* context, LOperand* string, LOperand* index) {
   2663     inputs_[0] = context;
   2664     inputs_[1] = string;
   2665     inputs_[2] = index;
   2666   }
   2667 
   2668   LOperand* context() { return inputs_[0]; }
   2669   LOperand* string() { return inputs_[1]; }
   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:
   2679   LStringCharFromCode(LOperand* context, LOperand* char_code) {
   2680     inputs_[0] = context;
   2681     inputs_[1] = char_code;
   2682   }
   2683 
   2684   LOperand* context() { return inputs_[0]; }
   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:
   2694   LStringCompareAndBranch(LOperand* context, LOperand* left, LOperand* right) {
   2695     inputs_[0] = context;
   2696     inputs_[1] = left;
   2697     inputs_[2] = right;
   2698   }
   2699 
   2700   LOperand* context() { return inputs_[0]; }
   2701   LOperand* left() { return inputs_[1]; }
   2702   LOperand* right() { return inputs_[2]; }
   2703 
   2704   DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch,
   2705                                "string-compare-and-branch")
   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:
   2717   explicit LTaggedToI(LOperand* value, LOperand* temp1, LOperand* temp2) {
   2718     inputs_[0] = value;
   2719     temps_[0] = temp1;
   2720     temps_[1] = temp2;
   2721   }
   2722 
   2723   LOperand* value() { return inputs_[0]; }
   2724   LOperand* temp1() { return temps_[0]; }
   2725   LOperand* temp2() { return temps_[1]; }
   2726 
   2727   DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
   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:
   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 
   2742   Token::Value op() const { return op_; }
   2743   LOperand* left() { return inputs_[0]; }
   2744   LOperand* right() { return inputs_[1]; }
   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:
   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 
   2763   Token::Value op() const { return op_; }
   2764   LOperand* left() { return inputs_[0]; }
   2765   LOperand* right() { return inputs_[1]; }
   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:
   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 
   2785   LOperand* function() { return inputs_[0]; }
   2786   LOperand* code_object() { return inputs_[1]; }
   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:
   2798   LStoreContextSlot(LOperand* context, LOperand* value, LOperand* temp) {
   2799     inputs_[0] = context;
   2800     inputs_[1] = value;
   2801     temps_[0] = temp;
   2802   }
   2803 
   2804   LOperand* context() { return inputs_[0]; }
   2805   LOperand* value() { return inputs_[1]; }
   2806   LOperand* temp() { return temps_[0]; }
   2807 
   2808   DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot")
   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:
   2819   LStoreGlobalCell(LOperand* value, LOperand* temp1, LOperand* temp2) {
   2820     inputs_[0] = value;
   2821     temps_[0] = temp1;
   2822     temps_[1] = temp2;
   2823   }
   2824 
   2825   LOperand* value() { return inputs_[0]; }
   2826   LOperand* temp1() { return temps_[0]; }
   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:
   2836   LSubI(LOperand* left, LOperand* right)
   2837       : shift_(NO_SHIFT), shift_amount_(0)  {
   2838     inputs_[0] = left;
   2839     inputs_[1] = right;
   2840   }
   2841 
   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 
   2848   LOperand* left() { return inputs_[0]; }
   2849   LOperand* right() { return inputs_[1]; }
   2850 
   2851   Shift shift() const { return shift_; }
   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:
   2865   LSubS(LOperand* left, LOperand* right) {
   2866     inputs_[0] = left;
   2867     inputs_[1] = right;
   2868   }
   2869 
   2870   LOperand* left() { return inputs_[0]; }
   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:
   2887   explicit LToFastProperties(LOperand* value) {
   2888     inputs_[0] = value;
   2889   }
   2890 
   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:
   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 
   2910   LOperand* object() { return inputs_[0]; }
   2911   LOperand* context() { return inputs_[1]; }
   2912   LOperand* temp1() { return temps_[0]; }
   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 
   2921   Handle<Map> original_map() { return hydrogen()->original_map().handle(); }
   2922   Handle<Map> transitioned_map() {
   2923     return hydrogen()->transitioned_map().handle();
   2924   }
   2925   ElementsKind from_kind() const { return hydrogen()->from_kind(); }
   2926   ElementsKind to_kind() const { return hydrogen()->to_kind(); }
   2927 };
   2928 
   2929 
   2930 class LTrapAllocationMemento FINAL : public LTemplateInstruction<0, 1, 2> {
   2931  public:
   2932   LTrapAllocationMemento(LOperand* object, LOperand* temp1, LOperand* temp2) {
   2933     inputs_[0] = object;
   2934     temps_[0] = temp1;
   2935     temps_[1] = temp2;
   2936   }
   2937 
   2938   LOperand* object() { return inputs_[0]; }
   2939   LOperand* temp1() { return temps_[0]; }
   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:
   2949   explicit LTruncateDoubleToIntOrSmi(LOperand* value) {
   2950     inputs_[0] = value;
   2951   }
   2952 
   2953   LOperand* value() { return inputs_[0]; }
   2954 
   2955   DECLARE_CONCRETE_INSTRUCTION(TruncateDoubleToIntOrSmi,
   2956                                "truncate-double-to-int-or-smi")
   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:
   2965   LTypeof(LOperand* context, LOperand* value) {
   2966     inputs_[0] = context;
   2967     inputs_[1] = value;
   2968   }
   2969 
   2970   LOperand* context() { return inputs_[0]; }
   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:
   2979   LTypeofIsAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) {
   2980     inputs_[0] = value;
   2981     temps_[0] = temp1;
   2982     temps_[1] = temp2;
   2983   }
   2984 
   2985   LOperand* value() { return inputs_[0]; }
   2986   LOperand* temp1() { return temps_[0]; }
   2987   LOperand* temp2() { return temps_[1]; }
   2988 
   2989   DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch")
   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:
   3000   explicit LUint32ToDouble(LOperand* value) {
   3001     inputs_[0] = value;
   3002   }
   3003 
   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:
   3012   LCheckMapValue(LOperand* value, LOperand* map, LOperand* temp) {
   3013     inputs_[0] = value;
   3014     inputs_[1] = map;
   3015     temps_[0] = temp;
   3016   }
   3017 
   3018   LOperand* value() { return inputs_[0]; }
   3019   LOperand* map() { return inputs_[1]; }
   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:
   3028   LLoadFieldByIndex(LOperand* object, LOperand* index) {
   3029     inputs_[0] = object;
   3030     inputs_[1] = index;
   3031   }
   3032 
   3033   LOperand* object() { return inputs_[0]; }
   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:
   3042   explicit LStoreFrameContext(LOperand* context) {
   3043     inputs_[0] = context;
   3044   }
   3045 
   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:
   3054   LAllocateBlockContext(LOperand* context, LOperand* function) {
   3055     inputs_[0] = context;
   3056     inputs_[1] = function;
   3057   }
   3058 
   3059   LOperand* context() { return inputs_[0]; }
   3060   LOperand* function() { return inputs_[1]; }
   3061 
   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:
   3071   LWrapReceiver(LOperand* receiver, LOperand* function) {
   3072     inputs_[0] = receiver;
   3073     inputs_[1] = function;
   3074   }
   3075 
   3076   DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
   3077   DECLARE_HYDROGEN_ACCESSOR(WrapReceiver)
   3078 
   3079   LOperand* receiver() { return inputs_[0]; }
   3080   LOperand* function() { return inputs_[1]; }
   3081 };
   3082 
   3083 
   3084 class LChunkBuilder;
   3085 class LPlatformChunk FINAL : public LChunk {
   3086  public:
   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:
   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 
   3208   int JSShiftAmountFromHConstant(HValue* constant) {
   3209     return HConstant::cast(constant)->Integer32Value() & 0x1f;
   3210   }
   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