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 
   3496   Handle<Object> handle(Isolate* isolate) {
   3497     if (object_.handle().is_null()) {
   3498       // Default arguments to is_not_in_new_space depend on this heap number
   3499       // to be tenured so that it's guaranteed not to be located in new space.
   3500       object_ = Unique<Object>::CreateUninitialized(
   3501           isolate->factory()->NewNumber(double_value_, TENURED));
   3502     }
   3503     AllowDeferredHandleDereference smi_check;
   3504     DCHECK(HasInteger32Value() || !object_.handle()->IsSmi());
   3505     return object_.handle();
   3506   }
   3507 
   3508   bool IsSpecialDouble() const {
   3509     return HasDoubleValue() &&
   3510            (bit_cast<int64_t>(double_value_) == bit_cast<int64_t>(-0.0) ||
   3511             std::isnan(double_value_));
   3512   }
   3513 
   3514   bool NotInNewSpace() const {
   3515     return IsNotInNewSpaceField::decode(bit_field_);
   3516   }
   3517 
   3518   bool ImmortalImmovable() const;
   3519 
   3520   bool IsCell() const {
   3521     InstanceType instance_type = GetInstanceType();
   3522     return instance_type == CELL_TYPE;
   3523   }
   3524 
   3525   Representation RequiredInputRepresentation(int index) override {
   3526     return Representation::None();
   3527   }
   3528 
   3529   Representation KnownOptimalRepresentation() override {
   3530     if (HasSmiValue() && SmiValuesAre31Bits()) return Representation::Smi();
   3531     if (HasInteger32Value()) return Representation::Integer32();
   3532     if (HasNumberValue()) return Representation::Double();
   3533     if (HasExternalReferenceValue()) return Representation::External();
   3534     return Representation::Tagged();
   3535   }
   3536 
   3537   bool EmitAtUses() override;
   3538   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3539   HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
   3540   Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone);
   3541   Maybe<HConstant*> CopyToTruncatedNumber(Isolate* isolate, Zone* zone);
   3542   bool HasInteger32Value() const {
   3543     return HasInt32ValueField::decode(bit_field_);
   3544   }
   3545   int32_t Integer32Value() const {
   3546     DCHECK(HasInteger32Value());
   3547     return int32_value_;
   3548   }
   3549   bool HasSmiValue() const { return HasSmiValueField::decode(bit_field_); }
   3550   bool HasDoubleValue() const {
   3551     return HasDoubleValueField::decode(bit_field_);
   3552   }
   3553   double DoubleValue() const {
   3554     DCHECK(HasDoubleValue());
   3555     return double_value_;
   3556   }
   3557   uint64_t DoubleValueAsBits() const {
   3558     uint64_t bits;
   3559     DCHECK(HasDoubleValue());
   3560     STATIC_ASSERT(sizeof(bits) == sizeof(double_value_));
   3561     std::memcpy(&bits, &double_value_, sizeof(bits));
   3562     return bits;
   3563   }
   3564   bool IsTheHole() const {
   3565     if (HasDoubleValue() && DoubleValueAsBits() == kHoleNanInt64) {
   3566       return true;
   3567     }
   3568     return object_.IsInitialized() &&
   3569            object_.IsKnownGlobal(isolate()->heap()->the_hole_value());
   3570   }
   3571   bool HasNumberValue() const { return HasDoubleValue(); }
   3572   int32_t NumberValueAsInteger32() const {
   3573     DCHECK(HasNumberValue());
   3574     // Irrespective of whether a numeric HConstant can be safely
   3575     // represented as an int32, we store the (in some cases lossy)
   3576     // representation of the number in int32_value_.
   3577     return int32_value_;
   3578   }
   3579   bool HasStringValue() const {
   3580     if (HasNumberValue()) return false;
   3581     DCHECK(!object_.handle().is_null());
   3582     return GetInstanceType() < FIRST_NONSTRING_TYPE;
   3583   }
   3584   Handle<String> StringValue() const {
   3585     DCHECK(HasStringValue());
   3586     return Handle<String>::cast(object_.handle());
   3587   }
   3588   bool HasInternalizedStringValue() const {
   3589     return HasStringValue() && StringShape(GetInstanceType()).IsInternalized();
   3590   }
   3591 
   3592   bool HasExternalReferenceValue() const {
   3593     return HasExternalReferenceValueField::decode(bit_field_);
   3594   }
   3595   ExternalReference ExternalReferenceValue() const {
   3596     return external_reference_value_;
   3597   }
   3598 
   3599   bool HasBooleanValue() const { return type_.IsBoolean(); }
   3600   bool BooleanValue() const { return BooleanValueField::decode(bit_field_); }
   3601   bool IsCallable() const { return IsCallableField::decode(bit_field_); }
   3602   bool IsUndetectable() const {
   3603     return IsUndetectableField::decode(bit_field_);
   3604   }
   3605   InstanceType GetInstanceType() const {
   3606     return InstanceTypeField::decode(bit_field_);
   3607   }
   3608 
   3609   bool HasMapValue() const { return GetInstanceType() == MAP_TYPE; }
   3610   Unique<Map> MapValue() const {
   3611     DCHECK(HasMapValue());
   3612     return Unique<Map>::cast(GetUnique());
   3613   }
   3614   bool HasStableMapValue() const {
   3615     DCHECK(HasMapValue() || !HasStableMapValueField::decode(bit_field_));
   3616     return HasStableMapValueField::decode(bit_field_);
   3617   }
   3618 
   3619   bool HasObjectMap() const { return !object_map_.IsNull(); }
   3620   Unique<Map> ObjectMap() const {
   3621     DCHECK(HasObjectMap());
   3622     return object_map_;
   3623   }
   3624 
   3625   intptr_t Hashcode() override {
   3626     if (HasInteger32Value()) {
   3627       return static_cast<intptr_t>(int32_value_);
   3628     } else if (HasDoubleValue()) {
   3629       uint64_t bits = DoubleValueAsBits();
   3630       if (sizeof(bits) > sizeof(intptr_t)) {
   3631         bits ^= (bits >> 32);
   3632       }
   3633       return static_cast<intptr_t>(bits);
   3634     } else if (HasExternalReferenceValue()) {
   3635       return reinterpret_cast<intptr_t>(external_reference_value_.address());
   3636     } else {
   3637       DCHECK(!object_.handle().is_null());
   3638       return object_.Hashcode();
   3639     }
   3640   }
   3641 
   3642   void FinalizeUniqueness() override {
   3643     if (!HasDoubleValue() && !HasExternalReferenceValue()) {
   3644       DCHECK(!object_.handle().is_null());
   3645       object_ = Unique<Object>(object_.handle());
   3646     }
   3647   }
   3648 
   3649   Unique<Object> GetUnique() const {
   3650     return object_;
   3651   }
   3652 
   3653   bool EqualsUnique(Unique<Object> other) const {
   3654     return object_.IsInitialized() && object_ == other;
   3655   }
   3656 
   3657   bool DataEquals(HValue* other) override {
   3658     HConstant* other_constant = HConstant::cast(other);
   3659     if (HasInteger32Value()) {
   3660       return other_constant->HasInteger32Value() &&
   3661              int32_value_ == other_constant->int32_value_;
   3662     } else if (HasDoubleValue()) {
   3663       return other_constant->HasDoubleValue() &&
   3664              std::memcmp(&double_value_, &other_constant->double_value_,
   3665                          sizeof(double_value_)) == 0;
   3666     } else if (HasExternalReferenceValue()) {
   3667       return other_constant->HasExternalReferenceValue() &&
   3668              external_reference_value_ ==
   3669                  other_constant->external_reference_value_;
   3670     } else {
   3671       if (other_constant->HasInteger32Value() ||
   3672           other_constant->HasDoubleValue() ||
   3673           other_constant->HasExternalReferenceValue()) {
   3674         return false;
   3675       }
   3676       DCHECK(!object_.handle().is_null());
   3677       return other_constant->object_ == object_;
   3678     }
   3679   }
   3680 
   3681 #ifdef DEBUG
   3682   void Verify() override {}
   3683 #endif
   3684 
   3685   DECLARE_CONCRETE_INSTRUCTION(Constant)
   3686 
   3687  protected:
   3688   Range* InferRange(Zone* zone) override;
   3689 
   3690  private:
   3691   friend class HGraph;
   3692   explicit HConstant(Special special);
   3693   explicit HConstant(Handle<Object> handle,
   3694                      Representation r = Representation::None());
   3695   HConstant(int32_t value,
   3696             Representation r = Representation::None(),
   3697             bool is_not_in_new_space = true,
   3698             Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
   3699   HConstant(double value,
   3700             Representation r = Representation::None(),
   3701             bool is_not_in_new_space = true,
   3702             Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
   3703   HConstant(Unique<Object> object,
   3704             Unique<Map> object_map,
   3705             bool has_stable_map_value,
   3706             Representation r,
   3707             HType type,
   3708             bool is_not_in_new_space,
   3709             bool boolean_value,
   3710             bool is_undetectable,
   3711             InstanceType instance_type);
   3712 
   3713   explicit HConstant(ExternalReference reference);
   3714 
   3715   void Initialize(Representation r);
   3716 
   3717   bool IsDeletable() const override { return true; }
   3718 
   3719   // If object_ is a map, this indicates whether the map is stable.
   3720   class HasStableMapValueField : public BitField<bool, 0, 1> {};
   3721 
   3722   // We store the HConstant in the most specific form safely possible.
   3723   // These flags tell us if the respective member fields hold valid, safe
   3724   // representations of the constant. More specific flags imply more general
   3725   // flags, but not the converse (i.e. smi => int32 => double).
   3726   class HasSmiValueField : public BitField<bool, 1, 1> {};
   3727   class HasInt32ValueField : public BitField<bool, 2, 1> {};
   3728   class HasDoubleValueField : public BitField<bool, 3, 1> {};
   3729 
   3730   class HasExternalReferenceValueField : public BitField<bool, 4, 1> {};
   3731   class IsNotInNewSpaceField : public BitField<bool, 5, 1> {};
   3732   class BooleanValueField : public BitField<bool, 6, 1> {};
   3733   class IsUndetectableField : public BitField<bool, 7, 1> {};
   3734   class IsCallableField : public BitField<bool, 8, 1> {};
   3735 
   3736   static const InstanceType kUnknownInstanceType = FILLER_TYPE;
   3737   class InstanceTypeField : public BitField<InstanceType, 16, 8> {};
   3738 
   3739   // If this is a numerical constant, object_ either points to the
   3740   // HeapObject the constant originated from or is null.  If the
   3741   // constant is non-numeric, object_ always points to a valid
   3742   // constant HeapObject.
   3743   Unique<Object> object_;
   3744 
   3745   // If object_ is a heap object, this points to the stable map of the object.
   3746   Unique<Map> object_map_;
   3747 
   3748   uint32_t bit_field_;
   3749 
   3750   int32_t int32_value_;
   3751   double double_value_;
   3752   ExternalReference external_reference_value_;
   3753 };
   3754 
   3755 
   3756 class HBinaryOperation : public HTemplateInstruction<3> {
   3757  public:
   3758   HBinaryOperation(HValue* context, HValue* left, HValue* right,
   3759                    Strength strength, HType type = HType::Tagged())
   3760       : HTemplateInstruction<3>(type),
   3761         strength_(strength),
   3762         observed_output_representation_(Representation::None()) {
   3763     DCHECK(left != NULL && right != NULL);
   3764     SetOperandAt(0, context);
   3765     SetOperandAt(1, left);
   3766     SetOperandAt(2, right);
   3767     observed_input_representation_[0] = Representation::None();
   3768     observed_input_representation_[1] = Representation::None();
   3769   }
   3770 
   3771   HValue* context() const { return OperandAt(0); }
   3772   HValue* left() const { return OperandAt(1); }
   3773   HValue* right() const { return OperandAt(2); }
   3774   Strength strength() const { return strength_; }
   3775 
   3776   // True if switching left and right operands likely generates better code.
   3777   bool AreOperandsBetterSwitched() {
   3778     if (!IsCommutative()) return false;
   3779 
   3780     // Constant operands are better off on the right, they can be inlined in
   3781     // many situations on most platforms.
   3782     if (left()->IsConstant()) return true;
   3783     if (right()->IsConstant()) return false;
   3784 
   3785     // Otherwise, if there is only one use of the right operand, it would be
   3786     // better off on the left for platforms that only have 2-arg arithmetic
   3787     // ops (e.g ia32, x64) that clobber the left operand.
   3788     return right()->HasOneUse();
   3789   }
   3790 
   3791   HValue* BetterLeftOperand() {
   3792     return AreOperandsBetterSwitched() ? right() : left();
   3793   }
   3794 
   3795   HValue* BetterRightOperand() {
   3796     return AreOperandsBetterSwitched() ? left() : right();
   3797   }
   3798 
   3799   void set_observed_input_representation(int index, Representation rep) {
   3800     DCHECK(index >= 1 && index <= 2);
   3801     observed_input_representation_[index - 1] = rep;
   3802   }
   3803 
   3804   virtual void initialize_output_representation(Representation observed) {
   3805     observed_output_representation_ = observed;
   3806   }
   3807 
   3808   Representation observed_input_representation(int index) override {
   3809     if (index == 0) return Representation::Tagged();
   3810     return observed_input_representation_[index - 1];
   3811   }
   3812 
   3813   void UpdateRepresentation(Representation new_rep,
   3814                             HInferRepresentationPhase* h_infer,
   3815                             const char* reason) override {
   3816     Representation rep = !FLAG_smi_binop && new_rep.IsSmi()
   3817         ? Representation::Integer32() : new_rep;
   3818     HValue::UpdateRepresentation(rep, h_infer, reason);
   3819   }
   3820 
   3821   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   3822   Representation RepresentationFromInputs() override;
   3823   Representation RepresentationFromOutput();
   3824   void AssumeRepresentation(Representation r) override;
   3825 
   3826   virtual bool IsCommutative() const { return false; }
   3827 
   3828   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3829 
   3830   Representation RequiredInputRepresentation(int index) override {
   3831     if (index == 0) return Representation::Tagged();
   3832     return representation();
   3833   }
   3834 
   3835   void SetOperandPositions(Zone* zone, SourcePosition left_pos,
   3836                            SourcePosition right_pos) {
   3837     set_operand_position(zone, 1, left_pos);
   3838     set_operand_position(zone, 2, right_pos);
   3839   }
   3840 
   3841   bool RightIsPowerOf2() {
   3842     if (!right()->IsInteger32Constant()) return false;
   3843     int32_t value = right()->GetInteger32Constant();
   3844     if (value < 0) {
   3845       return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(-value));
   3846     }
   3847     return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(value));
   3848   }
   3849 
   3850   Strength strength() { return strength_; }
   3851 
   3852   DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
   3853 
   3854  private:
   3855   bool IgnoreObservedOutputRepresentation(Representation current_rep);
   3856   Strength strength_;
   3857 
   3858   Representation observed_input_representation_[2];
   3859   Representation observed_output_representation_;
   3860 };
   3861 
   3862 
   3863 class HWrapReceiver final : public HTemplateInstruction<2> {
   3864  public:
   3865   DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
   3866 
   3867   bool DataEquals(HValue* other) override { return true; }
   3868 
   3869   Representation RequiredInputRepresentation(int index) override {
   3870     return Representation::Tagged();
   3871   }
   3872 
   3873   HValue* receiver() const { return OperandAt(0); }
   3874   HValue* function() const { return OperandAt(1); }
   3875 
   3876   HValue* Canonicalize() override;
   3877 
   3878   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3879   bool known_function() const { return known_function_; }
   3880 
   3881   DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
   3882 
   3883  private:
   3884   HWrapReceiver(HValue* receiver, HValue* function) {
   3885     known_function_ = function->IsConstant() &&
   3886         HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
   3887     set_representation(Representation::Tagged());
   3888     SetOperandAt(0, receiver);
   3889     SetOperandAt(1, function);
   3890     SetFlag(kUseGVN);
   3891   }
   3892 
   3893   bool known_function_;
   3894 };
   3895 
   3896 
   3897 class HApplyArguments final : public HTemplateInstruction<4> {
   3898  public:
   3899   DECLARE_INSTRUCTION_FACTORY_P4(HApplyArguments, HValue*, HValue*, HValue*,
   3900                                  HValue*);
   3901 
   3902   Representation RequiredInputRepresentation(int index) override {
   3903     // The length is untagged, all other inputs are tagged.
   3904     return (index == 2)
   3905         ? Representation::Integer32()
   3906         : Representation::Tagged();
   3907   }
   3908 
   3909   HValue* function() { return OperandAt(0); }
   3910   HValue* receiver() { return OperandAt(1); }
   3911   HValue* length() { return OperandAt(2); }
   3912   HValue* elements() { return OperandAt(3); }
   3913 
   3914   DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
   3915 
   3916  private:
   3917   HApplyArguments(HValue* function,
   3918                   HValue* receiver,
   3919                   HValue* length,
   3920                   HValue* elements) {
   3921     set_representation(Representation::Tagged());
   3922     SetOperandAt(0, function);
   3923     SetOperandAt(1, receiver);
   3924     SetOperandAt(2, length);
   3925     SetOperandAt(3, elements);
   3926     SetAllSideEffects();
   3927   }
   3928 };
   3929 
   3930 
   3931 class HArgumentsElements final : public HTemplateInstruction<0> {
   3932  public:
   3933   DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
   3934 
   3935   DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
   3936 
   3937   Representation RequiredInputRepresentation(int index) override {
   3938     return Representation::None();
   3939   }
   3940 
   3941   bool from_inlined() const { return from_inlined_; }
   3942 
   3943  protected:
   3944   bool DataEquals(HValue* other) override { return true; }
   3945 
   3946  private:
   3947   explicit HArgumentsElements(bool from_inlined) : from_inlined_(from_inlined) {
   3948     // The value produced by this instruction is a pointer into the stack
   3949     // that looks as if it was a smi because of alignment.
   3950     set_representation(Representation::Tagged());
   3951     SetFlag(kUseGVN);
   3952   }
   3953 
   3954   bool IsDeletable() const override { return true; }
   3955 
   3956   bool from_inlined_;
   3957 };
   3958 
   3959 
   3960 class HArgumentsLength final : public HUnaryOperation {
   3961  public:
   3962   DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue*);
   3963 
   3964   Representation RequiredInputRepresentation(int index) override {
   3965     return Representation::Tagged();
   3966   }
   3967 
   3968   DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
   3969 
   3970  protected:
   3971   bool DataEquals(HValue* other) override { return true; }
   3972 
   3973  private:
   3974   explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
   3975     set_representation(Representation::Integer32());
   3976     SetFlag(kUseGVN);
   3977   }
   3978 
   3979   bool IsDeletable() const override { return true; }
   3980 };
   3981 
   3982 
   3983 class HAccessArgumentsAt final : public HTemplateInstruction<3> {
   3984  public:
   3985   DECLARE_INSTRUCTION_FACTORY_P3(HAccessArgumentsAt, HValue*, HValue*, HValue*);
   3986 
   3987   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3988 
   3989   Representation RequiredInputRepresentation(int index) override {
   3990     // The arguments elements is considered tagged.
   3991     return index == 0
   3992         ? Representation::Tagged()
   3993         : Representation::Integer32();
   3994   }
   3995 
   3996   HValue* arguments() const { return OperandAt(0); }
   3997   HValue* length() const { return OperandAt(1); }
   3998   HValue* index() const { return OperandAt(2); }
   3999 
   4000   DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
   4001 
   4002  private:
   4003   HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
   4004     set_representation(Representation::Tagged());
   4005     SetFlag(kUseGVN);
   4006     SetOperandAt(0, arguments);
   4007     SetOperandAt(1, length);
   4008     SetOperandAt(2, index);
   4009   }
   4010 
   4011   bool DataEquals(HValue* other) override { return true; }
   4012 };
   4013 
   4014 
   4015 class HBoundsCheckBaseIndexInformation;
   4016 
   4017 
   4018 class HBoundsCheck final : public HTemplateInstruction<2> {
   4019  public:
   4020   DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
   4021 
   4022   bool skip_check() const { return skip_check_; }
   4023   void set_skip_check() { skip_check_ = true; }
   4024 
   4025   HValue* base() const { return base_; }
   4026   int offset() const { return offset_; }
   4027   int scale() const { return scale_; }
   4028 
   4029   void ApplyIndexChange();
   4030   bool DetectCompoundIndex() {
   4031     DCHECK(base() == NULL);
   4032 
   4033     DecompositionResult decomposition;
   4034     if (index()->TryDecompose(&decomposition)) {
   4035       base_ = decomposition.base();
   4036       offset_ = decomposition.offset();
   4037       scale_ = decomposition.scale();
   4038       return true;
   4039     } else {
   4040       base_ = index();
   4041       offset_ = 0;
   4042       scale_ = 0;
   4043       return false;
   4044     }
   4045   }
   4046 
   4047   Representation RequiredInputRepresentation(int index) override {
   4048     return representation();
   4049   }
   4050 
   4051   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4052   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   4053 
   4054   HValue* index() const { return OperandAt(0); }
   4055   HValue* length() const { return OperandAt(1); }
   4056   bool allow_equality() const { return allow_equality_; }
   4057   void set_allow_equality(bool v) { allow_equality_ = v; }
   4058 
   4059   int RedefinedOperandIndex() override { return 0; }
   4060   bool IsPurelyInformativeDefinition() override { return skip_check(); }
   4061 
   4062   DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
   4063 
   4064  protected:
   4065   friend class HBoundsCheckBaseIndexInformation;
   4066 
   4067   Range* InferRange(Zone* zone) override;
   4068 
   4069   bool DataEquals(HValue* other) override { return true; }
   4070   bool skip_check_;
   4071   HValue* base_;
   4072   int offset_;
   4073   int scale_;
   4074   bool allow_equality_;
   4075 
   4076  private:
   4077   // Normally HBoundsCheck should be created using the
   4078   // HGraphBuilder::AddBoundsCheck() helper.
   4079   // However when building stubs, where we know that the arguments are Int32,
   4080   // it makes sense to invoke this constructor directly.
   4081   HBoundsCheck(HValue* index, HValue* length)
   4082     : skip_check_(false),
   4083       base_(NULL), offset_(0), scale_(0),
   4084       allow_equality_(false) {
   4085     SetOperandAt(0, index);
   4086     SetOperandAt(1, length);
   4087     SetFlag(kFlexibleRepresentation);
   4088     SetFlag(kUseGVN);
   4089   }
   4090 
   4091   bool IsDeletable() const override { return skip_check() && !FLAG_debug_code; }
   4092 };
   4093 
   4094 
   4095 class HBoundsCheckBaseIndexInformation final : public HTemplateInstruction<2> {
   4096  public:
   4097   explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) {
   4098     DecompositionResult decomposition;
   4099     if (check->index()->TryDecompose(&decomposition)) {
   4100       SetOperandAt(0, decomposition.base());
   4101       SetOperandAt(1, check);
   4102     } else {
   4103       UNREACHABLE();
   4104     }
   4105   }
   4106 
   4107   HValue* base_index() const { return OperandAt(0); }
   4108   HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); }
   4109 
   4110   DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation)
   4111 
   4112   Representation RequiredInputRepresentation(int index) override {
   4113     return representation();
   4114   }
   4115 
   4116   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4117 
   4118   int RedefinedOperandIndex() override { return 0; }
   4119   bool IsPurelyInformativeDefinition() override { return true; }
   4120 };
   4121 
   4122 
   4123 class HBitwiseBinaryOperation : public HBinaryOperation {
   4124  public:
   4125   HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
   4126                           Strength strength, HType type = HType::TaggedNumber())
   4127       : HBinaryOperation(context, left, right, strength, type) {
   4128     SetFlag(kFlexibleRepresentation);
   4129     SetFlag(kTruncatingToInt32);
   4130     if (!is_strong(strength)) SetFlag(kAllowUndefinedAsNaN);
   4131     SetAllSideEffects();
   4132   }
   4133 
   4134   void RepresentationChanged(Representation to) override {
   4135     if (to.IsTagged() &&
   4136         (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
   4137       SetAllSideEffects();
   4138       ClearFlag(kUseGVN);
   4139     } else {
   4140       ClearAllSideEffects();
   4141       SetFlag(kUseGVN);
   4142     }
   4143     if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
   4144   }
   4145 
   4146   void UpdateRepresentation(Representation new_rep,
   4147                             HInferRepresentationPhase* h_infer,
   4148                             const char* reason) override {
   4149     // We only generate either int32 or generic tagged bitwise operations.
   4150     if (new_rep.IsDouble()) new_rep = Representation::Integer32();
   4151     HBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4152   }
   4153 
   4154   Representation observed_input_representation(int index) override {
   4155     Representation r = HBinaryOperation::observed_input_representation(index);
   4156     if (r.IsDouble()) return Representation::Integer32();
   4157     return r;
   4158   }
   4159 
   4160   void initialize_output_representation(Representation observed) override {
   4161     if (observed.IsDouble()) observed = Representation::Integer32();
   4162     HBinaryOperation::initialize_output_representation(observed);
   4163   }
   4164 
   4165   DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
   4166 
   4167  private:
   4168   bool IsDeletable() const override { return true; }
   4169 };
   4170 
   4171 
   4172 class HMathFloorOfDiv final : public HBinaryOperation {
   4173  public:
   4174   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HMathFloorOfDiv,
   4175                                               HValue*,
   4176                                               HValue*);
   4177 
   4178   DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
   4179 
   4180  protected:
   4181   bool DataEquals(HValue* other) override { return true; }
   4182 
   4183  private:
   4184   HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
   4185       : HBinaryOperation(context, left, right, Strength::WEAK) {
   4186     set_representation(Representation::Integer32());
   4187     SetFlag(kUseGVN);
   4188     SetFlag(kCanOverflow);
   4189     SetFlag(kCanBeDivByZero);
   4190     SetFlag(kLeftCanBeMinInt);
   4191     SetFlag(kLeftCanBeNegative);
   4192     SetFlag(kLeftCanBePositive);
   4193     SetFlag(kAllowUndefinedAsNaN);
   4194   }
   4195 
   4196   Range* InferRange(Zone* zone) override;
   4197 
   4198   bool IsDeletable() const override { return true; }
   4199 };
   4200 
   4201 
   4202 class HArithmeticBinaryOperation : public HBinaryOperation {
   4203  public:
   4204   HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right,
   4205                              Strength strength)
   4206       : HBinaryOperation(context, left, right, strength,
   4207                          HType::TaggedNumber()) {
   4208     SetAllSideEffects();
   4209     SetFlag(kFlexibleRepresentation);
   4210     if (!is_strong(strength)) SetFlag(kAllowUndefinedAsNaN);
   4211   }
   4212 
   4213   void RepresentationChanged(Representation to) override {
   4214     if (to.IsTagged() &&
   4215         (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
   4216       SetAllSideEffects();
   4217       ClearFlag(kUseGVN);
   4218     } else {
   4219       ClearAllSideEffects();
   4220       SetFlag(kUseGVN);
   4221     }
   4222     if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
   4223   }
   4224 
   4225   DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
   4226 
   4227  private:
   4228   bool IsDeletable() const override { return true; }
   4229 };
   4230 
   4231 
   4232 class HCompareGeneric final : public HBinaryOperation {
   4233  public:
   4234   static HCompareGeneric* New(Isolate* isolate, Zone* zone, HValue* context,
   4235                               HValue* left, HValue* right, Token::Value token,
   4236                               Strength strength = Strength::WEAK) {
   4237     return new (zone) HCompareGeneric(context, left, right, token, strength);
   4238   }
   4239 
   4240   Representation RequiredInputRepresentation(int index) override {
   4241     return index == 0
   4242         ? Representation::Tagged()
   4243         : representation();
   4244   }
   4245 
   4246   Token::Value token() const { return token_; }
   4247   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4248 
   4249   DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
   4250 
   4251  private:
   4252   HCompareGeneric(HValue* context, HValue* left, HValue* right,
   4253                   Token::Value token, Strength strength)
   4254       : HBinaryOperation(context, left, right, strength, HType::Boolean()),
   4255         token_(token) {
   4256     DCHECK(Token::IsCompareOp(token));
   4257     set_representation(Representation::Tagged());
   4258     SetAllSideEffects();
   4259   }
   4260 
   4261   Token::Value token_;
   4262 };
   4263 
   4264 
   4265 class HCompareNumericAndBranch : public HTemplateControlInstruction<2, 2> {
   4266  public:
   4267   static HCompareNumericAndBranch* New(Isolate* isolate, Zone* zone,
   4268                                        HValue* context, HValue* left,
   4269                                        HValue* right, Token::Value token,
   4270                                        HBasicBlock* true_target = NULL,
   4271                                        HBasicBlock* false_target = NULL,
   4272                                        Strength strength = Strength::WEAK) {
   4273     return new (zone) HCompareNumericAndBranch(left, right, token, true_target,
   4274                                                false_target, strength);
   4275   }
   4276   static HCompareNumericAndBranch* New(Isolate* isolate, Zone* zone,
   4277                                        HValue* context, HValue* left,
   4278                                        HValue* right, Token::Value token,
   4279                                        Strength strength) {
   4280     return new (zone)
   4281         HCompareNumericAndBranch(left, right, token, NULL, NULL, strength);
   4282   }
   4283 
   4284   HValue* left() const { return OperandAt(0); }
   4285   HValue* right() const { return OperandAt(1); }
   4286   Token::Value token() const { return token_; }
   4287 
   4288   void set_observed_input_representation(Representation left,
   4289                                          Representation right) {
   4290       observed_input_representation_[0] = left;
   4291       observed_input_representation_[1] = right;
   4292   }
   4293 
   4294   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   4295 
   4296   Representation RequiredInputRepresentation(int index) override {
   4297     return representation();
   4298   }
   4299   Representation observed_input_representation(int index) override {
   4300     return observed_input_representation_[index];
   4301   }
   4302 
   4303   bool KnownSuccessorBlock(HBasicBlock** block) override;
   4304 
   4305   Strength strength() const { return strength_; }
   4306 
   4307   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4308 
   4309   void SetOperandPositions(Zone* zone, SourcePosition left_pos,
   4310                            SourcePosition right_pos) {
   4311     set_operand_position(zone, 0, left_pos);
   4312     set_operand_position(zone, 1, right_pos);
   4313   }
   4314 
   4315   DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
   4316 
   4317  private:
   4318   HCompareNumericAndBranch(HValue* left, HValue* right, Token::Value token,
   4319                            HBasicBlock* true_target, HBasicBlock* false_target,
   4320                            Strength strength)
   4321       : token_(token), strength_(strength) {
   4322     SetFlag(kFlexibleRepresentation);
   4323     DCHECK(Token::IsCompareOp(token));
   4324     SetOperandAt(0, left);
   4325     SetOperandAt(1, right);
   4326     SetSuccessorAt(0, true_target);
   4327     SetSuccessorAt(1, false_target);
   4328   }
   4329 
   4330   Representation observed_input_representation_[2];
   4331   Token::Value token_;
   4332   Strength strength_;
   4333 };
   4334 
   4335 
   4336 class HCompareHoleAndBranch final : public HUnaryControlInstruction {
   4337  public:
   4338   DECLARE_INSTRUCTION_FACTORY_P1(HCompareHoleAndBranch, HValue*);
   4339   DECLARE_INSTRUCTION_FACTORY_P3(HCompareHoleAndBranch, HValue*,
   4340                                  HBasicBlock*, HBasicBlock*);
   4341 
   4342   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   4343 
   4344   Representation RequiredInputRepresentation(int index) override {
   4345     return representation();
   4346   }
   4347 
   4348   DECLARE_CONCRETE_INSTRUCTION(CompareHoleAndBranch)
   4349 
   4350  private:
   4351   HCompareHoleAndBranch(HValue* value,
   4352                         HBasicBlock* true_target = NULL,
   4353                         HBasicBlock* false_target = NULL)
   4354       : HUnaryControlInstruction(value, true_target, false_target) {
   4355     SetFlag(kFlexibleRepresentation);
   4356     SetFlag(kAllowUndefinedAsNaN);
   4357   }
   4358 };
   4359 
   4360 
   4361 class HCompareMinusZeroAndBranch final : public HUnaryControlInstruction {
   4362  public:
   4363   DECLARE_INSTRUCTION_FACTORY_P1(HCompareMinusZeroAndBranch, HValue*);
   4364 
   4365   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   4366 
   4367   Representation RequiredInputRepresentation(int index) override {
   4368     return representation();
   4369   }
   4370 
   4371   bool KnownSuccessorBlock(HBasicBlock** block) override;
   4372 
   4373   DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch)
   4374 
   4375  private:
   4376   explicit HCompareMinusZeroAndBranch(HValue* value)
   4377       : HUnaryControlInstruction(value, NULL, NULL) {
   4378   }
   4379 };
   4380 
   4381 
   4382 class HCompareObjectEqAndBranch : public HTemplateControlInstruction<2, 2> {
   4383  public:
   4384   DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue*, HValue*);
   4385   DECLARE_INSTRUCTION_FACTORY_P4(HCompareObjectEqAndBranch, HValue*, HValue*,
   4386                                  HBasicBlock*, HBasicBlock*);
   4387 
   4388   bool KnownSuccessorBlock(HBasicBlock** block) override;
   4389 
   4390   static const int kNoKnownSuccessorIndex = -1;
   4391   int known_successor_index() const { return known_successor_index_; }
   4392   void set_known_successor_index(int known_successor_index) {
   4393     known_successor_index_ = known_successor_index;
   4394   }
   4395 
   4396   HValue* left() const { return OperandAt(0); }
   4397   HValue* right() const { return OperandAt(1); }
   4398 
   4399   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4400 
   4401   Representation RequiredInputRepresentation(int index) override {
   4402     return Representation::Tagged();
   4403   }
   4404 
   4405   Representation observed_input_representation(int index) override {
   4406     return Representation::Tagged();
   4407   }
   4408 
   4409   DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
   4410 
   4411  private:
   4412   HCompareObjectEqAndBranch(HValue* left,
   4413                             HValue* right,
   4414                             HBasicBlock* true_target = NULL,
   4415                             HBasicBlock* false_target = NULL)
   4416       : known_successor_index_(kNoKnownSuccessorIndex) {
   4417     SetOperandAt(0, left);
   4418     SetOperandAt(1, right);
   4419     SetSuccessorAt(0, true_target);
   4420     SetSuccessorAt(1, false_target);
   4421   }
   4422 
   4423   int known_successor_index_;
   4424 };
   4425 
   4426 
   4427 class HIsStringAndBranch final : public HUnaryControlInstruction {
   4428  public:
   4429   DECLARE_INSTRUCTION_FACTORY_P1(HIsStringAndBranch, HValue*);
   4430   DECLARE_INSTRUCTION_FACTORY_P3(HIsStringAndBranch, HValue*,
   4431                                  HBasicBlock*, HBasicBlock*);
   4432 
   4433   Representation RequiredInputRepresentation(int index) override {
   4434     return Representation::Tagged();
   4435   }
   4436 
   4437   bool KnownSuccessorBlock(HBasicBlock** block) override;
   4438 
   4439   static const int kNoKnownSuccessorIndex = -1;
   4440   int known_successor_index() const { return known_successor_index_; }
   4441   void set_known_successor_index(int known_successor_index) {
   4442     known_successor_index_ = known_successor_index;
   4443   }
   4444 
   4445   DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
   4446 
   4447  protected:
   4448   int RedefinedOperandIndex() override { return 0; }
   4449 
   4450  private:
   4451   HIsStringAndBranch(HValue* value, HBasicBlock* true_target = NULL,
   4452                      HBasicBlock* false_target = NULL)
   4453       : HUnaryControlInstruction(value, true_target, false_target),
   4454         known_successor_index_(kNoKnownSuccessorIndex) {
   4455     set_representation(Representation::Tagged());
   4456   }
   4457 
   4458   int known_successor_index_;
   4459 };
   4460 
   4461 
   4462 class HIsSmiAndBranch final : public HUnaryControlInstruction {
   4463  public:
   4464   DECLARE_INSTRUCTION_FACTORY_P1(HIsSmiAndBranch, HValue*);
   4465   DECLARE_INSTRUCTION_FACTORY_P3(HIsSmiAndBranch, HValue*,
   4466                                  HBasicBlock*, HBasicBlock*);
   4467 
   4468   DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
   4469 
   4470   Representation RequiredInputRepresentation(int index) override {
   4471     return Representation::Tagged();
   4472   }
   4473 
   4474  protected:
   4475   bool DataEquals(HValue* other) override { return true; }
   4476   int RedefinedOperandIndex() override { return 0; }
   4477 
   4478  private:
   4479   HIsSmiAndBranch(HValue* value,
   4480                   HBasicBlock* true_target = NULL,
   4481                   HBasicBlock* false_target = NULL)
   4482       : HUnaryControlInstruction(value, true_target, false_target) {
   4483     set_representation(Representation::Tagged());
   4484   }
   4485 };
   4486 
   4487 
   4488 class HIsUndetectableAndBranch final : public HUnaryControlInstruction {
   4489  public:
   4490   DECLARE_INSTRUCTION_FACTORY_P1(HIsUndetectableAndBranch, HValue*);
   4491   DECLARE_INSTRUCTION_FACTORY_P3(HIsUndetectableAndBranch, HValue*,
   4492                                  HBasicBlock*, HBasicBlock*);
   4493 
   4494   Representation RequiredInputRepresentation(int index) override {
   4495     return Representation::Tagged();
   4496   }
   4497 
   4498   bool KnownSuccessorBlock(HBasicBlock** block) override;
   4499 
   4500   DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
   4501 
   4502  private:
   4503   HIsUndetectableAndBranch(HValue* value,
   4504                            HBasicBlock* true_target = NULL,
   4505                            HBasicBlock* false_target = NULL)
   4506       : HUnaryControlInstruction(value, true_target, false_target) {}
   4507 };
   4508 
   4509 
   4510 class HStringCompareAndBranch final : public HTemplateControlInstruction<2, 3> {
   4511  public:
   4512   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HStringCompareAndBranch,
   4513                                               HValue*,
   4514                                               HValue*,
   4515                                               Token::Value);
   4516 
   4517   HValue* context() const { return OperandAt(0); }
   4518   HValue* left() const { return OperandAt(1); }
   4519   HValue* right() const { return OperandAt(2); }
   4520   Token::Value token() const { return token_; }
   4521 
   4522   std::ostream& PrintDataTo(std::ostream& os) const final;  // NOLINT
   4523 
   4524   Representation RequiredInputRepresentation(int index) final {
   4525     return Representation::Tagged();
   4526   }
   4527 
   4528   DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
   4529 
   4530  private:
   4531   HStringCompareAndBranch(HValue* context, HValue* left, HValue* right,
   4532                           Token::Value token)
   4533       : token_(token) {
   4534     DCHECK(Token::IsCompareOp(token));
   4535     SetOperandAt(0, context);
   4536     SetOperandAt(1, left);
   4537     SetOperandAt(2, right);
   4538     set_representation(Representation::Tagged());
   4539     SetChangesFlag(kNewSpacePromotion);
   4540     SetDependsOnFlag(kStringChars);
   4541     SetDependsOnFlag(kStringLengths);
   4542   }
   4543 
   4544   Token::Value const token_;
   4545 };
   4546 
   4547 
   4548 class HHasInstanceTypeAndBranch final : public HUnaryControlInstruction {
   4549  public:
   4550   DECLARE_INSTRUCTION_FACTORY_P2(
   4551       HHasInstanceTypeAndBranch, HValue*, InstanceType);
   4552   DECLARE_INSTRUCTION_FACTORY_P3(
   4553       HHasInstanceTypeAndBranch, HValue*, InstanceType, InstanceType);
   4554 
   4555   InstanceType from() { return from_; }
   4556   InstanceType to() { return to_; }
   4557 
   4558   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4559 
   4560   Representation RequiredInputRepresentation(int index) override {
   4561     return Representation::Tagged();
   4562   }
   4563 
   4564   bool KnownSuccessorBlock(HBasicBlock** block) override;
   4565 
   4566   DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
   4567 
   4568  private:
   4569   HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
   4570       : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
   4571   HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
   4572       : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
   4573     DCHECK(to == LAST_TYPE);  // Others not implemented yet in backend.
   4574   }
   4575 
   4576   InstanceType from_;
   4577   InstanceType to_;  // Inclusive range, not all combinations work.
   4578 };
   4579 
   4580 
   4581 class HHasCachedArrayIndexAndBranch final : public HUnaryControlInstruction {
   4582  public:
   4583   DECLARE_INSTRUCTION_FACTORY_P1(HHasCachedArrayIndexAndBranch, HValue*);
   4584 
   4585   Representation RequiredInputRepresentation(int index) override {
   4586     return Representation::Tagged();
   4587   }
   4588 
   4589   DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
   4590  private:
   4591   explicit HHasCachedArrayIndexAndBranch(HValue* value)
   4592       : HUnaryControlInstruction(value, NULL, NULL) { }
   4593 };
   4594 
   4595 
   4596 class HGetCachedArrayIndex final : public HUnaryOperation {
   4597  public:
   4598   DECLARE_INSTRUCTION_FACTORY_P1(HGetCachedArrayIndex, HValue*);
   4599 
   4600   Representation RequiredInputRepresentation(int index) override {
   4601     return Representation::Tagged();
   4602   }
   4603 
   4604   DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
   4605 
   4606  protected:
   4607   bool DataEquals(HValue* other) override { return true; }
   4608 
   4609  private:
   4610   explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
   4611     set_representation(Representation::Tagged());
   4612     SetFlag(kUseGVN);
   4613   }
   4614 
   4615   bool IsDeletable() const override { return true; }
   4616 };
   4617 
   4618 
   4619 class HClassOfTestAndBranch final : public HUnaryControlInstruction {
   4620  public:
   4621   DECLARE_INSTRUCTION_FACTORY_P2(HClassOfTestAndBranch, HValue*,
   4622                                  Handle<String>);
   4623 
   4624   DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
   4625 
   4626   Representation RequiredInputRepresentation(int index) override {
   4627     return Representation::Tagged();
   4628   }
   4629 
   4630   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4631 
   4632   Handle<String> class_name() const { return class_name_; }
   4633 
   4634  private:
   4635   HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
   4636       : HUnaryControlInstruction(value, NULL, NULL),
   4637         class_name_(class_name) { }
   4638 
   4639   Handle<String> class_name_;
   4640 };
   4641 
   4642 
   4643 class HTypeofIsAndBranch final : public HUnaryControlInstruction {
   4644  public:
   4645   DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle<String>);
   4646 
   4647   Handle<String> type_literal() const { return type_literal_.handle(); }
   4648   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4649 
   4650   DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
   4651 
   4652   Representation RequiredInputRepresentation(int index) override {
   4653     return Representation::None();
   4654   }
   4655 
   4656   bool KnownSuccessorBlock(HBasicBlock** block) override;
   4657 
   4658   void FinalizeUniqueness() override {
   4659     type_literal_ = Unique<String>(type_literal_.handle());
   4660   }
   4661 
   4662  private:
   4663   HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
   4664       : HUnaryControlInstruction(value, NULL, NULL),
   4665         type_literal_(Unique<String>::CreateUninitialized(type_literal)) { }
   4666 
   4667   Unique<String> type_literal_;
   4668 };
   4669 
   4670 
   4671 class HInstanceOf final : public HBinaryOperation {
   4672  public:
   4673   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOf, HValue*, HValue*);
   4674 
   4675   Representation RequiredInputRepresentation(int index) override {
   4676     return Representation::Tagged();
   4677   }
   4678 
   4679   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4680 
   4681   DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
   4682 
   4683  private:
   4684   HInstanceOf(HValue* context, HValue* left, HValue* right)
   4685       : HBinaryOperation(context, left, right, Strength::WEAK,
   4686                          HType::Boolean()) {
   4687     set_representation(Representation::Tagged());
   4688     SetAllSideEffects();
   4689   }
   4690 };
   4691 
   4692 
   4693 class HHasInPrototypeChainAndBranch final
   4694     : public HTemplateControlInstruction<2, 2> {
   4695  public:
   4696   DECLARE_INSTRUCTION_FACTORY_P2(HHasInPrototypeChainAndBranch, HValue*,
   4697                                  HValue*);
   4698 
   4699   HValue* object() const { return OperandAt(0); }
   4700   HValue* prototype() const { return OperandAt(1); }
   4701 
   4702   Representation RequiredInputRepresentation(int index) override {
   4703     return Representation::Tagged();
   4704   }
   4705 
   4706   bool ObjectNeedsSmiCheck() const {
   4707     return !object()->type().IsHeapObject() &&
   4708            !object()->representation().IsHeapObject();
   4709   }
   4710 
   4711   DECLARE_CONCRETE_INSTRUCTION(HasInPrototypeChainAndBranch)
   4712 
   4713  private:
   4714   HHasInPrototypeChainAndBranch(HValue* object, HValue* prototype) {
   4715     SetOperandAt(0, object);
   4716     SetOperandAt(1, prototype);
   4717     SetDependsOnFlag(kCalls);
   4718   }
   4719 };
   4720 
   4721 
   4722 class HPower final : public HTemplateInstruction<2> {
   4723  public:
   4724   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4725                            HValue* left, HValue* right);
   4726 
   4727   HValue* left() { return OperandAt(0); }
   4728   HValue* right() const { return OperandAt(1); }
   4729 
   4730   Representation RequiredInputRepresentation(int index) override {
   4731     return index == 0
   4732       ? Representation::Double()
   4733       : Representation::None();
   4734   }
   4735   Representation observed_input_representation(int index) override {
   4736     return RequiredInputRepresentation(index);
   4737   }
   4738 
   4739   DECLARE_CONCRETE_INSTRUCTION(Power)
   4740 
   4741  protected:
   4742   bool DataEquals(HValue* other) override { return true; }
   4743 
   4744  private:
   4745   HPower(HValue* left, HValue* right) {
   4746     SetOperandAt(0, left);
   4747     SetOperandAt(1, right);
   4748     set_representation(Representation::Double());
   4749     SetFlag(kUseGVN);
   4750     SetChangesFlag(kNewSpacePromotion);
   4751   }
   4752 
   4753   bool IsDeletable() const override {
   4754     return !right()->representation().IsTagged();
   4755   }
   4756 };
   4757 
   4758 
   4759 enum ExternalAddType {
   4760   AddOfExternalAndTagged,
   4761   AddOfExternalAndInt32,
   4762   NoExternalAdd
   4763 };
   4764 
   4765 
   4766 class HAdd final : public HArithmeticBinaryOperation {
   4767  public:
   4768   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4769                            HValue* left, HValue* right,
   4770                            Strength strength = Strength::WEAK);
   4771   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4772                            HValue* left, HValue* right, Strength strength,
   4773                            ExternalAddType external_add_type);
   4774 
   4775   // Add is only commutative if two integer values are added and not if two
   4776   // tagged values are added (because it might be a String concatenation).
   4777   // We also do not commute (pointer + offset).
   4778   bool IsCommutative() const override {
   4779     return !representation().IsTagged() && !representation().IsExternal();
   4780   }
   4781 
   4782   HValue* Canonicalize() override;
   4783 
   4784   bool TryDecompose(DecompositionResult* decomposition) override {
   4785     if (left()->IsInteger32Constant()) {
   4786       decomposition->Apply(right(), left()->GetInteger32Constant());
   4787       return true;
   4788     } else if (right()->IsInteger32Constant()) {
   4789       decomposition->Apply(left(), right()->GetInteger32Constant());
   4790       return true;
   4791     } else {
   4792       return false;
   4793     }
   4794   }
   4795 
   4796   void RepresentationChanged(Representation to) override {
   4797     if (to.IsTagged() &&
   4798         (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() ||
   4799          left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) {
   4800       SetAllSideEffects();
   4801       ClearFlag(kUseGVN);
   4802     } else {
   4803       ClearAllSideEffects();
   4804       SetFlag(kUseGVN);
   4805     }
   4806     if (to.IsTagged()) {
   4807       SetChangesFlag(kNewSpacePromotion);
   4808       ClearFlag(kAllowUndefinedAsNaN);
   4809     }
   4810   }
   4811 
   4812   Representation RepresentationFromInputs() override;
   4813 
   4814   Representation RequiredInputRepresentation(int index) override;
   4815 
   4816   bool IsConsistentExternalRepresentation() {
   4817     return left()->representation().IsExternal() &&
   4818            ((external_add_type_ == AddOfExternalAndInt32 &&
   4819              right()->representation().IsInteger32()) ||
   4820             (external_add_type_ == AddOfExternalAndTagged &&
   4821              right()->representation().IsTagged()));
   4822   }
   4823 
   4824   ExternalAddType external_add_type() const { return external_add_type_; }
   4825 
   4826   DECLARE_CONCRETE_INSTRUCTION(Add)
   4827 
   4828  protected:
   4829   bool DataEquals(HValue* other) override { return true; }
   4830 
   4831   Range* InferRange(Zone* zone) override;
   4832 
   4833  private:
   4834   HAdd(HValue* context, HValue* left, HValue* right, Strength strength,
   4835        ExternalAddType external_add_type = NoExternalAdd)
   4836       : HArithmeticBinaryOperation(context, left, right, strength),
   4837         external_add_type_(external_add_type) {
   4838     SetFlag(kCanOverflow);
   4839     switch (external_add_type_) {
   4840       case AddOfExternalAndTagged:
   4841         DCHECK(left->representation().IsExternal());
   4842         DCHECK(right->representation().IsTagged());
   4843         SetDependsOnFlag(kNewSpacePromotion);
   4844         ClearFlag(HValue::kCanOverflow);
   4845         SetFlag(kHasNoObservableSideEffects);
   4846         break;
   4847 
   4848       case NoExternalAdd:
   4849         // This is a bit of a hack: The call to this constructor is generated
   4850         // by a macro that also supports sub and mul, so it doesn't pass in
   4851         // a value for external_add_type but uses the default.
   4852         if (left->representation().IsExternal()) {
   4853           external_add_type_ = AddOfExternalAndInt32;
   4854         }
   4855         break;
   4856 
   4857       case AddOfExternalAndInt32:
   4858         // See comment above.
   4859         UNREACHABLE();
   4860         break;
   4861     }
   4862   }
   4863 
   4864   ExternalAddType external_add_type_;
   4865 };
   4866 
   4867 
   4868 class HSub final : public HArithmeticBinaryOperation {
   4869  public:
   4870   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4871                            HValue* left, HValue* right,
   4872                            Strength strength = Strength::WEAK);
   4873 
   4874   HValue* Canonicalize() override;
   4875 
   4876   bool TryDecompose(DecompositionResult* decomposition) override {
   4877     if (right()->IsInteger32Constant()) {
   4878       decomposition->Apply(left(), -right()->GetInteger32Constant());
   4879       return true;
   4880     } else {
   4881       return false;
   4882     }
   4883   }
   4884 
   4885   DECLARE_CONCRETE_INSTRUCTION(Sub)
   4886 
   4887  protected:
   4888   bool DataEquals(HValue* other) override { return true; }
   4889 
   4890   Range* InferRange(Zone* zone) override;
   4891 
   4892  private:
   4893   HSub(HValue* context, HValue* left, HValue* right, Strength strength)
   4894       : HArithmeticBinaryOperation(context, left, right, strength) {
   4895     SetFlag(kCanOverflow);
   4896   }
   4897 };
   4898 
   4899 
   4900 class HMul final : public HArithmeticBinaryOperation {
   4901  public:
   4902   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4903                            HValue* left, HValue* right,
   4904                            Strength strength = Strength::WEAK);
   4905 
   4906   static HInstruction* NewImul(Isolate* isolate, Zone* zone, HValue* context,
   4907                                HValue* left, HValue* right,
   4908                                Strength strength = Strength::WEAK) {
   4909     HInstruction* instr =
   4910         HMul::New(isolate, zone, context, left, right, strength);
   4911     if (!instr->IsMul()) return instr;
   4912     HMul* mul = HMul::cast(instr);
   4913     // TODO(mstarzinger): Prevent bailout on minus zero for imul.
   4914     mul->AssumeRepresentation(Representation::Integer32());
   4915     mul->ClearFlag(HValue::kCanOverflow);
   4916     return mul;
   4917   }
   4918 
   4919   HValue* Canonicalize() override;
   4920 
   4921   // Only commutative if it is certain that not two objects are multiplicated.
   4922   bool IsCommutative() const override { return !representation().IsTagged(); }
   4923 
   4924   void UpdateRepresentation(Representation new_rep,
   4925                             HInferRepresentationPhase* h_infer,
   4926                             const char* reason) override {
   4927     HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4928   }
   4929 
   4930   bool MulMinusOne();
   4931 
   4932   DECLARE_CONCRETE_INSTRUCTION(Mul)
   4933 
   4934  protected:
   4935   bool DataEquals(HValue* other) override { return true; }
   4936 
   4937   Range* InferRange(Zone* zone) override;
   4938 
   4939  private:
   4940   HMul(HValue* context, HValue* left, HValue* right, Strength strength)
   4941       : HArithmeticBinaryOperation(context, left, right, strength) {
   4942     SetFlag(kCanOverflow);
   4943   }
   4944 };
   4945 
   4946 
   4947 class HMod final : public HArithmeticBinaryOperation {
   4948  public:
   4949   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4950                            HValue* left, HValue* right,
   4951                            Strength strength = Strength::WEAK);
   4952 
   4953   HValue* Canonicalize() override;
   4954 
   4955   void UpdateRepresentation(Representation new_rep,
   4956                             HInferRepresentationPhase* h_infer,
   4957                             const char* reason) override {
   4958     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
   4959     HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4960   }
   4961 
   4962   DECLARE_CONCRETE_INSTRUCTION(Mod)
   4963 
   4964  protected:
   4965   bool DataEquals(HValue* other) override { return true; }
   4966 
   4967   Range* InferRange(Zone* zone) override;
   4968 
   4969  private:
   4970   HMod(HValue* context, HValue* left, HValue* right, Strength strength)
   4971       : HArithmeticBinaryOperation(context, left, right, strength) {
   4972     SetFlag(kCanBeDivByZero);
   4973     SetFlag(kCanOverflow);
   4974     SetFlag(kLeftCanBeNegative);
   4975   }
   4976 };
   4977 
   4978 
   4979 class HDiv final : public HArithmeticBinaryOperation {
   4980  public:
   4981   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4982                            HValue* left, HValue* right,
   4983                            Strength strength = Strength::WEAK);
   4984 
   4985   HValue* Canonicalize() override;
   4986 
   4987   void UpdateRepresentation(Representation new_rep,
   4988                             HInferRepresentationPhase* h_infer,
   4989                             const char* reason) override {
   4990     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
   4991     HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4992   }
   4993 
   4994   DECLARE_CONCRETE_INSTRUCTION(Div)
   4995 
   4996  protected:
   4997   bool DataEquals(HValue* other) override { return true; }
   4998 
   4999   Range* InferRange(Zone* zone) override;
   5000 
   5001  private:
   5002   HDiv(HValue* context, HValue* left, HValue* right, Strength strength)
   5003       : HArithmeticBinaryOperation(context, left, right, strength) {
   5004     SetFlag(kCanBeDivByZero);
   5005     SetFlag(kCanOverflow);
   5006   }
   5007 };
   5008 
   5009 
   5010 class HMathMinMax final : public HArithmeticBinaryOperation {
   5011  public:
   5012   enum Operation { kMathMin, kMathMax };
   5013 
   5014   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   5015                            HValue* left, HValue* right, Operation op);
   5016 
   5017   Representation observed_input_representation(int index) override {
   5018     return RequiredInputRepresentation(index);
   5019   }
   5020 
   5021   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   5022 
   5023   Representation RepresentationFromInputs() override {
   5024     Representation left_rep = left()->representation();
   5025     Representation right_rep = right()->representation();
   5026     Representation result = Representation::Smi();
   5027     result = result.generalize(left_rep);
   5028     result = result.generalize(right_rep);
   5029     if (result.IsTagged()) return Representation::Double();
   5030     return result;
   5031   }
   5032 
   5033   bool IsCommutative() const override { return true; }
   5034 
   5035   Operation operation() { return operation_; }
   5036 
   5037   DECLARE_CONCRETE_INSTRUCTION(MathMinMax)
   5038 
   5039  protected:
   5040   bool DataEquals(HValue* other) override {
   5041     return other->IsMathMinMax() &&
   5042         HMathMinMax::cast(other)->operation_ == operation_;
   5043   }
   5044 
   5045   Range* InferRange(Zone* zone) override;
   5046 
   5047  private:
   5048   HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
   5049       : HArithmeticBinaryOperation(context, left, right, Strength::WEAK),
   5050         operation_(op) {}
   5051 
   5052   Operation operation_;
   5053 };
   5054 
   5055 
   5056 class HBitwise final : public HBitwiseBinaryOperation {
   5057  public:
   5058   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   5059                            Token::Value op, HValue* left, HValue* right,
   5060                            Strength strength = Strength::WEAK);
   5061 
   5062   Token::Value op() const { return op_; }
   5063 
   5064   bool IsCommutative() const override { return true; }
   5065 
   5066   HValue* Canonicalize() override;
   5067 
   5068   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5069 
   5070   DECLARE_CONCRETE_INSTRUCTION(Bitwise)
   5071 
   5072  protected:
   5073   bool DataEquals(HValue* other) override {
   5074     return op() == HBitwise::cast(other)->op();
   5075   }
   5076 
   5077   Range* InferRange(Zone* zone) override;
   5078 
   5079  private:
   5080   HBitwise(HValue* context, Token::Value op, HValue* left, HValue* right,
   5081            Strength strength)
   5082       : HBitwiseBinaryOperation(context, left, right, strength), op_(op) {
   5083     DCHECK(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
   5084     // BIT_AND with a smi-range positive value will always unset the
   5085     // entire sign-extension of the smi-sign.
   5086     if (op == Token::BIT_AND &&
   5087         ((left->IsConstant() &&
   5088           left->representation().IsSmi() &&
   5089           HConstant::cast(left)->Integer32Value() >= 0) ||
   5090          (right->IsConstant() &&
   5091           right->representation().IsSmi() &&
   5092           HConstant::cast(right)->Integer32Value() >= 0))) {
   5093       SetFlag(kTruncatingToSmi);
   5094       SetFlag(kTruncatingToInt32);
   5095     // BIT_OR with a smi-range negative value will always set the entire
   5096     // sign-extension of the smi-sign.
   5097     } else if (op == Token::BIT_OR &&
   5098         ((left->IsConstant() &&
   5099           left->representation().IsSmi() &&
   5100           HConstant::cast(left)->Integer32Value() < 0) ||
   5101          (right->IsConstant() &&
   5102           right->representation().IsSmi() &&
   5103           HConstant::cast(right)->Integer32Value() < 0))) {
   5104       SetFlag(kTruncatingToSmi);
   5105       SetFlag(kTruncatingToInt32);
   5106     }
   5107   }
   5108 
   5109   Token::Value op_;
   5110 };
   5111 
   5112 
   5113 class HShl final : public HBitwiseBinaryOperation {
   5114  public:
   5115   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   5116                            HValue* left, HValue* right,
   5117                            Strength strength = Strength::WEAK);
   5118 
   5119   Range* InferRange(Zone* zone) override;
   5120 
   5121   void UpdateRepresentation(Representation new_rep,
   5122                             HInferRepresentationPhase* h_infer,
   5123                             const char* reason) override {
   5124     if (new_rep.IsSmi() &&
   5125         !(right()->IsInteger32Constant() &&
   5126           right()->GetInteger32Constant() >= 0)) {
   5127       new_rep = Representation::Integer32();
   5128     }
   5129     HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   5130   }
   5131 
   5132   DECLARE_CONCRETE_INSTRUCTION(Shl)
   5133 
   5134  protected:
   5135   bool DataEquals(HValue* other) override { return true; }
   5136 
   5137  private:
   5138   HShl(HValue* context, HValue* left, HValue* right, Strength strength)
   5139       : HBitwiseBinaryOperation(context, left, right, strength) {}
   5140 };
   5141 
   5142 
   5143 class HShr final : public HBitwiseBinaryOperation {
   5144  public:
   5145   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   5146                            HValue* left, HValue* right,
   5147                            Strength strength = Strength::WEAK);
   5148 
   5149   bool TryDecompose(DecompositionResult* decomposition) override {
   5150     if (right()->IsInteger32Constant()) {
   5151       if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
   5152         // This is intended to look for HAdd and HSub, to handle compounds
   5153         // like ((base + offset) >> scale) with one single decomposition.
   5154         left()->TryDecompose(decomposition);
   5155         return true;
   5156       }
   5157     }
   5158     return false;
   5159   }
   5160 
   5161   Range* InferRange(Zone* zone) override;
   5162 
   5163   void UpdateRepresentation(Representation new_rep,
   5164                             HInferRepresentationPhase* h_infer,
   5165                             const char* reason) override {
   5166     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
   5167     HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   5168   }
   5169 
   5170   DECLARE_CONCRETE_INSTRUCTION(Shr)
   5171 
   5172  protected:
   5173   bool DataEquals(HValue* other) override { return true; }
   5174 
   5175  private:
   5176   HShr(HValue* context, HValue* left, HValue* right, Strength strength)
   5177       : HBitwiseBinaryOperation(context, left, right, strength) {}
   5178 };
   5179 
   5180 
   5181 class HSar final : public HBitwiseBinaryOperation {
   5182  public:
   5183   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   5184                            HValue* left, HValue* right,
   5185                            Strength strength = Strength::WEAK);
   5186 
   5187   bool TryDecompose(DecompositionResult* decomposition) override {
   5188     if (right()->IsInteger32Constant()) {
   5189       if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
   5190         // This is intended to look for HAdd and HSub, to handle compounds
   5191         // like ((base + offset) >> scale) with one single decomposition.
   5192         left()->TryDecompose(decomposition);
   5193         return true;
   5194       }
   5195     }
   5196     return false;
   5197   }
   5198 
   5199   Range* InferRange(Zone* zone) override;
   5200 
   5201   void UpdateRepresentation(Representation new_rep,
   5202                             HInferRepresentationPhase* h_infer,
   5203                             const char* reason) override {
   5204     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
   5205     HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   5206   }
   5207 
   5208   DECLARE_CONCRETE_INSTRUCTION(Sar)
   5209 
   5210  protected:
   5211   bool DataEquals(HValue* other) override { return true; }
   5212 
   5213  private:
   5214   HSar(HValue* context, HValue* left, HValue* right, Strength strength)
   5215       : HBitwiseBinaryOperation(context, left, right, strength) {}
   5216 };
   5217 
   5218 
   5219 class HRor final : public HBitwiseBinaryOperation {
   5220  public:
   5221   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   5222                            HValue* left, HValue* right,
   5223                            Strength strength = Strength::WEAK) {
   5224     return new (zone) HRor(context, left, right, strength);
   5225   }
   5226 
   5227   void UpdateRepresentation(Representation new_rep,
   5228                             HInferRepresentationPhase* h_infer,
   5229                             const char* reason) override {
   5230     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
   5231     HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   5232   }
   5233 
   5234   DECLARE_CONCRETE_INSTRUCTION(Ror)
   5235 
   5236  protected:
   5237   bool DataEquals(HValue* other) override { return true; }
   5238 
   5239  private:
   5240   HRor(HValue* context, HValue* left, HValue* right, Strength strength)
   5241       : HBitwiseBinaryOperation(context, left, right, strength) {
   5242     ChangeRepresentation(Representation::Integer32());
   5243   }
   5244 };
   5245 
   5246 
   5247 class HOsrEntry final : public HTemplateInstruction<0> {
   5248  public:
   5249   DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId);
   5250 
   5251   BailoutId ast_id() const { return ast_id_; }
   5252 
   5253   Representation RequiredInputRepresentation(int index) override {
   5254     return Representation::None();
   5255   }
   5256 
   5257   DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
   5258 
   5259  private:
   5260   explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
   5261     SetChangesFlag(kOsrEntries);
   5262     SetChangesFlag(kNewSpacePromotion);
   5263   }
   5264 
   5265   BailoutId ast_id_;
   5266 };
   5267 
   5268 
   5269 class HParameter final : public HTemplateInstruction<0> {
   5270  public:
   5271   enum ParameterKind {
   5272     STACK_PARAMETER,
   5273     REGISTER_PARAMETER
   5274   };
   5275 
   5276   DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned);
   5277   DECLARE_INSTRUCTION_FACTORY_P2(HParameter, unsigned, ParameterKind);
   5278   DECLARE_INSTRUCTION_FACTORY_P3(HParameter, unsigned, ParameterKind,
   5279                                  Representation);
   5280 
   5281   unsigned index() const { return index_; }
   5282   ParameterKind kind() const { return kind_; }
   5283 
   5284   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5285 
   5286   Representation RequiredInputRepresentation(int index) override {
   5287     return Representation::None();
   5288   }
   5289 
   5290   Representation KnownOptimalRepresentation() override {
   5291     // If a parameter is an input to a phi, that phi should not
   5292     // choose any more optimistic representation than Tagged.
   5293     return Representation::Tagged();
   5294   }
   5295 
   5296   DECLARE_CONCRETE_INSTRUCTION(Parameter)
   5297 
   5298  private:
   5299   explicit HParameter(unsigned index,
   5300                       ParameterKind kind = STACK_PARAMETER)
   5301       : index_(index),
   5302         kind_(kind) {
   5303     set_representation(Representation::Tagged());
   5304   }
   5305 
   5306   explicit HParameter(unsigned index,
   5307                       ParameterKind kind,
   5308                       Representation r)
   5309       : index_(index),
   5310         kind_(kind) {
   5311     set_representation(r);
   5312   }
   5313 
   5314   unsigned index_;
   5315   ParameterKind kind_;
   5316 };
   5317 
   5318 
   5319 class HCallStub final : public HUnaryCall {
   5320  public:
   5321   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallStub, CodeStub::Major, int);
   5322   CodeStub::Major major_key() { return major_key_; }
   5323 
   5324   HValue* context() { return value(); }
   5325 
   5326   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5327 
   5328   DECLARE_CONCRETE_INSTRUCTION(CallStub)
   5329 
   5330  private:
   5331   HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
   5332       : HUnaryCall(context, argument_count),
   5333         major_key_(major_key) {
   5334   }
   5335 
   5336   CodeStub::Major major_key_;
   5337 };
   5338 
   5339 
   5340 class HUnknownOSRValue final : public HTemplateInstruction<0> {
   5341  public:
   5342   DECLARE_INSTRUCTION_FACTORY_P2(HUnknownOSRValue, HEnvironment*, int);
   5343 
   5344   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5345 
   5346   Representation RequiredInputRepresentation(int index) override {
   5347     return Representation::None();
   5348   }
   5349 
   5350   void set_incoming_value(HPhi* value) { incoming_value_ = value; }
   5351   HPhi* incoming_value() { return incoming_value_; }
   5352   HEnvironment *environment() { return environment_; }
   5353   int index() { return index_; }
   5354 
   5355   Representation KnownOptimalRepresentation() override {
   5356     if (incoming_value_ == NULL) return Representation::None();
   5357     return incoming_value_->KnownOptimalRepresentation();
   5358   }
   5359 
   5360   DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
   5361 
   5362  private:
   5363   HUnknownOSRValue(HEnvironment* environment, int index)
   5364       : environment_(environment),
   5365         index_(index),
   5366         incoming_value_(NULL) {
   5367     set_representation(Representation::Tagged());
   5368   }
   5369 
   5370   HEnvironment* environment_;
   5371   int index_;
   5372   HPhi* incoming_value_;
   5373 };
   5374 
   5375 
   5376 class HLoadGlobalGeneric final : public HTemplateInstruction<2> {
   5377  public:
   5378   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadGlobalGeneric, HValue*,
   5379                                               Handle<String>, TypeofMode);
   5380 
   5381   HValue* context() { return OperandAt(0); }
   5382   HValue* global_object() { return OperandAt(1); }
   5383   Handle<String> name() const { return name_; }
   5384   TypeofMode typeof_mode() const { return typeof_mode_; }
   5385   FeedbackVectorSlot slot() const { return slot_; }
   5386   Handle<TypeFeedbackVector> feedback_vector() const {
   5387     return feedback_vector_;
   5388   }
   5389   bool HasVectorAndSlot() const { return true; }
   5390   void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
   5391                         FeedbackVectorSlot slot) {
   5392     feedback_vector_ = vector;
   5393     slot_ = slot;
   5394   }
   5395 
   5396   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5397 
   5398   Representation RequiredInputRepresentation(int index) override {
   5399     return Representation::Tagged();
   5400   }
   5401 
   5402   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
   5403 
   5404  private:
   5405   HLoadGlobalGeneric(HValue* context, HValue* global_object,
   5406                      Handle<String> name, TypeofMode typeof_mode)
   5407       : name_(name), typeof_mode_(typeof_mode) {
   5408     SetOperandAt(0, context);
   5409     SetOperandAt(1, global_object);
   5410     set_representation(Representation::Tagged());
   5411     SetAllSideEffects();
   5412   }
   5413 
   5414   Handle<String> name_;
   5415   TypeofMode typeof_mode_;
   5416   Handle<TypeFeedbackVector> feedback_vector_;
   5417   FeedbackVectorSlot slot_;
   5418 };
   5419 
   5420 
   5421 class HAllocate final : public HTemplateInstruction<2> {
   5422  public:
   5423   static bool CompatibleInstanceTypes(InstanceType type1,
   5424                                       InstanceType type2) {
   5425     return ComputeFlags(TENURED, type1) == ComputeFlags(TENURED, type2) &&
   5426         ComputeFlags(NOT_TENURED, type1) == ComputeFlags(NOT_TENURED, type2);
   5427   }
   5428 
   5429   static HAllocate* New(
   5430       Isolate* isolate, Zone* zone, HValue* context, HValue* size, HType type,
   5431       PretenureFlag pretenure_flag, InstanceType instance_type,
   5432       Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null()) {
   5433     return new(zone) HAllocate(context, size, type, pretenure_flag,
   5434         instance_type, allocation_site);
   5435   }
   5436 
   5437   // Maximum instance size for which allocations will be inlined.
   5438   static const int kMaxInlineSize = 64 * kPointerSize;
   5439 
   5440   HValue* context() const { return OperandAt(0); }
   5441   HValue* size() const { return OperandAt(1); }
   5442 
   5443   bool has_size_upper_bound() { return size_upper_bound_ != NULL; }
   5444   HConstant* size_upper_bound() { return size_upper_bound_; }
   5445   void set_size_upper_bound(HConstant* value) {
   5446     DCHECK(size_upper_bound_ == NULL);
   5447     size_upper_bound_ = value;
   5448   }
   5449 
   5450   Representation RequiredInputRepresentation(int index) override {
   5451     if (index == 0) {
   5452       return Representation::Tagged();
   5453     } else {
   5454       return Representation::Integer32();
   5455     }
   5456   }
   5457 
   5458   Handle<Map> GetMonomorphicJSObjectMap() override {
   5459     return known_initial_map_;
   5460   }
   5461 
   5462   void set_known_initial_map(Handle<Map> known_initial_map) {
   5463     known_initial_map_ = known_initial_map;
   5464   }
   5465 
   5466   bool IsNewSpaceAllocation() const {
   5467     return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
   5468   }
   5469 
   5470   bool IsOldSpaceAllocation() const {
   5471     return (flags_ & ALLOCATE_IN_OLD_SPACE) != 0;
   5472   }
   5473 
   5474   bool MustAllocateDoubleAligned() const {
   5475     return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
   5476   }
   5477 
   5478   bool MustPrefillWithFiller() const {
   5479     return (flags_ & PREFILL_WITH_FILLER) != 0;
   5480   }
   5481 
   5482   void MakePrefillWithFiller() {
   5483     flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
   5484   }
   5485 
   5486   bool MustClearNextMapWord() const {
   5487     return (flags_ & CLEAR_NEXT_MAP_WORD) != 0;
   5488   }
   5489 
   5490   void MakeDoubleAligned() {
   5491     flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
   5492   }
   5493 
   5494   bool HandleSideEffectDominator(GVNFlag side_effect,
   5495                                  HValue* dominator) override;
   5496 
   5497   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5498 
   5499   DECLARE_CONCRETE_INSTRUCTION(Allocate)
   5500 
   5501  private:
   5502   enum Flags {
   5503     ALLOCATE_IN_NEW_SPACE = 1 << 0,
   5504     ALLOCATE_IN_OLD_SPACE = 1 << 2,
   5505     ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
   5506     PREFILL_WITH_FILLER = 1 << 4,
   5507     CLEAR_NEXT_MAP_WORD = 1 << 5
   5508   };
   5509 
   5510   HAllocate(HValue* context,
   5511             HValue* size,
   5512             HType type,
   5513             PretenureFlag pretenure_flag,
   5514             InstanceType instance_type,
   5515             Handle<AllocationSite> allocation_site =
   5516                 Handle<AllocationSite>::null())
   5517       : HTemplateInstruction<2>(type),
   5518         flags_(ComputeFlags(pretenure_flag, instance_type)),
   5519         dominating_allocate_(NULL),
   5520         filler_free_space_size_(NULL),
   5521         size_upper_bound_(NULL) {
   5522     SetOperandAt(0, context);
   5523     UpdateSize(size);
   5524     set_representation(Representation::Tagged());
   5525     SetFlag(kTrackSideEffectDominators);
   5526     SetChangesFlag(kNewSpacePromotion);
   5527     SetDependsOnFlag(kNewSpacePromotion);
   5528 
   5529     if (FLAG_trace_pretenuring) {
   5530       PrintF("HAllocate with AllocationSite %p %s\n",
   5531              allocation_site.is_null()
   5532                  ? static_cast<void*>(NULL)
   5533                  : static_cast<void*>(*allocation_site),
   5534              pretenure_flag == TENURED ? "tenured" : "not tenured");
   5535     }
   5536   }
   5537 
   5538   static Flags ComputeFlags(PretenureFlag pretenure_flag,
   5539                             InstanceType instance_type) {
   5540     Flags flags = pretenure_flag == TENURED ? ALLOCATE_IN_OLD_SPACE
   5541                                             : ALLOCATE_IN_NEW_SPACE;
   5542     if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
   5543       flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED);
   5544     }
   5545     // We have to fill the allocated object with one word fillers if we do
   5546     // not use allocation folding since some allocations may depend on each
   5547     // other, i.e., have a pointer to each other. A GC in between these
   5548     // allocations may leave such objects behind in a not completely initialized
   5549     // state.
   5550     if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
   5551       flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER);
   5552     }
   5553     if (pretenure_flag == NOT_TENURED &&
   5554         AllocationSite::CanTrack(instance_type)) {
   5555       flags = static_cast<Flags>(flags | CLEAR_NEXT_MAP_WORD);
   5556     }
   5557     return flags;
   5558   }
   5559 
   5560   void UpdateClearNextMapWord(bool clear_next_map_word) {
   5561     flags_ = static_cast<Flags>(clear_next_map_word
   5562                                 ? flags_ | CLEAR_NEXT_MAP_WORD
   5563                                 : flags_ & ~CLEAR_NEXT_MAP_WORD);
   5564   }
   5565 
   5566   void UpdateSize(HValue* size) {
   5567     SetOperandAt(1, size);
   5568     if (size->IsInteger32Constant()) {
   5569       size_upper_bound_ = HConstant::cast(size);
   5570     } else {
   5571       size_upper_bound_ = NULL;
   5572     }
   5573   }
   5574 
   5575   HAllocate* GetFoldableDominator(HAllocate* dominator);
   5576 
   5577   void UpdateFreeSpaceFiller(int32_t filler_size);
   5578 
   5579   void CreateFreeSpaceFiller(int32_t filler_size);
   5580 
   5581   bool IsFoldable(HAllocate* allocate) {
   5582     return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) ||
   5583            (IsOldSpaceAllocation() && allocate->IsOldSpaceAllocation());
   5584   }
   5585 
   5586   void ClearNextMapWord(int offset);
   5587 
   5588   Flags flags_;
   5589   Handle<Map> known_initial_map_;
   5590   HAllocate* dominating_allocate_;
   5591   HStoreNamedField* filler_free_space_size_;
   5592   HConstant* size_upper_bound_;
   5593 };
   5594 
   5595 
   5596 class HStoreCodeEntry final : public HTemplateInstruction<2> {
   5597  public:
   5598   static HStoreCodeEntry* New(Isolate* isolate, Zone* zone, HValue* context,
   5599                               HValue* function, HValue* code) {
   5600     return new(zone) HStoreCodeEntry(function, code);
   5601   }
   5602 
   5603   Representation RequiredInputRepresentation(int index) override {
   5604     return Representation::Tagged();
   5605   }
   5606 
   5607   HValue* function() { return OperandAt(0); }
   5608   HValue* code_object() { return OperandAt(1); }
   5609 
   5610   DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry)
   5611 
   5612  private:
   5613   HStoreCodeEntry(HValue* function, HValue* code) {
   5614     SetOperandAt(0, function);
   5615     SetOperandAt(1, code);
   5616   }
   5617 };
   5618 
   5619 
   5620 class HInnerAllocatedObject final : public HTemplateInstruction<2> {
   5621  public:
   5622   static HInnerAllocatedObject* New(Isolate* isolate, Zone* zone,
   5623                                     HValue* context, HValue* value,
   5624                                     HValue* offset, HType type) {
   5625     return new(zone) HInnerAllocatedObject(value, offset, type);
   5626   }
   5627 
   5628   HValue* base_object() const { return OperandAt(0); }
   5629   HValue* offset() const { return OperandAt(1); }
   5630 
   5631   Representation RequiredInputRepresentation(int index) override {
   5632     return index == 0 ? Representation::Tagged() : Representation::Integer32();
   5633   }
   5634 
   5635   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5636 
   5637   DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
   5638 
   5639  private:
   5640   HInnerAllocatedObject(HValue* value,
   5641                         HValue* offset,
   5642                         HType type) : HTemplateInstruction<2>(type) {
   5643     DCHECK(value->IsAllocate());
   5644     DCHECK(type.IsHeapObject());
   5645     SetOperandAt(0, value);
   5646     SetOperandAt(1, offset);
   5647     set_representation(Representation::Tagged());
   5648   }
   5649 };
   5650 
   5651 
   5652 inline bool StoringValueNeedsWriteBarrier(HValue* value) {
   5653   return !value->type().IsSmi()
   5654       && !value->type().IsNull()
   5655       && !value->type().IsBoolean()
   5656       && !value->type().IsUndefined()
   5657       && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
   5658 }
   5659 
   5660 
   5661 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
   5662                                             HValue* value,
   5663                                             HValue* dominator) {
   5664   while (object->IsInnerAllocatedObject()) {
   5665     object = HInnerAllocatedObject::cast(object)->base_object();
   5666   }
   5667   if (object->IsConstant() &&
   5668       HConstant::cast(object)->HasExternalReferenceValue()) {
   5669     // Stores to external references require no write barriers
   5670     return false;
   5671   }
   5672   // We definitely need a write barrier unless the object is the allocation
   5673   // dominator.
   5674   if (object == dominator && object->IsAllocate()) {
   5675     // Stores to new space allocations require no write barriers.
   5676     if (HAllocate::cast(object)->IsNewSpaceAllocation()) {
   5677       return false;
   5678     }
   5679     // Stores to old space allocations require no write barriers if the value is
   5680     // a constant provably not in new space.
   5681     if (value->IsConstant() && HConstant::cast(value)->NotInNewSpace()) {
   5682       return false;
   5683     }
   5684   }
   5685   return true;
   5686 }
   5687 
   5688 
   5689 inline PointersToHereCheck PointersToHereCheckForObject(HValue* object,
   5690                                                         HValue* dominator) {
   5691   while (object->IsInnerAllocatedObject()) {
   5692     object = HInnerAllocatedObject::cast(object)->base_object();
   5693   }
   5694   if (object == dominator &&
   5695       object->IsAllocate() &&
   5696       HAllocate::cast(object)->IsNewSpaceAllocation()) {
   5697     return kPointersToHereAreAlwaysInteresting;
   5698   }
   5699   return kPointersToHereMaybeInteresting;
   5700 }
   5701 
   5702 
   5703 class HLoadContextSlot final : public HUnaryOperation {
   5704  public:
   5705   enum Mode {
   5706     // Perform a normal load of the context slot without checking its value.
   5707     kNoCheck,
   5708     // Load and check the value of the context slot. Deoptimize if it's the
   5709     // hole value. This is used for checking for loading of uninitialized
   5710     // harmony bindings where we deoptimize into full-codegen generated code
   5711     // which will subsequently throw a reference error.
   5712     kCheckDeoptimize,
   5713     // Load and check the value of the context slot. Return undefined if it's
   5714     // the hole value. This is used for non-harmony const assignments
   5715     kCheckReturnUndefined
   5716   };
   5717 
   5718   HLoadContextSlot(HValue* context, int slot_index, Mode mode)
   5719       : HUnaryOperation(context), slot_index_(slot_index), mode_(mode) {
   5720     set_representation(Representation::Tagged());
   5721     SetFlag(kUseGVN);
   5722     SetDependsOnFlag(kContextSlots);
   5723   }
   5724 
   5725   int slot_index() const { return slot_index_; }
   5726   Mode mode() const { return mode_; }
   5727 
   5728   bool DeoptimizesOnHole() {
   5729     return mode_ == kCheckDeoptimize;
   5730   }
   5731 
   5732   bool RequiresHoleCheck() const {
   5733     return mode_ != kNoCheck;
   5734   }
   5735 
   5736   Representation RequiredInputRepresentation(int index) override {
   5737     return Representation::Tagged();
   5738   }
   5739 
   5740   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5741 
   5742   DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
   5743 
   5744  protected:
   5745   bool DataEquals(HValue* other) override {
   5746     HLoadContextSlot* b = HLoadContextSlot::cast(other);
   5747     return (slot_index() == b->slot_index());
   5748   }
   5749 
   5750  private:
   5751   bool IsDeletable() const override { return !RequiresHoleCheck(); }
   5752 
   5753   int slot_index_;
   5754   Mode mode_;
   5755 };
   5756 
   5757 
   5758 class HStoreContextSlot final : public HTemplateInstruction<2> {
   5759  public:
   5760   enum Mode {
   5761     // Perform a normal store to the context slot without checking its previous
   5762     // value.
   5763     kNoCheck,
   5764     // Check the previous value of the context slot and deoptimize if it's the
   5765     // hole value. This is used for checking for assignments to uninitialized
   5766     // harmony bindings where we deoptimize into full-codegen generated code
   5767     // which will subsequently throw a reference error.
   5768     kCheckDeoptimize,
   5769     // Check the previous value and ignore assignment if it isn't a hole value
   5770     kCheckIgnoreAssignment
   5771   };
   5772 
   5773   DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
   5774                                  Mode, HValue*);
   5775 
   5776   HValue* context() const { return OperandAt(0); }
   5777   HValue* value() const { return OperandAt(1); }
   5778   int slot_index() const { return slot_index_; }
   5779   Mode mode() const { return mode_; }
   5780 
   5781   bool NeedsWriteBarrier() {
   5782     return StoringValueNeedsWriteBarrier(value());
   5783   }
   5784 
   5785   bool DeoptimizesOnHole() {
   5786     return mode_ == kCheckDeoptimize;
   5787   }
   5788 
   5789   bool RequiresHoleCheck() {
   5790     return mode_ != kNoCheck;
   5791   }
   5792 
   5793   Representation RequiredInputRepresentation(int index) override {
   5794     return Representation::Tagged();
   5795   }
   5796 
   5797   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5798 
   5799   DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
   5800 
   5801  private:
   5802   HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
   5803       : slot_index_(slot_index), mode_(mode) {
   5804     SetOperandAt(0, context);
   5805     SetOperandAt(1, value);
   5806     SetChangesFlag(kContextSlots);
   5807   }
   5808 
   5809   int slot_index_;
   5810   Mode mode_;
   5811 };
   5812 
   5813 
   5814 // Represents an access to a portion of an object, such as the map pointer,
   5815 // array elements pointer, etc, but not accesses to array elements themselves.
   5816 class HObjectAccess final {
   5817  public:
   5818   inline bool IsInobject() const {
   5819     return portion() != kBackingStore && portion() != kExternalMemory;
   5820   }
   5821 
   5822   inline bool IsExternalMemory() const {
   5823     return portion() == kExternalMemory;
   5824   }
   5825 
   5826   inline bool IsStringLength() const {
   5827     return portion() == kStringLengths;
   5828   }
   5829 
   5830   inline bool IsMap() const {
   5831     return portion() == kMaps;
   5832   }
   5833 
   5834   inline int offset() const {
   5835     return OffsetField::decode(value_);
   5836   }
   5837 
   5838   inline Representation representation() const {
   5839     return Representation::FromKind(RepresentationField::decode(value_));
   5840   }
   5841 
   5842   inline Handle<Name> name() const { return name_; }
   5843 
   5844   inline bool immutable() const {
   5845     return ImmutableField::decode(value_);
   5846   }
   5847 
   5848   // Returns true if access is being made to an in-object property that
   5849   // was already added to the object.
   5850   inline bool existing_inobject_property() const {
   5851     return ExistingInobjectPropertyField::decode(value_);
   5852   }
   5853 
   5854   inline HObjectAccess WithRepresentation(Representation representation) {
   5855     return HObjectAccess(portion(), offset(), representation, name(),
   5856                          immutable(), existing_inobject_property());
   5857   }
   5858 
   5859   static HObjectAccess ForHeapNumberValue() {
   5860     return HObjectAccess(
   5861         kDouble, HeapNumber::kValueOffset, Representation::Double());
   5862   }
   5863 
   5864   static HObjectAccess ForHeapNumberValueLowestBits() {
   5865     return HObjectAccess(kDouble,
   5866                          HeapNumber::kValueOffset,
   5867                          Representation::Integer32());
   5868   }
   5869 
   5870   static HObjectAccess ForHeapNumberValueHighestBits() {
   5871     return HObjectAccess(kDouble,
   5872                          HeapNumber::kValueOffset + kIntSize,
   5873                          Representation::Integer32());
   5874   }
   5875 
   5876   static HObjectAccess ForOddballToNumber(
   5877       Representation representation = Representation::Tagged()) {
   5878     return HObjectAccess(kInobject, Oddball::kToNumberOffset, representation);
   5879   }
   5880 
   5881   static HObjectAccess ForOddballTypeOf() {
   5882     return HObjectAccess(kInobject, Oddball::kTypeOfOffset,
   5883                          Representation::HeapObject());
   5884   }
   5885 
   5886   static HObjectAccess ForElementsPointer() {
   5887     return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
   5888   }
   5889 
   5890   static HObjectAccess ForLiteralsPointer() {
   5891     return HObjectAccess(kInobject, JSFunction::kLiteralsOffset);
   5892   }
   5893 
   5894   static HObjectAccess ForNextFunctionLinkPointer() {
   5895     return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
   5896   }
   5897 
   5898   static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
   5899     return HObjectAccess(
   5900         kArrayLengths,
   5901         JSArray::kLengthOffset,
   5902         IsFastElementsKind(elements_kind)
   5903             ? Representation::Smi() : Representation::Tagged());
   5904   }
   5905 
   5906   static HObjectAccess ForAllocationSiteOffset(int offset);
   5907 
   5908   static HObjectAccess ForAllocationSiteList() {
   5909     return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
   5910                          Handle<Name>::null(), false, false);
   5911   }
   5912 
   5913   static HObjectAccess ForFixedArrayLength() {
   5914     return HObjectAccess(
   5915         kArrayLengths,
   5916         FixedArray::kLengthOffset,
   5917         Representation::Smi());
   5918   }
   5919 
   5920   static HObjectAccess ForFixedTypedArrayBaseBasePointer() {
   5921     return HObjectAccess(kInobject, FixedTypedArrayBase::kBasePointerOffset,
   5922                          Representation::Tagged());
   5923   }
   5924 
   5925   static HObjectAccess ForFixedTypedArrayBaseExternalPointer() {
   5926     return HObjectAccess::ForObservableJSObjectOffset(
   5927         FixedTypedArrayBase::kExternalPointerOffset,
   5928         Representation::External());
   5929   }
   5930 
   5931   static HObjectAccess ForStringHashField() {
   5932     return HObjectAccess(kInobject,
   5933                          String::kHashFieldOffset,
   5934                          Representation::Integer32());
   5935   }
   5936 
   5937   static HObjectAccess ForStringLength() {
   5938     STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
   5939     return HObjectAccess(
   5940         kStringLengths,
   5941         String::kLengthOffset,
   5942         Representation::Smi());
   5943   }
   5944 
   5945   static HObjectAccess ForConsStringFirst() {
   5946     return HObjectAccess(kInobject, ConsString::kFirstOffset);
   5947   }
   5948 
   5949   static HObjectAccess ForConsStringSecond() {
   5950     return HObjectAccess(kInobject, ConsString::kSecondOffset);
   5951   }
   5952 
   5953   static HObjectAccess ForPropertiesPointer() {
   5954     return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
   5955   }
   5956 
   5957   static HObjectAccess ForPrototypeOrInitialMap() {
   5958     return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
   5959   }
   5960 
   5961   static HObjectAccess ForSharedFunctionInfoPointer() {
   5962     return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
   5963   }
   5964 
   5965   static HObjectAccess ForCodeEntryPointer() {
   5966     return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
   5967   }
   5968 
   5969   static HObjectAccess ForCodeOffset() {
   5970     return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
   5971   }
   5972 
   5973   static HObjectAccess ForOptimizedCodeMap() {
   5974     return HObjectAccess(kInobject,
   5975                          SharedFunctionInfo::kOptimizedCodeMapOffset);
   5976   }
   5977 
   5978   static HObjectAccess ForOptimizedCodeMapSharedCode() {
   5979     return HObjectAccess(kInobject, FixedArray::OffsetOfElementAt(
   5980                                         SharedFunctionInfo::kSharedCodeIndex));
   5981   }
   5982 
   5983   static HObjectAccess ForFunctionContextPointer() {
   5984     return HObjectAccess(kInobject, JSFunction::kContextOffset);
   5985   }
   5986 
   5987   static HObjectAccess ForMap() {
   5988     return HObjectAccess(kMaps, JSObject::kMapOffset);
   5989   }
   5990 
   5991   static HObjectAccess ForPrototype() {
   5992     return HObjectAccess(kMaps, Map::kPrototypeOffset);
   5993   }
   5994 
   5995   static HObjectAccess ForMapAsInteger32() {
   5996     return HObjectAccess(kMaps, JSObject::kMapOffset,
   5997                          Representation::Integer32());
   5998   }
   5999 
   6000   static HObjectAccess ForMapInObjectPropertiesOrConstructorFunctionIndex() {
   6001     return HObjectAccess(
   6002         kInobject, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset,
   6003         Representation::UInteger8());
   6004   }
   6005 
   6006   static HObjectAccess ForMapInstanceType() {
   6007     return HObjectAccess(kInobject,
   6008                          Map::kInstanceTypeOffset,
   6009                          Representation::UInteger8());
   6010   }
   6011 
   6012   static HObjectAccess ForMapInstanceSize() {
   6013     return HObjectAccess(kInobject,
   6014                          Map::kInstanceSizeOffset,
   6015                          Representation::UInteger8());
   6016   }
   6017 
   6018   static HObjectAccess ForMapBitField() {
   6019     return HObjectAccess(kInobject,
   6020                          Map::kBitFieldOffset,
   6021                          Representation::UInteger8());
   6022   }
   6023 
   6024   static HObjectAccess ForMapBitField2() {
   6025     return HObjectAccess(kInobject,
   6026                          Map::kBitField2Offset,
   6027                          Representation::UInteger8());
   6028   }
   6029 
   6030   static HObjectAccess ForNameHashField() {
   6031     return HObjectAccess(kInobject,
   6032                          Name::kHashFieldOffset,
   6033                          Representation::Integer32());
   6034   }
   6035 
   6036   static HObjectAccess ForMapInstanceTypeAndBitField() {
   6037     STATIC_ASSERT((Map::kInstanceTypeAndBitFieldOffset & 1) == 0);
   6038     // Ensure the two fields share one 16-bit word, endian-independent.
   6039     STATIC_ASSERT((Map::kBitFieldOffset & ~1) ==
   6040                   (Map::kInstanceTypeOffset & ~1));
   6041     return HObjectAccess(kInobject,
   6042                          Map::kInstanceTypeAndBitFieldOffset,
   6043                          Representation::UInteger16());
   6044   }
   6045 
   6046   static HObjectAccess ForPropertyCellValue() {
   6047     return HObjectAccess(kInobject, PropertyCell::kValueOffset);
   6048   }
   6049 
   6050   static HObjectAccess ForPropertyCellDetails() {
   6051     return HObjectAccess(kInobject, PropertyCell::kDetailsOffset,
   6052                          Representation::Smi());
   6053   }
   6054 
   6055   static HObjectAccess ForCellValue() {
   6056     return HObjectAccess(kInobject, Cell::kValueOffset);
   6057   }
   6058 
   6059   static HObjectAccess ForWeakCellValue() {
   6060     return HObjectAccess(kInobject, WeakCell::kValueOffset);
   6061   }
   6062 
   6063   static HObjectAccess ForWeakCellNext() {
   6064     return HObjectAccess(kInobject, WeakCell::kNextOffset);
   6065   }
   6066 
   6067   static HObjectAccess ForAllocationMementoSite() {
   6068     return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
   6069   }
   6070 
   6071   static HObjectAccess ForCounter() {
   6072     return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
   6073                          Handle<Name>::null(), false, false);
   6074   }
   6075 
   6076   static HObjectAccess ForExternalUInteger8() {
   6077     return HObjectAccess(kExternalMemory, 0, Representation::UInteger8(),
   6078                          Handle<Name>::null(), false, false);
   6079   }
   6080 
   6081   // Create an access to an offset in a fixed array header.
   6082   static HObjectAccess ForFixedArrayHeader(int offset);
   6083 
   6084   // Create an access to an in-object property in a JSObject.
   6085   // This kind of access must be used when the object |map| is known and
   6086   // in-object properties are being accessed. Accesses of the in-object
   6087   // properties can have different semantics depending on whether corresponding
   6088   // property was added to the map or not.
   6089   static HObjectAccess ForMapAndOffset(Handle<Map> map, int offset,
   6090       Representation representation = Representation::Tagged());
   6091 
   6092   // Create an access to an in-object property in a JSObject.
   6093   // This kind of access can be used for accessing object header fields or
   6094   // in-object properties if the map of the object is not known.
   6095   static HObjectAccess ForObservableJSObjectOffset(int offset,
   6096       Representation representation = Representation::Tagged()) {
   6097     return ForMapAndOffset(Handle<Map>::null(), offset, representation);
   6098   }
   6099 
   6100   // Create an access to an in-object property in a JSArray.
   6101   static HObjectAccess ForJSArrayOffset(int offset);
   6102 
   6103   static HObjectAccess ForContextSlot(int index);
   6104 
   6105   static HObjectAccess ForScriptContext(int index);
   6106 
   6107   // Create an access to the backing store of an object.
   6108   static HObjectAccess ForBackingStoreOffset(int offset,
   6109       Representation representation = Representation::Tagged());
   6110 
   6111   // Create an access to a resolved field (in-object or backing store).
   6112   static HObjectAccess ForField(Handle<Map> map, int index,
   6113                                 Representation representation,
   6114                                 Handle<Name> name);
   6115 
   6116   static HObjectAccess ForJSTypedArrayLength() {
   6117     return HObjectAccess::ForObservableJSObjectOffset(
   6118         JSTypedArray::kLengthOffset);
   6119   }
   6120 
   6121   static HObjectAccess ForJSArrayBufferBackingStore() {
   6122     return HObjectAccess::ForObservableJSObjectOffset(
   6123         JSArrayBuffer::kBackingStoreOffset, Representation::External());
   6124   }
   6125 
   6126   static HObjectAccess ForJSArrayBufferByteLength() {
   6127     return HObjectAccess::ForObservableJSObjectOffset(
   6128         JSArrayBuffer::kByteLengthOffset, Representation::Tagged());
   6129   }
   6130 
   6131   static HObjectAccess ForJSArrayBufferBitField() {
   6132     return HObjectAccess::ForObservableJSObjectOffset(
   6133         JSArrayBuffer::kBitFieldOffset, Representation::Integer32());
   6134   }
   6135 
   6136   static HObjectAccess ForJSArrayBufferBitFieldSlot() {
   6137     return HObjectAccess::ForObservableJSObjectOffset(
   6138         JSArrayBuffer::kBitFieldSlot, Representation::Smi());
   6139   }
   6140 
   6141   static HObjectAccess ForJSArrayBufferViewBuffer() {
   6142     return HObjectAccess::ForObservableJSObjectOffset(
   6143         JSArrayBufferView::kBufferOffset);
   6144   }
   6145 
   6146   static HObjectAccess ForJSArrayBufferViewByteOffset() {
   6147     return HObjectAccess::ForObservableJSObjectOffset(
   6148         JSArrayBufferView::kByteOffsetOffset);
   6149   }
   6150 
   6151   static HObjectAccess ForJSArrayBufferViewByteLength() {
   6152     return HObjectAccess::ForObservableJSObjectOffset(
   6153         JSArrayBufferView::kByteLengthOffset);
   6154   }
   6155 
   6156   static HObjectAccess ForJSGlobalObjectNativeContext() {
   6157     return HObjectAccess(kInobject, JSGlobalObject::kNativeContextOffset);
   6158   }
   6159 
   6160   static HObjectAccess ForJSRegExpFlags() {
   6161     return HObjectAccess(kInobject, JSRegExp::kFlagsOffset);
   6162   }
   6163 
   6164   static HObjectAccess ForJSRegExpSource() {
   6165     return HObjectAccess(kInobject, JSRegExp::kSourceOffset);
   6166   }
   6167 
   6168   static HObjectAccess ForJSCollectionTable() {
   6169     return HObjectAccess::ForObservableJSObjectOffset(
   6170         JSCollection::kTableOffset);
   6171   }
   6172 
   6173   template <typename CollectionType>
   6174   static HObjectAccess ForOrderedHashTableNumberOfBuckets() {
   6175     return HObjectAccess(kInobject, CollectionType::kNumberOfBucketsOffset,
   6176                          Representation::Smi());
   6177   }
   6178 
   6179   template <typename CollectionType>
   6180   static HObjectAccess ForOrderedHashTableNumberOfElements() {
   6181     return HObjectAccess(kInobject, CollectionType::kNumberOfElementsOffset,
   6182                          Representation::Smi());
   6183   }
   6184 
   6185   template <typename CollectionType>
   6186   static HObjectAccess ForOrderedHashTableNumberOfDeletedElements() {
   6187     return HObjectAccess(kInobject,
   6188                          CollectionType::kNumberOfDeletedElementsOffset,
   6189                          Representation::Smi());
   6190   }
   6191 
   6192   template <typename CollectionType>
   6193   static HObjectAccess ForOrderedHashTableNextTable() {
   6194     return HObjectAccess(kInobject, CollectionType::kNextTableOffset);
   6195   }
   6196 
   6197   template <typename CollectionType>
   6198   static HObjectAccess ForOrderedHashTableBucket(int bucket) {
   6199     return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
   6200                                         (bucket * kPointerSize),
   6201                          Representation::Smi());
   6202   }
   6203 
   6204   // Access into the data table of an OrderedHashTable with a
   6205   // known-at-compile-time bucket count.
   6206   template <typename CollectionType, int kBucketCount>
   6207   static HObjectAccess ForOrderedHashTableDataTableIndex(int index) {
   6208     return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
   6209                                         (kBucketCount * kPointerSize) +
   6210                                         (index * kPointerSize));
   6211   }
   6212 
   6213   inline bool Equals(HObjectAccess that) const {
   6214     return value_ == that.value_;  // portion and offset must match
   6215   }
   6216 
   6217  protected:
   6218   void SetGVNFlags(HValue *instr, PropertyAccessType access_type);
   6219 
   6220  private:
   6221   // internal use only; different parts of an object or array
   6222   enum Portion {
   6223     kMaps,             // map of an object
   6224     kArrayLengths,     // the length of an array
   6225     kStringLengths,    // the length of a string
   6226     kElementsPointer,  // elements pointer
   6227     kBackingStore,     // some field in the backing store
   6228     kDouble,           // some double field
   6229     kInobject,         // some other in-object field
   6230     kExternalMemory    // some field in external memory
   6231   };
   6232 
   6233   HObjectAccess() : value_(0) {}
   6234 
   6235   HObjectAccess(Portion portion, int offset,
   6236                 Representation representation = Representation::Tagged(),
   6237                 Handle<Name> name = Handle<Name>::null(),
   6238                 bool immutable = false, bool existing_inobject_property = true)
   6239       : value_(PortionField::encode(portion) |
   6240                RepresentationField::encode(representation.kind()) |
   6241                ImmutableField::encode(immutable ? 1 : 0) |
   6242                ExistingInobjectPropertyField::encode(
   6243                    existing_inobject_property ? 1 : 0) |
   6244                OffsetField::encode(offset)),
   6245         name_(name) {
   6246     // assert that the fields decode correctly
   6247     DCHECK(this->offset() == offset);
   6248     DCHECK(this->portion() == portion);
   6249     DCHECK(this->immutable() == immutable);
   6250     DCHECK(this->existing_inobject_property() == existing_inobject_property);
   6251     DCHECK(RepresentationField::decode(value_) == representation.kind());
   6252     DCHECK(!this->existing_inobject_property() || IsInobject());
   6253   }
   6254 
   6255   class PortionField : public BitField<Portion, 0, 3> {};
   6256   class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
   6257   class ImmutableField : public BitField<bool, 7, 1> {};
   6258   class ExistingInobjectPropertyField : public BitField<bool, 8, 1> {};
   6259   class OffsetField : public BitField<int, 9, 23> {};
   6260 
   6261   uint32_t value_;  // encodes portion, representation, immutable, and offset
   6262   Handle<Name> name_;
   6263 
   6264   friend class HLoadNamedField;
   6265   friend class HStoreNamedField;
   6266   friend class SideEffectsTracker;
   6267   friend std::ostream& operator<<(std::ostream& os,
   6268                                   const HObjectAccess& access);
   6269 
   6270   inline Portion portion() const {
   6271     return PortionField::decode(value_);
   6272   }
   6273 };
   6274 
   6275 
   6276 std::ostream& operator<<(std::ostream& os, const HObjectAccess& access);
   6277 
   6278 
   6279 class HLoadNamedField final : public HTemplateInstruction<2> {
   6280  public:
   6281   DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*,
   6282                                  HValue*, HObjectAccess);
   6283   DECLARE_INSTRUCTION_FACTORY_P5(HLoadNamedField, HValue*, HValue*,
   6284                                  HObjectAccess, const UniqueSet<Map>*, HType);
   6285 
   6286   HValue* object() const { return OperandAt(0); }
   6287   HValue* dependency() const {
   6288     DCHECK(HasDependency());
   6289     return OperandAt(1);
   6290   }
   6291   bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
   6292   HObjectAccess access() const { return access_; }
   6293   Representation field_representation() const {
   6294       return access_.representation();
   6295   }
   6296 
   6297   const UniqueSet<Map>* maps() const { return maps_; }
   6298 
   6299   bool HasEscapingOperandAt(int index) override { return false; }
   6300   bool HasOutOfBoundsAccess(int size) override {
   6301     return !access().IsInobject() || access().offset() >= size;
   6302   }
   6303   Representation RequiredInputRepresentation(int index) override {
   6304     if (index == 0) {
   6305       // object must be external in case of external memory access
   6306       return access().IsExternalMemory() ? Representation::External()
   6307                                          : Representation::Tagged();
   6308     }
   6309     DCHECK(index == 1);
   6310     return Representation::None();
   6311   }
   6312   Range* InferRange(Zone* zone) override;
   6313   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6314 
   6315   bool CanBeReplacedWith(HValue* other) const {
   6316     if (!CheckFlag(HValue::kCantBeReplaced)) return false;
   6317     if (!type().Equals(other->type())) return false;
   6318     if (!representation().Equals(other->representation())) return false;
   6319     if (!other->IsLoadNamedField()) return true;
   6320     HLoadNamedField* that = HLoadNamedField::cast(other);
   6321     if (this->maps_ == that->maps_) return true;
   6322     if (this->maps_ == NULL || that->maps_ == NULL) return false;
   6323     return this->maps_->IsSubset(that->maps_);
   6324   }
   6325 
   6326   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
   6327 
   6328  protected:
   6329   bool DataEquals(HValue* other) override {
   6330     HLoadNamedField* that = HLoadNamedField::cast(other);
   6331     if (!this->access_.Equals(that->access_)) return false;
   6332     if (this->maps_ == that->maps_) return true;
   6333     return (this->maps_ != NULL &&
   6334             that->maps_ != NULL &&
   6335             this->maps_->Equals(that->maps_));
   6336   }
   6337 
   6338  private:
   6339   HLoadNamedField(HValue* object,
   6340                   HValue* dependency,
   6341                   HObjectAccess access)
   6342       : access_(access), maps_(NULL) {
   6343     DCHECK_NOT_NULL(object);
   6344     SetOperandAt(0, object);
   6345     SetOperandAt(1, dependency ? dependency : object);
   6346 
   6347     Representation representation = access.representation();
   6348     if (representation.IsInteger8() ||
   6349         representation.IsUInteger8() ||
   6350         representation.IsInteger16() ||
   6351         representation.IsUInteger16()) {
   6352       set_representation(Representation::Integer32());
   6353     } else if (representation.IsSmi()) {
   6354       set_type(HType::Smi());
   6355       if (SmiValuesAre32Bits()) {
   6356         set_representation(Representation::Integer32());
   6357       } else {
   6358         set_representation(representation);
   6359       }
   6360     } else if (representation.IsDouble() ||
   6361                representation.IsExternal() ||
   6362                representation.IsInteger32()) {
   6363       set_representation(representation);
   6364     } else if (representation.IsHeapObject()) {
   6365       set_type(HType::HeapObject());
   6366       set_representation(Representation::Tagged());
   6367     } else {
   6368       set_representation(Representation::Tagged());
   6369     }
   6370     access.SetGVNFlags(this, LOAD);
   6371   }
   6372 
   6373   HLoadNamedField(HValue* object,
   6374                   HValue* dependency,
   6375                   HObjectAccess access,
   6376                   const UniqueSet<Map>* maps,
   6377                   HType type)
   6378       : HTemplateInstruction<2>(type), access_(access), maps_(maps) {
   6379     DCHECK_NOT_NULL(maps);
   6380     DCHECK_NE(0, maps->size());
   6381 
   6382     DCHECK_NOT_NULL(object);
   6383     SetOperandAt(0, object);
   6384     SetOperandAt(1, dependency ? dependency : object);
   6385 
   6386     DCHECK(access.representation().IsHeapObject());
   6387     DCHECK(type.IsHeapObject());
   6388     set_representation(Representation::Tagged());
   6389 
   6390     access.SetGVNFlags(this, LOAD);
   6391   }
   6392 
   6393   bool IsDeletable() const override { return true; }
   6394 
   6395   HObjectAccess access_;
   6396   const UniqueSet<Map>* maps_;
   6397 };
   6398 
   6399 
   6400 class HLoadNamedGeneric final : public HTemplateInstruction<2> {
   6401  public:
   6402   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadNamedGeneric, HValue*,
   6403                                               Handle<Name>, LanguageMode,
   6404                                               InlineCacheState);
   6405 
   6406   HValue* context() const { return OperandAt(0); }
   6407   HValue* object() const { return OperandAt(1); }
   6408   Handle<Name> name() const { return name_; }
   6409 
   6410   InlineCacheState initialization_state() const {
   6411     return initialization_state_;
   6412   }
   6413   FeedbackVectorSlot slot() const { return slot_; }
   6414   Handle<TypeFeedbackVector> feedback_vector() const {
   6415     return feedback_vector_;
   6416   }
   6417   bool HasVectorAndSlot() const { return true; }
   6418   void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
   6419                         FeedbackVectorSlot slot) {
   6420     feedback_vector_ = vector;
   6421     slot_ = slot;
   6422   }
   6423 
   6424   Representation RequiredInputRepresentation(int index) override {
   6425     return Representation::Tagged();
   6426   }
   6427 
   6428   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6429 
   6430   DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
   6431 
   6432   LanguageMode language_mode() const { return language_mode_; }
   6433 
   6434  private:
   6435   HLoadNamedGeneric(HValue* context, HValue* object, Handle<Name> name,
   6436                     LanguageMode language_mode,
   6437                     InlineCacheState initialization_state)
   6438       : name_(name),
   6439         language_mode_(language_mode),
   6440         initialization_state_(initialization_state) {
   6441     SetOperandAt(0, context);
   6442     SetOperandAt(1, object);
   6443     set_representation(Representation::Tagged());
   6444     SetAllSideEffects();
   6445   }
   6446 
   6447   Handle<Name> name_;
   6448   Handle<TypeFeedbackVector> feedback_vector_;
   6449   FeedbackVectorSlot slot_;
   6450   LanguageMode language_mode_;
   6451   InlineCacheState initialization_state_;
   6452 };
   6453 
   6454 
   6455 class HLoadFunctionPrototype final : public HUnaryOperation {
   6456  public:
   6457   DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);
   6458 
   6459   HValue* function() { return OperandAt(0); }
   6460 
   6461   Representation RequiredInputRepresentation(int index) override {
   6462     return Representation::Tagged();
   6463   }
   6464 
   6465   DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
   6466 
   6467  protected:
   6468   bool DataEquals(HValue* other) override { return true; }
   6469 
   6470  private:
   6471   explicit HLoadFunctionPrototype(HValue* function)
   6472       : HUnaryOperation(function) {
   6473     set_representation(Representation::Tagged());
   6474     SetFlag(kUseGVN);
   6475     SetDependsOnFlag(kCalls);
   6476   }
   6477 };
   6478 
   6479 class ArrayInstructionInterface {
   6480  public:
   6481   virtual HValue* GetKey() = 0;
   6482   virtual void SetKey(HValue* key) = 0;
   6483   virtual ElementsKind elements_kind() const = 0;
   6484   // TryIncreaseBaseOffset returns false if overflow would result.
   6485   virtual bool TryIncreaseBaseOffset(uint32_t increase_by_value) = 0;
   6486   virtual bool IsDehoisted() const = 0;
   6487   virtual void SetDehoisted(bool is_dehoisted) = 0;
   6488   virtual ~ArrayInstructionInterface() { }
   6489 
   6490   static Representation KeyedAccessIndexRequirement(Representation r) {
   6491     return r.IsInteger32() || SmiValuesAre32Bits()
   6492         ? Representation::Integer32() : Representation::Smi();
   6493   }
   6494 };
   6495 
   6496 
   6497 static const int kDefaultKeyedHeaderOffsetSentinel = -1;
   6498 
   6499 enum LoadKeyedHoleMode {
   6500   NEVER_RETURN_HOLE,
   6501   ALLOW_RETURN_HOLE,
   6502   CONVERT_HOLE_TO_UNDEFINED
   6503 };
   6504 
   6505 
   6506 class HLoadKeyed final : public HTemplateInstruction<4>,
   6507                          public ArrayInstructionInterface {
   6508  public:
   6509   DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
   6510                                  ElementsKind);
   6511   DECLARE_INSTRUCTION_FACTORY_P6(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
   6512                                  ElementsKind, LoadKeyedHoleMode);
   6513   DECLARE_INSTRUCTION_FACTORY_P7(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
   6514                                  ElementsKind, LoadKeyedHoleMode, int);
   6515 
   6516   bool is_fixed_typed_array() const {
   6517     return IsFixedTypedArrayElementsKind(elements_kind());
   6518   }
   6519   HValue* elements() const { return OperandAt(0); }
   6520   HValue* key() const { return OperandAt(1); }
   6521   HValue* dependency() const {
   6522     DCHECK(HasDependency());
   6523     return OperandAt(2);
   6524   }
   6525   bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
   6526   HValue* backing_store_owner() const {
   6527     DCHECK(HasBackingStoreOwner());
   6528     return OperandAt(3);
   6529   }
   6530   bool HasBackingStoreOwner() const { return OperandAt(0) != OperandAt(3); }
   6531   uint32_t base_offset() const { return BaseOffsetField::decode(bit_field_); }
   6532   bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
   6533   HValue* GetKey() override { return key(); }
   6534   void SetKey(HValue* key) override { SetOperandAt(1, key); }
   6535   bool IsDehoisted() const override {
   6536     return IsDehoistedField::decode(bit_field_);
   6537   }
   6538   void SetDehoisted(bool is_dehoisted) override {
   6539     bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
   6540   }
   6541   ElementsKind elements_kind() const override {
   6542     return ElementsKindField::decode(bit_field_);
   6543   }
   6544   LoadKeyedHoleMode hole_mode() const {
   6545     return HoleModeField::decode(bit_field_);
   6546   }
   6547 
   6548   Representation RequiredInputRepresentation(int index) override {
   6549     // kind_fast:                 tagged[int32] (none)
   6550     // kind_double:               tagged[int32] (none)
   6551     // kind_fixed_typed_array:    external[int32] (none)
   6552     // kind_external:             external[int32] (none)
   6553     if (index == 0) {
   6554       return is_fixed_typed_array() ? Representation::External()
   6555                                     : Representation::Tagged();
   6556     }
   6557     if (index == 1) {
   6558       return ArrayInstructionInterface::KeyedAccessIndexRequirement(
   6559           OperandAt(1)->representation());
   6560     }
   6561     if (index == 2) {
   6562       return Representation::None();
   6563     }
   6564     DCHECK_EQ(3, index);
   6565     return HasBackingStoreOwner() ? Representation::Tagged()
   6566                                   : Representation::None();
   6567   }
   6568 
   6569   Representation observed_input_representation(int index) override {
   6570     return RequiredInputRepresentation(index);
   6571   }
   6572 
   6573   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6574 
   6575   bool UsesMustHandleHole() const;
   6576   bool AllUsesCanTreatHoleAsNaN() const;
   6577   bool RequiresHoleCheck() const;
   6578 
   6579   Range* InferRange(Zone* zone) override;
   6580 
   6581   DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)
   6582 
   6583  protected:
   6584   bool DataEquals(HValue* other) override {
   6585     if (!other->IsLoadKeyed()) return false;
   6586     HLoadKeyed* other_load = HLoadKeyed::cast(other);
   6587 
   6588     if (base_offset() != other_load->base_offset()) return false;
   6589     return elements_kind() == other_load->elements_kind();
   6590   }
   6591 
   6592  private:
   6593   HLoadKeyed(HValue* obj, HValue* key, HValue* dependency,
   6594              HValue* backing_store_owner, ElementsKind elements_kind,
   6595              LoadKeyedHoleMode mode = NEVER_RETURN_HOLE,
   6596              int offset = kDefaultKeyedHeaderOffsetSentinel)
   6597       : bit_field_(0) {
   6598     offset = offset == kDefaultKeyedHeaderOffsetSentinel
   6599         ? GetDefaultHeaderSizeForElementsKind(elements_kind)
   6600         : offset;
   6601     bit_field_ = ElementsKindField::encode(elements_kind) |
   6602         HoleModeField::encode(mode) |
   6603         BaseOffsetField::encode(offset);
   6604 
   6605     SetOperandAt(0, obj);
   6606     SetOperandAt(1, key);
   6607     SetOperandAt(2, dependency != nullptr ? dependency : obj);
   6608     SetOperandAt(3, backing_store_owner != nullptr ? backing_store_owner : obj);
   6609     DCHECK_EQ(HasBackingStoreOwner(), is_fixed_typed_array());
   6610 
   6611     if (!is_fixed_typed_array()) {
   6612       // I can detect the case between storing double (holey and fast) and
   6613       // smi/object by looking at elements_kind_.
   6614       DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
   6615              IsFastDoubleElementsKind(elements_kind));
   6616 
   6617       if (IsFastSmiOrObjectElementsKind(elements_kind)) {
   6618         if (IsFastSmiElementsKind(elements_kind) &&
   6619             (!IsHoleyElementsKind(elements_kind) ||
   6620              mode == NEVER_RETURN_HOLE)) {
   6621           set_type(HType::Smi());
   6622           if (SmiValuesAre32Bits() && !RequiresHoleCheck()) {
   6623             set_representation(Representation::Integer32());
   6624           } else {
   6625             set_representation(Representation::Smi());
   6626           }
   6627         } else {
   6628           set_representation(Representation::Tagged());
   6629         }
   6630 
   6631         SetDependsOnFlag(kArrayElements);
   6632       } else {
   6633         set_representation(Representation::Double());
   6634         SetDependsOnFlag(kDoubleArrayElements);
   6635       }
   6636     } else {
   6637       if (elements_kind == FLOAT32_ELEMENTS ||
   6638           elements_kind == FLOAT64_ELEMENTS) {
   6639         set_representation(Representation::Double());
   6640       } else {
   6641         set_representation(Representation::Integer32());
   6642       }
   6643 
   6644       if (is_fixed_typed_array()) {
   6645         SetDependsOnFlag(kExternalMemory);
   6646         SetDependsOnFlag(kTypedArrayElements);
   6647       } else {
   6648         UNREACHABLE();
   6649       }
   6650       // Native code could change the specialized array.
   6651       SetDependsOnFlag(kCalls);
   6652     }
   6653 
   6654     SetFlag(kUseGVN);
   6655   }
   6656 
   6657   bool IsDeletable() const override { return !RequiresHoleCheck(); }
   6658 
   6659   // Establish some checks around our packed fields
   6660   enum LoadKeyedBits {
   6661     kBitsForElementsKind = 5,
   6662     kBitsForHoleMode = 2,
   6663     kBitsForBaseOffset = 24,
   6664     kBitsForIsDehoisted = 1,
   6665 
   6666     kStartElementsKind = 0,
   6667     kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
   6668     kStartBaseOffset = kStartHoleMode + kBitsForHoleMode,
   6669     kStartIsDehoisted = kStartBaseOffset + kBitsForBaseOffset
   6670   };
   6671 
   6672   STATIC_ASSERT((kBitsForElementsKind + kBitsForHoleMode + kBitsForBaseOffset +
   6673                  kBitsForIsDehoisted) <= sizeof(uint32_t) * 8);
   6674   STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
   6675   class ElementsKindField:
   6676     public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
   6677     {};  // NOLINT
   6678   class HoleModeField:
   6679     public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
   6680     {};  // NOLINT
   6681   class BaseOffsetField:
   6682     public BitField<uint32_t, kStartBaseOffset, kBitsForBaseOffset>
   6683     {};  // NOLINT
   6684   class IsDehoistedField:
   6685     public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
   6686     {};  // NOLINT
   6687   uint32_t bit_field_;
   6688 };
   6689 
   6690 
   6691 class HLoadKeyedGeneric final : public HTemplateInstruction<3> {
   6692  public:
   6693   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadKeyedGeneric, HValue*,
   6694                                               HValue*, LanguageMode,
   6695                                               InlineCacheState);
   6696   HValue* object() const { return OperandAt(0); }
   6697   HValue* key() const { return OperandAt(1); }
   6698   HValue* context() const { return OperandAt(2); }
   6699   InlineCacheState initialization_state() const {
   6700     return initialization_state_;
   6701   }
   6702   FeedbackVectorSlot slot() const { return slot_; }
   6703   Handle<TypeFeedbackVector> feedback_vector() const {
   6704     return feedback_vector_;
   6705   }
   6706   bool HasVectorAndSlot() const {
   6707     DCHECK(initialization_state_ == MEGAMORPHIC || !feedback_vector_.is_null());
   6708     return !feedback_vector_.is_null();
   6709   }
   6710   void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
   6711                         FeedbackVectorSlot slot) {
   6712     feedback_vector_ = vector;
   6713     slot_ = slot;
   6714   }
   6715 
   6716   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6717 
   6718   Representation RequiredInputRepresentation(int index) override {
   6719     // tagged[tagged]
   6720     return Representation::Tagged();
   6721   }
   6722 
   6723   HValue* Canonicalize() override;
   6724 
   6725   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
   6726 
   6727   LanguageMode language_mode() const { return language_mode_; }
   6728 
   6729  private:
   6730   HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key,
   6731                     LanguageMode language_mode,
   6732                     InlineCacheState initialization_state)
   6733       : initialization_state_(initialization_state),
   6734         language_mode_(language_mode) {
   6735     set_representation(Representation::Tagged());
   6736     SetOperandAt(0, obj);
   6737     SetOperandAt(1, key);
   6738     SetOperandAt(2, context);
   6739     SetAllSideEffects();
   6740   }
   6741 
   6742   Handle<TypeFeedbackVector> feedback_vector_;
   6743   FeedbackVectorSlot slot_;
   6744   InlineCacheState initialization_state_;
   6745   LanguageMode language_mode_;
   6746 };
   6747 
   6748 
   6749 // Indicates whether the store is a store to an entry that was previously
   6750 // initialized or not.
   6751 enum StoreFieldOrKeyedMode {
   6752   // The entry could be either previously initialized or not.
   6753   INITIALIZING_STORE,
   6754   // At the time of this store it is guaranteed that the entry is already
   6755   // initialized.
   6756   STORE_TO_INITIALIZED_ENTRY
   6757 };
   6758 
   6759 
   6760 class HStoreNamedField final : public HTemplateInstruction<3> {
   6761  public:
   6762   DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
   6763                                  HObjectAccess, HValue*);
   6764   DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue*,
   6765                                  HObjectAccess, HValue*, StoreFieldOrKeyedMode);
   6766 
   6767   DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
   6768 
   6769   bool HasEscapingOperandAt(int index) override { return index == 1; }
   6770   bool HasOutOfBoundsAccess(int size) override {
   6771     return !access().IsInobject() || access().offset() >= size;
   6772   }
   6773   Representation RequiredInputRepresentation(int index) override {
   6774     if (index == 0 && access().IsExternalMemory()) {
   6775       // object must be external in case of external memory access
   6776       return Representation::External();
   6777     } else if (index == 1) {
   6778       if (field_representation().IsInteger8() ||
   6779           field_representation().IsUInteger8() ||
   6780           field_representation().IsInteger16() ||
   6781           field_representation().IsUInteger16() ||
   6782           field_representation().IsInteger32()) {
   6783         return Representation::Integer32();
   6784       } else if (field_representation().IsDouble()) {
   6785         return field_representation();
   6786       } else if (field_representation().IsSmi()) {
   6787         if (SmiValuesAre32Bits() &&
   6788             store_mode() == STORE_TO_INITIALIZED_ENTRY) {
   6789           return Representation::Integer32();
   6790         }
   6791         return field_representation();
   6792       } else if (field_representation().IsExternal()) {
   6793         return Representation::External();
   6794       }
   6795     }
   6796     return Representation::Tagged();
   6797   }
   6798   bool HandleSideEffectDominator(GVNFlag side_effect,
   6799                                  HValue* dominator) override {
   6800     DCHECK(side_effect == kNewSpacePromotion);
   6801     if (!FLAG_use_write_barrier_elimination) return false;
   6802     dominator_ = dominator;
   6803     return false;
   6804   }
   6805   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6806 
   6807   HValue* object() const { return OperandAt(0); }
   6808   HValue* value() const { return OperandAt(1); }
   6809   HValue* transition() const { return OperandAt(2); }
   6810 
   6811   HObjectAccess access() const { return access_; }
   6812   HValue* dominator() const { return dominator_; }
   6813   bool has_transition() const { return HasTransitionField::decode(bit_field_); }
   6814   StoreFieldOrKeyedMode store_mode() const {
   6815     return StoreModeField::decode(bit_field_);
   6816   }
   6817 
   6818   Handle<Map> transition_map() const {
   6819     if (has_transition()) {
   6820       return Handle<Map>::cast(
   6821           HConstant::cast(transition())->handle(isolate()));
   6822     } else {
   6823       return Handle<Map>();
   6824     }
   6825   }
   6826 
   6827   void SetTransition(HConstant* transition) {
   6828     DCHECK(!has_transition());  // Only set once.
   6829     SetOperandAt(2, transition);
   6830     bit_field_ = HasTransitionField::update(bit_field_, true);
   6831     SetChangesFlag(kMaps);
   6832   }
   6833 
   6834   bool NeedsWriteBarrier() const {
   6835     DCHECK(!field_representation().IsDouble() ||
   6836            (FLAG_unbox_double_fields && access_.IsInobject()) ||
   6837            !has_transition());
   6838     if (field_representation().IsDouble()) return false;
   6839     if (field_representation().IsSmi()) return false;
   6840     if (field_representation().IsInteger32()) return false;
   6841     if (field_representation().IsExternal()) return false;
   6842     return StoringValueNeedsWriteBarrier(value()) &&
   6843         ReceiverObjectNeedsWriteBarrier(object(), value(), dominator());
   6844   }
   6845 
   6846   bool NeedsWriteBarrierForMap() {
   6847     return ReceiverObjectNeedsWriteBarrier(object(), transition(),
   6848                                            dominator());
   6849   }
   6850 
   6851   SmiCheck SmiCheckForWriteBarrier() const {
   6852     if (field_representation().IsHeapObject()) return OMIT_SMI_CHECK;
   6853     if (value()->type().IsHeapObject()) return OMIT_SMI_CHECK;
   6854     return INLINE_SMI_CHECK;
   6855   }
   6856 
   6857   PointersToHereCheck PointersToHereCheckForValue() const {
   6858     return PointersToHereCheckForObject(value(), dominator());
   6859   }
   6860 
   6861   Representation field_representation() const {
   6862     return access_.representation();
   6863   }
   6864 
   6865   void UpdateValue(HValue* value) {
   6866     SetOperandAt(1, value);
   6867   }
   6868 
   6869   bool CanBeReplacedWith(HStoreNamedField* that) const {
   6870     if (!this->access().Equals(that->access())) return false;
   6871     if (SmiValuesAre32Bits() &&
   6872         this->field_representation().IsSmi() &&
   6873         this->store_mode() == INITIALIZING_STORE &&
   6874         that->store_mode() == STORE_TO_INITIALIZED_ENTRY) {
   6875       // We cannot replace an initializing store to a smi field with a store to
   6876       // an initialized entry on 64-bit architectures (with 32-bit smis).
   6877       return false;
   6878     }
   6879     return true;
   6880   }
   6881 
   6882  private:
   6883   HStoreNamedField(HValue* obj, HObjectAccess access, HValue* val,
   6884                    StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
   6885       : access_(access),
   6886         dominator_(NULL),
   6887         bit_field_(HasTransitionField::encode(false) |
   6888                    StoreModeField::encode(store_mode)) {
   6889     // Stores to a non existing in-object property are allowed only to the
   6890     // newly allocated objects (via HAllocate or HInnerAllocatedObject).
   6891     DCHECK(!access.IsInobject() || access.existing_inobject_property() ||
   6892            obj->IsAllocate() || obj->IsInnerAllocatedObject());
   6893     SetOperandAt(0, obj);
   6894     SetOperandAt(1, val);
   6895     SetOperandAt(2, obj);
   6896     access.SetGVNFlags(this, STORE);
   6897   }
   6898 
   6899   class HasTransitionField : public BitField<bool, 0, 1> {};
   6900   class StoreModeField : public BitField<StoreFieldOrKeyedMode, 1, 1> {};
   6901 
   6902   HObjectAccess access_;
   6903   HValue* dominator_;
   6904   uint32_t bit_field_;
   6905 };
   6906 
   6907 
   6908 class HStoreNamedGeneric final : public HTemplateInstruction<3> {
   6909  public:
   6910   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HStoreNamedGeneric, HValue*,
   6911                                               Handle<Name>, HValue*,
   6912                                               LanguageMode, InlineCacheState);
   6913   HValue* object() const { return OperandAt(0); }
   6914   HValue* value() const { return OperandAt(1); }
   6915   HValue* context() const { return OperandAt(2); }
   6916   Handle<Name> name() const { return name_; }
   6917   LanguageMode language_mode() const { return language_mode_; }
   6918   InlineCacheState initialization_state() const {
   6919     return initialization_state_;
   6920   }
   6921 
   6922   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6923 
   6924   Representation RequiredInputRepresentation(int index) override {
   6925     return Representation::Tagged();
   6926   }
   6927 
   6928   FeedbackVectorSlot slot() const { return slot_; }
   6929   Handle<TypeFeedbackVector> feedback_vector() const {
   6930     return feedback_vector_;
   6931   }
   6932   bool HasVectorAndSlot() const { return true; }
   6933   void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
   6934                         FeedbackVectorSlot slot) {
   6935     feedback_vector_ = vector;
   6936     slot_ = slot;
   6937   }
   6938 
   6939   DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
   6940 
   6941  private:
   6942   HStoreNamedGeneric(HValue* context, HValue* object, Handle<Name> name,
   6943                      HValue* value, LanguageMode language_mode,
   6944                      InlineCacheState initialization_state)
   6945       : name_(name),
   6946         language_mode_(language_mode),
   6947         initialization_state_(initialization_state) {
   6948     SetOperandAt(0, object);
   6949     SetOperandAt(1, value);
   6950     SetOperandAt(2, context);
   6951     SetAllSideEffects();
   6952   }
   6953 
   6954   Handle<Name> name_;
   6955   Handle<TypeFeedbackVector> feedback_vector_;
   6956   FeedbackVectorSlot slot_;
   6957   LanguageMode language_mode_;
   6958   InlineCacheState initialization_state_;
   6959 };
   6960 
   6961 
   6962 class HStoreKeyed final : public HTemplateInstruction<4>,
   6963                           public ArrayInstructionInterface {
   6964  public:
   6965   DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*,
   6966                                  HValue*, ElementsKind);
   6967   DECLARE_INSTRUCTION_FACTORY_P6(HStoreKeyed, HValue*, HValue*, HValue*,
   6968                                  HValue*, ElementsKind, StoreFieldOrKeyedMode);
   6969   DECLARE_INSTRUCTION_FACTORY_P7(HStoreKeyed, HValue*, HValue*, HValue*,
   6970                                  HValue*, ElementsKind, StoreFieldOrKeyedMode,
   6971                                  int);
   6972 
   6973   Representation RequiredInputRepresentation(int index) override {
   6974     // kind_fast:               tagged[int32] = tagged
   6975     // kind_double:             tagged[int32] = double
   6976     // kind_smi   :             tagged[int32] = smi
   6977     // kind_fixed_typed_array:  tagged[int32] = (double | int32)
   6978     // kind_external:           external[int32] = (double | int32)
   6979     if (index == 0) {
   6980       return is_fixed_typed_array() ? Representation::External()
   6981                                     : Representation::Tagged();
   6982     } else if (index == 1) {
   6983       return ArrayInstructionInterface::KeyedAccessIndexRequirement(
   6984           OperandAt(1)->representation());
   6985     } else if (index == 2) {
   6986       return RequiredValueRepresentation(elements_kind(), store_mode());
   6987     }
   6988 
   6989     DCHECK_EQ(3, index);
   6990     return HasBackingStoreOwner() ? Representation::Tagged()
   6991                                   : Representation::None();
   6992   }
   6993 
   6994   static Representation RequiredValueRepresentation(
   6995       ElementsKind kind, StoreFieldOrKeyedMode mode) {
   6996     if (IsDoubleOrFloatElementsKind(kind)) {
   6997       return Representation::Double();
   6998     }
   6999 
   7000     if (kind == FAST_SMI_ELEMENTS && SmiValuesAre32Bits() &&
   7001         mode == STORE_TO_INITIALIZED_ENTRY) {
   7002       return Representation::Integer32();
   7003     }
   7004 
   7005     if (IsFastSmiElementsKind(kind)) {
   7006       return Representation::Smi();
   7007     }
   7008 
   7009     if (IsFixedTypedArrayElementsKind(kind)) {
   7010       return Representation::Integer32();
   7011     }
   7012     return Representation::Tagged();
   7013   }
   7014 
   7015   bool is_fixed_typed_array() const {
   7016     return IsFixedTypedArrayElementsKind(elements_kind());
   7017   }
   7018 
   7019   Representation observed_input_representation(int index) override {
   7020     if (index != 2) return RequiredInputRepresentation(index);
   7021     if (IsUninitialized()) {
   7022       return Representation::None();
   7023     }
   7024     Representation r =
   7025         RequiredValueRepresentation(elements_kind(), store_mode());
   7026     // For fast object elements kinds, don't assume anything.
   7027     if (r.IsTagged()) return Representation::None();
   7028     return r;
   7029   }
   7030 
   7031   HValue* elements() const { return OperandAt(0); }
   7032   HValue* key() const { return OperandAt(1); }
   7033   HValue* value() const { return OperandAt(2); }
   7034   HValue* backing_store_owner() const {
   7035     DCHECK(HasBackingStoreOwner());
   7036     return OperandAt(3);
   7037   }
   7038   bool HasBackingStoreOwner() const { return OperandAt(0) != OperandAt(3); }
   7039   bool value_is_smi() const { return IsFastSmiElementsKind(elements_kind()); }
   7040   StoreFieldOrKeyedMode store_mode() const {
   7041     return StoreModeField::decode(bit_field_);
   7042   }
   7043   ElementsKind elements_kind() const override {
   7044     return ElementsKindField::decode(bit_field_);
   7045   }
   7046   uint32_t base_offset() const { return base_offset_; }
   7047   bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
   7048   HValue* GetKey() override { return key(); }
   7049   void SetKey(HValue* key) override { SetOperandAt(1, key); }
   7050   bool IsDehoisted() const override {
   7051     return IsDehoistedField::decode(bit_field_);
   7052   }
   7053   void SetDehoisted(bool is_dehoisted) override {
   7054     bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
   7055   }
   7056   bool IsUninitialized() { return IsUninitializedField::decode(bit_field_); }
   7057   void SetUninitialized(bool is_uninitialized) {
   7058     bit_field_ = IsUninitializedField::update(bit_field_, is_uninitialized);
   7059   }
   7060 
   7061   bool IsConstantHoleStore() {
   7062     return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
   7063   }
   7064 
   7065   bool HandleSideEffectDominator(GVNFlag side_effect,
   7066                                  HValue* dominator) override {
   7067     DCHECK(side_effect == kNewSpacePromotion);
   7068     dominator_ = dominator;
   7069     return false;
   7070   }
   7071 
   7072   HValue* dominator() const { return dominator_; }
   7073 
   7074   bool NeedsWriteBarrier() {
   7075     if (value_is_smi()) {
   7076       return false;
   7077     } else {
   7078       return StoringValueNeedsWriteBarrier(value()) &&
   7079           ReceiverObjectNeedsWriteBarrier(elements(), value(), dominator());
   7080     }
   7081   }
   7082 
   7083   PointersToHereCheck PointersToHereCheckForValue() const {
   7084     return PointersToHereCheckForObject(value(), dominator());
   7085   }
   7086 
   7087   bool NeedsCanonicalization();
   7088 
   7089   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   7090 
   7091   DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
   7092 
   7093  private:
   7094   HStoreKeyed(HValue* obj, HValue* key, HValue* val,
   7095               HValue* backing_store_owner, ElementsKind elements_kind,
   7096               StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE,
   7097               int offset = kDefaultKeyedHeaderOffsetSentinel)
   7098       : base_offset_(offset == kDefaultKeyedHeaderOffsetSentinel
   7099                          ? GetDefaultHeaderSizeForElementsKind(elements_kind)
   7100                          : offset),
   7101         bit_field_(IsDehoistedField::encode(false) |
   7102                    IsUninitializedField::encode(false) |
   7103                    StoreModeField::encode(store_mode) |
   7104                    ElementsKindField::encode(elements_kind)),
   7105         dominator_(NULL) {
   7106     SetOperandAt(0, obj);
   7107     SetOperandAt(1, key);
   7108     SetOperandAt(2, val);
   7109     SetOperandAt(3, backing_store_owner != nullptr ? backing_store_owner : obj);
   7110     DCHECK_EQ(HasBackingStoreOwner(), is_fixed_typed_array());
   7111 
   7112     if (IsFastObjectElementsKind(elements_kind)) {
   7113       SetFlag(kTrackSideEffectDominators);
   7114       SetDependsOnFlag(kNewSpacePromotion);
   7115     }
   7116     if (IsFastDoubleElementsKind(elements_kind)) {
   7117       SetChangesFlag(kDoubleArrayElements);
   7118     } else if (IsFastSmiElementsKind(elements_kind)) {
   7119       SetChangesFlag(kArrayElements);
   7120     } else if (is_fixed_typed_array()) {
   7121       SetChangesFlag(kTypedArrayElements);
   7122       SetChangesFlag(kExternalMemory);
   7123       SetFlag(kAllowUndefinedAsNaN);
   7124     } else {
   7125       SetChangesFlag(kArrayElements);
   7126     }
   7127 
   7128     // {UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
   7129     if (elements_kind >= UINT8_ELEMENTS && elements_kind <= INT32_ELEMENTS) {
   7130       SetFlag(kTruncatingToInt32);
   7131     }
   7132   }
   7133 
   7134   class IsDehoistedField : public BitField<bool, 0, 1> {};
   7135   class IsUninitializedField : public BitField<bool, 1, 1> {};
   7136   class StoreModeField : public BitField<StoreFieldOrKeyedMode, 2, 1> {};
   7137   class ElementsKindField : public BitField<ElementsKind, 3, 5> {};
   7138 
   7139   uint32_t base_offset_;
   7140   uint32_t bit_field_;
   7141   HValue* dominator_;
   7142 };
   7143 
   7144 
   7145 class HStoreKeyedGeneric final : public HTemplateInstruction<4> {
   7146  public:
   7147   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HStoreKeyedGeneric, HValue*,
   7148                                               HValue*, HValue*, LanguageMode,
   7149                                               InlineCacheState);
   7150 
   7151   HValue* object() const { return OperandAt(0); }
   7152   HValue* key() const { return OperandAt(1); }
   7153   HValue* value() const { return OperandAt(2); }
   7154   HValue* context() const { return OperandAt(3); }
   7155   LanguageMode language_mode() const { return language_mode_; }
   7156   InlineCacheState initialization_state() const {
   7157     return initialization_state_;
   7158   }
   7159 
   7160   Representation RequiredInputRepresentation(int index) override {
   7161     // tagged[tagged] = tagged
   7162     return Representation::Tagged();
   7163   }
   7164 
   7165   FeedbackVectorSlot slot() const { return slot_; }
   7166   Handle<TypeFeedbackVector> feedback_vector() const {
   7167     return feedback_vector_;
   7168   }
   7169   bool HasVectorAndSlot() const {
   7170     return !feedback_vector_.is_null();
   7171   }
   7172   void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
   7173                         FeedbackVectorSlot slot) {
   7174     feedback_vector_ = vector;
   7175     slot_ = slot;
   7176   }
   7177 
   7178   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   7179 
   7180   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
   7181 
   7182  private:
   7183   HStoreKeyedGeneric(HValue* context, HValue* object, HValue* key,
   7184                      HValue* value, LanguageMode language_mode,
   7185                      InlineCacheState initialization_state)
   7186       : language_mode_(language_mode),
   7187         initialization_state_(initialization_state) {
   7188     SetOperandAt(0, object);
   7189     SetOperandAt(1, key);
   7190     SetOperandAt(2, value);
   7191     SetOperandAt(3, context);
   7192     SetAllSideEffects();
   7193   }
   7194 
   7195   Handle<TypeFeedbackVector> feedback_vector_;
   7196   FeedbackVectorSlot slot_;
   7197   LanguageMode language_mode_;
   7198   InlineCacheState initialization_state_;
   7199 };
   7200 
   7201 
   7202 class HTransitionElementsKind final : public HTemplateInstruction<2> {
   7203  public:
   7204   inline static HTransitionElementsKind* New(Isolate* isolate, Zone* zone,
   7205                                              HValue* context, HValue* object,
   7206                                              Handle<Map> original_map,
   7207                                              Handle<Map> transitioned_map) {
   7208     return new(zone) HTransitionElementsKind(context, object,
   7209                                              original_map, transitioned_map);
   7210   }
   7211 
   7212   Representation RequiredInputRepresentation(int index) override {
   7213     return Representation::Tagged();
   7214   }
   7215 
   7216   HValue* object() const { return OperandAt(0); }
   7217   HValue* context() const { return OperandAt(1); }
   7218   Unique<Map> original_map() const { return original_map_; }
   7219   Unique<Map> transitioned_map() const { return transitioned_map_; }
   7220   ElementsKind from_kind() const {
   7221     return FromElementsKindField::decode(bit_field_);
   7222   }
   7223   ElementsKind to_kind() const {
   7224     return ToElementsKindField::decode(bit_field_);
   7225   }
   7226   bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }
   7227 
   7228   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   7229 
   7230   DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
   7231 
   7232  protected:
   7233   bool DataEquals(HValue* other) override {
   7234     HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
   7235     return original_map_ == instr->original_map_ &&
   7236            transitioned_map_ == instr->transitioned_map_;
   7237   }
   7238 
   7239   int RedefinedOperandIndex() override { return 0; }
   7240 
   7241  private:
   7242   HTransitionElementsKind(HValue* context, HValue* object,
   7243                           Handle<Map> original_map,
   7244                           Handle<Map> transitioned_map)
   7245       : original_map_(Unique<Map>(original_map)),
   7246         transitioned_map_(Unique<Map>(transitioned_map)),
   7247         bit_field_(
   7248             FromElementsKindField::encode(original_map->elements_kind()) |
   7249             ToElementsKindField::encode(transitioned_map->elements_kind()) |
   7250             MapIsStableField::encode(transitioned_map->is_stable())) {
   7251     SetOperandAt(0, object);
   7252     SetOperandAt(1, context);
   7253     SetFlag(kUseGVN);
   7254     SetChangesFlag(kElementsKind);
   7255     if (!IsSimpleMapChangeTransition(from_kind(), to_kind())) {
   7256       SetChangesFlag(kElementsPointer);
   7257       SetChangesFlag(kNewSpacePromotion);
   7258     }
   7259     set_representation(Representation::Tagged());
   7260   }
   7261 
   7262   class FromElementsKindField : public BitField<ElementsKind, 0, 5> {};
   7263   class ToElementsKindField : public BitField<ElementsKind, 5, 5> {};
   7264   class MapIsStableField : public BitField<bool, 10, 1> {};
   7265 
   7266   Unique<Map> original_map_;
   7267   Unique<Map> transitioned_map_;
   7268   uint32_t bit_field_;
   7269 };
   7270 
   7271 
   7272 class HStringAdd final : public HBinaryOperation {
   7273  public:
   7274   static HInstruction* New(
   7275       Isolate* isolate, Zone* zone, HValue* context, HValue* left,
   7276       HValue* right, PretenureFlag pretenure_flag = NOT_TENURED,
   7277       StringAddFlags flags = STRING_ADD_CHECK_BOTH,
   7278       Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null());
   7279 
   7280   StringAddFlags flags() const { return flags_; }
   7281   PretenureFlag pretenure_flag() const { return pretenure_flag_; }
   7282 
   7283   Representation RequiredInputRepresentation(int index) override {
   7284     return Representation::Tagged();
   7285   }
   7286 
   7287   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   7288 
   7289   DECLARE_CONCRETE_INSTRUCTION(StringAdd)
   7290 
   7291  protected:
   7292   bool DataEquals(HValue* other) override {
   7293     return flags_ == HStringAdd::cast(other)->flags_ &&
   7294         pretenure_flag_ == HStringAdd::cast(other)->pretenure_flag_;
   7295   }
   7296 
   7297  private:
   7298   HStringAdd(HValue* context, HValue* left, HValue* right,
   7299              PretenureFlag pretenure_flag, StringAddFlags flags,
   7300              Handle<AllocationSite> allocation_site)
   7301       : HBinaryOperation(context, left, right, Strength::WEAK, HType::String()),
   7302         flags_(flags),
   7303         pretenure_flag_(pretenure_flag) {
   7304     set_representation(Representation::Tagged());
   7305     if ((flags & STRING_ADD_CONVERT) == STRING_ADD_CONVERT) {
   7306       SetAllSideEffects();
   7307       ClearFlag(kUseGVN);
   7308     } else {
   7309       SetChangesFlag(kNewSpacePromotion);
   7310       SetFlag(kUseGVN);
   7311     }
   7312     SetDependsOnFlag(kMaps);
   7313     if (FLAG_trace_pretenuring) {
   7314       PrintF("HStringAdd with AllocationSite %p %s\n",
   7315              allocation_site.is_null()
   7316                  ? static_cast<void*>(NULL)
   7317                  : static_cast<void*>(*allocation_site),
   7318              pretenure_flag == TENURED ? "tenured" : "not tenured");
   7319     }
   7320   }
   7321 
   7322   bool IsDeletable() const final {
   7323     return (flags_ & STRING_ADD_CONVERT) != STRING_ADD_CONVERT;
   7324   }
   7325 
   7326   const StringAddFlags flags_;
   7327   const PretenureFlag pretenure_flag_;
   7328 };
   7329 
   7330 
   7331 class HStringCharCodeAt final : public HTemplateInstruction<3> {
   7332  public:
   7333   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HStringCharCodeAt,
   7334                                               HValue*,
   7335                                               HValue*);
   7336 
   7337   Representation RequiredInputRepresentation(int index) override {
   7338     // The index is supposed to be Integer32.
   7339     return index == 2
   7340         ? Representation::Integer32()
   7341         : Representation::Tagged();
   7342   }
   7343 
   7344   HValue* context() const { return OperandAt(0); }
   7345   HValue* string() const { return OperandAt(1); }
   7346   HValue* index() const { return OperandAt(2); }
   7347 
   7348   DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
   7349 
   7350  protected:
   7351   bool DataEquals(HValue* other) override { return true; }
   7352 
   7353   Range* InferRange(Zone* zone) override {
   7354     return new(zone) Range(0, String::kMaxUtf16CodeUnit);
   7355   }
   7356 
   7357  private:
   7358   HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
   7359     SetOperandAt(0, context);
   7360     SetOperandAt(1, string);
   7361     SetOperandAt(2, index);
   7362     set_representation(Representation::Integer32());
   7363     SetFlag(kUseGVN);
   7364     SetDependsOnFlag(kMaps);
   7365     SetDependsOnFlag(kStringChars);
   7366     SetChangesFlag(kNewSpacePromotion);
   7367   }
   7368 
   7369   // No side effects: runtime function assumes string + number inputs.
   7370   bool IsDeletable() const override { return true; }
   7371 };
   7372 
   7373 
   7374 class HStringCharFromCode final : public HTemplateInstruction<2> {
   7375  public:
   7376   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   7377                            HValue* char_code);
   7378 
   7379   Representation RequiredInputRepresentation(int index) override {
   7380     return index == 0
   7381         ? Representation::Tagged()
   7382         : Representation::Integer32();
   7383   }
   7384 
   7385   HValue* context() const { return OperandAt(0); }
   7386   HValue* value() const { return OperandAt(1); }
   7387 
   7388   bool DataEquals(HValue* other) override { return true; }
   7389 
   7390   DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
   7391 
   7392  private:
   7393   HStringCharFromCode(HValue* context, HValue* char_code)
   7394       : HTemplateInstruction<2>(HType::String()) {
   7395     SetOperandAt(0, context);
   7396     SetOperandAt(1, char_code);
   7397     set_representation(Representation::Tagged());
   7398     SetFlag(kUseGVN);
   7399     SetChangesFlag(kNewSpacePromotion);
   7400   }
   7401 
   7402   bool IsDeletable() const override {
   7403     return !value()->ToNumberCanBeObserved();
   7404   }
   7405 };
   7406 
   7407 
   7408 class HTypeof final : public HTemplateInstruction<2> {
   7409  public:
   7410   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HTypeof, HValue*);
   7411 
   7412   HValue* context() const { return OperandAt(0); }
   7413   HValue* value() const { return OperandAt(1); }
   7414 
   7415   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   7416 
   7417   Representation RequiredInputRepresentation(int index) override {
   7418     return Representation::Tagged();
   7419   }
   7420 
   7421   DECLARE_CONCRETE_INSTRUCTION(Typeof)
   7422 
   7423  private:
   7424   explicit HTypeof(HValue* context, HValue* value) {
   7425     SetOperandAt(0, context);
   7426     SetOperandAt(1, value);
   7427     set_representation(Representation::Tagged());
   7428   }
   7429 
   7430   bool IsDeletable() const override { return true; }
   7431 };
   7432 
   7433 
   7434 class HTrapAllocationMemento final : public HTemplateInstruction<1> {
   7435  public:
   7436   DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
   7437 
   7438   Representation RequiredInputRepresentation(int index) override {
   7439     return Representation::Tagged();
   7440   }
   7441 
   7442   HValue* object() { return OperandAt(0); }
   7443 
   7444   DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
   7445 
   7446  private:
   7447   explicit HTrapAllocationMemento(HValue* obj) {
   7448     SetOperandAt(0, obj);
   7449   }
   7450 };
   7451 
   7452 
   7453 class HMaybeGrowElements final : public HTemplateInstruction<5> {
   7454  public:
   7455   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(HMaybeGrowElements, HValue*,
   7456                                               HValue*, HValue*, HValue*, bool,
   7457                                               ElementsKind);
   7458 
   7459   Representation RequiredInputRepresentation(int index) override {
   7460     if (index < 3) {
   7461       return Representation::Tagged();
   7462     }
   7463     DCHECK(index == 3 || index == 4);
   7464     return Representation::Integer32();
   7465   }
   7466 
   7467   HValue* context() const { return OperandAt(0); }
   7468   HValue* object() const { return OperandAt(1); }
   7469   HValue* elements() const { return OperandAt(2); }
   7470   HValue* key() const { return OperandAt(3); }
   7471   HValue* current_capacity() const { return OperandAt(4); }
   7472 
   7473   bool is_js_array() const { return is_js_array_; }
   7474   ElementsKind kind() const { return kind_; }
   7475 
   7476   DECLARE_CONCRETE_INSTRUCTION(MaybeGrowElements)
   7477 
   7478  protected:
   7479   bool DataEquals(HValue* other) override { return true; }
   7480 
   7481  private:
   7482   explicit HMaybeGrowElements(HValue* context, HValue* object, HValue* elements,
   7483                               HValue* key, HValue* current_capacity,
   7484                               bool is_js_array, ElementsKind kind) {
   7485     is_js_array_ = is_js_array;
   7486     kind_ = kind;
   7487 
   7488     SetOperandAt(0, context);
   7489     SetOperandAt(1, object);
   7490     SetOperandAt(2, elements);
   7491     SetOperandAt(3, key);
   7492     SetOperandAt(4, current_capacity);
   7493 
   7494     SetFlag(kUseGVN);
   7495     SetChangesFlag(kElementsPointer);
   7496     SetChangesFlag(kNewSpacePromotion);
   7497     set_representation(Representation::Tagged());
   7498   }
   7499 
   7500   bool is_js_array_;
   7501   ElementsKind kind_;
   7502 };
   7503 
   7504 
   7505 class HToFastProperties final : public HUnaryOperation {
   7506  public:
   7507   DECLARE_INSTRUCTION_FACTORY_P1(HToFastProperties, HValue*);
   7508 
   7509   Representation RequiredInputRepresentation(int index) override {
   7510     return Representation::Tagged();
   7511   }
   7512 
   7513   DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
   7514 
   7515  private:
   7516   explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
   7517     set_representation(Representation::Tagged());
   7518     SetChangesFlag(kNewSpacePromotion);
   7519 
   7520     // This instruction is not marked as kChangesMaps, but does
   7521     // change the map of the input operand. Use it only when creating
   7522     // object literals via a runtime call.
   7523     DCHECK(value->IsCallRuntime());
   7524 #ifdef DEBUG
   7525     const Runtime::Function* function = HCallRuntime::cast(value)->function();
   7526     DCHECK(function->function_id == Runtime::kCreateObjectLiteral);
   7527 #endif
   7528   }
   7529 
   7530   bool IsDeletable() const override { return true; }
   7531 };
   7532 
   7533 
   7534 class HSeqStringGetChar final : public HTemplateInstruction<2> {
   7535  public:
   7536   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   7537                            String::Encoding encoding, HValue* string,
   7538                            HValue* index);
   7539 
   7540   Representation RequiredInputRepresentation(int index) override {
   7541     return (index == 0) ? Representation::Tagged()
   7542                         : Representation::Integer32();
   7543   }
   7544 
   7545   String::Encoding encoding() const { return encoding_; }
   7546   HValue* string() const { return OperandAt(0); }
   7547   HValue* index() const { return OperandAt(1); }
   7548 
   7549   DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)
   7550 
   7551  protected:
   7552   bool DataEquals(HValue* other) override {
   7553     return encoding() == HSeqStringGetChar::cast(other)->encoding();
   7554   }
   7555 
   7556   Range* InferRange(Zone* zone) override {
   7557     if (encoding() == String::ONE_BYTE_ENCODING) {
   7558       return new(zone) Range(0, String::kMaxOneByteCharCode);
   7559     } else {
   7560       DCHECK_EQ(String::TWO_BYTE_ENCODING, encoding());
   7561       return  new(zone) Range(0, String::kMaxUtf16CodeUnit);
   7562     }
   7563   }
   7564 
   7565  private:
   7566   HSeqStringGetChar(String::Encoding encoding,
   7567                     HValue* string,
   7568                     HValue* index) : encoding_(encoding) {
   7569     SetOperandAt(0, string);
   7570     SetOperandAt(1, index);
   7571     set_representation(Representation::Integer32());
   7572     SetFlag(kUseGVN);
   7573     SetDependsOnFlag(kStringChars);
   7574   }
   7575 
   7576   bool IsDeletable() const override { return true; }
   7577 
   7578   String::Encoding encoding_;
   7579 };
   7580 
   7581 
   7582 class HSeqStringSetChar final : public HTemplateInstruction<4> {
   7583  public:
   7584   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(
   7585       HSeqStringSetChar, String::Encoding,
   7586       HValue*, HValue*, HValue*);
   7587 
   7588   String::Encoding encoding() { return encoding_; }
   7589   HValue* context() { return OperandAt(0); }
   7590   HValue* string() { return OperandAt(1); }
   7591   HValue* index() { return OperandAt(2); }
   7592   HValue* value() { return OperandAt(3); }
   7593 
   7594   Representation RequiredInputRepresentation(int index) override {
   7595     return (index <= 1) ? Representation::Tagged()
   7596                         : Representation::Integer32();
   7597   }
   7598 
   7599   DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
   7600 
   7601  private:
   7602   HSeqStringSetChar(HValue* context,
   7603                     String::Encoding encoding,
   7604                     HValue* string,
   7605                     HValue* index,
   7606                     HValue* value) : encoding_(encoding) {
   7607     SetOperandAt(0, context);
   7608     SetOperandAt(1, string);
   7609     SetOperandAt(2, index);
   7610     SetOperandAt(3, value);
   7611     set_representation(Representation::Tagged());
   7612     SetChangesFlag(kStringChars);
   7613   }
   7614 
   7615   String::Encoding encoding_;
   7616 };
   7617 
   7618 
   7619 class HCheckMapValue final : public HTemplateInstruction<2> {
   7620  public:
   7621   DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);
   7622 
   7623   Representation RequiredInputRepresentation(int index) override {
   7624     return Representation::Tagged();
   7625   }
   7626 
   7627   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   7628 
   7629   HType CalculateInferredType() override {
   7630     if (value()->type().IsHeapObject()) return value()->type();
   7631     return HType::HeapObject();
   7632   }
   7633 
   7634   HValue* value() const { return OperandAt(0); }
   7635   HValue* map() const { return OperandAt(1); }
   7636 
   7637   HValue* Canonicalize() override;
   7638 
   7639   DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
   7640 
   7641  protected:
   7642   int RedefinedOperandIndex() override { return 0; }
   7643 
   7644   bool DataEquals(HValue* other) override { return true; }
   7645 
   7646  private:
   7647   HCheckMapValue(HValue* value, HValue* map)
   7648       : HTemplateInstruction<2>(HType::HeapObject()) {
   7649     SetOperandAt(0, value);
   7650     SetOperandAt(1, map);
   7651     set_representation(Representation::Tagged());
   7652     SetFlag(kUseGVN);
   7653     SetDependsOnFlag(kMaps);
   7654     SetDependsOnFlag(kElementsKind);
   7655   }
   7656 };
   7657 
   7658 
   7659 class HForInPrepareMap final : public HTemplateInstruction<2> {
   7660  public:
   7661   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HForInPrepareMap, HValue*);
   7662 
   7663   Representation RequiredInputRepresentation(int index) override {
   7664     return Representation::Tagged();
   7665   }
   7666 
   7667   HValue* context() const { return OperandAt(0); }
   7668   HValue* enumerable() const { return OperandAt(1); }
   7669 
   7670   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   7671 
   7672   HType CalculateInferredType() override { return HType::Tagged(); }
   7673 
   7674   DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
   7675 
   7676  private:
   7677   HForInPrepareMap(HValue* context,
   7678                    HValue* object) {
   7679     SetOperandAt(0, context);
   7680     SetOperandAt(1, object);
   7681     set_representation(Representation::Tagged());
   7682     SetAllSideEffects();
   7683   }
   7684 };
   7685 
   7686 
   7687 class HForInCacheArray final : public HTemplateInstruction<2> {
   7688  public:
   7689   DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
   7690 
   7691   Representation RequiredInputRepresentation(int index) override {
   7692     return Representation::Tagged();
   7693   }
   7694 
   7695   HValue* enumerable() const { return OperandAt(0); }
   7696   HValue* map() const { return OperandAt(1); }
   7697   int idx() const { return idx_; }
   7698 
   7699   HForInCacheArray* index_cache() {
   7700     return index_cache_;
   7701   }
   7702 
   7703   void set_index_cache(HForInCacheArray* index_cache) {
   7704     index_cache_ = index_cache;
   7705   }
   7706 
   7707   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   7708 
   7709   HType CalculateInferredType() override { return HType::Tagged(); }
   7710 
   7711   DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
   7712 
   7713  private:
   7714   HForInCacheArray(HValue* enumerable,
   7715                    HValue* keys,
   7716                    int idx) : idx_(idx) {
   7717     SetOperandAt(0, enumerable);
   7718     SetOperandAt(1, keys);
   7719     set_representation(Representation::Tagged());
   7720   }
   7721 
   7722   int idx_;
   7723   HForInCacheArray* index_cache_;
   7724 };
   7725 
   7726 
   7727 class HLoadFieldByIndex final : public HTemplateInstruction<2> {
   7728  public:
   7729   DECLARE_INSTRUCTION_FACTORY_P2(HLoadFieldByIndex, HValue*, HValue*);
   7730 
   7731   HLoadFieldByIndex(HValue* object,
   7732                     HValue* index) {
   7733     SetOperandAt(0, object);
   7734     SetOperandAt(1, index);
   7735     SetChangesFlag(kNewSpacePromotion);
   7736     set_representation(Representation::Tagged());
   7737   }
   7738 
   7739   Representation RequiredInputRepresentation(int index) override {
   7740     if (index == 1) {
   7741       return Representation::Smi();
   7742     } else {
   7743       return Representation::Tagged();
   7744     }
   7745   }
   7746 
   7747   HValue* object() const { return OperandAt(0); }
   7748   HValue* index() const { return OperandAt(1); }
   7749 
   7750   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   7751 
   7752   HType CalculateInferredType() override { return HType::Tagged(); }
   7753 
   7754   DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
   7755 
   7756  private:
   7757   bool IsDeletable() const override { return true; }
   7758 };
   7759 
   7760 
   7761 class HStoreFrameContext: public HUnaryOperation {
   7762  public:
   7763   DECLARE_INSTRUCTION_FACTORY_P1(HStoreFrameContext, HValue*);
   7764 
   7765   HValue* context() { return OperandAt(0); }
   7766 
   7767   Representation RequiredInputRepresentation(int index) override {
   7768     return Representation::Tagged();
   7769   }
   7770 
   7771   DECLARE_CONCRETE_INSTRUCTION(StoreFrameContext)
   7772  private:
   7773   explicit HStoreFrameContext(HValue* context)
   7774       : HUnaryOperation(context) {
   7775     set_representation(Representation::Tagged());
   7776     SetChangesFlag(kContextSlots);
   7777   }
   7778 };
   7779 
   7780 
   7781 class HAllocateBlockContext: public HTemplateInstruction<2> {
   7782  public:
   7783   DECLARE_INSTRUCTION_FACTORY_P3(HAllocateBlockContext, HValue*,
   7784                                  HValue*, Handle<ScopeInfo>);
   7785   HValue* context() const { return OperandAt(0); }
   7786   HValue* function() const { return OperandAt(1); }
   7787   Handle<ScopeInfo> scope_info() const { return scope_info_; }
   7788 
   7789   Representation RequiredInputRepresentation(int index) override {
   7790     return Representation::Tagged();
   7791   }
   7792 
   7793   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   7794 
   7795   DECLARE_CONCRETE_INSTRUCTION(AllocateBlockContext)
   7796 
   7797  private:
   7798   HAllocateBlockContext(HValue* context,
   7799                         HValue* function,
   7800                         Handle<ScopeInfo> scope_info)
   7801       : scope_info_(scope_info) {
   7802     SetOperandAt(0, context);
   7803     SetOperandAt(1, function);
   7804     set_representation(Representation::Tagged());
   7805   }
   7806 
   7807   Handle<ScopeInfo> scope_info_;
   7808 };
   7809 
   7810 
   7811 
   7812 #undef DECLARE_INSTRUCTION
   7813 #undef DECLARE_CONCRETE_INSTRUCTION
   7814 
   7815 }  // namespace internal
   7816 }  // namespace v8
   7817 
   7818 #endif  // V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_
   7819