Home | History | Annotate | Download | only in ia32
      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_IA32_LITHIUM_IA32_H_
     29 #define V8_IA32_LITHIUM_IA32_H_
     30 
     31 #include "hydrogen.h"
     32 #include "lithium-allocator.h"
     33 #include "lithium.h"
     34 #include "safepoint-table.h"
     35 #include "utils.h"
     36 
     37 namespace v8 {
     38 namespace internal {
     39 
     40 // Forward declarations.
     41 class LCodeGen;
     42 
     43 #define LITHIUM_CONCRETE_INSTRUCTION_LIST(V)    \
     44   V(AccessArgumentsAt)                          \
     45   V(AddI)                                       \
     46   V(Allocate)                                   \
     47   V(ApplyArguments)                             \
     48   V(ArgumentsElements)                          \
     49   V(ArgumentsLength)                            \
     50   V(ArithmeticD)                                \
     51   V(ArithmeticT)                                \
     52   V(BitI)                                       \
     53   V(BoundsCheck)                                \
     54   V(Branch)                                     \
     55   V(CallConstantFunction)                       \
     56   V(CallFunction)                               \
     57   V(CallGlobal)                                 \
     58   V(CallKeyed)                                  \
     59   V(CallKnownGlobal)                            \
     60   V(CallNamed)                                  \
     61   V(CallNew)                                    \
     62   V(CallNewArray)                               \
     63   V(CallRuntime)                                \
     64   V(CallStub)                                   \
     65   V(CheckFunction)                              \
     66   V(CheckInstanceType)                          \
     67   V(CheckMaps)                                  \
     68   V(CheckMapValue)                              \
     69   V(CheckNonSmi)                                \
     70   V(CheckSmi)                                   \
     71   V(ClampDToUint8)                              \
     72   V(ClampIToUint8)                              \
     73   V(ClampTToUint8)                              \
     74   V(ClampTToUint8NoSSE2)                        \
     75   V(ClassOfTestAndBranch)                       \
     76   V(CompareNumericAndBranch)                    \
     77   V(CmpObjectEqAndBranch)                       \
     78   V(CmpHoleAndBranch)                           \
     79   V(CmpMapAndBranch)                            \
     80   V(CmpT)                                       \
     81   V(ConstantD)                                  \
     82   V(ConstantE)                                  \
     83   V(ConstantI)                                  \
     84   V(ConstantS)                                  \
     85   V(ConstantT)                                  \
     86   V(Context)                                    \
     87   V(DateField)                                  \
     88   V(DebugBreak)                                 \
     89   V(DeclareGlobals)                             \
     90   V(Deoptimize)                                 \
     91   V(DivI)                                       \
     92   V(DoubleToI)                                  \
     93   V(DoubleToSmi)                                \
     94   V(Drop)                                       \
     95   V(DummyUse)                                   \
     96   V(ElementsKind)                               \
     97   V(ForInCacheArray)                            \
     98   V(ForInPrepareMap)                            \
     99   V(FunctionLiteral)                            \
    100   V(GetCachedArrayIndex)                        \
    101   V(GlobalObject)                               \
    102   V(GlobalReceiver)                             \
    103   V(Goto)                                       \
    104   V(HasCachedArrayIndexAndBranch)               \
    105   V(HasInstanceTypeAndBranch)                   \
    106   V(InnerAllocatedObject)                       \
    107   V(InstanceOf)                                 \
    108   V(InstanceOfKnownGlobal)                      \
    109   V(InstanceSize)                               \
    110   V(InstructionGap)                             \
    111   V(Integer32ToDouble)                          \
    112   V(Integer32ToSmi)                             \
    113   V(InvokeFunction)                             \
    114   V(IsConstructCallAndBranch)                   \
    115   V(IsObjectAndBranch)                          \
    116   V(IsStringAndBranch)                          \
    117   V(IsSmiAndBranch)                             \
    118   V(IsNumberAndBranch)                          \
    119   V(IsUndetectableAndBranch)                    \
    120   V(Label)                                      \
    121   V(LazyBailout)                                \
    122   V(LoadContextSlot)                            \
    123   V(LoadExternalArrayPointer)                   \
    124   V(LoadFieldByIndex)                           \
    125   V(LoadFunctionPrototype)                      \
    126   V(LoadGlobalCell)                             \
    127   V(LoadGlobalGeneric)                          \
    128   V(LoadKeyed)                                  \
    129   V(LoadKeyedGeneric)                           \
    130   V(LoadNamedField)                             \
    131   V(LoadNamedGeneric)                           \
    132   V(MapEnumLength)                              \
    133   V(MathAbs)                                    \
    134   V(MathCos)                                    \
    135   V(MathExp)                                    \
    136   V(MathFloor)                                  \
    137   V(MathFloorOfDiv)                             \
    138   V(MathLog)                                    \
    139   V(MathMinMax)                                 \
    140   V(MathPowHalf)                                \
    141   V(MathRound)                                  \
    142   V(MathSin)                                    \
    143   V(MathSqrt)                                   \
    144   V(MathTan)                                    \
    145   V(ModI)                                       \
    146   V(MulI)                                       \
    147   V(NumberTagD)                                 \
    148   V(NumberTagI)                                 \
    149   V(NumberTagU)                                 \
    150   V(NumberUntagD)                               \
    151   V(OsrEntry)                                   \
    152   V(OuterContext)                               \
    153   V(Parameter)                                  \
    154   V(Power)                                      \
    155   V(Random)                                     \
    156   V(PushArgument)                               \
    157   V(RegExpLiteral)                              \
    158   V(Return)                                     \
    159   V(SeqStringSetChar)                           \
    160   V(ShiftI)                                     \
    161   V(SmiTag)                                     \
    162   V(SmiUntag)                                   \
    163   V(StackCheck)                                 \
    164   V(StoreContextSlot)                           \
    165   V(StoreGlobalCell)                            \
    166   V(StoreGlobalGeneric)                         \
    167   V(StoreKeyed)                                 \
    168   V(StoreKeyedGeneric)                          \
    169   V(StoreNamedField)                            \
    170   V(StoreNamedGeneric)                          \
    171   V(StringAdd)                                  \
    172   V(StringCharCodeAt)                           \
    173   V(StringCharFromCode)                         \
    174   V(StringCompareAndBranch)                     \
    175   V(SubI)                                       \
    176   V(TaggedToI)                                  \
    177   V(TaggedToINoSSE2)                            \
    178   V(ThisFunction)                               \
    179   V(Throw)                                      \
    180   V(ToFastProperties)                           \
    181   V(TransitionElementsKind)                     \
    182   V(TrapAllocationMemento)                      \
    183   V(Typeof)                                     \
    184   V(TypeofIsAndBranch)                          \
    185   V(Uint32ToDouble)                             \
    186   V(Uint32ToSmi)                                \
    187   V(UnknownOSRValue)                            \
    188   V(ValueOf)                                    \
    189   V(WrapReceiver)
    190 
    191 
    192 #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic)              \
    193   virtual Opcode opcode() const { return LInstruction::k##type; } \
    194   virtual void CompileToNative(LCodeGen* generator);              \
    195   virtual const char* Mnemonic() const { return mnemonic; }       \
    196   static L##type* cast(LInstruction* instr) {                     \
    197     ASSERT(instr->Is##type());                                    \
    198     return reinterpret_cast<L##type*>(instr);                     \
    199   }
    200 
    201 
    202 #define DECLARE_HYDROGEN_ACCESSOR(type)     \
    203   H##type* hydrogen() const {               \
    204     return H##type::cast(hydrogen_value()); \
    205   }
    206 
    207 
    208 class LInstruction: public ZoneObject {
    209  public:
    210   LInstruction()
    211       : environment_(NULL),
    212         hydrogen_value_(NULL),
    213         bit_field_(IsCallBits::encode(false)) {
    214     set_position(RelocInfo::kNoPosition);
    215   }
    216 
    217   virtual ~LInstruction() { }
    218 
    219   virtual void CompileToNative(LCodeGen* generator) = 0;
    220   virtual const char* Mnemonic() const = 0;
    221   virtual void PrintTo(StringStream* stream);
    222   virtual void PrintDataTo(StringStream* stream);
    223   virtual void PrintOutputOperandTo(StringStream* stream);
    224 
    225   enum Opcode {
    226     // Declare a unique enum value for each instruction.
    227 #define DECLARE_OPCODE(type) k##type,
    228     LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
    229     kNumberOfInstructions
    230 #undef DECLARE_OPCODE
    231   };
    232 
    233   virtual Opcode opcode() const = 0;
    234 
    235   // Declare non-virtual type testers for all leaf IR classes.
    236 #define DECLARE_PREDICATE(type) \
    237   bool Is##type() const { return opcode() == k##type; }
    238   LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
    239 #undef DECLARE_PREDICATE
    240 
    241   // Declare virtual predicates for instructions that don't have
    242   // an opcode.
    243   virtual bool IsGap() const { return false; }
    244 
    245   virtual bool IsControl() const { return false; }
    246 
    247   void set_environment(LEnvironment* env) { environment_ = env; }
    248   LEnvironment* environment() const { return environment_; }
    249   bool HasEnvironment() const { return environment_ != NULL; }
    250 
    251   void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); }
    252   LPointerMap* pointer_map() const { return pointer_map_.get(); }
    253   bool HasPointerMap() const { return pointer_map_.is_set(); }
    254 
    255   // The 31 bits PositionBits is used to store the int position value. And the
    256   // position value may be RelocInfo::kNoPosition (-1). The accessor always
    257   // +1/-1 so that the encoded value of position in bit_field_ is always >= 0
    258   // and can fit into the 31 bits PositionBits.
    259   void set_position(int pos) {
    260     bit_field_ = PositionBits::update(bit_field_, pos + 1);
    261   }
    262   int position() { return PositionBits::decode(bit_field_) - 1; }
    263 
    264   void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
    265   HValue* hydrogen_value() const { return hydrogen_value_; }
    266 
    267   virtual void SetDeferredLazyDeoptimizationEnvironment(LEnvironment* env) { }
    268 
    269   void MarkAsCall() { bit_field_ = IsCallBits::update(bit_field_, true); }
    270   bool IsCall() const { return IsCallBits::decode(bit_field_); }
    271 
    272   // Interface to the register allocator and iterators.
    273   bool ClobbersTemps() const { return IsCall(); }
    274   bool ClobbersRegisters() const { return IsCall(); }
    275   virtual bool ClobbersDoubleRegisters() const {
    276     return IsCall() ||
    277       (!CpuFeatures::IsSupported(SSE2) &&
    278        // We only have rudimentary X87Stack tracking, thus in general
    279        // cannot handle deoptimization nor phi-nodes.
    280        (HasEnvironment() || IsControl()));
    281   }
    282 
    283   virtual bool HasResult() const = 0;
    284   virtual LOperand* result() const = 0;
    285 
    286   bool HasDoubleRegisterResult();
    287   bool HasDoubleRegisterInput();
    288   bool IsDoubleInput(X87Register reg, LCodeGen* cgen);
    289 
    290   LOperand* FirstInput() { return InputAt(0); }
    291   LOperand* Output() { return HasResult() ? result() : NULL; }
    292 
    293   virtual bool HasInterestingComment(LCodeGen* gen) const { return true; }
    294 
    295 #ifdef DEBUG
    296   void VerifyCall();
    297 #endif
    298 
    299  private:
    300   // Iterator support.
    301   friend class InputIterator;
    302   virtual int InputCount() = 0;
    303   virtual LOperand* InputAt(int i) = 0;
    304 
    305   friend class TempIterator;
    306   virtual int TempCount() = 0;
    307   virtual LOperand* TempAt(int i) = 0;
    308 
    309   class IsCallBits: public BitField<bool, 0, 1> {};
    310   class PositionBits: public BitField<int, 1, 31> {};
    311 
    312   LEnvironment* environment_;
    313   SetOncePointer<LPointerMap> pointer_map_;
    314   HValue* hydrogen_value_;
    315   int bit_field_;
    316 };
    317 
    318 
    319 // R = number of result operands (0 or 1).
    320 // I = number of input operands.
    321 // T = number of temporary operands.
    322 template<int R, int I, int T>
    323 class LTemplateInstruction: public LInstruction {
    324  public:
    325   // Allow 0 or 1 output operands.
    326   STATIC_ASSERT(R == 0 || R == 1);
    327   virtual bool HasResult() const { return R != 0 && result() != NULL; }
    328   void set_result(LOperand* operand) { results_[0] = operand; }
    329   LOperand* result() const { return results_[0]; }
    330 
    331  protected:
    332   EmbeddedContainer<LOperand*, R> results_;
    333   EmbeddedContainer<LOperand*, I> inputs_;
    334   EmbeddedContainer<LOperand*, T> temps_;
    335 
    336  private:
    337   // Iterator support.
    338   virtual int InputCount() { return I; }
    339   virtual LOperand* InputAt(int i) { return inputs_[i]; }
    340 
    341   virtual int TempCount() { return T; }
    342   virtual LOperand* TempAt(int i) { return temps_[i]; }
    343 };
    344 
    345 
    346 class LGap: public LTemplateInstruction<0, 0, 0> {
    347  public:
    348   explicit LGap(HBasicBlock* block) : block_(block) {
    349     parallel_moves_[BEFORE] = NULL;
    350     parallel_moves_[START] = NULL;
    351     parallel_moves_[END] = NULL;
    352     parallel_moves_[AFTER] = NULL;
    353   }
    354 
    355   // Can't use the DECLARE-macro here because of sub-classes.
    356   virtual bool IsGap() const { return true; }
    357   virtual void PrintDataTo(StringStream* stream);
    358   static LGap* cast(LInstruction* instr) {
    359     ASSERT(instr->IsGap());
    360     return reinterpret_cast<LGap*>(instr);
    361   }
    362 
    363   bool IsRedundant() const;
    364 
    365   HBasicBlock* block() const { return block_; }
    366 
    367   enum InnerPosition {
    368     BEFORE,
    369     START,
    370     END,
    371     AFTER,
    372     FIRST_INNER_POSITION = BEFORE,
    373     LAST_INNER_POSITION = AFTER
    374   };
    375 
    376   LParallelMove* GetOrCreateParallelMove(InnerPosition pos, Zone* zone)  {
    377     if (parallel_moves_[pos] == NULL) {
    378       parallel_moves_[pos] = new(zone) LParallelMove(zone);
    379     }
    380     return parallel_moves_[pos];
    381   }
    382 
    383   LParallelMove* GetParallelMove(InnerPosition pos)  {
    384     return parallel_moves_[pos];
    385   }
    386 
    387  private:
    388   LParallelMove* parallel_moves_[LAST_INNER_POSITION + 1];
    389   HBasicBlock* block_;
    390 };
    391 
    392 
    393 class LInstructionGap: public LGap {
    394  public:
    395   explicit LInstructionGap(HBasicBlock* block) : LGap(block) { }
    396 
    397   virtual bool HasInterestingComment(LCodeGen* gen) const {
    398     return !IsRedundant();
    399   }
    400 
    401   DECLARE_CONCRETE_INSTRUCTION(InstructionGap, "gap")
    402 };
    403 
    404 
    405 class LGoto: public LTemplateInstruction<0, 0, 0> {
    406  public:
    407   explicit LGoto(int block_id) : block_id_(block_id) { }
    408 
    409   virtual bool HasInterestingComment(LCodeGen* gen) const;
    410   DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
    411   virtual void PrintDataTo(StringStream* stream);
    412   virtual bool IsControl() const { return true; }
    413 
    414   int block_id() const { return block_id_; }
    415 
    416  private:
    417   int block_id_;
    418 };
    419 
    420 
    421 class LLazyBailout: public LTemplateInstruction<0, 0, 0> {
    422  public:
    423   DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout")
    424 };
    425 
    426 
    427 class LDummyUse: public LTemplateInstruction<1, 1, 0> {
    428  public:
    429   explicit LDummyUse(LOperand* value) {
    430     inputs_[0] = value;
    431   }
    432   DECLARE_CONCRETE_INSTRUCTION(DummyUse, "dummy-use")
    433 };
    434 
    435 
    436 class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
    437  public:
    438   DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
    439   DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
    440 };
    441 
    442 
    443 class LLabel: public LGap {
    444  public:
    445   explicit LLabel(HBasicBlock* block)
    446       : LGap(block), replacement_(NULL) { }
    447 
    448   virtual bool HasInterestingComment(LCodeGen* gen) const { return false; }
    449   DECLARE_CONCRETE_INSTRUCTION(Label, "label")
    450 
    451   virtual void PrintDataTo(StringStream* stream);
    452 
    453   int block_id() const { return block()->block_id(); }
    454   bool is_loop_header() const { return block()->IsLoopHeader(); }
    455   bool is_osr_entry() const { return block()->is_osr_entry(); }
    456   Label* label() { return &label_; }
    457   LLabel* replacement() const { return replacement_; }
    458   void set_replacement(LLabel* label) { replacement_ = label; }
    459   bool HasReplacement() const { return replacement_ != NULL; }
    460 
    461  private:
    462   Label label_;
    463   LLabel* replacement_;
    464 };
    465 
    466 
    467 class LParameter: public LTemplateInstruction<1, 0, 0> {
    468  public:
    469   virtual bool HasInterestingComment(LCodeGen* gen) const { return false; }
    470   DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
    471 };
    472 
    473 
    474 class LCallStub: public LTemplateInstruction<1, 1, 0> {
    475  public:
    476   explicit LCallStub(LOperand* context) {
    477     inputs_[0] = context;
    478   }
    479 
    480   LOperand* context() { return inputs_[0]; }
    481 
    482   DECLARE_CONCRETE_INSTRUCTION(CallStub, "call-stub")
    483   DECLARE_HYDROGEN_ACCESSOR(CallStub)
    484 
    485   TranscendentalCache::Type transcendental_type() {
    486     return hydrogen()->transcendental_type();
    487   }
    488 };
    489 
    490 
    491 class LUnknownOSRValue: public LTemplateInstruction<1, 0, 0> {
    492  public:
    493   virtual bool HasInterestingComment(LCodeGen* gen) const { return false; }
    494   DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value")
    495 };
    496 
    497 
    498 template<int I, int T>
    499 class LControlInstruction: public LTemplateInstruction<0, I, T> {
    500  public:
    501   LControlInstruction() : false_label_(NULL), true_label_(NULL) { }
    502 
    503   virtual bool IsControl() const { return true; }
    504 
    505   int SuccessorCount() { return hydrogen()->SuccessorCount(); }
    506   HBasicBlock* SuccessorAt(int i) { return hydrogen()->SuccessorAt(i); }
    507 
    508   int TrueDestination(LChunk* chunk) {
    509     return chunk->LookupDestination(true_block_id());
    510   }
    511   int FalseDestination(LChunk* chunk) {
    512     return chunk->LookupDestination(false_block_id());
    513   }
    514 
    515   Label* TrueLabel(LChunk* chunk) {
    516     if (true_label_ == NULL) {
    517       true_label_ = chunk->GetAssemblyLabel(TrueDestination(chunk));
    518     }
    519     return true_label_;
    520   }
    521   Label* FalseLabel(LChunk* chunk) {
    522     if (false_label_ == NULL) {
    523       false_label_ = chunk->GetAssemblyLabel(FalseDestination(chunk));
    524     }
    525     return false_label_;
    526   }
    527 
    528  protected:
    529   int true_block_id() { return SuccessorAt(0)->block_id(); }
    530   int false_block_id() { return SuccessorAt(1)->block_id(); }
    531 
    532  private:
    533   HControlInstruction* hydrogen() {
    534     return HControlInstruction::cast(this->hydrogen_value());
    535   }
    536 
    537   Label* false_label_;
    538   Label* true_label_;
    539 };
    540 
    541 
    542 class LWrapReceiver: public LTemplateInstruction<1, 2, 1> {
    543  public:
    544   LWrapReceiver(LOperand* receiver,
    545                 LOperand* function,
    546                 LOperand* temp) {
    547     inputs_[0] = receiver;
    548     inputs_[1] = function;
    549     temps_[0] = temp;
    550   }
    551 
    552   LOperand* receiver() { return inputs_[0]; }
    553   LOperand* function() { return inputs_[1]; }
    554   LOperand* temp() { return temps_[0]; }
    555 
    556   DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
    557 };
    558 
    559 
    560 class LApplyArguments: public LTemplateInstruction<1, 4, 0> {
    561  public:
    562   LApplyArguments(LOperand* function,
    563                   LOperand* receiver,
    564                   LOperand* length,
    565                   LOperand* elements) {
    566     inputs_[0] = function;
    567     inputs_[1] = receiver;
    568     inputs_[2] = length;
    569     inputs_[3] = elements;
    570   }
    571 
    572   LOperand* function() { return inputs_[0]; }
    573   LOperand* receiver() { return inputs_[1]; }
    574   LOperand* length() { return inputs_[2]; }
    575   LOperand* elements() { return inputs_[3]; }
    576 
    577   DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply-arguments")
    578 };
    579 
    580 
    581 class LAccessArgumentsAt: public LTemplateInstruction<1, 3, 0> {
    582  public:
    583   LAccessArgumentsAt(LOperand* arguments, LOperand* length, LOperand* index) {
    584     inputs_[0] = arguments;
    585     inputs_[1] = length;
    586     inputs_[2] = index;
    587   }
    588 
    589   LOperand* arguments() { return inputs_[0]; }
    590   LOperand* length() { return inputs_[1]; }
    591   LOperand* index() { return inputs_[2]; }
    592 
    593   DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at")
    594 
    595   virtual void PrintDataTo(StringStream* stream);
    596 };
    597 
    598 
    599 class LArgumentsLength: public LTemplateInstruction<1, 1, 0> {
    600  public:
    601   explicit LArgumentsLength(LOperand* elements) {
    602     inputs_[0] = elements;
    603   }
    604 
    605   LOperand* elements() { return inputs_[0]; }
    606 
    607   DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments-length")
    608 };
    609 
    610 
    611 class LArgumentsElements: public LTemplateInstruction<1, 0, 0> {
    612  public:
    613   DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments-elements")
    614   DECLARE_HYDROGEN_ACCESSOR(ArgumentsElements)
    615 };
    616 
    617 
    618 class LDebugBreak: public LTemplateInstruction<0, 0, 0> {
    619  public:
    620   DECLARE_CONCRETE_INSTRUCTION(DebugBreak, "break")
    621 };
    622 
    623 
    624 class LModI: public LTemplateInstruction<1, 2, 1> {
    625  public:
    626   LModI(LOperand* left, LOperand* right, LOperand* temp) {
    627     inputs_[0] = left;
    628     inputs_[1] = right;
    629     temps_[0] = temp;
    630   }
    631 
    632   LOperand* left() { return inputs_[0]; }
    633   LOperand* right() { return inputs_[1]; }
    634   LOperand* temp() { return temps_[0]; }
    635 
    636   DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i")
    637   DECLARE_HYDROGEN_ACCESSOR(Mod)
    638 };
    639 
    640 
    641 class LDivI: public LTemplateInstruction<1, 2, 1> {
    642  public:
    643   LDivI(LOperand* left, LOperand* right, LOperand* temp) {
    644     inputs_[0] = left;
    645     inputs_[1] = right;
    646     temps_[0] = temp;
    647   }
    648 
    649   LOperand* left() { return inputs_[0]; }
    650   LOperand* right() { return inputs_[1]; }
    651 
    652   bool is_flooring() { return hydrogen_value()->IsMathFloorOfDiv(); }
    653 
    654   DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
    655   DECLARE_HYDROGEN_ACCESSOR(Div)
    656 };
    657 
    658 
    659 class LMathFloorOfDiv: public LTemplateInstruction<1, 2, 1> {
    660  public:
    661   LMathFloorOfDiv(LOperand* left,
    662                   LOperand* right,
    663                   LOperand* temp = NULL) {
    664     inputs_[0] = left;
    665     inputs_[1] = right;
    666     temps_[0] = temp;
    667   }
    668 
    669   LOperand* left() { return inputs_[0]; }
    670   LOperand* right() { return inputs_[1]; }
    671   LOperand* temp() { return temps_[0]; }
    672 
    673   DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv, "math-floor-of-div")
    674   DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
    675 };
    676 
    677 
    678 class LMulI: public LTemplateInstruction<1, 2, 1> {
    679  public:
    680   LMulI(LOperand* left, LOperand* right, LOperand* temp) {
    681     inputs_[0] = left;
    682     inputs_[1] = right;
    683     temps_[0] = temp;
    684   }
    685 
    686   LOperand* left() { return inputs_[0]; }
    687   LOperand* right() { return inputs_[1]; }
    688   LOperand* temp() { return temps_[0]; }
    689 
    690   DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i")
    691   DECLARE_HYDROGEN_ACCESSOR(Mul)
    692 };
    693 
    694 
    695 class LCompareNumericAndBranch: public LControlInstruction<2, 0> {
    696  public:
    697   LCompareNumericAndBranch(LOperand* left, LOperand* right) {
    698     inputs_[0] = left;
    699     inputs_[1] = right;
    700   }
    701 
    702   LOperand* left() { return inputs_[0]; }
    703   LOperand* right() { return inputs_[1]; }
    704 
    705   DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch,
    706                                "compare-numeric-and-branch")
    707   DECLARE_HYDROGEN_ACCESSOR(CompareNumericAndBranch)
    708 
    709   Token::Value op() const { return hydrogen()->token(); }
    710   bool is_double() const {
    711     return hydrogen()->representation().IsDouble();
    712   }
    713 
    714   virtual void PrintDataTo(StringStream* stream);
    715 };
    716 
    717 
    718 class LMathFloor: public LTemplateInstruction<1, 1, 0> {
    719  public:
    720   explicit LMathFloor(LOperand* value) {
    721     inputs_[0] = value;
    722   }
    723 
    724   LOperand* value() { return inputs_[0]; }
    725 
    726   DECLARE_CONCRETE_INSTRUCTION(MathFloor, "math-floor")
    727   DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
    728 };
    729 
    730 
    731 class LMathRound: public LTemplateInstruction<1, 2, 1> {
    732  public:
    733   LMathRound(LOperand* context, LOperand* value, LOperand* temp) {
    734     inputs_[1] = context;
    735     inputs_[0] = value;
    736     temps_[0] = temp;
    737   }
    738 
    739   LOperand* context() { return inputs_[1]; }
    740   LOperand* value() { return inputs_[0]; }
    741   LOperand* temp() { return temps_[0]; }
    742 
    743   DECLARE_CONCRETE_INSTRUCTION(MathRound, "math-round")
    744   DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
    745 };
    746 
    747 
    748 class LMathAbs: public LTemplateInstruction<1, 2, 0> {
    749  public:
    750   LMathAbs(LOperand* context, LOperand* value) {
    751     inputs_[1] = context;
    752     inputs_[0] = value;
    753   }
    754 
    755   LOperand* context() { return inputs_[1]; }
    756   LOperand* value() { return inputs_[0]; }
    757 
    758   DECLARE_CONCRETE_INSTRUCTION(MathAbs, "math-abs")
    759   DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
    760 };
    761 
    762 
    763 class LMathLog: public LTemplateInstruction<1, 1, 0> {
    764  public:
    765   explicit LMathLog(LOperand* value) {
    766     inputs_[0] = value;
    767   }
    768 
    769   LOperand* value() { return inputs_[0]; }
    770 
    771   DECLARE_CONCRETE_INSTRUCTION(MathLog, "math-log")
    772 };
    773 
    774 
    775 class LMathSin: public LTemplateInstruction<1, 1, 0> {
    776  public:
    777   explicit LMathSin(LOperand* value) {
    778     inputs_[0] = value;
    779   }
    780 
    781   LOperand* value() { return inputs_[0]; }
    782 
    783   DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin")
    784 };
    785 
    786 
    787 class LMathCos: public LTemplateInstruction<1, 1, 0> {
    788  public:
    789   explicit LMathCos(LOperand* value) {
    790     inputs_[0] = value;
    791   }
    792 
    793   LOperand* value() { return inputs_[0]; }
    794 
    795   DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos")
    796 };
    797 
    798 
    799 class LMathTan: public LTemplateInstruction<1, 1, 0> {
    800  public:
    801   explicit LMathTan(LOperand* value) {
    802     inputs_[0] = value;
    803   }
    804 
    805   LOperand* value() { return inputs_[0]; }
    806 
    807   DECLARE_CONCRETE_INSTRUCTION(MathTan, "math-tan")
    808 };
    809 
    810 
    811 class LMathExp: public LTemplateInstruction<1, 1, 2> {
    812  public:
    813   LMathExp(LOperand* value,
    814            LOperand* temp1,
    815            LOperand* temp2) {
    816     inputs_[0] = value;
    817     temps_[0] = temp1;
    818     temps_[1] = temp2;
    819     ExternalReference::InitializeMathExpData();
    820   }
    821 
    822   LOperand* value() { return inputs_[0]; }
    823   LOperand* temp1() { return temps_[0]; }
    824   LOperand* temp2() { return temps_[1]; }
    825 
    826   DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
    827 };
    828 
    829 
    830 class LMathSqrt: public LTemplateInstruction<1, 1, 0> {
    831  public:
    832   explicit LMathSqrt(LOperand* value) {
    833     inputs_[0] = value;
    834   }
    835 
    836   LOperand* value() { return inputs_[0]; }
    837 
    838   DECLARE_CONCRETE_INSTRUCTION(MathSqrt, "math-sqrt")
    839 };
    840 
    841 
    842 class LMathPowHalf: public LTemplateInstruction<1, 2, 1> {
    843  public:
    844   LMathPowHalf(LOperand* context, LOperand* value, LOperand* temp) {
    845     inputs_[1] = context;
    846     inputs_[0] = value;
    847     temps_[0] = temp;
    848   }
    849 
    850   LOperand* context() { return inputs_[1]; }
    851   LOperand* value() { return inputs_[0]; }
    852   LOperand* temp() { return temps_[0]; }
    853 
    854   DECLARE_CONCRETE_INSTRUCTION(MathPowHalf, "math-pow-half")
    855 };
    856 
    857 
    858 class LCmpObjectEqAndBranch: public LControlInstruction<2, 0> {
    859  public:
    860   LCmpObjectEqAndBranch(LOperand* left, LOperand* right) {
    861     inputs_[0] = left;
    862     inputs_[1] = right;
    863   }
    864 
    865   LOperand* left() { return inputs_[0]; }
    866   LOperand* right() { return inputs_[1]; }
    867 
    868   DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch, "cmp-object-eq-and-branch")
    869 };
    870 
    871 
    872 class LCmpHoleAndBranch: public LControlInstruction<1, 0> {
    873  public:
    874   explicit LCmpHoleAndBranch(LOperand* object) {
    875     inputs_[0] = object;
    876   }
    877 
    878   LOperand* object() { return inputs_[0]; }
    879 
    880   DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranch, "cmp-hole-and-branch")
    881   DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch)
    882 };
    883 
    884 
    885 class LIsObjectAndBranch: public LControlInstruction<1, 1> {
    886  public:
    887   LIsObjectAndBranch(LOperand* value, LOperand* temp) {
    888     inputs_[0] = value;
    889     temps_[0] = temp;
    890   }
    891 
    892   LOperand* value() { return inputs_[0]; }
    893   LOperand* temp() { return temps_[0]; }
    894 
    895   DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
    896 
    897   virtual void PrintDataTo(StringStream* stream);
    898 };
    899 
    900 
    901 class LIsNumberAndBranch: public LControlInstruction<1, 0> {
    902  public:
    903   explicit LIsNumberAndBranch(LOperand* value) {
    904     inputs_[0] = value;
    905   }
    906 
    907   LOperand* value() { return inputs_[0]; }
    908 
    909   DECLARE_CONCRETE_INSTRUCTION(IsNumberAndBranch, "is-number-and-branch")
    910   DECLARE_HYDROGEN_ACCESSOR(IsNumberAndBranch)
    911 };
    912 
    913 
    914 class LIsStringAndBranch: public LControlInstruction<1, 1> {
    915  public:
    916   LIsStringAndBranch(LOperand* value, LOperand* temp) {
    917     inputs_[0] = value;
    918     temps_[0] = temp;
    919   }
    920 
    921   LOperand* value() { return inputs_[0]; }
    922   LOperand* temp() { return temps_[0]; }
    923 
    924   DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch")
    925   DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch)
    926 
    927   virtual void PrintDataTo(StringStream* stream);
    928 };
    929 
    930 
    931 class LIsSmiAndBranch: public LControlInstruction<1, 0> {
    932  public:
    933   explicit LIsSmiAndBranch(LOperand* value) {
    934     inputs_[0] = value;
    935   }
    936 
    937   LOperand* value() { return inputs_[0]; }
    938 
    939   DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch")
    940   DECLARE_HYDROGEN_ACCESSOR(IsSmiAndBranch)
    941 
    942   virtual void PrintDataTo(StringStream* stream);
    943 };
    944 
    945 
    946 class LIsUndetectableAndBranch: public LControlInstruction<1, 1> {
    947  public:
    948   LIsUndetectableAndBranch(LOperand* value, LOperand* temp) {
    949     inputs_[0] = value;
    950     temps_[0] = temp;
    951   }
    952 
    953   LOperand* value() { return inputs_[0]; }
    954   LOperand* temp() { return temps_[0]; }
    955 
    956   DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch,
    957                                "is-undetectable-and-branch")
    958   DECLARE_HYDROGEN_ACCESSOR(IsUndetectableAndBranch)
    959 
    960   virtual void PrintDataTo(StringStream* stream);
    961 };
    962 
    963 
    964 class LStringCompareAndBranch: public LControlInstruction<3, 0> {
    965  public:
    966   LStringCompareAndBranch(LOperand* context, LOperand* left, LOperand* right) {
    967     inputs_[0] = context;
    968     inputs_[1] = left;
    969     inputs_[2] = right;
    970   }
    971 
    972   LOperand* left() { return inputs_[1]; }
    973   LOperand* right() { return inputs_[2]; }
    974 
    975   DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch,
    976                                "string-compare-and-branch")
    977   DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch)
    978 
    979   virtual void PrintDataTo(StringStream* stream);
    980 
    981   Token::Value op() const { return hydrogen()->token(); }
    982 };
    983 
    984 
    985 class LHasInstanceTypeAndBranch: public LControlInstruction<1, 1> {
    986  public:
    987   LHasInstanceTypeAndBranch(LOperand* value, LOperand* temp) {
    988     inputs_[0] = value;
    989     temps_[0] = temp;
    990   }
    991 
    992   LOperand* value() { return inputs_[0]; }
    993   LOperand* temp() { return temps_[0]; }
    994 
    995   DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch,
    996                                "has-instance-type-and-branch")
    997   DECLARE_HYDROGEN_ACCESSOR(HasInstanceTypeAndBranch)
    998 
    999   virtual void PrintDataTo(StringStream* stream);
   1000 };
   1001 
   1002 
   1003 class LGetCachedArrayIndex: public LTemplateInstruction<1, 1, 0> {
   1004  public:
   1005   explicit LGetCachedArrayIndex(LOperand* value) {
   1006     inputs_[0] = value;
   1007   }
   1008 
   1009   LOperand* value() { return inputs_[0]; }
   1010 
   1011   DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get-cached-array-index")
   1012   DECLARE_HYDROGEN_ACCESSOR(GetCachedArrayIndex)
   1013 };
   1014 
   1015 
   1016 class LHasCachedArrayIndexAndBranch: public LControlInstruction<1, 0> {
   1017  public:
   1018   explicit LHasCachedArrayIndexAndBranch(LOperand* value) {
   1019     inputs_[0] = value;
   1020   }
   1021 
   1022   LOperand* value() { return inputs_[0]; }
   1023 
   1024   DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch,
   1025                                "has-cached-array-index-and-branch")
   1026 
   1027   virtual void PrintDataTo(StringStream* stream);
   1028 };
   1029 
   1030 
   1031 class LIsConstructCallAndBranch: public LControlInstruction<0, 1> {
   1032  public:
   1033   explicit LIsConstructCallAndBranch(LOperand* temp) {
   1034     temps_[0] = temp;
   1035   }
   1036 
   1037   LOperand* temp() { return temps_[0]; }
   1038 
   1039   DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch,
   1040                                "is-construct-call-and-branch")
   1041 };
   1042 
   1043 
   1044 class LClassOfTestAndBranch: public LControlInstruction<1, 2> {
   1045  public:
   1046   LClassOfTestAndBranch(LOperand* value, LOperand* temp, LOperand* temp2) {
   1047     inputs_[0] = value;
   1048     temps_[0] = temp;
   1049     temps_[1] = temp2;
   1050   }
   1051 
   1052   LOperand* value() { return inputs_[0]; }
   1053   LOperand* temp() { return temps_[0]; }
   1054   LOperand* temp2() { return temps_[1]; }
   1055 
   1056   DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch,
   1057                                "class-of-test-and-branch")
   1058   DECLARE_HYDROGEN_ACCESSOR(ClassOfTestAndBranch)
   1059 
   1060   virtual void PrintDataTo(StringStream* stream);
   1061 };
   1062 
   1063 
   1064 class LCmpT: public LTemplateInstruction<1, 3, 0> {
   1065  public:
   1066   LCmpT(LOperand* context, LOperand* left, LOperand* right) {
   1067     inputs_[0] = context;
   1068     inputs_[1] = left;
   1069     inputs_[2] = right;
   1070   }
   1071 
   1072   DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t")
   1073   DECLARE_HYDROGEN_ACCESSOR(CompareGeneric)
   1074 
   1075   Token::Value op() const { return hydrogen()->token(); }
   1076 };
   1077 
   1078 
   1079 class LInstanceOf: public LTemplateInstruction<1, 3, 0> {
   1080  public:
   1081   LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
   1082     inputs_[0] = context;
   1083     inputs_[1] = left;
   1084     inputs_[2] = right;
   1085   }
   1086 
   1087   LOperand* context() { return inputs_[0]; }
   1088 
   1089   DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
   1090 };
   1091 
   1092 
   1093 class LInstanceOfKnownGlobal: public LTemplateInstruction<1, 2, 1> {
   1094  public:
   1095   LInstanceOfKnownGlobal(LOperand* context, LOperand* value, LOperand* temp) {
   1096     inputs_[0] = context;
   1097     inputs_[1] = value;
   1098     temps_[0] = temp;
   1099   }
   1100 
   1101   LOperand* value() { return inputs_[1]; }
   1102   LOperand* temp() { return temps_[0]; }
   1103 
   1104   DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
   1105                                "instance-of-known-global")
   1106   DECLARE_HYDROGEN_ACCESSOR(InstanceOfKnownGlobal)
   1107 
   1108   Handle<JSFunction> function() const { return hydrogen()->function(); }
   1109   LEnvironment* GetDeferredLazyDeoptimizationEnvironment() {
   1110     return lazy_deopt_env_;
   1111   }
   1112   virtual void SetDeferredLazyDeoptimizationEnvironment(LEnvironment* env) {
   1113     lazy_deopt_env_ = env;
   1114   }
   1115 
   1116  private:
   1117   LEnvironment* lazy_deopt_env_;
   1118 };
   1119 
   1120 
   1121 class LInstanceSize: public LTemplateInstruction<1, 1, 0> {
   1122  public:
   1123   explicit LInstanceSize(LOperand* object) {
   1124     inputs_[0] = object;
   1125   }
   1126 
   1127   LOperand* object() { return inputs_[0]; }
   1128 
   1129   DECLARE_CONCRETE_INSTRUCTION(InstanceSize, "instance-size")
   1130   DECLARE_HYDROGEN_ACCESSOR(InstanceSize)
   1131 };
   1132 
   1133 
   1134 class LBoundsCheck: public LTemplateInstruction<0, 2, 0> {
   1135  public:
   1136   LBoundsCheck(LOperand* index, LOperand* length) {
   1137     inputs_[0] = index;
   1138     inputs_[1] = length;
   1139   }
   1140 
   1141   LOperand* index() { return inputs_[0]; }
   1142   LOperand* length() { return inputs_[1]; }
   1143 
   1144   DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
   1145   DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
   1146 };
   1147 
   1148 
   1149 class LBitI: public LTemplateInstruction<1, 2, 0> {
   1150  public:
   1151   LBitI(LOperand* left, LOperand* right) {
   1152     inputs_[0] = left;
   1153     inputs_[1] = right;
   1154   }
   1155 
   1156   LOperand* left() { return inputs_[0]; }
   1157   LOperand* right() { return inputs_[1]; }
   1158 
   1159   DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i")
   1160   DECLARE_HYDROGEN_ACCESSOR(Bitwise)
   1161 
   1162   Token::Value op() const { return hydrogen()->op(); }
   1163 };
   1164 
   1165 
   1166 class LShiftI: public LTemplateInstruction<1, 2, 0> {
   1167  public:
   1168   LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
   1169       : op_(op), can_deopt_(can_deopt) {
   1170     inputs_[0] = left;
   1171     inputs_[1] = right;
   1172   }
   1173 
   1174   LOperand* left() { return inputs_[0]; }
   1175   LOperand* right() { return inputs_[1]; }
   1176 
   1177   DECLARE_CONCRETE_INSTRUCTION(ShiftI, "shift-i")
   1178 
   1179   Token::Value op() const { return op_; }
   1180   bool can_deopt() const { return can_deopt_; }
   1181 
   1182  private:
   1183   Token::Value op_;
   1184   bool can_deopt_;
   1185 };
   1186 
   1187 
   1188 class LSubI: public LTemplateInstruction<1, 2, 0> {
   1189  public:
   1190   LSubI(LOperand* left, LOperand* right) {
   1191     inputs_[0] = left;
   1192     inputs_[1] = right;
   1193   }
   1194 
   1195   LOperand* left() { return inputs_[0]; }
   1196   LOperand* right() { return inputs_[1]; }
   1197 
   1198   DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i")
   1199   DECLARE_HYDROGEN_ACCESSOR(Sub)
   1200 };
   1201 
   1202 
   1203 class LConstantI: public LTemplateInstruction<1, 0, 0> {
   1204  public:
   1205   DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i")
   1206   DECLARE_HYDROGEN_ACCESSOR(Constant)
   1207 
   1208   int32_t value() const { return hydrogen()->Integer32Value(); }
   1209 };
   1210 
   1211 
   1212 class LConstantS: public LTemplateInstruction<1, 0, 0> {
   1213  public:
   1214   DECLARE_CONCRETE_INSTRUCTION(ConstantS, "constant-s")
   1215   DECLARE_HYDROGEN_ACCESSOR(Constant)
   1216 
   1217   Smi* value() const { return Smi::FromInt(hydrogen()->Integer32Value()); }
   1218 };
   1219 
   1220 
   1221 class LConstantD: public LTemplateInstruction<1, 0, 1> {
   1222  public:
   1223   explicit LConstantD(LOperand* temp) {
   1224     temps_[0] = temp;
   1225   }
   1226 
   1227   LOperand* temp() { return temps_[0]; }
   1228 
   1229   DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
   1230   DECLARE_HYDROGEN_ACCESSOR(Constant)
   1231 
   1232   double value() const { return hydrogen()->DoubleValue(); }
   1233 };
   1234 
   1235 
   1236 class LConstantE: public LTemplateInstruction<1, 0, 0> {
   1237  public:
   1238   DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e")
   1239   DECLARE_HYDROGEN_ACCESSOR(Constant)
   1240 
   1241   ExternalReference value() const {
   1242     return hydrogen()->ExternalReferenceValue();
   1243   }
   1244 };
   1245 
   1246 
   1247 class LConstantT: public LTemplateInstruction<1, 0, 0> {
   1248  public:
   1249   DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
   1250   DECLARE_HYDROGEN_ACCESSOR(Constant)
   1251 
   1252   Handle<Object> value() const { return hydrogen()->handle(); }
   1253 };
   1254 
   1255 
   1256 class LBranch: public LControlInstruction<1, 1> {
   1257  public:
   1258   LBranch(LOperand* value, LOperand* temp) {
   1259     inputs_[0] = value;
   1260     temps_[0] = temp;
   1261   }
   1262 
   1263   LOperand* value() { return inputs_[0]; }
   1264   LOperand* temp() { return temps_[0]; }
   1265 
   1266   DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
   1267   DECLARE_HYDROGEN_ACCESSOR(Branch)
   1268 
   1269   virtual void PrintDataTo(StringStream* stream);
   1270 };
   1271 
   1272 
   1273 class LCmpMapAndBranch: public LControlInstruction<1, 0> {
   1274  public:
   1275   explicit LCmpMapAndBranch(LOperand* value) {
   1276     inputs_[0] = value;
   1277   }
   1278 
   1279   LOperand* value() { return inputs_[0]; }
   1280 
   1281   DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
   1282   DECLARE_HYDROGEN_ACCESSOR(CompareMap)
   1283 
   1284   Handle<Map> map() const { return hydrogen()->map(); }
   1285 };
   1286 
   1287 
   1288 class LMapEnumLength: public LTemplateInstruction<1, 1, 0> {
   1289  public:
   1290   explicit LMapEnumLength(LOperand* value) {
   1291     inputs_[0] = value;
   1292   }
   1293 
   1294   LOperand* value() { return inputs_[0]; }
   1295 
   1296   DECLARE_CONCRETE_INSTRUCTION(MapEnumLength, "map-enum-length")
   1297 };
   1298 
   1299 
   1300 class LElementsKind: public LTemplateInstruction<1, 1, 0> {
   1301  public:
   1302   explicit LElementsKind(LOperand* value) {
   1303     inputs_[0] = value;
   1304   }
   1305 
   1306   LOperand* value() { return inputs_[0]; }
   1307 
   1308   DECLARE_CONCRETE_INSTRUCTION(ElementsKind, "elements-kind")
   1309   DECLARE_HYDROGEN_ACCESSOR(ElementsKind)
   1310 };
   1311 
   1312 
   1313 class LValueOf: public LTemplateInstruction<1, 1, 1> {
   1314  public:
   1315   LValueOf(LOperand* value, LOperand* temp) {
   1316     inputs_[0] = value;
   1317     temps_[0] = temp;
   1318   }
   1319 
   1320   LOperand* value() { return inputs_[0]; }
   1321   LOperand* temp() { return temps_[0]; }
   1322 
   1323   DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value-of")
   1324   DECLARE_HYDROGEN_ACCESSOR(ValueOf)
   1325 };
   1326 
   1327 
   1328 class LDateField: public LTemplateInstruction<1, 1, 1> {
   1329  public:
   1330   LDateField(LOperand* date, LOperand* temp, Smi* index)
   1331       : index_(index) {
   1332     inputs_[0] = date;
   1333     temps_[0] = temp;
   1334   }
   1335 
   1336   LOperand* date() { return inputs_[0]; }
   1337   LOperand* temp() { return temps_[0]; }
   1338 
   1339   DECLARE_CONCRETE_INSTRUCTION(DateField, "date-field")
   1340   DECLARE_HYDROGEN_ACCESSOR(DateField)
   1341 
   1342   Smi* index() const { return index_; }
   1343 
   1344  private:
   1345   Smi* index_;
   1346 };
   1347 
   1348 
   1349 class LSeqStringSetChar: public LTemplateInstruction<1, 3, 0> {
   1350  public:
   1351   LSeqStringSetChar(String::Encoding encoding,
   1352                     LOperand* string,
   1353                     LOperand* index,
   1354                     LOperand* value) : encoding_(encoding) {
   1355     inputs_[0] = string;
   1356     inputs_[1] = index;
   1357     inputs_[2] = value;
   1358   }
   1359 
   1360   String::Encoding encoding() { return encoding_; }
   1361   LOperand* string() { return inputs_[0]; }
   1362   LOperand* index() { return inputs_[1]; }
   1363   LOperand* value() { return inputs_[2]; }
   1364 
   1365   DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char")
   1366   DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar)
   1367 
   1368  private:
   1369   String::Encoding encoding_;
   1370 };
   1371 
   1372 
   1373 class LThrow: public LTemplateInstruction<0, 2, 0> {
   1374  public:
   1375   LThrow(LOperand* context, LOperand* value) {
   1376     inputs_[0] = context;
   1377     inputs_[1] = value;
   1378   }
   1379 
   1380   LOperand* context() { return inputs_[0]; }
   1381   LOperand* value() { return inputs_[1]; }
   1382 
   1383   DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
   1384 };
   1385 
   1386 
   1387 class LAddI: public LTemplateInstruction<1, 2, 0> {
   1388  public:
   1389   LAddI(LOperand* left, LOperand* right) {
   1390     inputs_[0] = left;
   1391     inputs_[1] = right;
   1392   }
   1393 
   1394   LOperand* left() { return inputs_[0]; }
   1395   LOperand* right() { return inputs_[1]; }
   1396 
   1397   static bool UseLea(HAdd* add) {
   1398     return !add->CheckFlag(HValue::kCanOverflow) &&
   1399         add->BetterLeftOperand()->UseCount() > 1;
   1400   }
   1401 
   1402   DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i")
   1403   DECLARE_HYDROGEN_ACCESSOR(Add)
   1404 };
   1405 
   1406 
   1407 class LMathMinMax: public LTemplateInstruction<1, 2, 0> {
   1408  public:
   1409   LMathMinMax(LOperand* left, LOperand* right) {
   1410     inputs_[0] = left;
   1411     inputs_[1] = right;
   1412   }
   1413 
   1414   LOperand* left() { return inputs_[0]; }
   1415   LOperand* right() { return inputs_[1]; }
   1416 
   1417   DECLARE_CONCRETE_INSTRUCTION(MathMinMax, "math-min-max")
   1418   DECLARE_HYDROGEN_ACCESSOR(MathMinMax)
   1419 };
   1420 
   1421 
   1422 class LPower: public LTemplateInstruction<1, 2, 0> {
   1423  public:
   1424   LPower(LOperand* left, LOperand* right) {
   1425     inputs_[0] = left;
   1426     inputs_[1] = right;
   1427   }
   1428 
   1429   LOperand* left() { return inputs_[0]; }
   1430   LOperand* right() { return inputs_[1]; }
   1431 
   1432   DECLARE_CONCRETE_INSTRUCTION(Power, "power")
   1433   DECLARE_HYDROGEN_ACCESSOR(Power)
   1434 };
   1435 
   1436 
   1437 class LRandom: public LTemplateInstruction<1, 1, 0> {
   1438  public:
   1439   explicit LRandom(LOperand* global_object) {
   1440     inputs_[0] = global_object;
   1441   }
   1442 
   1443   LOperand* global_object() { return inputs_[0]; }
   1444 
   1445   DECLARE_CONCRETE_INSTRUCTION(Random, "random")
   1446   DECLARE_HYDROGEN_ACCESSOR(Random)
   1447 };
   1448 
   1449 
   1450 class LArithmeticD: public LTemplateInstruction<1, 2, 0> {
   1451  public:
   1452   LArithmeticD(Token::Value op, LOperand* left, LOperand* right)
   1453       : op_(op) {
   1454     inputs_[0] = left;
   1455     inputs_[1] = right;
   1456   }
   1457 
   1458   LOperand* left() { return inputs_[0]; }
   1459   LOperand* right() { return inputs_[1]; }
   1460 
   1461   Token::Value op() const { return op_; }
   1462 
   1463   virtual Opcode opcode() const { return LInstruction::kArithmeticD; }
   1464   virtual void CompileToNative(LCodeGen* generator);
   1465   virtual const char* Mnemonic() const;
   1466 
   1467  private:
   1468   Token::Value op_;
   1469 };
   1470 
   1471 
   1472 class LArithmeticT: public LTemplateInstruction<1, 3, 0> {
   1473  public:
   1474   LArithmeticT(Token::Value op,
   1475                LOperand* context,
   1476                LOperand* left,
   1477                LOperand* right)
   1478       : op_(op) {
   1479     inputs_[0] = context;
   1480     inputs_[1] = left;
   1481     inputs_[2] = right;
   1482   }
   1483 
   1484   LOperand* context() { return inputs_[0]; }
   1485   LOperand* left() { return inputs_[1]; }
   1486   LOperand* right() { return inputs_[2]; }
   1487 
   1488   virtual Opcode opcode() const { return LInstruction::kArithmeticT; }
   1489   virtual void CompileToNative(LCodeGen* generator);
   1490   virtual const char* Mnemonic() const;
   1491 
   1492   Token::Value op() const { return op_; }
   1493 
   1494  private:
   1495   Token::Value op_;
   1496 };
   1497 
   1498 
   1499 class LReturn: public LTemplateInstruction<0, 3, 0> {
   1500  public:
   1501   explicit LReturn(LOperand* value, LOperand* context,
   1502                    LOperand* parameter_count) {
   1503     inputs_[0] = value;
   1504     inputs_[1] = context;
   1505     inputs_[2] = parameter_count;
   1506   }
   1507 
   1508   bool has_constant_parameter_count() {
   1509     return parameter_count()->IsConstantOperand();
   1510   }
   1511   LConstantOperand* constant_parameter_count() {
   1512     ASSERT(has_constant_parameter_count());
   1513     return LConstantOperand::cast(parameter_count());
   1514   }
   1515   LOperand* parameter_count() { return inputs_[2]; }
   1516 
   1517   DECLARE_CONCRETE_INSTRUCTION(Return, "return")
   1518   DECLARE_HYDROGEN_ACCESSOR(Return)
   1519 };
   1520 
   1521 
   1522 class LLoadNamedField: public LTemplateInstruction<1, 1, 0> {
   1523  public:
   1524   explicit LLoadNamedField(LOperand* object) {
   1525     inputs_[0] = object;
   1526   }
   1527 
   1528   virtual bool ClobbersDoubleRegisters() const {
   1529     return !CpuFeatures::IsSupported(SSE2) &&
   1530         !hydrogen()->representation().IsDouble();
   1531   }
   1532 
   1533   LOperand* object() { return inputs_[0]; }
   1534 
   1535   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field")
   1536   DECLARE_HYDROGEN_ACCESSOR(LoadNamedField)
   1537 };
   1538 
   1539 
   1540 class LLoadNamedGeneric: public LTemplateInstruction<1, 2, 0> {
   1541  public:
   1542   LLoadNamedGeneric(LOperand* context, LOperand* object) {
   1543     inputs_[0] = context;
   1544     inputs_[1] = object;
   1545   }
   1546 
   1547   LOperand* context() { return inputs_[0]; }
   1548   LOperand* object() { return inputs_[1]; }
   1549 
   1550   DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic")
   1551   DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric)
   1552 
   1553   Handle<Object> name() const { return hydrogen()->name(); }
   1554 };
   1555 
   1556 
   1557 class LLoadFunctionPrototype: public LTemplateInstruction<1, 1, 1> {
   1558  public:
   1559   LLoadFunctionPrototype(LOperand* function, LOperand* temp) {
   1560     inputs_[0] = function;
   1561     temps_[0] = temp;
   1562   }
   1563 
   1564   LOperand* function() { return inputs_[0]; }
   1565   LOperand* temp() { return temps_[0]; }
   1566 
   1567   DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
   1568   DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
   1569 };
   1570 
   1571 
   1572 class LLoadExternalArrayPointer: public LTemplateInstruction<1, 1, 0> {
   1573  public:
   1574   explicit LLoadExternalArrayPointer(LOperand* object) {
   1575     inputs_[0] = object;
   1576   }
   1577 
   1578   LOperand* object() { return inputs_[0]; }
   1579 
   1580   DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer,
   1581                                "load-external-array-pointer")
   1582 };
   1583 
   1584 
   1585 class LLoadKeyed: public LTemplateInstruction<1, 2, 0> {
   1586  public:
   1587   LLoadKeyed(LOperand* elements, LOperand* key) {
   1588     inputs_[0] = elements;
   1589     inputs_[1] = key;
   1590   }
   1591   LOperand* elements() { return inputs_[0]; }
   1592   LOperand* key() { return inputs_[1]; }
   1593   ElementsKind elements_kind() const {
   1594     return hydrogen()->elements_kind();
   1595   }
   1596   bool is_external() const {
   1597     return hydrogen()->is_external();
   1598   }
   1599 
   1600   virtual bool ClobbersDoubleRegisters() const {
   1601     return !CpuFeatures::IsSupported(SSE2) &&
   1602         !IsDoubleOrFloatElementsKind(hydrogen()->elements_kind());
   1603   }
   1604 
   1605   DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
   1606   DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
   1607 
   1608   virtual void PrintDataTo(StringStream* stream);
   1609   uint32_t additional_index() const { return hydrogen()->index_offset(); }
   1610   bool key_is_smi() {
   1611     return hydrogen()->key()->representation().IsTagged();
   1612   }
   1613 };
   1614 
   1615 
   1616 inline static bool ExternalArrayOpRequiresTemp(
   1617     Representation key_representation,
   1618     ElementsKind elements_kind) {
   1619   // Operations that require the key to be divided by two to be converted into
   1620   // an index cannot fold the scale operation into a load and need an extra
   1621   // temp register to do the work.
   1622   return key_representation.IsSmi() &&
   1623       (elements_kind == EXTERNAL_BYTE_ELEMENTS ||
   1624        elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
   1625        elements_kind == EXTERNAL_PIXEL_ELEMENTS);
   1626 }
   1627 
   1628 
   1629 class LLoadKeyedGeneric: public LTemplateInstruction<1, 3, 0> {
   1630  public:
   1631   LLoadKeyedGeneric(LOperand* context, LOperand* obj, LOperand* key) {
   1632     inputs_[0] = context;
   1633     inputs_[1] = obj;
   1634     inputs_[2] = key;
   1635   }
   1636 
   1637   LOperand* context() { return inputs_[0]; }
   1638   LOperand* object() { return inputs_[1]; }
   1639   LOperand* key() { return inputs_[2]; }
   1640 
   1641   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic")
   1642 };
   1643 
   1644 
   1645 class LLoadGlobalCell: public LTemplateInstruction<1, 0, 0> {
   1646  public:
   1647   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell, "load-global-cell")
   1648   DECLARE_HYDROGEN_ACCESSOR(LoadGlobalCell)
   1649 };
   1650 
   1651 
   1652 class LLoadGlobalGeneric: public LTemplateInstruction<1, 2, 0> {
   1653  public:
   1654   LLoadGlobalGeneric(LOperand* context, LOperand* global_object) {
   1655     inputs_[0] = context;
   1656     inputs_[1] = global_object;
   1657   }
   1658 
   1659   LOperand* context() { return inputs_[0]; }
   1660   LOperand* global_object() { return inputs_[1]; }
   1661 
   1662   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
   1663   DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)
   1664 
   1665   Handle<Object> name() const { return hydrogen()->name(); }
   1666   bool for_typeof() const { return hydrogen()->for_typeof(); }
   1667 };
   1668 
   1669 
   1670 class LStoreGlobalCell: public LTemplateInstruction<0, 1, 0> {
   1671  public:
   1672   explicit LStoreGlobalCell(LOperand* value) {
   1673     inputs_[0] = value;
   1674   }
   1675 
   1676   LOperand* value() { return inputs_[0]; }
   1677 
   1678   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell")
   1679   DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell)
   1680 };
   1681 
   1682 
   1683 class LStoreGlobalGeneric: public LTemplateInstruction<0, 3, 0> {
   1684  public:
   1685   LStoreGlobalGeneric(LOperand* context,
   1686                       LOperand* global_object,
   1687                       LOperand* value) {
   1688     inputs_[0] = context;
   1689     inputs_[1] = global_object;
   1690     inputs_[2] = value;
   1691   }
   1692 
   1693   LOperand* context() { return inputs_[0]; }
   1694   LOperand* global_object() { return inputs_[1]; }
   1695   LOperand* value() { return inputs_[2]; }
   1696 
   1697   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric, "store-global-generic")
   1698   DECLARE_HYDROGEN_ACCESSOR(StoreGlobalGeneric)
   1699 
   1700   Handle<Object> name() const { return hydrogen()->name(); }
   1701   StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
   1702 };
   1703 
   1704 
   1705 class LLoadContextSlot: public LTemplateInstruction<1, 1, 0> {
   1706  public:
   1707   explicit LLoadContextSlot(LOperand* context) {
   1708     inputs_[0] = context;
   1709   }
   1710 
   1711   LOperand* context() { return inputs_[0]; }
   1712 
   1713   DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot")
   1714   DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot)
   1715 
   1716   int slot_index() { return hydrogen()->slot_index(); }
   1717 
   1718   virtual void PrintDataTo(StringStream* stream);
   1719 };
   1720 
   1721 
   1722 class LStoreContextSlot: public LTemplateInstruction<0, 2, 1> {
   1723  public:
   1724   LStoreContextSlot(LOperand* context, LOperand* value, LOperand* temp) {
   1725     inputs_[0] = context;
   1726     inputs_[1] = value;
   1727     temps_[0] = temp;
   1728   }
   1729 
   1730   LOperand* context() { return inputs_[0]; }
   1731   LOperand* value() { return inputs_[1]; }
   1732   LOperand* temp() { return temps_[0]; }
   1733 
   1734   DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot")
   1735   DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot)
   1736 
   1737   int slot_index() { return hydrogen()->slot_index(); }
   1738 
   1739   virtual void PrintDataTo(StringStream* stream);
   1740 };
   1741 
   1742 
   1743 class LPushArgument: public LTemplateInstruction<0, 1, 0> {
   1744  public:
   1745   explicit LPushArgument(LOperand* value) {
   1746     inputs_[0] = value;
   1747   }
   1748 
   1749   LOperand* value() { return inputs_[0]; }
   1750 
   1751   DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push-argument")
   1752 };
   1753 
   1754 
   1755 class LDrop: public LTemplateInstruction<0, 0, 0> {
   1756  public:
   1757   explicit LDrop(int count) : count_(count) { }
   1758 
   1759   int count() const { return count_; }
   1760 
   1761   DECLARE_CONCRETE_INSTRUCTION(Drop, "drop")
   1762 
   1763  private:
   1764   int count_;
   1765 };
   1766 
   1767 
   1768 class LInnerAllocatedObject: public LTemplateInstruction<1, 1, 0> {
   1769  public:
   1770   explicit LInnerAllocatedObject(LOperand* base_object) {
   1771     inputs_[0] = base_object;
   1772   }
   1773 
   1774   LOperand* base_object() { return inputs_[0]; }
   1775   int offset() { return hydrogen()->offset(); }
   1776 
   1777   virtual void PrintDataTo(StringStream* stream);
   1778 
   1779   DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "sub-allocated-object")
   1780   DECLARE_HYDROGEN_ACCESSOR(InnerAllocatedObject)
   1781 };
   1782 
   1783 
   1784 class LThisFunction: public LTemplateInstruction<1, 0, 0> {
   1785  public:
   1786   DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
   1787   DECLARE_HYDROGEN_ACCESSOR(ThisFunction)
   1788 };
   1789 
   1790 
   1791 class LContext: public LTemplateInstruction<1, 0, 0> {
   1792  public:
   1793   DECLARE_CONCRETE_INSTRUCTION(Context, "context")
   1794   DECLARE_HYDROGEN_ACCESSOR(Context)
   1795 };
   1796 
   1797 
   1798 class LOuterContext: public LTemplateInstruction<1, 1, 0> {
   1799  public:
   1800   explicit LOuterContext(LOperand* context) {
   1801     inputs_[0] = context;
   1802   }
   1803 
   1804   LOperand* context() { return inputs_[0]; }
   1805 
   1806   DECLARE_CONCRETE_INSTRUCTION(OuterContext, "outer-context")
   1807 };
   1808 
   1809 
   1810 class LDeclareGlobals: public LTemplateInstruction<0, 1, 0> {
   1811  public:
   1812   explicit LDeclareGlobals(LOperand* context) {
   1813     inputs_[0] = context;
   1814   }
   1815 
   1816   LOperand* context() { return inputs_[0]; }
   1817 
   1818   DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals, "declare-globals")
   1819   DECLARE_HYDROGEN_ACCESSOR(DeclareGlobals)
   1820 };
   1821 
   1822 
   1823 class LGlobalObject: public LTemplateInstruction<1, 1, 0> {
   1824  public:
   1825   explicit LGlobalObject(LOperand* context) {
   1826     inputs_[0] = context;
   1827   }
   1828 
   1829   LOperand* context() { return inputs_[0]; }
   1830 
   1831   DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
   1832 };
   1833 
   1834 
   1835 class LGlobalReceiver: public LTemplateInstruction<1, 1, 0> {
   1836  public:
   1837   explicit LGlobalReceiver(LOperand* global_object) {
   1838     inputs_[0] = global_object;
   1839   }
   1840 
   1841   LOperand* global() { return inputs_[0]; }
   1842 
   1843   DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global-receiver")
   1844 };
   1845 
   1846 
   1847 class LCallConstantFunction: public LTemplateInstruction<1, 0, 0> {
   1848  public:
   1849   DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call-constant-function")
   1850   DECLARE_HYDROGEN_ACCESSOR(CallConstantFunction)
   1851 
   1852   virtual void PrintDataTo(StringStream* stream);
   1853 
   1854   Handle<JSFunction> function() { return hydrogen()->function(); }
   1855   int arity() const { return hydrogen()->argument_count() - 1; }
   1856 };
   1857 
   1858 
   1859 class LInvokeFunction: public LTemplateInstruction<1, 2, 0> {
   1860  public:
   1861   LInvokeFunction(LOperand* context, LOperand* function) {
   1862     inputs_[0] = context;
   1863     inputs_[1] = function;
   1864   }
   1865 
   1866   LOperand* context() { return inputs_[0]; }
   1867   LOperand* function() { return inputs_[1]; }
   1868 
   1869   DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
   1870   DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
   1871 
   1872   virtual void PrintDataTo(StringStream* stream);
   1873 
   1874   int arity() const { return hydrogen()->argument_count() - 1; }
   1875 };
   1876 
   1877 
   1878 class LCallKeyed: public LTemplateInstruction<1, 2, 0> {
   1879  public:
   1880   LCallKeyed(LOperand* context, LOperand* key) {
   1881     inputs_[0] = context;
   1882     inputs_[1] = key;
   1883   }
   1884 
   1885   LOperand* context() { return inputs_[0]; }
   1886   LOperand* key() { return inputs_[1]; }
   1887 
   1888   DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call-keyed")
   1889   DECLARE_HYDROGEN_ACCESSOR(CallKeyed)
   1890 
   1891   virtual void PrintDataTo(StringStream* stream);
   1892 
   1893   int arity() const { return hydrogen()->argument_count() - 1; }
   1894 };
   1895 
   1896 
   1897 class LCallNamed: public LTemplateInstruction<1, 1, 0> {
   1898  public:
   1899   explicit LCallNamed(LOperand* context) {
   1900     inputs_[0] = context;
   1901   }
   1902 
   1903   LOperand* context() { return inputs_[0]; }
   1904 
   1905   DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call-named")
   1906   DECLARE_HYDROGEN_ACCESSOR(CallNamed)
   1907 
   1908   virtual void PrintDataTo(StringStream* stream);
   1909 
   1910   Handle<String> name() const { return hydrogen()->name(); }
   1911   int arity() const { return hydrogen()->argument_count() - 1; }
   1912 };
   1913 
   1914 
   1915 class LCallFunction: public LTemplateInstruction<1, 2, 0> {
   1916  public:
   1917   explicit LCallFunction(LOperand* context, LOperand* function) {
   1918     inputs_[0] = context;
   1919     inputs_[1] = function;
   1920   }
   1921 
   1922   LOperand* context() { return inputs_[0]; }
   1923   LOperand* function() { return inputs_[1]; }
   1924 
   1925   DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call-function")
   1926   DECLARE_HYDROGEN_ACCESSOR(CallFunction)
   1927 
   1928   int arity() const { return hydrogen()->argument_count() - 1; }
   1929 };
   1930 
   1931 
   1932 class LCallGlobal: public LTemplateInstruction<1, 1, 0> {
   1933  public:
   1934   explicit LCallGlobal(LOperand* context) {
   1935     inputs_[0] = context;
   1936   }
   1937 
   1938   LOperand* context() { return inputs_[0]; }
   1939 
   1940   DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call-global")
   1941   DECLARE_HYDROGEN_ACCESSOR(CallGlobal)
   1942 
   1943   virtual void PrintDataTo(StringStream* stream);
   1944 
   1945   Handle<String> name() const {return hydrogen()->name(); }
   1946   int arity() const { return hydrogen()->argument_count() - 1; }
   1947 };
   1948 
   1949 
   1950 class LCallKnownGlobal: public LTemplateInstruction<1, 0, 0> {
   1951  public:
   1952   DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call-known-global")
   1953   DECLARE_HYDROGEN_ACCESSOR(CallKnownGlobal)
   1954 
   1955   virtual void PrintDataTo(StringStream* stream);
   1956 
   1957   int arity() const { return hydrogen()->argument_count() - 1;  }
   1958 };
   1959 
   1960 
   1961 class LCallNew: public LTemplateInstruction<1, 2, 0> {
   1962  public:
   1963   LCallNew(LOperand* context, LOperand* constructor) {
   1964     inputs_[0] = context;
   1965     inputs_[1] = constructor;
   1966   }
   1967 
   1968   LOperand* context() { return inputs_[0]; }
   1969   LOperand* constructor() { return inputs_[1]; }
   1970 
   1971   DECLARE_CONCRETE_INSTRUCTION(CallNew, "call-new")
   1972   DECLARE_HYDROGEN_ACCESSOR(CallNew)
   1973 
   1974   virtual void PrintDataTo(StringStream* stream);
   1975 
   1976   int arity() const { return hydrogen()->argument_count() - 1; }
   1977 };
   1978 
   1979 
   1980 class LCallNewArray: public LTemplateInstruction<1, 2, 0> {
   1981  public:
   1982   LCallNewArray(LOperand* context, LOperand* constructor) {
   1983     inputs_[0] = context;
   1984     inputs_[1] = constructor;
   1985   }
   1986 
   1987   LOperand* context() { return inputs_[0]; }
   1988   LOperand* constructor() { return inputs_[1]; }
   1989 
   1990   DECLARE_CONCRETE_INSTRUCTION(CallNewArray, "call-new-array")
   1991   DECLARE_HYDROGEN_ACCESSOR(CallNewArray)
   1992 
   1993   virtual void PrintDataTo(StringStream* stream);
   1994 
   1995   int arity() const { return hydrogen()->argument_count() - 1; }
   1996 };
   1997 
   1998 
   1999 class LCallRuntime: public LTemplateInstruction<1, 1, 0> {
   2000  public:
   2001   explicit LCallRuntime(LOperand* context) {
   2002     inputs_[0] = context;
   2003   }
   2004 
   2005   LOperand* context() { return inputs_[0]; }
   2006 
   2007   DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
   2008   DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
   2009 
   2010   const Runtime::Function* function() const { return hydrogen()->function(); }
   2011   int arity() const { return hydrogen()->argument_count(); }
   2012 };
   2013 
   2014 
   2015 class LInteger32ToDouble: public LTemplateInstruction<1, 1, 0> {
   2016  public:
   2017   explicit LInteger32ToDouble(LOperand* value) {
   2018     inputs_[0] = value;
   2019   }
   2020 
   2021   LOperand* value() { return inputs_[0]; }
   2022 
   2023   DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double")
   2024 };
   2025 
   2026 
   2027 class LInteger32ToSmi: public LTemplateInstruction<1, 1, 0> {
   2028  public:
   2029   explicit LInteger32ToSmi(LOperand* value) {
   2030     inputs_[0] = value;
   2031   }
   2032 
   2033   LOperand* value() { return inputs_[0]; }
   2034 
   2035   DECLARE_CONCRETE_INSTRUCTION(Integer32ToSmi, "int32-to-smi")
   2036   DECLARE_HYDROGEN_ACCESSOR(Change)
   2037 };
   2038 
   2039 
   2040 class LUint32ToDouble: public LTemplateInstruction<1, 1, 1> {
   2041  public:
   2042   explicit LUint32ToDouble(LOperand* value, LOperand* temp) {
   2043     inputs_[0] = value;
   2044     temps_[0] = temp;
   2045   }
   2046 
   2047   LOperand* value() { return inputs_[0]; }
   2048   LOperand* temp() { return temps_[0]; }
   2049 
   2050   DECLARE_CONCRETE_INSTRUCTION(Uint32ToDouble, "uint32-to-double")
   2051 };
   2052 
   2053 
   2054 class LUint32ToSmi: public LTemplateInstruction<1, 1, 0> {
   2055  public:
   2056   explicit LUint32ToSmi(LOperand* value) {
   2057     inputs_[0] = value;
   2058   }
   2059 
   2060   LOperand* value() { return inputs_[0]; }
   2061 
   2062   DECLARE_CONCRETE_INSTRUCTION(Uint32ToSmi, "uint32-to-smi")
   2063   DECLARE_HYDROGEN_ACCESSOR(Change)
   2064 };
   2065 
   2066 
   2067 class LNumberTagI: public LTemplateInstruction<1, 1, 0> {
   2068  public:
   2069   explicit LNumberTagI(LOperand* value) {
   2070     inputs_[0] = value;
   2071   }
   2072 
   2073   LOperand* value() { return inputs_[0]; }
   2074 
   2075   DECLARE_CONCRETE_INSTRUCTION(NumberTagI, "number-tag-i")
   2076 };
   2077 
   2078 
   2079 class LNumberTagU: public LTemplateInstruction<1, 1, 1> {
   2080  public:
   2081   LNumberTagU(LOperand* value, LOperand* temp) {
   2082     inputs_[0] = value;
   2083     temps_[0] = temp;
   2084   }
   2085 
   2086   LOperand* value() { return inputs_[0]; }
   2087   LOperand* temp() { return temps_[0]; }
   2088 
   2089   DECLARE_CONCRETE_INSTRUCTION(NumberTagU, "number-tag-u")
   2090 };
   2091 
   2092 
   2093 class LNumberTagD: public LTemplateInstruction<1, 1, 1> {
   2094  public:
   2095   LNumberTagD(LOperand* value, LOperand* temp) {
   2096     inputs_[0] = value;
   2097     temps_[0] = temp;
   2098   }
   2099 
   2100   LOperand* value() { return inputs_[0]; }
   2101   LOperand* temp() { return temps_[0]; }
   2102 
   2103   DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d")
   2104   DECLARE_HYDROGEN_ACCESSOR(Change)
   2105 };
   2106 
   2107 
   2108 // Sometimes truncating conversion from a tagged value to an int32.
   2109 class LDoubleToI: public LTemplateInstruction<1, 1, 1> {
   2110  public:
   2111   LDoubleToI(LOperand* value, LOperand* temp) {
   2112     inputs_[0] = value;
   2113     temps_[0] = temp;
   2114   }
   2115 
   2116   LOperand* value() { return inputs_[0]; }
   2117   LOperand* temp() { return temps_[0]; }
   2118 
   2119   DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i")
   2120   DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
   2121 
   2122   bool truncating() { return hydrogen()->CanTruncateToInt32(); }
   2123 };
   2124 
   2125 
   2126 class LDoubleToSmi: public LTemplateInstruction<1, 1, 0> {
   2127  public:
   2128   explicit LDoubleToSmi(LOperand* value) {
   2129     inputs_[0] = value;
   2130   }
   2131 
   2132   LOperand* value() { return inputs_[0]; }
   2133 
   2134   DECLARE_CONCRETE_INSTRUCTION(DoubleToSmi, "double-to-smi")
   2135   DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
   2136 };
   2137 
   2138 
   2139 // Truncating conversion from a tagged value to an int32.
   2140 class LTaggedToI: public LTemplateInstruction<1, 1, 1> {
   2141  public:
   2142   LTaggedToI(LOperand* value, LOperand* temp) {
   2143     inputs_[0] = value;
   2144     temps_[0] = temp;
   2145   }
   2146 
   2147   LOperand* value() { return inputs_[0]; }
   2148   LOperand* temp() { return temps_[0]; }
   2149 
   2150   DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
   2151   DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
   2152 
   2153   bool truncating() { return hydrogen()->CanTruncateToInt32(); }
   2154 };
   2155 
   2156 
   2157 // Truncating conversion from a tagged value to an int32.
   2158 class LTaggedToINoSSE2: public LTemplateInstruction<1, 1, 3> {
   2159  public:
   2160   LTaggedToINoSSE2(LOperand* value,
   2161                    LOperand* temp1,
   2162                    LOperand* temp2,
   2163                    LOperand* temp3) {
   2164     inputs_[0] = value;
   2165     temps_[0] = temp1;
   2166     temps_[1] = temp2;
   2167     temps_[2] = temp3;
   2168   }
   2169 
   2170   LOperand* value() { return inputs_[0]; }
   2171   LOperand* scratch() { return temps_[0]; }
   2172   LOperand* scratch2() { return temps_[1]; }
   2173   LOperand* scratch3() { return temps_[2]; }
   2174 
   2175   DECLARE_CONCRETE_INSTRUCTION(TaggedToINoSSE2, "tagged-to-i-nosse2")
   2176   DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
   2177 
   2178   bool truncating() { return hydrogen()->CanTruncateToInt32(); }
   2179 };
   2180 
   2181 
   2182 class LSmiTag: public LTemplateInstruction<1, 1, 0> {
   2183  public:
   2184   explicit LSmiTag(LOperand* value) {
   2185     inputs_[0] = value;
   2186   }
   2187 
   2188   LOperand* value() { return inputs_[0]; }
   2189 
   2190   DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag")
   2191 };
   2192 
   2193 
   2194 class LNumberUntagD: public LTemplateInstruction<1, 1, 1> {
   2195  public:
   2196   explicit LNumberUntagD(LOperand* value, LOperand* temp) {
   2197     inputs_[0] = value;
   2198     temps_[0] = temp;
   2199   }
   2200 
   2201   LOperand* value() { return inputs_[0]; }
   2202   LOperand* temp() { return temps_[0]; }
   2203 
   2204   virtual bool ClobbersDoubleRegisters() const { return false; }
   2205 
   2206   DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
   2207   DECLARE_HYDROGEN_ACCESSOR(Change);
   2208 };
   2209 
   2210 
   2211 class LSmiUntag: public LTemplateInstruction<1, 1, 0> {
   2212  public:
   2213   LSmiUntag(LOperand* value, bool needs_check)
   2214       : needs_check_(needs_check) {
   2215     inputs_[0] = value;
   2216   }
   2217 
   2218   LOperand* value() { return inputs_[0]; }
   2219 
   2220   DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
   2221 
   2222   bool needs_check() const { return needs_check_; }
   2223 
   2224  private:
   2225   bool needs_check_;
   2226 };
   2227 
   2228 
   2229 class LStoreNamedField: public LTemplateInstruction<0, 2, 2> {
   2230  public:
   2231   LStoreNamedField(LOperand* obj,
   2232                    LOperand* val,
   2233                    LOperand* temp,
   2234                    LOperand* temp_map) {
   2235     inputs_[0] = obj;
   2236     inputs_[1] = val;
   2237     temps_[0] = temp;
   2238     temps_[1] = temp_map;
   2239   }
   2240 
   2241   LOperand* object() { return inputs_[0]; }
   2242   LOperand* value() { return inputs_[1]; }
   2243   LOperand* temp() { return temps_[0]; }
   2244   LOperand* temp_map() { return temps_[1]; }
   2245 
   2246   DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
   2247   DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
   2248 
   2249   virtual void PrintDataTo(StringStream* stream);
   2250 
   2251   Handle<Map> transition() const { return hydrogen()->transition_map(); }
   2252   Representation representation() const {
   2253     return hydrogen()->field_representation();
   2254   }
   2255 };
   2256 
   2257 
   2258 class LStoreNamedGeneric: public LTemplateInstruction<0, 3, 0> {
   2259  public:
   2260   LStoreNamedGeneric(LOperand* context, LOperand* object, LOperand* value) {
   2261     inputs_[0] = context;
   2262     inputs_[1] = object;
   2263     inputs_[2] = value;
   2264   }
   2265 
   2266   LOperand* context() { return inputs_[0]; }
   2267   LOperand* object() { return inputs_[1]; }
   2268   LOperand* value() { return inputs_[2]; }
   2269 
   2270   DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
   2271   DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
   2272 
   2273   virtual void PrintDataTo(StringStream* stream);
   2274   Handle<Object> name() const { return hydrogen()->name(); }
   2275   StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
   2276 };
   2277 
   2278 
   2279 class LStoreKeyed: public LTemplateInstruction<0, 3, 0> {
   2280  public:
   2281   LStoreKeyed(LOperand* obj, LOperand* key, LOperand* val) {
   2282     inputs_[0] = obj;
   2283     inputs_[1] = key;
   2284     inputs_[2] = val;
   2285   }
   2286 
   2287   bool is_external() const { return hydrogen()->is_external(); }
   2288   LOperand* elements() { return inputs_[0]; }
   2289   LOperand* key() { return inputs_[1]; }
   2290   LOperand* value() { return inputs_[2]; }
   2291   ElementsKind elements_kind() const {
   2292     return hydrogen()->elements_kind();
   2293   }
   2294 
   2295   DECLARE_CONCRETE_INSTRUCTION(StoreKeyed, "store-keyed")
   2296   DECLARE_HYDROGEN_ACCESSOR(StoreKeyed)
   2297 
   2298   virtual void PrintDataTo(StringStream* stream);
   2299   uint32_t additional_index() const { return hydrogen()->index_offset(); }
   2300   bool NeedsCanonicalization() { return hydrogen()->NeedsCanonicalization(); }
   2301 };
   2302 
   2303 
   2304 class LStoreKeyedGeneric: public LTemplateInstruction<0, 4, 0> {
   2305  public:
   2306   LStoreKeyedGeneric(LOperand* context,
   2307                      LOperand* object,
   2308                      LOperand* key,
   2309                      LOperand* value) {
   2310     inputs_[0] = context;
   2311     inputs_[1] = object;
   2312     inputs_[2] = key;
   2313     inputs_[3] = value;
   2314   }
   2315 
   2316   LOperand* context() { return inputs_[0]; }
   2317   LOperand* object() { return inputs_[1]; }
   2318   LOperand* key() { return inputs_[2]; }
   2319   LOperand* value() { return inputs_[3]; }
   2320 
   2321   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
   2322   DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
   2323 
   2324   virtual void PrintDataTo(StringStream* stream);
   2325 
   2326   StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
   2327 };
   2328 
   2329 
   2330 class LTransitionElementsKind: public LTemplateInstruction<0, 2, 2> {
   2331  public:
   2332   LTransitionElementsKind(LOperand* object,
   2333                           LOperand* context,
   2334                           LOperand* new_map_temp,
   2335                           LOperand* temp) {
   2336     inputs_[0] = object;
   2337     inputs_[1] = context;
   2338     temps_[0] = new_map_temp;
   2339     temps_[1] = temp;
   2340   }
   2341 
   2342   LOperand* context() { return inputs_[1]; }
   2343   LOperand* object() { return inputs_[0]; }
   2344   LOperand* new_map_temp() { return temps_[0]; }
   2345   LOperand* temp() { return temps_[1]; }
   2346 
   2347   DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind,
   2348                                "transition-elements-kind")
   2349   DECLARE_HYDROGEN_ACCESSOR(TransitionElementsKind)
   2350 
   2351   virtual void PrintDataTo(StringStream* stream);
   2352 
   2353   Handle<Map> original_map() { return hydrogen()->original_map(); }
   2354   Handle<Map> transitioned_map() { return hydrogen()->transitioned_map(); }
   2355   ElementsKind from_kind() { return hydrogen()->from_kind(); }
   2356   ElementsKind to_kind() { return hydrogen()->to_kind(); }
   2357 };
   2358 
   2359 
   2360 class LTrapAllocationMemento : public LTemplateInstruction<0, 1, 1> {
   2361  public:
   2362   LTrapAllocationMemento(LOperand* object,
   2363                          LOperand* temp) {
   2364     inputs_[0] = object;
   2365     temps_[0] = temp;
   2366   }
   2367 
   2368   LOperand* object() { return inputs_[0]; }
   2369   LOperand* temp() { return temps_[0]; }
   2370 
   2371   DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento,
   2372                                "trap-allocation-memento")
   2373 };
   2374 
   2375 
   2376 class LStringAdd: public LTemplateInstruction<1, 3, 0> {
   2377  public:
   2378   LStringAdd(LOperand* context, LOperand* left, LOperand* right) {
   2379     inputs_[0] = context;
   2380     inputs_[1] = left;
   2381     inputs_[2] = right;
   2382   }
   2383 
   2384   LOperand* context() { return inputs_[0]; }
   2385   LOperand* left() { return inputs_[1]; }
   2386   LOperand* right() { return inputs_[2]; }
   2387 
   2388   DECLARE_CONCRETE_INSTRUCTION(StringAdd, "string-add")
   2389   DECLARE_HYDROGEN_ACCESSOR(StringAdd)
   2390 };
   2391 
   2392 
   2393 class LStringCharCodeAt: public LTemplateInstruction<1, 3, 0> {
   2394  public:
   2395   LStringCharCodeAt(LOperand* context, LOperand* string, LOperand* index) {
   2396     inputs_[0] = context;
   2397     inputs_[1] = string;
   2398     inputs_[2] = index;
   2399   }
   2400 
   2401   LOperand* context() { return inputs_[0]; }
   2402   LOperand* string() { return inputs_[1]; }
   2403   LOperand* index() { return inputs_[2]; }
   2404 
   2405   DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at")
   2406   DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt)
   2407 };
   2408 
   2409 
   2410 class LStringCharFromCode: public LTemplateInstruction<1, 2, 0> {
   2411  public:
   2412   LStringCharFromCode(LOperand* context, LOperand* char_code) {
   2413     inputs_[0] = context;
   2414     inputs_[1] = char_code;
   2415   }
   2416 
   2417   LOperand* context() { return inputs_[0]; }
   2418   LOperand* char_code() { return inputs_[1]; }
   2419 
   2420   DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code")
   2421   DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode)
   2422 };
   2423 
   2424 
   2425 class LCheckFunction: public LTemplateInstruction<0, 1, 0> {
   2426  public:
   2427   explicit LCheckFunction(LOperand* value) {
   2428     inputs_[0] = value;
   2429   }
   2430 
   2431   LOperand* value() { return inputs_[0]; }
   2432 
   2433   DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check-function")
   2434   DECLARE_HYDROGEN_ACCESSOR(CheckFunction)
   2435 };
   2436 
   2437 
   2438 class LCheckInstanceType: public LTemplateInstruction<0, 1, 1> {
   2439  public:
   2440   LCheckInstanceType(LOperand* value, LOperand* temp) {
   2441     inputs_[0] = value;
   2442     temps_[0] = temp;
   2443   }
   2444 
   2445   LOperand* value() { return inputs_[0]; }
   2446   LOperand* temp() { return temps_[0]; }
   2447 
   2448   DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type")
   2449   DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType)
   2450 };
   2451 
   2452 
   2453 class LCheckMaps: public LTemplateInstruction<0, 1, 0> {
   2454  public:
   2455   explicit LCheckMaps(LOperand* value) {
   2456     inputs_[0] = value;
   2457   }
   2458 
   2459   LOperand* value() { return inputs_[0]; }
   2460 
   2461   DECLARE_CONCRETE_INSTRUCTION(CheckMaps, "check-maps")
   2462   DECLARE_HYDROGEN_ACCESSOR(CheckMaps)
   2463 };
   2464 
   2465 
   2466 class LCheckSmi: public LTemplateInstruction<1, 1, 0> {
   2467  public:
   2468   explicit LCheckSmi(LOperand* value) {
   2469     inputs_[0] = value;
   2470   }
   2471 
   2472   LOperand* value() { return inputs_[0]; }
   2473 
   2474   DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi")
   2475 };
   2476 
   2477 
   2478 class LClampDToUint8: public LTemplateInstruction<1, 1, 0> {
   2479  public:
   2480   explicit LClampDToUint8(LOperand* value) {
   2481     inputs_[0] = value;
   2482   }
   2483 
   2484   LOperand* unclamped() { return inputs_[0]; }
   2485 
   2486   DECLARE_CONCRETE_INSTRUCTION(ClampDToUint8, "clamp-d-to-uint8")
   2487 };
   2488 
   2489 
   2490 class LClampIToUint8: public LTemplateInstruction<1, 1, 0> {
   2491  public:
   2492   explicit LClampIToUint8(LOperand* value) {
   2493     inputs_[0] = value;
   2494   }
   2495 
   2496   LOperand* unclamped() { return inputs_[0]; }
   2497 
   2498   DECLARE_CONCRETE_INSTRUCTION(ClampIToUint8, "clamp-i-to-uint8")
   2499 };
   2500 
   2501 
   2502 class LClampTToUint8: public LTemplateInstruction<1, 1, 1> {
   2503  public:
   2504   LClampTToUint8(LOperand* value, LOperand* temp) {
   2505     inputs_[0] = value;
   2506     temps_[0] = temp;
   2507   }
   2508 
   2509   LOperand* unclamped() { return inputs_[0]; }
   2510 
   2511   DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8, "clamp-t-to-uint8")
   2512 };
   2513 
   2514 
   2515 // Truncating conversion from a tagged value to an int32.
   2516 class LClampTToUint8NoSSE2: public LTemplateInstruction<1, 1, 3> {
   2517  public:
   2518   LClampTToUint8NoSSE2(LOperand* unclamped,
   2519                        LOperand* temp1,
   2520                        LOperand* temp2,
   2521                        LOperand* temp3) {
   2522     inputs_[0] = unclamped;
   2523     temps_[0] = temp1;
   2524     temps_[1] = temp2;
   2525     temps_[2] = temp3;
   2526   }
   2527 
   2528   LOperand* unclamped() { return inputs_[0]; }
   2529   LOperand* scratch() { return temps_[0]; }
   2530   LOperand* scratch2() { return temps_[1]; }
   2531   LOperand* scratch3() { return temps_[2]; }
   2532 
   2533   DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8NoSSE2,
   2534                                "clamp-t-to-uint8-nosse2")
   2535   DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
   2536 };
   2537 
   2538 
   2539 class LCheckNonSmi: public LTemplateInstruction<0, 1, 0> {
   2540  public:
   2541   explicit LCheckNonSmi(LOperand* value) {
   2542     inputs_[0] = value;
   2543   }
   2544 
   2545   LOperand* value() { return inputs_[0]; }
   2546 
   2547   DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi")
   2548   DECLARE_HYDROGEN_ACCESSOR(CheckHeapObject)
   2549 };
   2550 
   2551 
   2552 class LAllocate: public LTemplateInstruction<1, 2, 1> {
   2553  public:
   2554   LAllocate(LOperand* context, LOperand* size, LOperand* temp) {
   2555     inputs_[0] = context;
   2556     inputs_[1] = size;
   2557     temps_[0] = temp;
   2558   }
   2559 
   2560   LOperand* context() { return inputs_[0]; }
   2561   LOperand* size() { return inputs_[1]; }
   2562   LOperand* temp() { return temps_[0]; }
   2563 
   2564   DECLARE_CONCRETE_INSTRUCTION(Allocate, "allocate")
   2565   DECLARE_HYDROGEN_ACCESSOR(Allocate)
   2566 };
   2567 
   2568 
   2569 class LRegExpLiteral: public LTemplateInstruction<1, 1, 0> {
   2570  public:
   2571   explicit LRegExpLiteral(LOperand* context) {
   2572     inputs_[0] = context;
   2573   }
   2574 
   2575   LOperand* context() { return inputs_[0]; }
   2576 
   2577   DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp-literal")
   2578   DECLARE_HYDROGEN_ACCESSOR(RegExpLiteral)
   2579 };
   2580 
   2581 
   2582 class LFunctionLiteral: public LTemplateInstruction<1, 1, 0> {
   2583  public:
   2584   explicit LFunctionLiteral(LOperand* context) {
   2585     inputs_[0] = context;
   2586   }
   2587 
   2588   LOperand* context() { return inputs_[0]; }
   2589 
   2590   DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function-literal")
   2591   DECLARE_HYDROGEN_ACCESSOR(FunctionLiteral)
   2592 };
   2593 
   2594 
   2595 class LToFastProperties: public LTemplateInstruction<1, 1, 0> {
   2596  public:
   2597   explicit LToFastProperties(LOperand* value) {
   2598     inputs_[0] = value;
   2599   }
   2600 
   2601   LOperand* value() { return inputs_[0]; }
   2602 
   2603   DECLARE_CONCRETE_INSTRUCTION(ToFastProperties, "to-fast-properties")
   2604   DECLARE_HYDROGEN_ACCESSOR(ToFastProperties)
   2605 };
   2606 
   2607 
   2608 class LTypeof: public LTemplateInstruction<1, 2, 0> {
   2609  public:
   2610   LTypeof(LOperand* context, LOperand* value) {
   2611     inputs_[0] = context;
   2612     inputs_[1] = value;
   2613   }
   2614 
   2615   LOperand* context() { return inputs_[0]; }
   2616   LOperand* value() { return inputs_[1]; }
   2617 
   2618   DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
   2619 };
   2620 
   2621 
   2622 class LTypeofIsAndBranch: public LControlInstruction<1, 0> {
   2623  public:
   2624   explicit LTypeofIsAndBranch(LOperand* value) {
   2625     inputs_[0] = value;
   2626   }
   2627 
   2628   LOperand* value() { return inputs_[0]; }
   2629 
   2630   DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch")
   2631   DECLARE_HYDROGEN_ACCESSOR(TypeofIsAndBranch)
   2632 
   2633   Handle<String> type_literal() { return hydrogen()->type_literal(); }
   2634 
   2635   virtual void PrintDataTo(StringStream* stream);
   2636 };
   2637 
   2638 
   2639 class LOsrEntry: public LTemplateInstruction<0, 0, 0> {
   2640  public:
   2641   LOsrEntry() {}
   2642 
   2643   virtual bool HasInterestingComment(LCodeGen* gen) const { return false; }
   2644   DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry")
   2645 };
   2646 
   2647 
   2648 class LStackCheck: public LTemplateInstruction<0, 1, 0> {
   2649  public:
   2650   explicit LStackCheck(LOperand* context) {
   2651     inputs_[0] = context;
   2652   }
   2653 
   2654   LOperand* context() { return inputs_[0]; }
   2655 
   2656   DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check")
   2657   DECLARE_HYDROGEN_ACCESSOR(StackCheck)
   2658 
   2659   Label* done_label() { return &done_label_; }
   2660 
   2661  private:
   2662   Label done_label_;
   2663 };
   2664 
   2665 
   2666 class LForInPrepareMap: public LTemplateInstruction<1, 2, 0> {
   2667  public:
   2668   LForInPrepareMap(LOperand* context, LOperand* object) {
   2669     inputs_[0] = context;
   2670     inputs_[1] = object;
   2671   }
   2672 
   2673   LOperand* context() { return inputs_[0]; }
   2674   LOperand* object() { return inputs_[1]; }
   2675 
   2676   DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap, "for-in-prepare-map")
   2677 };
   2678 
   2679 
   2680 class LForInCacheArray: public LTemplateInstruction<1, 1, 0> {
   2681  public:
   2682   explicit LForInCacheArray(LOperand* map) {
   2683     inputs_[0] = map;
   2684   }
   2685 
   2686   LOperand* map() { return inputs_[0]; }
   2687 
   2688   DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray, "for-in-cache-array")
   2689 
   2690   int idx() {
   2691     return HForInCacheArray::cast(this->hydrogen_value())->idx();
   2692   }
   2693 };
   2694 
   2695 
   2696 class LCheckMapValue: public LTemplateInstruction<0, 2, 0> {
   2697  public:
   2698   LCheckMapValue(LOperand* value, LOperand* map) {
   2699     inputs_[0] = value;
   2700     inputs_[1] = map;
   2701   }
   2702 
   2703   LOperand* value() { return inputs_[0]; }
   2704   LOperand* map() { return inputs_[1]; }
   2705 
   2706   DECLARE_CONCRETE_INSTRUCTION(CheckMapValue, "check-map-value")
   2707 };
   2708 
   2709 
   2710 class LLoadFieldByIndex: public LTemplateInstruction<1, 2, 0> {
   2711  public:
   2712   LLoadFieldByIndex(LOperand* object, LOperand* index) {
   2713     inputs_[0] = object;
   2714     inputs_[1] = index;
   2715   }
   2716 
   2717   LOperand* object() { return inputs_[0]; }
   2718   LOperand* index() { return inputs_[1]; }
   2719 
   2720   DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex, "load-field-by-index")
   2721 };
   2722 
   2723 
   2724 class LChunkBuilder;
   2725 class LPlatformChunk: public LChunk {
   2726  public:
   2727   LPlatformChunk(CompilationInfo* info, HGraph* graph)
   2728       : LChunk(info, graph),
   2729         num_double_slots_(0) { }
   2730 
   2731   int GetNextSpillIndex(bool is_double);
   2732   LOperand* GetNextSpillSlot(bool is_double);
   2733 
   2734   int num_double_slots() const { return num_double_slots_; }
   2735 
   2736  private:
   2737   int num_double_slots_;
   2738 };
   2739 
   2740 
   2741 class LChunkBuilder BASE_EMBEDDED {
   2742  public:
   2743   LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator)
   2744       : chunk_(NULL),
   2745         info_(info),
   2746         graph_(graph),
   2747         zone_(graph->zone()),
   2748         status_(UNUSED),
   2749         current_instruction_(NULL),
   2750         current_block_(NULL),
   2751         next_block_(NULL),
   2752         argument_count_(0),
   2753         allocator_(allocator),
   2754         position_(RelocInfo::kNoPosition),
   2755         instruction_pending_deoptimization_environment_(NULL),
   2756         pending_deoptimization_ast_id_(BailoutId::None()) { }
   2757 
   2758   // Build the sequence for the graph.
   2759   LPlatformChunk* Build();
   2760 
   2761   // Declare methods that deal with the individual node types.
   2762 #define DECLARE_DO(type) LInstruction* Do##type(H##type* node);
   2763   HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
   2764 #undef DECLARE_DO
   2765 
   2766   static HValue* SimplifiedDivisorForMathFloorOfDiv(HValue* val);
   2767 
   2768   LInstruction* DoMathFloor(HUnaryMathOperation* instr);
   2769   LInstruction* DoMathRound(HUnaryMathOperation* instr);
   2770   LInstruction* DoMathAbs(HUnaryMathOperation* instr);
   2771   LInstruction* DoMathLog(HUnaryMathOperation* instr);
   2772   LInstruction* DoMathSin(HUnaryMathOperation* instr);
   2773   LInstruction* DoMathCos(HUnaryMathOperation* instr);
   2774   LInstruction* DoMathTan(HUnaryMathOperation* instr);
   2775   LInstruction* DoMathExp(HUnaryMathOperation* instr);
   2776   LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
   2777   LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);
   2778 
   2779  private:
   2780   enum Status {
   2781     UNUSED,
   2782     BUILDING,
   2783     DONE,
   2784     ABORTED
   2785   };
   2786 
   2787   LPlatformChunk* chunk() const { return chunk_; }
   2788   CompilationInfo* info() const { return info_; }
   2789   HGraph* graph() const { return graph_; }
   2790   Zone* zone() const { return zone_; }
   2791 
   2792   bool is_unused() const { return status_ == UNUSED; }
   2793   bool is_building() const { return status_ == BUILDING; }
   2794   bool is_done() const { return status_ == DONE; }
   2795   bool is_aborted() const { return status_ == ABORTED; }
   2796 
   2797   void Abort(BailoutReason reason);
   2798 
   2799   // Methods for getting operands for Use / Define / Temp.
   2800   LUnallocated* ToUnallocated(Register reg);
   2801   LUnallocated* ToUnallocated(XMMRegister reg);
   2802   LUnallocated* ToUnallocated(X87Register reg);
   2803 
   2804   // Methods for setting up define-use relationships.
   2805   MUST_USE_RESULT LOperand* Use(HValue* value, LUnallocated* operand);
   2806   MUST_USE_RESULT LOperand* UseFixed(HValue* value, Register fixed_register);
   2807   MUST_USE_RESULT LOperand* UseFixedDouble(HValue* value,
   2808                                            XMMRegister fixed_register);
   2809 
   2810   // A value that is guaranteed to be allocated to a register.
   2811   // Operand created by UseRegister is guaranteed to be live until the end of
   2812   // instruction. This means that register allocator will not reuse it's
   2813   // register for any other operand inside instruction.
   2814   // Operand created by UseRegisterAtStart is guaranteed to be live only at
   2815   // instruction start. Register allocator is free to assign the same register
   2816   // to some other operand used inside instruction (i.e. temporary or
   2817   // output).
   2818   MUST_USE_RESULT LOperand* UseRegister(HValue* value);
   2819   MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value);
   2820 
   2821   // An input operand in a register that may be trashed.
   2822   MUST_USE_RESULT LOperand* UseTempRegister(HValue* value);
   2823 
   2824   // An input operand in a register or stack slot.
   2825   MUST_USE_RESULT LOperand* Use(HValue* value);
   2826   MUST_USE_RESULT LOperand* UseAtStart(HValue* value);
   2827 
   2828   // An input operand in a register, stack slot or a constant operand.
   2829   MUST_USE_RESULT LOperand* UseOrConstant(HValue* value);
   2830   MUST_USE_RESULT LOperand* UseOrConstantAtStart(HValue* value);
   2831 
   2832   // An input operand in a register or a constant operand.
   2833   MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value);
   2834   MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value);
   2835 
   2836   // An input operand in a constant operand.
   2837   MUST_USE_RESULT LOperand* UseConstant(HValue* value);
   2838 
   2839   // An input operand in register, stack slot or a constant operand.
   2840   // Will not be moved to a register even if one is freely available.
   2841   MUST_USE_RESULT LOperand* UseAny(HValue* value);
   2842 
   2843   // Temporary operand that must be in a register.
   2844   MUST_USE_RESULT LUnallocated* TempRegister();
   2845   MUST_USE_RESULT LOperand* FixedTemp(Register reg);
   2846   MUST_USE_RESULT LOperand* FixedTemp(XMMRegister reg);
   2847 
   2848   // Methods for setting up define-use relationships.
   2849   // Return the same instruction that they are passed.
   2850   template<int I, int T>
   2851       LInstruction* Define(LTemplateInstruction<1, I, T>* instr,
   2852                            LUnallocated* result);
   2853   template<int I, int T>
   2854       LInstruction* DefineAsRegister(LTemplateInstruction<1, I, T>* instr);
   2855   template<int I, int T>
   2856       LInstruction* DefineAsSpilled(LTemplateInstruction<1, I, T>* instr,
   2857                                     int index);
   2858   template<int I, int T>
   2859       LInstruction* DefineSameAsFirst(LTemplateInstruction<1, I, T>* instr);
   2860   template<int I, int T>
   2861       LInstruction* DefineFixed(LTemplateInstruction<1, I, T>* instr,
   2862                                 Register reg);
   2863   template<int I, int T>
   2864       LInstruction* DefineFixedDouble(LTemplateInstruction<1, I, T>* instr,
   2865                                       XMMRegister reg);
   2866   template<int I, int T>
   2867       LInstruction* DefineX87TOS(LTemplateInstruction<1, I, T>* instr);
   2868   // Assigns an environment to an instruction.  An instruction which can
   2869   // deoptimize must have an environment.
   2870   LInstruction* AssignEnvironment(LInstruction* instr);
   2871   // Assigns a pointer map to an instruction.  An instruction which can
   2872   // trigger a GC or a lazy deoptimization must have a pointer map.
   2873   LInstruction* AssignPointerMap(LInstruction* instr);
   2874 
   2875   enum CanDeoptimize { CAN_DEOPTIMIZE_EAGERLY, CANNOT_DEOPTIMIZE_EAGERLY };
   2876 
   2877   // Marks a call for the register allocator.  Assigns a pointer map to
   2878   // support GC and lazy deoptimization.  Assigns an environment to support
   2879   // eager deoptimization if CAN_DEOPTIMIZE_EAGERLY.
   2880   LInstruction* MarkAsCall(
   2881       LInstruction* instr,
   2882       HInstruction* hinstr,
   2883       CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY);
   2884 
   2885   LEnvironment* CreateEnvironment(HEnvironment* hydrogen_env,
   2886                                   int* argument_index_accumulator,
   2887                                   ZoneList<HValue*>* objects_to_materialize);
   2888 
   2889   void VisitInstruction(HInstruction* current);
   2890 
   2891   void DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block);
   2892   LInstruction* DoShift(Token::Value op, HBitwiseBinaryOperation* instr);
   2893   LInstruction* DoArithmeticD(Token::Value op,
   2894                               HArithmeticBinaryOperation* instr);
   2895   LInstruction* DoArithmeticT(Token::Value op,
   2896                               HArithmeticBinaryOperation* instr);
   2897 
   2898   LOperand* GetStoreKeyedValueOperand(HStoreKeyed* instr);
   2899 
   2900   LPlatformChunk* chunk_;
   2901   CompilationInfo* info_;
   2902   HGraph* const graph_;
   2903   Zone* zone_;
   2904   Status status_;
   2905   HInstruction* current_instruction_;
   2906   HBasicBlock* current_block_;
   2907   HBasicBlock* next_block_;
   2908   int argument_count_;
   2909   LAllocator* allocator_;
   2910   int position_;
   2911   LInstruction* instruction_pending_deoptimization_environment_;
   2912   BailoutId pending_deoptimization_ast_id_;
   2913 
   2914   DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
   2915 };
   2916 
   2917 #undef DECLARE_HYDROGEN_ACCESSOR
   2918 #undef DECLARE_CONCRETE_INSTRUCTION
   2919 
   2920 } }  // namespace v8::internal
   2921 
   2922 #endif  // V8_IA32_LITHIUM_IA32_H_
   2923