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