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