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