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