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(Allocate)                                 \
     52   V(ApplyArguments)                           \
     53   V(ArgumentsElements)                        \
     54   V(ArgumentsLength)                          \
     55   V(ArgumentsObject)                          \
     56   V(Bitwise)                                  \
     57   V(BlockEntry)                               \
     58   V(BoundsCheck)                              \
     59   V(Branch)                                   \
     60   V(CallWithDescriptor)                       \
     61   V(CallNewArray)                             \
     62   V(CallRuntime)                              \
     63   V(CapturedObject)                           \
     64   V(Change)                                   \
     65   V(CheckArrayBufferNotNeutered)              \
     66   V(CheckHeapObject)                          \
     67   V(CheckInstanceType)                        \
     68   V(CheckMaps)                                \
     69   V(CheckMapValue)                            \
     70   V(CheckSmi)                                 \
     71   V(CheckValue)                               \
     72   V(ClampToUint8)                             \
     73   V(ClassOfTestAndBranch)                     \
     74   V(CompareNumericAndBranch)                  \
     75   V(CompareHoleAndBranch)                     \
     76   V(CompareGeneric)                           \
     77   V(CompareObjectEqAndBranch)                 \
     78   V(CompareMap)                               \
     79   V(Constant)                                 \
     80   V(Context)                                  \
     81   V(DebugBreak)                               \
     82   V(DeclareGlobals)                           \
     83   V(Deoptimize)                               \
     84   V(Div)                                      \
     85   V(DoubleBits)                               \
     86   V(DummyUse)                                 \
     87   V(EnterInlined)                             \
     88   V(EnvironmentMarker)                        \
     89   V(ForceRepresentation)                      \
     90   V(ForInCacheArray)                          \
     91   V(ForInPrepareMap)                          \
     92   V(GetCachedArrayIndex)                      \
     93   V(Goto)                                     \
     94   V(HasCachedArrayIndexAndBranch)             \
     95   V(HasInstanceTypeAndBranch)                 \
     96   V(InnerAllocatedObject)                     \
     97   V(InvokeFunction)                           \
     98   V(HasInPrototypeChainAndBranch)             \
     99   V(IsStringAndBranch)                        \
    100   V(IsSmiAndBranch)                           \
    101   V(IsUndetectableAndBranch)                  \
    102   V(LeaveInlined)                             \
    103   V(LoadContextSlot)                          \
    104   V(LoadFieldByIndex)                         \
    105   V(LoadFunctionPrototype)                    \
    106   V(LoadGlobalGeneric)                        \
    107   V(LoadKeyed)                                \
    108   V(LoadKeyedGeneric)                         \
    109   V(LoadNamedField)                           \
    110   V(LoadNamedGeneric)                         \
    111   V(LoadRoot)                                 \
    112   V(MathFloorOfDiv)                           \
    113   V(MathMinMax)                               \
    114   V(MaybeGrowElements)                        \
    115   V(Mod)                                      \
    116   V(Mul)                                      \
    117   V(OsrEntry)                                 \
    118   V(Parameter)                                \
    119   V(Power)                                    \
    120   V(Prologue)                                 \
    121   V(PushArguments)                            \
    122   V(Return)                                   \
    123   V(Ror)                                      \
    124   V(Sar)                                      \
    125   V(SeqStringGetChar)                         \
    126   V(SeqStringSetChar)                         \
    127   V(Shl)                                      \
    128   V(Shr)                                      \
    129   V(Simulate)                                 \
    130   V(StackCheck)                               \
    131   V(StoreCodeEntry)                           \
    132   V(StoreContextSlot)                         \
    133   V(StoreKeyed)                               \
    134   V(StoreKeyedGeneric)                        \
    135   V(StoreNamedField)                          \
    136   V(StoreNamedGeneric)                        \
    137   V(StringAdd)                                \
    138   V(StringCharCodeAt)                         \
    139   V(StringCharFromCode)                       \
    140   V(StringCompareAndBranch)                   \
    141   V(Sub)                                      \
    142   V(ThisFunction)                             \
    143   V(TransitionElementsKind)                   \
    144   V(TrapAllocationMemento)                    \
    145   V(Typeof)                                   \
    146   V(TypeofIsAndBranch)                        \
    147   V(UnaryMathOperation)                       \
    148   V(UnknownOSRValue)                          \
    149   V(UseConst)                                 \
    150   V(WrapReceiver)
    151 
    152 #define GVN_TRACKED_FLAG_LIST(V)               \
    153   V(NewSpacePromotion)
    154 
    155 #define GVN_UNTRACKED_FLAG_LIST(V)             \
    156   V(ArrayElements)                             \
    157   V(ArrayLengths)                              \
    158   V(StringLengths)                             \
    159   V(BackingStoreFields)                        \
    160   V(Calls)                                     \
    161   V(ContextSlots)                              \
    162   V(DoubleArrayElements)                       \
    163   V(DoubleFields)                              \
    164   V(ElementsKind)                              \
    165   V(ElementsPointer)                           \
    166   V(GlobalVars)                                \
    167   V(InobjectFields)                            \
    168   V(Maps)                                      \
    169   V(OsrEntries)                                \
    170   V(ExternalMemory)                            \
    171   V(StringChars)                               \
    172   V(TypedArrayElements)
    173 
    174 
    175 #define DECLARE_ABSTRACT_INSTRUCTION(type)     \
    176   bool Is##type() const final { return true; } \
    177   static H##type* cast(HValue* value) {        \
    178     DCHECK(value->Is##type());                 \
    179     return reinterpret_cast<H##type*>(value);  \
    180   }
    181 
    182 
    183 #define DECLARE_CONCRETE_INSTRUCTION(type)                      \
    184   LInstruction* CompileToLithium(LChunkBuilder* builder) final; \
    185   static H##type* cast(HValue* value) {                         \
    186     DCHECK(value->Is##type());                                  \
    187     return reinterpret_cast<H##type*>(value);                   \
    188   }                                                             \
    189   Opcode opcode() const final { return HValue::k##type; }
    190 
    191 
    192 enum PropertyAccessType { LOAD, STORE };
    193 
    194 
    195 class Range final : public ZoneObject {
    196  public:
    197   Range()
    198       : lower_(kMinInt),
    199         upper_(kMaxInt),
    200         next_(NULL),
    201         can_be_minus_zero_(false) { }
    202 
    203   Range(int32_t lower, int32_t upper)
    204       : lower_(lower),
    205         upper_(upper),
    206         next_(NULL),
    207         can_be_minus_zero_(false) { }
    208 
    209   int32_t upper() const { return upper_; }
    210   int32_t lower() const { return lower_; }
    211   Range* next() const { return next_; }
    212   Range* CopyClearLower(Zone* zone) const {
    213     return new(zone) Range(kMinInt, upper_);
    214   }
    215   Range* CopyClearUpper(Zone* zone) const {
    216     return new(zone) Range(lower_, kMaxInt);
    217   }
    218   Range* Copy(Zone* zone) const {
    219     Range* result = new(zone) Range(lower_, upper_);
    220     result->set_can_be_minus_zero(CanBeMinusZero());
    221     return result;
    222   }
    223   int32_t Mask() const;
    224   void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
    225   bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
    226   bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
    227   bool CanBeNegative() const { return lower_ < 0; }
    228   bool CanBePositive() const { return upper_ > 0; }
    229   bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
    230   bool IsMostGeneric() const {
    231     return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
    232   }
    233   bool IsInSmiRange() const {
    234     return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
    235   }
    236   void ClampToSmi() {
    237     lower_ = Max(lower_, Smi::kMinValue);
    238     upper_ = Min(upper_, Smi::kMaxValue);
    239   }
    240   void KeepOrder();
    241 #ifdef DEBUG
    242   void Verify() const;
    243 #endif
    244 
    245   void StackUpon(Range* other) {
    246     Intersect(other);
    247     next_ = other;
    248   }
    249 
    250   void Intersect(Range* other);
    251   void Union(Range* other);
    252   void CombinedMax(Range* other);
    253   void CombinedMin(Range* other);
    254 
    255   void AddConstant(int32_t value);
    256   void Sar(int32_t value);
    257   void Shl(int32_t value);
    258   bool AddAndCheckOverflow(const Representation& r, Range* other);
    259   bool SubAndCheckOverflow(const Representation& r, Range* other);
    260   bool MulAndCheckOverflow(const Representation& r, Range* other);
    261 
    262  private:
    263   int32_t lower_;
    264   int32_t upper_;
    265   Range* next_;
    266   bool can_be_minus_zero_;
    267 };
    268 
    269 
    270 class HUseListNode: public ZoneObject {
    271  public:
    272   HUseListNode(HValue* value, int index, HUseListNode* tail)
    273       : tail_(tail), value_(value), index_(index) {
    274   }
    275 
    276   HUseListNode* tail();
    277   HValue* value() const { return value_; }
    278   int index() const { return index_; }
    279 
    280   void set_tail(HUseListNode* list) { tail_ = list; }
    281 
    282 #ifdef DEBUG
    283   void Zap() {
    284     tail_ = reinterpret_cast<HUseListNode*>(1);
    285     value_ = NULL;
    286     index_ = -1;
    287   }
    288 #endif
    289 
    290  private:
    291   HUseListNode* tail_;
    292   HValue* value_;
    293   int index_;
    294 };
    295 
    296 
    297 // We reuse use list nodes behind the scenes as uses are added and deleted.
    298 // This class is the safe way to iterate uses while deleting them.
    299 class HUseIterator final BASE_EMBEDDED {
    300  public:
    301   bool Done() { return current_ == NULL; }
    302   void Advance();
    303 
    304   HValue* value() {
    305     DCHECK(!Done());
    306     return value_;
    307   }
    308 
    309   int index() {
    310     DCHECK(!Done());
    311     return index_;
    312   }
    313 
    314  private:
    315   explicit HUseIterator(HUseListNode* head);
    316 
    317   HUseListNode* current_;
    318   HUseListNode* next_;
    319   HValue* value_;
    320   int index_;
    321 
    322   friend class HValue;
    323 };
    324 
    325 
    326 // All tracked flags should appear before untracked ones.
    327 enum GVNFlag {
    328   // Declare global value numbering flags.
    329 #define DECLARE_FLAG(Type) k##Type,
    330   GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
    331   GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
    332 #undef DECLARE_FLAG
    333 #define COUNT_FLAG(Type) + 1
    334   kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG),
    335   kNumberOfUntrackedSideEffects = 0 GVN_UNTRACKED_FLAG_LIST(COUNT_FLAG),
    336 #undef COUNT_FLAG
    337   kNumberOfFlags = kNumberOfTrackedSideEffects + kNumberOfUntrackedSideEffects
    338 };
    339 
    340 
    341 static inline GVNFlag GVNFlagFromInt(int i) {
    342   DCHECK(i >= 0);
    343   DCHECK(i < kNumberOfFlags);
    344   return static_cast<GVNFlag>(i);
    345 }
    346 
    347 
    348 class DecompositionResult final BASE_EMBEDDED {
    349  public:
    350   DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
    351 
    352   HValue* base() { return base_; }
    353   int offset() { return offset_; }
    354   int scale() { return scale_; }
    355 
    356   bool Apply(HValue* other_base, int other_offset, int other_scale = 0) {
    357     if (base_ == NULL) {
    358       base_ = other_base;
    359       offset_ = other_offset;
    360       scale_ = other_scale;
    361       return true;
    362     } else {
    363       if (scale_ == 0) {
    364         base_ = other_base;
    365         offset_ += other_offset;
    366         scale_ = other_scale;
    367         return true;
    368       } else {
    369         return false;
    370       }
    371     }
    372   }
    373 
    374   void SwapValues(HValue** other_base, int* other_offset, int* other_scale) {
    375     swap(&base_, other_base);
    376     swap(&offset_, other_offset);
    377     swap(&scale_, other_scale);
    378   }
    379 
    380  private:
    381   template <class T> void swap(T* a, T* b) {
    382     T c(*a);
    383     *a = *b;
    384     *b = c;
    385   }
    386 
    387   HValue* base_;
    388   int offset_;
    389   int scale_;
    390 };
    391 
    392 
    393 typedef EnumSet<GVNFlag, int32_t> GVNFlagSet;
    394 
    395 
    396 class HValue : public ZoneObject {
    397  public:
    398   static const int kNoNumber = -1;
    399 
    400   enum Flag {
    401     kFlexibleRepresentation,
    402     kCannotBeTagged,
    403     // Participate in Global Value Numbering, i.e. elimination of
    404     // unnecessary recomputations. If an instruction sets this flag, it must
    405     // implement DataEquals(), which will be used to determine if other
    406     // occurrences of the instruction are indeed the same.
    407     kUseGVN,
    408     // Track instructions that are dominating side effects. If an instruction
    409     // sets this flag, it must implement HandleSideEffectDominator() and should
    410     // indicate which side effects to track by setting GVN flags.
    411     kTrackSideEffectDominators,
    412     kCanOverflow,
    413     kBailoutOnMinusZero,
    414     kCanBeDivByZero,
    415     kLeftCanBeMinInt,
    416     kLeftCanBeNegative,
    417     kLeftCanBePositive,
    418     kAllowUndefinedAsNaN,
    419     kIsArguments,
    420     kTruncatingToInt32,
    421     kAllUsesTruncatingToInt32,
    422     kTruncatingToSmi,
    423     kAllUsesTruncatingToSmi,
    424     // Set after an instruction is killed.
    425     kIsDead,
    426     // Instructions that are allowed to produce full range unsigned integer
    427     // values are marked with kUint32 flag. If arithmetic shift or a load from
    428     // EXTERNAL_UINT32_ELEMENTS array is not marked with this flag
    429     // it will deoptimize if result does not fit into signed integer range.
    430     // HGraph::ComputeSafeUint32Operations is responsible for setting this
    431     // flag.
    432     kUint32,
    433     kHasNoObservableSideEffects,
    434     // Indicates an instruction shouldn't be replaced by optimization, this flag
    435     // is useful to set in cases where recomputing a value is cheaper than
    436     // extending the value's live range and spilling it.
    437     kCantBeReplaced,
    438     // Indicates the instruction is live during dead code elimination.
    439     kIsLive,
    440 
    441     // HEnvironmentMarkers are deleted before dead code
    442     // elimination takes place, so they can repurpose the kIsLive flag:
    443     kEndsLiveRange = kIsLive,
    444 
    445     // TODO(everyone): Don't forget to update this!
    446     kLastFlag = kIsLive
    447   };
    448 
    449   STATIC_ASSERT(kLastFlag < kBitsPerInt);
    450 
    451   static HValue* cast(HValue* value) { return value; }
    452 
    453   enum Opcode {
    454     // Declare a unique enum value for each hydrogen instruction.
    455   #define DECLARE_OPCODE(type) k##type,
    456     HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
    457     kPhi
    458   #undef DECLARE_OPCODE
    459   };
    460   virtual Opcode opcode() const = 0;
    461 
    462   // Declare a non-virtual predicates for each concrete HInstruction or HValue.
    463   #define DECLARE_PREDICATE(type) \
    464     bool Is##type() const { return opcode() == k##type; }
    465     HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
    466   #undef DECLARE_PREDICATE
    467     bool IsPhi() const { return opcode() == kPhi; }
    468 
    469   // Declare virtual predicates for abstract HInstruction or HValue
    470   #define DECLARE_PREDICATE(type) \
    471     virtual bool Is##type() const { return false; }
    472     HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
    473   #undef DECLARE_PREDICATE
    474 
    475   bool IsBitwiseBinaryShift() {
    476     return IsShl() || IsShr() || IsSar();
    477   }
    478 
    479   explicit HValue(HType type = HType::Tagged())
    480       : block_(NULL),
    481         id_(kNoNumber),
    482         type_(type),
    483         use_list_(NULL),
    484         range_(NULL),
    485 #ifdef DEBUG
    486         range_poisoned_(false),
    487 #endif
    488         flags_(0) {}
    489   virtual ~HValue() {}
    490 
    491   virtual SourcePosition position() const { return SourcePosition::Unknown(); }
    492   virtual SourcePosition operand_position(int index) const {
    493     return position();
    494   }
    495 
    496   HBasicBlock* block() const { return block_; }
    497   void SetBlock(HBasicBlock* block);
    498 
    499   // Note: Never call this method for an unlinked value.
    500   Isolate* isolate() const;
    501 
    502   int id() const { return id_; }
    503   void set_id(int id) { id_ = id; }
    504 
    505   HUseIterator uses() const { return HUseIterator(use_list_); }
    506 
    507   virtual bool EmitAtUses() { return false; }
    508 
    509   Representation representation() const { return representation_; }
    510   void ChangeRepresentation(Representation r) {
    511     DCHECK(CheckFlag(kFlexibleRepresentation));
    512     DCHECK(!CheckFlag(kCannotBeTagged) || !r.IsTagged());
    513     RepresentationChanged(r);
    514     representation_ = r;
    515     if (r.IsTagged()) {
    516       // Tagged is the bottom of the lattice, don't go any further.
    517       ClearFlag(kFlexibleRepresentation);
    518     }
    519   }
    520   virtual void AssumeRepresentation(Representation r);
    521 
    522   virtual Representation KnownOptimalRepresentation() {
    523     Representation r = representation();
    524     if (r.IsTagged()) {
    525       HType t = type();
    526       if (t.IsSmi()) return Representation::Smi();
    527       if (t.IsHeapNumber()) return Representation::Double();
    528       if (t.IsHeapObject()) return r;
    529       return Representation::None();
    530     }
    531     return r;
    532   }
    533 
    534   HType type() const { return type_; }
    535   void set_type(HType new_type) {
    536     DCHECK(new_type.IsSubtypeOf(type_));
    537     type_ = new_type;
    538   }
    539 
    540   // There are HInstructions that do not really change a value, they
    541   // only add pieces of information to it (like bounds checks, map checks,
    542   // smi checks...).
    543   // We call these instructions "informative definitions", or "iDef".
    544   // One of the iDef operands is special because it is the value that is
    545   // "transferred" to the output, we call it the "redefined operand".
    546   // If an HValue is an iDef it must override RedefinedOperandIndex() so that
    547   // it does not return kNoRedefinedOperand;
    548   static const int kNoRedefinedOperand = -1;
    549   virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
    550   bool IsInformativeDefinition() {
    551     return RedefinedOperandIndex() != kNoRedefinedOperand;
    552   }
    553   HValue* RedefinedOperand() {
    554     int index = RedefinedOperandIndex();
    555     return index == kNoRedefinedOperand ? NULL : OperandAt(index);
    556   }
    557 
    558   bool CanReplaceWithDummyUses();
    559 
    560   virtual int argument_delta() const { return 0; }
    561 
    562   // A purely informative definition is an idef that will not emit code and
    563   // should therefore be removed from the graph in the RestoreActualValues
    564   // phase (so that live ranges will be shorter).
    565   virtual bool IsPurelyInformativeDefinition() { return false; }
    566 
    567   // This method must always return the original HValue SSA definition,
    568   // regardless of any chain of iDefs of this value.
    569   HValue* ActualValue() {
    570     HValue* value = this;
    571     int index;
    572     while ((index = value->RedefinedOperandIndex()) != kNoRedefinedOperand) {
    573       value = value->OperandAt(index);
    574     }
    575     return value;
    576   }
    577 
    578   bool IsInteger32Constant();
    579   int32_t GetInteger32Constant();
    580   bool EqualsInteger32Constant(int32_t value);
    581 
    582   bool IsDefinedAfter(HBasicBlock* other) const;
    583 
    584   // Operands.
    585   virtual int OperandCount() const = 0;
    586   virtual HValue* OperandAt(int index) const = 0;
    587   void SetOperandAt(int index, HValue* value);
    588 
    589   void DeleteAndReplaceWith(HValue* other);
    590   void ReplaceAllUsesWith(HValue* other);
    591   bool HasNoUses() const { return use_list_ == NULL; }
    592   bool HasOneUse() const {
    593     return use_list_ != NULL && use_list_->tail() == NULL;
    594   }
    595   bool HasMultipleUses() const {
    596     return use_list_ != NULL && use_list_->tail() != NULL;
    597   }
    598   int UseCount() const;
    599 
    600   // Mark this HValue as dead and to be removed from other HValues' use lists.
    601   void Kill();
    602 
    603   int flags() const { return flags_; }
    604   void SetFlag(Flag f) { flags_ |= (1 << f); }
    605   void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
    606   bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
    607   void CopyFlag(Flag f, HValue* other) {
    608     if (other->CheckFlag(f)) SetFlag(f);
    609   }
    610 
    611   // Returns true if the flag specified is set for all uses, false otherwise.
    612   bool CheckUsesForFlag(Flag f) const;
    613   // Same as before and the first one without the flag is returned in value.
    614   bool CheckUsesForFlag(Flag f, HValue** value) const;
    615   // Returns true if the flag specified is set for all uses, and this set
    616   // of uses is non-empty.
    617   bool HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const;
    618 
    619   GVNFlagSet ChangesFlags() const { return changes_flags_; }
    620   GVNFlagSet DependsOnFlags() const { return depends_on_flags_; }
    621   void SetChangesFlag(GVNFlag f) { changes_flags_.Add(f); }
    622   void SetDependsOnFlag(GVNFlag f) { depends_on_flags_.Add(f); }
    623   void ClearChangesFlag(GVNFlag f) { changes_flags_.Remove(f); }
    624   void ClearDependsOnFlag(GVNFlag f) { depends_on_flags_.Remove(f); }
    625   bool CheckChangesFlag(GVNFlag f) const {
    626     return changes_flags_.Contains(f);
    627   }
    628   bool CheckDependsOnFlag(GVNFlag f) const {
    629     return depends_on_flags_.Contains(f);
    630   }
    631   void SetAllSideEffects() { changes_flags_.Add(AllSideEffectsFlagSet()); }
    632   void ClearAllSideEffects() {
    633     changes_flags_.Remove(AllSideEffectsFlagSet());
    634   }
    635   bool HasSideEffects() const {
    636     return changes_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
    637   }
    638   bool HasObservableSideEffects() const {
    639     return !CheckFlag(kHasNoObservableSideEffects) &&
    640         changes_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
    641   }
    642 
    643   GVNFlagSet SideEffectFlags() const {
    644     GVNFlagSet result = ChangesFlags();
    645     result.Intersect(AllSideEffectsFlagSet());
    646     return result;
    647   }
    648 
    649   GVNFlagSet ObservableChangesFlags() const {
    650     GVNFlagSet result = ChangesFlags();
    651     result.Intersect(AllObservableSideEffectsFlagSet());
    652     return result;
    653   }
    654 
    655   Range* range() const {
    656     DCHECK(!range_poisoned_);
    657     return range_;
    658   }
    659   bool HasRange() const {
    660     DCHECK(!range_poisoned_);
    661     return range_ != NULL;
    662   }
    663 #ifdef DEBUG
    664   void PoisonRange() { range_poisoned_ = true; }
    665 #endif
    666   void AddNewRange(Range* r, Zone* zone);
    667   void RemoveLastAddedRange();
    668   void ComputeInitialRange(Zone* zone);
    669 
    670   // Escape analysis helpers.
    671   virtual bool HasEscapingOperandAt(int index) { return true; }
    672   virtual bool HasOutOfBoundsAccess(int size) { return false; }
    673 
    674   // Representation helpers.
    675   virtual Representation observed_input_representation(int index) {
    676     return Representation::None();
    677   }
    678   virtual Representation RequiredInputRepresentation(int index) = 0;
    679   virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
    680 
    681   // This gives the instruction an opportunity to replace itself with an
    682   // instruction that does the same in some better way.  To replace an
    683   // instruction with a new one, first add the new instruction to the graph,
    684   // then return it.  Return NULL to have the instruction deleted.
    685   virtual HValue* Canonicalize() { return this; }
    686 
    687   bool Equals(HValue* other);
    688   virtual intptr_t Hashcode();
    689 
    690   // Compute unique ids upfront that is safe wrt GC and concurrent compilation.
    691   virtual void FinalizeUniqueness() { }
    692 
    693   // Printing support.
    694   virtual std::ostream& PrintTo(std::ostream& os) const = 0;  // NOLINT
    695 
    696   const char* Mnemonic() const;
    697 
    698   // Type information helpers.
    699   bool HasMonomorphicJSObjectType();
    700 
    701   // TODO(mstarzinger): For now instructions can override this function to
    702   // specify statically known types, once HType can convey more information
    703   // it should be based on the HType.
    704   virtual Handle<Map> GetMonomorphicJSObjectMap() { return Handle<Map>(); }
    705 
    706   // Updated the inferred type of this instruction and returns true if
    707   // it has changed.
    708   bool UpdateInferredType();
    709 
    710   virtual HType CalculateInferredType();
    711 
    712   // This function must be overridden for instructions which have the
    713   // kTrackSideEffectDominators flag set, to track instructions that are
    714   // dominating side effects.
    715   // It returns true if it removed an instruction which had side effects.
    716   virtual bool HandleSideEffectDominator(GVNFlag side_effect,
    717                                          HValue* dominator) {
    718     UNREACHABLE();
    719     return false;
    720   }
    721 
    722   // Check if this instruction has some reason that prevents elimination.
    723   bool CannotBeEliminated() const {
    724     return HasObservableSideEffects() || !IsDeletable();
    725   }
    726 
    727 #ifdef DEBUG
    728   virtual void Verify() = 0;
    729 #endif
    730 
    731   // Returns true conservatively if the program might be able to observe a
    732   // ToString() operation on this value.
    733   bool ToStringCanBeObserved() const {
    734     return ToStringOrToNumberCanBeObserved();
    735   }
    736 
    737   // Returns true conservatively if the program might be able to observe a
    738   // ToNumber() operation on this value.
    739   bool ToNumberCanBeObserved() const {
    740     return ToStringOrToNumberCanBeObserved();
    741   }
    742 
    743   MinusZeroMode GetMinusZeroMode() {
    744     return CheckFlag(kBailoutOnMinusZero)
    745         ? FAIL_ON_MINUS_ZERO : TREAT_MINUS_ZERO_AS_ZERO;
    746   }
    747 
    748  protected:
    749   // This function must be overridden for instructions with flag kUseGVN, to
    750   // compare the non-Operand parts of the instruction.
    751   virtual bool DataEquals(HValue* other) {
    752     UNREACHABLE();
    753     return false;
    754   }
    755 
    756   bool ToStringOrToNumberCanBeObserved() const {
    757     if (type().IsTaggedPrimitive()) return false;
    758     if (type().IsJSReceiver()) return true;
    759     return !representation().IsSmiOrInteger32() && !representation().IsDouble();
    760   }
    761 
    762   virtual Representation RepresentationFromInputs() {
    763     return representation();
    764   }
    765   virtual Representation RepresentationFromUses();
    766   Representation RepresentationFromUseRequirements();
    767   bool HasNonSmiUse();
    768   virtual void UpdateRepresentation(Representation new_rep,
    769                                     HInferRepresentationPhase* h_infer,
    770                                     const char* reason);
    771   void AddDependantsToWorklist(HInferRepresentationPhase* h_infer);
    772 
    773   virtual void RepresentationChanged(Representation to) { }
    774 
    775   virtual Range* InferRange(Zone* zone);
    776   virtual void DeleteFromGraph() = 0;
    777   virtual void InternalSetOperandAt(int index, HValue* value) = 0;
    778   void clear_block() {
    779     DCHECK(block_ != NULL);
    780     block_ = NULL;
    781   }
    782 
    783   void set_representation(Representation r) {
    784     DCHECK(representation_.IsNone() && !r.IsNone());
    785     representation_ = r;
    786   }
    787 
    788   static GVNFlagSet AllFlagSet() {
    789     GVNFlagSet result;
    790 #define ADD_FLAG(Type) result.Add(k##Type);
    791   GVN_TRACKED_FLAG_LIST(ADD_FLAG)
    792   GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
    793 #undef ADD_FLAG
    794     return result;
    795   }
    796 
    797   // A flag mask to mark an instruction as having arbitrary side effects.
    798   static GVNFlagSet AllSideEffectsFlagSet() {
    799     GVNFlagSet result = AllFlagSet();
    800     result.Remove(kOsrEntries);
    801     return result;
    802   }
    803   friend std::ostream& operator<<(std::ostream& os, const ChangesOf& v);
    804 
    805   // A flag mask of all side effects that can make observable changes in
    806   // an executing program (i.e. are not safe to repeat, move or remove);
    807   static GVNFlagSet AllObservableSideEffectsFlagSet() {
    808     GVNFlagSet result = AllFlagSet();
    809     result.Remove(kNewSpacePromotion);
    810     result.Remove(kElementsKind);
    811     result.Remove(kElementsPointer);
    812     result.Remove(kMaps);
    813     return result;
    814   }
    815 
    816   // Remove the matching use from the use list if present.  Returns the
    817   // removed list node or NULL.
    818   HUseListNode* RemoveUse(HValue* value, int index);
    819 
    820   void RegisterUse(int index, HValue* new_value);
    821 
    822   HBasicBlock* block_;
    823 
    824   // The id of this instruction in the hydrogen graph, assigned when first
    825   // added to the graph. Reflects creation order.
    826   int id_;
    827 
    828   Representation representation_;
    829   HType type_;
    830   HUseListNode* use_list_;
    831   Range* range_;
    832 #ifdef DEBUG
    833   bool range_poisoned_;
    834 #endif
    835   int flags_;
    836   GVNFlagSet changes_flags_;
    837   GVNFlagSet depends_on_flags_;
    838 
    839  private:
    840   virtual bool IsDeletable() const { return false; }
    841 
    842   DISALLOW_COPY_AND_ASSIGN(HValue);
    843 };
    844 
    845 // Support for printing various aspects of an HValue.
    846 struct NameOf {
    847   explicit NameOf(const HValue* const v) : value(v) {}
    848   const HValue* value;
    849 };
    850 
    851 
    852 struct TypeOf {
    853   explicit TypeOf(const HValue* const v) : value(v) {}
    854   const HValue* value;
    855 };
    856 
    857 
    858 struct ChangesOf {
    859   explicit ChangesOf(const HValue* const v) : value(v) {}
    860   const HValue* value;
    861 };
    862 
    863 
    864 std::ostream& operator<<(std::ostream& os, const HValue& v);
    865 std::ostream& operator<<(std::ostream& os, const NameOf& v);
    866 std::ostream& operator<<(std::ostream& os, const TypeOf& v);
    867 std::ostream& operator<<(std::ostream& os, const ChangesOf& v);
    868 
    869 
    870 #define DECLARE_INSTRUCTION_FACTORY_P0(I)                        \
    871   static I* New(Isolate* isolate, Zone* zone, HValue* context) { \
    872     return new (zone) I();                                       \
    873   }
    874 
    875 #define DECLARE_INSTRUCTION_FACTORY_P1(I, P1)                           \
    876   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1) { \
    877     return new (zone) I(p1);                                            \
    878   }
    879 
    880 #define DECLARE_INSTRUCTION_FACTORY_P2(I, P1, P2)                              \
    881   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2) { \
    882     return new (zone) I(p1, p2);                                               \
    883   }
    884 
    885 #define DECLARE_INSTRUCTION_FACTORY_P3(I, P1, P2, P3)                        \
    886   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
    887                 P3 p3) {                                                     \
    888     return new (zone) I(p1, p2, p3);                                         \
    889   }
    890 
    891 #define DECLARE_INSTRUCTION_FACTORY_P4(I, P1, P2, P3, P4)                    \
    892   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
    893                 P3 p3, P4 p4) {                                              \
    894     return new (zone) I(p1, p2, p3, p4);                                     \
    895   }
    896 
    897 #define DECLARE_INSTRUCTION_FACTORY_P5(I, P1, P2, P3, P4, P5)                \
    898   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
    899                 P3 p3, P4 p4, P5 p5) {                                       \
    900     return new (zone) I(p1, p2, p3, p4, p5);                                 \
    901   }
    902 
    903 #define DECLARE_INSTRUCTION_FACTORY_P6(I, P1, P2, P3, P4, P5, P6)            \
    904   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
    905                 P3 p3, P4 p4, P5 p5, P6 p6) {                                \
    906     return new (zone) I(p1, p2, p3, p4, p5, p6);                             \
    907   }
    908 
    909 #define DECLARE_INSTRUCTION_FACTORY_P7(I, P1, P2, P3, P4, P5, P6, P7)        \
    910   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
    911                 P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {                         \
    912     return new (zone) I(p1, p2, p3, p4, p5, p6, p7);                         \
    913   }
    914 
    915 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(I)           \
    916   static I* New(Isolate* isolate, Zone* zone, HValue* context) { \
    917     return new (zone) I(context);                                \
    918   }
    919 
    920 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(I, P1)              \
    921   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1) { \
    922     return new (zone) I(context, p1);                                   \
    923   }
    924 
    925 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(I, P1, P2)                 \
    926   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2) { \
    927     return new (zone) I(context, p1, p2);                                      \
    928   }
    929 
    930 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(I, P1, P2, P3)           \
    931   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
    932                 P3 p3) {                                                     \
    933     return new (zone) I(context, p1, p2, p3);                                \
    934   }
    935 
    936 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(I, P1, P2, P3, P4)       \
    937   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
    938                 P3 p3, P4 p4) {                                              \
    939     return new (zone) I(context, p1, p2, p3, p4);                            \
    940   }
    941 
    942 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(I, P1, P2, P3, P4, P5)   \
    943   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
    944                 P3 p3, P4 p4, P5 p5) {                                       \
    945     return new (zone) I(context, p1, p2, p3, p4, p5);                        \
    946   }
    947 
    948 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(I, P1, P2, P3, P4, P5, P6) \
    949   static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2,   \
    950                 P3 p3, P4 p4, P5 p5, P6 p6) {                                  \
    951     return new (zone) I(context, p1, p2, p3, p4, p5, p6);                      \
    952   }
    953 
    954 
    955 // A helper class to represent per-operand position information attached to
    956 // the HInstruction in the compact form. Uses tagging to distinguish between
    957 // case when only instruction's position is available and case when operands'
    958 // positions are also available.
    959 // In the first case it contains intruction's position as a tagged value.
    960 // In the second case it points to an array which contains instruction's
    961 // position and operands' positions.
    962 class HPositionInfo {
    963  public:
    964   explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { }
    965 
    966   SourcePosition position() const {
    967     if (has_operand_positions()) {
    968       return operand_positions()[kInstructionPosIndex];
    969     }
    970     return SourcePosition::FromRaw(static_cast<int>(UntagPosition(data_)));
    971   }
    972 
    973   void set_position(SourcePosition pos) {
    974     if (has_operand_positions()) {
    975       operand_positions()[kInstructionPosIndex] = pos;
    976     } else {
    977       data_ = TagPosition(pos.raw());
    978     }
    979   }
    980 
    981   void ensure_storage_for_operand_positions(Zone* zone, int operand_count) {
    982     if (has_operand_positions()) {
    983       return;
    984     }
    985 
    986     const int length = kFirstOperandPosIndex + operand_count;
    987     SourcePosition* positions = zone->NewArray<SourcePosition>(length);
    988     for (int i = 0; i < length; i++) {
    989       positions[i] = SourcePosition::Unknown();
    990     }
    991 
    992     const SourcePosition pos = position();
    993     data_ = reinterpret_cast<intptr_t>(positions);
    994     set_position(pos);
    995 
    996     DCHECK(has_operand_positions());
    997   }
    998 
    999   SourcePosition operand_position(int idx) const {
   1000     if (!has_operand_positions()) {
   1001       return position();
   1002     }
   1003     return *operand_position_slot(idx);
   1004   }
   1005 
   1006   void set_operand_position(int idx, SourcePosition pos) {
   1007     *operand_position_slot(idx) = pos;
   1008   }
   1009 
   1010  private:
   1011   static const intptr_t kInstructionPosIndex = 0;
   1012   static const intptr_t kFirstOperandPosIndex = 1;
   1013 
   1014   SourcePosition* operand_position_slot(int idx) const {
   1015     DCHECK(has_operand_positions());
   1016     return &(operand_positions()[kFirstOperandPosIndex + idx]);
   1017   }
   1018 
   1019   bool has_operand_positions() const {
   1020     return !IsTaggedPosition(data_);
   1021   }
   1022 
   1023   SourcePosition* operand_positions() const {
   1024     DCHECK(has_operand_positions());
   1025     return reinterpret_cast<SourcePosition*>(data_);
   1026   }
   1027 
   1028   static const intptr_t kPositionTag = 1;
   1029   static const intptr_t kPositionShift = 1;
   1030   static bool IsTaggedPosition(intptr_t val) {
   1031     return (val & kPositionTag) != 0;
   1032   }
   1033   static intptr_t UntagPosition(intptr_t val) {
   1034     DCHECK(IsTaggedPosition(val));
   1035     return val >> kPositionShift;
   1036   }
   1037   static intptr_t TagPosition(intptr_t val) {
   1038     const intptr_t result = (val << kPositionShift) | kPositionTag;
   1039     DCHECK(UntagPosition(result) == val);
   1040     return result;
   1041   }
   1042 
   1043   intptr_t data_;
   1044 };
   1045 
   1046 
   1047 class HInstruction : public HValue {
   1048  public:
   1049   HInstruction* next() const { return next_; }
   1050   HInstruction* previous() const { return previous_; }
   1051 
   1052   std::ostream& PrintTo(std::ostream& os) const override;          // NOLINT
   1053   virtual std::ostream& PrintDataTo(std::ostream& os) const;       // NOLINT
   1054 
   1055   bool IsLinked() const { return block() != NULL; }
   1056   void Unlink();
   1057 
   1058   void InsertBefore(HInstruction* next);
   1059 
   1060   template<class T> T* Prepend(T* instr) {
   1061     instr->InsertBefore(this);
   1062     return instr;
   1063   }
   1064 
   1065   void InsertAfter(HInstruction* previous);
   1066 
   1067   template<class T> T* Append(T* instr) {
   1068     instr->InsertAfter(this);
   1069     return instr;
   1070   }
   1071 
   1072   // The position is a write-once variable.
   1073   SourcePosition position() const override {
   1074     return SourcePosition(position_.position());
   1075   }
   1076   bool has_position() const {
   1077     return !position().IsUnknown();
   1078   }
   1079   void set_position(SourcePosition position) {
   1080     DCHECK(!has_position());
   1081     DCHECK(!position.IsUnknown());
   1082     position_.set_position(position);
   1083   }
   1084 
   1085   SourcePosition operand_position(int index) const override {
   1086     const SourcePosition pos = position_.operand_position(index);
   1087     return pos.IsUnknown() ? position() : pos;
   1088   }
   1089   void set_operand_position(Zone* zone, int index, SourcePosition pos) {
   1090     DCHECK(0 <= index && index < OperandCount());
   1091     position_.ensure_storage_for_operand_positions(zone, OperandCount());
   1092     position_.set_operand_position(index, pos);
   1093   }
   1094 
   1095   bool Dominates(HInstruction* other);
   1096   bool CanTruncateToSmi() const { return CheckFlag(kTruncatingToSmi); }
   1097   bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
   1098 
   1099   virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
   1100 
   1101 #ifdef DEBUG
   1102   void Verify() override;
   1103 #endif
   1104 
   1105   bool CanDeoptimize();
   1106 
   1107   virtual bool HasStackCheck() { return false; }
   1108 
   1109   DECLARE_ABSTRACT_INSTRUCTION(Instruction)
   1110 
   1111  protected:
   1112   explicit HInstruction(HType type = HType::Tagged())
   1113       : HValue(type),
   1114         next_(NULL),
   1115         previous_(NULL),
   1116         position_(RelocInfo::kNoPosition) {
   1117     SetDependsOnFlag(kOsrEntries);
   1118   }
   1119 
   1120   void DeleteFromGraph() override { Unlink(); }
   1121 
   1122  private:
   1123   void InitializeAsFirst(HBasicBlock* block) {
   1124     DCHECK(!IsLinked());
   1125     SetBlock(block);
   1126   }
   1127 
   1128   HInstruction* next_;
   1129   HInstruction* previous_;
   1130   HPositionInfo position_;
   1131 
   1132   friend class HBasicBlock;
   1133 };
   1134 
   1135 
   1136 template<int V>
   1137 class HTemplateInstruction : public HInstruction {
   1138  public:
   1139   int OperandCount() const final { return V; }
   1140   HValue* OperandAt(int i) const final { return inputs_[i]; }
   1141 
   1142  protected:
   1143   explicit HTemplateInstruction(HType type = HType::Tagged())
   1144       : HInstruction(type) {}
   1145 
   1146   void InternalSetOperandAt(int i, HValue* value) final { inputs_[i] = value; }
   1147 
   1148  private:
   1149   EmbeddedContainer<HValue*, V> inputs_;
   1150 };
   1151 
   1152 
   1153 class HControlInstruction : public HInstruction {
   1154  public:
   1155   virtual HBasicBlock* SuccessorAt(int i) const = 0;
   1156   virtual int SuccessorCount() const = 0;
   1157   virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
   1158 
   1159   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1160 
   1161   virtual bool KnownSuccessorBlock(HBasicBlock** block) {
   1162     *block = NULL;
   1163     return false;
   1164   }
   1165 
   1166   HBasicBlock* FirstSuccessor() {
   1167     return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
   1168   }
   1169   HBasicBlock* SecondSuccessor() {
   1170     return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
   1171   }
   1172 
   1173   void Not() {
   1174     HBasicBlock* swap = SuccessorAt(0);
   1175     SetSuccessorAt(0, SuccessorAt(1));
   1176     SetSuccessorAt(1, swap);
   1177   }
   1178 
   1179   DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
   1180 };
   1181 
   1182 
   1183 class HSuccessorIterator final BASE_EMBEDDED {
   1184  public:
   1185   explicit HSuccessorIterator(const HControlInstruction* instr)
   1186       : instr_(instr), current_(0) {}
   1187 
   1188   bool Done() { return current_ >= instr_->SuccessorCount(); }
   1189   HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
   1190   void Advance() { current_++; }
   1191 
   1192  private:
   1193   const HControlInstruction* instr_;
   1194   int current_;
   1195 };
   1196 
   1197 
   1198 template<int S, int V>
   1199 class HTemplateControlInstruction : public HControlInstruction {
   1200  public:
   1201   int SuccessorCount() const override { return S; }
   1202   HBasicBlock* SuccessorAt(int i) const override { return successors_[i]; }
   1203   void SetSuccessorAt(int i, HBasicBlock* block) override {
   1204     successors_[i] = block;
   1205   }
   1206 
   1207   int OperandCount() const override { return V; }
   1208   HValue* OperandAt(int i) const override { return inputs_[i]; }
   1209 
   1210 
   1211  protected:
   1212   void InternalSetOperandAt(int i, HValue* value) override {
   1213     inputs_[i] = value;
   1214   }
   1215 
   1216  private:
   1217   EmbeddedContainer<HBasicBlock*, S> successors_;
   1218   EmbeddedContainer<HValue*, V> inputs_;
   1219 };
   1220 
   1221 
   1222 class HBlockEntry final : public HTemplateInstruction<0> {
   1223  public:
   1224   Representation RequiredInputRepresentation(int index) override {
   1225     return Representation::None();
   1226   }
   1227 
   1228   DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
   1229 };
   1230 
   1231 
   1232 class HDummyUse final : public HTemplateInstruction<1> {
   1233  public:
   1234   explicit HDummyUse(HValue* value)
   1235       : HTemplateInstruction<1>(HType::Smi()) {
   1236     SetOperandAt(0, value);
   1237     // Pretend to be a Smi so that the HChange instructions inserted
   1238     // before any use generate as little code as possible.
   1239     set_representation(Representation::Tagged());
   1240   }
   1241 
   1242   HValue* value() const { return OperandAt(0); }
   1243 
   1244   bool HasEscapingOperandAt(int index) override { return false; }
   1245   Representation RequiredInputRepresentation(int index) override {
   1246     return Representation::None();
   1247   }
   1248 
   1249   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1250 
   1251   DECLARE_CONCRETE_INSTRUCTION(DummyUse);
   1252 };
   1253 
   1254 
   1255 // Inserts an int3/stop break instruction for debugging purposes.
   1256 class HDebugBreak final : public HTemplateInstruction<0> {
   1257  public:
   1258   DECLARE_INSTRUCTION_FACTORY_P0(HDebugBreak);
   1259 
   1260   Representation RequiredInputRepresentation(int index) override {
   1261     return Representation::None();
   1262   }
   1263 
   1264   DECLARE_CONCRETE_INSTRUCTION(DebugBreak)
   1265 };
   1266 
   1267 
   1268 class HPrologue final : public HTemplateInstruction<0> {
   1269  public:
   1270   static HPrologue* New(Zone* zone) { return new (zone) HPrologue(); }
   1271 
   1272   Representation RequiredInputRepresentation(int index) override {
   1273     return Representation::None();
   1274   }
   1275 
   1276   DECLARE_CONCRETE_INSTRUCTION(Prologue)
   1277 };
   1278 
   1279 
   1280 class HGoto final : public HTemplateControlInstruction<1, 0> {
   1281  public:
   1282   explicit HGoto(HBasicBlock* target) {
   1283     SetSuccessorAt(0, target);
   1284   }
   1285 
   1286   bool KnownSuccessorBlock(HBasicBlock** block) override {
   1287     *block = FirstSuccessor();
   1288     return true;
   1289   }
   1290 
   1291   Representation RequiredInputRepresentation(int index) override {
   1292     return Representation::None();
   1293   }
   1294 
   1295   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1296 
   1297   DECLARE_CONCRETE_INSTRUCTION(Goto)
   1298 };
   1299 
   1300 
   1301 class HDeoptimize final : public HTemplateControlInstruction<1, 0> {
   1302  public:
   1303   static HDeoptimize* New(Isolate* isolate, Zone* zone, HValue* context,
   1304                           Deoptimizer::DeoptReason reason,
   1305                           Deoptimizer::BailoutType type,
   1306                           HBasicBlock* unreachable_continuation) {
   1307     return new(zone) HDeoptimize(reason, type, unreachable_continuation);
   1308   }
   1309 
   1310   bool KnownSuccessorBlock(HBasicBlock** block) override {
   1311     *block = NULL;
   1312     return true;
   1313   }
   1314 
   1315   Representation RequiredInputRepresentation(int index) override {
   1316     return Representation::None();
   1317   }
   1318 
   1319   Deoptimizer::DeoptReason reason() const { return reason_; }
   1320   Deoptimizer::BailoutType type() { return type_; }
   1321 
   1322   DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
   1323 
   1324  private:
   1325   explicit HDeoptimize(Deoptimizer::DeoptReason reason,
   1326                        Deoptimizer::BailoutType type,
   1327                        HBasicBlock* unreachable_continuation)
   1328       : reason_(reason), type_(type) {
   1329     SetSuccessorAt(0, unreachable_continuation);
   1330   }
   1331 
   1332   Deoptimizer::DeoptReason reason_;
   1333   Deoptimizer::BailoutType type_;
   1334 };
   1335 
   1336 
   1337 class HUnaryControlInstruction : public HTemplateControlInstruction<2, 1> {
   1338  public:
   1339   HUnaryControlInstruction(HValue* value,
   1340                            HBasicBlock* true_target,
   1341                            HBasicBlock* false_target) {
   1342     SetOperandAt(0, value);
   1343     SetSuccessorAt(0, true_target);
   1344     SetSuccessorAt(1, false_target);
   1345   }
   1346 
   1347   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1348 
   1349   HValue* value() const { return OperandAt(0); }
   1350 };
   1351 
   1352 
   1353 class HBranch final : public HUnaryControlInstruction {
   1354  public:
   1355   DECLARE_INSTRUCTION_FACTORY_P1(HBranch, HValue*);
   1356   DECLARE_INSTRUCTION_FACTORY_P2(HBranch, HValue*, ToBooleanICStub::Types);
   1357   DECLARE_INSTRUCTION_FACTORY_P4(HBranch, HValue*, ToBooleanICStub::Types,
   1358                                  HBasicBlock*, HBasicBlock*);
   1359 
   1360   Representation RequiredInputRepresentation(int index) override {
   1361     return Representation::None();
   1362   }
   1363   Representation observed_input_representation(int index) override;
   1364 
   1365   bool KnownSuccessorBlock(HBasicBlock** block) override;
   1366 
   1367   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1368 
   1369   ToBooleanICStub::Types expected_input_types() const {
   1370     return expected_input_types_;
   1371   }
   1372 
   1373   DECLARE_CONCRETE_INSTRUCTION(Branch)
   1374 
   1375  private:
   1376   HBranch(HValue* value, ToBooleanICStub::Types expected_input_types =
   1377                              ToBooleanICStub::Types(),
   1378           HBasicBlock* true_target = NULL, HBasicBlock* false_target = NULL)
   1379       : HUnaryControlInstruction(value, true_target, false_target),
   1380         expected_input_types_(expected_input_types) {
   1381     SetFlag(kAllowUndefinedAsNaN);
   1382   }
   1383 
   1384   ToBooleanICStub::Types expected_input_types_;
   1385 };
   1386 
   1387 
   1388 class HCompareMap final : public HUnaryControlInstruction {
   1389  public:
   1390   DECLARE_INSTRUCTION_FACTORY_P2(HCompareMap, HValue*, Handle<Map>);
   1391   DECLARE_INSTRUCTION_FACTORY_P4(HCompareMap, HValue*, Handle<Map>,
   1392                                  HBasicBlock*, HBasicBlock*);
   1393 
   1394   bool KnownSuccessorBlock(HBasicBlock** block) override {
   1395     if (known_successor_index() != kNoKnownSuccessorIndex) {
   1396       *block = SuccessorAt(known_successor_index());
   1397       return true;
   1398     }
   1399     *block = NULL;
   1400     return false;
   1401   }
   1402 
   1403   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1404 
   1405   static const int kNoKnownSuccessorIndex = -1;
   1406   int known_successor_index() const {
   1407     return KnownSuccessorIndexField::decode(bit_field_) -
   1408            kInternalKnownSuccessorOffset;
   1409   }
   1410   void set_known_successor_index(int index) {
   1411     DCHECK(index >= 0 - kInternalKnownSuccessorOffset);
   1412     bit_field_ = KnownSuccessorIndexField::update(
   1413         bit_field_, index + kInternalKnownSuccessorOffset);
   1414   }
   1415 
   1416   Unique<Map> map() const { return map_; }
   1417   bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }
   1418 
   1419   Representation RequiredInputRepresentation(int index) override {
   1420     return Representation::Tagged();
   1421   }
   1422 
   1423   DECLARE_CONCRETE_INSTRUCTION(CompareMap)
   1424 
   1425  protected:
   1426   int RedefinedOperandIndex() override { return 0; }
   1427 
   1428  private:
   1429   HCompareMap(HValue* value, Handle<Map> map, HBasicBlock* true_target = NULL,
   1430               HBasicBlock* false_target = NULL)
   1431       : HUnaryControlInstruction(value, true_target, false_target),
   1432         bit_field_(KnownSuccessorIndexField::encode(
   1433                        kNoKnownSuccessorIndex + kInternalKnownSuccessorOffset) |
   1434                    MapIsStableField::encode(map->is_stable())),
   1435         map_(Unique<Map>::CreateImmovable(map)) {
   1436     set_representation(Representation::Tagged());
   1437   }
   1438 
   1439   // BitFields can only store unsigned values, so use an offset.
   1440   // Adding kInternalKnownSuccessorOffset must yield an unsigned value.
   1441   static const int kInternalKnownSuccessorOffset = 1;
   1442   STATIC_ASSERT(kNoKnownSuccessorIndex + kInternalKnownSuccessorOffset >= 0);
   1443 
   1444   class KnownSuccessorIndexField : public BitField<int, 0, 31> {};
   1445   class MapIsStableField : public BitField<bool, 31, 1> {};
   1446 
   1447   uint32_t bit_field_;
   1448   Unique<Map> map_;
   1449 };
   1450 
   1451 
   1452 class HContext final : public HTemplateInstruction<0> {
   1453  public:
   1454   static HContext* New(Zone* zone) {
   1455     return new(zone) HContext();
   1456   }
   1457 
   1458   Representation RequiredInputRepresentation(int index) override {
   1459     return Representation::None();
   1460   }
   1461 
   1462   DECLARE_CONCRETE_INSTRUCTION(Context)
   1463 
   1464  protected:
   1465   bool DataEquals(HValue* other) override { return true; }
   1466 
   1467  private:
   1468   HContext() {
   1469     set_representation(Representation::Tagged());
   1470     SetFlag(kUseGVN);
   1471   }
   1472 
   1473   bool IsDeletable() const override { return true; }
   1474 };
   1475 
   1476 
   1477 class HReturn final : public HTemplateControlInstruction<0, 3> {
   1478  public:
   1479   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HReturn, HValue*, HValue*);
   1480   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HReturn, HValue*);
   1481 
   1482   Representation RequiredInputRepresentation(int index) override {
   1483     // TODO(titzer): require an Int32 input for faster returns.
   1484     if (index == 2) return Representation::Smi();
   1485     return Representation::Tagged();
   1486   }
   1487 
   1488   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1489 
   1490   HValue* value() const { return OperandAt(0); }
   1491   HValue* context() const { return OperandAt(1); }
   1492   HValue* parameter_count() const { return OperandAt(2); }
   1493 
   1494   DECLARE_CONCRETE_INSTRUCTION(Return)
   1495 
   1496  private:
   1497   HReturn(HValue* context, HValue* value, HValue* parameter_count = 0) {
   1498     SetOperandAt(0, value);
   1499     SetOperandAt(1, context);
   1500     SetOperandAt(2, parameter_count);
   1501   }
   1502 };
   1503 
   1504 
   1505 class HAbnormalExit final : public HTemplateControlInstruction<0, 0> {
   1506  public:
   1507   DECLARE_INSTRUCTION_FACTORY_P0(HAbnormalExit);
   1508 
   1509   Representation RequiredInputRepresentation(int index) override {
   1510     return Representation::None();
   1511   }
   1512 
   1513   DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
   1514  private:
   1515   HAbnormalExit() {}
   1516 };
   1517 
   1518 
   1519 class HUnaryOperation : public HTemplateInstruction<1> {
   1520  public:
   1521   explicit HUnaryOperation(HValue* value, HType type = HType::Tagged())
   1522       : HTemplateInstruction<1>(type) {
   1523     SetOperandAt(0, value);
   1524   }
   1525 
   1526   static HUnaryOperation* cast(HValue* value) {
   1527     return reinterpret_cast<HUnaryOperation*>(value);
   1528   }
   1529 
   1530   HValue* value() const { return OperandAt(0); }
   1531   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1532 };
   1533 
   1534 
   1535 class HUseConst final : public HUnaryOperation {
   1536  public:
   1537   DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue*);
   1538 
   1539   Representation RequiredInputRepresentation(int index) override {
   1540     return Representation::None();
   1541   }
   1542 
   1543   DECLARE_CONCRETE_INSTRUCTION(UseConst)
   1544 
   1545  private:
   1546     explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
   1547 };
   1548 
   1549 
   1550 class HForceRepresentation final : public HTemplateInstruction<1> {
   1551  public:
   1552   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   1553                            HValue* value,
   1554                            Representation required_representation);
   1555 
   1556   HValue* value() const { return OperandAt(0); }
   1557 
   1558   Representation observed_input_representation(int index) override {
   1559     // We haven't actually *observed* this, but it's closer to the truth
   1560     // than 'None'.
   1561     return representation();  // Same as the output representation.
   1562   }
   1563   Representation RequiredInputRepresentation(int index) override {
   1564     return representation();  // Same as the output representation.
   1565   }
   1566 
   1567   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1568 
   1569   DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
   1570 
   1571  private:
   1572   HForceRepresentation(HValue* value, Representation required_representation) {
   1573     SetOperandAt(0, value);
   1574     set_representation(required_representation);
   1575   }
   1576 };
   1577 
   1578 
   1579 class HChange final : public HUnaryOperation {
   1580  public:
   1581   HChange(HValue* value,
   1582           Representation to,
   1583           bool is_truncating_to_smi,
   1584           bool is_truncating_to_int32)
   1585       : HUnaryOperation(value) {
   1586     DCHECK(!value->representation().IsNone());
   1587     DCHECK(!to.IsNone());
   1588     DCHECK(!value->representation().Equals(to));
   1589     set_representation(to);
   1590     SetFlag(kUseGVN);
   1591     SetFlag(kCanOverflow);
   1592     if (is_truncating_to_smi && to.IsSmi()) {
   1593       SetFlag(kTruncatingToSmi);
   1594       SetFlag(kTruncatingToInt32);
   1595     }
   1596     if (is_truncating_to_int32) SetFlag(kTruncatingToInt32);
   1597     if (value->representation().IsSmi() || value->type().IsSmi()) {
   1598       set_type(HType::Smi());
   1599     } else {
   1600       set_type(HType::TaggedNumber());
   1601       if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
   1602     }
   1603   }
   1604 
   1605   bool can_convert_undefined_to_nan() {
   1606     return CheckUsesForFlag(kAllowUndefinedAsNaN);
   1607   }
   1608 
   1609   HType CalculateInferredType() override;
   1610   HValue* Canonicalize() override;
   1611 
   1612   Representation from() const { return value()->representation(); }
   1613   Representation to() const { return representation(); }
   1614   bool deoptimize_on_minus_zero() const {
   1615     return CheckFlag(kBailoutOnMinusZero);
   1616   }
   1617   Representation RequiredInputRepresentation(int index) override {
   1618     return from();
   1619   }
   1620 
   1621   Range* InferRange(Zone* zone) override;
   1622 
   1623   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1624 
   1625   DECLARE_CONCRETE_INSTRUCTION(Change)
   1626 
   1627  protected:
   1628   bool DataEquals(HValue* other) override { return true; }
   1629 
   1630  private:
   1631   bool IsDeletable() const override {
   1632     return !from().IsTagged() || value()->type().IsSmi();
   1633   }
   1634 };
   1635 
   1636 
   1637 class HClampToUint8 final : public HUnaryOperation {
   1638  public:
   1639   DECLARE_INSTRUCTION_FACTORY_P1(HClampToUint8, HValue*);
   1640 
   1641   Representation RequiredInputRepresentation(int index) override {
   1642     return Representation::None();
   1643   }
   1644 
   1645   DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
   1646 
   1647  protected:
   1648   bool DataEquals(HValue* other) override { return true; }
   1649 
   1650  private:
   1651   explicit HClampToUint8(HValue* value)
   1652       : HUnaryOperation(value) {
   1653     set_representation(Representation::Integer32());
   1654     SetFlag(kAllowUndefinedAsNaN);
   1655     SetFlag(kUseGVN);
   1656   }
   1657 
   1658   bool IsDeletable() const override { return true; }
   1659 };
   1660 
   1661 
   1662 class HDoubleBits final : public HUnaryOperation {
   1663  public:
   1664   enum Bits { HIGH, LOW };
   1665   DECLARE_INSTRUCTION_FACTORY_P2(HDoubleBits, HValue*, Bits);
   1666 
   1667   Representation RequiredInputRepresentation(int index) override {
   1668     return Representation::Double();
   1669   }
   1670 
   1671   DECLARE_CONCRETE_INSTRUCTION(DoubleBits)
   1672 
   1673   Bits bits() { return bits_; }
   1674 
   1675  protected:
   1676   bool DataEquals(HValue* other) override {
   1677     return other->IsDoubleBits() && HDoubleBits::cast(other)->bits() == bits();
   1678   }
   1679 
   1680  private:
   1681   HDoubleBits(HValue* value, Bits bits)
   1682       : HUnaryOperation(value), bits_(bits) {
   1683     set_representation(Representation::Integer32());
   1684     SetFlag(kUseGVN);
   1685   }
   1686 
   1687   bool IsDeletable() const override { return true; }
   1688 
   1689   Bits bits_;
   1690 };
   1691 
   1692 
   1693 enum RemovableSimulate {
   1694   REMOVABLE_SIMULATE,
   1695   FIXED_SIMULATE
   1696 };
   1697 
   1698 
   1699 class HSimulate final : public HInstruction {
   1700  public:
   1701   HSimulate(BailoutId ast_id, int pop_count, Zone* zone,
   1702             RemovableSimulate removable)
   1703       : ast_id_(ast_id),
   1704         pop_count_(pop_count),
   1705         values_(2, zone),
   1706         assigned_indexes_(2, zone),
   1707         zone_(zone),
   1708         bit_field_(RemovableField::encode(removable) |
   1709                    DoneWithReplayField::encode(false)) {}
   1710   ~HSimulate() {}
   1711 
   1712   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1713 
   1714   bool HasAstId() const { return !ast_id_.IsNone(); }
   1715   BailoutId ast_id() const { return ast_id_; }
   1716   void set_ast_id(BailoutId id) {
   1717     DCHECK(!HasAstId());
   1718     ast_id_ = id;
   1719   }
   1720 
   1721   int pop_count() const { return pop_count_; }
   1722   const ZoneList<HValue*>* values() const { return &values_; }
   1723   int GetAssignedIndexAt(int index) const {
   1724     DCHECK(HasAssignedIndexAt(index));
   1725     return assigned_indexes_[index];
   1726   }
   1727   bool HasAssignedIndexAt(int index) const {
   1728     return assigned_indexes_[index] != kNoIndex;
   1729   }
   1730   void AddAssignedValue(int index, HValue* value) {
   1731     AddValue(index, value);
   1732   }
   1733   void AddPushedValue(HValue* value) {
   1734     AddValue(kNoIndex, value);
   1735   }
   1736   int ToOperandIndex(int environment_index) {
   1737     for (int i = 0; i < assigned_indexes_.length(); ++i) {
   1738       if (assigned_indexes_[i] == environment_index) return i;
   1739     }
   1740     return -1;
   1741   }
   1742   int OperandCount() const override { return values_.length(); }
   1743   HValue* OperandAt(int index) const override { return values_[index]; }
   1744 
   1745   bool HasEscapingOperandAt(int index) override { return false; }
   1746   Representation RequiredInputRepresentation(int index) override {
   1747     return Representation::None();
   1748   }
   1749 
   1750   void MergeWith(ZoneList<HSimulate*>* list);
   1751   bool is_candidate_for_removal() {
   1752     return RemovableField::decode(bit_field_) == REMOVABLE_SIMULATE;
   1753   }
   1754 
   1755   // Replay effects of this instruction on the given environment.
   1756   void ReplayEnvironment(HEnvironment* env);
   1757 
   1758   DECLARE_CONCRETE_INSTRUCTION(Simulate)
   1759 
   1760 #ifdef DEBUG
   1761   void Verify() override;
   1762   void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
   1763   Handle<JSFunction> closure() const { return closure_; }
   1764 #endif
   1765 
   1766  protected:
   1767   void InternalSetOperandAt(int index, HValue* value) override {
   1768     values_[index] = value;
   1769   }
   1770 
   1771  private:
   1772   static const int kNoIndex = -1;
   1773   void AddValue(int index, HValue* value) {
   1774     assigned_indexes_.Add(index, zone_);
   1775     // Resize the list of pushed values.
   1776     values_.Add(NULL, zone_);
   1777     // Set the operand through the base method in HValue to make sure that the
   1778     // use lists are correctly updated.
   1779     SetOperandAt(values_.length() - 1, value);
   1780   }
   1781   bool HasValueForIndex(int index) {
   1782     for (int i = 0; i < assigned_indexes_.length(); ++i) {
   1783       if (assigned_indexes_[i] == index) return true;
   1784     }
   1785     return false;
   1786   }
   1787   bool is_done_with_replay() const {
   1788     return DoneWithReplayField::decode(bit_field_);
   1789   }
   1790   void set_done_with_replay() {
   1791     bit_field_ = DoneWithReplayField::update(bit_field_, true);
   1792   }
   1793 
   1794   class RemovableField : public BitField<RemovableSimulate, 0, 1> {};
   1795   class DoneWithReplayField : public BitField<bool, 1, 1> {};
   1796 
   1797   BailoutId ast_id_;
   1798   int pop_count_;
   1799   ZoneList<HValue*> values_;
   1800   ZoneList<int> assigned_indexes_;
   1801   Zone* zone_;
   1802   uint32_t bit_field_;
   1803 
   1804 #ifdef DEBUG
   1805   Handle<JSFunction> closure_;
   1806 #endif
   1807 };
   1808 
   1809 
   1810 class HEnvironmentMarker final : public HTemplateInstruction<1> {
   1811  public:
   1812   enum Kind { BIND, LOOKUP };
   1813 
   1814   DECLARE_INSTRUCTION_FACTORY_P2(HEnvironmentMarker, Kind, int);
   1815 
   1816   Kind kind() const { return kind_; }
   1817   int index() const { return index_; }
   1818   HSimulate* next_simulate() { return next_simulate_; }
   1819   void set_next_simulate(HSimulate* simulate) {
   1820     next_simulate_ = simulate;
   1821   }
   1822 
   1823   Representation RequiredInputRepresentation(int index) override {
   1824     return Representation::None();
   1825   }
   1826 
   1827   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1828 
   1829 #ifdef DEBUG
   1830   void set_closure(Handle<JSFunction> closure) {
   1831     DCHECK(closure_.is_null());
   1832     DCHECK(!closure.is_null());
   1833     closure_ = closure;
   1834   }
   1835   Handle<JSFunction> closure() const { return closure_; }
   1836 #endif
   1837 
   1838   DECLARE_CONCRETE_INSTRUCTION(EnvironmentMarker);
   1839 
   1840  private:
   1841   HEnvironmentMarker(Kind kind, int index)
   1842       : kind_(kind), index_(index), next_simulate_(NULL) { }
   1843 
   1844   Kind kind_;
   1845   int index_;
   1846   HSimulate* next_simulate_;
   1847 
   1848 #ifdef DEBUG
   1849   Handle<JSFunction> closure_;
   1850 #endif
   1851 };
   1852 
   1853 
   1854 class HStackCheck final : public HTemplateInstruction<1> {
   1855  public:
   1856   enum Type {
   1857     kFunctionEntry,
   1858     kBackwardsBranch
   1859   };
   1860 
   1861   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HStackCheck, Type);
   1862 
   1863   HValue* context() { return OperandAt(0); }
   1864 
   1865   Representation RequiredInputRepresentation(int index) override {
   1866     return Representation::Tagged();
   1867   }
   1868 
   1869   void Eliminate() {
   1870     // The stack check eliminator might try to eliminate the same stack
   1871     // check instruction multiple times.
   1872     if (IsLinked()) {
   1873       DeleteAndReplaceWith(NULL);
   1874     }
   1875   }
   1876 
   1877   bool is_function_entry() { return type_ == kFunctionEntry; }
   1878   bool is_backwards_branch() { return type_ == kBackwardsBranch; }
   1879 
   1880   DECLARE_CONCRETE_INSTRUCTION(StackCheck)
   1881 
   1882  private:
   1883   HStackCheck(HValue* context, Type type) : type_(type) {
   1884     SetOperandAt(0, context);
   1885     SetChangesFlag(kNewSpacePromotion);
   1886   }
   1887 
   1888   Type type_;
   1889 };
   1890 
   1891 
   1892 enum InliningKind {
   1893   NORMAL_RETURN,          // Drop the function from the environment on return.
   1894   CONSTRUCT_CALL_RETURN,  // Either use allocated receiver or return value.
   1895   GETTER_CALL_RETURN,     // Returning from a getter, need to restore context.
   1896   SETTER_CALL_RETURN      // Use the RHS of the assignment as the return value.
   1897 };
   1898 
   1899 
   1900 class HArgumentsObject;
   1901 class HConstant;
   1902 
   1903 
   1904 class HEnterInlined final : public HTemplateInstruction<0> {
   1905  public:
   1906   static HEnterInlined* New(Isolate* isolate, Zone* zone, HValue* context,
   1907                             BailoutId return_id, Handle<JSFunction> closure,
   1908                             HConstant* closure_context, int arguments_count,
   1909                             FunctionLiteral* function,
   1910                             InliningKind inlining_kind, Variable* arguments_var,
   1911                             HArgumentsObject* arguments_object,
   1912                             TailCallMode syntactic_tail_call_mode) {
   1913     return new (zone)
   1914         HEnterInlined(return_id, closure, closure_context, arguments_count,
   1915                       function, inlining_kind, arguments_var, arguments_object,
   1916                       syntactic_tail_call_mode, zone);
   1917   }
   1918 
   1919   void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
   1920   ZoneList<HBasicBlock*>* return_targets() { return &return_targets_; }
   1921 
   1922   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   1923 
   1924   Handle<SharedFunctionInfo> shared() const { return shared_; }
   1925   Handle<JSFunction> closure() const { return closure_; }
   1926   HConstant* closure_context() const { return closure_context_; }
   1927   int arguments_count() const { return arguments_count_; }
   1928   bool arguments_pushed() const { return arguments_pushed_; }
   1929   void set_arguments_pushed() { arguments_pushed_ = true; }
   1930   FunctionLiteral* function() const { return function_; }
   1931   InliningKind inlining_kind() const { return inlining_kind_; }
   1932   TailCallMode syntactic_tail_call_mode() const {
   1933     return syntactic_tail_call_mode_;
   1934   }
   1935   BailoutId ReturnId() const { return return_id_; }
   1936   int inlining_id() const { return inlining_id_; }
   1937   void set_inlining_id(int inlining_id) { inlining_id_ = inlining_id; }
   1938 
   1939   Representation RequiredInputRepresentation(int index) override {
   1940     return Representation::None();
   1941   }
   1942 
   1943   Variable* arguments_var() { return arguments_var_; }
   1944   HArgumentsObject* arguments_object() { return arguments_object_; }
   1945 
   1946   DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
   1947 
   1948  private:
   1949   HEnterInlined(BailoutId return_id, Handle<JSFunction> closure,
   1950                 HConstant* closure_context, int arguments_count,
   1951                 FunctionLiteral* function, InliningKind inlining_kind,
   1952                 Variable* arguments_var, HArgumentsObject* arguments_object,
   1953                 TailCallMode syntactic_tail_call_mode, Zone* zone)
   1954       : return_id_(return_id),
   1955         shared_(handle(closure->shared())),
   1956         closure_(closure),
   1957         closure_context_(closure_context),
   1958         arguments_count_(arguments_count),
   1959         arguments_pushed_(false),
   1960         function_(function),
   1961         inlining_kind_(inlining_kind),
   1962         syntactic_tail_call_mode_(syntactic_tail_call_mode),
   1963         inlining_id_(0),
   1964         arguments_var_(arguments_var),
   1965         arguments_object_(arguments_object),
   1966         return_targets_(2, zone) {}
   1967 
   1968   BailoutId return_id_;
   1969   Handle<SharedFunctionInfo> shared_;
   1970   Handle<JSFunction> closure_;
   1971   HConstant* closure_context_;
   1972   int arguments_count_;
   1973   bool arguments_pushed_;
   1974   FunctionLiteral* function_;
   1975   InliningKind inlining_kind_;
   1976   TailCallMode syntactic_tail_call_mode_;
   1977   int inlining_id_;
   1978   Variable* arguments_var_;
   1979   HArgumentsObject* arguments_object_;
   1980   ZoneList<HBasicBlock*> return_targets_;
   1981 };
   1982 
   1983 
   1984 class HLeaveInlined final : public HTemplateInstruction<0> {
   1985  public:
   1986   HLeaveInlined(HEnterInlined* entry,
   1987                 int drop_count)
   1988       : entry_(entry),
   1989         drop_count_(drop_count) { }
   1990 
   1991   Representation RequiredInputRepresentation(int index) override {
   1992     return Representation::None();
   1993   }
   1994 
   1995   int argument_delta() const override {
   1996     return entry_->arguments_pushed() ? -drop_count_ : 0;
   1997   }
   1998 
   1999   DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
   2000 
   2001  private:
   2002   HEnterInlined* entry_;
   2003   int drop_count_;
   2004 };
   2005 
   2006 
   2007 class HPushArguments final : public HInstruction {
   2008  public:
   2009   static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context) {
   2010     return new(zone) HPushArguments(zone);
   2011   }
   2012   static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
   2013                              HValue* arg1) {
   2014     HPushArguments* instr = new(zone) HPushArguments(zone);
   2015     instr->AddInput(arg1);
   2016     return instr;
   2017   }
   2018   static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
   2019                              HValue* arg1, HValue* arg2) {
   2020     HPushArguments* instr = new(zone) HPushArguments(zone);
   2021     instr->AddInput(arg1);
   2022     instr->AddInput(arg2);
   2023     return instr;
   2024   }
   2025   static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
   2026                              HValue* arg1, HValue* arg2, HValue* arg3) {
   2027     HPushArguments* instr = new(zone) HPushArguments(zone);
   2028     instr->AddInput(arg1);
   2029     instr->AddInput(arg2);
   2030     instr->AddInput(arg3);
   2031     return instr;
   2032   }
   2033   static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
   2034                              HValue* arg1, HValue* arg2, HValue* arg3,
   2035                              HValue* arg4) {
   2036     HPushArguments* instr = new(zone) HPushArguments(zone);
   2037     instr->AddInput(arg1);
   2038     instr->AddInput(arg2);
   2039     instr->AddInput(arg3);
   2040     instr->AddInput(arg4);
   2041     return instr;
   2042   }
   2043 
   2044   Representation RequiredInputRepresentation(int index) override {
   2045     return Representation::Tagged();
   2046   }
   2047 
   2048   int argument_delta() const override { return inputs_.length(); }
   2049   HValue* argument(int i) { return OperandAt(i); }
   2050 
   2051   int OperandCount() const final { return inputs_.length(); }
   2052   HValue* OperandAt(int i) const final { return inputs_[i]; }
   2053 
   2054   void AddInput(HValue* value);
   2055 
   2056   DECLARE_CONCRETE_INSTRUCTION(PushArguments)
   2057 
   2058  protected:
   2059   void InternalSetOperandAt(int i, HValue* value) final { inputs_[i] = value; }
   2060 
   2061  private:
   2062   explicit HPushArguments(Zone* zone)
   2063       : HInstruction(HType::Tagged()), inputs_(4, zone) {
   2064     set_representation(Representation::Tagged());
   2065   }
   2066 
   2067   ZoneList<HValue*> inputs_;
   2068 };
   2069 
   2070 
   2071 class HThisFunction final : public HTemplateInstruction<0> {
   2072  public:
   2073   DECLARE_INSTRUCTION_FACTORY_P0(HThisFunction);
   2074 
   2075   Representation RequiredInputRepresentation(int index) override {
   2076     return Representation::None();
   2077   }
   2078 
   2079   DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
   2080 
   2081  protected:
   2082   bool DataEquals(HValue* other) override { return true; }
   2083 
   2084  private:
   2085   HThisFunction() {
   2086     set_representation(Representation::Tagged());
   2087     SetFlag(kUseGVN);
   2088   }
   2089 
   2090   bool IsDeletable() const override { return true; }
   2091 };
   2092 
   2093 
   2094 class HDeclareGlobals final : public HUnaryOperation {
   2095  public:
   2096   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HDeclareGlobals,
   2097                                               Handle<FixedArray>,
   2098                                               int);
   2099 
   2100   HValue* context() { return OperandAt(0); }
   2101   Handle<FixedArray> pairs() const { return pairs_; }
   2102   int flags() const { return flags_; }
   2103 
   2104   DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
   2105 
   2106   Representation RequiredInputRepresentation(int index) override {
   2107     return Representation::Tagged();
   2108   }
   2109 
   2110  private:
   2111   HDeclareGlobals(HValue* context,
   2112                   Handle<FixedArray> pairs,
   2113                   int flags)
   2114       : HUnaryOperation(context),
   2115         pairs_(pairs),
   2116         flags_(flags) {
   2117     set_representation(Representation::Tagged());
   2118     SetAllSideEffects();
   2119   }
   2120 
   2121   Handle<FixedArray> pairs_;
   2122   int flags_;
   2123 };
   2124 
   2125 
   2126 template <int V>
   2127 class HCall : public HTemplateInstruction<V> {
   2128  public:
   2129   // The argument count includes the receiver.
   2130   explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
   2131     this->set_representation(Representation::Tagged());
   2132     this->SetAllSideEffects();
   2133   }
   2134 
   2135   virtual int argument_count() const {
   2136     return argument_count_;
   2137   }
   2138 
   2139   int argument_delta() const override { return -argument_count(); }
   2140 
   2141  private:
   2142   int argument_count_;
   2143 };
   2144 
   2145 
   2146 class HUnaryCall : public HCall<1> {
   2147  public:
   2148   HUnaryCall(HValue* value, int argument_count)
   2149       : HCall<1>(argument_count) {
   2150     SetOperandAt(0, value);
   2151   }
   2152 
   2153   Representation RequiredInputRepresentation(int index) final {
   2154     return Representation::Tagged();
   2155   }
   2156 
   2157   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2158 
   2159   HValue* value() const { return OperandAt(0); }
   2160 };
   2161 
   2162 
   2163 class HBinaryCall : public HCall<2> {
   2164  public:
   2165   HBinaryCall(HValue* first, HValue* second, int argument_count)
   2166       : HCall<2>(argument_count) {
   2167     SetOperandAt(0, first);
   2168     SetOperandAt(1, second);
   2169   }
   2170 
   2171   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2172 
   2173   Representation RequiredInputRepresentation(int index) final {
   2174     return Representation::Tagged();
   2175   }
   2176 
   2177   HValue* first() const { return OperandAt(0); }
   2178   HValue* second() const { return OperandAt(1); }
   2179 };
   2180 
   2181 
   2182 class HCallWithDescriptor final : public HInstruction {
   2183  public:
   2184   static HCallWithDescriptor* New(
   2185       Isolate* isolate, Zone* zone, HValue* context, HValue* target,
   2186       int argument_count, CallInterfaceDescriptor descriptor,
   2187       const Vector<HValue*>& operands,
   2188       TailCallMode syntactic_tail_call_mode = TailCallMode::kDisallow,
   2189       TailCallMode tail_call_mode = TailCallMode::kDisallow) {
   2190     HCallWithDescriptor* res = new (zone)
   2191         HCallWithDescriptor(target, argument_count, descriptor, operands,
   2192                             syntactic_tail_call_mode, tail_call_mode, zone);
   2193     return res;
   2194   }
   2195 
   2196   int OperandCount() const final { return values_.length(); }
   2197   HValue* OperandAt(int index) const final { return values_[index]; }
   2198 
   2199   Representation RequiredInputRepresentation(int index) final {
   2200     if (index == 0 || index == 1) {
   2201       // Target + context
   2202       return Representation::Tagged();
   2203     } else {
   2204       int par_index = index - 2;
   2205       DCHECK(par_index < GetParameterCount());
   2206       return RepresentationFromType(descriptor_.GetParameterType(par_index));
   2207     }
   2208   }
   2209 
   2210   DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor)
   2211 
   2212   // Defines whether this instruction corresponds to a JS call at tail position.
   2213   TailCallMode syntactic_tail_call_mode() const {
   2214     return SyntacticTailCallModeField::decode(bit_field_);
   2215   }
   2216 
   2217   // Defines whether this call should be generated as a tail call.
   2218   TailCallMode tail_call_mode() const {
   2219     return TailCallModeField::decode(bit_field_);
   2220   }
   2221   bool IsTailCall() const { return tail_call_mode() == TailCallMode::kAllow; }
   2222 
   2223   virtual int argument_count() const {
   2224     return argument_count_;
   2225   }
   2226 
   2227   int argument_delta() const override { return -argument_count_; }
   2228 
   2229   CallInterfaceDescriptor descriptor() const { return descriptor_; }
   2230 
   2231   HValue* target() {
   2232     return OperandAt(0);
   2233   }
   2234 
   2235   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2236 
   2237  private:
   2238   // The argument count includes the receiver.
   2239   HCallWithDescriptor(HValue* target, int argument_count,
   2240                       CallInterfaceDescriptor descriptor,
   2241                       const Vector<HValue*>& operands,
   2242                       TailCallMode syntactic_tail_call_mode,
   2243                       TailCallMode tail_call_mode, Zone* zone)
   2244       : descriptor_(descriptor),
   2245         values_(GetParameterCount() + 1, zone),
   2246         argument_count_(argument_count),
   2247         bit_field_(
   2248             TailCallModeField::encode(tail_call_mode) |
   2249             SyntacticTailCallModeField::encode(syntactic_tail_call_mode)) {
   2250     DCHECK_EQ(operands.length(), GetParameterCount());
   2251     // We can only tail call without any stack arguments.
   2252     DCHECK(tail_call_mode != TailCallMode::kAllow || argument_count == 0);
   2253     AddOperand(target, zone);
   2254     for (int i = 0; i < operands.length(); i++) {
   2255       AddOperand(operands[i], zone);
   2256     }
   2257     this->set_representation(Representation::Tagged());
   2258     this->SetAllSideEffects();
   2259   }
   2260 
   2261   void AddOperand(HValue* v, Zone* zone) {
   2262     values_.Add(NULL, zone);
   2263     SetOperandAt(values_.length() - 1, v);
   2264   }
   2265 
   2266   int GetParameterCount() const {
   2267     return descriptor_.GetRegisterParameterCount() + 1;
   2268   }
   2269 
   2270   void InternalSetOperandAt(int index, HValue* value) final {
   2271     values_[index] = value;
   2272   }
   2273 
   2274   CallInterfaceDescriptor descriptor_;
   2275   ZoneList<HValue*> values_;
   2276   int argument_count_;
   2277   class TailCallModeField : public BitField<TailCallMode, 0, 1> {};
   2278   class SyntacticTailCallModeField
   2279       : public BitField<TailCallMode, TailCallModeField::kNext, 1> {};
   2280   uint32_t bit_field_;
   2281 };
   2282 
   2283 
   2284 class HInvokeFunction final : public HBinaryCall {
   2285  public:
   2286   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HInvokeFunction, HValue*,
   2287                                               Handle<JSFunction>, int,
   2288                                               TailCallMode, TailCallMode);
   2289 
   2290   HValue* context() { return first(); }
   2291   HValue* function() { return second(); }
   2292   Handle<JSFunction> known_function() { return known_function_; }
   2293   int formal_parameter_count() const { return formal_parameter_count_; }
   2294 
   2295   bool HasStackCheck() final { return HasStackCheckField::decode(bit_field_); }
   2296 
   2297   // Defines whether this instruction corresponds to a JS call at tail position.
   2298   TailCallMode syntactic_tail_call_mode() const {
   2299     return SyntacticTailCallModeField::decode(bit_field_);
   2300   }
   2301 
   2302   // Defines whether this call should be generated as a tail call.
   2303   TailCallMode tail_call_mode() const {
   2304     return TailCallModeField::decode(bit_field_);
   2305   }
   2306 
   2307   DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
   2308 
   2309   std::ostream& PrintTo(std::ostream& os) const override;      // NOLINT
   2310   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2311 
   2312  private:
   2313   void set_has_stack_check(bool has_stack_check) {
   2314     bit_field_ = HasStackCheckField::update(bit_field_, has_stack_check);
   2315   }
   2316 
   2317   HInvokeFunction(HValue* context, HValue* function,
   2318                   Handle<JSFunction> known_function, int argument_count,
   2319                   TailCallMode syntactic_tail_call_mode,
   2320                   TailCallMode tail_call_mode)
   2321       : HBinaryCall(context, function, argument_count),
   2322         known_function_(known_function),
   2323         bit_field_(
   2324             TailCallModeField::encode(tail_call_mode) |
   2325             SyntacticTailCallModeField::encode(syntactic_tail_call_mode)) {
   2326     DCHECK(tail_call_mode != TailCallMode::kAllow ||
   2327            syntactic_tail_call_mode == TailCallMode::kAllow);
   2328     formal_parameter_count_ =
   2329         known_function.is_null()
   2330             ? 0
   2331             : known_function->shared()->internal_formal_parameter_count();
   2332     set_has_stack_check(
   2333         !known_function.is_null() &&
   2334         (known_function->code()->kind() == Code::FUNCTION ||
   2335          known_function->code()->kind() == Code::OPTIMIZED_FUNCTION));
   2336   }
   2337 
   2338   Handle<JSFunction> known_function_;
   2339   int formal_parameter_count_;
   2340 
   2341   class HasStackCheckField : public BitField<bool, 0, 1> {};
   2342   class TailCallModeField
   2343       : public BitField<TailCallMode, HasStackCheckField::kNext, 1> {};
   2344   class SyntacticTailCallModeField
   2345       : public BitField<TailCallMode, TailCallModeField::kNext, 1> {};
   2346   uint32_t bit_field_;
   2347 };
   2348 
   2349 
   2350 class HCallNewArray final : public HBinaryCall {
   2351  public:
   2352   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HCallNewArray, HValue*, int,
   2353                                               ElementsKind,
   2354                                               Handle<AllocationSite>);
   2355 
   2356   HValue* context() { return first(); }
   2357   HValue* constructor() { return second(); }
   2358 
   2359   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2360 
   2361   ElementsKind elements_kind() const { return elements_kind_; }
   2362   Handle<AllocationSite> site() const { return site_; }
   2363 
   2364   DECLARE_CONCRETE_INSTRUCTION(CallNewArray)
   2365 
   2366  private:
   2367   HCallNewArray(HValue* context, HValue* constructor, int argument_count,
   2368                 ElementsKind elements_kind, Handle<AllocationSite> site)
   2369       : HBinaryCall(context, constructor, argument_count),
   2370         elements_kind_(elements_kind),
   2371         site_(site) {}
   2372 
   2373   ElementsKind elements_kind_;
   2374   Handle<AllocationSite> site_;
   2375 };
   2376 
   2377 
   2378 class HCallRuntime final : public HCall<1> {
   2379  public:
   2380   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallRuntime,
   2381                                               const Runtime::Function*, int);
   2382 
   2383   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2384 
   2385   HValue* context() { return OperandAt(0); }
   2386   const Runtime::Function* function() const { return c_function_; }
   2387   SaveFPRegsMode save_doubles() const { return save_doubles_; }
   2388   void set_save_doubles(SaveFPRegsMode save_doubles) {
   2389     save_doubles_ = save_doubles;
   2390   }
   2391 
   2392   Representation RequiredInputRepresentation(int index) override {
   2393     return Representation::Tagged();
   2394   }
   2395 
   2396   DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
   2397 
   2398  private:
   2399   HCallRuntime(HValue* context, const Runtime::Function* c_function,
   2400                int argument_count)
   2401       : HCall<1>(argument_count),
   2402         c_function_(c_function),
   2403         save_doubles_(kDontSaveFPRegs) {
   2404     SetOperandAt(0, context);
   2405   }
   2406 
   2407   const Runtime::Function* c_function_;
   2408   SaveFPRegsMode save_doubles_;
   2409 };
   2410 
   2411 
   2412 class HUnaryMathOperation final : public HTemplateInstruction<2> {
   2413  public:
   2414   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   2415                            HValue* value, BuiltinFunctionId op);
   2416 
   2417   HValue* context() const { return OperandAt(0); }
   2418   HValue* value() const { return OperandAt(1); }
   2419 
   2420   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2421 
   2422   Representation RequiredInputRepresentation(int index) override {
   2423     if (index == 0) {
   2424       return Representation::Tagged();
   2425     } else {
   2426       switch (op_) {
   2427         case kMathCos:
   2428         case kMathFloor:
   2429         case kMathRound:
   2430         case kMathFround:
   2431         case kMathSin:
   2432         case kMathSqrt:
   2433         case kMathPowHalf:
   2434         case kMathLog:
   2435         case kMathExp:
   2436           return Representation::Double();
   2437         case kMathAbs:
   2438           return representation();
   2439         case kMathClz32:
   2440           return Representation::Integer32();
   2441         default:
   2442           UNREACHABLE();
   2443           return Representation::None();
   2444       }
   2445     }
   2446   }
   2447 
   2448   Range* InferRange(Zone* zone) override;
   2449 
   2450   HValue* Canonicalize() override;
   2451   Representation RepresentationFromUses() override;
   2452   Representation RepresentationFromInputs() override;
   2453 
   2454   BuiltinFunctionId op() const { return op_; }
   2455   const char* OpName() const;
   2456 
   2457   DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
   2458 
   2459  protected:
   2460   bool DataEquals(HValue* other) override {
   2461     HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
   2462     return op_ == b->op();
   2463   }
   2464 
   2465  private:
   2466   // Indicates if we support a double (and int32) output for Math.floor and
   2467   // Math.round.
   2468   bool SupportsFlexibleFloorAndRound() const {
   2469 #if V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_PPC
   2470     return true;
   2471 #elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
   2472     return CpuFeatures::IsSupported(SSE4_1);
   2473 #else
   2474     return false;
   2475 #endif
   2476   }
   2477   HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
   2478       : HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
   2479     SetOperandAt(0, context);
   2480     SetOperandAt(1, value);
   2481     switch (op) {
   2482       case kMathFloor:
   2483       case kMathRound:
   2484         if (SupportsFlexibleFloorAndRound()) {
   2485           SetFlag(kFlexibleRepresentation);
   2486         } else {
   2487           set_representation(Representation::Integer32());
   2488         }
   2489         break;
   2490       case kMathClz32:
   2491         set_representation(Representation::Integer32());
   2492         break;
   2493       case kMathAbs:
   2494         // Not setting representation here: it is None intentionally.
   2495         SetFlag(kFlexibleRepresentation);
   2496         // TODO(svenpanne) This flag is actually only needed if representation()
   2497         // is tagged, and not when it is an unboxed double or unboxed integer.
   2498         SetChangesFlag(kNewSpacePromotion);
   2499         break;
   2500       case kMathCos:
   2501       case kMathFround:
   2502       case kMathLog:
   2503       case kMathExp:
   2504       case kMathSin:
   2505       case kMathSqrt:
   2506       case kMathPowHalf:
   2507         set_representation(Representation::Double());
   2508         break;
   2509       default:
   2510         UNREACHABLE();
   2511     }
   2512     SetFlag(kUseGVN);
   2513     SetFlag(kAllowUndefinedAsNaN);
   2514   }
   2515 
   2516   bool IsDeletable() const override {
   2517     // TODO(crankshaft): This should be true, however the semantics of this
   2518     // instruction also include the ToNumber conversion that is mentioned in the
   2519     // spec, which is of course observable.
   2520     return false;
   2521   }
   2522 
   2523   HValue* SimplifiedDividendForMathFloorOfDiv(HDiv* hdiv);
   2524   HValue* SimplifiedDivisorForMathFloorOfDiv(HDiv* hdiv);
   2525 
   2526   BuiltinFunctionId op_;
   2527 };
   2528 
   2529 
   2530 class HLoadRoot final : public HTemplateInstruction<0> {
   2531  public:
   2532   DECLARE_INSTRUCTION_FACTORY_P1(HLoadRoot, Heap::RootListIndex);
   2533   DECLARE_INSTRUCTION_FACTORY_P2(HLoadRoot, Heap::RootListIndex, HType);
   2534 
   2535   Representation RequiredInputRepresentation(int index) override {
   2536     return Representation::None();
   2537   }
   2538 
   2539   Heap::RootListIndex index() const { return index_; }
   2540 
   2541   DECLARE_CONCRETE_INSTRUCTION(LoadRoot)
   2542 
   2543  protected:
   2544   bool DataEquals(HValue* other) override {
   2545     HLoadRoot* b = HLoadRoot::cast(other);
   2546     return index_ == b->index_;
   2547   }
   2548 
   2549  private:
   2550   explicit HLoadRoot(Heap::RootListIndex index, HType type = HType::Tagged())
   2551       : HTemplateInstruction<0>(type), index_(index) {
   2552     SetFlag(kUseGVN);
   2553     // TODO(bmeurer): We'll need kDependsOnRoots once we add the
   2554     // corresponding HStoreRoot instruction.
   2555     SetDependsOnFlag(kCalls);
   2556     set_representation(Representation::Tagged());
   2557   }
   2558 
   2559   bool IsDeletable() const override { return true; }
   2560 
   2561   const Heap::RootListIndex index_;
   2562 };
   2563 
   2564 
   2565 class HCheckMaps final : public HTemplateInstruction<2> {
   2566  public:
   2567   static HCheckMaps* New(Isolate* isolate, Zone* zone, HValue* context,
   2568                          HValue* value, Handle<Map> map,
   2569                          HValue* typecheck = NULL) {
   2570     return new(zone) HCheckMaps(value, new(zone) UniqueSet<Map>(
   2571             Unique<Map>::CreateImmovable(map), zone), typecheck);
   2572   }
   2573   static HCheckMaps* New(Isolate* isolate, Zone* zone, HValue* context,
   2574                          HValue* value, SmallMapList* map_list,
   2575                          HValue* typecheck = NULL) {
   2576     UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone);
   2577     for (int i = 0; i < map_list->length(); ++i) {
   2578       maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone);
   2579     }
   2580     return new(zone) HCheckMaps(value, maps, typecheck);
   2581   }
   2582 
   2583   bool IsStabilityCheck() const {
   2584     return IsStabilityCheckField::decode(bit_field_);
   2585   }
   2586   void MarkAsStabilityCheck() {
   2587     bit_field_ = MapsAreStableField::encode(true) |
   2588                  HasMigrationTargetField::encode(false) |
   2589                  IsStabilityCheckField::encode(true);
   2590     ClearChangesFlag(kNewSpacePromotion);
   2591     ClearDependsOnFlag(kElementsKind);
   2592     ClearDependsOnFlag(kMaps);
   2593   }
   2594 
   2595   bool HasEscapingOperandAt(int index) override { return false; }
   2596   Representation RequiredInputRepresentation(int index) override {
   2597     return Representation::Tagged();
   2598   }
   2599 
   2600   HType CalculateInferredType() override {
   2601     if (value()->type().IsHeapObject()) return value()->type();
   2602     return HType::HeapObject();
   2603   }
   2604 
   2605   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2606 
   2607   HValue* value() const { return OperandAt(0); }
   2608   HValue* typecheck() const { return OperandAt(1); }
   2609 
   2610   const UniqueSet<Map>* maps() const { return maps_; }
   2611   void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; }
   2612 
   2613   bool maps_are_stable() const {
   2614     return MapsAreStableField::decode(bit_field_);
   2615   }
   2616 
   2617   bool HasMigrationTarget() const {
   2618     return HasMigrationTargetField::decode(bit_field_);
   2619   }
   2620 
   2621   HValue* Canonicalize() override;
   2622 
   2623   static HCheckMaps* CreateAndInsertAfter(Zone* zone,
   2624                                           HValue* value,
   2625                                           Unique<Map> map,
   2626                                           bool map_is_stable,
   2627                                           HInstruction* instr) {
   2628     return instr->Append(new(zone) HCheckMaps(
   2629             value, new(zone) UniqueSet<Map>(map, zone), map_is_stable));
   2630   }
   2631 
   2632   static HCheckMaps* CreateAndInsertBefore(Zone* zone,
   2633                                            HValue* value,
   2634                                            const UniqueSet<Map>* maps,
   2635                                            bool maps_are_stable,
   2636                                            HInstruction* instr) {
   2637     return instr->Prepend(new(zone) HCheckMaps(value, maps, maps_are_stable));
   2638   }
   2639 
   2640   DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
   2641 
   2642  protected:
   2643   bool DataEquals(HValue* other) override {
   2644     return this->maps()->Equals(HCheckMaps::cast(other)->maps());
   2645   }
   2646 
   2647   int RedefinedOperandIndex() override { return 0; }
   2648 
   2649  private:
   2650   HCheckMaps(HValue* value, const UniqueSet<Map>* maps, bool maps_are_stable)
   2651       : HTemplateInstruction<2>(HType::HeapObject()),
   2652         maps_(maps),
   2653         bit_field_(HasMigrationTargetField::encode(false) |
   2654                    IsStabilityCheckField::encode(false) |
   2655                    MapsAreStableField::encode(maps_are_stable)) {
   2656     DCHECK_NE(0, maps->size());
   2657     SetOperandAt(0, value);
   2658     // Use the object value for the dependency.
   2659     SetOperandAt(1, value);
   2660     set_representation(Representation::Tagged());
   2661     SetFlag(kUseGVN);
   2662     SetDependsOnFlag(kMaps);
   2663     SetDependsOnFlag(kElementsKind);
   2664   }
   2665 
   2666   HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck)
   2667       : HTemplateInstruction<2>(HType::HeapObject()),
   2668         maps_(maps),
   2669         bit_field_(HasMigrationTargetField::encode(false) |
   2670                    IsStabilityCheckField::encode(false) |
   2671                    MapsAreStableField::encode(true)) {
   2672     DCHECK_NE(0, maps->size());
   2673     SetOperandAt(0, value);
   2674     // Use the object value for the dependency if NULL is passed.
   2675     SetOperandAt(1, typecheck ? typecheck : value);
   2676     set_representation(Representation::Tagged());
   2677     SetFlag(kUseGVN);
   2678     SetDependsOnFlag(kMaps);
   2679     SetDependsOnFlag(kElementsKind);
   2680     for (int i = 0; i < maps->size(); ++i) {
   2681       Handle<Map> map = maps->at(i).handle();
   2682       if (map->is_migration_target()) {
   2683         bit_field_ = HasMigrationTargetField::update(bit_field_, true);
   2684       }
   2685       if (!map->is_stable()) {
   2686         bit_field_ = MapsAreStableField::update(bit_field_, false);
   2687       }
   2688     }
   2689     if (HasMigrationTarget()) SetChangesFlag(kNewSpacePromotion);
   2690   }
   2691 
   2692   class HasMigrationTargetField : public BitField<bool, 0, 1> {};
   2693   class IsStabilityCheckField : public BitField<bool, 1, 1> {};
   2694   class MapsAreStableField : public BitField<bool, 2, 1> {};
   2695 
   2696   const UniqueSet<Map>* maps_;
   2697   uint32_t bit_field_;
   2698 };
   2699 
   2700 
   2701 class HCheckValue final : public HUnaryOperation {
   2702  public:
   2703   static HCheckValue* New(Isolate* isolate, Zone* zone, HValue* context,
   2704                           HValue* value, Handle<JSFunction> func) {
   2705     bool in_new_space = isolate->heap()->InNewSpace(*func);
   2706     // NOTE: We create an uninitialized Unique and initialize it later.
   2707     // This is because a JSFunction can move due to GC during graph creation.
   2708     Unique<JSFunction> target = Unique<JSFunction>::CreateUninitialized(func);
   2709     HCheckValue* check = new(zone) HCheckValue(value, target, in_new_space);
   2710     return check;
   2711   }
   2712   static HCheckValue* New(Isolate* isolate, Zone* zone, HValue* context,
   2713                           HValue* value, Unique<HeapObject> target,
   2714                           bool object_in_new_space) {
   2715     return new(zone) HCheckValue(value, target, object_in_new_space);
   2716   }
   2717 
   2718   void FinalizeUniqueness() override {
   2719     object_ = Unique<HeapObject>(object_.handle());
   2720   }
   2721 
   2722   Representation RequiredInputRepresentation(int index) override {
   2723     return Representation::Tagged();
   2724   }
   2725   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2726 
   2727   HValue* Canonicalize() override;
   2728 
   2729 #ifdef DEBUG
   2730   void Verify() override;
   2731 #endif
   2732 
   2733   Unique<HeapObject> object() const { return object_; }
   2734   bool object_in_new_space() const { return object_in_new_space_; }
   2735 
   2736   DECLARE_CONCRETE_INSTRUCTION(CheckValue)
   2737 
   2738  protected:
   2739   bool DataEquals(HValue* other) override {
   2740     HCheckValue* b = HCheckValue::cast(other);
   2741     return object_ == b->object_;
   2742   }
   2743 
   2744  private:
   2745   HCheckValue(HValue* value, Unique<HeapObject> object,
   2746                bool object_in_new_space)
   2747       : HUnaryOperation(value, value->type()),
   2748         object_(object),
   2749         object_in_new_space_(object_in_new_space) {
   2750     set_representation(Representation::Tagged());
   2751     SetFlag(kUseGVN);
   2752   }
   2753 
   2754   Unique<HeapObject> object_;
   2755   bool object_in_new_space_;
   2756 };
   2757 
   2758 
   2759 class HCheckInstanceType final : public HUnaryOperation {
   2760  public:
   2761   enum Check {
   2762     IS_JS_RECEIVER,
   2763     IS_JS_ARRAY,
   2764     IS_JS_FUNCTION,
   2765     IS_JS_DATE,
   2766     IS_STRING,
   2767     IS_INTERNALIZED_STRING,
   2768     LAST_INTERVAL_CHECK = IS_JS_DATE
   2769   };
   2770 
   2771   DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue*, Check);
   2772 
   2773   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2774 
   2775   Representation RequiredInputRepresentation(int index) override {
   2776     return Representation::Tagged();
   2777   }
   2778 
   2779   HType CalculateInferredType() override {
   2780     switch (check_) {
   2781       case IS_JS_RECEIVER: return HType::JSReceiver();
   2782       case IS_JS_ARRAY: return HType::JSArray();
   2783       case IS_JS_FUNCTION:
   2784         return HType::JSObject();
   2785       case IS_JS_DATE: return HType::JSObject();
   2786       case IS_STRING: return HType::String();
   2787       case IS_INTERNALIZED_STRING: return HType::String();
   2788     }
   2789     UNREACHABLE();
   2790     return HType::Tagged();
   2791   }
   2792 
   2793   HValue* Canonicalize() override;
   2794 
   2795   bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
   2796   void GetCheckInterval(InstanceType* first, InstanceType* last);
   2797   void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
   2798 
   2799   Check check() const { return check_; }
   2800 
   2801   DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
   2802 
   2803  protected:
   2804   // TODO(ager): It could be nice to allow the ommision of instance
   2805   // type checks if we have already performed an instance type check
   2806   // with a larger range.
   2807   bool DataEquals(HValue* other) override {
   2808     HCheckInstanceType* b = HCheckInstanceType::cast(other);
   2809     return check_ == b->check_;
   2810   }
   2811 
   2812   int RedefinedOperandIndex() override { return 0; }
   2813 
   2814  private:
   2815   const char* GetCheckName() const;
   2816 
   2817   HCheckInstanceType(HValue* value, Check check)
   2818       : HUnaryOperation(value, HType::HeapObject()), check_(check) {
   2819     set_representation(Representation::Tagged());
   2820     SetFlag(kUseGVN);
   2821   }
   2822 
   2823   const Check check_;
   2824 };
   2825 
   2826 
   2827 class HCheckSmi final : public HUnaryOperation {
   2828  public:
   2829   DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue*);
   2830 
   2831   Representation RequiredInputRepresentation(int index) override {
   2832     return Representation::Tagged();
   2833   }
   2834 
   2835   HValue* Canonicalize() override {
   2836     HType value_type = value()->type();
   2837     if (value_type.IsSmi()) {
   2838       return NULL;
   2839     }
   2840     return this;
   2841   }
   2842 
   2843   DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
   2844 
   2845  protected:
   2846   bool DataEquals(HValue* other) override { return true; }
   2847 
   2848  private:
   2849   explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
   2850     set_representation(Representation::Smi());
   2851     SetFlag(kUseGVN);
   2852   }
   2853 };
   2854 
   2855 
   2856 class HCheckArrayBufferNotNeutered final : public HUnaryOperation {
   2857  public:
   2858   DECLARE_INSTRUCTION_FACTORY_P1(HCheckArrayBufferNotNeutered, HValue*);
   2859 
   2860   bool HasEscapingOperandAt(int index) override { return false; }
   2861   Representation RequiredInputRepresentation(int index) override {
   2862     return Representation::Tagged();
   2863   }
   2864 
   2865   HType CalculateInferredType() override {
   2866     if (value()->type().IsHeapObject()) return value()->type();
   2867     return HType::HeapObject();
   2868   }
   2869 
   2870   DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered)
   2871 
   2872  protected:
   2873   bool DataEquals(HValue* other) override { return true; }
   2874   int RedefinedOperandIndex() override { return 0; }
   2875 
   2876  private:
   2877   explicit HCheckArrayBufferNotNeutered(HValue* value)
   2878       : HUnaryOperation(value) {
   2879     set_representation(Representation::Tagged());
   2880     SetFlag(kUseGVN);
   2881     SetDependsOnFlag(kCalls);
   2882   }
   2883 };
   2884 
   2885 
   2886 class HCheckHeapObject final : public HUnaryOperation {
   2887  public:
   2888   DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
   2889 
   2890   bool HasEscapingOperandAt(int index) override { return false; }
   2891   Representation RequiredInputRepresentation(int index) override {
   2892     return Representation::Tagged();
   2893   }
   2894 
   2895   HType CalculateInferredType() override {
   2896     if (value()->type().IsHeapObject()) return value()->type();
   2897     return HType::HeapObject();
   2898   }
   2899 
   2900 #ifdef DEBUG
   2901   void Verify() override;
   2902 #endif
   2903 
   2904   HValue* Canonicalize() override {
   2905     return value()->type().IsHeapObject() ? NULL : this;
   2906   }
   2907 
   2908   DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
   2909 
   2910  protected:
   2911   bool DataEquals(HValue* other) override { return true; }
   2912 
   2913  private:
   2914   explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) {
   2915     set_representation(Representation::Tagged());
   2916     SetFlag(kUseGVN);
   2917   }
   2918 };
   2919 
   2920 
   2921 class HPhi final : public HValue {
   2922  public:
   2923   HPhi(int merged_index, Zone* zone)
   2924       : inputs_(2, zone), merged_index_(merged_index) {
   2925     DCHECK(merged_index >= 0 || merged_index == kInvalidMergedIndex);
   2926     SetFlag(kFlexibleRepresentation);
   2927     SetFlag(kAllowUndefinedAsNaN);
   2928   }
   2929 
   2930   Representation RepresentationFromInputs() override;
   2931 
   2932   Range* InferRange(Zone* zone) override;
   2933   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   2934   Representation RequiredInputRepresentation(int index) override {
   2935     return representation();
   2936   }
   2937   Representation KnownOptimalRepresentation() override {
   2938     return representation();
   2939   }
   2940   HType CalculateInferredType() override;
   2941   int OperandCount() const override { return inputs_.length(); }
   2942   HValue* OperandAt(int index) const override { return inputs_[index]; }
   2943   HValue* GetRedundantReplacement();
   2944   void AddInput(HValue* value);
   2945   bool HasRealUses();
   2946 
   2947   bool IsReceiver() const { return merged_index_ == 0; }
   2948   bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
   2949 
   2950   SourcePosition position() const override;
   2951 
   2952   int merged_index() const { return merged_index_; }
   2953 
   2954   std::ostream& PrintTo(std::ostream& os) const override;  // NOLINT
   2955 
   2956 #ifdef DEBUG
   2957   void Verify() override;
   2958 #endif
   2959 
   2960   void InitRealUses(int id);
   2961   void AddNonPhiUsesFrom(HPhi* other);
   2962 
   2963   Representation representation_from_indirect_uses() const {
   2964     return representation_from_indirect_uses_;
   2965   }
   2966 
   2967   bool has_type_feedback_from_uses() const {
   2968     return has_type_feedback_from_uses_;
   2969   }
   2970 
   2971   int phi_id() { return phi_id_; }
   2972 
   2973   static HPhi* cast(HValue* value) {
   2974     DCHECK(value->IsPhi());
   2975     return reinterpret_cast<HPhi*>(value);
   2976   }
   2977   Opcode opcode() const override { return HValue::kPhi; }
   2978 
   2979   void SimplifyConstantInputs();
   2980 
   2981   // Marker value representing an invalid merge index.
   2982   static const int kInvalidMergedIndex = -1;
   2983 
   2984  protected:
   2985   void DeleteFromGraph() override;
   2986   void InternalSetOperandAt(int index, HValue* value) override {
   2987     inputs_[index] = value;
   2988   }
   2989 
   2990  private:
   2991   Representation representation_from_non_phi_uses() const {
   2992     return representation_from_non_phi_uses_;
   2993   }
   2994 
   2995   ZoneList<HValue*> inputs_;
   2996   int merged_index_ = 0;
   2997 
   2998   int phi_id_ = -1;
   2999 
   3000   Representation representation_from_indirect_uses_ = Representation::None();
   3001   Representation representation_from_non_phi_uses_ = Representation::None();
   3002   bool has_type_feedback_from_uses_ = false;
   3003 
   3004   bool IsDeletable() const override { return !IsReceiver(); }
   3005 };
   3006 
   3007 
   3008 // Common base class for HArgumentsObject and HCapturedObject.
   3009 class HDematerializedObject : public HInstruction {
   3010  public:
   3011   HDematerializedObject(int count, Zone* zone) : values_(count, zone) {}
   3012 
   3013   int OperandCount() const final { return values_.length(); }
   3014   HValue* OperandAt(int index) const final { return values_[index]; }
   3015 
   3016   bool HasEscapingOperandAt(int index) final { return false; }
   3017   Representation RequiredInputRepresentation(int index) final {
   3018     return Representation::None();
   3019   }
   3020 
   3021  protected:
   3022   void InternalSetOperandAt(int index, HValue* value) final {
   3023     values_[index] = value;
   3024   }
   3025 
   3026   // List of values tracked by this marker.
   3027   ZoneList<HValue*> values_;
   3028 };
   3029 
   3030 
   3031 class HArgumentsObject final : public HDematerializedObject {
   3032  public:
   3033   static HArgumentsObject* New(Isolate* isolate, Zone* zone, HValue* context,
   3034                                int count) {
   3035     return new(zone) HArgumentsObject(count, zone);
   3036   }
   3037 
   3038   // The values contain a list of all elements in the arguments object
   3039   // including the receiver object, which is skipped when materializing.
   3040   const ZoneList<HValue*>* arguments_values() const { return &values_; }
   3041   int arguments_count() const { return values_.length(); }
   3042 
   3043   void AddArgument(HValue* argument, Zone* zone) {
   3044     values_.Add(NULL, zone);  // Resize list.
   3045     SetOperandAt(values_.length() - 1, argument);
   3046   }
   3047 
   3048   DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
   3049 
   3050  private:
   3051   HArgumentsObject(int count, Zone* zone)
   3052       : HDematerializedObject(count, zone) {
   3053     set_representation(Representation::Tagged());
   3054     SetFlag(kIsArguments);
   3055   }
   3056 };
   3057 
   3058 
   3059 class HCapturedObject final : public HDematerializedObject {
   3060  public:
   3061   HCapturedObject(int length, int id, Zone* zone)
   3062       : HDematerializedObject(length, zone), capture_id_(id) {
   3063     set_representation(Representation::Tagged());
   3064     values_.AddBlock(NULL, length, zone);  // Resize list.
   3065   }
   3066 
   3067   // The values contain a list of all in-object properties inside the
   3068   // captured object and is index by field index. Properties in the
   3069   // properties or elements backing store are not tracked here.
   3070   const ZoneList<HValue*>* values() const { return &values_; }
   3071   int length() const { return values_.length(); }
   3072   int capture_id() const { return capture_id_; }
   3073 
   3074   // Shortcut for the map value of this captured object.
   3075   HValue* map_value() const { return values()->first(); }
   3076 
   3077   void ReuseSideEffectsFromStore(HInstruction* store) {
   3078     DCHECK(store->HasObservableSideEffects());
   3079     DCHECK(store->IsStoreNamedField());
   3080     changes_flags_.Add(store->ChangesFlags());
   3081   }
   3082 
   3083   // Replay effects of this instruction on the given environment.
   3084   void ReplayEnvironment(HEnvironment* env);
   3085 
   3086   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3087 
   3088   DECLARE_CONCRETE_INSTRUCTION(CapturedObject)
   3089 
   3090  private:
   3091   int capture_id_;
   3092 
   3093   // Note that we cannot DCE captured objects as they are used to replay
   3094   // the environment. This method is here as an explicit reminder.
   3095   // TODO(mstarzinger): Turn HSimulates into full snapshots maybe?
   3096   bool IsDeletable() const final { return false; }
   3097 };
   3098 
   3099 
   3100 class HConstant final : public HTemplateInstruction<0> {
   3101  public:
   3102   enum Special { kHoleNaN };
   3103 
   3104   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Special);
   3105   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, int32_t);
   3106   DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation);
   3107   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double);
   3108   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle<Object>);
   3109   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);
   3110 
   3111   static HConstant* CreateAndInsertAfter(Isolate* isolate, Zone* zone,
   3112                                          HValue* context, int32_t value,
   3113                                          Representation representation,
   3114                                          HInstruction* instruction) {
   3115     return instruction->Append(
   3116         HConstant::New(isolate, zone, context, value, representation));
   3117   }
   3118 
   3119   Handle<Map> GetMonomorphicJSObjectMap() override {
   3120     Handle<Object> object = object_.handle();
   3121     if (!object.is_null() && object->IsHeapObject()) {
   3122       return v8::internal::handle(HeapObject::cast(*object)->map());
   3123     }
   3124     return Handle<Map>();
   3125   }
   3126 
   3127   static HConstant* CreateAndInsertBefore(Isolate* isolate, Zone* zone,
   3128                                           HValue* context, int32_t value,
   3129                                           Representation representation,
   3130                                           HInstruction* instruction) {
   3131     return instruction->Prepend(
   3132         HConstant::New(isolate, zone, context, value, representation));
   3133   }
   3134 
   3135   static HConstant* CreateAndInsertBefore(Zone* zone,
   3136                                           Unique<Map> map,
   3137                                           bool map_is_stable,
   3138                                           HInstruction* instruction) {
   3139     return instruction->Prepend(new(zone) HConstant(
   3140         map, Unique<Map>(Handle<Map>::null()), map_is_stable,
   3141         Representation::Tagged(), HType::HeapObject(), true,
   3142         false, false, MAP_TYPE));
   3143   }
   3144 
   3145   static HConstant* CreateAndInsertAfter(Zone* zone,
   3146                                          Unique<Map> map,
   3147                                          bool map_is_stable,
   3148                                          HInstruction* instruction) {
   3149     return instruction->Append(new(zone) HConstant(
   3150             map, Unique<Map>(Handle<Map>::null()), map_is_stable,
   3151             Representation::Tagged(), HType::HeapObject(), true,
   3152             false, false, MAP_TYPE));
   3153   }
   3154 
   3155   Handle<Object> handle(Isolate* isolate) {
   3156     if (object_.handle().is_null()) {
   3157       // Default arguments to is_not_in_new_space depend on this heap number
   3158       // to be tenured so that it's guaranteed not to be located in new space.
   3159       object_ = Unique<Object>::CreateUninitialized(
   3160           isolate->factory()->NewNumber(double_value_, TENURED));
   3161     }
   3162     AllowDeferredHandleDereference smi_check;
   3163     DCHECK(HasInteger32Value() || !object_.handle()->IsSmi());
   3164     return object_.handle();
   3165   }
   3166 
   3167   bool IsSpecialDouble() const {
   3168     return HasDoubleValue() &&
   3169            (bit_cast<int64_t>(double_value_) == bit_cast<int64_t>(-0.0) ||
   3170             std::isnan(double_value_));
   3171   }
   3172 
   3173   bool NotInNewSpace() const {
   3174     return IsNotInNewSpaceField::decode(bit_field_);
   3175   }
   3176 
   3177   bool ImmortalImmovable() const;
   3178 
   3179   bool IsCell() const {
   3180     InstanceType instance_type = GetInstanceType();
   3181     return instance_type == CELL_TYPE;
   3182   }
   3183 
   3184   Representation RequiredInputRepresentation(int index) override {
   3185     return Representation::None();
   3186   }
   3187 
   3188   Representation KnownOptimalRepresentation() override {
   3189     if (HasSmiValue() && SmiValuesAre31Bits()) return Representation::Smi();
   3190     if (HasInteger32Value()) return Representation::Integer32();
   3191     if (HasNumberValue()) return Representation::Double();
   3192     if (HasExternalReferenceValue()) return Representation::External();
   3193     return Representation::Tagged();
   3194   }
   3195 
   3196   bool EmitAtUses() override;
   3197   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3198   HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
   3199   Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone);
   3200   Maybe<HConstant*> CopyToTruncatedNumber(Isolate* isolate, Zone* zone);
   3201   bool HasInteger32Value() const {
   3202     return HasInt32ValueField::decode(bit_field_);
   3203   }
   3204   int32_t Integer32Value() const {
   3205     DCHECK(HasInteger32Value());
   3206     return int32_value_;
   3207   }
   3208   bool HasSmiValue() const { return HasSmiValueField::decode(bit_field_); }
   3209   bool HasDoubleValue() const {
   3210     return HasDoubleValueField::decode(bit_field_);
   3211   }
   3212   double DoubleValue() const {
   3213     DCHECK(HasDoubleValue());
   3214     return double_value_;
   3215   }
   3216   uint64_t DoubleValueAsBits() const {
   3217     uint64_t bits;
   3218     DCHECK(HasDoubleValue());
   3219     STATIC_ASSERT(sizeof(bits) == sizeof(double_value_));
   3220     std::memcpy(&bits, &double_value_, sizeof(bits));
   3221     return bits;
   3222   }
   3223   bool IsTheHole() const {
   3224     if (HasDoubleValue() && DoubleValueAsBits() == kHoleNanInt64) {
   3225       return true;
   3226     }
   3227     return object_.IsInitialized() &&
   3228            object_.IsKnownGlobal(isolate()->heap()->the_hole_value());
   3229   }
   3230   bool HasNumberValue() const { return HasDoubleValue(); }
   3231   int32_t NumberValueAsInteger32() const {
   3232     DCHECK(HasNumberValue());
   3233     // Irrespective of whether a numeric HConstant can be safely
   3234     // represented as an int32, we store the (in some cases lossy)
   3235     // representation of the number in int32_value_.
   3236     return int32_value_;
   3237   }
   3238   bool HasStringValue() const {
   3239     if (HasNumberValue()) return false;
   3240     DCHECK(!object_.handle().is_null());
   3241     return GetInstanceType() < FIRST_NONSTRING_TYPE;
   3242   }
   3243   Handle<String> StringValue() const {
   3244     DCHECK(HasStringValue());
   3245     return Handle<String>::cast(object_.handle());
   3246   }
   3247   bool HasInternalizedStringValue() const {
   3248     return HasStringValue() && StringShape(GetInstanceType()).IsInternalized();
   3249   }
   3250 
   3251   bool HasExternalReferenceValue() const {
   3252     return HasExternalReferenceValueField::decode(bit_field_);
   3253   }
   3254   ExternalReference ExternalReferenceValue() const {
   3255     return external_reference_value_;
   3256   }
   3257 
   3258   bool HasBooleanValue() const { return type_.IsBoolean(); }
   3259   bool BooleanValue() const { return BooleanValueField::decode(bit_field_); }
   3260   bool IsCallable() const { return IsCallableField::decode(bit_field_); }
   3261   bool IsUndetectable() const {
   3262     return IsUndetectableField::decode(bit_field_);
   3263   }
   3264   InstanceType GetInstanceType() const {
   3265     return InstanceTypeField::decode(bit_field_);
   3266   }
   3267 
   3268   bool HasMapValue() const { return GetInstanceType() == MAP_TYPE; }
   3269   Unique<Map> MapValue() const {
   3270     DCHECK(HasMapValue());
   3271     return Unique<Map>::cast(GetUnique());
   3272   }
   3273   bool HasStableMapValue() const {
   3274     DCHECK(HasMapValue() || !HasStableMapValueField::decode(bit_field_));
   3275     return HasStableMapValueField::decode(bit_field_);
   3276   }
   3277 
   3278   bool HasObjectMap() const { return !object_map_.IsNull(); }
   3279   Unique<Map> ObjectMap() const {
   3280     DCHECK(HasObjectMap());
   3281     return object_map_;
   3282   }
   3283 
   3284   intptr_t Hashcode() override {
   3285     if (HasInteger32Value()) {
   3286       return static_cast<intptr_t>(int32_value_);
   3287     } else if (HasDoubleValue()) {
   3288       uint64_t bits = DoubleValueAsBits();
   3289       if (sizeof(bits) > sizeof(intptr_t)) {
   3290         bits ^= (bits >> 32);
   3291       }
   3292       return static_cast<intptr_t>(bits);
   3293     } else if (HasExternalReferenceValue()) {
   3294       return reinterpret_cast<intptr_t>(external_reference_value_.address());
   3295     } else {
   3296       DCHECK(!object_.handle().is_null());
   3297       return object_.Hashcode();
   3298     }
   3299   }
   3300 
   3301   void FinalizeUniqueness() override {
   3302     if (!HasDoubleValue() && !HasExternalReferenceValue()) {
   3303       DCHECK(!object_.handle().is_null());
   3304       object_ = Unique<Object>(object_.handle());
   3305     }
   3306   }
   3307 
   3308   Unique<Object> GetUnique() const {
   3309     return object_;
   3310   }
   3311 
   3312   bool EqualsUnique(Unique<Object> other) const {
   3313     return object_.IsInitialized() && object_ == other;
   3314   }
   3315 
   3316   bool DataEquals(HValue* other) override {
   3317     HConstant* other_constant = HConstant::cast(other);
   3318     if (HasInteger32Value()) {
   3319       return other_constant->HasInteger32Value() &&
   3320              int32_value_ == other_constant->int32_value_;
   3321     } else if (HasDoubleValue()) {
   3322       return other_constant->HasDoubleValue() &&
   3323              std::memcmp(&double_value_, &other_constant->double_value_,
   3324                          sizeof(double_value_)) == 0;
   3325     } else if (HasExternalReferenceValue()) {
   3326       return other_constant->HasExternalReferenceValue() &&
   3327              external_reference_value_ ==
   3328                  other_constant->external_reference_value_;
   3329     } else {
   3330       if (other_constant->HasInteger32Value() ||
   3331           other_constant->HasDoubleValue() ||
   3332           other_constant->HasExternalReferenceValue()) {
   3333         return false;
   3334       }
   3335       DCHECK(!object_.handle().is_null());
   3336       return other_constant->object_ == object_;
   3337     }
   3338   }
   3339 
   3340 #ifdef DEBUG
   3341   void Verify() override {}
   3342 #endif
   3343 
   3344   DECLARE_CONCRETE_INSTRUCTION(Constant)
   3345 
   3346  protected:
   3347   Range* InferRange(Zone* zone) override;
   3348 
   3349  private:
   3350   friend class HGraph;
   3351   explicit HConstant(Special special);
   3352   explicit HConstant(Handle<Object> handle,
   3353                      Representation r = Representation::None());
   3354   HConstant(int32_t value,
   3355             Representation r = Representation::None(),
   3356             bool is_not_in_new_space = true,
   3357             Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
   3358   HConstant(double value,
   3359             Representation r = Representation::None(),
   3360             bool is_not_in_new_space = true,
   3361             Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
   3362   HConstant(Unique<Object> object,
   3363             Unique<Map> object_map,
   3364             bool has_stable_map_value,
   3365             Representation r,
   3366             HType type,
   3367             bool is_not_in_new_space,
   3368             bool boolean_value,
   3369             bool is_undetectable,
   3370             InstanceType instance_type);
   3371 
   3372   explicit HConstant(ExternalReference reference);
   3373 
   3374   void Initialize(Representation r);
   3375 
   3376   bool IsDeletable() const override { return true; }
   3377 
   3378   // If object_ is a map, this indicates whether the map is stable.
   3379   class HasStableMapValueField : public BitField<bool, 0, 1> {};
   3380 
   3381   // We store the HConstant in the most specific form safely possible.
   3382   // These flags tell us if the respective member fields hold valid, safe
   3383   // representations of the constant. More specific flags imply more general
   3384   // flags, but not the converse (i.e. smi => int32 => double).
   3385   class HasSmiValueField : public BitField<bool, 1, 1> {};
   3386   class HasInt32ValueField : public BitField<bool, 2, 1> {};
   3387   class HasDoubleValueField : public BitField<bool, 3, 1> {};
   3388 
   3389   class HasExternalReferenceValueField : public BitField<bool, 4, 1> {};
   3390   class IsNotInNewSpaceField : public BitField<bool, 5, 1> {};
   3391   class BooleanValueField : public BitField<bool, 6, 1> {};
   3392   class IsUndetectableField : public BitField<bool, 7, 1> {};
   3393   class IsCallableField : public BitField<bool, 8, 1> {};
   3394 
   3395   static const InstanceType kUnknownInstanceType = FILLER_TYPE;
   3396   class InstanceTypeField : public BitField<InstanceType, 16, 8> {};
   3397 
   3398   // If this is a numerical constant, object_ either points to the
   3399   // HeapObject the constant originated from or is null.  If the
   3400   // constant is non-numeric, object_ always points to a valid
   3401   // constant HeapObject.
   3402   Unique<Object> object_;
   3403 
   3404   // If object_ is a heap object, this points to the stable map of the object.
   3405   Unique<Map> object_map_;
   3406 
   3407   uint32_t bit_field_;
   3408 
   3409   int32_t int32_value_;
   3410   double double_value_;
   3411   ExternalReference external_reference_value_;
   3412 };
   3413 
   3414 
   3415 class HBinaryOperation : public HTemplateInstruction<3> {
   3416  public:
   3417   HBinaryOperation(HValue* context, HValue* left, HValue* right,
   3418                    HType type = HType::Tagged())
   3419       : HTemplateInstruction<3>(type),
   3420         observed_output_representation_(Representation::None()) {
   3421     DCHECK(left != NULL && right != NULL);
   3422     SetOperandAt(0, context);
   3423     SetOperandAt(1, left);
   3424     SetOperandAt(2, right);
   3425     observed_input_representation_[0] = Representation::None();
   3426     observed_input_representation_[1] = Representation::None();
   3427   }
   3428 
   3429   HValue* context() const { return OperandAt(0); }
   3430   HValue* left() const { return OperandAt(1); }
   3431   HValue* right() const { return OperandAt(2); }
   3432 
   3433   // True if switching left and right operands likely generates better code.
   3434   bool AreOperandsBetterSwitched() {
   3435     if (!IsCommutative()) return false;
   3436 
   3437     // Constant operands are better off on the right, they can be inlined in
   3438     // many situations on most platforms.
   3439     if (left()->IsConstant()) return true;
   3440     if (right()->IsConstant()) return false;
   3441 
   3442     // Otherwise, if there is only one use of the right operand, it would be
   3443     // better off on the left for platforms that only have 2-arg arithmetic
   3444     // ops (e.g ia32, x64) that clobber the left operand.
   3445     return right()->HasOneUse();
   3446   }
   3447 
   3448   HValue* BetterLeftOperand() {
   3449     return AreOperandsBetterSwitched() ? right() : left();
   3450   }
   3451 
   3452   HValue* BetterRightOperand() {
   3453     return AreOperandsBetterSwitched() ? left() : right();
   3454   }
   3455 
   3456   void set_observed_input_representation(int index, Representation rep) {
   3457     DCHECK(index >= 1 && index <= 2);
   3458     observed_input_representation_[index - 1] = rep;
   3459   }
   3460 
   3461   virtual void initialize_output_representation(Representation observed) {
   3462     observed_output_representation_ = observed;
   3463   }
   3464 
   3465   Representation observed_input_representation(int index) override {
   3466     if (index == 0) return Representation::Tagged();
   3467     return observed_input_representation_[index - 1];
   3468   }
   3469 
   3470   void UpdateRepresentation(Representation new_rep,
   3471                             HInferRepresentationPhase* h_infer,
   3472                             const char* reason) override {
   3473     Representation rep = !FLAG_smi_binop && new_rep.IsSmi()
   3474         ? Representation::Integer32() : new_rep;
   3475     HValue::UpdateRepresentation(rep, h_infer, reason);
   3476   }
   3477 
   3478   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   3479   Representation RepresentationFromInputs() override;
   3480   Representation RepresentationFromOutput();
   3481   void AssumeRepresentation(Representation r) override;
   3482 
   3483   virtual bool IsCommutative() const { return false; }
   3484 
   3485   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3486 
   3487   Representation RequiredInputRepresentation(int index) override {
   3488     if (index == 0) return Representation::Tagged();
   3489     return representation();
   3490   }
   3491 
   3492   void SetOperandPositions(Zone* zone, SourcePosition left_pos,
   3493                            SourcePosition right_pos) {
   3494     set_operand_position(zone, 1, left_pos);
   3495     set_operand_position(zone, 2, right_pos);
   3496   }
   3497 
   3498   bool RightIsPowerOf2() {
   3499     if (!right()->IsInteger32Constant()) return false;
   3500     int32_t value = right()->GetInteger32Constant();
   3501     if (value < 0) {
   3502       return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(-value));
   3503     }
   3504     return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(value));
   3505   }
   3506 
   3507   DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
   3508 
   3509  private:
   3510   bool IgnoreObservedOutputRepresentation(Representation current_rep);
   3511 
   3512   Representation observed_input_representation_[2];
   3513   Representation observed_output_representation_;
   3514 };
   3515 
   3516 
   3517 class HWrapReceiver final : public HTemplateInstruction<2> {
   3518  public:
   3519   DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
   3520 
   3521   bool DataEquals(HValue* other) override { return true; }
   3522 
   3523   Representation RequiredInputRepresentation(int index) override {
   3524     return Representation::Tagged();
   3525   }
   3526 
   3527   HValue* receiver() const { return OperandAt(0); }
   3528   HValue* function() const { return OperandAt(1); }
   3529 
   3530   HValue* Canonicalize() override;
   3531 
   3532   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3533   bool known_function() const { return known_function_; }
   3534 
   3535   DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
   3536 
   3537  private:
   3538   HWrapReceiver(HValue* receiver, HValue* function) {
   3539     known_function_ = function->IsConstant() &&
   3540         HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
   3541     set_representation(Representation::Tagged());
   3542     SetOperandAt(0, receiver);
   3543     SetOperandAt(1, function);
   3544     SetFlag(kUseGVN);
   3545   }
   3546 
   3547   bool known_function_;
   3548 };
   3549 
   3550 
   3551 class HApplyArguments final : public HTemplateInstruction<4> {
   3552  public:
   3553   DECLARE_INSTRUCTION_FACTORY_P5(HApplyArguments, HValue*, HValue*, HValue*,
   3554                                  HValue*, TailCallMode);
   3555 
   3556   Representation RequiredInputRepresentation(int index) override {
   3557     // The length is untagged, all other inputs are tagged.
   3558     return (index == 2)
   3559         ? Representation::Integer32()
   3560         : Representation::Tagged();
   3561   }
   3562 
   3563   HValue* function() { return OperandAt(0); }
   3564   HValue* receiver() { return OperandAt(1); }
   3565   HValue* length() { return OperandAt(2); }
   3566   HValue* elements() { return OperandAt(3); }
   3567 
   3568   TailCallMode tail_call_mode() const {
   3569     return TailCallModeField::decode(bit_field_);
   3570   }
   3571 
   3572   DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
   3573 
   3574  private:
   3575   HApplyArguments(HValue* function, HValue* receiver, HValue* length,
   3576                   HValue* elements, TailCallMode tail_call_mode)
   3577       : bit_field_(TailCallModeField::encode(tail_call_mode)) {
   3578     set_representation(Representation::Tagged());
   3579     SetOperandAt(0, function);
   3580     SetOperandAt(1, receiver);
   3581     SetOperandAt(2, length);
   3582     SetOperandAt(3, elements);
   3583     SetAllSideEffects();
   3584   }
   3585 
   3586   class TailCallModeField : public BitField<TailCallMode, 0, 1> {};
   3587   uint32_t bit_field_;
   3588 };
   3589 
   3590 
   3591 class HArgumentsElements final : public HTemplateInstruction<0> {
   3592  public:
   3593   DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
   3594   DECLARE_INSTRUCTION_FACTORY_P2(HArgumentsElements, bool, bool);
   3595 
   3596   DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
   3597 
   3598   Representation RequiredInputRepresentation(int index) override {
   3599     return Representation::None();
   3600   }
   3601 
   3602   bool from_inlined() const { return from_inlined_; }
   3603   bool arguments_adaptor() const { return arguments_adaptor_; }
   3604 
   3605  protected:
   3606   bool DataEquals(HValue* other) override { return true; }
   3607 
   3608  private:
   3609   explicit HArgumentsElements(bool from_inlined, bool arguments_adaptor = true)
   3610       : from_inlined_(from_inlined), arguments_adaptor_(arguments_adaptor) {
   3611     // The value produced by this instruction is a pointer into the stack
   3612     // that looks as if it was a smi because of alignment.
   3613     set_representation(Representation::Tagged());
   3614     SetFlag(kUseGVN);
   3615   }
   3616 
   3617   bool IsDeletable() const override { return true; }
   3618 
   3619   bool from_inlined_;
   3620   bool arguments_adaptor_;
   3621 };
   3622 
   3623 
   3624 class HArgumentsLength final : public HUnaryOperation {
   3625  public:
   3626   DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue*);
   3627 
   3628   Representation RequiredInputRepresentation(int index) override {
   3629     return Representation::Tagged();
   3630   }
   3631 
   3632   DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
   3633 
   3634  protected:
   3635   bool DataEquals(HValue* other) override { return true; }
   3636 
   3637  private:
   3638   explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
   3639     set_representation(Representation::Integer32());
   3640     SetFlag(kUseGVN);
   3641   }
   3642 
   3643   bool IsDeletable() const override { return true; }
   3644 };
   3645 
   3646 
   3647 class HAccessArgumentsAt final : public HTemplateInstruction<3> {
   3648  public:
   3649   DECLARE_INSTRUCTION_FACTORY_P3(HAccessArgumentsAt, HValue*, HValue*, HValue*);
   3650 
   3651   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3652 
   3653   Representation RequiredInputRepresentation(int index) override {
   3654     // The arguments elements is considered tagged.
   3655     return index == 0
   3656         ? Representation::Tagged()
   3657         : Representation::Integer32();
   3658   }
   3659 
   3660   HValue* arguments() const { return OperandAt(0); }
   3661   HValue* length() const { return OperandAt(1); }
   3662   HValue* index() const { return OperandAt(2); }
   3663 
   3664   DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
   3665 
   3666  private:
   3667   HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
   3668     set_representation(Representation::Tagged());
   3669     SetFlag(kUseGVN);
   3670     SetOperandAt(0, arguments);
   3671     SetOperandAt(1, length);
   3672     SetOperandAt(2, index);
   3673   }
   3674 
   3675   bool DataEquals(HValue* other) override { return true; }
   3676 };
   3677 
   3678 
   3679 class HBoundsCheck final : public HTemplateInstruction<2> {
   3680  public:
   3681   DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
   3682 
   3683   bool skip_check() const { return skip_check_; }
   3684   void set_skip_check() { skip_check_ = true; }
   3685 
   3686   HValue* base() const { return base_; }
   3687   int offset() const { return offset_; }
   3688   int scale() const { return scale_; }
   3689 
   3690   Representation RequiredInputRepresentation(int index) override {
   3691     return representation();
   3692   }
   3693 
   3694   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3695   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   3696 
   3697   HValue* index() const { return OperandAt(0); }
   3698   HValue* length() const { return OperandAt(1); }
   3699   bool allow_equality() const { return allow_equality_; }
   3700   void set_allow_equality(bool v) { allow_equality_ = v; }
   3701 
   3702   int RedefinedOperandIndex() override { return 0; }
   3703   bool IsPurelyInformativeDefinition() override { return skip_check(); }
   3704 
   3705   DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
   3706 
   3707  protected:
   3708   Range* InferRange(Zone* zone) override;
   3709 
   3710   bool DataEquals(HValue* other) override { return true; }
   3711   bool skip_check_;
   3712   HValue* base_;
   3713   int offset_;
   3714   int scale_;
   3715   bool allow_equality_;
   3716 
   3717  private:
   3718   // Normally HBoundsCheck should be created using the
   3719   // HGraphBuilder::AddBoundsCheck() helper.
   3720   // However when building stubs, where we know that the arguments are Int32,
   3721   // it makes sense to invoke this constructor directly.
   3722   HBoundsCheck(HValue* index, HValue* length)
   3723     : skip_check_(false),
   3724       base_(NULL), offset_(0), scale_(0),
   3725       allow_equality_(false) {
   3726     SetOperandAt(0, index);
   3727     SetOperandAt(1, length);
   3728     SetFlag(kFlexibleRepresentation);
   3729     SetFlag(kUseGVN);
   3730   }
   3731 
   3732   bool IsDeletable() const override { return skip_check() && !FLAG_debug_code; }
   3733 };
   3734 
   3735 
   3736 class HBitwiseBinaryOperation : public HBinaryOperation {
   3737  public:
   3738   HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
   3739                           HType type = HType::TaggedNumber())
   3740       : HBinaryOperation(context, left, right, type) {
   3741     SetFlag(kFlexibleRepresentation);
   3742     SetFlag(kTruncatingToInt32);
   3743     SetFlag(kAllowUndefinedAsNaN);
   3744     SetAllSideEffects();
   3745   }
   3746 
   3747   void RepresentationChanged(Representation to) override {
   3748     if (to.IsTagged() &&
   3749         (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
   3750       SetAllSideEffects();
   3751       ClearFlag(kUseGVN);
   3752     } else {
   3753       ClearAllSideEffects();
   3754       SetFlag(kUseGVN);
   3755     }
   3756     if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
   3757   }
   3758 
   3759   void UpdateRepresentation(Representation new_rep,
   3760                             HInferRepresentationPhase* h_infer,
   3761                             const char* reason) override {
   3762     // We only generate either int32 or generic tagged bitwise operations.
   3763     if (new_rep.IsDouble()) new_rep = Representation::Integer32();
   3764     HBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   3765   }
   3766 
   3767   Representation observed_input_representation(int index) override {
   3768     Representation r = HBinaryOperation::observed_input_representation(index);
   3769     if (r.IsDouble()) return Representation::Integer32();
   3770     return r;
   3771   }
   3772 
   3773   void initialize_output_representation(Representation observed) override {
   3774     if (observed.IsDouble()) observed = Representation::Integer32();
   3775     HBinaryOperation::initialize_output_representation(observed);
   3776   }
   3777 
   3778   DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
   3779 
   3780  private:
   3781   bool IsDeletable() const override { return true; }
   3782 };
   3783 
   3784 
   3785 class HMathFloorOfDiv final : public HBinaryOperation {
   3786  public:
   3787   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HMathFloorOfDiv,
   3788                                               HValue*,
   3789                                               HValue*);
   3790 
   3791   DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
   3792 
   3793  protected:
   3794   bool DataEquals(HValue* other) override { return true; }
   3795 
   3796  private:
   3797   HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
   3798       : HBinaryOperation(context, left, right) {
   3799     set_representation(Representation::Integer32());
   3800     SetFlag(kUseGVN);
   3801     SetFlag(kCanOverflow);
   3802     SetFlag(kCanBeDivByZero);
   3803     SetFlag(kLeftCanBeMinInt);
   3804     SetFlag(kLeftCanBeNegative);
   3805     SetFlag(kLeftCanBePositive);
   3806     SetFlag(kAllowUndefinedAsNaN);
   3807   }
   3808 
   3809   Range* InferRange(Zone* zone) override;
   3810 
   3811   bool IsDeletable() const override { return true; }
   3812 };
   3813 
   3814 
   3815 class HArithmeticBinaryOperation : public HBinaryOperation {
   3816  public:
   3817   HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right)
   3818       : HBinaryOperation(context, left, right, HType::TaggedNumber()) {
   3819     SetAllSideEffects();
   3820     SetFlag(kFlexibleRepresentation);
   3821     SetFlag(kAllowUndefinedAsNaN);
   3822   }
   3823 
   3824   void RepresentationChanged(Representation to) override {
   3825     if (to.IsTagged() &&
   3826         (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
   3827       SetAllSideEffects();
   3828       ClearFlag(kUseGVN);
   3829     } else {
   3830       ClearAllSideEffects();
   3831       SetFlag(kUseGVN);
   3832     }
   3833     if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
   3834   }
   3835 
   3836   DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
   3837 
   3838  private:
   3839   bool IsDeletable() const override { return true; }
   3840 };
   3841 
   3842 
   3843 class HCompareGeneric final : public HBinaryOperation {
   3844  public:
   3845   static HCompareGeneric* New(Isolate* isolate, Zone* zone, HValue* context,
   3846                               HValue* left, HValue* right, Token::Value token) {
   3847     return new (zone) HCompareGeneric(context, left, right, token);
   3848   }
   3849 
   3850   Representation RequiredInputRepresentation(int index) override {
   3851     return index == 0
   3852         ? Representation::Tagged()
   3853         : representation();
   3854   }
   3855 
   3856   Token::Value token() const { return token_; }
   3857   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3858 
   3859   DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
   3860 
   3861  private:
   3862   HCompareGeneric(HValue* context, HValue* left, HValue* right,
   3863                   Token::Value token)
   3864       : HBinaryOperation(context, left, right, HType::Boolean()),
   3865         token_(token) {
   3866     DCHECK(Token::IsCompareOp(token));
   3867     set_representation(Representation::Tagged());
   3868     SetAllSideEffects();
   3869   }
   3870 
   3871   Token::Value token_;
   3872 };
   3873 
   3874 
   3875 class HCompareNumericAndBranch : public HTemplateControlInstruction<2, 2> {
   3876  public:
   3877   static HCompareNumericAndBranch* New(Isolate* isolate, Zone* zone,
   3878                                        HValue* context, HValue* left,
   3879                                        HValue* right, Token::Value token,
   3880                                        HBasicBlock* true_target = NULL,
   3881                                        HBasicBlock* false_target = NULL) {
   3882     return new (zone)
   3883         HCompareNumericAndBranch(left, right, token, true_target, false_target);
   3884   }
   3885 
   3886   HValue* left() const { return OperandAt(0); }
   3887   HValue* right() const { return OperandAt(1); }
   3888   Token::Value token() const { return token_; }
   3889 
   3890   void set_observed_input_representation(Representation left,
   3891                                          Representation right) {
   3892       observed_input_representation_[0] = left;
   3893       observed_input_representation_[1] = right;
   3894   }
   3895 
   3896   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   3897 
   3898   Representation RequiredInputRepresentation(int index) override {
   3899     return representation();
   3900   }
   3901   Representation observed_input_representation(int index) override {
   3902     return observed_input_representation_[index];
   3903   }
   3904 
   3905   bool KnownSuccessorBlock(HBasicBlock** block) override;
   3906 
   3907   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3908 
   3909   void SetOperandPositions(Zone* zone, SourcePosition left_pos,
   3910                            SourcePosition right_pos) {
   3911     set_operand_position(zone, 0, left_pos);
   3912     set_operand_position(zone, 1, right_pos);
   3913   }
   3914 
   3915   DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
   3916 
   3917  private:
   3918   HCompareNumericAndBranch(HValue* left, HValue* right, Token::Value token,
   3919                            HBasicBlock* true_target, HBasicBlock* false_target)
   3920       : token_(token) {
   3921     SetFlag(kFlexibleRepresentation);
   3922     DCHECK(Token::IsCompareOp(token));
   3923     SetOperandAt(0, left);
   3924     SetOperandAt(1, right);
   3925     SetSuccessorAt(0, true_target);
   3926     SetSuccessorAt(1, false_target);
   3927   }
   3928 
   3929   Representation observed_input_representation_[2];
   3930   Token::Value token_;
   3931 };
   3932 
   3933 
   3934 class HCompareHoleAndBranch final : public HUnaryControlInstruction {
   3935  public:
   3936   DECLARE_INSTRUCTION_FACTORY_P1(HCompareHoleAndBranch, HValue*);
   3937   DECLARE_INSTRUCTION_FACTORY_P3(HCompareHoleAndBranch, HValue*,
   3938                                  HBasicBlock*, HBasicBlock*);
   3939 
   3940   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   3941 
   3942   Representation RequiredInputRepresentation(int index) override {
   3943     return representation();
   3944   }
   3945 
   3946   DECLARE_CONCRETE_INSTRUCTION(CompareHoleAndBranch)
   3947 
   3948  private:
   3949   HCompareHoleAndBranch(HValue* value,
   3950                         HBasicBlock* true_target = NULL,
   3951                         HBasicBlock* false_target = NULL)
   3952       : HUnaryControlInstruction(value, true_target, false_target) {
   3953     SetFlag(kFlexibleRepresentation);
   3954     SetFlag(kAllowUndefinedAsNaN);
   3955   }
   3956 };
   3957 
   3958 
   3959 class HCompareObjectEqAndBranch : public HTemplateControlInstruction<2, 2> {
   3960  public:
   3961   DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue*, HValue*);
   3962   DECLARE_INSTRUCTION_FACTORY_P4(HCompareObjectEqAndBranch, HValue*, HValue*,
   3963                                  HBasicBlock*, HBasicBlock*);
   3964 
   3965   bool KnownSuccessorBlock(HBasicBlock** block) override;
   3966 
   3967   static const int kNoKnownSuccessorIndex = -1;
   3968   int known_successor_index() const { return known_successor_index_; }
   3969   void set_known_successor_index(int known_successor_index) {
   3970     known_successor_index_ = known_successor_index;
   3971   }
   3972 
   3973   HValue* left() const { return OperandAt(0); }
   3974   HValue* right() const { return OperandAt(1); }
   3975 
   3976   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3977 
   3978   Representation RequiredInputRepresentation(int index) override {
   3979     return Representation::Tagged();
   3980   }
   3981 
   3982   Representation observed_input_representation(int index) override {
   3983     return Representation::Tagged();
   3984   }
   3985 
   3986   DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
   3987 
   3988  private:
   3989   HCompareObjectEqAndBranch(HValue* left,
   3990                             HValue* right,
   3991                             HBasicBlock* true_target = NULL,
   3992                             HBasicBlock* false_target = NULL)
   3993       : known_successor_index_(kNoKnownSuccessorIndex) {
   3994     SetOperandAt(0, left);
   3995     SetOperandAt(1, right);
   3996     SetSuccessorAt(0, true_target);
   3997     SetSuccessorAt(1, false_target);
   3998   }
   3999 
   4000   int known_successor_index_;
   4001 };
   4002 
   4003 
   4004 class HIsStringAndBranch final : public HUnaryControlInstruction {
   4005  public:
   4006   DECLARE_INSTRUCTION_FACTORY_P1(HIsStringAndBranch, HValue*);
   4007   DECLARE_INSTRUCTION_FACTORY_P3(HIsStringAndBranch, HValue*,
   4008                                  HBasicBlock*, HBasicBlock*);
   4009 
   4010   Representation RequiredInputRepresentation(int index) override {
   4011     return Representation::Tagged();
   4012   }
   4013 
   4014   bool KnownSuccessorBlock(HBasicBlock** block) override;
   4015 
   4016   static const int kNoKnownSuccessorIndex = -1;
   4017   int known_successor_index() const { return known_successor_index_; }
   4018   void set_known_successor_index(int known_successor_index) {
   4019     known_successor_index_ = known_successor_index;
   4020   }
   4021 
   4022   DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
   4023 
   4024  protected:
   4025   int RedefinedOperandIndex() override { return 0; }
   4026 
   4027  private:
   4028   HIsStringAndBranch(HValue* value, HBasicBlock* true_target = NULL,
   4029                      HBasicBlock* false_target = NULL)
   4030       : HUnaryControlInstruction(value, true_target, false_target),
   4031         known_successor_index_(kNoKnownSuccessorIndex) {
   4032     set_representation(Representation::Tagged());
   4033   }
   4034 
   4035   int known_successor_index_;
   4036 };
   4037 
   4038 
   4039 class HIsSmiAndBranch final : public HUnaryControlInstruction {
   4040  public:
   4041   DECLARE_INSTRUCTION_FACTORY_P1(HIsSmiAndBranch, HValue*);
   4042   DECLARE_INSTRUCTION_FACTORY_P3(HIsSmiAndBranch, HValue*,
   4043                                  HBasicBlock*, HBasicBlock*);
   4044 
   4045   DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
   4046 
   4047   Representation RequiredInputRepresentation(int index) override {
   4048     return Representation::Tagged();
   4049   }
   4050 
   4051  protected:
   4052   bool DataEquals(HValue* other) override { return true; }
   4053   int RedefinedOperandIndex() override { return 0; }
   4054 
   4055  private:
   4056   HIsSmiAndBranch(HValue* value,
   4057                   HBasicBlock* true_target = NULL,
   4058                   HBasicBlock* false_target = NULL)
   4059       : HUnaryControlInstruction(value, true_target, false_target) {
   4060     set_representation(Representation::Tagged());
   4061   }
   4062 };
   4063 
   4064 
   4065 class HIsUndetectableAndBranch final : public HUnaryControlInstruction {
   4066  public:
   4067   DECLARE_INSTRUCTION_FACTORY_P1(HIsUndetectableAndBranch, HValue*);
   4068   DECLARE_INSTRUCTION_FACTORY_P3(HIsUndetectableAndBranch, HValue*,
   4069                                  HBasicBlock*, HBasicBlock*);
   4070 
   4071   Representation RequiredInputRepresentation(int index) override {
   4072     return Representation::Tagged();
   4073   }
   4074 
   4075   bool KnownSuccessorBlock(HBasicBlock** block) override;
   4076 
   4077   DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
   4078 
   4079  private:
   4080   HIsUndetectableAndBranch(HValue* value,
   4081                            HBasicBlock* true_target = NULL,
   4082                            HBasicBlock* false_target = NULL)
   4083       : HUnaryControlInstruction(value, true_target, false_target) {}
   4084 };
   4085 
   4086 
   4087 class HStringCompareAndBranch final : public HTemplateControlInstruction<2, 3> {
   4088  public:
   4089   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HStringCompareAndBranch,
   4090                                               HValue*,
   4091                                               HValue*,
   4092                                               Token::Value);
   4093 
   4094   HValue* context() const { return OperandAt(0); }
   4095   HValue* left() const { return OperandAt(1); }
   4096   HValue* right() const { return OperandAt(2); }
   4097   Token::Value token() const { return token_; }
   4098 
   4099   std::ostream& PrintDataTo(std::ostream& os) const final;  // NOLINT
   4100 
   4101   Representation RequiredInputRepresentation(int index) final {
   4102     return Representation::Tagged();
   4103   }
   4104 
   4105   DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
   4106 
   4107  private:
   4108   HStringCompareAndBranch(HValue* context, HValue* left, HValue* right,
   4109                           Token::Value token)
   4110       : token_(token) {
   4111     DCHECK(Token::IsCompareOp(token));
   4112     SetOperandAt(0, context);
   4113     SetOperandAt(1, left);
   4114     SetOperandAt(2, right);
   4115     set_representation(Representation::Tagged());
   4116     SetChangesFlag(kNewSpacePromotion);
   4117     SetDependsOnFlag(kStringChars);
   4118     SetDependsOnFlag(kStringLengths);
   4119   }
   4120 
   4121   Token::Value const token_;
   4122 };
   4123 
   4124 
   4125 class HHasInstanceTypeAndBranch final : public HUnaryControlInstruction {
   4126  public:
   4127   DECLARE_INSTRUCTION_FACTORY_P2(
   4128       HHasInstanceTypeAndBranch, HValue*, InstanceType);
   4129   DECLARE_INSTRUCTION_FACTORY_P3(
   4130       HHasInstanceTypeAndBranch, HValue*, InstanceType, InstanceType);
   4131 
   4132   InstanceType from() { return from_; }
   4133   InstanceType to() { return to_; }
   4134 
   4135   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4136 
   4137   Representation RequiredInputRepresentation(int index) override {
   4138     return Representation::Tagged();
   4139   }
   4140 
   4141   bool KnownSuccessorBlock(HBasicBlock** block) override;
   4142 
   4143   DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
   4144 
   4145  private:
   4146   HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
   4147       : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
   4148   HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
   4149       : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
   4150     DCHECK(to == LAST_TYPE);  // Others not implemented yet in backend.
   4151   }
   4152 
   4153   InstanceType from_;
   4154   InstanceType to_;  // Inclusive range, not all combinations work.
   4155 };
   4156 
   4157 
   4158 class HHasCachedArrayIndexAndBranch final : public HUnaryControlInstruction {
   4159  public:
   4160   DECLARE_INSTRUCTION_FACTORY_P1(HHasCachedArrayIndexAndBranch, HValue*);
   4161 
   4162   Representation RequiredInputRepresentation(int index) override {
   4163     return Representation::Tagged();
   4164   }
   4165 
   4166   DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
   4167  private:
   4168   explicit HHasCachedArrayIndexAndBranch(HValue* value)
   4169       : HUnaryControlInstruction(value, NULL, NULL) { }
   4170 };
   4171 
   4172 
   4173 class HGetCachedArrayIndex final : public HUnaryOperation {
   4174  public:
   4175   DECLARE_INSTRUCTION_FACTORY_P1(HGetCachedArrayIndex, HValue*);
   4176 
   4177   Representation RequiredInputRepresentation(int index) override {
   4178     return Representation::Tagged();
   4179   }
   4180 
   4181   DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
   4182 
   4183  protected:
   4184   bool DataEquals(HValue* other) override { return true; }
   4185 
   4186  private:
   4187   explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
   4188     set_representation(Representation::Tagged());
   4189     SetFlag(kUseGVN);
   4190   }
   4191 
   4192   bool IsDeletable() const override { return true; }
   4193 };
   4194 
   4195 
   4196 class HClassOfTestAndBranch final : public HUnaryControlInstruction {
   4197  public:
   4198   DECLARE_INSTRUCTION_FACTORY_P2(HClassOfTestAndBranch, HValue*,
   4199                                  Handle<String>);
   4200 
   4201   DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
   4202 
   4203   Representation RequiredInputRepresentation(int index) override {
   4204     return Representation::Tagged();
   4205   }
   4206 
   4207   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4208 
   4209   Handle<String> class_name() const { return class_name_; }
   4210 
   4211  private:
   4212   HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
   4213       : HUnaryControlInstruction(value, NULL, NULL),
   4214         class_name_(class_name) { }
   4215 
   4216   Handle<String> class_name_;
   4217 };
   4218 
   4219 
   4220 class HTypeofIsAndBranch final : public HUnaryControlInstruction {
   4221  public:
   4222   DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle<String>);
   4223 
   4224   Handle<String> type_literal() const { return type_literal_.handle(); }
   4225   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4226 
   4227   DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
   4228 
   4229   Representation RequiredInputRepresentation(int index) override {
   4230     return Representation::None();
   4231   }
   4232 
   4233   bool KnownSuccessorBlock(HBasicBlock** block) override;
   4234 
   4235   void FinalizeUniqueness() override {
   4236     type_literal_ = Unique<String>(type_literal_.handle());
   4237   }
   4238 
   4239  private:
   4240   HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
   4241       : HUnaryControlInstruction(value, NULL, NULL),
   4242         type_literal_(Unique<String>::CreateUninitialized(type_literal)) { }
   4243 
   4244   Unique<String> type_literal_;
   4245 };
   4246 
   4247 
   4248 class HHasInPrototypeChainAndBranch final
   4249     : public HTemplateControlInstruction<2, 2> {
   4250  public:
   4251   DECLARE_INSTRUCTION_FACTORY_P2(HHasInPrototypeChainAndBranch, HValue*,
   4252                                  HValue*);
   4253 
   4254   HValue* object() const { return OperandAt(0); }
   4255   HValue* prototype() const { return OperandAt(1); }
   4256 
   4257   Representation RequiredInputRepresentation(int index) override {
   4258     return Representation::Tagged();
   4259   }
   4260 
   4261   bool ObjectNeedsSmiCheck() const {
   4262     return !object()->type().IsHeapObject() &&
   4263            !object()->representation().IsHeapObject();
   4264   }
   4265 
   4266   DECLARE_CONCRETE_INSTRUCTION(HasInPrototypeChainAndBranch)
   4267 
   4268  private:
   4269   HHasInPrototypeChainAndBranch(HValue* object, HValue* prototype) {
   4270     SetOperandAt(0, object);
   4271     SetOperandAt(1, prototype);
   4272     SetDependsOnFlag(kCalls);
   4273   }
   4274 };
   4275 
   4276 
   4277 class HPower final : public HTemplateInstruction<2> {
   4278  public:
   4279   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4280                            HValue* left, HValue* right);
   4281 
   4282   HValue* left() { return OperandAt(0); }
   4283   HValue* right() const { return OperandAt(1); }
   4284 
   4285   Representation RequiredInputRepresentation(int index) override {
   4286     return index == 0
   4287       ? Representation::Double()
   4288       : Representation::None();
   4289   }
   4290   Representation observed_input_representation(int index) override {
   4291     return RequiredInputRepresentation(index);
   4292   }
   4293 
   4294   DECLARE_CONCRETE_INSTRUCTION(Power)
   4295 
   4296  protected:
   4297   bool DataEquals(HValue* other) override { return true; }
   4298 
   4299  private:
   4300   HPower(HValue* left, HValue* right) {
   4301     SetOperandAt(0, left);
   4302     SetOperandAt(1, right);
   4303     set_representation(Representation::Double());
   4304     SetFlag(kUseGVN);
   4305     SetChangesFlag(kNewSpacePromotion);
   4306   }
   4307 
   4308   bool IsDeletable() const override {
   4309     return !right()->representation().IsTagged();
   4310   }
   4311 };
   4312 
   4313 
   4314 enum ExternalAddType {
   4315   AddOfExternalAndTagged,
   4316   AddOfExternalAndInt32,
   4317   NoExternalAdd
   4318 };
   4319 
   4320 
   4321 class HAdd final : public HArithmeticBinaryOperation {
   4322  public:
   4323   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4324                            HValue* left, HValue* right);
   4325   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4326                            HValue* left, HValue* right,
   4327                            ExternalAddType external_add_type);
   4328 
   4329   // Add is only commutative if two integer values are added and not if two
   4330   // tagged values are added (because it might be a String concatenation).
   4331   // We also do not commute (pointer + offset).
   4332   bool IsCommutative() const override {
   4333     return !representation().IsTagged() && !representation().IsExternal();
   4334   }
   4335 
   4336   HValue* Canonicalize() override;
   4337 
   4338   void RepresentationChanged(Representation to) override {
   4339     if (to.IsTagged() &&
   4340         (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() ||
   4341          left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) {
   4342       SetAllSideEffects();
   4343       ClearFlag(kUseGVN);
   4344     } else {
   4345       ClearAllSideEffects();
   4346       SetFlag(kUseGVN);
   4347     }
   4348     if (to.IsTagged()) {
   4349       SetChangesFlag(kNewSpacePromotion);
   4350       ClearFlag(kAllowUndefinedAsNaN);
   4351     }
   4352     if (!right()->type().IsTaggedNumber() &&
   4353         !right()->representation().IsDouble() &&
   4354         !right()->representation().IsSmiOrInteger32()) {
   4355       ClearFlag(kAllowUndefinedAsNaN);
   4356     }
   4357   }
   4358 
   4359   Representation RepresentationFromInputs() override;
   4360 
   4361   Representation RequiredInputRepresentation(int index) override;
   4362 
   4363   bool IsConsistentExternalRepresentation() {
   4364     return left()->representation().IsExternal() &&
   4365            ((external_add_type_ == AddOfExternalAndInt32 &&
   4366              right()->representation().IsInteger32()) ||
   4367             (external_add_type_ == AddOfExternalAndTagged &&
   4368              right()->representation().IsTagged()));
   4369   }
   4370 
   4371   ExternalAddType external_add_type() const { return external_add_type_; }
   4372 
   4373   DECLARE_CONCRETE_INSTRUCTION(Add)
   4374 
   4375  protected:
   4376   bool DataEquals(HValue* other) override { return true; }
   4377 
   4378   Range* InferRange(Zone* zone) override;
   4379 
   4380  private:
   4381   HAdd(HValue* context, HValue* left, HValue* right,
   4382        ExternalAddType external_add_type = NoExternalAdd)
   4383       : HArithmeticBinaryOperation(context, left, right),
   4384         external_add_type_(external_add_type) {
   4385     SetFlag(kCanOverflow);
   4386     switch (external_add_type_) {
   4387       case AddOfExternalAndTagged:
   4388         DCHECK(left->representation().IsExternal());
   4389         DCHECK(right->representation().IsTagged());
   4390         SetDependsOnFlag(kNewSpacePromotion);
   4391         ClearFlag(HValue::kCanOverflow);
   4392         SetFlag(kHasNoObservableSideEffects);
   4393         break;
   4394 
   4395       case NoExternalAdd:
   4396         // This is a bit of a hack: The call to this constructor is generated
   4397         // by a macro that also supports sub and mul, so it doesn't pass in
   4398         // a value for external_add_type but uses the default.
   4399         if (left->representation().IsExternal()) {
   4400           external_add_type_ = AddOfExternalAndInt32;
   4401         }
   4402         break;
   4403 
   4404       case AddOfExternalAndInt32:
   4405         // See comment above.
   4406         UNREACHABLE();
   4407         break;
   4408     }
   4409   }
   4410 
   4411   ExternalAddType external_add_type_;
   4412 };
   4413 
   4414 
   4415 class HSub final : public HArithmeticBinaryOperation {
   4416  public:
   4417   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4418                            HValue* left, HValue* right);
   4419 
   4420   HValue* Canonicalize() override;
   4421 
   4422   DECLARE_CONCRETE_INSTRUCTION(Sub)
   4423 
   4424  protected:
   4425   bool DataEquals(HValue* other) override { return true; }
   4426 
   4427   Range* InferRange(Zone* zone) override;
   4428 
   4429  private:
   4430   HSub(HValue* context, HValue* left, HValue* right)
   4431       : HArithmeticBinaryOperation(context, left, right) {
   4432     SetFlag(kCanOverflow);
   4433   }
   4434 };
   4435 
   4436 
   4437 class HMul final : public HArithmeticBinaryOperation {
   4438  public:
   4439   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4440                            HValue* left, HValue* right);
   4441 
   4442   static HInstruction* NewImul(Isolate* isolate, Zone* zone, HValue* context,
   4443                                HValue* left, HValue* right) {
   4444     HInstruction* instr = HMul::New(isolate, zone, context, left, right);
   4445     if (!instr->IsMul()) return instr;
   4446     HMul* mul = HMul::cast(instr);
   4447     // TODO(mstarzinger): Prevent bailout on minus zero for imul.
   4448     mul->AssumeRepresentation(Representation::Integer32());
   4449     mul->ClearFlag(HValue::kCanOverflow);
   4450     return mul;
   4451   }
   4452 
   4453   HValue* Canonicalize() override;
   4454 
   4455   // Only commutative if it is certain that not two objects are multiplicated.
   4456   bool IsCommutative() const override { return !representation().IsTagged(); }
   4457 
   4458   void UpdateRepresentation(Representation new_rep,
   4459                             HInferRepresentationPhase* h_infer,
   4460                             const char* reason) override {
   4461     HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4462   }
   4463 
   4464   bool MulMinusOne();
   4465 
   4466   DECLARE_CONCRETE_INSTRUCTION(Mul)
   4467 
   4468  protected:
   4469   bool DataEquals(HValue* other) override { return true; }
   4470 
   4471   Range* InferRange(Zone* zone) override;
   4472 
   4473  private:
   4474   HMul(HValue* context, HValue* left, HValue* right)
   4475       : HArithmeticBinaryOperation(context, left, right) {
   4476     SetFlag(kCanOverflow);
   4477   }
   4478 };
   4479 
   4480 
   4481 class HMod final : public HArithmeticBinaryOperation {
   4482  public:
   4483   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4484                            HValue* left, HValue* right);
   4485 
   4486   HValue* Canonicalize() override;
   4487 
   4488   void UpdateRepresentation(Representation new_rep,
   4489                             HInferRepresentationPhase* h_infer,
   4490                             const char* reason) override {
   4491     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
   4492     HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4493   }
   4494 
   4495   DECLARE_CONCRETE_INSTRUCTION(Mod)
   4496 
   4497  protected:
   4498   bool DataEquals(HValue* other) override { return true; }
   4499 
   4500   Range* InferRange(Zone* zone) override;
   4501 
   4502  private:
   4503   HMod(HValue* context, HValue* left, HValue* right)
   4504       : HArithmeticBinaryOperation(context, left, right) {
   4505     SetFlag(kCanBeDivByZero);
   4506     SetFlag(kCanOverflow);
   4507     SetFlag(kLeftCanBeNegative);
   4508   }
   4509 };
   4510 
   4511 
   4512 class HDiv final : public HArithmeticBinaryOperation {
   4513  public:
   4514   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4515                            HValue* left, HValue* right);
   4516 
   4517   HValue* Canonicalize() override;
   4518 
   4519   void UpdateRepresentation(Representation new_rep,
   4520                             HInferRepresentationPhase* h_infer,
   4521                             const char* reason) override {
   4522     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
   4523     HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4524   }
   4525 
   4526   DECLARE_CONCRETE_INSTRUCTION(Div)
   4527 
   4528  protected:
   4529   bool DataEquals(HValue* other) override { return true; }
   4530 
   4531   Range* InferRange(Zone* zone) override;
   4532 
   4533  private:
   4534   HDiv(HValue* context, HValue* left, HValue* right)
   4535       : HArithmeticBinaryOperation(context, left, right) {
   4536     SetFlag(kCanBeDivByZero);
   4537     SetFlag(kCanOverflow);
   4538   }
   4539 };
   4540 
   4541 
   4542 class HMathMinMax final : public HArithmeticBinaryOperation {
   4543  public:
   4544   enum Operation { kMathMin, kMathMax };
   4545 
   4546   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4547                            HValue* left, HValue* right, Operation op);
   4548 
   4549   Representation observed_input_representation(int index) override {
   4550     return RequiredInputRepresentation(index);
   4551   }
   4552 
   4553   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   4554 
   4555   Representation RepresentationFromInputs() override {
   4556     Representation left_rep = left()->representation();
   4557     Representation right_rep = right()->representation();
   4558     Representation result = Representation::Smi();
   4559     result = result.generalize(left_rep);
   4560     result = result.generalize(right_rep);
   4561     if (result.IsTagged()) return Representation::Double();
   4562     return result;
   4563   }
   4564 
   4565   bool IsCommutative() const override { return true; }
   4566 
   4567   Operation operation() { return operation_; }
   4568 
   4569   DECLARE_CONCRETE_INSTRUCTION(MathMinMax)
   4570 
   4571  protected:
   4572   bool DataEquals(HValue* other) override {
   4573     return other->IsMathMinMax() &&
   4574         HMathMinMax::cast(other)->operation_ == operation_;
   4575   }
   4576 
   4577   Range* InferRange(Zone* zone) override;
   4578 
   4579  private:
   4580   HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
   4581       : HArithmeticBinaryOperation(context, left, right), operation_(op) {}
   4582 
   4583   Operation operation_;
   4584 };
   4585 
   4586 
   4587 class HBitwise final : public HBitwiseBinaryOperation {
   4588  public:
   4589   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4590                            Token::Value op, HValue* left, HValue* right);
   4591 
   4592   Token::Value op() const { return op_; }
   4593 
   4594   bool IsCommutative() const override { return true; }
   4595 
   4596   HValue* Canonicalize() override;
   4597 
   4598   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4599 
   4600   DECLARE_CONCRETE_INSTRUCTION(Bitwise)
   4601 
   4602  protected:
   4603   bool DataEquals(HValue* other) override {
   4604     return op() == HBitwise::cast(other)->op();
   4605   }
   4606 
   4607   Range* InferRange(Zone* zone) override;
   4608 
   4609  private:
   4610   HBitwise(HValue* context, Token::Value op, HValue* left, HValue* right)
   4611       : HBitwiseBinaryOperation(context, left, right), op_(op) {
   4612     DCHECK(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
   4613     // BIT_AND with a smi-range positive value will always unset the
   4614     // entire sign-extension of the smi-sign.
   4615     if (op == Token::BIT_AND &&
   4616         ((left->IsConstant() &&
   4617           left->representation().IsSmi() &&
   4618           HConstant::cast(left)->Integer32Value() >= 0) ||
   4619          (right->IsConstant() &&
   4620           right->representation().IsSmi() &&
   4621           HConstant::cast(right)->Integer32Value() >= 0))) {
   4622       SetFlag(kTruncatingToSmi);
   4623       SetFlag(kTruncatingToInt32);
   4624     // BIT_OR with a smi-range negative value will always set the entire
   4625     // sign-extension of the smi-sign.
   4626     } else if (op == Token::BIT_OR &&
   4627         ((left->IsConstant() &&
   4628           left->representation().IsSmi() &&
   4629           HConstant::cast(left)->Integer32Value() < 0) ||
   4630          (right->IsConstant() &&
   4631           right->representation().IsSmi() &&
   4632           HConstant::cast(right)->Integer32Value() < 0))) {
   4633       SetFlag(kTruncatingToSmi);
   4634       SetFlag(kTruncatingToInt32);
   4635     }
   4636   }
   4637 
   4638   Token::Value op_;
   4639 };
   4640 
   4641 
   4642 class HShl final : public HBitwiseBinaryOperation {
   4643  public:
   4644   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4645                            HValue* left, HValue* right);
   4646 
   4647   Range* InferRange(Zone* zone) override;
   4648 
   4649   void UpdateRepresentation(Representation new_rep,
   4650                             HInferRepresentationPhase* h_infer,
   4651                             const char* reason) override {
   4652     if (new_rep.IsSmi() &&
   4653         !(right()->IsInteger32Constant() &&
   4654           right()->GetInteger32Constant() >= 0)) {
   4655       new_rep = Representation::Integer32();
   4656     }
   4657     HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4658   }
   4659 
   4660   DECLARE_CONCRETE_INSTRUCTION(Shl)
   4661 
   4662  protected:
   4663   bool DataEquals(HValue* other) override { return true; }
   4664 
   4665  private:
   4666   HShl(HValue* context, HValue* left, HValue* right)
   4667       : HBitwiseBinaryOperation(context, left, right) {}
   4668 };
   4669 
   4670 
   4671 class HShr final : public HBitwiseBinaryOperation {
   4672  public:
   4673   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4674                            HValue* left, HValue* right);
   4675 
   4676   Range* InferRange(Zone* zone) override;
   4677 
   4678   void UpdateRepresentation(Representation new_rep,
   4679                             HInferRepresentationPhase* h_infer,
   4680                             const char* reason) override {
   4681     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
   4682     HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4683   }
   4684 
   4685   DECLARE_CONCRETE_INSTRUCTION(Shr)
   4686 
   4687  protected:
   4688   bool DataEquals(HValue* other) override { return true; }
   4689 
   4690  private:
   4691   HShr(HValue* context, HValue* left, HValue* right)
   4692       : HBitwiseBinaryOperation(context, left, right) {}
   4693 };
   4694 
   4695 
   4696 class HSar final : public HBitwiseBinaryOperation {
   4697  public:
   4698   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4699                            HValue* left, HValue* right);
   4700 
   4701   Range* InferRange(Zone* zone) override;
   4702 
   4703   void UpdateRepresentation(Representation new_rep,
   4704                             HInferRepresentationPhase* h_infer,
   4705                             const char* reason) override {
   4706     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
   4707     HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4708   }
   4709 
   4710   DECLARE_CONCRETE_INSTRUCTION(Sar)
   4711 
   4712  protected:
   4713   bool DataEquals(HValue* other) override { return true; }
   4714 
   4715  private:
   4716   HSar(HValue* context, HValue* left, HValue* right)
   4717       : HBitwiseBinaryOperation(context, left, right) {}
   4718 };
   4719 
   4720 
   4721 class HRor final : public HBitwiseBinaryOperation {
   4722  public:
   4723   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4724                            HValue* left, HValue* right) {
   4725     return new (zone) HRor(context, left, right);
   4726   }
   4727 
   4728   void UpdateRepresentation(Representation new_rep,
   4729                             HInferRepresentationPhase* h_infer,
   4730                             const char* reason) override {
   4731     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
   4732     HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4733   }
   4734 
   4735   DECLARE_CONCRETE_INSTRUCTION(Ror)
   4736 
   4737  protected:
   4738   bool DataEquals(HValue* other) override { return true; }
   4739 
   4740  private:
   4741   HRor(HValue* context, HValue* left, HValue* right)
   4742       : HBitwiseBinaryOperation(context, left, right) {
   4743     ChangeRepresentation(Representation::Integer32());
   4744   }
   4745 };
   4746 
   4747 
   4748 class HOsrEntry final : public HTemplateInstruction<0> {
   4749  public:
   4750   DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId);
   4751 
   4752   BailoutId ast_id() const { return ast_id_; }
   4753 
   4754   Representation RequiredInputRepresentation(int index) override {
   4755     return Representation::None();
   4756   }
   4757 
   4758   DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
   4759 
   4760  private:
   4761   explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
   4762     SetChangesFlag(kOsrEntries);
   4763     SetChangesFlag(kNewSpacePromotion);
   4764   }
   4765 
   4766   BailoutId ast_id_;
   4767 };
   4768 
   4769 
   4770 class HParameter final : public HTemplateInstruction<0> {
   4771  public:
   4772   enum ParameterKind {
   4773     STACK_PARAMETER,
   4774     REGISTER_PARAMETER
   4775   };
   4776 
   4777   DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned);
   4778   DECLARE_INSTRUCTION_FACTORY_P2(HParameter, unsigned, ParameterKind);
   4779   DECLARE_INSTRUCTION_FACTORY_P3(HParameter, unsigned, ParameterKind,
   4780                                  Representation);
   4781 
   4782   unsigned index() const { return index_; }
   4783   ParameterKind kind() const { return kind_; }
   4784 
   4785   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4786 
   4787   Representation RequiredInputRepresentation(int index) override {
   4788     return Representation::None();
   4789   }
   4790 
   4791   Representation KnownOptimalRepresentation() override {
   4792     // If a parameter is an input to a phi, that phi should not
   4793     // choose any more optimistic representation than Tagged.
   4794     return Representation::Tagged();
   4795   }
   4796 
   4797   DECLARE_CONCRETE_INSTRUCTION(Parameter)
   4798 
   4799  private:
   4800   explicit HParameter(unsigned index,
   4801                       ParameterKind kind = STACK_PARAMETER)
   4802       : index_(index),
   4803         kind_(kind) {
   4804     set_representation(Representation::Tagged());
   4805   }
   4806 
   4807   explicit HParameter(unsigned index,
   4808                       ParameterKind kind,
   4809                       Representation r)
   4810       : index_(index),
   4811         kind_(kind) {
   4812     set_representation(r);
   4813   }
   4814 
   4815   unsigned index_;
   4816   ParameterKind kind_;
   4817 };
   4818 
   4819 
   4820 class HUnknownOSRValue final : public HTemplateInstruction<0> {
   4821  public:
   4822   DECLARE_INSTRUCTION_FACTORY_P2(HUnknownOSRValue, HEnvironment*, int);
   4823 
   4824   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4825 
   4826   Representation RequiredInputRepresentation(int index) override {
   4827     return Representation::None();
   4828   }
   4829 
   4830   void set_incoming_value(HPhi* value) { incoming_value_ = value; }
   4831   HPhi* incoming_value() { return incoming_value_; }
   4832   HEnvironment *environment() { return environment_; }
   4833   int index() { return index_; }
   4834 
   4835   Representation KnownOptimalRepresentation() override {
   4836     if (incoming_value_ == NULL) return Representation::None();
   4837     return incoming_value_->KnownOptimalRepresentation();
   4838   }
   4839 
   4840   DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
   4841 
   4842  private:
   4843   HUnknownOSRValue(HEnvironment* environment, int index)
   4844       : environment_(environment),
   4845         index_(index),
   4846         incoming_value_(NULL) {
   4847     set_representation(Representation::Tagged());
   4848   }
   4849 
   4850   HEnvironment* environment_;
   4851   int index_;
   4852   HPhi* incoming_value_;
   4853 };
   4854 
   4855 class HLoadGlobalGeneric final : public HTemplateInstruction<1> {
   4856  public:
   4857   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadGlobalGeneric,
   4858                                               Handle<String>, TypeofMode,
   4859                                               Handle<TypeFeedbackVector>,
   4860                                               FeedbackVectorSlot);
   4861 
   4862   HValue* context() { return OperandAt(0); }
   4863   Handle<String> name() const { return name_; }
   4864   TypeofMode typeof_mode() const { return typeof_mode_; }
   4865   FeedbackVectorSlot slot() const { return slot_; }
   4866   Handle<TypeFeedbackVector> feedback_vector() const {
   4867     return feedback_vector_;
   4868   }
   4869 
   4870   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4871 
   4872   Representation RequiredInputRepresentation(int index) override {
   4873     return Representation::Tagged();
   4874   }
   4875 
   4876   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
   4877 
   4878  private:
   4879   HLoadGlobalGeneric(HValue* context, Handle<String> name,
   4880                      TypeofMode typeof_mode, Handle<TypeFeedbackVector> vector,
   4881                      FeedbackVectorSlot slot)
   4882       : name_(name),
   4883         typeof_mode_(typeof_mode),
   4884         feedback_vector_(vector),
   4885         slot_(slot) {
   4886     SetOperandAt(0, context);
   4887     set_representation(Representation::Tagged());
   4888     SetAllSideEffects();
   4889   }
   4890 
   4891   Handle<String> name_;
   4892   TypeofMode typeof_mode_;
   4893   Handle<TypeFeedbackVector> feedback_vector_;
   4894   FeedbackVectorSlot slot_;
   4895 };
   4896 
   4897 class HAllocate final : public HTemplateInstruction<3> {
   4898  public:
   4899   static bool CompatibleInstanceTypes(InstanceType type1,
   4900                                       InstanceType type2) {
   4901     return ComputeFlags(TENURED, type1) == ComputeFlags(TENURED, type2) &&
   4902         ComputeFlags(NOT_TENURED, type1) == ComputeFlags(NOT_TENURED, type2);
   4903   }
   4904 
   4905   static HAllocate* New(
   4906       Isolate* isolate, Zone* zone, HValue* context, HValue* size, HType type,
   4907       PretenureFlag pretenure_flag, InstanceType instance_type,
   4908       HValue* dominator,
   4909       Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null()) {
   4910     return new (zone) HAllocate(context, size, type, pretenure_flag,
   4911                                 instance_type, dominator, allocation_site);
   4912   }
   4913 
   4914   // Maximum instance size for which allocations will be inlined.
   4915   static const int kMaxInlineSize = 64 * kPointerSize;
   4916 
   4917   HValue* context() const { return OperandAt(0); }
   4918   HValue* size() const { return OperandAt(1); }
   4919   HValue* allocation_folding_dominator() const { return OperandAt(2); }
   4920 
   4921   Representation RequiredInputRepresentation(int index) override {
   4922     if (index == 0) {
   4923       return Representation::Tagged();
   4924     } else {
   4925       return Representation::Integer32();
   4926     }
   4927   }
   4928 
   4929   Handle<Map> GetMonomorphicJSObjectMap() override {
   4930     return known_initial_map_;
   4931   }
   4932 
   4933   void set_known_initial_map(Handle<Map> known_initial_map) {
   4934     known_initial_map_ = known_initial_map;
   4935   }
   4936 
   4937   bool IsNewSpaceAllocation() const {
   4938     return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
   4939   }
   4940 
   4941   bool IsOldSpaceAllocation() const {
   4942     return (flags_ & ALLOCATE_IN_OLD_SPACE) != 0;
   4943   }
   4944 
   4945   bool MustAllocateDoubleAligned() const {
   4946     return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
   4947   }
   4948 
   4949   bool MustPrefillWithFiller() const {
   4950     return (flags_ & PREFILL_WITH_FILLER) != 0;
   4951   }
   4952 
   4953   void MakePrefillWithFiller() {
   4954     flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
   4955   }
   4956 
   4957   void MakeDoubleAligned() {
   4958     flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
   4959   }
   4960 
   4961   void MakeAllocationFoldingDominator() {
   4962     flags_ =
   4963         static_cast<HAllocate::Flags>(flags_ | ALLOCATION_FOLDING_DOMINATOR);
   4964   }
   4965 
   4966   bool IsAllocationFoldingDominator() {
   4967     return (flags_ & ALLOCATION_FOLDING_DOMINATOR) != 0;
   4968   }
   4969 
   4970   void MakeFoldedAllocation(HAllocate* dominator) {
   4971     flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATION_FOLDED);
   4972     ClearFlag(kTrackSideEffectDominators);
   4973     ClearChangesFlag(kNewSpacePromotion);
   4974     SetOperandAt(2, dominator);
   4975   }
   4976 
   4977   bool IsAllocationFolded() { return (flags_ & ALLOCATION_FOLDED) != 0; }
   4978 
   4979   bool HandleSideEffectDominator(GVNFlag side_effect,
   4980                                  HValue* dominator) override;
   4981 
   4982   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4983 
   4984   DECLARE_CONCRETE_INSTRUCTION(Allocate)
   4985 
   4986  private:
   4987   enum Flags {
   4988     ALLOCATE_IN_NEW_SPACE = 1 << 0,
   4989     ALLOCATE_IN_OLD_SPACE = 1 << 2,
   4990     ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
   4991     PREFILL_WITH_FILLER = 1 << 4,
   4992     ALLOCATION_FOLDING_DOMINATOR = 1 << 5,
   4993     ALLOCATION_FOLDED = 1 << 6
   4994   };
   4995 
   4996   HAllocate(
   4997       HValue* context, HValue* size, HType type, PretenureFlag pretenure_flag,
   4998       InstanceType instance_type, HValue* dominator,
   4999       Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null())
   5000       : HTemplateInstruction<3>(type),
   5001         flags_(ComputeFlags(pretenure_flag, instance_type)) {
   5002     SetOperandAt(0, context);
   5003     UpdateSize(size);
   5004     SetOperandAt(2, dominator);
   5005     set_representation(Representation::Tagged());
   5006     SetFlag(kTrackSideEffectDominators);
   5007     SetChangesFlag(kNewSpacePromotion);
   5008     SetDependsOnFlag(kNewSpacePromotion);
   5009 
   5010     if (FLAG_trace_pretenuring) {
   5011       PrintF("HAllocate with AllocationSite %p %s\n",
   5012              allocation_site.is_null()
   5013                  ? static_cast<void*>(NULL)
   5014                  : static_cast<void*>(*allocation_site),
   5015              pretenure_flag == TENURED ? "tenured" : "not tenured");
   5016     }
   5017   }
   5018 
   5019   static Flags ComputeFlags(PretenureFlag pretenure_flag,
   5020                             InstanceType instance_type) {
   5021     Flags flags = pretenure_flag == TENURED ? ALLOCATE_IN_OLD_SPACE
   5022                                             : ALLOCATE_IN_NEW_SPACE;
   5023     if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
   5024       flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED);
   5025     }
   5026     // We have to fill the allocated object with one word fillers if we do
   5027     // not use allocation folding since some allocations may depend on each
   5028     // other, i.e., have a pointer to each other. A GC in between these
   5029     // allocations may leave such objects behind in a not completely initialized
   5030     // state.
   5031     if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
   5032       flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER);
   5033     }
   5034     return flags;
   5035   }
   5036 
   5037   void UpdateSize(HValue* size) {
   5038     SetOperandAt(1, size);
   5039   }
   5040 
   5041   bool IsFoldable(HAllocate* allocate) {
   5042     return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) ||
   5043            (IsOldSpaceAllocation() && allocate->IsOldSpaceAllocation());
   5044   }
   5045 
   5046   Flags flags_;
   5047   Handle<Map> known_initial_map_;
   5048 };
   5049 
   5050 
   5051 class HStoreCodeEntry final : public HTemplateInstruction<2> {
   5052  public:
   5053   static HStoreCodeEntry* New(Isolate* isolate, Zone* zone, HValue* context,
   5054                               HValue* function, HValue* code) {
   5055     return new(zone) HStoreCodeEntry(function, code);
   5056   }
   5057 
   5058   Representation RequiredInputRepresentation(int index) override {
   5059     return Representation::Tagged();
   5060   }
   5061 
   5062   HValue* function() { return OperandAt(0); }
   5063   HValue* code_object() { return OperandAt(1); }
   5064 
   5065   DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry)
   5066 
   5067  private:
   5068   HStoreCodeEntry(HValue* function, HValue* code) {
   5069     SetOperandAt(0, function);
   5070     SetOperandAt(1, code);
   5071   }
   5072 };
   5073 
   5074 
   5075 class HInnerAllocatedObject final : public HTemplateInstruction<2> {
   5076  public:
   5077   static HInnerAllocatedObject* New(Isolate* isolate, Zone* zone,
   5078                                     HValue* context, HValue* value,
   5079                                     HValue* offset, HType type) {
   5080     return new(zone) HInnerAllocatedObject(value, offset, type);
   5081   }
   5082 
   5083   HValue* base_object() const { return OperandAt(0); }
   5084   HValue* offset() const { return OperandAt(1); }
   5085 
   5086   Representation RequiredInputRepresentation(int index) override {
   5087     return index == 0 ? Representation::Tagged() : Representation::Integer32();
   5088   }
   5089 
   5090   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5091 
   5092   DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
   5093 
   5094  private:
   5095   HInnerAllocatedObject(HValue* value,
   5096                         HValue* offset,
   5097                         HType type) : HTemplateInstruction<2>(type) {
   5098     DCHECK(value->IsAllocate());
   5099     DCHECK(type.IsHeapObject());
   5100     SetOperandAt(0, value);
   5101     SetOperandAt(1, offset);
   5102     set_representation(Representation::Tagged());
   5103   }
   5104 };
   5105 
   5106 
   5107 inline bool StoringValueNeedsWriteBarrier(HValue* value) {
   5108   return !value->type().IsSmi()
   5109       && !value->type().IsNull()
   5110       && !value->type().IsBoolean()
   5111       && !value->type().IsUndefined()
   5112       && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
   5113 }
   5114 
   5115 
   5116 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
   5117                                             HValue* value,
   5118                                             HValue* dominator) {
   5119   // There may be multiple inner allocates dominated by one allocate.
   5120   while (object->IsInnerAllocatedObject()) {
   5121     object = HInnerAllocatedObject::cast(object)->base_object();
   5122   }
   5123 
   5124   if (object->IsAllocate()) {
   5125     HAllocate* allocate = HAllocate::cast(object);
   5126     if (allocate->IsAllocationFolded()) {
   5127       HValue* dominator = allocate->allocation_folding_dominator();
   5128       // There is no guarantee that all allocations are folded together because
   5129       // GVN performs a fixpoint.
   5130       if (HAllocate::cast(dominator)->IsAllocationFoldingDominator()) {
   5131         object = dominator;
   5132       }
   5133     }
   5134   }
   5135 
   5136   if (object->IsConstant() &&
   5137       HConstant::cast(object)->HasExternalReferenceValue()) {
   5138     // Stores to external references require no write barriers
   5139     return false;
   5140   }
   5141   // We definitely need a write barrier unless the object is the allocation
   5142   // dominator.
   5143   if (object == dominator && object->IsAllocate()) {
   5144     // Stores to new space allocations require no write barriers.
   5145     if (HAllocate::cast(object)->IsNewSpaceAllocation()) {
   5146       return false;
   5147     }
   5148   }
   5149   return true;
   5150 }
   5151 
   5152 
   5153 inline PointersToHereCheck PointersToHereCheckForObject(HValue* object,
   5154                                                         HValue* dominator) {
   5155   while (object->IsInnerAllocatedObject()) {
   5156     object = HInnerAllocatedObject::cast(object)->base_object();
   5157   }
   5158   if (object == dominator &&
   5159       object->IsAllocate() &&
   5160       HAllocate::cast(object)->IsNewSpaceAllocation()) {
   5161     return kPointersToHereAreAlwaysInteresting;
   5162   }
   5163   return kPointersToHereMaybeInteresting;
   5164 }
   5165 
   5166 
   5167 class HLoadContextSlot final : public HUnaryOperation {
   5168  public:
   5169   enum Mode {
   5170     // Perform a normal load of the context slot without checking its value.
   5171     kNoCheck,
   5172     // Load and check the value of the context slot. Deoptimize if it's the
   5173     // hole value. This is used for checking for loading of uninitialized
   5174     // harmony bindings where we deoptimize into full-codegen generated code
   5175     // which will subsequently throw a reference error.
   5176     kCheckDeoptimize
   5177   };
   5178 
   5179   HLoadContextSlot(HValue* context, int slot_index, Mode mode)
   5180       : HUnaryOperation(context), slot_index_(slot_index), mode_(mode) {
   5181     set_representation(Representation::Tagged());
   5182     SetFlag(kUseGVN);
   5183     SetDependsOnFlag(kContextSlots);
   5184   }
   5185 
   5186   int slot_index() const { return slot_index_; }
   5187   Mode mode() const { return mode_; }
   5188 
   5189   bool DeoptimizesOnHole() {
   5190     return mode_ == kCheckDeoptimize;
   5191   }
   5192 
   5193   bool RequiresHoleCheck() const {
   5194     return mode_ != kNoCheck;
   5195   }
   5196 
   5197   Representation RequiredInputRepresentation(int index) override {
   5198     return Representation::Tagged();
   5199   }
   5200 
   5201   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5202 
   5203   DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
   5204 
   5205  protected:
   5206   bool DataEquals(HValue* other) override {
   5207     HLoadContextSlot* b = HLoadContextSlot::cast(other);
   5208     return (slot_index() == b->slot_index());
   5209   }
   5210 
   5211  private:
   5212   bool IsDeletable() const override { return !RequiresHoleCheck(); }
   5213 
   5214   int slot_index_;
   5215   Mode mode_;
   5216 };
   5217 
   5218 
   5219 class HStoreContextSlot final : public HTemplateInstruction<2> {
   5220  public:
   5221   enum Mode {
   5222     // Perform a normal store to the context slot without checking its previous
   5223     // value.
   5224     kNoCheck,
   5225     // Check the previous value of the context slot and deoptimize if it's the
   5226     // hole value. This is used for checking for assignments to uninitialized
   5227     // harmony bindings where we deoptimize into full-codegen generated code
   5228     // which will subsequently throw a reference error.
   5229     kCheckDeoptimize
   5230   };
   5231 
   5232   DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
   5233                                  Mode, HValue*);
   5234 
   5235   HValue* context() const { return OperandAt(0); }
   5236   HValue* value() const { return OperandAt(1); }
   5237   int slot_index() const { return slot_index_; }
   5238   Mode mode() const { return mode_; }
   5239 
   5240   bool NeedsWriteBarrier() {
   5241     return StoringValueNeedsWriteBarrier(value());
   5242   }
   5243 
   5244   bool DeoptimizesOnHole() {
   5245     return mode_ == kCheckDeoptimize;
   5246   }
   5247 
   5248   bool RequiresHoleCheck() {
   5249     return mode_ != kNoCheck;
   5250   }
   5251 
   5252   Representation RequiredInputRepresentation(int index) override {
   5253     return Representation::Tagged();
   5254   }
   5255 
   5256   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5257 
   5258   DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
   5259 
   5260  private:
   5261   HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
   5262       : slot_index_(slot_index), mode_(mode) {
   5263     SetOperandAt(0, context);
   5264     SetOperandAt(1, value);
   5265     SetChangesFlag(kContextSlots);
   5266   }
   5267 
   5268   int slot_index_;
   5269   Mode mode_;
   5270 };
   5271 
   5272 
   5273 // Represents an access to a portion of an object, such as the map pointer,
   5274 // array elements pointer, etc, but not accesses to array elements themselves.
   5275 class HObjectAccess final {
   5276  public:
   5277   inline bool IsInobject() const {
   5278     return portion() != kBackingStore && portion() != kExternalMemory;
   5279   }
   5280 
   5281   inline bool IsExternalMemory() const {
   5282     return portion() == kExternalMemory;
   5283   }
   5284 
   5285   inline bool IsStringLength() const {
   5286     return portion() == kStringLengths;
   5287   }
   5288 
   5289   inline bool IsMap() const {
   5290     return portion() == kMaps;
   5291   }
   5292 
   5293   inline int offset() const {
   5294     return OffsetField::decode(value_);
   5295   }
   5296 
   5297   inline Representation representation() const {
   5298     return Representation::FromKind(RepresentationField::decode(value_));
   5299   }
   5300 
   5301   inline Handle<Name> name() const { return name_; }
   5302 
   5303   inline bool immutable() const {
   5304     return ImmutableField::decode(value_);
   5305   }
   5306 
   5307   // Returns true if access is being made to an in-object property that
   5308   // was already added to the object.
   5309   inline bool existing_inobject_property() const {
   5310     return ExistingInobjectPropertyField::decode(value_);
   5311   }
   5312 
   5313   inline HObjectAccess WithRepresentation(Representation representation) {
   5314     return HObjectAccess(portion(), offset(), representation, name(),
   5315                          immutable(), existing_inobject_property());
   5316   }
   5317 
   5318   static HObjectAccess ForHeapNumberValue() {
   5319     return HObjectAccess(
   5320         kDouble, HeapNumber::kValueOffset, Representation::Double());
   5321   }
   5322 
   5323   static HObjectAccess ForHeapNumberValueLowestBits() {
   5324     return HObjectAccess(kDouble,
   5325                          HeapNumber::kValueOffset,
   5326                          Representation::Integer32());
   5327   }
   5328 
   5329   static HObjectAccess ForHeapNumberValueHighestBits() {
   5330     return HObjectAccess(kDouble,
   5331                          HeapNumber::kValueOffset + kIntSize,
   5332                          Representation::Integer32());
   5333   }
   5334 
   5335   static HObjectAccess ForOddballToNumber(
   5336       Representation representation = Representation::Tagged()) {
   5337     return HObjectAccess(kInobject, Oddball::kToNumberOffset, representation);
   5338   }
   5339 
   5340   static HObjectAccess ForOddballTypeOf() {
   5341     return HObjectAccess(kInobject, Oddball::kTypeOfOffset,
   5342                          Representation::HeapObject());
   5343   }
   5344 
   5345   static HObjectAccess ForElementsPointer() {
   5346     return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
   5347   }
   5348 
   5349   static HObjectAccess ForLiteralsPointer() {
   5350     return HObjectAccess(kInobject, JSFunction::kLiteralsOffset);
   5351   }
   5352 
   5353   static HObjectAccess ForNextFunctionLinkPointer() {
   5354     return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
   5355   }
   5356 
   5357   static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
   5358     return HObjectAccess(
   5359         kArrayLengths,
   5360         JSArray::kLengthOffset,
   5361         IsFastElementsKind(elements_kind)
   5362             ? Representation::Smi() : Representation::Tagged());
   5363   }
   5364 
   5365   static HObjectAccess ForAllocationSiteOffset(int offset);
   5366 
   5367   static HObjectAccess ForAllocationSiteList() {
   5368     return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
   5369                          Handle<Name>::null(), false, false);
   5370   }
   5371 
   5372   static HObjectAccess ForFixedArrayLength() {
   5373     return HObjectAccess(
   5374         kArrayLengths,
   5375         FixedArray::kLengthOffset,
   5376         Representation::Smi());
   5377   }
   5378 
   5379   static HObjectAccess ForFixedTypedArrayBaseBasePointer() {
   5380     return HObjectAccess(kInobject, FixedTypedArrayBase::kBasePointerOffset,
   5381                          Representation::Tagged());
   5382   }
   5383 
   5384   static HObjectAccess ForFixedTypedArrayBaseExternalPointer() {
   5385     return HObjectAccess::ForObservableJSObjectOffset(
   5386         FixedTypedArrayBase::kExternalPointerOffset,
   5387         Representation::External());
   5388   }
   5389 
   5390   static HObjectAccess ForStringHashField() {
   5391     return HObjectAccess(kInobject,
   5392                          String::kHashFieldOffset,
   5393                          Representation::Integer32());
   5394   }
   5395 
   5396   static HObjectAccess ForStringLength() {
   5397     STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
   5398     return HObjectAccess(
   5399         kStringLengths,
   5400         String::kLengthOffset,
   5401         Representation::Smi());
   5402   }
   5403 
   5404   static HObjectAccess ForConsStringFirst() {
   5405     return HObjectAccess(kInobject, ConsString::kFirstOffset);
   5406   }
   5407 
   5408   static HObjectAccess ForConsStringSecond() {
   5409     return HObjectAccess(kInobject, ConsString::kSecondOffset);
   5410   }
   5411 
   5412   static HObjectAccess ForPropertiesPointer() {
   5413     return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
   5414   }
   5415 
   5416   static HObjectAccess ForPrototypeOrInitialMap() {
   5417     return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
   5418   }
   5419 
   5420   static HObjectAccess ForSharedFunctionInfoPointer() {
   5421     return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
   5422   }
   5423 
   5424   static HObjectAccess ForCodeEntryPointer() {
   5425     return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
   5426   }
   5427 
   5428   static HObjectAccess ForCodeOffset() {
   5429     return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
   5430   }
   5431 
   5432   static HObjectAccess ForOptimizedCodeMap() {
   5433     return HObjectAccess(kInobject,
   5434                          SharedFunctionInfo::kOptimizedCodeMapOffset);
   5435   }
   5436 
   5437   static HObjectAccess ForOptimizedCodeMapSharedCode() {
   5438     return HObjectAccess(kInobject, FixedArray::OffsetOfElementAt(
   5439                                         SharedFunctionInfo::kSharedCodeIndex));
   5440   }
   5441 
   5442   static HObjectAccess ForFunctionContextPointer() {
   5443     return HObjectAccess(kInobject, JSFunction::kContextOffset);
   5444   }
   5445 
   5446   static HObjectAccess ForMap() {
   5447     return HObjectAccess(kMaps, JSObject::kMapOffset);
   5448   }
   5449 
   5450   static HObjectAccess ForPrototype() {
   5451     return HObjectAccess(kMaps, Map::kPrototypeOffset);
   5452   }
   5453 
   5454   static HObjectAccess ForMapAsInteger32() {
   5455     return HObjectAccess(kMaps, JSObject::kMapOffset,
   5456                          Representation::Integer32());
   5457   }
   5458 
   5459   static HObjectAccess ForMapInObjectPropertiesOrConstructorFunctionIndex() {
   5460     return HObjectAccess(
   5461         kInobject, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset,
   5462         Representation::UInteger8());
   5463   }
   5464 
   5465   static HObjectAccess ForMapInstanceType() {
   5466     return HObjectAccess(kInobject,
   5467                          Map::kInstanceTypeOffset,
   5468                          Representation::UInteger8());
   5469   }
   5470 
   5471   static HObjectAccess ForMapInstanceSize() {
   5472     return HObjectAccess(kInobject,
   5473                          Map::kInstanceSizeOffset,
   5474                          Representation::UInteger8());
   5475   }
   5476 
   5477   static HObjectAccess ForMapBitField() {
   5478     return HObjectAccess(kInobject,
   5479                          Map::kBitFieldOffset,
   5480                          Representation::UInteger8());
   5481   }
   5482 
   5483   static HObjectAccess ForMapBitField2() {
   5484     return HObjectAccess(kInobject,
   5485                          Map::kBitField2Offset,
   5486                          Representation::UInteger8());
   5487   }
   5488 
   5489   static HObjectAccess ForMapBitField3() {
   5490     return HObjectAccess(kInobject, Map::kBitField3Offset,
   5491                          Representation::Integer32());
   5492   }
   5493 
   5494   static HObjectAccess ForMapDescriptors() {
   5495     return HObjectAccess(kInobject, Map::kDescriptorsOffset);
   5496   }
   5497 
   5498   static HObjectAccess ForNameHashField() {
   5499     return HObjectAccess(kInobject,
   5500                          Name::kHashFieldOffset,
   5501                          Representation::Integer32());
   5502   }
   5503 
   5504   static HObjectAccess ForMapInstanceTypeAndBitField() {
   5505     STATIC_ASSERT((Map::kInstanceTypeAndBitFieldOffset & 1) == 0);
   5506     // Ensure the two fields share one 16-bit word, endian-independent.
   5507     STATIC_ASSERT((Map::kBitFieldOffset & ~1) ==
   5508                   (Map::kInstanceTypeOffset & ~1));
   5509     return HObjectAccess(kInobject,
   5510                          Map::kInstanceTypeAndBitFieldOffset,
   5511                          Representation::UInteger16());
   5512   }
   5513 
   5514   static HObjectAccess ForPropertyCellValue() {
   5515     return HObjectAccess(kInobject, PropertyCell::kValueOffset);
   5516   }
   5517 
   5518   static HObjectAccess ForPropertyCellDetails() {
   5519     return HObjectAccess(kInobject, PropertyCell::kDetailsOffset,
   5520                          Representation::Smi());
   5521   }
   5522 
   5523   static HObjectAccess ForCellValue() {
   5524     return HObjectAccess(kInobject, Cell::kValueOffset);
   5525   }
   5526 
   5527   static HObjectAccess ForWeakCellValue() {
   5528     return HObjectAccess(kInobject, WeakCell::kValueOffset);
   5529   }
   5530 
   5531   static HObjectAccess ForWeakCellNext() {
   5532     return HObjectAccess(kInobject, WeakCell::kNextOffset);
   5533   }
   5534 
   5535   static HObjectAccess ForAllocationMementoSite() {
   5536     return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
   5537   }
   5538 
   5539   static HObjectAccess ForCounter() {
   5540     return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
   5541                          Handle<Name>::null(), false, false);
   5542   }
   5543 
   5544   static HObjectAccess ForExternalUInteger8() {
   5545     return HObjectAccess(kExternalMemory, 0, Representation::UInteger8(),
   5546                          Handle<Name>::null(), false, false);
   5547   }
   5548 
   5549   static HObjectAccess ForBoundTargetFunction() {
   5550     return HObjectAccess(kInobject,
   5551                          JSBoundFunction::kBoundTargetFunctionOffset);
   5552   }
   5553 
   5554   static HObjectAccess ForBoundThis() {
   5555     return HObjectAccess(kInobject, JSBoundFunction::kBoundThisOffset);
   5556   }
   5557 
   5558   static HObjectAccess ForBoundArguments() {
   5559     return HObjectAccess(kInobject, JSBoundFunction::kBoundArgumentsOffset);
   5560   }
   5561 
   5562   // Create an access to an offset in a fixed array header.
   5563   static HObjectAccess ForFixedArrayHeader(int offset);
   5564 
   5565   // Create an access to an in-object property in a JSObject.
   5566   // This kind of access must be used when the object |map| is known and
   5567   // in-object properties are being accessed. Accesses of the in-object
   5568   // properties can have different semantics depending on whether corresponding
   5569   // property was added to the map or not.
   5570   static HObjectAccess ForMapAndOffset(Handle<Map> map, int offset,
   5571       Representation representation = Representation::Tagged());
   5572 
   5573   // Create an access to an in-object property in a JSObject.
   5574   // This kind of access can be used for accessing object header fields or
   5575   // in-object properties if the map of the object is not known.
   5576   static HObjectAccess ForObservableJSObjectOffset(int offset,
   5577       Representation representation = Representation::Tagged()) {
   5578     return ForMapAndOffset(Handle<Map>::null(), offset, representation);
   5579   }
   5580 
   5581   // Create an access to an in-object property in a JSArray.
   5582   static HObjectAccess ForJSArrayOffset(int offset);
   5583 
   5584   static HObjectAccess ForContextSlot(int index);
   5585 
   5586   static HObjectAccess ForScriptContext(int index);
   5587 
   5588   // Create an access to the backing store of an object.
   5589   static HObjectAccess ForBackingStoreOffset(int offset,
   5590       Representation representation = Representation::Tagged());
   5591 
   5592   // Create an access to a resolved field (in-object or backing store).
   5593   static HObjectAccess ForField(Handle<Map> map, int index,
   5594                                 Representation representation,
   5595                                 Handle<Name> name);
   5596 
   5597   static HObjectAccess ForJSTypedArrayLength() {
   5598     return HObjectAccess::ForObservableJSObjectOffset(
   5599         JSTypedArray::kLengthOffset);
   5600   }
   5601 
   5602   static HObjectAccess ForJSArrayBufferBackingStore() {
   5603     return HObjectAccess::ForObservableJSObjectOffset(
   5604         JSArrayBuffer::kBackingStoreOffset, Representation::External());
   5605   }
   5606 
   5607   static HObjectAccess ForJSArrayBufferByteLength() {
   5608     return HObjectAccess::ForObservableJSObjectOffset(
   5609         JSArrayBuffer::kByteLengthOffset, Representation::Tagged());
   5610   }
   5611 
   5612   static HObjectAccess ForJSArrayBufferBitField() {
   5613     return HObjectAccess::ForObservableJSObjectOffset(
   5614         JSArrayBuffer::kBitFieldOffset, Representation::Integer32());
   5615   }
   5616 
   5617   static HObjectAccess ForJSArrayBufferBitFieldSlot() {
   5618     return HObjectAccess::ForObservableJSObjectOffset(
   5619         JSArrayBuffer::kBitFieldSlot, Representation::Smi());
   5620   }
   5621 
   5622   static HObjectAccess ForJSArrayBufferViewBuffer() {
   5623     return HObjectAccess::ForObservableJSObjectOffset(
   5624         JSArrayBufferView::kBufferOffset);
   5625   }
   5626 
   5627   static HObjectAccess ForJSArrayBufferViewByteOffset() {
   5628     return HObjectAccess::ForObservableJSObjectOffset(
   5629         JSArrayBufferView::kByteOffsetOffset);
   5630   }
   5631 
   5632   static HObjectAccess ForJSArrayBufferViewByteLength() {
   5633     return HObjectAccess::ForObservableJSObjectOffset(
   5634         JSArrayBufferView::kByteLengthOffset);
   5635   }
   5636 
   5637   static HObjectAccess ForJSGlobalObjectNativeContext() {
   5638     return HObjectAccess(kInobject, JSGlobalObject::kNativeContextOffset);
   5639   }
   5640 
   5641   static HObjectAccess ForJSRegExpFlags() {
   5642     return HObjectAccess(kInobject, JSRegExp::kFlagsOffset);
   5643   }
   5644 
   5645   static HObjectAccess ForJSRegExpSource() {
   5646     return HObjectAccess(kInobject, JSRegExp::kSourceOffset);
   5647   }
   5648 
   5649   static HObjectAccess ForJSCollectionTable() {
   5650     return HObjectAccess::ForObservableJSObjectOffset(
   5651         JSCollection::kTableOffset);
   5652   }
   5653 
   5654   template <typename CollectionType>
   5655   static HObjectAccess ForOrderedHashTableNumberOfBuckets() {
   5656     return HObjectAccess(kInobject, CollectionType::kNumberOfBucketsOffset,
   5657                          Representation::Smi());
   5658   }
   5659 
   5660   template <typename CollectionType>
   5661   static HObjectAccess ForOrderedHashTableNumberOfElements() {
   5662     return HObjectAccess(kInobject, CollectionType::kNumberOfElementsOffset,
   5663                          Representation::Smi());
   5664   }
   5665 
   5666   template <typename CollectionType>
   5667   static HObjectAccess ForOrderedHashTableNumberOfDeletedElements() {
   5668     return HObjectAccess(kInobject,
   5669                          CollectionType::kNumberOfDeletedElementsOffset,
   5670                          Representation::Smi());
   5671   }
   5672 
   5673   template <typename CollectionType>
   5674   static HObjectAccess ForOrderedHashTableNextTable() {
   5675     return HObjectAccess(kInobject, CollectionType::kNextTableOffset);
   5676   }
   5677 
   5678   template <typename CollectionType>
   5679   static HObjectAccess ForOrderedHashTableBucket(int bucket) {
   5680     return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
   5681                                         (bucket * kPointerSize),
   5682                          Representation::Smi());
   5683   }
   5684 
   5685   // Access into the data table of an OrderedHashTable with a
   5686   // known-at-compile-time bucket count.
   5687   template <typename CollectionType, int kBucketCount>
   5688   static HObjectAccess ForOrderedHashTableDataTableIndex(int index) {
   5689     return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
   5690                                         (kBucketCount * kPointerSize) +
   5691                                         (index * kPointerSize));
   5692   }
   5693 
   5694   inline bool Equals(HObjectAccess that) const {
   5695     return value_ == that.value_;  // portion and offset must match
   5696   }
   5697 
   5698  protected:
   5699   void SetGVNFlags(HValue *instr, PropertyAccessType access_type);
   5700 
   5701  private:
   5702   // internal use only; different parts of an object or array
   5703   enum Portion {
   5704     kMaps,             // map of an object
   5705     kArrayLengths,     // the length of an array
   5706     kStringLengths,    // the length of a string
   5707     kElementsPointer,  // elements pointer
   5708     kBackingStore,     // some field in the backing store
   5709     kDouble,           // some double field
   5710     kInobject,         // some other in-object field
   5711     kExternalMemory    // some field in external memory
   5712   };
   5713 
   5714   HObjectAccess() : value_(0) {}
   5715 
   5716   HObjectAccess(Portion portion, int offset,
   5717                 Representation representation = Representation::Tagged(),
   5718                 Handle<Name> name = Handle<Name>::null(),
   5719                 bool immutable = false, bool existing_inobject_property = true)
   5720       : value_(PortionField::encode(portion) |
   5721                RepresentationField::encode(representation.kind()) |
   5722                ImmutableField::encode(immutable ? 1 : 0) |
   5723                ExistingInobjectPropertyField::encode(
   5724                    existing_inobject_property ? 1 : 0) |
   5725                OffsetField::encode(offset)),
   5726         name_(name) {
   5727     // assert that the fields decode correctly
   5728     DCHECK(this->offset() == offset);
   5729     DCHECK(this->portion() == portion);
   5730     DCHECK(this->immutable() == immutable);
   5731     DCHECK(this->existing_inobject_property() == existing_inobject_property);
   5732     DCHECK(RepresentationField::decode(value_) == representation.kind());
   5733     DCHECK(!this->existing_inobject_property() || IsInobject());
   5734   }
   5735 
   5736   class PortionField : public BitField<Portion, 0, 3> {};
   5737   class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
   5738   class ImmutableField : public BitField<bool, 7, 1> {};
   5739   class ExistingInobjectPropertyField : public BitField<bool, 8, 1> {};
   5740   class OffsetField : public BitField<int, 9, 23> {};
   5741 
   5742   uint32_t value_;  // encodes portion, representation, immutable, and offset
   5743   Handle<Name> name_;
   5744 
   5745   friend class HLoadNamedField;
   5746   friend class HStoreNamedField;
   5747   friend class SideEffectsTracker;
   5748   friend std::ostream& operator<<(std::ostream& os,
   5749                                   const HObjectAccess& access);
   5750 
   5751   inline Portion portion() const {
   5752     return PortionField::decode(value_);
   5753   }
   5754 };
   5755 
   5756 
   5757 std::ostream& operator<<(std::ostream& os, const HObjectAccess& access);
   5758 
   5759 
   5760 class HLoadNamedField final : public HTemplateInstruction<2> {
   5761  public:
   5762   DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*,
   5763                                  HValue*, HObjectAccess);
   5764   DECLARE_INSTRUCTION_FACTORY_P5(HLoadNamedField, HValue*, HValue*,
   5765                                  HObjectAccess, const UniqueSet<Map>*, HType);
   5766 
   5767   HValue* object() const { return OperandAt(0); }
   5768   HValue* dependency() const {
   5769     DCHECK(HasDependency());
   5770     return OperandAt(1);
   5771   }
   5772   bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
   5773   HObjectAccess access() const { return access_; }
   5774   Representation field_representation() const {
   5775       return access_.representation();
   5776   }
   5777 
   5778   const UniqueSet<Map>* maps() const { return maps_; }
   5779 
   5780   bool HasEscapingOperandAt(int index) override { return false; }
   5781   bool HasOutOfBoundsAccess(int size) override {
   5782     return !access().IsInobject() || access().offset() >= size;
   5783   }
   5784   Representation RequiredInputRepresentation(int index) override {
   5785     if (index == 0) {
   5786       // object must be external in case of external memory access
   5787       return access().IsExternalMemory() ? Representation::External()
   5788                                          : Representation::Tagged();
   5789     }
   5790     DCHECK(index == 1);
   5791     return Representation::None();
   5792   }
   5793   Range* InferRange(Zone* zone) override;
   5794   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5795 
   5796   bool CanBeReplacedWith(HValue* other) const {
   5797     if (!CheckFlag(HValue::kCantBeReplaced)) return false;
   5798     if (!type().Equals(other->type())) return false;
   5799     if (!representation().Equals(other->representation())) return false;
   5800     if (!other->IsLoadNamedField()) return true;
   5801     HLoadNamedField* that = HLoadNamedField::cast(other);
   5802     if (this->maps_ == that->maps_) return true;
   5803     if (this->maps_ == NULL || that->maps_ == NULL) return false;
   5804     return this->maps_->IsSubset(that->maps_);
   5805   }
   5806 
   5807   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
   5808 
   5809  protected:
   5810   bool DataEquals(HValue* other) override {
   5811     HLoadNamedField* that = HLoadNamedField::cast(other);
   5812     if (!this->access_.Equals(that->access_)) return false;
   5813     if (this->maps_ == that->maps_) return true;
   5814     return (this->maps_ != NULL &&
   5815             that->maps_ != NULL &&
   5816             this->maps_->Equals(that->maps_));
   5817   }
   5818 
   5819  private:
   5820   HLoadNamedField(HValue* object,
   5821                   HValue* dependency,
   5822                   HObjectAccess access)
   5823       : access_(access), maps_(NULL) {
   5824     DCHECK_NOT_NULL(object);
   5825     SetOperandAt(0, object);
   5826     SetOperandAt(1, dependency ? dependency : object);
   5827 
   5828     Representation representation = access.representation();
   5829     if (representation.IsInteger8() ||
   5830         representation.IsUInteger8() ||
   5831         representation.IsInteger16() ||
   5832         representation.IsUInteger16()) {
   5833       set_representation(Representation::Integer32());
   5834     } else if (representation.IsSmi()) {
   5835       set_type(HType::Smi());
   5836       if (SmiValuesAre32Bits()) {
   5837         set_representation(Representation::Integer32());
   5838       } else {
   5839         set_representation(representation);
   5840       }
   5841     } else if (representation.IsDouble() ||
   5842                representation.IsExternal() ||
   5843                representation.IsInteger32()) {
   5844       set_representation(representation);
   5845     } else if (representation.IsHeapObject()) {
   5846       set_type(HType::HeapObject());
   5847       set_representation(Representation::Tagged());
   5848     } else {
   5849       set_representation(Representation::Tagged());
   5850     }
   5851     access.SetGVNFlags(this, LOAD);
   5852   }
   5853 
   5854   HLoadNamedField(HValue* object,
   5855                   HValue* dependency,
   5856                   HObjectAccess access,
   5857                   const UniqueSet<Map>* maps,
   5858                   HType type)
   5859       : HTemplateInstruction<2>(type), access_(access), maps_(maps) {
   5860     DCHECK_NOT_NULL(maps);
   5861     DCHECK_NE(0, maps->size());
   5862 
   5863     DCHECK_NOT_NULL(object);
   5864     SetOperandAt(0, object);
   5865     SetOperandAt(1, dependency ? dependency : object);
   5866 
   5867     DCHECK(access.representation().IsHeapObject());
   5868     DCHECK(type.IsHeapObject());
   5869     set_representation(Representation::Tagged());
   5870 
   5871     access.SetGVNFlags(this, LOAD);
   5872   }
   5873 
   5874   bool IsDeletable() const override { return true; }
   5875 
   5876   HObjectAccess access_;
   5877   const UniqueSet<Map>* maps_;
   5878 };
   5879 
   5880 
   5881 class HLoadNamedGeneric final : public HTemplateInstruction<2> {
   5882  public:
   5883   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadNamedGeneric, HValue*,
   5884                                               Handle<Name>,
   5885                                               Handle<TypeFeedbackVector>,
   5886                                               FeedbackVectorSlot);
   5887 
   5888   HValue* context() const { return OperandAt(0); }
   5889   HValue* object() const { return OperandAt(1); }
   5890   Handle<Name> name() const { return name_; }
   5891 
   5892   FeedbackVectorSlot slot() const { return slot_; }
   5893   Handle<TypeFeedbackVector> feedback_vector() const {
   5894     return feedback_vector_;
   5895   }
   5896 
   5897   Representation RequiredInputRepresentation(int index) override {
   5898     return Representation::Tagged();
   5899   }
   5900 
   5901   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5902 
   5903   DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
   5904 
   5905  private:
   5906   HLoadNamedGeneric(HValue* context, HValue* object, Handle<Name> name,
   5907                     Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
   5908       : name_(name), feedback_vector_(vector), slot_(slot) {
   5909     SetOperandAt(0, context);
   5910     SetOperandAt(1, object);
   5911     set_representation(Representation::Tagged());
   5912     SetAllSideEffects();
   5913   }
   5914 
   5915   Handle<Name> name_;
   5916   Handle<TypeFeedbackVector> feedback_vector_;
   5917   FeedbackVectorSlot slot_;
   5918 };
   5919 
   5920 
   5921 class HLoadFunctionPrototype final : public HUnaryOperation {
   5922  public:
   5923   DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);
   5924 
   5925   HValue* function() { return OperandAt(0); }
   5926 
   5927   Representation RequiredInputRepresentation(int index) override {
   5928     return Representation::Tagged();
   5929   }
   5930 
   5931   DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
   5932 
   5933  protected:
   5934   bool DataEquals(HValue* other) override { return true; }
   5935 
   5936  private:
   5937   explicit HLoadFunctionPrototype(HValue* function)
   5938       : HUnaryOperation(function) {
   5939     set_representation(Representation::Tagged());
   5940     SetFlag(kUseGVN);
   5941     SetDependsOnFlag(kCalls);
   5942   }
   5943 };
   5944 
   5945 class ArrayInstructionInterface {
   5946  public:
   5947   virtual HValue* GetKey() = 0;
   5948   virtual void SetKey(HValue* key) = 0;
   5949   virtual ElementsKind elements_kind() const = 0;
   5950   // TryIncreaseBaseOffset returns false if overflow would result.
   5951   virtual bool TryIncreaseBaseOffset(uint32_t increase_by_value) = 0;
   5952   virtual bool IsDehoisted() const = 0;
   5953   virtual void SetDehoisted(bool is_dehoisted) = 0;
   5954   virtual ~ArrayInstructionInterface() { }
   5955 
   5956   static Representation KeyedAccessIndexRequirement(Representation r) {
   5957     return r.IsInteger32() || SmiValuesAre32Bits()
   5958         ? Representation::Integer32() : Representation::Smi();
   5959   }
   5960 };
   5961 
   5962 
   5963 static const int kDefaultKeyedHeaderOffsetSentinel = -1;
   5964 
   5965 enum LoadKeyedHoleMode {
   5966   NEVER_RETURN_HOLE,
   5967   ALLOW_RETURN_HOLE,
   5968   CONVERT_HOLE_TO_UNDEFINED
   5969 };
   5970 
   5971 
   5972 class HLoadKeyed final : public HTemplateInstruction<4>,
   5973                          public ArrayInstructionInterface {
   5974  public:
   5975   DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
   5976                                  ElementsKind);
   5977   DECLARE_INSTRUCTION_FACTORY_P6(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
   5978                                  ElementsKind, LoadKeyedHoleMode);
   5979   DECLARE_INSTRUCTION_FACTORY_P7(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
   5980                                  ElementsKind, LoadKeyedHoleMode, int);
   5981 
   5982   bool is_fixed_typed_array() const {
   5983     return IsFixedTypedArrayElementsKind(elements_kind());
   5984   }
   5985   HValue* elements() const { return OperandAt(0); }
   5986   HValue* key() const { return OperandAt(1); }
   5987   HValue* dependency() const {
   5988     DCHECK(HasDependency());
   5989     return OperandAt(2);
   5990   }
   5991   bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
   5992   HValue* backing_store_owner() const {
   5993     DCHECK(HasBackingStoreOwner());
   5994     return OperandAt(3);
   5995   }
   5996   bool HasBackingStoreOwner() const { return OperandAt(0) != OperandAt(3); }
   5997   uint32_t base_offset() const { return BaseOffsetField::decode(bit_field_); }
   5998   bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
   5999   HValue* GetKey() override { return key(); }
   6000   void SetKey(HValue* key) override { SetOperandAt(1, key); }
   6001   bool IsDehoisted() const override {
   6002     return IsDehoistedField::decode(bit_field_);
   6003   }
   6004   void SetDehoisted(bool is_dehoisted) override {
   6005     bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
   6006   }
   6007   ElementsKind elements_kind() const override {
   6008     return ElementsKindField::decode(bit_field_);
   6009   }
   6010   LoadKeyedHoleMode hole_mode() const {
   6011     return HoleModeField::decode(bit_field_);
   6012   }
   6013 
   6014   Representation RequiredInputRepresentation(int index) override {
   6015     // kind_fast:                 tagged[int32] (none)
   6016     // kind_double:               tagged[int32] (none)
   6017     // kind_fixed_typed_array:    external[int32] (none)
   6018     // kind_external:             external[int32] (none)
   6019     if (index == 0) {
   6020       return is_fixed_typed_array() ? Representation::External()
   6021                                     : Representation::Tagged();
   6022     }
   6023     if (index == 1) {
   6024       return ArrayInstructionInterface::KeyedAccessIndexRequirement(
   6025           OperandAt(1)->representation());
   6026     }
   6027     if (index == 2) {
   6028       return Representation::None();
   6029     }
   6030     DCHECK_EQ(3, index);
   6031     return HasBackingStoreOwner() ? Representation::Tagged()
   6032                                   : Representation::None();
   6033   }
   6034 
   6035   Representation observed_input_representation(int index) override {
   6036     return RequiredInputRepresentation(index);
   6037   }
   6038 
   6039   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6040 
   6041   bool UsesMustHandleHole() const;
   6042   bool AllUsesCanTreatHoleAsNaN() const;
   6043   bool RequiresHoleCheck() const;
   6044 
   6045   Range* InferRange(Zone* zone) override;
   6046 
   6047   DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)
   6048 
   6049  protected:
   6050   bool DataEquals(HValue* other) override {
   6051     if (!other->IsLoadKeyed()) return false;
   6052     HLoadKeyed* other_load = HLoadKeyed::cast(other);
   6053 
   6054     if (base_offset() != other_load->base_offset()) return false;
   6055     return elements_kind() == other_load->elements_kind();
   6056   }
   6057 
   6058  private:
   6059   HLoadKeyed(HValue* obj, HValue* key, HValue* dependency,
   6060              HValue* backing_store_owner, ElementsKind elements_kind,
   6061              LoadKeyedHoleMode mode = NEVER_RETURN_HOLE,
   6062              int offset = kDefaultKeyedHeaderOffsetSentinel)
   6063       : bit_field_(0) {
   6064     offset = offset == kDefaultKeyedHeaderOffsetSentinel
   6065         ? GetDefaultHeaderSizeForElementsKind(elements_kind)
   6066         : offset;
   6067     bit_field_ = ElementsKindField::encode(elements_kind) |
   6068         HoleModeField::encode(mode) |
   6069         BaseOffsetField::encode(offset);
   6070 
   6071     SetOperandAt(0, obj);
   6072     SetOperandAt(1, key);
   6073     SetOperandAt(2, dependency != nullptr ? dependency : obj);
   6074     SetOperandAt(3, backing_store_owner != nullptr ? backing_store_owner : obj);
   6075     DCHECK_EQ(HasBackingStoreOwner(), is_fixed_typed_array());
   6076 
   6077     if (!is_fixed_typed_array()) {
   6078       // I can detect the case between storing double (holey and fast) and
   6079       // smi/object by looking at elements_kind_.
   6080       DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
   6081              IsFastDoubleElementsKind(elements_kind));
   6082 
   6083       if (IsFastSmiOrObjectElementsKind(elements_kind)) {
   6084         if (IsFastSmiElementsKind(elements_kind) &&
   6085             (!IsHoleyElementsKind(elements_kind) ||
   6086              mode == NEVER_RETURN_HOLE)) {
   6087           set_type(HType::Smi());
   6088           if (SmiValuesAre32Bits() && !RequiresHoleCheck()) {
   6089             set_representation(Representation::Integer32());
   6090           } else {
   6091             set_representation(Representation::Smi());
   6092           }
   6093         } else {
   6094           set_representation(Representation::Tagged());
   6095         }
   6096 
   6097         SetDependsOnFlag(kArrayElements);
   6098       } else {
   6099         set_representation(Representation::Double());
   6100         SetDependsOnFlag(kDoubleArrayElements);
   6101       }
   6102     } else {
   6103       if (elements_kind == FLOAT32_ELEMENTS ||
   6104           elements_kind == FLOAT64_ELEMENTS) {
   6105         set_representation(Representation::Double());
   6106       } else {
   6107         set_representation(Representation::Integer32());
   6108       }
   6109 
   6110       if (is_fixed_typed_array()) {
   6111         SetDependsOnFlag(kExternalMemory);
   6112         SetDependsOnFlag(kTypedArrayElements);
   6113       } else {
   6114         UNREACHABLE();
   6115       }
   6116       // Native code could change the specialized array.
   6117       SetDependsOnFlag(kCalls);
   6118     }
   6119 
   6120     SetFlag(kUseGVN);
   6121   }
   6122 
   6123   bool IsDeletable() const override { return !RequiresHoleCheck(); }
   6124 
   6125   // Establish some checks around our packed fields
   6126   enum LoadKeyedBits {
   6127     kBitsForElementsKind = 5,
   6128     kBitsForHoleMode = 2,
   6129     kBitsForBaseOffset = 24,
   6130     kBitsForIsDehoisted = 1,
   6131 
   6132     kStartElementsKind = 0,
   6133     kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
   6134     kStartBaseOffset = kStartHoleMode + kBitsForHoleMode,
   6135     kStartIsDehoisted = kStartBaseOffset + kBitsForBaseOffset
   6136   };
   6137 
   6138   STATIC_ASSERT((kBitsForElementsKind + kBitsForHoleMode + kBitsForBaseOffset +
   6139                  kBitsForIsDehoisted) <= sizeof(uint32_t) * 8);
   6140   STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
   6141   class ElementsKindField:
   6142     public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
   6143     {};  // NOLINT
   6144   class HoleModeField:
   6145     public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
   6146     {};  // NOLINT
   6147   class BaseOffsetField:
   6148     public BitField<uint32_t, kStartBaseOffset, kBitsForBaseOffset>
   6149     {};  // NOLINT
   6150   class IsDehoistedField:
   6151     public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
   6152     {};  // NOLINT
   6153   uint32_t bit_field_;
   6154 };
   6155 
   6156 
   6157 class HLoadKeyedGeneric final : public HTemplateInstruction<3> {
   6158  public:
   6159   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadKeyedGeneric, HValue*,
   6160                                               HValue*,
   6161                                               Handle<TypeFeedbackVector>,
   6162                                               FeedbackVectorSlot);
   6163   HValue* object() const { return OperandAt(0); }
   6164   HValue* key() const { return OperandAt(1); }
   6165   HValue* context() const { return OperandAt(2); }
   6166   FeedbackVectorSlot slot() const { return slot_; }
   6167   Handle<TypeFeedbackVector> feedback_vector() const {
   6168     return feedback_vector_;
   6169   }
   6170 
   6171   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6172 
   6173   Representation RequiredInputRepresentation(int index) override {
   6174     // tagged[tagged]
   6175     return Representation::Tagged();
   6176   }
   6177 
   6178   HValue* Canonicalize() override;
   6179 
   6180   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
   6181 
   6182  private:
   6183   HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key,
   6184                     Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
   6185       : feedback_vector_(vector), slot_(slot) {
   6186     set_representation(Representation::Tagged());
   6187     SetOperandAt(0, obj);
   6188     SetOperandAt(1, key);
   6189     SetOperandAt(2, context);
   6190     SetAllSideEffects();
   6191   }
   6192 
   6193   Handle<TypeFeedbackVector> feedback_vector_;
   6194   FeedbackVectorSlot slot_;
   6195 };
   6196 
   6197 
   6198 // Indicates whether the store is a store to an entry that was previously
   6199 // initialized or not.
   6200 enum StoreFieldOrKeyedMode {
   6201   // The entry could be either previously initialized or not.
   6202   INITIALIZING_STORE,
   6203   // At the time of this store it is guaranteed that the entry is already
   6204   // initialized.
   6205   STORE_TO_INITIALIZED_ENTRY
   6206 };
   6207 
   6208 
   6209 class HStoreNamedField final : public HTemplateInstruction<3> {
   6210  public:
   6211   DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
   6212                                  HObjectAccess, HValue*);
   6213   DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue*,
   6214                                  HObjectAccess, HValue*, StoreFieldOrKeyedMode);
   6215 
   6216   DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
   6217 
   6218   bool HasEscapingOperandAt(int index) override { return index == 1; }
   6219   bool HasOutOfBoundsAccess(int size) override {
   6220     return !access().IsInobject() || access().offset() >= size;
   6221   }
   6222   Representation RequiredInputRepresentation(int index) override {
   6223     if (index == 0 && access().IsExternalMemory()) {
   6224       // object must be external in case of external memory access
   6225       return Representation::External();
   6226     } else if (index == 1) {
   6227       if (field_representation().IsInteger8() ||
   6228           field_representation().IsUInteger8() ||
   6229           field_representation().IsInteger16() ||
   6230           field_representation().IsUInteger16() ||
   6231           field_representation().IsInteger32()) {
   6232         return Representation::Integer32();
   6233       } else if (field_representation().IsDouble()) {
   6234         return field_representation();
   6235       } else if (field_representation().IsSmi()) {
   6236         if (SmiValuesAre32Bits() &&
   6237             store_mode() == STORE_TO_INITIALIZED_ENTRY) {
   6238           return Representation::Integer32();
   6239         }
   6240         return field_representation();
   6241       } else if (field_representation().IsExternal()) {
   6242         return Representation::External();
   6243       }
   6244     }
   6245     return Representation::Tagged();
   6246   }
   6247   bool HandleSideEffectDominator(GVNFlag side_effect,
   6248                                  HValue* dominator) override {
   6249     DCHECK(side_effect == kNewSpacePromotion);
   6250     if (!FLAG_use_write_barrier_elimination) return false;
   6251     dominator_ = dominator;
   6252     return false;
   6253   }
   6254   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6255 
   6256   HValue* object() const { return OperandAt(0); }
   6257   HValue* value() const { return OperandAt(1); }
   6258   HValue* transition() const { return OperandAt(2); }
   6259 
   6260   HObjectAccess access() const { return access_; }
   6261   HValue* dominator() const { return dominator_; }
   6262   bool has_transition() const { return HasTransitionField::decode(bit_field_); }
   6263   StoreFieldOrKeyedMode store_mode() const {
   6264     return StoreModeField::decode(bit_field_);
   6265   }
   6266 
   6267   Handle<Map> transition_map() const {
   6268     if (has_transition()) {
   6269       return Handle<Map>::cast(
   6270           HConstant::cast(transition())->handle(isolate()));
   6271     } else {
   6272       return Handle<Map>();
   6273     }
   6274   }
   6275 
   6276   void SetTransition(HConstant* transition) {
   6277     DCHECK(!has_transition());  // Only set once.
   6278     SetOperandAt(2, transition);
   6279     bit_field_ = HasTransitionField::update(bit_field_, true);
   6280     SetChangesFlag(kMaps);
   6281   }
   6282 
   6283   bool NeedsWriteBarrier() const {
   6284     DCHECK(!field_representation().IsDouble() ||
   6285            (FLAG_unbox_double_fields && access_.IsInobject()) ||
   6286            !has_transition());
   6287     if (field_representation().IsDouble()) return false;
   6288     if (field_representation().IsSmi()) return false;
   6289     if (field_representation().IsInteger32()) return false;
   6290     if (field_representation().IsExternal()) return false;
   6291     return StoringValueNeedsWriteBarrier(value()) &&
   6292         ReceiverObjectNeedsWriteBarrier(object(), value(), dominator());
   6293   }
   6294 
   6295   bool NeedsWriteBarrierForMap() {
   6296     return ReceiverObjectNeedsWriteBarrier(object(), transition(),
   6297                                            dominator());
   6298   }
   6299 
   6300   SmiCheck SmiCheckForWriteBarrier() const {
   6301     if (field_representation().IsHeapObject()) return OMIT_SMI_CHECK;
   6302     if (value()->type().IsHeapObject()) return OMIT_SMI_CHECK;
   6303     return INLINE_SMI_CHECK;
   6304   }
   6305 
   6306   PointersToHereCheck PointersToHereCheckForValue() const {
   6307     return PointersToHereCheckForObject(value(), dominator());
   6308   }
   6309 
   6310   Representation field_representation() const {
   6311     return access_.representation();
   6312   }
   6313 
   6314   void UpdateValue(HValue* value) {
   6315     SetOperandAt(1, value);
   6316   }
   6317 
   6318   bool CanBeReplacedWith(HStoreNamedField* that) const {
   6319     if (!this->access().Equals(that->access())) return false;
   6320     if (SmiValuesAre32Bits() &&
   6321         this->field_representation().IsSmi() &&
   6322         this->store_mode() == INITIALIZING_STORE &&
   6323         that->store_mode() == STORE_TO_INITIALIZED_ENTRY) {
   6324       // We cannot replace an initializing store to a smi field with a store to
   6325       // an initialized entry on 64-bit architectures (with 32-bit smis).
   6326       return false;
   6327     }
   6328     return true;
   6329   }
   6330 
   6331  private:
   6332   HStoreNamedField(HValue* obj, HObjectAccess access, HValue* val,
   6333                    StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
   6334       : access_(access),
   6335         dominator_(NULL),
   6336         bit_field_(HasTransitionField::encode(false) |
   6337                    StoreModeField::encode(store_mode)) {
   6338     // Stores to a non existing in-object property are allowed only to the
   6339     // newly allocated objects (via HAllocate or HInnerAllocatedObject).
   6340     DCHECK(!access.IsInobject() || access.existing_inobject_property() ||
   6341            obj->IsAllocate() || obj->IsInnerAllocatedObject());
   6342     SetOperandAt(0, obj);
   6343     SetOperandAt(1, val);
   6344     SetOperandAt(2, obj);
   6345     access.SetGVNFlags(this, STORE);
   6346   }
   6347 
   6348   class HasTransitionField : public BitField<bool, 0, 1> {};
   6349   class StoreModeField : public BitField<StoreFieldOrKeyedMode, 1, 1> {};
   6350 
   6351   HObjectAccess access_;
   6352   HValue* dominator_;
   6353   uint32_t bit_field_;
   6354 };
   6355 
   6356 class HStoreNamedGeneric final : public HTemplateInstruction<3> {
   6357  public:
   6358   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(HStoreNamedGeneric, HValue*,
   6359                                               Handle<Name>, HValue*,
   6360                                               LanguageMode,
   6361                                               Handle<TypeFeedbackVector>,
   6362                                               FeedbackVectorSlot);
   6363   HValue* object() const { return OperandAt(0); }
   6364   HValue* value() const { return OperandAt(1); }
   6365   HValue* context() const { return OperandAt(2); }
   6366   Handle<Name> name() const { return name_; }
   6367   LanguageMode language_mode() const { return language_mode_; }
   6368 
   6369   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6370 
   6371   Representation RequiredInputRepresentation(int index) override {
   6372     return Representation::Tagged();
   6373   }
   6374 
   6375   FeedbackVectorSlot slot() const { return slot_; }
   6376   Handle<TypeFeedbackVector> feedback_vector() const {
   6377     return feedback_vector_;
   6378   }
   6379 
   6380   DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
   6381 
   6382  private:
   6383   HStoreNamedGeneric(HValue* context, HValue* object, Handle<Name> name,
   6384                      HValue* value, LanguageMode language_mode,
   6385                      Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
   6386       : name_(name),
   6387         feedback_vector_(vector),
   6388         slot_(slot),
   6389         language_mode_(language_mode) {
   6390     SetOperandAt(0, object);
   6391     SetOperandAt(1, value);
   6392     SetOperandAt(2, context);
   6393     SetAllSideEffects();
   6394   }
   6395 
   6396   Handle<Name> name_;
   6397   Handle<TypeFeedbackVector> feedback_vector_;
   6398   FeedbackVectorSlot slot_;
   6399   LanguageMode language_mode_;
   6400 };
   6401 
   6402 class HStoreKeyed final : public HTemplateInstruction<4>,
   6403                           public ArrayInstructionInterface {
   6404  public:
   6405   DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*,
   6406                                  HValue*, ElementsKind);
   6407   DECLARE_INSTRUCTION_FACTORY_P6(HStoreKeyed, HValue*, HValue*, HValue*,
   6408                                  HValue*, ElementsKind, StoreFieldOrKeyedMode);
   6409   DECLARE_INSTRUCTION_FACTORY_P7(HStoreKeyed, HValue*, HValue*, HValue*,
   6410                                  HValue*, ElementsKind, StoreFieldOrKeyedMode,
   6411                                  int);
   6412 
   6413   Representation RequiredInputRepresentation(int index) override {
   6414     // kind_fast:               tagged[int32] = tagged
   6415     // kind_double:             tagged[int32] = double
   6416     // kind_smi   :             tagged[int32] = smi
   6417     // kind_fixed_typed_array:  tagged[int32] = (double | int32)
   6418     // kind_external:           external[int32] = (double | int32)
   6419     if (index == 0) {
   6420       return is_fixed_typed_array() ? Representation::External()
   6421                                     : Representation::Tagged();
   6422     } else if (index == 1) {
   6423       return ArrayInstructionInterface::KeyedAccessIndexRequirement(
   6424           OperandAt(1)->representation());
   6425     } else if (index == 2) {
   6426       return RequiredValueRepresentation(elements_kind(), store_mode());
   6427     }
   6428 
   6429     DCHECK_EQ(3, index);
   6430     return HasBackingStoreOwner() ? Representation::Tagged()
   6431                                   : Representation::None();
   6432   }
   6433 
   6434   static Representation RequiredValueRepresentation(
   6435       ElementsKind kind, StoreFieldOrKeyedMode mode) {
   6436     if (IsDoubleOrFloatElementsKind(kind)) {
   6437       return Representation::Double();
   6438     }
   6439 
   6440     if (kind == FAST_SMI_ELEMENTS && SmiValuesAre32Bits() &&
   6441         mode == STORE_TO_INITIALIZED_ENTRY) {
   6442       return Representation::Integer32();
   6443     }
   6444 
   6445     if (IsFastSmiElementsKind(kind)) {
   6446       return Representation::Smi();
   6447     }
   6448 
   6449     if (IsFixedTypedArrayElementsKind(kind)) {
   6450       return Representation::Integer32();
   6451     }
   6452     return Representation::Tagged();
   6453   }
   6454 
   6455   bool is_fixed_typed_array() const {
   6456     return IsFixedTypedArrayElementsKind(elements_kind());
   6457   }
   6458 
   6459   Representation observed_input_representation(int index) override {
   6460     if (index != 2) return RequiredInputRepresentation(index);
   6461     if (IsUninitialized()) {
   6462       return Representation::None();
   6463     }
   6464     Representation r =
   6465         RequiredValueRepresentation(elements_kind(), store_mode());
   6466     // For fast object elements kinds, don't assume anything.
   6467     if (r.IsTagged()) return Representation::None();
   6468     return r;
   6469   }
   6470 
   6471   HValue* elements() const { return OperandAt(0); }
   6472   HValue* key() const { return OperandAt(1); }
   6473   HValue* value() const { return OperandAt(2); }
   6474   HValue* backing_store_owner() const {
   6475     DCHECK(HasBackingStoreOwner());
   6476     return OperandAt(3);
   6477   }
   6478   bool HasBackingStoreOwner() const { return OperandAt(0) != OperandAt(3); }
   6479   bool value_is_smi() const { return IsFastSmiElementsKind(elements_kind()); }
   6480   StoreFieldOrKeyedMode store_mode() const {
   6481     return StoreModeField::decode(bit_field_);
   6482   }
   6483   ElementsKind elements_kind() const override {
   6484     return ElementsKindField::decode(bit_field_);
   6485   }
   6486   uint32_t base_offset() const { return base_offset_; }
   6487   bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
   6488   HValue* GetKey() override { return key(); }
   6489   void SetKey(HValue* key) override { SetOperandAt(1, key); }
   6490   bool IsDehoisted() const override {
   6491     return IsDehoistedField::decode(bit_field_);
   6492   }
   6493   void SetDehoisted(bool is_dehoisted) override {
   6494     bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
   6495   }
   6496   bool IsUninitialized() { return IsUninitializedField::decode(bit_field_); }
   6497   void SetUninitialized(bool is_uninitialized) {
   6498     bit_field_ = IsUninitializedField::update(bit_field_, is_uninitialized);
   6499   }
   6500 
   6501   bool IsConstantHoleStore() {
   6502     return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
   6503   }
   6504 
   6505   bool HandleSideEffectDominator(GVNFlag side_effect,
   6506                                  HValue* dominator) override {
   6507     DCHECK(side_effect == kNewSpacePromotion);
   6508     dominator_ = dominator;
   6509     return false;
   6510   }
   6511 
   6512   HValue* dominator() const { return dominator_; }
   6513 
   6514   bool NeedsWriteBarrier() {
   6515     if (value_is_smi()) {
   6516       return false;
   6517     } else {
   6518       return StoringValueNeedsWriteBarrier(value()) &&
   6519           ReceiverObjectNeedsWriteBarrier(elements(), value(), dominator());
   6520     }
   6521   }
   6522 
   6523   PointersToHereCheck PointersToHereCheckForValue() const {
   6524     return PointersToHereCheckForObject(value(), dominator());
   6525   }
   6526 
   6527   bool NeedsCanonicalization();
   6528 
   6529   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6530 
   6531   DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
   6532 
   6533  private:
   6534   HStoreKeyed(HValue* obj, HValue* key, HValue* val,
   6535               HValue* backing_store_owner, ElementsKind elements_kind,
   6536               StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE,
   6537               int offset = kDefaultKeyedHeaderOffsetSentinel)
   6538       : base_offset_(offset == kDefaultKeyedHeaderOffsetSentinel
   6539                          ? GetDefaultHeaderSizeForElementsKind(elements_kind)
   6540                          : offset),
   6541         bit_field_(IsDehoistedField::encode(false) |
   6542                    IsUninitializedField::encode(false) |
   6543                    StoreModeField::encode(store_mode) |
   6544                    ElementsKindField::encode(elements_kind)),
   6545         dominator_(NULL) {
   6546     SetOperandAt(0, obj);
   6547     SetOperandAt(1, key);
   6548     SetOperandAt(2, val);
   6549     SetOperandAt(3, backing_store_owner != nullptr ? backing_store_owner : obj);
   6550     DCHECK_EQ(HasBackingStoreOwner(), is_fixed_typed_array());
   6551 
   6552     if (IsFastObjectElementsKind(elements_kind)) {
   6553       SetFlag(kTrackSideEffectDominators);
   6554       SetDependsOnFlag(kNewSpacePromotion);
   6555     }
   6556     if (IsFastDoubleElementsKind(elements_kind)) {
   6557       SetChangesFlag(kDoubleArrayElements);
   6558     } else if (IsFastSmiElementsKind(elements_kind)) {
   6559       SetChangesFlag(kArrayElements);
   6560     } else if (is_fixed_typed_array()) {
   6561       SetChangesFlag(kTypedArrayElements);
   6562       SetChangesFlag(kExternalMemory);
   6563       SetFlag(kAllowUndefinedAsNaN);
   6564     } else {
   6565       SetChangesFlag(kArrayElements);
   6566     }
   6567 
   6568     // {UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
   6569     if (elements_kind >= UINT8_ELEMENTS && elements_kind <= INT32_ELEMENTS) {
   6570       SetFlag(kTruncatingToInt32);
   6571     }
   6572   }
   6573 
   6574   class IsDehoistedField : public BitField<bool, 0, 1> {};
   6575   class IsUninitializedField : public BitField<bool, 1, 1> {};
   6576   class StoreModeField : public BitField<StoreFieldOrKeyedMode, 2, 1> {};
   6577   class ElementsKindField : public BitField<ElementsKind, 3, 5> {};
   6578 
   6579   uint32_t base_offset_;
   6580   uint32_t bit_field_;
   6581   HValue* dominator_;
   6582 };
   6583 
   6584 class HStoreKeyedGeneric final : public HTemplateInstruction<4> {
   6585  public:
   6586   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(HStoreKeyedGeneric, HValue*,
   6587                                               HValue*, HValue*, LanguageMode,
   6588                                               Handle<TypeFeedbackVector>,
   6589                                               FeedbackVectorSlot);
   6590 
   6591   HValue* object() const { return OperandAt(0); }
   6592   HValue* key() const { return OperandAt(1); }
   6593   HValue* value() const { return OperandAt(2); }
   6594   HValue* context() const { return OperandAt(3); }
   6595   LanguageMode language_mode() const { return language_mode_; }
   6596 
   6597   Representation RequiredInputRepresentation(int index) override {
   6598     // tagged[tagged] = tagged
   6599     return Representation::Tagged();
   6600   }
   6601 
   6602   FeedbackVectorSlot slot() const { return slot_; }
   6603   Handle<TypeFeedbackVector> feedback_vector() const {
   6604     return feedback_vector_;
   6605   }
   6606 
   6607   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6608 
   6609   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
   6610 
   6611  private:
   6612   HStoreKeyedGeneric(HValue* context, HValue* object, HValue* key,
   6613                      HValue* value, LanguageMode language_mode,
   6614                      Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
   6615       : feedback_vector_(vector), slot_(slot), language_mode_(language_mode) {
   6616     SetOperandAt(0, object);
   6617     SetOperandAt(1, key);
   6618     SetOperandAt(2, value);
   6619     SetOperandAt(3, context);
   6620     SetAllSideEffects();
   6621   }
   6622 
   6623   Handle<TypeFeedbackVector> feedback_vector_;
   6624   FeedbackVectorSlot slot_;
   6625   LanguageMode language_mode_;
   6626 };
   6627 
   6628 class HTransitionElementsKind final : public HTemplateInstruction<2> {
   6629  public:
   6630   inline static HTransitionElementsKind* New(Isolate* isolate, Zone* zone,
   6631                                              HValue* context, HValue* object,
   6632                                              Handle<Map> original_map,
   6633                                              Handle<Map> transitioned_map) {
   6634     return new(zone) HTransitionElementsKind(context, object,
   6635                                              original_map, transitioned_map);
   6636   }
   6637 
   6638   Representation RequiredInputRepresentation(int index) override {
   6639     return Representation::Tagged();
   6640   }
   6641 
   6642   HValue* object() const { return OperandAt(0); }
   6643   HValue* context() const { return OperandAt(1); }
   6644   Unique<Map> original_map() const { return original_map_; }
   6645   Unique<Map> transitioned_map() const { return transitioned_map_; }
   6646   ElementsKind from_kind() const {
   6647     return FromElementsKindField::decode(bit_field_);
   6648   }
   6649   ElementsKind to_kind() const {
   6650     return ToElementsKindField::decode(bit_field_);
   6651   }
   6652   bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }
   6653 
   6654   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6655 
   6656   DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
   6657 
   6658  protected:
   6659   bool DataEquals(HValue* other) override {
   6660     HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
   6661     return original_map_ == instr->original_map_ &&
   6662            transitioned_map_ == instr->transitioned_map_;
   6663   }
   6664 
   6665   int RedefinedOperandIndex() override { return 0; }
   6666 
   6667  private:
   6668   HTransitionElementsKind(HValue* context, HValue* object,
   6669                           Handle<Map> original_map,
   6670                           Handle<Map> transitioned_map)
   6671       : original_map_(Unique<Map>(original_map)),
   6672         transitioned_map_(Unique<Map>(transitioned_map)),
   6673         bit_field_(
   6674             FromElementsKindField::encode(original_map->elements_kind()) |
   6675             ToElementsKindField::encode(transitioned_map->elements_kind()) |
   6676             MapIsStableField::encode(transitioned_map->is_stable())) {
   6677     SetOperandAt(0, object);
   6678     SetOperandAt(1, context);
   6679     SetFlag(kUseGVN);
   6680     SetChangesFlag(kElementsKind);
   6681     if (!IsSimpleMapChangeTransition(from_kind(), to_kind())) {
   6682       SetChangesFlag(kElementsPointer);
   6683       SetChangesFlag(kNewSpacePromotion);
   6684     }
   6685     set_representation(Representation::Tagged());
   6686   }
   6687 
   6688   class FromElementsKindField : public BitField<ElementsKind, 0, 5> {};
   6689   class ToElementsKindField : public BitField<ElementsKind, 5, 5> {};
   6690   class MapIsStableField : public BitField<bool, 10, 1> {};
   6691 
   6692   Unique<Map> original_map_;
   6693   Unique<Map> transitioned_map_;
   6694   uint32_t bit_field_;
   6695 };
   6696 
   6697 
   6698 class HStringAdd final : public HBinaryOperation {
   6699  public:
   6700   static HInstruction* New(
   6701       Isolate* isolate, Zone* zone, HValue* context, HValue* left,
   6702       HValue* right, PretenureFlag pretenure_flag = NOT_TENURED,
   6703       StringAddFlags flags = STRING_ADD_CHECK_BOTH,
   6704       Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null());
   6705 
   6706   StringAddFlags flags() const { return flags_; }
   6707   PretenureFlag pretenure_flag() const { return pretenure_flag_; }
   6708 
   6709   Representation RequiredInputRepresentation(int index) override {
   6710     return Representation::Tagged();
   6711   }
   6712 
   6713   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6714 
   6715   DECLARE_CONCRETE_INSTRUCTION(StringAdd)
   6716 
   6717  protected:
   6718   bool DataEquals(HValue* other) override {
   6719     return flags_ == HStringAdd::cast(other)->flags_ &&
   6720         pretenure_flag_ == HStringAdd::cast(other)->pretenure_flag_;
   6721   }
   6722 
   6723  private:
   6724   HStringAdd(HValue* context, HValue* left, HValue* right,
   6725              PretenureFlag pretenure_flag, StringAddFlags flags,
   6726              Handle<AllocationSite> allocation_site)
   6727       : HBinaryOperation(context, left, right, HType::String()),
   6728         flags_(flags),
   6729         pretenure_flag_(pretenure_flag) {
   6730     set_representation(Representation::Tagged());
   6731     if ((flags & STRING_ADD_CONVERT) == STRING_ADD_CONVERT) {
   6732       SetAllSideEffects();
   6733       ClearFlag(kUseGVN);
   6734     } else {
   6735       SetChangesFlag(kNewSpacePromotion);
   6736       SetFlag(kUseGVN);
   6737     }
   6738     SetDependsOnFlag(kMaps);
   6739     if (FLAG_trace_pretenuring) {
   6740       PrintF("HStringAdd with AllocationSite %p %s\n",
   6741              allocation_site.is_null()
   6742                  ? static_cast<void*>(NULL)
   6743                  : static_cast<void*>(*allocation_site),
   6744              pretenure_flag == TENURED ? "tenured" : "not tenured");
   6745     }
   6746   }
   6747 
   6748   bool IsDeletable() const final {
   6749     return (flags_ & STRING_ADD_CONVERT) != STRING_ADD_CONVERT;
   6750   }
   6751 
   6752   const StringAddFlags flags_;
   6753   const PretenureFlag pretenure_flag_;
   6754 };
   6755 
   6756 
   6757 class HStringCharCodeAt final : public HTemplateInstruction<3> {
   6758  public:
   6759   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HStringCharCodeAt,
   6760                                               HValue*,
   6761                                               HValue*);
   6762 
   6763   Representation RequiredInputRepresentation(int index) override {
   6764     // The index is supposed to be Integer32.
   6765     return index == 2
   6766         ? Representation::Integer32()
   6767         : Representation::Tagged();
   6768   }
   6769 
   6770   HValue* context() const { return OperandAt(0); }
   6771   HValue* string() const { return OperandAt(1); }
   6772   HValue* index() const { return OperandAt(2); }
   6773 
   6774   DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
   6775 
   6776  protected:
   6777   bool DataEquals(HValue* other) override { return true; }
   6778 
   6779   Range* InferRange(Zone* zone) override {
   6780     return new(zone) Range(0, String::kMaxUtf16CodeUnit);
   6781   }
   6782 
   6783  private:
   6784   HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
   6785     SetOperandAt(0, context);
   6786     SetOperandAt(1, string);
   6787     SetOperandAt(2, index);
   6788     set_representation(Representation::Integer32());
   6789     SetFlag(kUseGVN);
   6790     SetDependsOnFlag(kMaps);
   6791     SetDependsOnFlag(kStringChars);
   6792     SetChangesFlag(kNewSpacePromotion);
   6793   }
   6794 
   6795   // No side effects: runtime function assumes string + number inputs.
   6796   bool IsDeletable() const override { return true; }
   6797 };
   6798 
   6799 
   6800 class HStringCharFromCode final : public HTemplateInstruction<2> {
   6801  public:
   6802   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   6803                            HValue* char_code);
   6804 
   6805   Representation RequiredInputRepresentation(int index) override {
   6806     return index == 0
   6807         ? Representation::Tagged()
   6808         : Representation::Integer32();
   6809   }
   6810 
   6811   HValue* context() const { return OperandAt(0); }
   6812   HValue* value() const { return OperandAt(1); }
   6813 
   6814   bool DataEquals(HValue* other) override { return true; }
   6815 
   6816   DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
   6817 
   6818  private:
   6819   HStringCharFromCode(HValue* context, HValue* char_code)
   6820       : HTemplateInstruction<2>(HType::String()) {
   6821     SetOperandAt(0, context);
   6822     SetOperandAt(1, char_code);
   6823     set_representation(Representation::Tagged());
   6824     SetFlag(kUseGVN);
   6825     SetChangesFlag(kNewSpacePromotion);
   6826   }
   6827 
   6828   bool IsDeletable() const override {
   6829     return !value()->ToNumberCanBeObserved();
   6830   }
   6831 };
   6832 
   6833 
   6834 class HTypeof final : public HTemplateInstruction<2> {
   6835  public:
   6836   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HTypeof, HValue*);
   6837 
   6838   HValue* context() const { return OperandAt(0); }
   6839   HValue* value() const { return OperandAt(1); }
   6840 
   6841   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6842 
   6843   Representation RequiredInputRepresentation(int index) override {
   6844     return Representation::Tagged();
   6845   }
   6846 
   6847   DECLARE_CONCRETE_INSTRUCTION(Typeof)
   6848 
   6849  private:
   6850   explicit HTypeof(HValue* context, HValue* value) {
   6851     SetOperandAt(0, context);
   6852     SetOperandAt(1, value);
   6853     set_representation(Representation::Tagged());
   6854   }
   6855 
   6856   bool IsDeletable() const override { return true; }
   6857 };
   6858 
   6859 
   6860 class HTrapAllocationMemento final : public HTemplateInstruction<1> {
   6861  public:
   6862   DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
   6863 
   6864   Representation RequiredInputRepresentation(int index) override {
   6865     return Representation::Tagged();
   6866   }
   6867 
   6868   HValue* object() { return OperandAt(0); }
   6869 
   6870   DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
   6871 
   6872  private:
   6873   explicit HTrapAllocationMemento(HValue* obj) {
   6874     SetOperandAt(0, obj);
   6875   }
   6876 };
   6877 
   6878 
   6879 class HMaybeGrowElements final : public HTemplateInstruction<5> {
   6880  public:
   6881   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(HMaybeGrowElements, HValue*,
   6882                                               HValue*, HValue*, HValue*, bool,
   6883                                               ElementsKind);
   6884 
   6885   Representation RequiredInputRepresentation(int index) override {
   6886     if (index < 3) {
   6887       return Representation::Tagged();
   6888     }
   6889     DCHECK(index == 3 || index == 4);
   6890     return Representation::Integer32();
   6891   }
   6892 
   6893   HValue* context() const { return OperandAt(0); }
   6894   HValue* object() const { return OperandAt(1); }
   6895   HValue* elements() const { return OperandAt(2); }
   6896   HValue* key() const { return OperandAt(3); }
   6897   HValue* current_capacity() const { return OperandAt(4); }
   6898 
   6899   bool is_js_array() const { return is_js_array_; }
   6900   ElementsKind kind() const { return kind_; }
   6901 
   6902   DECLARE_CONCRETE_INSTRUCTION(MaybeGrowElements)
   6903 
   6904  protected:
   6905   bool DataEquals(HValue* other) override { return true; }
   6906 
   6907  private:
   6908   explicit HMaybeGrowElements(HValue* context, HValue* object, HValue* elements,
   6909                               HValue* key, HValue* current_capacity,
   6910                               bool is_js_array, ElementsKind kind) {
   6911     is_js_array_ = is_js_array;
   6912     kind_ = kind;
   6913 
   6914     SetOperandAt(0, context);
   6915     SetOperandAt(1, object);
   6916     SetOperandAt(2, elements);
   6917     SetOperandAt(3, key);
   6918     SetOperandAt(4, current_capacity);
   6919 
   6920     SetFlag(kUseGVN);
   6921     SetChangesFlag(kElementsPointer);
   6922     SetChangesFlag(kNewSpacePromotion);
   6923     set_representation(Representation::Tagged());
   6924   }
   6925 
   6926   bool is_js_array_;
   6927   ElementsKind kind_;
   6928 };
   6929 
   6930 
   6931 class HSeqStringGetChar final : public HTemplateInstruction<2> {
   6932  public:
   6933   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   6934                            String::Encoding encoding, HValue* string,
   6935                            HValue* index);
   6936 
   6937   Representation RequiredInputRepresentation(int index) override {
   6938     return (index == 0) ? Representation::Tagged()
   6939                         : Representation::Integer32();
   6940   }
   6941 
   6942   String::Encoding encoding() const { return encoding_; }
   6943   HValue* string() const { return OperandAt(0); }
   6944   HValue* index() const { return OperandAt(1); }
   6945 
   6946   DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)
   6947 
   6948  protected:
   6949   bool DataEquals(HValue* other) override {
   6950     return encoding() == HSeqStringGetChar::cast(other)->encoding();
   6951   }
   6952 
   6953   Range* InferRange(Zone* zone) override {
   6954     if (encoding() == String::ONE_BYTE_ENCODING) {
   6955       return new(zone) Range(0, String::kMaxOneByteCharCode);
   6956     } else {
   6957       DCHECK_EQ(String::TWO_BYTE_ENCODING, encoding());
   6958       return  new(zone) Range(0, String::kMaxUtf16CodeUnit);
   6959     }
   6960   }
   6961 
   6962  private:
   6963   HSeqStringGetChar(String::Encoding encoding,
   6964                     HValue* string,
   6965                     HValue* index) : encoding_(encoding) {
   6966     SetOperandAt(0, string);
   6967     SetOperandAt(1, index);
   6968     set_representation(Representation::Integer32());
   6969     SetFlag(kUseGVN);
   6970     SetDependsOnFlag(kStringChars);
   6971   }
   6972 
   6973   bool IsDeletable() const override { return true; }
   6974 
   6975   String::Encoding encoding_;
   6976 };
   6977 
   6978 
   6979 class HSeqStringSetChar final : public HTemplateInstruction<4> {
   6980  public:
   6981   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(
   6982       HSeqStringSetChar, String::Encoding,
   6983       HValue*, HValue*, HValue*);
   6984 
   6985   String::Encoding encoding() { return encoding_; }
   6986   HValue* context() { return OperandAt(0); }
   6987   HValue* string() { return OperandAt(1); }
   6988   HValue* index() { return OperandAt(2); }
   6989   HValue* value() { return OperandAt(3); }
   6990 
   6991   Representation RequiredInputRepresentation(int index) override {
   6992     return (index <= 1) ? Representation::Tagged()
   6993                         : Representation::Integer32();
   6994   }
   6995 
   6996   DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
   6997 
   6998  private:
   6999   HSeqStringSetChar(HValue* context,
   7000                     String::Encoding encoding,
   7001                     HValue* string,
   7002                     HValue* index,
   7003                     HValue* value) : encoding_(encoding) {
   7004     SetOperandAt(0, context);
   7005     SetOperandAt(1, string);
   7006     SetOperandAt(2, index);
   7007     SetOperandAt(3, value);
   7008     set_representation(Representation::Tagged());
   7009     SetChangesFlag(kStringChars);
   7010   }
   7011 
   7012   String::Encoding encoding_;
   7013 };
   7014 
   7015 
   7016 class HCheckMapValue final : public HTemplateInstruction<2> {
   7017  public:
   7018   DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);
   7019 
   7020   Representation RequiredInputRepresentation(int index) override {
   7021     return Representation::Tagged();
   7022   }
   7023 
   7024   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   7025 
   7026   HType CalculateInferredType() override {
   7027     if (value()->type().IsHeapObject()) return value()->type();
   7028     return HType::HeapObject();
   7029   }
   7030 
   7031   HValue* value() const { return OperandAt(0); }
   7032   HValue* map() const { return OperandAt(1); }
   7033 
   7034   HValue* Canonicalize() override;
   7035 
   7036   DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
   7037 
   7038  protected:
   7039   int RedefinedOperandIndex() override { return 0; }
   7040 
   7041   bool DataEquals(HValue* other) override { return true; }
   7042 
   7043  private:
   7044   HCheckMapValue(HValue* value, HValue* map)
   7045       : HTemplateInstruction<2>(HType::HeapObject()) {
   7046     SetOperandAt(0, value);
   7047     SetOperandAt(1, map);
   7048     set_representation(Representation::Tagged());
   7049     SetFlag(kUseGVN);
   7050     SetDependsOnFlag(kMaps);
   7051     SetDependsOnFlag(kElementsKind);
   7052   }
   7053 };
   7054 
   7055 
   7056 class HForInPrepareMap final : public HTemplateInstruction<2> {
   7057  public:
   7058   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HForInPrepareMap, HValue*);
   7059 
   7060   Representation RequiredInputRepresentation(int index) override {
   7061     return Representation::Tagged();
   7062   }
   7063 
   7064   HValue* context() const { return OperandAt(0); }
   7065   HValue* enumerable() const { return OperandAt(1); }
   7066 
   7067   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   7068 
   7069   HType CalculateInferredType() override { return HType::Tagged(); }
   7070 
   7071   DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
   7072 
   7073  private:
   7074   HForInPrepareMap(HValue* context,
   7075                    HValue* object) {
   7076     SetOperandAt(0, context);
   7077     SetOperandAt(1, object);
   7078     set_representation(Representation::Tagged());
   7079     SetAllSideEffects();
   7080   }
   7081 };
   7082 
   7083 
   7084 class HForInCacheArray final : public HTemplateInstruction<2> {
   7085  public:
   7086   DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
   7087 
   7088   Representation RequiredInputRepresentation(int index) override {
   7089     return Representation::Tagged();
   7090   }
   7091 
   7092   HValue* enumerable() const { return OperandAt(0); }
   7093   HValue* map() const { return OperandAt(1); }
   7094   int idx() const { return idx_; }
   7095 
   7096   HForInCacheArray* index_cache() {
   7097     return index_cache_;
   7098   }
   7099 
   7100   void set_index_cache(HForInCacheArray* index_cache) {
   7101     index_cache_ = index_cache;
   7102   }
   7103 
   7104   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   7105 
   7106   HType CalculateInferredType() override { return HType::Tagged(); }
   7107 
   7108   DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
   7109 
   7110  private:
   7111   HForInCacheArray(HValue* enumerable,
   7112                    HValue* keys,
   7113                    int idx) : idx_(idx) {
   7114     SetOperandAt(0, enumerable);
   7115     SetOperandAt(1, keys);
   7116     set_representation(Representation::Tagged());
   7117   }
   7118 
   7119   int idx_;
   7120   HForInCacheArray* index_cache_;
   7121 };
   7122 
   7123 
   7124 class HLoadFieldByIndex final : public HTemplateInstruction<2> {
   7125  public:
   7126   DECLARE_INSTRUCTION_FACTORY_P2(HLoadFieldByIndex, HValue*, HValue*);
   7127 
   7128   HLoadFieldByIndex(HValue* object,
   7129                     HValue* index) {
   7130     SetOperandAt(0, object);
   7131     SetOperandAt(1, index);
   7132     SetChangesFlag(kNewSpacePromotion);
   7133     set_representation(Representation::Tagged());
   7134   }
   7135 
   7136   Representation RequiredInputRepresentation(int index) override {
   7137     if (index == 1) {
   7138       return Representation::Smi();
   7139     } else {
   7140       return Representation::Tagged();
   7141     }
   7142   }
   7143 
   7144   HValue* object() const { return OperandAt(0); }
   7145   HValue* index() const { return OperandAt(1); }
   7146 
   7147   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   7148 
   7149   HType CalculateInferredType() override { return HType::Tagged(); }
   7150 
   7151   DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
   7152 
   7153  private:
   7154   bool IsDeletable() const override { return true; }
   7155 };
   7156 
   7157 #undef DECLARE_INSTRUCTION
   7158 #undef DECLARE_CONCRETE_INSTRUCTION
   7159 
   7160 }  // namespace internal
   7161 }  // namespace v8
   7162 
   7163 #endif  // V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_
   7164