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