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