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