Home | History | Annotate | Download | only in crankshaft
      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_HYDROGEN_INSTRUCTIONS_H_
      6 #define V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_
      7 
      8 #include <cstring>
      9 #include <iosfwd>
     10 
     11 #include "src/allocation.h"
     12 #include "src/base/bits.h"
     13 #include "src/bit-vector.h"
     14 #include "src/code-stubs.h"
     15 #include "src/conversions.h"
     16 #include "src/crankshaft/hydrogen-types.h"
     17 #include "src/crankshaft/unique.h"
     18 #include "src/deoptimizer.h"
     19 #include "src/small-pointer-list.h"
     20 #include "src/utils.h"
     21 #include "src/zone.h"
     22 
     23 namespace v8 {
     24 namespace internal {
     25 
     26 // Forward declarations.
     27 struct ChangesOf;
     28 class HBasicBlock;
     29 class HDiv;
     30 class HEnvironment;
     31 class HInferRepresentationPhase;
     32 class HInstruction;
     33 class HLoopInformation;
     34 class HStoreNamedField;
     35 class HValue;
     36 class LInstruction;
     37 class LChunkBuilder;
     38 
     39 #define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V) \
     40   V(ArithmeticBinaryOperation)                \
     41   V(BinaryOperation)                          \
     42   V(BitwiseBinaryOperation)                   \
     43   V(ControlInstruction)                       \
     44   V(Instruction)
     45 
     46 
     47 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
     48   V(AbnormalExit)                             \
     49   V(AccessArgumentsAt)                        \
     50   V(Add)                                      \
     51   V(AllocateBlockContext)                     \
     52   V(Allocate)                                 \
     53   V(ApplyArguments)                           \
     54   V(ArgumentsElements)                        \
     55   V(ArgumentsLength)                          \
     56   V(ArgumentsObject)                          \
     57   V(Bitwise)                                  \
     58   V(BlockEntry)                               \
     59   V(BoundsCheck)                              \
     60   V(BoundsCheckBaseIndexInformation)          \
     61   V(Branch)                                   \
     62   V(CallWithDescriptor)                       \
     63   V(CallJSFunction)                           \
     64   V(CallFunction)                             \
     65   V(CallNewArray)                             \
     66   V(CallRuntime)                              \
     67   V(CallStub)                                 \
     68   V(CapturedObject)                           \
     69   V(Change)                                   \
     70   V(CheckArrayBufferNotNeutered)              \
     71   V(CheckHeapObject)                          \
     72   V(CheckInstanceType)                        \
     73   V(CheckMaps)                                \
     74   V(CheckMapValue)                            \
     75   V(CheckSmi)                                 \
     76   V(CheckValue)                               \
     77   V(ClampToUint8)                             \
     78   V(ClassOfTestAndBranch)                     \
     79   V(CompareNumericAndBranch)                  \
     80   V(CompareHoleAndBranch)                     \
     81   V(CompareGeneric)                           \
     82   V(CompareMinusZeroAndBranch)                \
     83   V(CompareObjectEqAndBranch)                 \
     84   V(CompareMap)                               \
     85   V(Constant)                                 \
     86   V(ConstructDouble)                          \
     87   V(Context)                                  \
     88   V(DebugBreak)                               \
     89   V(DeclareGlobals)                           \
     90   V(Deoptimize)                               \
     91   V(Div)                                      \
     92   V(DoubleBits)                               \
     93   V(DummyUse)                                 \
     94   V(EnterInlined)                             \
     95   V(EnvironmentMarker)                        \
     96   V(ForceRepresentation)                      \
     97   V(ForInCacheArray)                          \
     98   V(ForInPrepareMap)                          \
     99   V(GetCachedArrayIndex)                      \
    100   V(Goto)                                     \
    101   V(HasCachedArrayIndexAndBranch)             \
    102   V(HasInstanceTypeAndBranch)                 \
    103   V(InnerAllocatedObject)                     \
    104   V(InstanceOf)                               \
    105   V(InvokeFunction)                           \
    106   V(HasInPrototypeChainAndBranch)             \
    107   V(IsStringAndBranch)                        \
    108   V(IsSmiAndBranch)                           \
    109   V(IsUndetectableAndBranch)                  \
    110   V(LeaveInlined)                             \
    111   V(LoadContextSlot)                          \
    112   V(LoadFieldByIndex)                         \
    113   V(LoadFunctionPrototype)                    \
    114   V(LoadGlobalGeneric)                        \
    115   V(LoadKeyed)                                \
    116   V(LoadKeyedGeneric)                         \
    117   V(LoadNamedField)                           \
    118   V(LoadNamedGeneric)                         \
    119   V(LoadRoot)                                 \
    120   V(MapEnumLength)                            \
    121   V(MathFloorOfDiv)                           \
    122   V(MathMinMax)                               \
    123   V(MaybeGrowElements)                        \
    124   V(Mod)                                      \
    125   V(Mul)                                      \
    126   V(OsrEntry)                                 \
    127   V(Parameter)                                \
    128   V(Power)                                    \
    129   V(Prologue)                                 \
    130   V(PushArguments)                            \
    131   V(Return)                                   \
    132   V(Ror)                                      \
    133   V(Sar)                                      \
    134   V(SeqStringGetChar)                         \
    135   V(SeqStringSetChar)                         \
    136   V(Shl)                                      \
    137   V(Shr)                                      \
    138   V(Simulate)                                 \
    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(Sub)                                      \
    152   V(ThisFunction)                             \
    153   V(ToFastProperties)                         \
    154   V(TransitionElementsKind)                   \
    155   V(TrapAllocationMemento)                    \
    156   V(Typeof)                                   \
    157   V(TypeofIsAndBranch)                        \
    158   V(UnaryMathOperation)                       \
    159   V(UnknownOSRValue)                          \
    160   V(UseConst)                                 \
    161   V(WrapReceiver)
    162 
    163 #define GVN_TRACKED_FLAG_LIST(V)               \
    164   V(NewSpacePromotion)
    165 
    166 #define GVN_UNTRACKED_FLAG_LIST(V)             \
    167   V(ArrayElements)                             \
    168   V(ArrayLengths)                              \
    169   V(StringLengths)                             \
    170   V(BackingStoreFields)                        \
    171   V(Calls)                                     \
    172   V(ContextSlots)                              \
    173   V(DoubleArrayElements)                       \
    174   V(DoubleFields)                              \
    175   V(ElementsKind)                              \
    176   V(ElementsPointer)                           \
    177   V(GlobalVars)                                \
    178   V(InobjectFields)                            \
    179   V(Maps)                                      \
    180   V(OsrEntries)                                \
    181   V(ExternalMemory)                            \
    182   V(StringChars)                               \
    183   V(TypedArrayElements)
    184 
    185 
    186 #define DECLARE_ABSTRACT_INSTRUCTION(type)     \
    187   bool Is##type() const final { return true; } \
    188   static H##type* cast(HValue* value) {        \
    189     DCHECK(value->Is##type());                 \
    190     return reinterpret_cast<H##type*>(value);  \
    191   }
    192 
    193 
    194 #define DECLARE_CONCRETE_INSTRUCTION(type)                      \
    195   LInstruction* CompileToLithium(LChunkBuilder* builder) final; \
    196   static H##type* cast(HValue* value) {                         \
    197     DCHECK(value->Is##type());                                  \
    198     return reinterpret_cast<H##type*>(value);                   \
    199   }                                                             \
    200   Opcode opcode() const final { return HValue::k##type; }
    201 
    202 
    203 enum PropertyAccessType { LOAD, STORE };
    204 
    205 
    206 class Range final : public ZoneObject {
    207  public:
    208   Range()
    209       : lower_(kMinInt),
    210         upper_(kMaxInt),
    211         next_(NULL),
    212         can_be_minus_zero_(false) { }
    213 
    214   Range(int32_t lower, int32_t upper)
    215       : lower_(lower),
    216         upper_(upper),
    217         next_(NULL),
    218         can_be_minus_zero_(false) { }
    219 
    220   int32_t upper() const { return upper_; }
    221   int32_t lower() const { return lower_; }
    222   Range* next() const { return next_; }
    223   Range* CopyClearLower(Zone* zone) const {
    224     return new(zone) Range(kMinInt, upper_);
    225   }
    226   Range* CopyClearUpper(Zone* zone) const {
    227     return new(zone) Range(lower_, kMaxInt);
    228   }
    229   Range* Copy(Zone* zone) const {
    230     Range* result = new(zone) Range(lower_, upper_);
    231     result->set_can_be_minus_zero(CanBeMinusZero());
    232     return result;
    233   }
    234   int32_t Mask() const;
    235   void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
    236   bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
    237   bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
    238   bool CanBeNegative() const { return lower_ < 0; }
    239   bool CanBePositive() const { return upper_ > 0; }
    240   bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
    241   bool IsMostGeneric() const {
    242     return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
    243   }
    244   bool IsInSmiRange() const {
    245     return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
    246   }
    247   void ClampToSmi() {
    248     lower_ = Max(lower_, Smi::kMinValue);
    249     upper_ = Min(upper_, Smi::kMaxValue);
    250   }
    251   void KeepOrder();
    252 #ifdef DEBUG
    253   void Verify() const;
    254 #endif
    255 
    256   void StackUpon(Range* other) {
    257     Intersect(other);
    258     next_ = other;
    259   }
    260 
    261   void Intersect(Range* other);
    262   void Union(Range* other);
    263   void CombinedMax(Range* other);
    264   void CombinedMin(Range* other);
    265 
    266   void AddConstant(int32_t value);
    267   void Sar(int32_t value);
    268   void Shl(int32_t value);
    269   bool AddAndCheckOverflow(const Representation& r, Range* other);
    270   bool SubAndCheckOverflow(const Representation& r, Range* other);
    271   bool MulAndCheckOverflow(const Representation& r, Range* other);
    272 
    273  private:
    274   int32_t lower_;
    275   int32_t upper_;
    276   Range* next_;
    277   bool can_be_minus_zero_;
    278 };
    279 
    280 
    281 class HUseListNode: public ZoneObject {
    282  public:
    283   HUseListNode(HValue* value, int index, HUseListNode* tail)
    284       : tail_(tail), value_(value), index_(index) {
    285   }
    286 
    287   HUseListNode* tail();
    288   HValue* value() const { return value_; }
    289   int index() const { return index_; }
    290 
    291   void set_tail(HUseListNode* list) { tail_ = list; }
    292 
    293 #ifdef DEBUG
    294   void Zap() {
    295     tail_ = reinterpret_cast<HUseListNode*>(1);
    296     value_ = NULL;
    297     index_ = -1;
    298   }
    299 #endif
    300 
    301  private:
    302   HUseListNode* tail_;
    303   HValue* value_;
    304   int index_;
    305 };
    306 
    307 
    308 // We reuse use list nodes behind the scenes as uses are added and deleted.
    309 // This class is the safe way to iterate uses while deleting them.
    310 class HUseIterator final BASE_EMBEDDED {
    311  public:
    312   bool Done() { return current_ == NULL; }
    313   void Advance();
    314 
    315   HValue* value() {
    316     DCHECK(!Done());
    317     return value_;
    318   }
    319 
    320   int index() {
    321     DCHECK(!Done());
    322     return index_;
    323   }
    324 
    325  private:
    326   explicit HUseIterator(HUseListNode* head);
    327 
    328   HUseListNode* current_;
    329   HUseListNode* next_;
    330   HValue* value_;
    331   int index_;
    332 
    333   friend class HValue;
    334 };
    335 
    336 
    337 // All tracked flags should appear before untracked ones.
    338 enum GVNFlag {
    339   // Declare global value numbering flags.
    340 #define DECLARE_FLAG(Type) k##Type,
    341   GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
    342   GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
    343 #undef DECLARE_FLAG
    344 #define COUNT_FLAG(Type) + 1
    345   kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG),
    346   kNumberOfUntrackedSideEffects = 0 GVN_UNTRACKED_FLAG_LIST(COUNT_FLAG),
    347 #undef COUNT_FLAG
    348   kNumberOfFlags = kNumberOfTrackedSideEffects + kNumberOfUntrackedSideEffects
    349 };
    350 
    351 
    352 static inline GVNFlag GVNFlagFromInt(int i) {
    353   DCHECK(i >= 0);
    354   DCHECK(i < kNumberOfFlags);
    355   return static_cast<GVNFlag>(i);
    356 }
    357 
    358 
    359 class DecompositionResult final BASE_EMBEDDED {
    360  public:
    361   DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
    362 
    363   HValue* base() { return base_; }
    364   int offset() { return offset_; }
    365   int scale() { return scale_; }
    366 
    367   bool Apply(HValue* other_base, int other_offset, int other_scale = 0) {
    368     if (base_ == NULL) {
    369       base_ = other_base;
    370       offset_ = other_offset;
    371       scale_ = other_scale;
    372       return true;
    373     } else {
    374       if (scale_ == 0) {
    375         base_ = other_base;
    376         offset_ += other_offset;
    377         scale_ = other_scale;
    378         return true;
    379       } else {
    380         return false;
    381       }
    382     }
    383   }
    384 
    385   void SwapValues(HValue** other_base, int* other_offset, int* other_scale) {
    386     swap(&base_, other_base);
    387     swap(&offset_, other_offset);
    388     swap(&scale_, other_scale);
    389   }
    390 
    391  private:
    392   template <class T> void swap(T* a, T* b) {
    393     T c(*a);
    394     *a = *b;
    395     *b = c;
    396   }
    397 
    398   HValue* base_;
    399   int offset_;
    400   int scale_;
    401 };
    402 
    403 
    404 typedef EnumSet<GVNFlag, int32_t> GVNFlagSet;
    405 
    406 
    407 class HValue : public ZoneObject {
    408  public:
    409   static const int kNoNumber = -1;
    410 
    411   enum Flag {
    412     kFlexibleRepresentation,
    413     kCannotBeTagged,
    414     // Participate in Global Value Numbering, i.e. elimination of
    415     // unnecessary recomputations. If an instruction sets this flag, it must
    416     // implement DataEquals(), which will be used to determine if other
    417     // occurrences of the instruction are indeed the same.
    418     kUseGVN,
    419     // Track instructions that are dominating side effects. If an instruction
    420     // sets this flag, it must implement HandleSideEffectDominator() and should
    421     // indicate which side effects to track by setting GVN flags.
    422     kTrackSideEffectDominators,
    423     kCanOverflow,
    424     kBailoutOnMinusZero,
    425     kCanBeDivByZero,
    426     kLeftCanBeMinInt,
    427     kLeftCanBeNegative,
    428     kLeftCanBePositive,
    429     kAllowUndefinedAsNaN,
    430     kIsArguments,
    431     kTruncatingToInt32,
    432     kAllUsesTruncatingToInt32,
    433     kTruncatingToSmi,
    434     kAllUsesTruncatingToSmi,
    435     // Set after an instruction is killed.
    436     kIsDead,
    437     // Instructions that are allowed to produce full range unsigned integer
    438     // values are marked with kUint32 flag. If arithmetic shift or a load from
    439     // EXTERNAL_UINT32_ELEMENTS array is not marked with this flag
    440     // it will deoptimize if result does not fit into signed integer range.
    441     // HGraph::ComputeSafeUint32Operations is responsible for setting this
    442     // flag.
    443     kUint32,
    444     kHasNoObservableSideEffects,
    445     // Indicates an instruction shouldn't be replaced by optimization, this flag
    446     // is useful to set in cases where recomputing a value is cheaper than
    447     // extending the value's live range and spilling it.
    448     kCantBeReplaced,
    449     // Indicates the instruction is live during dead code elimination.
    450     kIsLive,
    451 
    452     // HEnvironmentMarkers are deleted before dead code
    453     // elimination takes place, so they can repurpose the kIsLive flag:
    454     kEndsLiveRange = kIsLive,
    455 
    456     // TODO(everyone): Don't forget to update this!
    457     kLastFlag = kIsLive
    458   };
    459 
    460   STATIC_ASSERT(kLastFlag < kBitsPerInt);
    461 
    462   static HValue* cast(HValue* value) { return value; }
    463 
    464   enum Opcode {
    465     // Declare a unique enum value for each hydrogen instruction.
    466   #define DECLARE_OPCODE(type) k##type,
    467     HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
    468     kPhi
    469   #undef DECLARE_OPCODE
    470   };
    471   virtual Opcode opcode() const = 0;
    472 
    473   // Declare a non-virtual predicates for each concrete HInstruction or HValue.
    474   #define DECLARE_PREDICATE(type) \
    475     bool Is##type() const { return opcode() == k##type; }
    476     HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
    477   #undef DECLARE_PREDICATE
    478     bool IsPhi() const { return opcode() == kPhi; }
    479 
    480   // Declare virtual predicates for abstract HInstruction or HValue
    481   #define DECLARE_PREDICATE(type) \
    482     virtual bool Is##type() const { return false; }
    483     HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
    484   #undef DECLARE_PREDICATE
    485 
    486   bool IsBitwiseBinaryShift() {
    487     return IsShl() || IsShr() || IsSar();
    488   }
    489 
    490   explicit HValue(HType type = HType::Tagged())
    491       : block_(NULL),
    492         id_(kNoNumber),
    493         type_(type),
    494         use_list_(NULL),
    495         range_(NULL),
    496 #ifdef DEBUG
    497         range_poisoned_(false),
    498 #endif
    499         flags_(0) {}
    500   virtual ~HValue() {}
    501 
    502   virtual SourcePosition position() const { return SourcePosition::Unknown(); }
    503   virtual SourcePosition operand_position(int index) const {
    504     return position();
    505   }
    506 
    507   HBasicBlock* block() const { return block_; }
    508   void SetBlock(HBasicBlock* block);
    509 
    510   // Note: Never call this method for an unlinked value.
    511   Isolate* isolate() const;
    512 
    513   int id() const { return id_; }
    514   void set_id(int id) { id_ = id; }
    515 
    516   HUseIterator uses() const { return HUseIterator(use_list_); }
    517 
    518   virtual bool EmitAtUses() { return false; }
    519 
    520   Representation representation() const { return representation_; }
    521   void ChangeRepresentation(Representation r) {
    522     DCHECK(CheckFlag(kFlexibleRepresentation));
    523     DCHECK(!CheckFlag(kCannotBeTagged) || !r.IsTagged());
    524     RepresentationChanged(r);
    525     representation_ = r;
    526     if (r.IsTagged()) {
    527       // Tagged is the bottom of the lattice, don't go any further.
    528       ClearFlag(kFlexibleRepresentation);
    529     }
    530   }
    531   virtual void AssumeRepresentation(Representation r);
    532 
    533   virtual Representation KnownOptimalRepresentation() {
    534     Representation r = representation();
    535     if (r.IsTagged()) {
    536       HType t = type();
    537       if (t.IsSmi()) return Representation::Smi();
    538       if (t.IsHeapNumber()) return Representation::Double();
    539       if (t.IsHeapObject()) return r;
    540       return Representation::None();
    541     }
    542     return r;
    543   }
    544 
    545   HType type() const { return type_; }
    546   void set_type(HType new_type) {
    547     DCHECK(new_type.IsSubtypeOf(type_));
    548     type_ = new_type;
    549   }
    550 
    551   // There are HInstructions that do not really change a value, they
    552   // only add pieces of information to it (like bounds checks, map checks,
    553   // smi checks...).
    554   // We call these instructions "informative definitions", or "iDef".
    555   // One of the iDef operands is special because it is the value that is
    556   // "transferred" to the output, we call it the "redefined operand".
    557   // If an HValue is an iDef it must override RedefinedOperandIndex() so that
    558   // it does not return kNoRedefinedOperand;
    559   static const int kNoRedefinedOperand = -1;
    560   virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
    561   bool IsInformativeDefinition() {
    562     return RedefinedOperandIndex() != kNoRedefinedOperand;
    563   }
    564   HValue* RedefinedOperand() {
    565     int index = RedefinedOperandIndex();
    566     return index == kNoRedefinedOperand ? NULL : OperandAt(index);
    567   }
    568 
    569   bool CanReplaceWithDummyUses();
    570 
    571   virtual int argument_delta() const { return 0; }
    572 
    573   // A purely informative definition is an idef that will not emit code and
    574   // should therefore be removed from the graph in the RestoreActualValues
    575   // phase (so that live ranges will be shorter).
    576   virtual bool IsPurelyInformativeDefinition() { return false; }
    577 
    578   // This method must always return the original HValue SSA definition,
    579   // regardless of any chain of iDefs of this value.
    580   HValue* ActualValue() {
    581     HValue* value = this;
    582     int index;
    583     while ((index = value->RedefinedOperandIndex()) != kNoRedefinedOperand) {
    584       value = value->OperandAt(index);
    585     }
    586     return value;
    587   }
    588 
    589   bool IsInteger32Constant();
    590   int32_t GetInteger32Constant();
    591   bool EqualsInteger32Constant(int32_t value);
    592 
    593   bool IsDefinedAfter(HBasicBlock* other) const;
    594 
    595   // Operands.
    596   virtual int OperandCount() const = 0;
    597   virtual HValue* OperandAt(int index) const = 0;
    598   void SetOperandAt(int index, HValue* value);
    599 
    600   void DeleteAndReplaceWith(HValue* other);
    601   void ReplaceAllUsesWith(HValue* other);
    602   bool HasNoUses() const { return use_list_ == NULL; }
    603   bool HasOneUse() const {
    604     return use_list_ != NULL && use_list_->tail() == NULL;
    605   }
    606   bool HasMultipleUses() const {
    607     return use_list_ != NULL && use_list_->tail() != NULL;
    608   }
    609   int UseCount() const;
    610 
    611   // Mark this HValue as dead and to be removed from other HValues' use lists.
    612   void Kill();
    613 
    614   int flags() const { return flags_; }
    615   void SetFlag(Flag f) { flags_ |= (1 << f); }
    616   void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
    617   bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
    618   void CopyFlag(Flag f, HValue* other) {
    619     if (other->CheckFlag(f)) SetFlag(f);
    620   }
    621 
    622   // Returns true if the flag specified is set for all uses, false otherwise.
    623   bool CheckUsesForFlag(Flag f) const;
    624   // Same as before and the first one without the flag is returned in value.
    625   bool CheckUsesForFlag(Flag f, HValue** value) const;
    626   // Returns true if the flag specified is set for all uses, and this set
    627   // of uses is non-empty.
    628   bool HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const;
    629 
    630   GVNFlagSet ChangesFlags() const { return changes_flags_; }
    631   GVNFlagSet DependsOnFlags() const { return depends_on_flags_; }
    632   void SetChangesFlag(GVNFlag f) { changes_flags_.Add(f); }
    633   void SetDependsOnFlag(GVNFlag f) { depends_on_flags_.Add(f); }
    634   void ClearChangesFlag(GVNFlag f) { changes_flags_.Remove(f); }
    635   void ClearDependsOnFlag(GVNFlag f) { depends_on_flags_.Remove(f); }
    636   bool CheckChangesFlag(GVNFlag f) const {
    637     return changes_flags_.Contains(f);
    638   }
    639   bool CheckDependsOnFlag(GVNFlag f) const {
    640     return depends_on_flags_.Contains(f);
    641   }
    642   void SetAllSideEffects() { changes_flags_.Add(AllSideEffectsFlagSet()); }
    643   void ClearAllSideEffects() {
    644     changes_flags_.Remove(AllSideEffectsFlagSet());
    645   }
    646   bool HasSideEffects() const {
    647     return changes_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
    648   }
    649   bool HasObservableSideEffects() const {
    650     return !CheckFlag(kHasNoObservableSideEffects) &&
    651         changes_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
    652   }
    653 
    654   GVNFlagSet SideEffectFlags() const {
    655     GVNFlagSet result = ChangesFlags();
    656     result.Intersect(AllSideEffectsFlagSet());
    657     return result;
    658   }
    659 
    660   GVNFlagSet ObservableChangesFlags() const {
    661     GVNFlagSet result = ChangesFlags();
    662     result.Intersect(AllObservableSideEffectsFlagSet());
    663     return result;
    664   }
    665 
    666   Range* range() const {
    667     DCHECK(!range_poisoned_);
    668     return range_;
    669   }
    670   bool HasRange() const {
    671     DCHECK(!range_poisoned_);
    672     return range_ != NULL;
    673   }
    674 #ifdef DEBUG
    675   void PoisonRange() { range_poisoned_ = true; }
    676 #endif
    677   void AddNewRange(Range* r, Zone* zone);
    678   void RemoveLastAddedRange();
    679   void ComputeInitialRange(Zone* zone);
    680 
    681   // Escape analysis helpers.
    682   virtual bool HasEscapingOperandAt(int index) { return true; }
    683   virtual bool HasOutOfBoundsAccess(int size) { return false; }
    684 
    685   // Representation helpers.
    686   virtual Representation observed_input_representation(int index) {
    687     return Representation::None();
    688   }
    689   virtual Representation RequiredInputRepresentation(int index) = 0;
    690   virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
    691 
    692   // This gives the instruction an opportunity to replace itself with an
    693   // instruction that does the same in some better way.  To replace an
    694   // instruction with a new one, first add the new instruction to the graph,
    695   // then return it.  Return NULL to have the instruction deleted.
    696   virtual HValue* Canonicalize() { return this; }
    697 
    698   bool Equals(HValue* other);
    699   virtual intptr_t Hashcode();
    700 
    701   // Compute unique ids upfront that is safe wrt GC and concurrent compilation.
    702   virtual void FinalizeUniqueness() { }
    703 
    704   // Printing support.
    705   virtual std::ostream& PrintTo(std::ostream& os) const = 0;  // NOLINT
    706 
    707   const char* Mnemonic() const;
    708 
    709   // Type information helpers.
    710   bool HasMonomorphicJSObjectType();
    711 
    712   // TODO(mstarzinger): For now instructions can override this function to
    713   // specify statically known types, once HType can convey more information
    714   // it should be based on the HType.
    715   virtual Handle<Map> GetMonomorphicJSObjectMap() { return Handle<Map>(); }
    716 
    717   // Updated the inferred type of this instruction and returns true if
    718   // it has changed.
    719   bool UpdateInferredType();
    720 
    721   virtual HType CalculateInferredType();
    722 
    723   // This function must be overridden for instructions which have the
    724   // kTrackSideEffectDominators flag set, to track instructions that are
    725   // dominating side effects.
    726   // It returns true if it removed an instruction which had side effects.
    727   virtual bool HandleSideEffectDominator(GVNFlag side_effect,
    728                                          HValue* dominator) {
    729     UNREACHABLE();
    730     return false;
    731   }
    732 
    733   // Check if this instruction has some reason that prevents elimination.
    734   bool CannotBeEliminated() const {
    735     return HasObservableSideEffects() || !IsDeletable();
    736   }
    737 
    738 #ifdef DEBUG
    739   virtual void Verify() = 0;
    740 #endif
    741 
    742   virtual bool TryDecompose(DecompositionResult* decomposition) {
    743     if (RedefinedOperand() != NULL) {
    744       return RedefinedOperand()->TryDecompose(decomposition);
    745     } else {
    746       return false;
    747     }
    748   }
    749 
    750   // Returns true conservatively if the program might be able to observe a
    751   // ToString() operation on this value.
    752   bool ToStringCanBeObserved() const {
    753     return ToStringOrToNumberCanBeObserved();
    754   }
    755 
    756   // Returns true conservatively if the program might be able to observe a
    757   // ToNumber() operation on this value.
    758   bool ToNumberCanBeObserved() const {
    759     return ToStringOrToNumberCanBeObserved();
    760   }
    761 
    762   MinusZeroMode GetMinusZeroMode() {
    763     return CheckFlag(kBailoutOnMinusZero)
    764         ? FAIL_ON_MINUS_ZERO : TREAT_MINUS_ZERO_AS_ZERO;
    765   }
    766 
    767  protected:
    768   // This function must be overridden for instructions with flag kUseGVN, to
    769   // compare the non-Operand parts of the instruction.
    770   virtual bool DataEquals(HValue* other) {
    771     UNREACHABLE();
    772     return false;
    773   }
    774 
    775   bool ToStringOrToNumberCanBeObserved() const {
    776     if (type().IsTaggedPrimitive()) return false;
    777     if (type().IsJSReceiver()) return true;
    778     return !representation().IsSmiOrInteger32() && !representation().IsDouble();
    779   }
    780 
    781   virtual Representation RepresentationFromInputs() {
    782     return representation();
    783   }
    784   virtual Representation RepresentationFromUses();
    785   Representation RepresentationFromUseRequirements();
    786   bool HasNonSmiUse();
    787   virtual void UpdateRepresentation(Representation new_rep,
    788                                     HInferRepresentationPhase* h_infer,
    789                                     const char* reason);
    790   void AddDependantsToWorklist(HInferRepresentationPhase* h_infer);
    791 
    792   virtual void RepresentationChanged(Representation to) { }
    793 
    794   virtual Range* InferRange(Zone* zone);
    795   virtual void DeleteFromGraph() = 0;
    796   virtual void InternalSetOperandAt(int index, HValue* value) = 0;
    797   void clear_block() {
    798     DCHECK(block_ != NULL);
    799     block_ = NULL;
    800   }
    801 
    802   void set_representation(Representation r) {
    803     DCHECK(representation_.IsNone() && !r.IsNone());
    804     representation_ = r;
    805   }
    806 
    807   static GVNFlagSet AllFlagSet() {
    808     GVNFlagSet result;
    809 #define ADD_FLAG(Type) result.Add(k##Type);
    810   GVN_TRACKED_FLAG_LIST(ADD_FLAG)
    811   GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
    812 #undef ADD_FLAG
    813     return result;
    814   }
    815 
    816   // A flag mask to mark an instruction as having arbitrary side effects.
    817   static GVNFlagSet AllSideEffectsFlagSet() {
    818     GVNFlagSet result = AllFlagSet();
    819     result.Remove(kOsrEntries);
    820     return result;
    821   }
    822   friend std::ostream& operator<<(std::ostream& os, const ChangesOf& v);
    823 
    824   // A flag mask of all side effects that can make observable changes in
    825   // an executing program (i.e. are not safe to repeat, move or remove);
    826   static GVNFlagSet AllObservableSideEffectsFlagSet() {
    827     GVNFlagSet result = AllFlagSet();
    828     result.Remove(kNewSpacePromotion);
    829     result.Remove(kElementsKind);
    830     result.Remove(kElementsPointer);
    831     result.Remove(kMaps);
    832     return result;
    833   }
    834 
    835   // Remove the matching use from the use list if present.  Returns the
    836   // removed list node or NULL.
    837   HUseListNode* RemoveUse(HValue* value, int index);
    838 
    839   void RegisterUse(int index, HValue* new_value);
    840 
    841   HBasicBlock* block_;
    842 
    843   // The id of this instruction in the hydrogen graph, assigned when first
    844   // added to the graph. Reflects creation order.
    845   int id_;
    846 
    847   Representation representation_;
    848   HType type_;
    849   HUseListNode* use_list_;
    850   Range* range_;
    851 #ifdef DEBUG
    852   bool range_poisoned_;
    853 #endif
    854   int flags_;
    855   GVNFlagSet changes_flags_;
    856   GVNFlagSet depends_on_flags_;
    857 
    858  private:
    859   virtual bool IsDeletable() const { return false; }
    860 
    861   DISALLOW_COPY_AND_ASSIGN(HValue);
    862 };
    863 
    864 // Support for printing various aspects of an HValue.
    865 struct NameOf {
    866   explicit NameOf(const HValue* const v) : value(v) {}
    867   const HValue* value;
    868 };
    869 
    870 
    871 struct TypeOf {
    872   explicit TypeOf(const HValue* const v) : value(v) {}
    873   const HValue* value;
    874 };
    875 
    876 
    877 struct ChangesOf {
    878   explicit ChangesOf(const HValue* const v) : value(v) {}
    879   const HValue* value;
    880 };
    881 
    882 
    883 std::ostream& operator<<(std::ostream& os, const HValue& v);
    884 std::ostream& operator<<(std::ostream& os, const NameOf& v);
    885 std::ostream& operator<<(std::ostream& os, const TypeOf& v);
    886 std::ostream& operator<<(std::ostream& os, const ChangesOf& v);
    887 
    888 
    889 #define DECLARE_INSTRUCTION_FACTORY_P0(I)                        \
    890   static I* New(Isolate* isolate, Zone* zone, HValue* context) { \
    891     return new (zone) I();                                       \
    892   }
    893 
    894 #define DECLARE_INSTRUCTION_FACTORY_P1(I, P1)                           \
    895   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1) { \
    896     return new (zone) I(p1);                                            \
    897   }
    898 
    899 #define DECLARE_INSTRUCTION_FACTORY_P2(I, P1, P2)                              \
    900   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2) { \
    901     return new (zone) I(p1, p2);                                               \
    902   }
    903 
    904 #define DECLARE_INSTRUCTION_FACTORY_P3(I, P1, P2, P3)                        \
    905   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
    906                 P3 p3) {                                                     \
    907     return new (zone) I(p1, p2, p3);                                         \
    908   }
    909 
    910 #define DECLARE_INSTRUCTION_FACTORY_P4(I, P1, P2, P3, P4)                    \
    911   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
    912                 P3 p3, P4 p4) {                                              \
    913     return new (zone) I(p1, p2, p3, p4);                                     \
    914   }
    915 
    916 #define DECLARE_INSTRUCTION_FACTORY_P5(I, P1, P2, P3, P4, P5)                \
    917   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
    918                 P3 p3, P4 p4, P5 p5) {                                       \
    919     return new (zone) I(p1, p2, p3, p4, p5);                                 \
    920   }
    921 
    922 #define DECLARE_INSTRUCTION_FACTORY_P6(I, P1, P2, P3, P4, P5, P6)            \
    923   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
    924                 P3 p3, P4 p4, P5 p5, P6 p6) {                                \
    925     return new (zone) I(p1, p2, p3, p4, p5, p6);                             \
    926   }
    927 
    928 #define DECLARE_INSTRUCTION_FACTORY_P7(I, P1, P2, P3, P4, P5, P6, P7)        \
    929   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
    930                 P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {                         \
    931     return new (zone) I(p1, p2, p3, p4, p5, p6, p7);                         \
    932   }
    933 
    934 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(I)           \
    935   static I* New(Isolate* isolate, Zone* zone, HValue* context) { \
    936     return new (zone) I(context);                                \
    937   }
    938 
    939 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(I, P1)              \
    940   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1) { \
    941     return new (zone) I(context, p1);                                   \
    942   }
    943 
    944 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(I, P1, P2)                 \
    945   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2) { \
    946     return new (zone) I(context, p1, p2);                                      \
    947   }
    948 
    949 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(I, P1, P2, P3)           \
    950   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
    951                 P3 p3) {                                                     \
    952     return new (zone) I(context, p1, p2, p3);                                \
    953   }
    954 
    955 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(I, P1, P2, P3, P4)       \
    956   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
    957                 P3 p3, P4 p4) {                                              \
    958     return new (zone) I(context, p1, p2, p3, p4);                            \
    959   }
    960 
    961 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(I, P1, P2, P3, P4, P5)   \
    962   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
    963                 P3 p3, P4 p4, P5 p5) {                                       \
    964     return new (zone) I(context, p1, p2, p3, p4, p5);                        \
    965   }
    966 
    967 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(I, P1, P2, P3, P4, P5, P6) \
    968   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2,   \
    969                 P3 p3, P4 p4, P5 p5, P6 p6) {                                  \
    970     return new (zone) I(context, p1, p2, p3, p4, p5, p6);                      \
    971   }
    972 
    973 
    974 // A helper class to represent per-operand position information attached to
    975 // the HInstruction in the compact form. Uses tagging to distinguish between
    976 // case when only instruction's position is available and case when operands'
    977 // positions are also available.
    978 // In the first case it contains intruction's position as a tagged value.
    979 // In the second case it points to an array which contains instruction's
    980 // position and operands' positions.
    981 class HPositionInfo {
    982  public:
    983   explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { }
    984 
    985   SourcePosition position() const {
    986     if (has_operand_positions()) {
    987       return operand_positions()[kInstructionPosIndex];
    988     }
    989     return SourcePosition::FromRaw(static_cast<int>(UntagPosition(data_)));
    990   }
    991 
    992   void set_position(SourcePosition pos) {
    993     if (has_operand_positions()) {
    994       operand_positions()[kInstructionPosIndex] = pos;
    995     } else {
    996       data_ = TagPosition(pos.raw());
    997     }
    998   }
    999 
   1000   void ensure_storage_for_operand_positions(Zone* zone, int operand_count) {
   1001     if (has_operand_positions()) {
   1002       return;
   1003     }
   1004 
   1005     const int length = kFirstOperandPosIndex + operand_count;
   1006     SourcePosition* positions = zone->NewArray<SourcePosition>(length);
   1007     for (int i = 0; i < length; i++) {
   1008       positions[i] = SourcePosition::Unknown();
   1009     }
   1010 
   1011     const SourcePosition pos = position();
   1012     data_ = reinterpret_cast<intptr_t>(positions);
   1013     set_position(pos);
   1014 
   1015     DCHECK(has_operand_positions());
   1016   }
   1017 
   1018   SourcePosition operand_position(int idx) const {
   1019     if (!has_operand_positions()) {
   1020       return position();
   1021     }
   1022     return *operand_position_slot(idx);
   1023   }
   1024 
   1025   void set_operand_position(int idx, SourcePosition pos) {
   1026     *operand_position_slot(idx) = pos;
   1027   }
   1028 
   1029  private:
   1030   static const intptr_t kInstructionPosIndex = 0;
   1031   static const intptr_t kFirstOperandPosIndex = 1;
   1032 
   1033   SourcePosition* operand_position_slot(int idx) const {
   1034     DCHECK(has_operand_positions());
   1035     return &(operand_positions()[kFirstOperandPosIndex + idx]);
   1036   }
   1037 
   1038   bool has_operand_positions() const {
   1039     return !IsTaggedPosition(data_);
   1040   }
   1041 
   1042   SourcePosition* operand_positions() const {
   1043     DCHECK(has_operand_positions());
   1044     return reinterpret_cast<SourcePosition*>(data_);
   1045   }
   1046 
   1047   static const intptr_t kPositionTag = 1;
   1048   static const intptr_t kPositionShift = 1;
   1049   static bool IsTaggedPosition(intptr_t val) {
   1050     return (val & kPositionTag) != 0;
   1051   }
   1052   static intptr_t UntagPosition(intptr_t val) {
   1053     DCHECK(IsTaggedPosition(val));
   1054     return val >> kPositionShift;
   1055   }
   1056   static intptr_t TagPosition(intptr_t val) {
   1057     const intptr_t result = (val << kPositionShift) | kPositionTag;
   1058     DCHECK(UntagPosition(result) == val);
   1059     return result;
   1060   }
   1061 
   1062   intptr_t data_;
   1063 };
   1064 
   1065 
   1066 class HInstruction : public HValue {
   1067  public:
   1068   HInstruction* next() const { return next_; }
   1069   HInstruction* previous() const { return previous_; }
   1070 
   1071   std::ostream& PrintTo(std::ostream& os) const override;          // NOLINT
   1072   virtual std::ostream& PrintDataTo(std::ostream& os) const;       // NOLINT
   1073 
   1074   bool IsLinked() const { return block() != NULL; }
   1075   void Unlink();
   1076 
   1077   void InsertBefore(HInstruction* next);
   1078 
   1079   template<class T> T* Prepend(T* instr) {
   1080     instr->InsertBefore(this);
   1081     return instr;
   1082   }
   1083 
   1084   void InsertAfter(HInstruction* previous);
   1085 
   1086   template<class T> T* Append(T* instr) {
   1087     instr->InsertAfter(this);
   1088     return instr;
   1089   }
   1090 
   1091   // The position is a write-once variable.
   1092   SourcePosition position() const override {
   1093     return SourcePosition(position_.position());
   1094   }
   1095   bool has_position() const {
   1096     return !position().IsUnknown();
   1097   }
   1098   void set_position(SourcePosition position) {
   1099     DCHECK(!has_position());
   1100     DCHECK(!position.IsUnknown());
   1101     position_.set_position(position);
   1102   }
   1103 
   1104   SourcePosition operand_position(int index) const override {
   1105     const SourcePosition pos = position_.operand_position(index);
   1106     return pos.IsUnknown() ? position() : pos;
   1107   }
   1108   void set_operand_position(Zone* zone, int index, SourcePosition pos) {
   1109     DCHECK(0 <= index && index < OperandCount());
   1110     position_.ensure_storage_for_operand_positions(zone, OperandCount());
   1111     position_.set_operand_position(index, pos);
   1112   }
   1113 
   1114   bool Dominates(HInstruction* other);
   1115   bool CanTruncateToSmi() const { return CheckFlag(kTruncatingToSmi); }
   1116   bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
   1117 
   1118   virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
   1119 
   1120 #ifdef DEBUG
   1121   void Verify() override;
   1122 #endif
   1123 
   1124   bool CanDeoptimize();
   1125 
   1126   virtual bool HasStackCheck() { return false; }
   1127 
   1128   DECLARE_ABSTRACT_INSTRUCTION(Instruction)
   1129 
   1130  protected:
   1131   explicit HInstruction(HType type = HType::Tagged())
   1132       : HValue(type),
   1133         next_(NULL),
   1134         previous_(NULL),
   1135         position_(RelocInfo::kNoPosition) {
   1136     SetDependsOnFlag(kOsrEntries);
   1137   }
   1138 
   1139   void DeleteFromGraph() override { Unlink(); }
   1140 
   1141  private:
   1142   void InitializeAsFirst(HBasicBlock* block) {
   1143     DCHECK(!IsLinked());
   1144     SetBlock(block);
   1145   }
   1146 
   1147   HInstruction* next_;
   1148   HInstruction* previous_;
   1149   HPositionInfo position_;
   1150 
   1151   friend class HBasicBlock;
   1152 };
   1153 
   1154 
   1155 template<int V>
   1156 class HTemplateInstruction : public HInstruction {
   1157  public:
   1158   int OperandCount() const final { return V; }
   1159   HValue* OperandAt(int i) const final { return inputs_[i]; }
   1160 
   1161  protected:
   1162   explicit HTemplateInstruction(HType type = HType::Tagged())
   1163       : HInstruction(type) {}
   1164 
   1165   void InternalSetOperandAt(int i, HValue* value) final { inputs_[i] = value; }
   1166 
   1167  private:
   1168   EmbeddedContainer<HValue*, V> inputs_;
   1169 };
   1170 
   1171 
   1172 class HControlInstruction : public HInstruction {
   1173  public:
   1174   virtual HBasicBlock* SuccessorAt(int i) const = 0;
   1175   virtual int SuccessorCount() const = 0;
   1176   virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
   1177 
   1178   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1179 
   1180   virtual bool KnownSuccessorBlock(HBasicBlock** block) {
   1181     *block = NULL;
   1182     return false;
   1183   }
   1184 
   1185   HBasicBlock* FirstSuccessor() {
   1186     return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
   1187   }
   1188   HBasicBlock* SecondSuccessor() {
   1189     return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
   1190   }
   1191 
   1192   void Not() {
   1193     HBasicBlock* swap = SuccessorAt(0);
   1194     SetSuccessorAt(0, SuccessorAt(1));
   1195     SetSuccessorAt(1, swap);
   1196   }
   1197 
   1198   DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
   1199 };
   1200 
   1201 
   1202 class HSuccessorIterator final BASE_EMBEDDED {
   1203  public:
   1204   explicit HSuccessorIterator(const HControlInstruction* instr)
   1205       : instr_(instr), current_(0) {}
   1206 
   1207   bool Done() { return current_ >= instr_->SuccessorCount(); }
   1208   HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
   1209   void Advance() { current_++; }
   1210 
   1211  private:
   1212   const HControlInstruction* instr_;
   1213   int current_;
   1214 };
   1215 
   1216 
   1217 template<int S, int V>
   1218 class HTemplateControlInstruction : public HControlInstruction {
   1219  public:
   1220   int SuccessorCount() const override { return S; }
   1221   HBasicBlock* SuccessorAt(int i) const override { return successors_[i]; }
   1222   void SetSuccessorAt(int i, HBasicBlock* block) override {
   1223     successors_[i] = block;
   1224   }
   1225 
   1226   int OperandCount() const override { return V; }
   1227   HValue* OperandAt(int i) const override { return inputs_[i]; }
   1228 
   1229 
   1230  protected:
   1231   void InternalSetOperandAt(int i, HValue* value) override {
   1232     inputs_[i] = value;
   1233   }
   1234 
   1235  private:
   1236   EmbeddedContainer<HBasicBlock*, S> successors_;
   1237   EmbeddedContainer<HValue*, V> inputs_;
   1238 };
   1239 
   1240 
   1241 class HBlockEntry final : public HTemplateInstruction<0> {
   1242  public:
   1243   Representation RequiredInputRepresentation(int index) override {
   1244     return Representation::None();
   1245   }
   1246 
   1247   DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
   1248 };
   1249 
   1250 
   1251 class HDummyUse final : public HTemplateInstruction<1> {
   1252  public:
   1253   explicit HDummyUse(HValue* value)
   1254       : HTemplateInstruction<1>(HType::Smi()) {
   1255     SetOperandAt(0, value);
   1256     // Pretend to be a Smi so that the HChange instructions inserted
   1257     // before any use generate as little code as possible.
   1258     set_representation(Representation::Tagged());
   1259   }
   1260 
   1261   HValue* value() const { return OperandAt(0); }
   1262 
   1263   bool HasEscapingOperandAt(int index) override { return false; }
   1264   Representation RequiredInputRepresentation(int index) override {
   1265     return Representation::None();
   1266   }
   1267 
   1268   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1269 
   1270   DECLARE_CONCRETE_INSTRUCTION(DummyUse);
   1271 };
   1272 
   1273 
   1274 // Inserts an int3/stop break instruction for debugging purposes.
   1275 class HDebugBreak final : public HTemplateInstruction<0> {
   1276  public:
   1277   DECLARE_INSTRUCTION_FACTORY_P0(HDebugBreak);
   1278 
   1279   Representation RequiredInputRepresentation(int index) override {
   1280     return Representation::None();
   1281   }
   1282 
   1283   DECLARE_CONCRETE_INSTRUCTION(DebugBreak)
   1284 };
   1285 
   1286 
   1287 class HPrologue final : public HTemplateInstruction<0> {
   1288  public:
   1289   static HPrologue* New(Zone* zone) { return new (zone) HPrologue(); }
   1290 
   1291   Representation RequiredInputRepresentation(int index) override {
   1292     return Representation::None();
   1293   }
   1294 
   1295   DECLARE_CONCRETE_INSTRUCTION(Prologue)
   1296 };
   1297 
   1298 
   1299 class HGoto final : public HTemplateControlInstruction<1, 0> {
   1300  public:
   1301   explicit HGoto(HBasicBlock* target) {
   1302     SetSuccessorAt(0, target);
   1303   }
   1304 
   1305   bool KnownSuccessorBlock(HBasicBlock** block) override {
   1306     *block = FirstSuccessor();
   1307     return true;
   1308   }
   1309 
   1310   Representation RequiredInputRepresentation(int index) override {
   1311     return Representation::None();
   1312   }
   1313 
   1314   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1315 
   1316   DECLARE_CONCRETE_INSTRUCTION(Goto)
   1317 };
   1318 
   1319 
   1320 class HDeoptimize final : public HTemplateControlInstruction<1, 0> {
   1321  public:
   1322   static HDeoptimize* New(Isolate* isolate, Zone* zone, HValue* context,
   1323                           Deoptimizer::DeoptReason reason,
   1324                           Deoptimizer::BailoutType type,
   1325                           HBasicBlock* unreachable_continuation) {
   1326     return new(zone) HDeoptimize(reason, type, unreachable_continuation);
   1327   }
   1328 
   1329   bool KnownSuccessorBlock(HBasicBlock** block) override {
   1330     *block = NULL;
   1331     return true;
   1332   }
   1333 
   1334   Representation RequiredInputRepresentation(int index) override {
   1335     return Representation::None();
   1336   }
   1337 
   1338   Deoptimizer::DeoptReason reason() const { return reason_; }
   1339   Deoptimizer::BailoutType type() { return type_; }
   1340 
   1341   DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
   1342 
   1343  private:
   1344   explicit HDeoptimize(Deoptimizer::DeoptReason reason,
   1345                        Deoptimizer::BailoutType type,
   1346                        HBasicBlock* unreachable_continuation)
   1347       : reason_(reason), type_(type) {
   1348     SetSuccessorAt(0, unreachable_continuation);
   1349   }
   1350 
   1351   Deoptimizer::DeoptReason reason_;
   1352   Deoptimizer::BailoutType type_;
   1353 };
   1354 
   1355 
   1356 class HUnaryControlInstruction : public HTemplateControlInstruction<2, 1> {
   1357  public:
   1358   HUnaryControlInstruction(HValue* value,
   1359                            HBasicBlock* true_target,
   1360                            HBasicBlock* false_target) {
   1361     SetOperandAt(0, value);
   1362     SetSuccessorAt(0, true_target);
   1363     SetSuccessorAt(1, false_target);
   1364   }
   1365 
   1366   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1367 
   1368   HValue* value() const { return OperandAt(0); }
   1369 };
   1370 
   1371 
   1372 class HBranch final : public HUnaryControlInstruction {
   1373  public:
   1374   DECLARE_INSTRUCTION_FACTORY_P1(HBranch, HValue*);
   1375   DECLARE_INSTRUCTION_FACTORY_P2(HBranch, HValue*,
   1376                                  ToBooleanStub::Types);
   1377   DECLARE_INSTRUCTION_FACTORY_P4(HBranch, HValue*,
   1378                                  ToBooleanStub::Types,
   1379                                  HBasicBlock*, HBasicBlock*);
   1380 
   1381   Representation RequiredInputRepresentation(int index) override {
   1382     return Representation::None();
   1383   }
   1384   Representation observed_input_representation(int index) override;
   1385 
   1386   bool KnownSuccessorBlock(HBasicBlock** block) override;
   1387 
   1388   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1389 
   1390   ToBooleanStub::Types expected_input_types() const {
   1391     return expected_input_types_;
   1392   }
   1393 
   1394   DECLARE_CONCRETE_INSTRUCTION(Branch)
   1395 
   1396  private:
   1397   HBranch(HValue* value,
   1398           ToBooleanStub::Types expected_input_types = ToBooleanStub::Types(),
   1399           HBasicBlock* true_target = NULL,
   1400           HBasicBlock* false_target = NULL)
   1401       : HUnaryControlInstruction(value, true_target, false_target),
   1402         expected_input_types_(expected_input_types) {
   1403     SetFlag(kAllowUndefinedAsNaN);
   1404   }
   1405 
   1406   ToBooleanStub::Types expected_input_types_;
   1407 };
   1408 
   1409 
   1410 class HCompareMap final : public HUnaryControlInstruction {
   1411  public:
   1412   DECLARE_INSTRUCTION_FACTORY_P2(HCompareMap, HValue*, Handle<Map>);
   1413   DECLARE_INSTRUCTION_FACTORY_P4(HCompareMap, HValue*, Handle<Map>,
   1414                                  HBasicBlock*, HBasicBlock*);
   1415 
   1416   bool KnownSuccessorBlock(HBasicBlock** block) override {
   1417     if (known_successor_index() != kNoKnownSuccessorIndex) {
   1418       *block = SuccessorAt(known_successor_index());
   1419       return true;
   1420     }
   1421     *block = NULL;
   1422     return false;
   1423   }
   1424 
   1425   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1426 
   1427   static const int kNoKnownSuccessorIndex = -1;
   1428   int known_successor_index() const {
   1429     return KnownSuccessorIndexField::decode(bit_field_) -
   1430            kInternalKnownSuccessorOffset;
   1431   }
   1432   void set_known_successor_index(int index) {
   1433     DCHECK(index >= 0 - kInternalKnownSuccessorOffset);
   1434     bit_field_ = KnownSuccessorIndexField::update(
   1435         bit_field_, index + kInternalKnownSuccessorOffset);
   1436   }
   1437 
   1438   Unique<Map> map() const { return map_; }
   1439   bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }
   1440 
   1441   Representation RequiredInputRepresentation(int index) override {
   1442     return Representation::Tagged();
   1443   }
   1444 
   1445   DECLARE_CONCRETE_INSTRUCTION(CompareMap)
   1446 
   1447  protected:
   1448   int RedefinedOperandIndex() override { return 0; }
   1449 
   1450  private:
   1451   HCompareMap(HValue* value, Handle<Map> map, HBasicBlock* true_target = NULL,
   1452               HBasicBlock* false_target = NULL)
   1453       : HUnaryControlInstruction(value, true_target, false_target),
   1454         bit_field_(KnownSuccessorIndexField::encode(
   1455                        kNoKnownSuccessorIndex + kInternalKnownSuccessorOffset) |
   1456                    MapIsStableField::encode(map->is_stable())),
   1457         map_(Unique<Map>::CreateImmovable(map)) {
   1458     set_representation(Representation::Tagged());
   1459   }
   1460 
   1461   // BitFields can only store unsigned values, so use an offset.
   1462   // Adding kInternalKnownSuccessorOffset must yield an unsigned value.
   1463   static const int kInternalKnownSuccessorOffset = 1;
   1464   STATIC_ASSERT(kNoKnownSuccessorIndex + kInternalKnownSuccessorOffset >= 0);
   1465 
   1466   class KnownSuccessorIndexField : public BitField<int, 0, 31> {};
   1467   class MapIsStableField : public BitField<bool, 31, 1> {};
   1468 
   1469   uint32_t bit_field_;
   1470   Unique<Map> map_;
   1471 };
   1472 
   1473 
   1474 class HContext final : public HTemplateInstruction<0> {
   1475  public:
   1476   static HContext* New(Zone* zone) {
   1477     return new(zone) HContext();
   1478   }
   1479 
   1480   Representation RequiredInputRepresentation(int index) override {
   1481     return Representation::None();
   1482   }
   1483 
   1484   DECLARE_CONCRETE_INSTRUCTION(Context)
   1485 
   1486  protected:
   1487   bool DataEquals(HValue* other) override { return true; }
   1488 
   1489  private:
   1490   HContext() {
   1491     set_representation(Representation::Tagged());
   1492     SetFlag(kUseGVN);
   1493   }
   1494 
   1495   bool IsDeletable() const override { return true; }
   1496 };
   1497 
   1498 
   1499 class HReturn final : public HTemplateControlInstruction<0, 3> {
   1500  public:
   1501   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HReturn, HValue*, HValue*);
   1502   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HReturn, HValue*);
   1503 
   1504   Representation RequiredInputRepresentation(int index) override {
   1505     // TODO(titzer): require an Int32 input for faster returns.
   1506     if (index == 2) return Representation::Smi();
   1507     return Representation::Tagged();
   1508   }
   1509 
   1510   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1511 
   1512   HValue* value() const { return OperandAt(0); }
   1513   HValue* context() const { return OperandAt(1); }
   1514   HValue* parameter_count() const { return OperandAt(2); }
   1515 
   1516   DECLARE_CONCRETE_INSTRUCTION(Return)
   1517 
   1518  private:
   1519   HReturn(HValue* context, HValue* value, HValue* parameter_count = 0) {
   1520     SetOperandAt(0, value);
   1521     SetOperandAt(1, context);
   1522     SetOperandAt(2, parameter_count);
   1523   }
   1524 };
   1525 
   1526 
   1527 class HAbnormalExit final : public HTemplateControlInstruction<0, 0> {
   1528  public:
   1529   DECLARE_INSTRUCTION_FACTORY_P0(HAbnormalExit);
   1530 
   1531   Representation RequiredInputRepresentation(int index) override {
   1532     return Representation::None();
   1533   }
   1534 
   1535   DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
   1536  private:
   1537   HAbnormalExit() {}
   1538 };
   1539 
   1540 
   1541 class HUnaryOperation : public HTemplateInstruction<1> {
   1542  public:
   1543   explicit HUnaryOperation(HValue* value, HType type = HType::Tagged())
   1544       : HTemplateInstruction<1>(type) {
   1545     SetOperandAt(0, value);
   1546   }
   1547 
   1548   static HUnaryOperation* cast(HValue* value) {
   1549     return reinterpret_cast<HUnaryOperation*>(value);
   1550   }
   1551 
   1552   HValue* value() const { return OperandAt(0); }
   1553   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1554 };
   1555 
   1556 
   1557 class HUseConst final : public HUnaryOperation {
   1558  public:
   1559   DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue*);
   1560 
   1561   Representation RequiredInputRepresentation(int index) override {
   1562     return Representation::None();
   1563   }
   1564 
   1565   DECLARE_CONCRETE_INSTRUCTION(UseConst)
   1566 
   1567  private:
   1568     explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
   1569 };
   1570 
   1571 
   1572 class HForceRepresentation final : public HTemplateInstruction<1> {
   1573  public:
   1574   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   1575                            HValue* value,
   1576                            Representation required_representation);
   1577 
   1578   HValue* value() const { return OperandAt(0); }
   1579 
   1580   Representation observed_input_representation(int index) override {
   1581     // We haven't actually *observed* this, but it's closer to the truth
   1582     // than 'None'.
   1583     return representation();  // Same as the output representation.
   1584   }
   1585   Representation RequiredInputRepresentation(int index) override {
   1586     return representation();  // Same as the output representation.
   1587   }
   1588 
   1589   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1590 
   1591   DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
   1592 
   1593  private:
   1594   HForceRepresentation(HValue* value, Representation required_representation) {
   1595     SetOperandAt(0, value);
   1596     set_representation(required_representation);
   1597   }
   1598 };
   1599 
   1600 
   1601 class HChange final : public HUnaryOperation {
   1602  public:
   1603   HChange(HValue* value,
   1604           Representation to,
   1605           bool is_truncating_to_smi,
   1606           bool is_truncating_to_int32)
   1607       : HUnaryOperation(value) {
   1608     DCHECK(!value->representation().IsNone());
   1609     DCHECK(!to.IsNone());
   1610     DCHECK(!value->representation().Equals(to));
   1611     set_representation(to);
   1612     SetFlag(kUseGVN);
   1613     SetFlag(kCanOverflow);
   1614     if (is_truncating_to_smi && to.IsSmi()) {
   1615       SetFlag(kTruncatingToSmi);
   1616       SetFlag(kTruncatingToInt32);
   1617     }
   1618     if (is_truncating_to_int32) SetFlag(kTruncatingToInt32);
   1619     if (value->representation().IsSmi() || value->type().IsSmi()) {
   1620       set_type(HType::Smi());
   1621     } else {
   1622       set_type(HType::TaggedNumber());
   1623       if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
   1624     }
   1625   }
   1626 
   1627   bool can_convert_undefined_to_nan() {
   1628     return CheckUsesForFlag(kAllowUndefinedAsNaN);
   1629   }
   1630 
   1631   HType CalculateInferredType() override;
   1632   HValue* Canonicalize() override;
   1633 
   1634   Representation from() const { return value()->representation(); }
   1635   Representation to() const { return representation(); }
   1636   bool deoptimize_on_minus_zero() const {
   1637     return CheckFlag(kBailoutOnMinusZero);
   1638   }
   1639   Representation RequiredInputRepresentation(int index) override {
   1640     return from();
   1641   }
   1642 
   1643   Range* InferRange(Zone* zone) override;
   1644 
   1645   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1646 
   1647   DECLARE_CONCRETE_INSTRUCTION(Change)
   1648 
   1649  protected:
   1650   bool DataEquals(HValue* other) override { return true; }
   1651 
   1652  private:
   1653   bool IsDeletable() const override {
   1654     return !from().IsTagged() || value()->type().IsSmi();
   1655   }
   1656 };
   1657 
   1658 
   1659 class HClampToUint8 final : public HUnaryOperation {
   1660  public:
   1661   DECLARE_INSTRUCTION_FACTORY_P1(HClampToUint8, HValue*);
   1662 
   1663   Representation RequiredInputRepresentation(int index) override {
   1664     return Representation::None();
   1665   }
   1666 
   1667   DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
   1668 
   1669  protected:
   1670   bool DataEquals(HValue* other) override { return true; }
   1671 
   1672  private:
   1673   explicit HClampToUint8(HValue* value)
   1674       : HUnaryOperation(value) {
   1675     set_representation(Representation::Integer32());
   1676     SetFlag(kAllowUndefinedAsNaN);
   1677     SetFlag(kUseGVN);
   1678   }
   1679 
   1680   bool IsDeletable() const override { return true; }
   1681 };
   1682 
   1683 
   1684 class HDoubleBits final : public HUnaryOperation {
   1685  public:
   1686   enum Bits { HIGH, LOW };
   1687   DECLARE_INSTRUCTION_FACTORY_P2(HDoubleBits, HValue*, Bits);
   1688 
   1689   Representation RequiredInputRepresentation(int index) override {
   1690     return Representation::Double();
   1691   }
   1692 
   1693   DECLARE_CONCRETE_INSTRUCTION(DoubleBits)
   1694 
   1695   Bits bits() { return bits_; }
   1696 
   1697  protected:
   1698   bool DataEquals(HValue* other) override {
   1699     return other->IsDoubleBits() && HDoubleBits::cast(other)->bits() == bits();
   1700   }
   1701 
   1702  private:
   1703   HDoubleBits(HValue* value, Bits bits)
   1704       : HUnaryOperation(value), bits_(bits) {
   1705     set_representation(Representation::Integer32());
   1706     SetFlag(kUseGVN);
   1707   }
   1708 
   1709   bool IsDeletable() const override { return true; }
   1710 
   1711   Bits bits_;
   1712 };
   1713 
   1714 
   1715 class HConstructDouble final : public HTemplateInstruction<2> {
   1716  public:
   1717   DECLARE_INSTRUCTION_FACTORY_P2(HConstructDouble, HValue*, HValue*);
   1718 
   1719   Representation RequiredInputRepresentation(int index) override {
   1720     return Representation::Integer32();
   1721   }
   1722 
   1723   DECLARE_CONCRETE_INSTRUCTION(ConstructDouble)
   1724 
   1725   HValue* hi() { return OperandAt(0); }
   1726   HValue* lo() { return OperandAt(1); }
   1727 
   1728  protected:
   1729   bool DataEquals(HValue* other) override { return true; }
   1730 
   1731  private:
   1732   explicit HConstructDouble(HValue* hi, HValue* lo) {
   1733     set_representation(Representation::Double());
   1734     SetFlag(kUseGVN);
   1735     SetOperandAt(0, hi);
   1736     SetOperandAt(1, lo);
   1737   }
   1738 
   1739   bool IsDeletable() const override { return true; }
   1740 };
   1741 
   1742 
   1743 enum RemovableSimulate {
   1744   REMOVABLE_SIMULATE,
   1745   FIXED_SIMULATE
   1746 };
   1747 
   1748 
   1749 class HSimulate final : public HInstruction {
   1750  public:
   1751   HSimulate(BailoutId ast_id, int pop_count, Zone* zone,
   1752             RemovableSimulate removable)
   1753       : ast_id_(ast_id),
   1754         pop_count_(pop_count),
   1755         values_(2, zone),
   1756         assigned_indexes_(2, zone),
   1757         zone_(zone),
   1758         bit_field_(RemovableField::encode(removable) |
   1759                    DoneWithReplayField::encode(false)) {}
   1760   ~HSimulate() {}
   1761 
   1762   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1763 
   1764   bool HasAstId() const { return !ast_id_.IsNone(); }
   1765   BailoutId ast_id() const { return ast_id_; }
   1766   void set_ast_id(BailoutId id) {
   1767     DCHECK(!HasAstId());
   1768     ast_id_ = id;
   1769   }
   1770 
   1771   int pop_count() const { return pop_count_; }
   1772   const ZoneList<HValue*>* values() const { return &values_; }
   1773   int GetAssignedIndexAt(int index) const {
   1774     DCHECK(HasAssignedIndexAt(index));
   1775     return assigned_indexes_[index];
   1776   }
   1777   bool HasAssignedIndexAt(int index) const {
   1778     return assigned_indexes_[index] != kNoIndex;
   1779   }
   1780   void AddAssignedValue(int index, HValue* value) {
   1781     AddValue(index, value);
   1782   }
   1783   void AddPushedValue(HValue* value) {
   1784     AddValue(kNoIndex, value);
   1785   }
   1786   int ToOperandIndex(int environment_index) {
   1787     for (int i = 0; i < assigned_indexes_.length(); ++i) {
   1788       if (assigned_indexes_[i] == environment_index) return i;
   1789     }
   1790     return -1;
   1791   }
   1792   int OperandCount() const override { return values_.length(); }
   1793   HValue* OperandAt(int index) const override { return values_[index]; }
   1794 
   1795   bool HasEscapingOperandAt(int index) override { return false; }
   1796   Representation RequiredInputRepresentation(int index) override {
   1797     return Representation::None();
   1798   }
   1799 
   1800   void MergeWith(ZoneList<HSimulate*>* list);
   1801   bool is_candidate_for_removal() {
   1802     return RemovableField::decode(bit_field_) == REMOVABLE_SIMULATE;
   1803   }
   1804 
   1805   // Replay effects of this instruction on the given environment.
   1806   void ReplayEnvironment(HEnvironment* env);
   1807 
   1808   DECLARE_CONCRETE_INSTRUCTION(Simulate)
   1809 
   1810 #ifdef DEBUG
   1811   void Verify() override;
   1812   void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
   1813   Handle<JSFunction> closure() const { return closure_; }
   1814 #endif
   1815 
   1816  protected:
   1817   void InternalSetOperandAt(int index, HValue* value) override {
   1818     values_[index] = value;
   1819   }
   1820 
   1821  private:
   1822   static const int kNoIndex = -1;
   1823   void AddValue(int index, HValue* value) {
   1824     assigned_indexes_.Add(index, zone_);
   1825     // Resize the list of pushed values.
   1826     values_.Add(NULL, zone_);
   1827     // Set the operand through the base method in HValue to make sure that the
   1828     // use lists are correctly updated.
   1829     SetOperandAt(values_.length() - 1, value);
   1830   }
   1831   bool HasValueForIndex(int index) {
   1832     for (int i = 0; i < assigned_indexes_.length(); ++i) {
   1833       if (assigned_indexes_[i] == index) return true;
   1834     }
   1835     return false;
   1836   }
   1837   bool is_done_with_replay() const {
   1838     return DoneWithReplayField::decode(bit_field_);
   1839   }
   1840   void set_done_with_replay() {
   1841     bit_field_ = DoneWithReplayField::update(bit_field_, true);
   1842   }
   1843 
   1844   class RemovableField : public BitField<RemovableSimulate, 0, 1> {};
   1845   class DoneWithReplayField : public BitField<bool, 1, 1> {};
   1846 
   1847   BailoutId ast_id_;
   1848   int pop_count_;
   1849   ZoneList<HValue*> values_;
   1850   ZoneList<int> assigned_indexes_;
   1851   Zone* zone_;
   1852   uint32_t bit_field_;
   1853 
   1854 #ifdef DEBUG
   1855   Handle<JSFunction> closure_;
   1856 #endif
   1857 };
   1858 
   1859 
   1860 class HEnvironmentMarker final : public HTemplateInstruction<1> {
   1861  public:
   1862   enum Kind { BIND, LOOKUP };
   1863 
   1864   DECLARE_INSTRUCTION_FACTORY_P2(HEnvironmentMarker, Kind, int);
   1865 
   1866   Kind kind() const { return kind_; }
   1867   int index() const { return index_; }
   1868   HSimulate* next_simulate() { return next_simulate_; }
   1869   void set_next_simulate(HSimulate* simulate) {
   1870     next_simulate_ = simulate;
   1871   }
   1872 
   1873   Representation RequiredInputRepresentation(int index) override {
   1874     return Representation::None();
   1875   }
   1876 
   1877   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1878 
   1879 #ifdef DEBUG
   1880   void set_closure(Handle<JSFunction> closure) {
   1881     DCHECK(closure_.is_null());
   1882     DCHECK(!closure.is_null());
   1883     closure_ = closure;
   1884   }
   1885   Handle<JSFunction> closure() const { return closure_; }
   1886 #endif
   1887 
   1888   DECLARE_CONCRETE_INSTRUCTION(EnvironmentMarker);
   1889 
   1890  private:
   1891   HEnvironmentMarker(Kind kind, int index)
   1892       : kind_(kind), index_(index), next_simulate_(NULL) { }
   1893 
   1894   Kind kind_;
   1895   int index_;
   1896   HSimulate* next_simulate_;
   1897 
   1898 #ifdef DEBUG
   1899   Handle<JSFunction> closure_;
   1900 #endif
   1901 };
   1902 
   1903 
   1904 class HStackCheck final : public HTemplateInstruction<1> {
   1905  public:
   1906   enum Type {
   1907     kFunctionEntry,
   1908     kBackwardsBranch
   1909   };
   1910 
   1911   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HStackCheck, Type);
   1912 
   1913   HValue* context() { return OperandAt(0); }
   1914 
   1915   Representation RequiredInputRepresentation(int index) override {
   1916     return Representation::Tagged();
   1917   }
   1918 
   1919   void Eliminate() {
   1920     // The stack check eliminator might try to eliminate the same stack
   1921     // check instruction multiple times.
   1922     if (IsLinked()) {
   1923       DeleteAndReplaceWith(NULL);
   1924     }
   1925   }
   1926 
   1927   bool is_function_entry() { return type_ == kFunctionEntry; }
   1928   bool is_backwards_branch() { return type_ == kBackwardsBranch; }
   1929 
   1930   DECLARE_CONCRETE_INSTRUCTION(StackCheck)
   1931 
   1932  private:
   1933   HStackCheck(HValue* context, Type type) : type_(type) {
   1934     SetOperandAt(0, context);
   1935     SetChangesFlag(kNewSpacePromotion);
   1936   }
   1937 
   1938   Type type_;
   1939 };
   1940 
   1941 
   1942 enum InliningKind {
   1943   NORMAL_RETURN,          // Drop the function from the environment on return.
   1944   CONSTRUCT_CALL_RETURN,  // Either use allocated receiver or return value.
   1945   GETTER_CALL_RETURN,     // Returning from a getter, need to restore context.
   1946   SETTER_CALL_RETURN      // Use the RHS of the assignment as the return value.
   1947 };
   1948 
   1949 
   1950 class HArgumentsObject;
   1951 class HConstant;
   1952 
   1953 
   1954 class HEnterInlined final : public HTemplateInstruction<0> {
   1955  public:
   1956   static HEnterInlined* New(Isolate* isolate, Zone* zone, HValue* context,
   1957                             BailoutId return_id, Handle<JSFunction> closure,
   1958                             HConstant* closure_context, int arguments_count,
   1959                             FunctionLiteral* function,
   1960                             InliningKind inlining_kind, Variable* arguments_var,
   1961                             HArgumentsObject* arguments_object) {
   1962     return new (zone) HEnterInlined(return_id, closure, closure_context,
   1963                                     arguments_count, function, inlining_kind,
   1964                                     arguments_var, arguments_object, zone);
   1965   }
   1966 
   1967   void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
   1968   ZoneList<HBasicBlock*>* return_targets() { return &return_targets_; }
   1969 
   1970   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1971 
   1972   Handle<SharedFunctionInfo> shared() const { return shared_; }
   1973   Handle<JSFunction> closure() const { return closure_; }
   1974   HConstant* closure_context() const { return closure_context_; }
   1975   int arguments_count() const { return arguments_count_; }
   1976   bool arguments_pushed() const { return arguments_pushed_; }
   1977   void set_arguments_pushed() { arguments_pushed_ = true; }
   1978   FunctionLiteral* function() const { return function_; }
   1979   InliningKind inlining_kind() const { return inlining_kind_; }
   1980   BailoutId ReturnId() const { return return_id_; }
   1981   int inlining_id() const { return inlining_id_; }
   1982   void set_inlining_id(int inlining_id) { inlining_id_ = inlining_id; }
   1983 
   1984   Representation RequiredInputRepresentation(int index) override {
   1985     return Representation::None();
   1986   }
   1987 
   1988   Variable* arguments_var() { return arguments_var_; }
   1989   HArgumentsObject* arguments_object() { return arguments_object_; }
   1990 
   1991   DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
   1992 
   1993  private:
   1994   HEnterInlined(BailoutId return_id, Handle<JSFunction> closure,
   1995                 HConstant* closure_context, int arguments_count,
   1996                 FunctionLiteral* function, InliningKind inlining_kind,
   1997                 Variable* arguments_var, HArgumentsObject* arguments_object,
   1998                 Zone* zone)
   1999       : return_id_(return_id),
   2000         shared_(handle(closure->shared())),
   2001         closure_(closure),
   2002         closure_context_(closure_context),
   2003         arguments_count_(arguments_count),
   2004         arguments_pushed_(false),
   2005         function_(function),
   2006         inlining_kind_(inlining_kind),
   2007         inlining_id_(0),
   2008         arguments_var_(arguments_var),
   2009         arguments_object_(arguments_object),
   2010         return_targets_(2, zone) {}
   2011 
   2012   BailoutId return_id_;
   2013   Handle<SharedFunctionInfo> shared_;
   2014   Handle<JSFunction> closure_;
   2015   HConstant* closure_context_;
   2016   int arguments_count_;
   2017   bool arguments_pushed_;
   2018   FunctionLiteral* function_;
   2019   InliningKind inlining_kind_;
   2020   int inlining_id_;
   2021   Variable* arguments_var_;
   2022   HArgumentsObject* arguments_object_;
   2023   ZoneList<HBasicBlock*> return_targets_;
   2024 };
   2025 
   2026 
   2027 class HLeaveInlined final : public HTemplateInstruction<0> {
   2028  public:
   2029   HLeaveInlined(HEnterInlined* entry,
   2030                 int drop_count)
   2031       : entry_(entry),
   2032         drop_count_(drop_count) { }
   2033 
   2034   Representation RequiredInputRepresentation(int index) override {
   2035     return Representation::None();
   2036   }
   2037 
   2038   int argument_delta() const override {
   2039     return entry_->arguments_pushed() ? -drop_count_ : 0;
   2040   }
   2041 
   2042   DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
   2043 
   2044  private:
   2045   HEnterInlined* entry_;
   2046   int drop_count_;
   2047 };
   2048 
   2049 
   2050 class HPushArguments final : public HInstruction {
   2051  public:
   2052   static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context) {
   2053     return new(zone) HPushArguments(zone);
   2054   }
   2055   static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
   2056                              HValue* arg1) {
   2057     HPushArguments* instr = new(zone) HPushArguments(zone);
   2058     instr->AddInput(arg1);
   2059     return instr;
   2060   }
   2061   static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
   2062                              HValue* arg1, HValue* arg2) {
   2063     HPushArguments* instr = new(zone) HPushArguments(zone);
   2064     instr->AddInput(arg1);
   2065     instr->AddInput(arg2);
   2066     return instr;
   2067   }
   2068   static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
   2069                              HValue* arg1, HValue* arg2, HValue* arg3) {
   2070     HPushArguments* instr = new(zone) HPushArguments(zone);
   2071     instr->AddInput(arg1);
   2072     instr->AddInput(arg2);
   2073     instr->AddInput(arg3);
   2074     return instr;
   2075   }
   2076   static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
   2077                              HValue* arg1, HValue* arg2, HValue* arg3,
   2078                              HValue* arg4) {
   2079     HPushArguments* instr = new(zone) HPushArguments(zone);
   2080     instr->AddInput(arg1);
   2081     instr->AddInput(arg2);
   2082     instr->AddInput(arg3);
   2083     instr->AddInput(arg4);
   2084     return instr;
   2085   }
   2086 
   2087   Representation RequiredInputRepresentation(int index) override {
   2088     return Representation::Tagged();
   2089   }
   2090 
   2091   int argument_delta() const override { return inputs_.length(); }
   2092   HValue* argument(int i) { return OperandAt(i); }
   2093 
   2094   int OperandCount() const final { return inputs_.length(); }
   2095   HValue* OperandAt(int i) const final { return inputs_[i]; }
   2096 
   2097   void AddInput(HValue* value);
   2098 
   2099   DECLARE_CONCRETE_INSTRUCTION(PushArguments)
   2100 
   2101  protected:
   2102   void InternalSetOperandAt(int i, HValue* value) final { inputs_[i] = value; }
   2103 
   2104  private:
   2105   explicit HPushArguments(Zone* zone)
   2106       : HInstruction(HType::Tagged()), inputs_(4, zone) {
   2107     set_representation(Representation::Tagged());
   2108   }
   2109 
   2110   ZoneList<HValue*> inputs_;
   2111 };
   2112 
   2113 
   2114 class HThisFunction final : public HTemplateInstruction<0> {
   2115  public:
   2116   DECLARE_INSTRUCTION_FACTORY_P0(HThisFunction);
   2117 
   2118   Representation RequiredInputRepresentation(int index) override {
   2119     return Representation::None();
   2120   }
   2121 
   2122   DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
   2123 
   2124  protected:
   2125   bool DataEquals(HValue* other) override { return true; }
   2126 
   2127  private:
   2128   HThisFunction() {
   2129     set_representation(Representation::Tagged());
   2130     SetFlag(kUseGVN);
   2131   }
   2132 
   2133   bool IsDeletable() const override { return true; }
   2134 };
   2135 
   2136 
   2137 class HDeclareGlobals final : public HUnaryOperation {
   2138  public:
   2139   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HDeclareGlobals,
   2140                                               Handle<FixedArray>,
   2141                                               int);
   2142 
   2143   HValue* context() { return OperandAt(0); }
   2144   Handle<FixedArray> pairs() const { return pairs_; }
   2145   int flags() const { return flags_; }
   2146 
   2147   DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
   2148 
   2149   Representation RequiredInputRepresentation(int index) override {
   2150     return Representation::Tagged();
   2151   }
   2152 
   2153  private:
   2154   HDeclareGlobals(HValue* context,
   2155                   Handle<FixedArray> pairs,
   2156                   int flags)
   2157       : HUnaryOperation(context),
   2158         pairs_(pairs),
   2159         flags_(flags) {
   2160     set_representation(Representation::Tagged());
   2161     SetAllSideEffects();
   2162   }
   2163 
   2164   Handle<FixedArray> pairs_;
   2165   int flags_;
   2166 };
   2167 
   2168 
   2169 template <int V>
   2170 class HCall : public HTemplateInstruction<V> {
   2171  public:
   2172   // The argument count includes the receiver.
   2173   explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
   2174     this->set_representation(Representation::Tagged());
   2175     this->SetAllSideEffects();
   2176   }
   2177 
   2178   HType CalculateInferredType() final { return HType::Tagged(); }
   2179 
   2180   virtual int argument_count() const {
   2181     return argument_count_;
   2182   }
   2183 
   2184   int argument_delta() const override { return -argument_count(); }
   2185 
   2186  private:
   2187   int argument_count_;
   2188 };
   2189 
   2190 
   2191 class HUnaryCall : public HCall<1> {
   2192  public:
   2193   HUnaryCall(HValue* value, int argument_count)
   2194       : HCall<1>(argument_count) {
   2195     SetOperandAt(0, value);
   2196   }
   2197 
   2198   Representation RequiredInputRepresentation(int index) final {
   2199     return Representation::Tagged();
   2200   }
   2201 
   2202   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2203 
   2204   HValue* value() const { return OperandAt(0); }
   2205 };
   2206 
   2207 
   2208 class HBinaryCall : public HCall<2> {
   2209  public:
   2210   HBinaryCall(HValue* first, HValue* second, int argument_count)
   2211       : HCall<2>(argument_count) {
   2212     SetOperandAt(0, first);
   2213     SetOperandAt(1, second);
   2214   }
   2215 
   2216   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2217 
   2218   Representation RequiredInputRepresentation(int index) final {
   2219     return Representation::Tagged();
   2220   }
   2221 
   2222   HValue* first() const { return OperandAt(0); }
   2223   HValue* second() const { return OperandAt(1); }
   2224 };
   2225 
   2226 
   2227 class HCallJSFunction final : public HCall<1> {
   2228  public:
   2229   static HCallJSFunction* New(Isolate* isolate, Zone* zone, HValue* context,
   2230                               HValue* function, int argument_count);
   2231 
   2232   HValue* function() const { return OperandAt(0); }
   2233 
   2234   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2235 
   2236   Representation RequiredInputRepresentation(int index) final {
   2237     DCHECK(index == 0);
   2238     return Representation::Tagged();
   2239   }
   2240 
   2241   bool HasStackCheck() final { return has_stack_check_; }
   2242 
   2243   DECLARE_CONCRETE_INSTRUCTION(CallJSFunction)
   2244 
   2245  private:
   2246   // The argument count includes the receiver.
   2247   HCallJSFunction(HValue* function,
   2248                   int argument_count,
   2249                   bool has_stack_check)
   2250       : HCall<1>(argument_count),
   2251         has_stack_check_(has_stack_check) {
   2252       SetOperandAt(0, function);
   2253   }
   2254 
   2255   bool has_stack_check_;
   2256 };
   2257 
   2258 
   2259 enum CallMode { NORMAL_CALL, TAIL_CALL };
   2260 
   2261 
   2262 class HCallWithDescriptor final : public HInstruction {
   2263  public:
   2264   static HCallWithDescriptor* New(Isolate* isolate, Zone* zone, HValue* context,
   2265                                   HValue* target, int argument_count,
   2266                                   CallInterfaceDescriptor descriptor,
   2267                                   const Vector<HValue*>& operands,
   2268                                   CallMode call_mode = NORMAL_CALL) {
   2269     HCallWithDescriptor* res = new (zone) HCallWithDescriptor(
   2270         target, argument_count, descriptor, operands, call_mode, zone);
   2271     DCHECK(operands.length() == res->GetParameterCount());
   2272     return res;
   2273   }
   2274 
   2275   int OperandCount() const final { return values_.length(); }
   2276   HValue* OperandAt(int index) const final { return values_[index]; }
   2277 
   2278   Representation RequiredInputRepresentation(int index) final {
   2279     if (index == 0 || index == 1) {
   2280       // Target + context
   2281       return Representation::Tagged();
   2282     } else {
   2283       int par_index = index - 2;
   2284       DCHECK(par_index < GetParameterCount());
   2285       return RepresentationFromType(descriptor_.GetParameterType(par_index));
   2286     }
   2287   }
   2288 
   2289   DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor)
   2290 
   2291   HType CalculateInferredType() final { return HType::Tagged(); }
   2292 
   2293   bool IsTailCall() const { return call_mode_ == TAIL_CALL; }
   2294 
   2295   virtual int argument_count() const {
   2296     return argument_count_;
   2297   }
   2298 
   2299   int argument_delta() const override { return -argument_count_; }
   2300 
   2301   CallInterfaceDescriptor descriptor() const { return descriptor_; }
   2302 
   2303   HValue* target() {
   2304     return OperandAt(0);
   2305   }
   2306 
   2307   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2308 
   2309  private:
   2310   // The argument count includes the receiver.
   2311   HCallWithDescriptor(HValue* target, int argument_count,
   2312                       CallInterfaceDescriptor descriptor,
   2313                       const Vector<HValue*>& operands, CallMode call_mode,
   2314                       Zone* zone)
   2315       : descriptor_(descriptor),
   2316         values_(GetParameterCount() + 1, zone),
   2317         argument_count_(argument_count),
   2318         call_mode_(call_mode) {
   2319     // We can only tail call without any stack arguments.
   2320     DCHECK(call_mode != TAIL_CALL || argument_count == 0);
   2321     AddOperand(target, zone);
   2322     for (int i = 0; i < operands.length(); i++) {
   2323       AddOperand(operands[i], zone);
   2324     }
   2325     this->set_representation(Representation::Tagged());
   2326     this->SetAllSideEffects();
   2327   }
   2328 
   2329   void AddOperand(HValue* v, Zone* zone) {
   2330     values_.Add(NULL, zone);
   2331     SetOperandAt(values_.length() - 1, v);
   2332   }
   2333 
   2334   int GetParameterCount() const {
   2335     return descriptor_.GetRegisterParameterCount() + 1;
   2336   }
   2337 
   2338   void InternalSetOperandAt(int index, HValue* value) final {
   2339     values_[index] = value;
   2340   }
   2341 
   2342   CallInterfaceDescriptor descriptor_;
   2343   ZoneList<HValue*> values_;
   2344   int argument_count_;
   2345   CallMode call_mode_;
   2346 };
   2347 
   2348 
   2349 class HInvokeFunction final : public HBinaryCall {
   2350  public:
   2351   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInvokeFunction, HValue*, int);
   2352 
   2353   HInvokeFunction(HValue* context,
   2354                   HValue* function,
   2355                   Handle<JSFunction> known_function,
   2356                   int argument_count)
   2357       : HBinaryCall(context, function, argument_count),
   2358         known_function_(known_function) {
   2359     formal_parameter_count_ =
   2360         known_function.is_null()
   2361             ? 0
   2362             : known_function->shared()->internal_formal_parameter_count();
   2363     has_stack_check_ = !known_function.is_null() &&
   2364         (known_function->code()->kind() == Code::FUNCTION ||
   2365          known_function->code()->kind() == Code::OPTIMIZED_FUNCTION);
   2366   }
   2367 
   2368   static HInvokeFunction* New(Isolate* isolate, Zone* zone, HValue* context,
   2369                               HValue* function,
   2370                               Handle<JSFunction> known_function,
   2371                               int argument_count) {
   2372     return new(zone) HInvokeFunction(context, function,
   2373                                      known_function, argument_count);
   2374   }
   2375 
   2376   HValue* context() { return first(); }
   2377   HValue* function() { return second(); }
   2378   Handle<JSFunction> known_function() { return known_function_; }
   2379   int formal_parameter_count() const { return formal_parameter_count_; }
   2380 
   2381   bool HasStackCheck() final { return has_stack_check_; }
   2382 
   2383   DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
   2384 
   2385  private:
   2386   HInvokeFunction(HValue* context, HValue* function, int argument_count)
   2387       : HBinaryCall(context, function, argument_count),
   2388         has_stack_check_(false) {
   2389   }
   2390 
   2391   Handle<JSFunction> known_function_;
   2392   int formal_parameter_count_;
   2393   bool has_stack_check_;
   2394 };
   2395 
   2396 
   2397 class HCallFunction final : public HBinaryCall {
   2398  public:
   2399   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCallFunction, HValue*, int,
   2400                                               ConvertReceiverMode);
   2401 
   2402   HValue* context() const { return first(); }
   2403   HValue* function() const { return second(); }
   2404 
   2405   ConvertReceiverMode convert_mode() const { return convert_mode_; }
   2406   FeedbackVectorSlot slot() const { return slot_; }
   2407   Handle<TypeFeedbackVector> feedback_vector() const {
   2408     return feedback_vector_;
   2409   }
   2410   bool HasVectorAndSlot() const { return !feedback_vector_.is_null(); }
   2411   void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
   2412                         FeedbackVectorSlot slot) {
   2413     feedback_vector_ = vector;
   2414     slot_ = slot;
   2415   }
   2416 
   2417   DECLARE_CONCRETE_INSTRUCTION(CallFunction)
   2418 
   2419   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2420 
   2421   int argument_delta() const override { return -argument_count(); }
   2422 
   2423  private:
   2424   HCallFunction(HValue* context, HValue* function, int argument_count,
   2425                 ConvertReceiverMode convert_mode)
   2426       : HBinaryCall(context, function, argument_count),
   2427         convert_mode_(convert_mode) {}
   2428   Handle<TypeFeedbackVector> feedback_vector_;
   2429   FeedbackVectorSlot slot_;
   2430   ConvertReceiverMode convert_mode_;
   2431 };
   2432 
   2433 
   2434 class HCallNewArray final : public HBinaryCall {
   2435  public:
   2436   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HCallNewArray, HValue*, int,
   2437                                               ElementsKind,
   2438                                               Handle<AllocationSite>);
   2439 
   2440   HValue* context() { return first(); }
   2441   HValue* constructor() { return second(); }
   2442 
   2443   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2444 
   2445   ElementsKind elements_kind() const { return elements_kind_; }
   2446   Handle<AllocationSite> site() const { return site_; }
   2447 
   2448   DECLARE_CONCRETE_INSTRUCTION(CallNewArray)
   2449 
   2450  private:
   2451   HCallNewArray(HValue* context, HValue* constructor, int argument_count,
   2452                 ElementsKind elements_kind, Handle<AllocationSite> site)
   2453       : HBinaryCall(context, constructor, argument_count),
   2454         elements_kind_(elements_kind),
   2455         site_(site) {}
   2456 
   2457   ElementsKind elements_kind_;
   2458   Handle<AllocationSite> site_;
   2459 };
   2460 
   2461 
   2462 class HCallRuntime final : public HCall<1> {
   2463  public:
   2464   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallRuntime,
   2465                                               const Runtime::Function*, int);
   2466 
   2467   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2468 
   2469   HValue* context() { return OperandAt(0); }
   2470   const Runtime::Function* function() const { return c_function_; }
   2471   SaveFPRegsMode save_doubles() const { return save_doubles_; }
   2472   void set_save_doubles(SaveFPRegsMode save_doubles) {
   2473     save_doubles_ = save_doubles;
   2474   }
   2475 
   2476   Representation RequiredInputRepresentation(int index) override {
   2477     return Representation::Tagged();
   2478   }
   2479 
   2480   DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
   2481 
   2482  private:
   2483   HCallRuntime(HValue* context, const Runtime::Function* c_function,
   2484                int argument_count)
   2485       : HCall<1>(argument_count),
   2486         c_function_(c_function),
   2487         save_doubles_(kDontSaveFPRegs) {
   2488     SetOperandAt(0, context);
   2489   }
   2490 
   2491   const Runtime::Function* c_function_;
   2492   SaveFPRegsMode save_doubles_;
   2493 };
   2494 
   2495 
   2496 class HMapEnumLength final : public HUnaryOperation {
   2497  public:
   2498   DECLARE_INSTRUCTION_FACTORY_P1(HMapEnumLength, HValue*);
   2499 
   2500   Representation RequiredInputRepresentation(int index) override {
   2501     return Representation::Tagged();
   2502   }
   2503 
   2504   DECLARE_CONCRETE_INSTRUCTION(MapEnumLength)
   2505 
   2506  protected:
   2507   bool DataEquals(HValue* other) override { return true; }
   2508 
   2509  private:
   2510   explicit HMapEnumLength(HValue* value)
   2511       : HUnaryOperation(value, HType::Smi()) {
   2512     set_representation(Representation::Smi());
   2513     SetFlag(kUseGVN);
   2514     SetDependsOnFlag(kMaps);
   2515   }
   2516 
   2517   bool IsDeletable() const override { return true; }
   2518 };
   2519 
   2520 
   2521 class HUnaryMathOperation final : public HTemplateInstruction<2> {
   2522  public:
   2523   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   2524                            HValue* value, BuiltinFunctionId op);
   2525 
   2526   HValue* context() const { return OperandAt(0); }
   2527   HValue* value() const { return OperandAt(1); }
   2528 
   2529   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2530 
   2531   Representation RequiredInputRepresentation(int index) override {
   2532     if (index == 0) {
   2533       return Representation::Tagged();
   2534     } else {
   2535       switch (op_) {
   2536         case kMathFloor:
   2537         case kMathRound:
   2538         case kMathFround:
   2539         case kMathSqrt:
   2540         case kMathPowHalf:
   2541         case kMathLog:
   2542         case kMathExp:
   2543           return Representation::Double();
   2544         case kMathAbs:
   2545           return representation();
   2546         case kMathClz32:
   2547           return Representation::Integer32();
   2548         default:
   2549           UNREACHABLE();
   2550           return Representation::None();
   2551       }
   2552     }
   2553   }
   2554 
   2555   Range* InferRange(Zone* zone) override;
   2556 
   2557   HValue* Canonicalize() override;
   2558   Representation RepresentationFromUses() override;
   2559   Representation RepresentationFromInputs() override;
   2560 
   2561   BuiltinFunctionId op() const { return op_; }
   2562   const char* OpName() const;
   2563 
   2564   DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
   2565 
   2566  protected:
   2567   bool DataEquals(HValue* other) override {
   2568     HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
   2569     return op_ == b->op();
   2570   }
   2571 
   2572  private:
   2573   // Indicates if we support a double (and int32) output for Math.floor and
   2574   // Math.round.
   2575   bool SupportsFlexibleFloorAndRound() const {
   2576 #ifdef V8_TARGET_ARCH_ARM64
   2577     // TODO(rmcilroy): Re-enable this for Arm64 once http://crbug.com/476477 is
   2578     // fixed.
   2579     return false;
   2580 #else
   2581     return false;
   2582 #endif
   2583   }
   2584   HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
   2585       : HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
   2586     SetOperandAt(0, context);
   2587     SetOperandAt(1, value);
   2588     switch (op) {
   2589       case kMathFloor:
   2590       case kMathRound:
   2591         if (SupportsFlexibleFloorAndRound()) {
   2592           SetFlag(kFlexibleRepresentation);
   2593         } else {
   2594           set_representation(Representation::Integer32());
   2595         }
   2596         break;
   2597       case kMathClz32:
   2598         set_representation(Representation::Integer32());
   2599         break;
   2600       case kMathAbs:
   2601         // Not setting representation here: it is None intentionally.
   2602         SetFlag(kFlexibleRepresentation);
   2603         // TODO(svenpanne) This flag is actually only needed if representation()
   2604         // is tagged, and not when it is an unboxed double or unboxed integer.
   2605         SetChangesFlag(kNewSpacePromotion);
   2606         break;
   2607       case kMathFround:
   2608       case kMathLog:
   2609       case kMathExp:
   2610       case kMathSqrt:
   2611       case kMathPowHalf:
   2612         set_representation(Representation::Double());
   2613         break;
   2614       default:
   2615         UNREACHABLE();
   2616     }
   2617     SetFlag(kUseGVN);
   2618     SetFlag(kAllowUndefinedAsNaN);
   2619   }
   2620 
   2621   bool IsDeletable() const override {
   2622     // TODO(crankshaft): This should be true, however the semantics of this
   2623     // instruction also include the ToNumber conversion that is mentioned in the
   2624     // spec, which is of course observable.
   2625     return false;
   2626   }
   2627 
   2628   HValue* SimplifiedDividendForMathFloorOfDiv(HDiv* hdiv);
   2629   HValue* SimplifiedDivisorForMathFloorOfDiv(HDiv* hdiv);
   2630 
   2631   BuiltinFunctionId op_;
   2632 };
   2633 
   2634 
   2635 class HLoadRoot final : public HTemplateInstruction<0> {
   2636  public:
   2637   DECLARE_INSTRUCTION_FACTORY_P1(HLoadRoot, Heap::RootListIndex);
   2638   DECLARE_INSTRUCTION_FACTORY_P2(HLoadRoot, Heap::RootListIndex, HType);
   2639 
   2640   Representation RequiredInputRepresentation(int index) override {
   2641     return Representation::None();
   2642   }
   2643 
   2644   Heap::RootListIndex index() const { return index_; }
   2645 
   2646   DECLARE_CONCRETE_INSTRUCTION(LoadRoot)
   2647 
   2648  protected:
   2649   bool DataEquals(HValue* other) override {
   2650     HLoadRoot* b = HLoadRoot::cast(other);
   2651     return index_ == b->index_;
   2652   }
   2653 
   2654  private:
   2655   explicit HLoadRoot(Heap::RootListIndex index, HType type = HType::Tagged())
   2656       : HTemplateInstruction<0>(type), index_(index) {
   2657     SetFlag(kUseGVN);
   2658     // TODO(bmeurer): We'll need kDependsOnRoots once we add the
   2659     // corresponding HStoreRoot instruction.
   2660     SetDependsOnFlag(kCalls);
   2661     set_representation(Representation::Tagged());
   2662   }
   2663 
   2664   bool IsDeletable() const override { return true; }
   2665 
   2666   const Heap::RootListIndex index_;
   2667 };
   2668 
   2669 
   2670 class HCheckMaps final : public HTemplateInstruction<2> {
   2671  public:
   2672   static HCheckMaps* New(Isolate* isolate, Zone* zone, HValue* context,
   2673                          HValue* value, Handle<Map> map,
   2674                          HValue* typecheck = NULL) {
   2675     return new(zone) HCheckMaps(value, new(zone) UniqueSet<Map>(
   2676             Unique<Map>::CreateImmovable(map), zone), typecheck);
   2677   }
   2678   static HCheckMaps* New(Isolate* isolate, Zone* zone, HValue* context,
   2679                          HValue* value, SmallMapList* map_list,
   2680                          HValue* typecheck = NULL) {
   2681     UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone);
   2682     for (int i = 0; i < map_list->length(); ++i) {
   2683       maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone);
   2684     }
   2685     return new(zone) HCheckMaps(value, maps, typecheck);
   2686   }
   2687 
   2688   bool IsStabilityCheck() const {
   2689     return IsStabilityCheckField::decode(bit_field_);
   2690   }
   2691   void MarkAsStabilityCheck() {
   2692     bit_field_ = MapsAreStableField::encode(true) |
   2693                  HasMigrationTargetField::encode(false) |
   2694                  IsStabilityCheckField::encode(true);
   2695     ClearChangesFlag(kNewSpacePromotion);
   2696     ClearDependsOnFlag(kElementsKind);
   2697     ClearDependsOnFlag(kMaps);
   2698   }
   2699 
   2700   bool HasEscapingOperandAt(int index) override { return false; }
   2701   Representation RequiredInputRepresentation(int index) override {
   2702     return Representation::Tagged();
   2703   }
   2704 
   2705   HType CalculateInferredType() override {
   2706     if (value()->type().IsHeapObject()) return value()->type();
   2707     return HType::HeapObject();
   2708   }
   2709 
   2710   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2711 
   2712   HValue* value() const { return OperandAt(0); }
   2713   HValue* typecheck() const { return OperandAt(1); }
   2714 
   2715   const UniqueSet<Map>* maps() const { return maps_; }
   2716   void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; }
   2717 
   2718   bool maps_are_stable() const {
   2719     return MapsAreStableField::decode(bit_field_);
   2720   }
   2721 
   2722   bool HasMigrationTarget() const {
   2723     return HasMigrationTargetField::decode(bit_field_);
   2724   }
   2725 
   2726   HValue* Canonicalize() override;
   2727 
   2728   static HCheckMaps* CreateAndInsertAfter(Zone* zone,
   2729                                           HValue* value,
   2730                                           Unique<Map> map,
   2731                                           bool map_is_stable,
   2732                                           HInstruction* instr) {
   2733     return instr->Append(new(zone) HCheckMaps(
   2734             value, new(zone) UniqueSet<Map>(map, zone), map_is_stable));
   2735   }
   2736 
   2737   static HCheckMaps* CreateAndInsertBefore(Zone* zone,
   2738                                            HValue* value,
   2739                                            const UniqueSet<Map>* maps,
   2740                                            bool maps_are_stable,
   2741                                            HInstruction* instr) {
   2742     return instr->Prepend(new(zone) HCheckMaps(value, maps, maps_are_stable));
   2743   }
   2744 
   2745   DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
   2746 
   2747  protected:
   2748   bool DataEquals(HValue* other) override {
   2749     return this->maps()->Equals(HCheckMaps::cast(other)->maps());
   2750   }
   2751 
   2752   int RedefinedOperandIndex() override { return 0; }
   2753 
   2754  private:
   2755   HCheckMaps(HValue* value, const UniqueSet<Map>* maps, bool maps_are_stable)
   2756       : HTemplateInstruction<2>(HType::HeapObject()),
   2757         maps_(maps),
   2758         bit_field_(HasMigrationTargetField::encode(false) |
   2759                    IsStabilityCheckField::encode(false) |
   2760                    MapsAreStableField::encode(maps_are_stable)) {
   2761     DCHECK_NE(0, maps->size());
   2762     SetOperandAt(0, value);
   2763     // Use the object value for the dependency.
   2764     SetOperandAt(1, value);
   2765     set_representation(Representation::Tagged());
   2766     SetFlag(kUseGVN);
   2767     SetDependsOnFlag(kMaps);
   2768     SetDependsOnFlag(kElementsKind);
   2769   }
   2770 
   2771   HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck)
   2772       : HTemplateInstruction<2>(HType::HeapObject()),
   2773         maps_(maps),
   2774         bit_field_(HasMigrationTargetField::encode(false) |
   2775                    IsStabilityCheckField::encode(false) |
   2776                    MapsAreStableField::encode(true)) {
   2777     DCHECK_NE(0, maps->size());
   2778     SetOperandAt(0, value);
   2779     // Use the object value for the dependency if NULL is passed.
   2780     SetOperandAt(1, typecheck ? typecheck : value);
   2781     set_representation(Representation::Tagged());
   2782     SetFlag(kUseGVN);
   2783     SetDependsOnFlag(kMaps);
   2784     SetDependsOnFlag(kElementsKind);
   2785     for (int i = 0; i < maps->size(); ++i) {
   2786       Handle<Map> map = maps->at(i).handle();
   2787       if (map->is_migration_target()) {
   2788         bit_field_ = HasMigrationTargetField::update(bit_field_, true);
   2789       }
   2790       if (!map->is_stable()) {
   2791         bit_field_ = MapsAreStableField::update(bit_field_, false);
   2792       }
   2793     }
   2794     if (HasMigrationTarget()) SetChangesFlag(kNewSpacePromotion);
   2795   }
   2796 
   2797   class HasMigrationTargetField : public BitField<bool, 0, 1> {};
   2798   class IsStabilityCheckField : public BitField<bool, 1, 1> {};
   2799   class MapsAreStableField : public BitField<bool, 2, 1> {};
   2800 
   2801   const UniqueSet<Map>* maps_;
   2802   uint32_t bit_field_;
   2803 };
   2804 
   2805 
   2806 class HCheckValue final : public HUnaryOperation {
   2807  public:
   2808   static HCheckValue* New(Isolate* isolate, Zone* zone, HValue* context,
   2809                           HValue* value, Handle<JSFunction> func) {
   2810     bool in_new_space = isolate->heap()->InNewSpace(*func);
   2811     // NOTE: We create an uninitialized Unique and initialize it later.
   2812     // This is because a JSFunction can move due to GC during graph creation.
   2813     // TODO(titzer): This is a migration crutch. Replace with some kind of
   2814     // Uniqueness scope later.
   2815     Unique<JSFunction> target = Unique<JSFunction>::CreateUninitialized(func);
   2816     HCheckValue* check = new(zone) HCheckValue(value, target, in_new_space);
   2817     return check;
   2818   }
   2819   static HCheckValue* New(Isolate* isolate, Zone* zone, HValue* context,
   2820                           HValue* value, Unique<HeapObject> target,
   2821                           bool object_in_new_space) {
   2822     return new(zone) HCheckValue(value, target, object_in_new_space);
   2823   }
   2824 
   2825   void FinalizeUniqueness() override {
   2826     object_ = Unique<HeapObject>(object_.handle());
   2827   }
   2828 
   2829   Representation RequiredInputRepresentation(int index) override {
   2830     return Representation::Tagged();
   2831   }
   2832   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2833 
   2834   HValue* Canonicalize() override;
   2835 
   2836 #ifdef DEBUG
   2837   void Verify() override;
   2838 #endif
   2839 
   2840   Unique<HeapObject> object() const { return object_; }
   2841   bool object_in_new_space() const { return object_in_new_space_; }
   2842 
   2843   DECLARE_CONCRETE_INSTRUCTION(CheckValue)
   2844 
   2845  protected:
   2846   bool DataEquals(HValue* other) override {
   2847     HCheckValue* b = HCheckValue::cast(other);
   2848     return object_ == b->object_;
   2849   }
   2850 
   2851  private:
   2852   HCheckValue(HValue* value, Unique<HeapObject> object,
   2853                bool object_in_new_space)
   2854       : HUnaryOperation(value, value->type()),
   2855         object_(object),
   2856         object_in_new_space_(object_in_new_space) {
   2857     set_representation(Representation::Tagged());
   2858     SetFlag(kUseGVN);
   2859   }
   2860 
   2861   Unique<HeapObject> object_;
   2862   bool object_in_new_space_;
   2863 };
   2864 
   2865 
   2866 class HCheckInstanceType final : public HUnaryOperation {
   2867  public:
   2868   enum Check {
   2869     IS_JS_RECEIVER,
   2870     IS_JS_ARRAY,
   2871     IS_JS_DATE,
   2872     IS_STRING,
   2873     IS_INTERNALIZED_STRING,
   2874     LAST_INTERVAL_CHECK = IS_JS_DATE
   2875   };
   2876 
   2877   DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue*, Check);
   2878 
   2879   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2880 
   2881   Representation RequiredInputRepresentation(int index) override {
   2882     return Representation::Tagged();
   2883   }
   2884 
   2885   HType CalculateInferredType() override {
   2886     switch (check_) {
   2887       case IS_JS_RECEIVER: return HType::JSReceiver();
   2888       case IS_JS_ARRAY: return HType::JSArray();
   2889       case IS_JS_DATE: return HType::JSObject();
   2890       case IS_STRING: return HType::String();
   2891       case IS_INTERNALIZED_STRING: return HType::String();
   2892     }
   2893     UNREACHABLE();
   2894     return HType::Tagged();
   2895   }
   2896 
   2897   HValue* Canonicalize() override;
   2898 
   2899   bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
   2900   void GetCheckInterval(InstanceType* first, InstanceType* last);
   2901   void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
   2902 
   2903   Check check() const { return check_; }
   2904 
   2905   DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
   2906 
   2907  protected:
   2908   // TODO(ager): It could be nice to allow the ommision of instance
   2909   // type checks if we have already performed an instance type check
   2910   // with a larger range.
   2911   bool DataEquals(HValue* other) override {
   2912     HCheckInstanceType* b = HCheckInstanceType::cast(other);
   2913     return check_ == b->check_;
   2914   }
   2915 
   2916   int RedefinedOperandIndex() override { return 0; }
   2917 
   2918  private:
   2919   const char* GetCheckName() const;
   2920 
   2921   HCheckInstanceType(HValue* value, Check check)
   2922       : HUnaryOperation(value, HType::HeapObject()), check_(check) {
   2923     set_representation(Representation::Tagged());
   2924     SetFlag(kUseGVN);
   2925   }
   2926 
   2927   const Check check_;
   2928 };
   2929 
   2930 
   2931 class HCheckSmi final : public HUnaryOperation {
   2932  public:
   2933   DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue*);
   2934 
   2935   Representation RequiredInputRepresentation(int index) override {
   2936     return Representation::Tagged();
   2937   }
   2938 
   2939   HValue* Canonicalize() override {
   2940     HType value_type = value()->type();
   2941     if (value_type.IsSmi()) {
   2942       return NULL;
   2943     }
   2944     return this;
   2945   }
   2946 
   2947   DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
   2948 
   2949  protected:
   2950   bool DataEquals(HValue* other) override { return true; }
   2951 
   2952  private:
   2953   explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
   2954     set_representation(Representation::Smi());
   2955     SetFlag(kUseGVN);
   2956   }
   2957 };
   2958 
   2959 
   2960 class HCheckArrayBufferNotNeutered final : public HUnaryOperation {
   2961  public:
   2962   DECLARE_INSTRUCTION_FACTORY_P1(HCheckArrayBufferNotNeutered, HValue*);
   2963 
   2964   bool HasEscapingOperandAt(int index) override { return false; }
   2965   Representation RequiredInputRepresentation(int index) override {
   2966     return Representation::Tagged();
   2967   }
   2968 
   2969   HType CalculateInferredType() override {
   2970     if (value()->type().IsHeapObject()) return value()->type();
   2971     return HType::HeapObject();
   2972   }
   2973 
   2974   DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered)
   2975 
   2976  protected:
   2977   bool DataEquals(HValue* other) override { return true; }
   2978   int RedefinedOperandIndex() override { return 0; }
   2979 
   2980  private:
   2981   explicit HCheckArrayBufferNotNeutered(HValue* value)
   2982       : HUnaryOperation(value) {
   2983     set_representation(Representation::Tagged());
   2984     SetFlag(kUseGVN);
   2985     SetDependsOnFlag(kCalls);
   2986   }
   2987 };
   2988 
   2989 
   2990 class HCheckHeapObject final : public HUnaryOperation {
   2991  public:
   2992   DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
   2993 
   2994   bool HasEscapingOperandAt(int index) override { return false; }
   2995   Representation RequiredInputRepresentation(int index) override {
   2996     return Representation::Tagged();
   2997   }
   2998 
   2999   HType CalculateInferredType() override {
   3000     if (value()->type().IsHeapObject()) return value()->type();
   3001     return HType::HeapObject();
   3002   }
   3003 
   3004 #ifdef DEBUG
   3005   void Verify() override;
   3006 #endif
   3007 
   3008   HValue* Canonicalize() override {
   3009     return value()->type().IsHeapObject() ? NULL : this;
   3010   }
   3011 
   3012   DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
   3013 
   3014  protected:
   3015   bool DataEquals(HValue* other) override { return true; }
   3016 
   3017  private:
   3018   explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) {
   3019     set_representation(Representation::Tagged());
   3020     SetFlag(kUseGVN);
   3021   }
   3022 };
   3023 
   3024 
   3025 class InductionVariableData;
   3026 
   3027 
   3028 struct InductionVariableLimitUpdate {
   3029   InductionVariableData* updated_variable;
   3030   HValue* limit;
   3031   bool limit_is_upper;
   3032   bool limit_is_included;
   3033 
   3034   InductionVariableLimitUpdate()
   3035       : updated_variable(NULL), limit(NULL),
   3036         limit_is_upper(false), limit_is_included(false) {}
   3037 };
   3038 
   3039 
   3040 class HBoundsCheck;
   3041 class HPhi;
   3042 class HBitwise;
   3043 
   3044 
   3045 class InductionVariableData final : public ZoneObject {
   3046  public:
   3047   class InductionVariableCheck : public ZoneObject {
   3048    public:
   3049     HBoundsCheck* check() { return check_; }
   3050     InductionVariableCheck* next() { return next_; }
   3051     bool HasUpperLimit() { return upper_limit_ >= 0; }
   3052     int32_t upper_limit() {
   3053       DCHECK(HasUpperLimit());
   3054       return upper_limit_;
   3055     }
   3056     void set_upper_limit(int32_t upper_limit) {
   3057       upper_limit_ = upper_limit;
   3058     }
   3059 
   3060     bool processed() { return processed_; }
   3061     void set_processed() { processed_ = true; }
   3062 
   3063     InductionVariableCheck(HBoundsCheck* check,
   3064                            InductionVariableCheck* next,
   3065                            int32_t upper_limit = kNoLimit)
   3066         : check_(check), next_(next), upper_limit_(upper_limit),
   3067           processed_(false) {}
   3068 
   3069    private:
   3070     HBoundsCheck* check_;
   3071     InductionVariableCheck* next_;
   3072     int32_t upper_limit_;
   3073     bool processed_;
   3074   };
   3075 
   3076   class ChecksRelatedToLength : public ZoneObject {
   3077    public:
   3078     HValue* length() { return length_; }
   3079     ChecksRelatedToLength* next() { return next_; }
   3080     InductionVariableCheck* checks() { return checks_; }
   3081 
   3082     void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
   3083     void CloseCurrentBlock();
   3084 
   3085     ChecksRelatedToLength(HValue* length, ChecksRelatedToLength* next)
   3086       : length_(length), next_(next), checks_(NULL),
   3087         first_check_in_block_(NULL),
   3088         added_index_(NULL),
   3089         added_constant_(NULL),
   3090         current_and_mask_in_block_(0),
   3091         current_or_mask_in_block_(0) {}
   3092 
   3093    private:
   3094     void UseNewIndexInCurrentBlock(Token::Value token,
   3095                                    int32_t mask,
   3096                                    HValue* index_base,
   3097                                    HValue* context);
   3098 
   3099     HBoundsCheck* first_check_in_block() { return first_check_in_block_; }
   3100     HBitwise* added_index() { return added_index_; }
   3101     void set_added_index(HBitwise* index) { added_index_ = index; }
   3102     HConstant* added_constant() { return added_constant_; }
   3103     void set_added_constant(HConstant* constant) { added_constant_ = constant; }
   3104     int32_t current_and_mask_in_block() { return current_and_mask_in_block_; }
   3105     int32_t current_or_mask_in_block() { return current_or_mask_in_block_; }
   3106     int32_t current_upper_limit() { return current_upper_limit_; }
   3107 
   3108     HValue* length_;
   3109     ChecksRelatedToLength* next_;
   3110     InductionVariableCheck* checks_;
   3111 
   3112     HBoundsCheck* first_check_in_block_;
   3113     HBitwise* added_index_;
   3114     HConstant* added_constant_;
   3115     int32_t current_and_mask_in_block_;
   3116     int32_t current_or_mask_in_block_;
   3117     int32_t current_upper_limit_;
   3118   };
   3119 
   3120   struct LimitFromPredecessorBlock {
   3121     InductionVariableData* variable;
   3122     Token::Value token;
   3123     HValue* limit;
   3124     HBasicBlock* other_target;
   3125 
   3126     bool LimitIsValid() { return token != Token::ILLEGAL; }
   3127 
   3128     bool LimitIsIncluded() {
   3129       return Token::IsEqualityOp(token) ||
   3130           token == Token::GTE || token == Token::LTE;
   3131     }
   3132     bool LimitIsUpper() {
   3133       return token == Token::LTE || token == Token::LT || token == Token::NE;
   3134     }
   3135 
   3136     LimitFromPredecessorBlock()
   3137         : variable(NULL),
   3138           token(Token::ILLEGAL),
   3139           limit(NULL),
   3140           other_target(NULL) {}
   3141   };
   3142 
   3143   static const int32_t kNoLimit = -1;
   3144 
   3145   static InductionVariableData* ExaminePhi(HPhi* phi);
   3146   static void ComputeLimitFromPredecessorBlock(
   3147       HBasicBlock* block,
   3148       LimitFromPredecessorBlock* result);
   3149   static bool ComputeInductionVariableLimit(
   3150       HBasicBlock* block,
   3151       InductionVariableLimitUpdate* additional_limit);
   3152 
   3153   struct BitwiseDecompositionResult {
   3154     HValue* base;
   3155     int32_t and_mask;
   3156     int32_t or_mask;
   3157     HValue* context;
   3158 
   3159     BitwiseDecompositionResult()
   3160         : base(NULL), and_mask(0), or_mask(0), context(NULL) {}
   3161   };
   3162   static void DecomposeBitwise(HValue* value,
   3163                                BitwiseDecompositionResult* result);
   3164 
   3165   void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
   3166 
   3167   bool CheckIfBranchIsLoopGuard(Token::Value token,
   3168                                 HBasicBlock* current_branch,
   3169                                 HBasicBlock* other_branch);
   3170 
   3171   void UpdateAdditionalLimit(InductionVariableLimitUpdate* update);
   3172 
   3173   HPhi* phi() { return phi_; }
   3174   HValue* base() { return base_; }
   3175   int32_t increment() { return increment_; }
   3176   HValue* limit() { return limit_; }
   3177   bool limit_included() { return limit_included_; }
   3178   HBasicBlock* limit_validity() { return limit_validity_; }
   3179   HBasicBlock* induction_exit_block() { return induction_exit_block_; }
   3180   HBasicBlock* induction_exit_target() { return induction_exit_target_; }
   3181   ChecksRelatedToLength* checks() { return checks_; }
   3182   HValue* additional_upper_limit() { return additional_upper_limit_; }
   3183   bool additional_upper_limit_is_included() {
   3184     return additional_upper_limit_is_included_;
   3185   }
   3186   HValue* additional_lower_limit() { return additional_lower_limit_; }
   3187   bool additional_lower_limit_is_included() {
   3188     return additional_lower_limit_is_included_;
   3189   }
   3190 
   3191   bool LowerLimitIsNonNegativeConstant() {
   3192     if (base()->IsInteger32Constant() && base()->GetInteger32Constant() >= 0) {
   3193       return true;
   3194     }
   3195     if (additional_lower_limit() != NULL &&
   3196         additional_lower_limit()->IsInteger32Constant() &&
   3197         additional_lower_limit()->GetInteger32Constant() >= 0) {
   3198       // Ignoring the corner case of !additional_lower_limit_is_included()
   3199       // is safe, handling it adds unneeded complexity.
   3200       return true;
   3201     }
   3202     return false;
   3203   }
   3204 
   3205   int32_t ComputeUpperLimit(int32_t and_mask, int32_t or_mask);
   3206 
   3207  private:
   3208   template <class T> void swap(T* a, T* b) {
   3209     T c(*a);
   3210     *a = *b;
   3211     *b = c;
   3212   }
   3213 
   3214   InductionVariableData(HPhi* phi, HValue* base, int32_t increment)
   3215       : phi_(phi), base_(IgnoreOsrValue(base)), increment_(increment),
   3216         limit_(NULL), limit_included_(false), limit_validity_(NULL),
   3217         induction_exit_block_(NULL), induction_exit_target_(NULL),
   3218         checks_(NULL),
   3219         additional_upper_limit_(NULL),
   3220         additional_upper_limit_is_included_(false),
   3221         additional_lower_limit_(NULL),
   3222         additional_lower_limit_is_included_(false) {}
   3223 
   3224   static int32_t ComputeIncrement(HPhi* phi, HValue* phi_operand);
   3225 
   3226   static HValue* IgnoreOsrValue(HValue* v);
   3227   static InductionVariableData* GetInductionVariableData(HValue* v);
   3228 
   3229   HPhi* phi_;
   3230   HValue* base_;
   3231   int32_t increment_;
   3232   HValue* limit_;
   3233   bool limit_included_;
   3234   HBasicBlock* limit_validity_;
   3235   HBasicBlock* induction_exit_block_;
   3236   HBasicBlock* induction_exit_target_;
   3237   ChecksRelatedToLength* checks_;
   3238   HValue* additional_upper_limit_;
   3239   bool additional_upper_limit_is_included_;
   3240   HValue* additional_lower_limit_;
   3241   bool additional_lower_limit_is_included_;
   3242 };
   3243 
   3244 
   3245 class HPhi final : public HValue {
   3246  public:
   3247   HPhi(int merged_index, Zone* zone)
   3248       : inputs_(2, zone), merged_index_(merged_index) {
   3249     DCHECK(merged_index >= 0 || merged_index == kInvalidMergedIndex);
   3250     SetFlag(kFlexibleRepresentation);
   3251     SetFlag(kAllowUndefinedAsNaN);
   3252   }
   3253 
   3254   Representation RepresentationFromInputs() override;
   3255 
   3256   Range* InferRange(Zone* zone) override;
   3257   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   3258   Representation RequiredInputRepresentation(int index) override {
   3259     return representation();
   3260   }
   3261   Representation KnownOptimalRepresentation() override {
   3262     return representation();
   3263   }
   3264   HType CalculateInferredType() override;
   3265   int OperandCount() const override { return inputs_.length(); }
   3266   HValue* OperandAt(int index) const override { return inputs_[index]; }
   3267   HValue* GetRedundantReplacement();
   3268   void AddInput(HValue* value);
   3269   bool HasRealUses();
   3270 
   3271   bool IsReceiver() const { return merged_index_ == 0; }
   3272   bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
   3273 
   3274   SourcePosition position() const override;
   3275 
   3276   int merged_index() const { return merged_index_; }
   3277 
   3278   InductionVariableData* induction_variable_data() {
   3279     return induction_variable_data_;
   3280   }
   3281   bool IsInductionVariable() {
   3282     return induction_variable_data_ != NULL;
   3283   }
   3284   bool IsLimitedInductionVariable() {
   3285     return IsInductionVariable() &&
   3286         induction_variable_data_->limit() != NULL;
   3287   }
   3288   void DetectInductionVariable() {
   3289     DCHECK(induction_variable_data_ == NULL);
   3290     induction_variable_data_ = InductionVariableData::ExaminePhi(this);
   3291   }
   3292 
   3293   std::ostream& PrintTo(std::ostream& os) const override;  // NOLINT
   3294 
   3295 #ifdef DEBUG
   3296   void Verify() override;
   3297 #endif
   3298 
   3299   void InitRealUses(int id);
   3300   void AddNonPhiUsesFrom(HPhi* other);
   3301 
   3302   Representation representation_from_indirect_uses() const {
   3303     return representation_from_indirect_uses_;
   3304   }
   3305 
   3306   bool has_type_feedback_from_uses() const {
   3307     return has_type_feedback_from_uses_;
   3308   }
   3309 
   3310   int phi_id() { return phi_id_; }
   3311 
   3312   static HPhi* cast(HValue* value) {
   3313     DCHECK(value->IsPhi());
   3314     return reinterpret_cast<HPhi*>(value);
   3315   }
   3316   Opcode opcode() const override { return HValue::kPhi; }
   3317 
   3318   void SimplifyConstantInputs();
   3319 
   3320   // Marker value representing an invalid merge index.
   3321   static const int kInvalidMergedIndex = -1;
   3322 
   3323  protected:
   3324   void DeleteFromGraph() override;
   3325   void InternalSetOperandAt(int index, HValue* value) override {
   3326     inputs_[index] = value;
   3327   }
   3328 
   3329  private:
   3330   Representation representation_from_non_phi_uses() const {
   3331     return representation_from_non_phi_uses_;
   3332   }
   3333 
   3334   ZoneList<HValue*> inputs_;
   3335   int merged_index_ = 0;
   3336 
   3337   int phi_id_ = -1;
   3338   InductionVariableData* induction_variable_data_ = nullptr;
   3339 
   3340   Representation representation_from_indirect_uses_ = Representation::None();
   3341   Representation representation_from_non_phi_uses_ = Representation::None();
   3342   bool has_type_feedback_from_uses_ = false;
   3343 
   3344   // TODO(titzer): we can't eliminate the receiver for generating backtraces
   3345   bool IsDeletable() const override { return !IsReceiver(); }
   3346 };
   3347 
   3348 
   3349 // Common base class for HArgumentsObject and HCapturedObject.
   3350 class HDematerializedObject : public HInstruction {
   3351  public:
   3352   HDematerializedObject(int count, Zone* zone) : values_(count, zone) {}
   3353 
   3354   int OperandCount() const final { return values_.length(); }
   3355   HValue* OperandAt(int index) const final { return values_[index]; }
   3356 
   3357   bool HasEscapingOperandAt(int index) final { return false; }
   3358   Representation RequiredInputRepresentation(int index) final {
   3359     return Representation::None();
   3360   }
   3361 
   3362  protected:
   3363   void InternalSetOperandAt(int index, HValue* value) final {
   3364     values_[index] = value;
   3365   }
   3366 
   3367   // List of values tracked by this marker.
   3368   ZoneList<HValue*> values_;
   3369 };
   3370 
   3371 
   3372 class HArgumentsObject final : public HDematerializedObject {
   3373  public:
   3374   static HArgumentsObject* New(Isolate* isolate, Zone* zone, HValue* context,
   3375                                int count) {
   3376     return new(zone) HArgumentsObject(count, zone);
   3377   }
   3378 
   3379   // The values contain a list of all elements in the arguments object
   3380   // including the receiver object, which is skipped when materializing.
   3381   const ZoneList<HValue*>* arguments_values() const { return &values_; }
   3382   int arguments_count() const { return values_.length(); }
   3383 
   3384   void AddArgument(HValue* argument, Zone* zone) {
   3385     values_.Add(NULL, zone);  // Resize list.
   3386     SetOperandAt(values_.length() - 1, argument);
   3387   }
   3388 
   3389   DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
   3390 
   3391  private:
   3392   HArgumentsObject(int count, Zone* zone)
   3393       : HDematerializedObject(count, zone) {
   3394     set_representation(Representation::Tagged());
   3395     SetFlag(kIsArguments);
   3396   }
   3397 };
   3398 
   3399 
   3400 class HCapturedObject final : public HDematerializedObject {
   3401  public:
   3402   HCapturedObject(int length, int id, Zone* zone)
   3403       : HDematerializedObject(length, zone), capture_id_(id) {
   3404     set_representation(Representation::Tagged());
   3405     values_.AddBlock(NULL, length, zone);  // Resize list.
   3406   }
   3407 
   3408   // The values contain a list of all in-object properties inside the
   3409   // captured object and is index by field index. Properties in the
   3410   // properties or elements backing store are not tracked here.
   3411   const ZoneList<HValue*>* values() const { return &values_; }
   3412   int length() const { return values_.length(); }
   3413   int capture_id() const { return capture_id_; }
   3414 
   3415   // Shortcut for the map value of this captured object.
   3416   HValue* map_value() const { return values()->first(); }
   3417 
   3418   void ReuseSideEffectsFromStore(HInstruction* store) {
   3419     DCHECK(store->HasObservableSideEffects());
   3420     DCHECK(store->IsStoreNamedField());
   3421     changes_flags_.Add(store->ChangesFlags());
   3422   }
   3423 
   3424   // Replay effects of this instruction on the given environment.
   3425   void ReplayEnvironment(HEnvironment* env);
   3426 
   3427   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3428 
   3429   DECLARE_CONCRETE_INSTRUCTION(CapturedObject)
   3430 
   3431  private:
   3432   int capture_id_;
   3433 
   3434   // Note that we cannot DCE captured objects as they are used to replay
   3435   // the environment. This method is here as an explicit reminder.
   3436   // TODO(mstarzinger): Turn HSimulates into full snapshots maybe?
   3437   bool IsDeletable() const final { return false; }
   3438 };
   3439 
   3440 
   3441 class HConstant final : public HTemplateInstruction<0> {
   3442  public:
   3443   enum Special { kHoleNaN };
   3444 
   3445   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Special);
   3446   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, int32_t);
   3447   DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation);
   3448   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double);
   3449   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle<Object>);
   3450   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);
   3451 
   3452   static HConstant* CreateAndInsertAfter(Isolate* isolate, Zone* zone,
   3453                                          HValue* context, int32_t value,
   3454                                          Representation representation,
   3455                                          HInstruction* instruction) {
   3456     return instruction->Append(
   3457         HConstant::New(isolate, zone, context, value, representation));
   3458   }
   3459 
   3460   Handle<Map> GetMonomorphicJSObjectMap() override {
   3461     Handle<Object> object = object_.handle();
   3462     if (!object.is_null() && object->IsHeapObject()) {
   3463       return v8::internal::handle(HeapObject::cast(*object)->map());
   3464     }
   3465     return Handle<Map>();
   3466   }
   3467 
   3468   static HConstant* CreateAndInsertBefore(Isolate* isolate, Zone* zone,
   3469                                           HValue* context, int32_t value,
   3470                                           Representation representation,
   3471                                           HInstruction* instruction) {
   3472     return instruction->Prepend(
   3473         HConstant::New(isolate, zone, context, value, representation));
   3474   }
   3475 
   3476   static HConstant* CreateAndInsertBefore(Zone* zone,
   3477                                           Unique<Map> map,
   3478                                           bool map_is_stable,
   3479                                           HInstruction* instruction) {
   3480     return instruction->Prepend(new(zone) HConstant(
   3481         map, Unique<Map>(Handle<Map>::null()), map_is_stable,
   3482         Representation::Tagged(), HType::HeapObject(), true,
   3483         false, false, MAP_TYPE));
   3484   }
   3485 
   3486   static HConstant* CreateAndInsertAfter(Zone* zone,
   3487                                          Unique<Map> map,
   3488                                          bool map_is_stable,
   3489                                          HInstruction* instruction) {
   3490     return instruction->Append(new(zone) HConstant(
   3491             map, Unique<Map>(Handle<Map>::null()), map_is_stable,
   3492             Representation::Tagged(), HType::HeapObject(), true,
   3493             false, false, MAP_TYPE));
   3494   }
   3495