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