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