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