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