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