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