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