Home | History | Annotate | Download | only in mips
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_MIPS_LITHIUM_MIPS_H_
     29 #define V8_MIPS_LITHIUM_MIPS_H_
     30 
     31 #include "hydrogen.h"
     32 #include "lithium-allocator.h"
     33 #include "lithium.h"
     34 #include "safepoint-table.h"
     35 #include "utils.h"
     36 
     37 namespace v8 {
     38 namespace internal {
     39 
     40 // Forward declarations.
     41 class LCodeGen;
     42 
     43 #define LITHIUM_ALL_INSTRUCTION_LIST(V)         \
     44   V(ControlInstruction)                         \
     45   V(Call)                                       \
     46   LITHIUM_CONCRETE_INSTRUCTION_LIST(V)
     47 
     48 
     49 #define LITHIUM_CONCRETE_INSTRUCTION_LIST(V)    \
     50   V(AccessArgumentsAt)                          \
     51   V(AddI)                                       \
     52   V(AllocateObject)                             \
     53   V(ApplyArguments)                             \
     54   V(ArgumentsElements)                          \
     55   V(ArgumentsLength)                            \
     56   V(ArithmeticD)                                \
     57   V(ArithmeticT)                                \
     58   V(ArrayLiteral)                               \
     59   V(BitI)                                       \
     60   V(BitNotI)                                    \
     61   V(BoundsCheck)                                \
     62   V(Branch)                                     \
     63   V(CallConstantFunction)                       \
     64   V(CallFunction)                               \
     65   V(CallGlobal)                                 \
     66   V(CallKeyed)                                  \
     67   V(CallKnownGlobal)                            \
     68   V(CallNamed)                                  \
     69   V(CallNew)                                    \
     70   V(CallRuntime)                                \
     71   V(CallStub)                                   \
     72   V(CheckFunction)                              \
     73   V(CheckInstanceType)                          \
     74   V(CheckMap)                                   \
     75   V(CheckNonSmi)                                \
     76   V(CheckPrototypeMaps)                         \
     77   V(CheckSmi)                                   \
     78   V(ClampDToUint8)                              \
     79   V(ClampIToUint8)                              \
     80   V(ClampTToUint8)                              \
     81   V(ClassOfTestAndBranch)                       \
     82   V(CmpConstantEqAndBranch)                     \
     83   V(CmpIDAndBranch)                             \
     84   V(CmpObjectEqAndBranch)                       \
     85   V(CmpMapAndBranch)                            \
     86   V(CmpT)                                       \
     87   V(ConstantD)                                  \
     88   V(ConstantI)                                  \
     89   V(ConstantT)                                  \
     90   V(Context)                                    \
     91   V(DeclareGlobals)                             \
     92   V(DeleteProperty)                             \
     93   V(Deoptimize)                                 \
     94   V(DivI)                                       \
     95   V(DoubleToI)                                  \
     96   V(ElementsKind)                               \
     97   V(FastLiteral)                                \
     98   V(FixedArrayBaseLength)                       \
     99   V(FunctionLiteral)                            \
    100   V(GetCachedArrayIndex)                        \
    101   V(GlobalObject)                               \
    102   V(GlobalReceiver)                             \
    103   V(Goto)                                       \
    104   V(HasCachedArrayIndexAndBranch)               \
    105   V(HasInstanceTypeAndBranch)                   \
    106   V(In)                                         \
    107   V(InstanceOf)                                 \
    108   V(InstanceOfKnownGlobal)                      \
    109   V(InstructionGap)                             \
    110   V(Integer32ToDouble)                          \
    111   V(InvokeFunction)                             \
    112   V(IsConstructCallAndBranch)                   \
    113   V(IsNilAndBranch)                             \
    114   V(IsObjectAndBranch)                          \
    115   V(IsStringAndBranch)                          \
    116   V(IsSmiAndBranch)                             \
    117   V(IsUndetectableAndBranch)                    \
    118   V(StringCompareAndBranch)                     \
    119   V(JSArrayLength)                              \
    120   V(Label)                                      \
    121   V(LazyBailout)                                \
    122   V(LoadContextSlot)                            \
    123   V(LoadElements)                               \
    124   V(LoadExternalArrayPointer)                   \
    125   V(LoadFunctionPrototype)                      \
    126   V(LoadGlobalCell)                             \
    127   V(LoadGlobalGeneric)                          \
    128   V(LoadKeyedFastDoubleElement)                 \
    129   V(LoadKeyedFastElement)                       \
    130   V(LoadKeyedGeneric)                           \
    131   V(LoadKeyedSpecializedArrayElement)           \
    132   V(LoadNamedField)                             \
    133   V(LoadNamedFieldPolymorphic)                  \
    134   V(LoadNamedGeneric)                           \
    135   V(ModI)                                       \
    136   V(MulI)                                       \
    137   V(NumberTagD)                                 \
    138   V(NumberTagI)                                 \
    139   V(NumberUntagD)                               \
    140   V(ObjectLiteral)                              \
    141   V(OsrEntry)                                   \
    142   V(OuterContext)                               \
    143   V(Parameter)                                  \
    144   V(Power)                                      \
    145   V(PushArgument)                               \
    146   V(Random)                                     \
    147   V(RegExpLiteral)                              \
    148   V(Return)                                     \
    149   V(ShiftI)                                     \
    150   V(SmiTag)                                     \
    151   V(SmiUntag)                                   \
    152   V(StackCheck)                                 \
    153   V(StoreContextSlot)                           \
    154   V(StoreGlobalCell)                            \
    155   V(StoreGlobalGeneric)                         \
    156   V(StoreKeyedFastDoubleElement)                \
    157   V(StoreKeyedFastElement)                      \
    158   V(StoreKeyedGeneric)                          \
    159   V(StoreKeyedSpecializedArrayElement)          \
    160   V(StoreNamedField)                            \
    161   V(StoreNamedGeneric)                          \
    162   V(StringAdd)                                  \
    163   V(StringCharCodeAt)                           \
    164   V(StringCharFromCode)                         \
    165   V(StringLength)                               \
    166   V(SubI)                                       \
    167   V(TaggedToI)                                  \
    168   V(ThisFunction)                               \
    169   V(Throw)                                      \
    170   V(ToFastProperties)                           \
    171   V(TransitionElementsKind)                     \
    172   V(Typeof)                                     \
    173   V(TypeofIsAndBranch)                          \
    174   V(UnaryMathOperation)                         \
    175   V(UnknownOSRValue)                            \
    176   V(ValueOf)                                    \
    177   V(ForInPrepareMap)                            \
    178   V(ForInCacheArray)                            \
    179   V(CheckMapValue)                              \
    180   V(LoadFieldByIndex)                           \
    181   V(DateField)                                  \
    182   V(WrapReceiver)
    183 
    184 #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic)              \
    185   virtual Opcode opcode() const { return LInstruction::k##type; } \
    186   virtual void CompileToNative(LCodeGen* generator);              \
    187   virtual const char* Mnemonic() const { return mnemonic; }       \
    188   static L##type* cast(LInstruction* instr) {                     \
    189     ASSERT(instr->Is##type());                                    \
    190     return reinterpret_cast<L##type*>(instr);                     \
    191   }
    192 
    193 
    194 #define DECLARE_HYDROGEN_ACCESSOR(type)     \
    195   H##type* hydrogen() const {               \
    196     return H##type::cast(hydrogen_value()); \
    197   }
    198 
    199 
    200 class LInstruction: public ZoneObject {
    201  public:
    202   LInstruction()
    203       :  environment_(NULL),
    204          hydrogen_value_(NULL),
    205          is_call_(false),
    206          is_save_doubles_(false) { }
    207   virtual ~LInstruction() { }
    208 
    209   virtual void CompileToNative(LCodeGen* generator) = 0;
    210   virtual const char* Mnemonic() const = 0;
    211   virtual void PrintTo(StringStream* stream);
    212   virtual void PrintDataTo(StringStream* stream) = 0;
    213   virtual void PrintOutputOperandTo(StringStream* stream) = 0;
    214 
    215   enum Opcode {
    216     // Declare a unique enum value for each instruction.
    217 #define DECLARE_OPCODE(type) k##type,
    218     LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
    219     kNumberOfInstructions
    220 #undef DECLARE_OPCODE
    221   };
    222 
    223   virtual Opcode opcode() const = 0;
    224 
    225   // Declare non-virtual type testers for all leaf IR classes.
    226 #define DECLARE_PREDICATE(type) \
    227   bool Is##type() const { return opcode() == k##type; }
    228   LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
    229 #undef DECLARE_PREDICATE
    230 
    231   // Declare virtual predicates for instructions that don't have
    232   // an opcode.
    233   virtual bool IsGap() const { return false; }
    234 
    235   virtual bool IsControl() const { return false; }
    236 
    237   void set_environment(LEnvironment* env) { environment_ = env; }
    238   LEnvironment* environment() const { return environment_; }
    239   bool HasEnvironment() const { return environment_ != NULL; }
    240 
    241   void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); }
    242   LPointerMap* pointer_map() const { return pointer_map_.get(); }
    243   bool HasPointerMap() const { return pointer_map_.is_set(); }
    244 
    245   void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
    246   HValue* hydrogen_value() const { return hydrogen_value_; }
    247 
    248   void set_deoptimization_environment(LEnvironment* env) {
    249     deoptimization_environment_.set(env);
    250   }
    251   LEnvironment* deoptimization_environment() const {
    252     return deoptimization_environment_.get();
    253   }
    254   bool HasDeoptimizationEnvironment() const {
    255     return deoptimization_environment_.is_set();
    256   }
    257 
    258   void MarkAsCall() { is_call_ = true; }
    259   void MarkAsSaveDoubles() { is_save_doubles_ = true; }
    260 
    261   // Interface to the register allocator and iterators.
    262   bool IsMarkedAsCall() const { return is_call_; }
    263   bool IsMarkedAsSaveDoubles() const { return is_save_doubles_; }
    264 
    265   virtual bool HasResult() const = 0;
    266   virtual LOperand* result() = 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 #ifdef DEBUG
    277   void VerifyCall();
    278 #endif
    279 
    280  private:
    281   LEnvironment* environment_;
    282   SetOncePointer<LPointerMap> pointer_map_;
    283   HValue* hydrogen_value_;
    284   SetOncePointer<LEnvironment> deoptimization_environment_;
    285   bool is_call_;
    286   bool is_save_doubles_;
    287 };
    288 
    289 
    290 // R = number of result operands (0 or 1).
    291 // I = number of input operands.
    292 // T = number of temporary operands.
    293 template<int R, int I, int T>
    294 class LTemplateInstruction: public LInstruction {
    295  public:
    296   // Allow 0 or 1 output operands.
    297   STATIC_ASSERT(R == 0 || R == 1);
    298   virtual bool HasResult() const { return R != 0; }
    299   void set_result(LOperand* operand) { results_[0] = operand; }
    300   LOperand* result() { return results_[0]; }
    301 
    302   int InputCount() { return I; }
    303   LOperand* InputAt(int i) { return inputs_[i]; }
    304 
    305   int TempCount() { return T; }
    306   LOperand* TempAt(int i) { return temps_[i]; }
    307 
    308   virtual void PrintDataTo(StringStream* stream);
    309   virtual void PrintOutputOperandTo(StringStream* stream);
    310 
    311  protected:
    312   EmbeddedContainer<LOperand*, R> results_;
    313   EmbeddedContainer<LOperand*, I> inputs_;
    314   EmbeddedContainer<LOperand*, T> temps_;
    315 };
    316 
    317 
    318 class LGap: public LTemplateInstruction<0, 0, 0> {
    319  public:
    320   explicit LGap(HBasicBlock* block)
    321       : block_(block) {
    322     parallel_moves_[BEFORE] = NULL;
    323     parallel_moves_[START] = NULL;
    324     parallel_moves_[END] = NULL;
    325     parallel_moves_[AFTER] = NULL;
    326   }
    327 
    328   // Can't use the DECLARE-macro here because of sub-classes.
    329   virtual bool IsGap() const { return true; }
    330   virtual void PrintDataTo(StringStream* stream);
    331   static LGap* cast(LInstruction* instr) {
    332     ASSERT(instr->IsGap());
    333     return reinterpret_cast<LGap*>(instr);
    334   }
    335 
    336   bool IsRedundant() const;
    337 
    338   HBasicBlock* block() const { return block_; }
    339 
    340   enum InnerPosition {
    341     BEFORE,
    342     START,
    343     END,
    344     AFTER,
    345     FIRST_INNER_POSITION = BEFORE,
    346     LAST_INNER_POSITION = AFTER
    347   };
    348 
    349   LParallelMove* GetOrCreateParallelMove(InnerPosition pos)  {
    350     if (parallel_moves_[pos] == NULL) parallel_moves_[pos] = new LParallelMove;
    351     return parallel_moves_[pos];
    352   }
    353 
    354   LParallelMove* GetParallelMove(InnerPosition pos)  {
    355     return parallel_moves_[pos];
    356   }
    357 
    358  private:
    359   LParallelMove* parallel_moves_[LAST_INNER_POSITION + 1];
    360   HBasicBlock* block_;
    361 };
    362 
    363 
    364 class LInstructionGap: public LGap {
    365  public:
    366   explicit LInstructionGap(HBasicBlock* block) : LGap(block) { }
    367 
    368   DECLARE_CONCRETE_INSTRUCTION(InstructionGap, "gap")
    369 };
    370 
    371 
    372 class LGoto: public LTemplateInstruction<0, 0, 0> {
    373  public:
    374   explicit LGoto(int block_id) : block_id_(block_id) { }
    375 
    376   DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
    377   virtual void PrintDataTo(StringStream* stream);
    378   virtual bool IsControl() const { return true; }
    379 
    380   int block_id() const { return block_id_; }
    381 
    382  private:
    383   int block_id_;
    384 };
    385 
    386 
    387 class LLazyBailout: public LTemplateInstruction<0, 0, 0> {
    388  public:
    389   LLazyBailout() : gap_instructions_size_(0) { }
    390 
    391   DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout")
    392 
    393   void set_gap_instructions_size(int gap_instructions_size) {
    394     gap_instructions_size_ = gap_instructions_size;
    395   }
    396   int gap_instructions_size() { return gap_instructions_size_; }
    397 
    398  private:
    399   int gap_instructions_size_;
    400 };
    401 
    402 
    403 class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
    404  public:
    405   DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
    406 };
    407 
    408 
    409 class LLabel: public LGap {
    410  public:
    411   explicit LLabel(HBasicBlock* block)
    412       : LGap(block), replacement_(NULL) { }
    413 
    414   DECLARE_CONCRETE_INSTRUCTION(Label, "label")
    415 
    416   virtual void PrintDataTo(StringStream* stream);
    417 
    418   int block_id() const { return block()->block_id(); }
    419   bool is_loop_header() const { return block()->IsLoopHeader(); }
    420   Label* label() { return &label_; }
    421   LLabel* replacement() const { return replacement_; }
    422   void set_replacement(LLabel* label) { replacement_ = label; }
    423   bool HasReplacement() const { return replacement_ != NULL; }
    424 
    425  private:
    426   Label label_;
    427   LLabel* replacement_;
    428 };
    429 
    430 
    431 class LParameter: public LTemplateInstruction<1, 0, 0> {
    432  public:
    433   DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
    434 };
    435 
    436 
    437 class LCallStub: public LTemplateInstruction<1, 0, 0> {
    438  public:
    439   DECLARE_CONCRETE_INSTRUCTION(CallStub, "call-stub")
    440   DECLARE_HYDROGEN_ACCESSOR(CallStub)
    441 
    442   TranscendentalCache::Type transcendental_type() {
    443     return hydrogen()->transcendental_type();
    444   }
    445 };
    446 
    447 
    448 class LUnknownOSRValue: public LTemplateInstruction<1, 0, 0> {
    449  public:
    450   DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value")
    451 };
    452 
    453 
    454 template<int I, int T>
    455 class LControlInstruction: public LTemplateInstruction<0, I, T> {
    456  public:
    457   virtual bool IsControl() const { return true; }
    458 
    459   int SuccessorCount() { return hydrogen()->SuccessorCount(); }
    460   HBasicBlock* SuccessorAt(int i) { return hydrogen()->SuccessorAt(i); }
    461   int true_block_id() { return hydrogen()->SuccessorAt(0)->block_id(); }
    462   int false_block_id() { return hydrogen()->SuccessorAt(1)->block_id(); }
    463 
    464  private:
    465   HControlInstruction* hydrogen() {
    466     return HControlInstruction::cast(this->hydrogen_value());
    467   }
    468 };
    469 
    470 
    471 class LWrapReceiver: public LTemplateInstruction<1, 2, 0> {
    472  public:
    473   LWrapReceiver(LOperand* receiver, LOperand* function) {
    474     inputs_[0] = receiver;
    475     inputs_[1] = function;
    476   }
    477 
    478   DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
    479 
    480   LOperand* receiver() { return inputs_[0]; }
    481   LOperand* function() { return inputs_[1]; }
    482 };
    483 
    484 
    485 class LApplyArguments: public LTemplateInstruction<1, 4, 0> {
    486  public:
    487   LApplyArguments(LOperand* function,
    488                   LOperand* receiver,
    489                   LOperand* length,
    490                   LOperand* elements) {
    491     inputs_[0] = function;
    492     inputs_[1] = receiver;
    493     inputs_[2] = length;
    494     inputs_[3] = elements;
    495   }
    496 
    497   DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply-arguments")
    498 
    499   LOperand* function() { return inputs_[0]; }
    500   LOperand* receiver() { return inputs_[1]; }
    501   LOperand* length() { return inputs_[2]; }
    502   LOperand* elements() { return inputs_[3]; }
    503 };
    504 
    505 
    506 class LAccessArgumentsAt: public LTemplateInstruction<1, 3, 0> {
    507  public:
    508   LAccessArgumentsAt(LOperand* arguments, LOperand* length, LOperand* index) {
    509     inputs_[0] = arguments;
    510     inputs_[1] = length;
    511     inputs_[2] = index;
    512   }
    513 
    514   DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at")
    515 
    516   LOperand* arguments() { return inputs_[0]; }
    517   LOperand* length() { return inputs_[1]; }
    518   LOperand* index() { return inputs_[2]; }
    519 
    520   virtual void PrintDataTo(StringStream* stream);
    521 };
    522 
    523 
    524 class LArgumentsLength: public LTemplateInstruction<1, 1, 0> {
    525  public:
    526   explicit LArgumentsLength(LOperand* elements) {
    527     inputs_[0] = elements;
    528   }
    529 
    530   DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments-length")
    531 };
    532 
    533 
    534 class LArgumentsElements: public LTemplateInstruction<1, 0, 0> {
    535  public:
    536   LArgumentsElements() { }
    537 
    538   DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments-elements")
    539 };
    540 
    541 
    542 class LModI: public LTemplateInstruction<1, 2, 3> {
    543  public:
    544   // Used when the right hand is a constant power of 2.
    545   LModI(LOperand* left,
    546         LOperand* right) {
    547     inputs_[0] = left;
    548     inputs_[1] = right;
    549     temps_[0] = NULL;
    550     temps_[1] = NULL;
    551     temps_[2] = NULL;
    552   }
    553 
    554   // Used for the standard case.
    555   LModI(LOperand* left,
    556         LOperand* right,
    557         LOperand* temp1,
    558         LOperand* temp2,
    559         LOperand* temp3) {
    560     inputs_[0] = left;
    561     inputs_[1] = right;
    562     temps_[0] = temp1;
    563     temps_[1] = temp2;
    564     temps_[2] = temp3;
    565   }
    566 
    567   DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i")
    568   DECLARE_HYDROGEN_ACCESSOR(Mod)
    569 };
    570 
    571 
    572 class LDivI: public LTemplateInstruction<1, 2, 0> {
    573  public:
    574   LDivI(LOperand* left, LOperand* right) {
    575     inputs_[0] = left;
    576     inputs_[1] = right;
    577   }
    578 
    579   DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
    580   DECLARE_HYDROGEN_ACCESSOR(Div)
    581 };
    582 
    583 
    584 class LMulI: public LTemplateInstruction<1, 2, 1> {
    585  public:
    586   LMulI(LOperand* left, LOperand* right, LOperand* temp) {
    587     inputs_[0] = left;
    588     inputs_[1] = right;
    589     temps_[0] = temp;
    590   }
    591 
    592   DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i")
    593   DECLARE_HYDROGEN_ACCESSOR(Mul)
    594 };
    595 
    596 
    597 class LCmpIDAndBranch: public LControlInstruction<2, 0> {
    598  public:
    599   LCmpIDAndBranch(LOperand* left, LOperand* right) {
    600     inputs_[0] = left;
    601     inputs_[1] = right;
    602   }
    603 
    604   DECLARE_CONCRETE_INSTRUCTION(CmpIDAndBranch, "cmp-id-and-branch")
    605   DECLARE_HYDROGEN_ACCESSOR(CompareIDAndBranch)
    606 
    607   Token::Value op() const { return hydrogen()->token(); }
    608   bool is_double() const {
    609     return hydrogen()->GetInputRepresentation().IsDouble();
    610   }
    611 
    612   virtual void PrintDataTo(StringStream* stream);
    613 };
    614 
    615 
    616 class LUnaryMathOperation: public LTemplateInstruction<1, 1, 1> {
    617  public:
    618   LUnaryMathOperation(LOperand* value, LOperand* temp) {
    619     inputs_[0] = value;
    620     temps_[0] = temp;
    621   }
    622 
    623   DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary-math-operation")
    624   DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
    625 
    626   virtual void PrintDataTo(StringStream* stream);
    627   BuiltinFunctionId op() const { return hydrogen()->op(); }
    628 };
    629 
    630 
    631 class LCmpObjectEqAndBranch: public LControlInstruction<2, 0> {
    632  public:
    633   LCmpObjectEqAndBranch(LOperand* left, LOperand* right) {
    634     inputs_[0] = left;
    635     inputs_[1] = right;
    636   }
    637 
    638   DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch,
    639                                "cmp-object-eq-and-branch")
    640   DECLARE_HYDROGEN_ACCESSOR(CompareObjectEqAndBranch)
    641 };
    642 
    643 
    644 class LCmpConstantEqAndBranch: public LControlInstruction<1, 0> {
    645  public:
    646   explicit LCmpConstantEqAndBranch(LOperand* left) {
    647     inputs_[0] = left;
    648   }
    649 
    650   DECLARE_CONCRETE_INSTRUCTION(CmpConstantEqAndBranch,
    651                                "cmp-constant-eq-and-branch")
    652   DECLARE_HYDROGEN_ACCESSOR(CompareConstantEqAndBranch)
    653 };
    654 
    655 
    656 class LIsNilAndBranch: public LControlInstruction<1, 0> {
    657  public:
    658   explicit LIsNilAndBranch(LOperand* value) {
    659     inputs_[0] = value;
    660   }
    661 
    662   DECLARE_CONCRETE_INSTRUCTION(IsNilAndBranch, "is-nil-and-branch")
    663   DECLARE_HYDROGEN_ACCESSOR(IsNilAndBranch)
    664 
    665   EqualityKind kind() const { return hydrogen()->kind(); }
    666   NilValue nil() const { return hydrogen()->nil(); }
    667 
    668   virtual void PrintDataTo(StringStream* stream);
    669 };
    670 
    671 
    672 class LIsObjectAndBranch: public LControlInstruction<1, 1> {
    673  public:
    674   LIsObjectAndBranch(LOperand* value, LOperand* temp) {
    675     inputs_[0] = value;
    676     temps_[0] = temp;
    677   }
    678 
    679   DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
    680   DECLARE_HYDROGEN_ACCESSOR(IsObjectAndBranch)
    681 
    682   virtual void PrintDataTo(StringStream* stream);
    683 };
    684 
    685 
    686 class LIsStringAndBranch: public LControlInstruction<1, 1> {
    687  public:
    688   LIsStringAndBranch(LOperand* value, LOperand* temp) {
    689     inputs_[0] = value;
    690     temps_[0] = temp;
    691   }
    692 
    693   DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch")
    694   DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch)
    695 
    696   virtual void PrintDataTo(StringStream* stream);
    697 };
    698 
    699 
    700 class LIsSmiAndBranch: public LControlInstruction<1, 0> {
    701  public:
    702   explicit LIsSmiAndBranch(LOperand* value) {
    703     inputs_[0] = value;
    704   }
    705 
    706   DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch")
    707   DECLARE_HYDROGEN_ACCESSOR(IsSmiAndBranch)
    708 
    709   virtual void PrintDataTo(StringStream* stream);
    710 };
    711 
    712 
    713 class LIsUndetectableAndBranch: public LControlInstruction<1, 1> {
    714  public:
    715   explicit LIsUndetectableAndBranch(LOperand* value, LOperand* temp) {
    716     inputs_[0] = value;
    717     temps_[0] = temp;
    718   }
    719 
    720   DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch,
    721                                "is-undetectable-and-branch")
    722   DECLARE_HYDROGEN_ACCESSOR(IsUndetectableAndBranch)
    723 
    724   virtual void PrintDataTo(StringStream* stream);
    725 };
    726 
    727 
    728 class LStringCompareAndBranch: public LControlInstruction<2, 0> {
    729  public:
    730   LStringCompareAndBranch(LOperand* left, LOperand* right) {
    731     inputs_[0] = left;
    732     inputs_[1] = right;
    733   }
    734 
    735   DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch,
    736                                "string-compare-and-branch")
    737   DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch)
    738 
    739   Token::Value op() const { return hydrogen()->token(); }
    740 
    741   virtual void PrintDataTo(StringStream* stream);
    742 };
    743 
    744 
    745 class LHasInstanceTypeAndBranch: public LControlInstruction<1, 0> {
    746  public:
    747   explicit LHasInstanceTypeAndBranch(LOperand* value) {
    748     inputs_[0] = value;
    749   }
    750 
    751   DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch,
    752                                "has-instance-type-and-branch")
    753   DECLARE_HYDROGEN_ACCESSOR(HasInstanceTypeAndBranch)
    754 
    755   virtual void PrintDataTo(StringStream* stream);
    756 };
    757 
    758 
    759 class LGetCachedArrayIndex: public LTemplateInstruction<1, 1, 0> {
    760  public:
    761   explicit LGetCachedArrayIndex(LOperand* value) {
    762     inputs_[0] = value;
    763   }
    764 
    765   DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get-cached-array-index")
    766   DECLARE_HYDROGEN_ACCESSOR(GetCachedArrayIndex)
    767 };
    768 
    769 
    770 class LHasCachedArrayIndexAndBranch: public LControlInstruction<1, 0> {
    771  public:
    772   explicit LHasCachedArrayIndexAndBranch(LOperand* value) {
    773     inputs_[0] = value;
    774   }
    775 
    776   DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch,
    777                                "has-cached-array-index-and-branch")
    778   DECLARE_HYDROGEN_ACCESSOR(HasCachedArrayIndexAndBranch)
    779 
    780   virtual void PrintDataTo(StringStream* stream);
    781 };
    782 
    783 
    784 class LClassOfTestAndBranch: public LControlInstruction<1, 1> {
    785  public:
    786   LClassOfTestAndBranch(LOperand* value, LOperand* temp) {
    787     inputs_[0] = value;
    788     temps_[0] = temp;
    789   }
    790 
    791   DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch,
    792                                "class-of-test-and-branch")
    793   DECLARE_HYDROGEN_ACCESSOR(ClassOfTestAndBranch)
    794 
    795   virtual void PrintDataTo(StringStream* stream);
    796 };
    797 
    798 
    799 class LCmpT: public LTemplateInstruction<1, 2, 0> {
    800  public:
    801   LCmpT(LOperand* left, LOperand* right) {
    802     inputs_[0] = left;
    803     inputs_[1] = right;
    804   }
    805 
    806   DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t")
    807   DECLARE_HYDROGEN_ACCESSOR(CompareGeneric)
    808 
    809   Token::Value op() const { return hydrogen()->token(); }
    810 };
    811 
    812 
    813 class LInstanceOf: public LTemplateInstruction<1, 2, 0> {
    814  public:
    815   LInstanceOf(LOperand* left, LOperand* right) {
    816     inputs_[0] = left;
    817     inputs_[1] = right;
    818   }
    819 
    820   DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
    821 };
    822 
    823 
    824 class LInstanceOfKnownGlobal: public LTemplateInstruction<1, 1, 1> {
    825  public:
    826   LInstanceOfKnownGlobal(LOperand* value, LOperand* temp) {
    827     inputs_[0] = value;
    828     temps_[0] = temp;
    829   }
    830 
    831   DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
    832                                "instance-of-known-global")
    833   DECLARE_HYDROGEN_ACCESSOR(InstanceOfKnownGlobal)
    834 
    835   Handle<JSFunction> function() const { return hydrogen()->function(); }
    836 };
    837 
    838 
    839 class LBoundsCheck: public LTemplateInstruction<0, 2, 0> {
    840  public:
    841   LBoundsCheck(LOperand* index, LOperand* length) {
    842     inputs_[0] = index;
    843     inputs_[1] = length;
    844   }
    845 
    846   LOperand* index() { return inputs_[0]; }
    847   LOperand* length() { return inputs_[1]; }
    848 
    849   DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
    850 };
    851 
    852 
    853 class LBitI: public LTemplateInstruction<1, 2, 0> {
    854  public:
    855   LBitI(LOperand* left, LOperand* right) {
    856     inputs_[0] = left;
    857     inputs_[1] = right;
    858   }
    859 
    860   Token::Value op() const { return hydrogen()->op(); }
    861 
    862   DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i")
    863   DECLARE_HYDROGEN_ACCESSOR(Bitwise)
    864 };
    865 
    866 
    867 class LShiftI: public LTemplateInstruction<1, 2, 0> {
    868  public:
    869   LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
    870       : op_(op), can_deopt_(can_deopt) {
    871     inputs_[0] = left;
    872     inputs_[1] = right;
    873   }
    874 
    875   Token::Value op() const { return op_; }
    876 
    877   bool can_deopt() const { return can_deopt_; }
    878 
    879   DECLARE_CONCRETE_INSTRUCTION(ShiftI, "shift-i")
    880 
    881  private:
    882   Token::Value op_;
    883   bool can_deopt_;
    884 };
    885 
    886 
    887 class LSubI: public LTemplateInstruction<1, 2, 0> {
    888  public:
    889   LSubI(LOperand* left, LOperand* right) {
    890     inputs_[0] = left;
    891     inputs_[1] = right;
    892   }
    893 
    894   DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i")
    895   DECLARE_HYDROGEN_ACCESSOR(Sub)
    896 };
    897 
    898 
    899 class LConstantI: public LTemplateInstruction<1, 0, 0> {
    900  public:
    901   DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i")
    902   DECLARE_HYDROGEN_ACCESSOR(Constant)
    903 
    904   int32_t value() const { return hydrogen()->Integer32Value(); }
    905 };
    906 
    907 
    908 class LConstantD: public LTemplateInstruction<1, 0, 0> {
    909  public:
    910   DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
    911   DECLARE_HYDROGEN_ACCESSOR(Constant)
    912 
    913   double value() const { return hydrogen()->DoubleValue(); }
    914 };
    915 
    916 
    917 class LConstantT: public LTemplateInstruction<1, 0, 0> {
    918  public:
    919   DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
    920   DECLARE_HYDROGEN_ACCESSOR(Constant)
    921 
    922   Handle<Object> value() const { return hydrogen()->handle(); }
    923 };
    924 
    925 
    926 class LBranch: public LControlInstruction<1, 0> {
    927  public:
    928   explicit LBranch(LOperand* value) {
    929     inputs_[0] = value;
    930   }
    931 
    932   DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
    933   DECLARE_HYDROGEN_ACCESSOR(Branch)
    934 
    935   virtual void PrintDataTo(StringStream* stream);
    936 };
    937 
    938 
    939 class LCmpMapAndBranch: public LTemplateInstruction<0, 1, 1> {
    940  public:
    941   LCmpMapAndBranch(LOperand* value, LOperand* temp) {
    942     inputs_[0] = value;
    943     temps_[0] = temp;
    944   }
    945 
    946   DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
    947   DECLARE_HYDROGEN_ACCESSOR(CompareMap)
    948 
    949   virtual bool IsControl() const { return true; }
    950 
    951   Handle<Map> map() const { return hydrogen()->map(); }
    952   int true_block_id() const {
    953     return hydrogen()->FirstSuccessor()->block_id();
    954   }
    955   int false_block_id() const {
    956     return hydrogen()->SecondSuccessor()->block_id();
    957   }
    958 };
    959 
    960 
    961 class LJSArrayLength: public LTemplateInstruction<1, 1, 0> {
    962  public:
    963   explicit LJSArrayLength(LOperand* value) {
    964     inputs_[0] = value;
    965   }
    966 
    967   DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js-array-length")
    968   DECLARE_HYDROGEN_ACCESSOR(JSArrayLength)
    969 };
    970 
    971 
    972 class LFixedArrayBaseLength: public LTemplateInstruction<1, 1, 0> {
    973  public:
    974   explicit LFixedArrayBaseLength(LOperand* value) {
    975     inputs_[0] = value;
    976   }
    977 
    978   DECLARE_CONCRETE_INSTRUCTION(FixedArrayBaseLength,
    979                                "fixed-array-base-length")
    980   DECLARE_HYDROGEN_ACCESSOR(FixedArrayBaseLength)
    981 };
    982 
    983 
    984 class LElementsKind: public LTemplateInstruction<1, 1, 0> {
    985  public:
    986   explicit LElementsKind(LOperand* value) {
    987     inputs_[0] = value;
    988   }
    989 
    990   DECLARE_CONCRETE_INSTRUCTION(ElementsKind, "elements-kind")
    991   DECLARE_HYDROGEN_ACCESSOR(ElementsKind)
    992 };
    993 
    994 
    995 class LValueOf: public LTemplateInstruction<1, 1, 1> {
    996  public:
    997   LValueOf(LOperand* value, LOperand* temp) {
    998     inputs_[0] = value;
    999     temps_[0] = temp;
   1000   }
   1001 
   1002   DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value-of")
   1003   DECLARE_HYDROGEN_ACCESSOR(ValueOf)
   1004 };
   1005 
   1006 
   1007 class LDateField: public LTemplateInstruction<1, 1, 1> {
   1008  public:
   1009   LDateField(LOperand* date, LOperand* temp, Smi* index) : index_(index) {
   1010     inputs_[0] = date;
   1011     temps_[0] = temp;
   1012   }
   1013 
   1014   DECLARE_CONCRETE_INSTRUCTION(ValueOf, "date-field")
   1015   DECLARE_HYDROGEN_ACCESSOR(ValueOf)
   1016   Smi* index() const { return index_; }
   1017 
   1018  private:
   1019   Smi* index_;
   1020 };
   1021 
   1022 
   1023 class LThrow: public LTemplateInstruction<0, 1, 0> {
   1024  public:
   1025   explicit LThrow(LOperand* value) {
   1026     inputs_[0] = value;
   1027   }
   1028 
   1029   DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
   1030 };
   1031 
   1032 
   1033 class LBitNotI: public LTemplateInstruction<1, 1, 0> {
   1034  public:
   1035   explicit LBitNotI(LOperand* value) {
   1036     inputs_[0] = value;
   1037   }
   1038 
   1039   DECLARE_CONCRETE_INSTRUCTION(BitNotI, "bit-not-i")
   1040 };
   1041 
   1042 
   1043 class LAddI: public LTemplateInstruction<1, 2, 0> {
   1044  public:
   1045   LAddI(LOperand* left, LOperand* right) {
   1046     inputs_[0] = left;
   1047     inputs_[1] = right;
   1048   }
   1049 
   1050   DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i")
   1051   DECLARE_HYDROGEN_ACCESSOR(Add)
   1052 };
   1053 
   1054 
   1055 class LPower: public LTemplateInstruction<1, 2, 0> {
   1056  public:
   1057   LPower(LOperand* left, LOperand* right) {
   1058     inputs_[0] = left;
   1059     inputs_[1] = right;
   1060   }
   1061 
   1062   DECLARE_CONCRETE_INSTRUCTION(Power, "power")
   1063   DECLARE_HYDROGEN_ACCESSOR(Power)
   1064 };
   1065 
   1066 
   1067 class LRandom: public LTemplateInstruction<1, 1, 0> {
   1068  public:
   1069   explicit LRandom(LOperand* global_object) {
   1070     inputs_[0] = global_object;
   1071   }
   1072 
   1073   DECLARE_CONCRETE_INSTRUCTION(Random, "random")
   1074   DECLARE_HYDROGEN_ACCESSOR(Random)
   1075 };
   1076 
   1077 
   1078 class LArithmeticD: public LTemplateInstruction<1, 2, 0> {
   1079  public:
   1080   LArithmeticD(Token::Value op, LOperand* left, LOperand* right)
   1081       : op_(op) {
   1082     inputs_[0] = left;
   1083     inputs_[1] = right;
   1084   }
   1085 
   1086   Token::Value op() const { return op_; }
   1087 
   1088   virtual Opcode opcode() const { return LInstruction::kArithmeticD; }
   1089   virtual void CompileToNative(LCodeGen* generator);
   1090   virtual const char* Mnemonic() const;
   1091 
   1092  private:
   1093   Token::Value op_;
   1094 };
   1095 
   1096 
   1097 class LArithmeticT: public LTemplateInstruction<1, 2, 0> {
   1098  public:
   1099   LArithmeticT(Token::Value op, LOperand* left, LOperand* right)
   1100       : op_(op) {
   1101     inputs_[0] = left;
   1102     inputs_[1] = right;
   1103   }
   1104 
   1105   virtual Opcode opcode() const { return LInstruction::kArithmeticT; }
   1106   virtual void CompileToNative(LCodeGen* generator);
   1107   virtual const char* Mnemonic() const;
   1108 
   1109   Token::Value op() const { return op_; }
   1110 
   1111  private:
   1112   Token::Value op_;
   1113 };
   1114 
   1115 
   1116 class LReturn: public LTemplateInstruction<0, 1, 0> {
   1117  public:
   1118   explicit LReturn(LOperand* value) {
   1119     inputs_[0] = value;
   1120   }
   1121 
   1122   DECLARE_CONCRETE_INSTRUCTION(Return, "return")
   1123 };
   1124 
   1125 
   1126 class LLoadNamedField: public LTemplateInstruction<1, 1, 0> {
   1127  public:
   1128   explicit LLoadNamedField(LOperand* object) {
   1129     inputs_[0] = object;
   1130   }
   1131 
   1132   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field")
   1133   DECLARE_HYDROGEN_ACCESSOR(LoadNamedField)
   1134 };
   1135 
   1136 
   1137 class LLoadNamedFieldPolymorphic: public LTemplateInstruction<1, 1, 0> {
   1138  public:
   1139   explicit LLoadNamedFieldPolymorphic(LOperand* object) {
   1140     inputs_[0] = object;
   1141   }
   1142 
   1143   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field-polymorphic")
   1144   DECLARE_HYDROGEN_ACCESSOR(LoadNamedFieldPolymorphic)
   1145 
   1146   LOperand* object() { return inputs_[0]; }
   1147 };
   1148 
   1149 
   1150 class LLoadNamedGeneric: public LTemplateInstruction<1, 1, 0> {
   1151  public:
   1152   explicit LLoadNamedGeneric(LOperand* object) {
   1153     inputs_[0] = object;
   1154   }
   1155 
   1156   DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic")
   1157   DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric)
   1158 
   1159   LOperand* object() { return inputs_[0]; }
   1160   Handle<Object> name() const { return hydrogen()->name(); }
   1161 };
   1162 
   1163 
   1164 class LLoadFunctionPrototype: public LTemplateInstruction<1, 1, 0> {
   1165  public:
   1166   explicit LLoadFunctionPrototype(LOperand* function) {
   1167     inputs_[0] = function;
   1168   }
   1169 
   1170   DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
   1171   DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
   1172 
   1173   LOperand* function() { return inputs_[0]; }
   1174 };
   1175 
   1176 
   1177 class LLoadElements: public LTemplateInstruction<1, 1, 0> {
   1178  public:
   1179   explicit LLoadElements(LOperand* object) {
   1180     inputs_[0] = object;
   1181   }
   1182 
   1183   DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements")
   1184 };
   1185 
   1186 
   1187 class LLoadExternalArrayPointer: public LTemplateInstruction<1, 1, 0> {
   1188  public:
   1189   explicit LLoadExternalArrayPointer(LOperand* object) {
   1190     inputs_[0] = object;
   1191   }
   1192 
   1193   DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer,
   1194                                "load-external-array-pointer")
   1195 };
   1196 
   1197 
   1198 class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> {
   1199  public:
   1200   LLoadKeyedFastElement(LOperand* elements, LOperand* key) {
   1201     inputs_[0] = elements;
   1202     inputs_[1] = key;
   1203   }
   1204 
   1205   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement, "load-keyed-fast-element")
   1206   DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastElement)
   1207 
   1208   LOperand* elements() { return inputs_[0]; }
   1209   LOperand* key() { return inputs_[1]; }
   1210 };
   1211 
   1212 
   1213 class LLoadKeyedFastDoubleElement: public LTemplateInstruction<1, 2, 0> {
   1214  public:
   1215   LLoadKeyedFastDoubleElement(LOperand* elements, LOperand* key) {
   1216     inputs_[0] = elements;
   1217     inputs_[1] = key;
   1218   }
   1219 
   1220   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement,
   1221                                "load-keyed-fast-double-element")
   1222   DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastDoubleElement)
   1223 
   1224   LOperand* elements() { return inputs_[0]; }
   1225   LOperand* key() { return inputs_[1]; }
   1226 };
   1227 
   1228 
   1229 class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
   1230  public:
   1231   LLoadKeyedSpecializedArrayElement(LOperand* external_pointer,
   1232                                     LOperand* key) {
   1233     inputs_[0] = external_pointer;
   1234     inputs_[1] = key;
   1235   }
   1236 
   1237   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement,
   1238                                "load-keyed-specialized-array-element")
   1239   DECLARE_HYDROGEN_ACCESSOR(LoadKeyedSpecializedArrayElement)
   1240 
   1241   LOperand* external_pointer() { return inputs_[0]; }
   1242   LOperand* key() { return inputs_[1]; }
   1243   ElementsKind elements_kind() const {
   1244     return hydrogen()->elements_kind();
   1245   }
   1246 };
   1247 
   1248 
   1249 class LLoadKeyedGeneric: public LTemplateInstruction<1, 2, 0> {
   1250  public:
   1251   LLoadKeyedGeneric(LOperand* obj, LOperand* key) {
   1252     inputs_[0] = obj;
   1253     inputs_[1] = key;
   1254   }
   1255 
   1256   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic")
   1257 
   1258   LOperand* object() { return inputs_[0]; }
   1259   LOperand* key() { return inputs_[1]; }
   1260 };
   1261 
   1262 
   1263 class LLoadGlobalCell: public LTemplateInstruction<1, 0, 0> {
   1264  public:
   1265   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell, "load-global-cell")
   1266   DECLARE_HYDROGEN_ACCESSOR(LoadGlobalCell)
   1267 };
   1268 
   1269 
   1270 class LLoadGlobalGeneric: public LTemplateInstruction<1, 1, 0> {
   1271  public:
   1272   explicit LLoadGlobalGeneric(LOperand* global_object) {
   1273     inputs_[0] = global_object;
   1274   }
   1275 
   1276   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
   1277   DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)
   1278 
   1279   LOperand* global_object() { return inputs_[0]; }
   1280   Handle<Object> name() const { return hydrogen()->name(); }
   1281   bool for_typeof() const { return hydrogen()->for_typeof(); }
   1282 };
   1283 
   1284 
   1285 class LStoreGlobalCell: public LTemplateInstruction<0, 1, 1> {
   1286  public:
   1287   LStoreGlobalCell(LOperand* value, LOperand* temp) {
   1288     inputs_[0] = value;
   1289     temps_[0] = temp;
   1290   }
   1291 
   1292   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell")
   1293   DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell)
   1294 
   1295   LOperand* value() { return inputs_[0]; }
   1296 };
   1297 
   1298 
   1299 class LStoreGlobalGeneric: public LTemplateInstruction<0, 2, 0> {
   1300  public:
   1301   explicit LStoreGlobalGeneric(LOperand* global_object,
   1302                                LOperand* value) {
   1303     inputs_[0] = global_object;
   1304     inputs_[1] = value;
   1305   }
   1306 
   1307   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric, "store-global-generic")
   1308   DECLARE_HYDROGEN_ACCESSOR(StoreGlobalGeneric)
   1309 
   1310   LOperand* global_object() { return InputAt(0); }
   1311   Handle<Object> name() const { return hydrogen()->name(); }
   1312   LOperand* value() { return InputAt(1); }
   1313   StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
   1314 };
   1315 
   1316 
   1317 class LLoadContextSlot: public LTemplateInstruction<1, 1, 0> {
   1318  public:
   1319   explicit LLoadContextSlot(LOperand* context) {
   1320     inputs_[0] = context;
   1321   }
   1322 
   1323   DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot")
   1324   DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot)
   1325 
   1326   LOperand* context() { return InputAt(0); }
   1327   int slot_index() { return hydrogen()->slot_index(); }
   1328 
   1329   virtual void PrintDataTo(StringStream* stream);
   1330 };
   1331 
   1332 
   1333 class LStoreContextSlot: public LTemplateInstruction<0, 2, 0> {
   1334  public:
   1335   LStoreContextSlot(LOperand* context, LOperand* value) {
   1336     inputs_[0] = context;
   1337     inputs_[1] = value;
   1338   }
   1339 
   1340   DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot")
   1341   DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot)
   1342 
   1343   LOperand* context() { return InputAt(0); }
   1344   LOperand* value() { return InputAt(1); }
   1345   int slot_index() { return hydrogen()->slot_index(); }
   1346 
   1347   virtual void PrintDataTo(StringStream* stream);
   1348 };
   1349 
   1350 
   1351 class LPushArgument: public LTemplateInstruction<0, 1, 0> {
   1352  public:
   1353   explicit LPushArgument(LOperand* value) {
   1354     inputs_[0] = value;
   1355   }
   1356 
   1357   DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push-argument")
   1358 };
   1359 
   1360 
   1361 class LThisFunction: public LTemplateInstruction<1, 0, 0> {
   1362  public:
   1363   DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
   1364   DECLARE_HYDROGEN_ACCESSOR(ThisFunction)
   1365 };
   1366 
   1367 
   1368 class LContext: public LTemplateInstruction<1, 0, 0> {
   1369  public:
   1370   DECLARE_CONCRETE_INSTRUCTION(Context, "context")
   1371 };
   1372 
   1373 
   1374 class LOuterContext: public LTemplateInstruction<1, 1, 0> {
   1375  public:
   1376   explicit LOuterContext(LOperand* context) {
   1377     inputs_[0] = context;
   1378   }
   1379 
   1380   DECLARE_CONCRETE_INSTRUCTION(OuterContext, "outer-context")
   1381 
   1382   LOperand* context() { return InputAt(0); }
   1383 };
   1384 
   1385 
   1386 class LDeclareGlobals: public LTemplateInstruction<0, 0, 0> {
   1387  public:
   1388   DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals, "declare-globals")
   1389   DECLARE_HYDROGEN_ACCESSOR(DeclareGlobals)
   1390 };
   1391 
   1392 
   1393 class LGlobalObject: public LTemplateInstruction<1, 1, 0> {
   1394  public:
   1395   explicit LGlobalObject(LOperand* context) {
   1396     inputs_[0] = context;
   1397   }
   1398 
   1399   DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
   1400 
   1401   LOperand* context() { return InputAt(0); }
   1402 };
   1403 
   1404 
   1405 class LGlobalReceiver: public LTemplateInstruction<1, 1, 0> {
   1406  public:
   1407   explicit LGlobalReceiver(LOperand* global_object) {
   1408     inputs_[0] = global_object;
   1409   }
   1410 
   1411   DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global-receiver")
   1412 
   1413   LOperand* global() { return InputAt(0); }
   1414 };
   1415 
   1416 
   1417 class LCallConstantFunction: public LTemplateInstruction<1, 0, 0> {
   1418  public:
   1419   DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call-constant-function")
   1420   DECLARE_HYDROGEN_ACCESSOR(CallConstantFunction)
   1421 
   1422   virtual void PrintDataTo(StringStream* stream);
   1423 
   1424   Handle<JSFunction> function() { return hydrogen()->function(); }
   1425   int arity() const { return hydrogen()->argument_count() - 1; }
   1426 };
   1427 
   1428 
   1429 class LInvokeFunction: public LTemplateInstruction<1, 1, 0> {
   1430  public:
   1431   explicit LInvokeFunction(LOperand* function) {
   1432     inputs_[0] = function;
   1433   }
   1434 
   1435   DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
   1436   DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
   1437 
   1438   LOperand* function() { return inputs_[0]; }
   1439 
   1440   virtual void PrintDataTo(StringStream* stream);
   1441 
   1442   int arity() const { return hydrogen()->argument_count() - 1; }
   1443 };
   1444 
   1445 
   1446 class LCallKeyed: public LTemplateInstruction<1, 1, 0> {
   1447  public:
   1448   explicit LCallKeyed(LOperand* key) {
   1449     inputs_[0] = key;
   1450   }
   1451 
   1452   DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call-keyed")
   1453   DECLARE_HYDROGEN_ACCESSOR(CallKeyed)
   1454 
   1455   virtual void PrintDataTo(StringStream* stream);
   1456 
   1457   int arity() const { return hydrogen()->argument_count() - 1; }
   1458 };
   1459 
   1460 
   1461 
   1462 class LCallNamed: public LTemplateInstruction<1, 0, 0> {
   1463  public:
   1464   DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call-named")
   1465   DECLARE_HYDROGEN_ACCESSOR(CallNamed)
   1466 
   1467   virtual void PrintDataTo(StringStream* stream);
   1468 
   1469   Handle<String> name() const { return hydrogen()->name(); }
   1470   int arity() const { return hydrogen()->argument_count() - 1; }
   1471 };
   1472 
   1473 
   1474 class LCallFunction: public LTemplateInstruction<1, 1, 0> {
   1475  public:
   1476   explicit LCallFunction(LOperand* function) {
   1477     inputs_[0] = function;
   1478   }
   1479 
   1480   DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call-function")
   1481   DECLARE_HYDROGEN_ACCESSOR(CallFunction)
   1482 
   1483   LOperand* function() { return inputs_[0]; }
   1484   int arity() const { return hydrogen()->argument_count() - 1; }
   1485 };
   1486 
   1487 
   1488 class LCallGlobal: public LTemplateInstruction<1, 0, 0> {
   1489  public:
   1490   DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call-global")
   1491   DECLARE_HYDROGEN_ACCESSOR(CallGlobal)
   1492 
   1493   virtual void PrintDataTo(StringStream* stream);
   1494 
   1495   Handle<String> name() const {return hydrogen()->name(); }
   1496   int arity() const { return hydrogen()->argument_count() - 1; }
   1497 };
   1498 
   1499 
   1500 class LCallKnownGlobal: public LTemplateInstruction<1, 0, 0> {
   1501  public:
   1502   DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call-known-global")
   1503   DECLARE_HYDROGEN_ACCESSOR(CallKnownGlobal)
   1504 
   1505   virtual void PrintDataTo(StringStream* stream);
   1506 
   1507   Handle<JSFunction> target() const { return hydrogen()->target();  }
   1508   int arity() const { return hydrogen()->argument_count() - 1;  }
   1509 };
   1510 
   1511 
   1512 class LCallNew: public LTemplateInstruction<1, 1, 0> {
   1513  public:
   1514   explicit LCallNew(LOperand* constructor) {
   1515     inputs_[0] = constructor;
   1516   }
   1517 
   1518   DECLARE_CONCRETE_INSTRUCTION(CallNew, "call-new")
   1519   DECLARE_HYDROGEN_ACCESSOR(CallNew)
   1520 
   1521   virtual void PrintDataTo(StringStream* stream);
   1522 
   1523   int arity() const { return hydrogen()->argument_count() - 1; }
   1524 };
   1525 
   1526 
   1527 class LCallRuntime: public LTemplateInstruction<1, 0, 0> {
   1528  public:
   1529   DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
   1530   DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
   1531 
   1532   const Runtime::Function* function() const { return hydrogen()->function(); }
   1533   int arity() const { return hydrogen()->argument_count(); }
   1534 };
   1535 
   1536 
   1537 class LInteger32ToDouble: public LTemplateInstruction<1, 1, 0> {
   1538  public:
   1539   explicit LInteger32ToDouble(LOperand* value) {
   1540     inputs_[0] = value;
   1541   }
   1542 
   1543   DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double")
   1544 };
   1545 
   1546 
   1547 class LNumberTagI: public LTemplateInstruction<1, 1, 0> {
   1548  public:
   1549   explicit LNumberTagI(LOperand* value) {
   1550     inputs_[0] = value;
   1551   }
   1552 
   1553   DECLARE_CONCRETE_INSTRUCTION(NumberTagI, "number-tag-i")
   1554 };
   1555 
   1556 
   1557 class LNumberTagD: public LTemplateInstruction<1, 1, 2> {
   1558  public:
   1559   LNumberTagD(LOperand* value, LOperand* temp1, LOperand* temp2) {
   1560     inputs_[0] = value;
   1561     temps_[0] = temp1;
   1562     temps_[1] = temp2;
   1563   }
   1564 
   1565   DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d")
   1566 };
   1567 
   1568 
   1569 // Sometimes truncating conversion from a tagged value to an int32.
   1570 class LDoubleToI: public LTemplateInstruction<1, 1, 2> {
   1571  public:
   1572   LDoubleToI(LOperand* value, LOperand* temp1, LOperand* temp2) {
   1573     inputs_[0] = value;
   1574     temps_[0] = temp1;
   1575     temps_[1] = temp2;
   1576   }
   1577 
   1578   DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i")
   1579   DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
   1580 
   1581   bool truncating() { return hydrogen()->CanTruncateToInt32(); }
   1582 };
   1583 
   1584 
   1585 // Truncating conversion from a tagged value to an int32.
   1586 class LTaggedToI: public LTemplateInstruction<1, 1, 3> {
   1587  public:
   1588   LTaggedToI(LOperand* value,
   1589              LOperand* temp1,
   1590              LOperand* temp2,
   1591              LOperand* temp3) {
   1592     inputs_[0] = value;
   1593     temps_[0] = temp1;
   1594     temps_[1] = temp2;
   1595     temps_[2] = temp3;
   1596   }
   1597 
   1598   DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
   1599   DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
   1600 
   1601   bool truncating() { return hydrogen()->CanTruncateToInt32(); }
   1602 };
   1603 
   1604 
   1605 class LSmiTag: public LTemplateInstruction<1, 1, 0> {
   1606  public:
   1607   explicit LSmiTag(LOperand* value) {
   1608     inputs_[0] = value;
   1609   }
   1610 
   1611   DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag")
   1612 };
   1613 
   1614 
   1615 class LNumberUntagD: public LTemplateInstruction<1, 1, 0> {
   1616  public:
   1617   explicit LNumberUntagD(LOperand* value) {
   1618     inputs_[0] = value;
   1619   }
   1620 
   1621   DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
   1622   DECLARE_HYDROGEN_ACCESSOR(Change)
   1623 };
   1624 
   1625 
   1626 class LSmiUntag: public LTemplateInstruction<1, 1, 0> {
   1627  public:
   1628   LSmiUntag(LOperand* value, bool needs_check)
   1629       : needs_check_(needs_check) {
   1630     inputs_[0] = value;
   1631   }
   1632 
   1633   DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
   1634 
   1635   bool needs_check() const { return needs_check_; }
   1636 
   1637  private:
   1638   bool needs_check_;
   1639 };
   1640 
   1641 
   1642 class LStoreNamedField: public LTemplateInstruction<0, 2, 0> {
   1643  public:
   1644   LStoreNamedField(LOperand* obj, LOperand* val) {
   1645     inputs_[0] = obj;
   1646     inputs_[1] = val;
   1647   }
   1648 
   1649   DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
   1650   DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
   1651 
   1652   virtual void PrintDataTo(StringStream* stream);
   1653 
   1654   LOperand* object() { return inputs_[0]; }
   1655   LOperand* value() { return inputs_[1]; }
   1656 
   1657   Handle<Object> name() const { return hydrogen()->name(); }
   1658   bool is_in_object() { return hydrogen()->is_in_object(); }
   1659   int offset() { return hydrogen()->offset(); }
   1660   Handle<Map> transition() const { return hydrogen()->transition(); }
   1661 };
   1662 
   1663 
   1664 class LStoreNamedGeneric: public LTemplateInstruction<0, 2, 0> {
   1665  public:
   1666   LStoreNamedGeneric(LOperand* obj, LOperand* val) {
   1667     inputs_[0] = obj;
   1668     inputs_[1] = val;
   1669   }
   1670 
   1671   DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
   1672   DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
   1673 
   1674   virtual void PrintDataTo(StringStream* stream);
   1675 
   1676   LOperand* object() { return inputs_[0]; }
   1677   LOperand* value() { return inputs_[1]; }
   1678   Handle<Object> name() const { return hydrogen()->name(); }
   1679   StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
   1680 };
   1681 
   1682 
   1683 class LStoreKeyedFastElement: public LTemplateInstruction<0, 3, 0> {
   1684  public:
   1685   LStoreKeyedFastElement(LOperand* obj, LOperand* key, LOperand* val) {
   1686     inputs_[0] = obj;
   1687     inputs_[1] = key;
   1688     inputs_[2] = val;
   1689   }
   1690 
   1691   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
   1692                                "store-keyed-fast-element")
   1693   DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastElement)
   1694 
   1695   virtual void PrintDataTo(StringStream* stream);
   1696 
   1697   LOperand* object() { return inputs_[0]; }
   1698   LOperand* key() { return inputs_[1]; }
   1699   LOperand* value() { return inputs_[2]; }
   1700 };
   1701 
   1702 
   1703 class LStoreKeyedFastDoubleElement: public LTemplateInstruction<0, 3, 0> {
   1704  public:
   1705   LStoreKeyedFastDoubleElement(LOperand* elements,
   1706                                LOperand* key,
   1707                                LOperand* val) {
   1708     inputs_[0] = elements;
   1709     inputs_[1] = key;
   1710     inputs_[2] = val;
   1711   }
   1712 
   1713   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement,
   1714                                "store-keyed-fast-double-element")
   1715   DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastDoubleElement)
   1716 
   1717   virtual void PrintDataTo(StringStream* stream);
   1718 
   1719   LOperand* elements() { return inputs_[0]; }
   1720   LOperand* key() { return inputs_[1]; }
   1721   LOperand* value() { return inputs_[2]; }
   1722 };
   1723 
   1724 
   1725 class LStoreKeyedGeneric: public LTemplateInstruction<0, 3, 0> {
   1726  public:
   1727   LStoreKeyedGeneric(LOperand* obj, LOperand* key, LOperand* val) {
   1728     inputs_[0] = obj;
   1729     inputs_[1] = key;
   1730     inputs_[2] = val;
   1731   }
   1732 
   1733   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
   1734   DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
   1735 
   1736   virtual void PrintDataTo(StringStream* stream);
   1737 
   1738   LOperand* object() { return inputs_[0]; }
   1739   LOperand* key() { return inputs_[1]; }
   1740   LOperand* value() { return inputs_[2]; }
   1741   StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
   1742 };
   1743 
   1744 class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0, 3, 0> {
   1745  public:
   1746   LStoreKeyedSpecializedArrayElement(LOperand* external_pointer,
   1747                                      LOperand* key,
   1748                                      LOperand* val) {
   1749     inputs_[0] = external_pointer;
   1750     inputs_[1] = key;
   1751     inputs_[2] = val;
   1752   }
   1753 
   1754   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement,
   1755                                "store-keyed-specialized-array-element")
   1756   DECLARE_HYDROGEN_ACCESSOR(StoreKeyedSpecializedArrayElement)
   1757 
   1758   LOperand* external_pointer() { return inputs_[0]; }
   1759   LOperand* key() { return inputs_[1]; }
   1760   LOperand* value() { return inputs_[2]; }
   1761   ElementsKind elements_kind() const {
   1762     return hydrogen()->elements_kind();
   1763   }
   1764 };
   1765 
   1766 
   1767 class LTransitionElementsKind: public LTemplateInstruction<1, 1, 2> {
   1768  public:
   1769   LTransitionElementsKind(LOperand* object,
   1770                           LOperand* new_map_temp,
   1771                           LOperand* temp_reg) {
   1772     inputs_[0] = object;
   1773     temps_[0] = new_map_temp;
   1774     temps_[1] = temp_reg;
   1775   }
   1776 
   1777   DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind,
   1778                                "transition-elements-kind")
   1779   DECLARE_HYDROGEN_ACCESSOR(TransitionElementsKind)
   1780 
   1781   virtual void PrintDataTo(StringStream* stream);
   1782 
   1783   LOperand* object() { return inputs_[0]; }
   1784   LOperand* new_map_reg() { return temps_[0]; }
   1785   LOperand* temp_reg() { return temps_[1]; }
   1786   Handle<Map> original_map() { return hydrogen()->original_map(); }
   1787   Handle<Map> transitioned_map() { return hydrogen()->transitioned_map(); }
   1788 };
   1789 
   1790 
   1791 class LStringAdd: public LTemplateInstruction<1, 2, 0> {
   1792  public:
   1793   LStringAdd(LOperand* left, LOperand* right) {
   1794     inputs_[0] = left;
   1795     inputs_[1] = right;
   1796   }
   1797 
   1798   DECLARE_CONCRETE_INSTRUCTION(StringAdd, "string-add")
   1799   DECLARE_HYDROGEN_ACCESSOR(StringAdd)
   1800 
   1801   LOperand* left() { return inputs_[0]; }
   1802   LOperand* right() { return inputs_[1]; }
   1803 };
   1804 
   1805 
   1806 
   1807 class LStringCharCodeAt: public LTemplateInstruction<1, 2, 0> {
   1808  public:
   1809   LStringCharCodeAt(LOperand* string, LOperand* index) {
   1810     inputs_[0] = string;
   1811     inputs_[1] = index;
   1812   }
   1813 
   1814   DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at")
   1815   DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt)
   1816 
   1817   LOperand* string() { return inputs_[0]; }
   1818   LOperand* index() { return inputs_[1]; }
   1819 };
   1820 
   1821 
   1822 class LStringCharFromCode: public LTemplateInstruction<1, 1, 0> {
   1823  public:
   1824   explicit LStringCharFromCode(LOperand* char_code) {
   1825     inputs_[0] = char_code;
   1826   }
   1827 
   1828   DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code")
   1829   DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode)
   1830 
   1831   LOperand* char_code() { return inputs_[0]; }
   1832 };
   1833 
   1834 
   1835 class LStringLength: public LTemplateInstruction<1, 1, 0> {
   1836  public:
   1837   explicit LStringLength(LOperand* string) {
   1838     inputs_[0] = string;
   1839   }
   1840 
   1841   DECLARE_CONCRETE_INSTRUCTION(StringLength, "string-length")
   1842   DECLARE_HYDROGEN_ACCESSOR(StringLength)
   1843 
   1844   LOperand* string() { return inputs_[0]; }
   1845 };
   1846 
   1847 
   1848 class LCheckFunction: public LTemplateInstruction<0, 1, 0> {
   1849  public:
   1850   explicit LCheckFunction(LOperand* value) {
   1851     inputs_[0] = value;
   1852   }
   1853 
   1854   LOperand* value() { return InputAt(0); }
   1855 
   1856   DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check-function")
   1857   DECLARE_HYDROGEN_ACCESSOR(CheckFunction)
   1858 };
   1859 
   1860 
   1861 class LCheckInstanceType: public LTemplateInstruction<0, 1, 0> {
   1862  public:
   1863   explicit LCheckInstanceType(LOperand* value) {
   1864     inputs_[0] = value;
   1865   }
   1866 
   1867   DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type")
   1868   DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType)
   1869 };
   1870 
   1871 
   1872 class LCheckMap: public LTemplateInstruction<0, 1, 0> {
   1873  public:
   1874   explicit LCheckMap(LOperand* value) {
   1875     inputs_[0] = value;
   1876   }
   1877 
   1878   DECLARE_CONCRETE_INSTRUCTION(CheckMap, "check-map")
   1879   DECLARE_HYDROGEN_ACCESSOR(CheckMap)
   1880 };
   1881 
   1882 
   1883 class LCheckPrototypeMaps: public LTemplateInstruction<0, 0, 2> {
   1884  public:
   1885   LCheckPrototypeMaps(LOperand* temp1, LOperand* temp2)  {
   1886     temps_[0] = temp1;
   1887     temps_[1] = temp2;
   1888   }
   1889 
   1890   DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check-prototype-maps")
   1891   DECLARE_HYDROGEN_ACCESSOR(CheckPrototypeMaps)
   1892 
   1893   Handle<JSObject> prototype() const { return hydrogen()->prototype(); }
   1894   Handle<JSObject> holder() const { return hydrogen()->holder(); }
   1895 };
   1896 
   1897 
   1898 class LCheckSmi: public LTemplateInstruction<0, 1, 0> {
   1899  public:
   1900   explicit LCheckSmi(LOperand* value) {
   1901     inputs_[0] = value;
   1902   }
   1903 
   1904   DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi")
   1905 };
   1906 
   1907 
   1908 class LCheckNonSmi: public LTemplateInstruction<0, 1, 0> {
   1909  public:
   1910   explicit LCheckNonSmi(LOperand* value) {
   1911     inputs_[0] = value;
   1912   }
   1913 
   1914   DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi")
   1915 };
   1916 
   1917 
   1918 class LClampDToUint8: public LTemplateInstruction<1, 1, 1> {
   1919  public:
   1920   LClampDToUint8(LOperand* value, LOperand* temp) {
   1921     inputs_[0] = value;
   1922     temps_[0] = temp;
   1923   }
   1924 
   1925   LOperand* unclamped() { return inputs_[0]; }
   1926 
   1927   DECLARE_CONCRETE_INSTRUCTION(ClampDToUint8, "clamp-d-to-uint8")
   1928 };
   1929 
   1930 
   1931 class LClampIToUint8: public LTemplateInstruction<1, 1, 0> {
   1932  public:
   1933   explicit LClampIToUint8(LOperand* value) {
   1934     inputs_[0] = value;
   1935   }
   1936 
   1937   LOperand* unclamped() { return inputs_[0]; }
   1938 
   1939   DECLARE_CONCRETE_INSTRUCTION(ClampIToUint8, "clamp-i-to-uint8")
   1940 };
   1941 
   1942 
   1943 class LClampTToUint8: public LTemplateInstruction<1, 1, 1> {
   1944  public:
   1945   LClampTToUint8(LOperand* value, LOperand* temp) {
   1946     inputs_[0] = value;
   1947     temps_[0] = temp;
   1948   }
   1949 
   1950   LOperand* unclamped() { return inputs_[0]; }
   1951 
   1952   DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8, "clamp-t-to-uint8")
   1953 };
   1954 
   1955 
   1956 class LAllocateObject: public LTemplateInstruction<1, 0, 2> {
   1957  public:
   1958   LAllocateObject(LOperand* temp1, LOperand* temp2) {
   1959     temps_[0] = temp1;
   1960     temps_[1] = temp2;
   1961   }
   1962 
   1963   DECLARE_CONCRETE_INSTRUCTION(AllocateObject, "allocate-object")
   1964   DECLARE_HYDROGEN_ACCESSOR(AllocateObject)
   1965 };
   1966 
   1967 
   1968 class LFastLiteral: public LTemplateInstruction<1, 0, 0> {
   1969  public:
   1970   DECLARE_CONCRETE_INSTRUCTION(FastLiteral, "fast-literal")
   1971   DECLARE_HYDROGEN_ACCESSOR(FastLiteral)
   1972 };
   1973 
   1974 
   1975 class LArrayLiteral: public LTemplateInstruction<1, 0, 0> {
   1976  public:
   1977   DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral, "array-literal")
   1978   DECLARE_HYDROGEN_ACCESSOR(ArrayLiteral)
   1979 };
   1980 
   1981 
   1982 class LObjectLiteral: public LTemplateInstruction<1, 0, 0> {
   1983  public:
   1984   DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object-literal")
   1985   DECLARE_HYDROGEN_ACCESSOR(ObjectLiteral)
   1986 };
   1987 
   1988 
   1989 class LRegExpLiteral: public LTemplateInstruction<1, 0, 0> {
   1990  public:
   1991   DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp-literal")
   1992   DECLARE_HYDROGEN_ACCESSOR(RegExpLiteral)
   1993 };
   1994 
   1995 
   1996 class LFunctionLiteral: public LTemplateInstruction<1, 0, 0> {
   1997  public:
   1998   DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function-literal")
   1999   DECLARE_HYDROGEN_ACCESSOR(FunctionLiteral)
   2000 
   2001   Handle<SharedFunctionInfo> shared_info() { return hydrogen()->shared_info(); }
   2002 };
   2003 
   2004 
   2005 class LToFastProperties: public LTemplateInstruction<1, 1, 0> {
   2006  public:
   2007   explicit LToFastProperties(LOperand* value) {
   2008     inputs_[0] = value;
   2009   }
   2010 
   2011   DECLARE_CONCRETE_INSTRUCTION(ToFastProperties, "to-fast-properties")
   2012   DECLARE_HYDROGEN_ACCESSOR(ToFastProperties)
   2013 };
   2014 
   2015 
   2016 class LTypeof: public LTemplateInstruction<1, 1, 0> {
   2017  public:
   2018   explicit LTypeof(LOperand* value) {
   2019     inputs_[0] = value;
   2020   }
   2021 
   2022   DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
   2023 };
   2024 
   2025 
   2026 class LTypeofIsAndBranch: public LControlInstruction<1, 0> {
   2027  public:
   2028   explicit LTypeofIsAndBranch(LOperand* value) {
   2029     inputs_[0] = value;
   2030   }
   2031 
   2032   DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch")
   2033   DECLARE_HYDROGEN_ACCESSOR(TypeofIsAndBranch)
   2034 
   2035   Handle<String> type_literal() { return hydrogen()->type_literal(); }
   2036 
   2037   virtual void PrintDataTo(StringStream* stream);
   2038 };
   2039 
   2040 
   2041 class LIsConstructCallAndBranch: public LControlInstruction<0, 1> {
   2042  public:
   2043   explicit LIsConstructCallAndBranch(LOperand* temp) {
   2044     temps_[0] = temp;
   2045   }
   2046 
   2047   DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch,
   2048                                "is-construct-call-and-branch")
   2049 };
   2050 
   2051 
   2052 class LDeleteProperty: public LTemplateInstruction<1, 2, 0> {
   2053  public:
   2054   LDeleteProperty(LOperand* obj, LOperand* key) {
   2055     inputs_[0] = obj;
   2056     inputs_[1] = key;
   2057   }
   2058 
   2059   DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete-property")
   2060 
   2061   LOperand* object() { return inputs_[0]; }
   2062   LOperand* key() { return inputs_[1]; }
   2063 };
   2064 
   2065 
   2066 class LOsrEntry: public LTemplateInstruction<0, 0, 0> {
   2067  public:
   2068   LOsrEntry();
   2069 
   2070   DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry")
   2071 
   2072   LOperand** SpilledRegisterArray() { return register_spills_; }
   2073   LOperand** SpilledDoubleRegisterArray() { return double_register_spills_; }
   2074 
   2075   void MarkSpilledRegister(int allocation_index, LOperand* spill_operand);
   2076   void MarkSpilledDoubleRegister(int allocation_index,
   2077                                  LOperand* spill_operand);
   2078 
   2079  private:
   2080   // Arrays of spill slot operands for registers with an assigned spill
   2081   // slot, i.e., that must also be restored to the spill slot on OSR entry.
   2082   // NULL if the register has no assigned spill slot.  Indexed by allocation
   2083   // index.
   2084   LOperand* register_spills_[Register::kNumAllocatableRegisters];
   2085   LOperand* double_register_spills_[DoubleRegister::kNumAllocatableRegisters];
   2086 };
   2087 
   2088 
   2089 class LStackCheck: public LTemplateInstruction<0, 0, 0> {
   2090  public:
   2091   DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check")
   2092   DECLARE_HYDROGEN_ACCESSOR(StackCheck)
   2093 
   2094   Label* done_label() { return &done_label_; }
   2095 
   2096  private:
   2097   Label done_label_;
   2098 };
   2099 
   2100 
   2101 class LIn: public LTemplateInstruction<1, 2, 0> {
   2102  public:
   2103   LIn(LOperand* key, LOperand* object) {
   2104     inputs_[0] = key;
   2105     inputs_[1] = object;
   2106   }
   2107 
   2108   LOperand* key() { return inputs_[0]; }
   2109   LOperand* object() { return inputs_[1]; }
   2110 
   2111   DECLARE_CONCRETE_INSTRUCTION(In, "in")
   2112 };
   2113 
   2114 
   2115 class LForInPrepareMap: public LTemplateInstruction<1, 1, 0> {
   2116  public:
   2117   explicit LForInPrepareMap(LOperand* object) {
   2118     inputs_[0] = object;
   2119   }
   2120 
   2121   LOperand* object() { return inputs_[0]; }
   2122 
   2123   DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap, "for-in-prepare-map")
   2124 };
   2125 
   2126 
   2127 class LForInCacheArray: public LTemplateInstruction<1, 1, 0> {
   2128  public:
   2129   explicit LForInCacheArray(LOperand* map) {
   2130     inputs_[0] = map;
   2131   }
   2132 
   2133   LOperand* map() { return inputs_[0]; }
   2134 
   2135   DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray, "for-in-cache-array")
   2136 
   2137   int idx() {
   2138     return HForInCacheArray::cast(this->hydrogen_value())->idx();
   2139   }
   2140 };
   2141 
   2142 
   2143 class LCheckMapValue: public LTemplateInstruction<0, 2, 0> {
   2144  public:
   2145   LCheckMapValue(LOperand* value, LOperand* map) {
   2146     inputs_[0] = value;
   2147     inputs_[1] = map;
   2148   }
   2149 
   2150   LOperand* value() { return inputs_[0]; }
   2151   LOperand* map() { return inputs_[1]; }
   2152 
   2153   DECLARE_CONCRETE_INSTRUCTION(CheckMapValue, "check-map-value")
   2154 };
   2155 
   2156 
   2157 class LLoadFieldByIndex: public LTemplateInstruction<1, 2, 0> {
   2158  public:
   2159   LLoadFieldByIndex(LOperand* object, LOperand* index) {
   2160     inputs_[0] = object;
   2161     inputs_[1] = index;
   2162   }
   2163 
   2164   LOperand* object() { return inputs_[0]; }
   2165   LOperand* index() { return inputs_[1]; }
   2166 
   2167   DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex, "load-field-by-index")
   2168 };
   2169 
   2170 
   2171 class LChunkBuilder;
   2172 class LChunk: public ZoneObject {
   2173  public:
   2174   explicit LChunk(CompilationInfo* info, HGraph* graph);
   2175 
   2176   void AddInstruction(LInstruction* instruction, HBasicBlock* block);
   2177   LConstantOperand* DefineConstantOperand(HConstant* constant);
   2178   Handle<Object> LookupLiteral(LConstantOperand* operand) const;
   2179   Representation LookupLiteralRepresentation(LConstantOperand* operand) const;
   2180 
   2181   int GetNextSpillIndex(bool is_double);
   2182   LOperand* GetNextSpillSlot(bool is_double);
   2183 
   2184   int ParameterAt(int index);
   2185   int GetParameterStackSlot(int index) const;
   2186   int spill_slot_count() const { return spill_slot_count_; }
   2187   CompilationInfo* info() const { return info_; }
   2188   HGraph* graph() const { return graph_; }
   2189   const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
   2190   void AddGapMove(int index, LOperand* from, LOperand* to);
   2191   LGap* GetGapAt(int index) const;
   2192   bool IsGapAt(int index) const;
   2193   int NearestGapPos(int index) const;
   2194   void MarkEmptyBlocks();
   2195   const ZoneList<LPointerMap*>* pointer_maps() const { return &pointer_maps_; }
   2196   LLabel* GetLabel(int block_id) const {
   2197     HBasicBlock* block = graph_->blocks()->at(block_id);
   2198     int first_instruction = block->first_instruction_index();
   2199     return LLabel::cast(instructions_[first_instruction]);
   2200   }
   2201   int LookupDestination(int block_id) const {
   2202     LLabel* cur = GetLabel(block_id);
   2203     while (cur->replacement() != NULL) {
   2204       cur = cur->replacement();
   2205     }
   2206     return cur->block_id();
   2207   }
   2208   Label* GetAssemblyLabel(int block_id) const {
   2209     LLabel* label = GetLabel(block_id);
   2210     ASSERT(!label->HasReplacement());
   2211     return label->label();
   2212   }
   2213 
   2214   const ZoneList<Handle<JSFunction> >* inlined_closures() const {
   2215     return &inlined_closures_;
   2216   }
   2217 
   2218   void AddInlinedClosure(Handle<JSFunction> closure) {
   2219     inlined_closures_.Add(closure);
   2220   }
   2221 
   2222  private:
   2223   int spill_slot_count_;
   2224   CompilationInfo* info_;
   2225   HGraph* const graph_;
   2226   ZoneList<LInstruction*> instructions_;
   2227   ZoneList<LPointerMap*> pointer_maps_;
   2228   ZoneList<Handle<JSFunction> > inlined_closures_;
   2229 };
   2230 
   2231 
   2232 class LChunkBuilder BASE_EMBEDDED {
   2233  public:
   2234   LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator)
   2235       : chunk_(NULL),
   2236         info_(info),
   2237         graph_(graph),
   2238         zone_(graph->isolate()->zone()),
   2239         status_(UNUSED),
   2240         current_instruction_(NULL),
   2241         current_block_(NULL),
   2242         next_block_(NULL),
   2243         argument_count_(0),
   2244         allocator_(allocator),
   2245         position_(RelocInfo::kNoPosition),
   2246         instruction_pending_deoptimization_environment_(NULL),
   2247         pending_deoptimization_ast_id_(AstNode::kNoNumber) { }
   2248 
   2249   // Build the sequence for the graph.
   2250   LChunk* Build();
   2251 
   2252   // Declare methods that deal with the individual node types.
   2253 #define DECLARE_DO(type) LInstruction* Do##type(H##type* node);
   2254   HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
   2255 #undef DECLARE_DO
   2256 
   2257  private:
   2258   enum Status {
   2259     UNUSED,
   2260     BUILDING,
   2261     DONE,
   2262     ABORTED
   2263   };
   2264 
   2265   LChunk* chunk() const { return chunk_; }
   2266   CompilationInfo* info() const { return info_; }
   2267   HGraph* graph() const { return graph_; }
   2268   Zone* zone() const { return zone_; }
   2269 
   2270   bool is_unused() const { return status_ == UNUSED; }
   2271   bool is_building() const { return status_ == BUILDING; }
   2272   bool is_done() const { return status_ == DONE; }
   2273   bool is_aborted() const { return status_ == ABORTED; }
   2274 
   2275   void Abort(const char* format, ...);
   2276 
   2277   // Methods for getting operands for Use / Define / Temp.
   2278   LUnallocated* ToUnallocated(Register reg);
   2279   LUnallocated* ToUnallocated(DoubleRegister reg);
   2280 
   2281   // Methods for setting up define-use relationships.
   2282   MUST_USE_RESULT LOperand* Use(HValue* value, LUnallocated* operand);
   2283   MUST_USE_RESULT LOperand* UseFixed(HValue* value, Register fixed_register);
   2284   MUST_USE_RESULT LOperand* UseFixedDouble(HValue* value,
   2285                                            DoubleRegister fixed_register);
   2286 
   2287   // A value that is guaranteed to be allocated to a register.
   2288   // Operand created by UseRegister is guaranteed to be live until the end of
   2289   // instruction. This means that register allocator will not reuse it's
   2290   // register for any other operand inside instruction.
   2291   // Operand created by UseRegisterAtStart is guaranteed to be live only at
   2292   // instruction start. Register allocator is free to assign the same register
   2293   // to some other operand used inside instruction (i.e. temporary or
   2294   // output).
   2295   MUST_USE_RESULT LOperand* UseRegister(HValue* value);
   2296   MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value);
   2297 
   2298   // An input operand in a register that may be trashed.
   2299   MUST_USE_RESULT LOperand* UseTempRegister(HValue* value);
   2300 
   2301   // An input operand in a register or stack slot.
   2302   MUST_USE_RESULT LOperand* Use(HValue* value);
   2303   MUST_USE_RESULT LOperand* UseAtStart(HValue* value);
   2304 
   2305   // An input operand in a register, stack slot or a constant operand.
   2306   MUST_USE_RESULT LOperand* UseOrConstant(HValue* value);
   2307   MUST_USE_RESULT LOperand* UseOrConstantAtStart(HValue* value);
   2308 
   2309   // An input operand in a register or a constant operand.
   2310   MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value);
   2311   MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value);
   2312 
   2313   // An input operand in register, stack slot or a constant operand.
   2314   // Will not be moved to a register even if one is freely available.
   2315   MUST_USE_RESULT LOperand* UseAny(HValue* value);
   2316 
   2317   // Temporary operand that must be in a register.
   2318   MUST_USE_RESULT LUnallocated* TempRegister();
   2319   MUST_USE_RESULT LOperand* FixedTemp(Register reg);
   2320   MUST_USE_RESULT LOperand* FixedTemp(DoubleRegister reg);
   2321 
   2322   // Methods for setting up define-use relationships.
   2323   // Return the same instruction that they are passed.
   2324   template<int I, int T>
   2325       LInstruction* Define(LTemplateInstruction<1, I, T>* instr,
   2326                            LUnallocated* result);
   2327   template<int I, int T>
   2328       LInstruction* DefineAsRegister(LTemplateInstruction<1, I, T>* instr);
   2329   template<int I, int T>
   2330       LInstruction* DefineAsSpilled(LTemplateInstruction<1, I, T>* instr,
   2331                                     int index);
   2332   template<int I, int T>
   2333       LInstruction* DefineSameAsFirst(LTemplateInstruction<1, I, T>* instr);
   2334   template<int I, int T>
   2335       LInstruction* DefineFixed(LTemplateInstruction<1, I, T>* instr,
   2336                                 Register reg);
   2337   template<int I, int T>
   2338       LInstruction* DefineFixedDouble(LTemplateInstruction<1, I, T>* instr,
   2339                                       DoubleRegister reg);
   2340   LInstruction* AssignEnvironment(LInstruction* instr);
   2341   LInstruction* AssignPointerMap(LInstruction* instr);
   2342 
   2343   enum CanDeoptimize { CAN_DEOPTIMIZE_EAGERLY, CANNOT_DEOPTIMIZE_EAGERLY };
   2344 
   2345   // By default we assume that instruction sequences generated for calls
   2346   // cannot deoptimize eagerly and we do not attach environment to this
   2347   // instruction.
   2348   LInstruction* MarkAsCall(
   2349       LInstruction* instr,
   2350       HInstruction* hinstr,
   2351       CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY);
   2352   LInstruction* MarkAsSaveDoubles(LInstruction* instr);
   2353 
   2354   LInstruction* SetInstructionPendingDeoptimizationEnvironment(
   2355       LInstruction* instr, int ast_id);
   2356   void ClearInstructionPendingDeoptimizationEnvironment();
   2357 
   2358   LEnvironment* CreateEnvironment(HEnvironment* hydrogen_env,
   2359                                   int* argument_index_accumulator);
   2360 
   2361   void VisitInstruction(HInstruction* current);
   2362 
   2363   void DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block);
   2364   LInstruction* DoBit(Token::Value op, HBitwiseBinaryOperation* instr);
   2365   LInstruction* DoShift(Token::Value op, HBitwiseBinaryOperation* instr);
   2366   LInstruction* DoArithmeticD(Token::Value op,
   2367                               HArithmeticBinaryOperation* instr);
   2368   LInstruction* DoArithmeticT(Token::Value op,
   2369                               HArithmeticBinaryOperation* instr);
   2370 
   2371   LChunk* chunk_;
   2372   CompilationInfo* info_;
   2373   HGraph* const graph_;
   2374   Zone* zone_;
   2375   Status status_;
   2376   HInstruction* current_instruction_;
   2377   HBasicBlock* current_block_;
   2378   HBasicBlock* next_block_;
   2379   int argument_count_;
   2380   LAllocator* allocator_;
   2381   int position_;
   2382   LInstruction* instruction_pending_deoptimization_environment_;
   2383   int pending_deoptimization_ast_id_;
   2384 
   2385   DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
   2386 };
   2387 
   2388 #undef DECLARE_HYDROGEN_ACCESSOR
   2389 #undef DECLARE_CONCRETE_INSTRUCTION
   2390 
   2391 } }  // namespace v8::internal
   2392 
   2393 #endif  // V8_MIPS_LITHIUM_MIPS_H_
   2394