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<TypeFeedbackVector>);
   1948 
   1949   HValue* context() { return OperandAt(0); }
   1950   Handle<FixedArray> pairs() const { return pairs_; }
   1951   int flags() const { return flags_; }
   1952   Handle<TypeFeedbackVector> feedback_vector() const {
   1953     return feedback_vector_;
   1954   }
   1955 
   1956   DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
   1957 
   1958   Representation RequiredInputRepresentation(int index) override {
   1959     return Representation::Tagged();
   1960   }
   1961 
   1962  private:
   1963   HDeclareGlobals(HValue* context, Handle<FixedArray> pairs, int flags,
   1964                   Handle<TypeFeedbackVector> feedback_vector)
   1965       : HUnaryOperation(context),
   1966         pairs_(pairs),
   1967         feedback_vector_(feedback_vector),
   1968         flags_(flags) {
   1969     set_representation(Representation::Tagged());
   1970     SetAllSideEffects();
   1971   }
   1972 
   1973   Handle<FixedArray> pairs_;
   1974   Handle<TypeFeedbackVector> feedback_vector_;
   1975   int flags_;
   1976 };
   1977 
   1978 
   1979 template <int V>
   1980 class HCall : public HTemplateInstruction<V> {
   1981  public:
   1982   // The argument count includes the receiver.
   1983   explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
   1984     this->set_representation(Representation::Tagged());
   1985     this->SetAllSideEffects();
   1986   }
   1987 
   1988   virtual int argument_count() const {
   1989     return argument_count_;
   1990   }
   1991 
   1992   int argument_delta() const override { return -argument_count(); }
   1993 
   1994  private:
   1995   int argument_count_;
   1996 };
   1997 
   1998 
   1999 class HUnaryCall : public HCall<1> {
   2000  public:
   2001   HUnaryCall(HValue* value, int argument_count)
   2002       : HCall<1>(argument_count) {
   2003     SetOperandAt(0, value);
   2004   }
   2005 
   2006   Representation RequiredInputRepresentation(int index) final {
   2007     return Representation::Tagged();
   2008   }
   2009 
   2010   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2011 
   2012   HValue* value() const { return OperandAt(0); }
   2013 };
   2014 
   2015 
   2016 class HBinaryCall : public HCall<2> {
   2017  public:
   2018   HBinaryCall(HValue* first, HValue* second, int argument_count)
   2019       : HCall<2>(argument_count) {
   2020     SetOperandAt(0, first);
   2021     SetOperandAt(1, second);
   2022   }
   2023 
   2024   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2025 
   2026   Representation RequiredInputRepresentation(int index) final {
   2027     return Representation::Tagged();
   2028   }
   2029 
   2030   HValue* first() const { return OperandAt(0); }
   2031   HValue* second() const { return OperandAt(1); }
   2032 };
   2033 
   2034 
   2035 class HCallWithDescriptor final : public HInstruction {
   2036  public:
   2037   static HCallWithDescriptor* New(
   2038       Isolate* isolate, Zone* zone, HValue* context, HValue* target,
   2039       int argument_count, CallInterfaceDescriptor descriptor,
   2040       const Vector<HValue*>& operands,
   2041       TailCallMode syntactic_tail_call_mode = TailCallMode::kDisallow,
   2042       TailCallMode tail_call_mode = TailCallMode::kDisallow) {
   2043     HCallWithDescriptor* res = new (zone) HCallWithDescriptor(
   2044         Code::STUB, context, target, argument_count, descriptor, operands,
   2045         syntactic_tail_call_mode, tail_call_mode, zone);
   2046     return res;
   2047   }
   2048 
   2049   static HCallWithDescriptor* New(
   2050       Isolate* isolate, Zone* zone, HValue* context, Code::Kind kind,
   2051       HValue* target, int argument_count, CallInterfaceDescriptor descriptor,
   2052       const Vector<HValue*>& operands,
   2053       TailCallMode syntactic_tail_call_mode = TailCallMode::kDisallow,
   2054       TailCallMode tail_call_mode = TailCallMode::kDisallow) {
   2055     HCallWithDescriptor* res = new (zone) HCallWithDescriptor(
   2056         kind, context, target, argument_count, descriptor, operands,
   2057         syntactic_tail_call_mode, tail_call_mode, zone);
   2058     return res;
   2059   }
   2060 
   2061   int OperandCount() const final { return values_.length(); }
   2062   HValue* OperandAt(int index) const final { return values_[index]; }
   2063 
   2064   Representation RequiredInputRepresentation(int index) final {
   2065     if (index == 0 || index == 1) {
   2066       // Target + context
   2067       return Representation::Tagged();
   2068     } else {
   2069       int par_index = index - 2;
   2070       DCHECK(par_index < GetParameterCount());
   2071       return RepresentationFromMachineType(
   2072           descriptor_.GetParameterType(par_index));
   2073     }
   2074   }
   2075 
   2076   DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor)
   2077 
   2078   // Defines whether this instruction corresponds to a JS call at tail position.
   2079   TailCallMode syntactic_tail_call_mode() const {
   2080     return SyntacticTailCallModeField::decode(bit_field_);
   2081   }
   2082 
   2083   // Defines whether this call should be generated as a tail call.
   2084   TailCallMode tail_call_mode() const {
   2085     return TailCallModeField::decode(bit_field_);
   2086   }
   2087   bool IsTailCall() const { return tail_call_mode() == TailCallMode::kAllow; }
   2088 
   2089   Code::Kind kind() const { return KindField::decode(bit_field_); }
   2090 
   2091   virtual int argument_count() const {
   2092     return argument_count_;
   2093   }
   2094 
   2095   int argument_delta() const override { return -argument_count_; }
   2096 
   2097   CallInterfaceDescriptor descriptor() const { return descriptor_; }
   2098 
   2099   HValue* target() { return OperandAt(0); }
   2100   HValue* context() { return OperandAt(1); }
   2101   HValue* parameter(int index) {
   2102     DCHECK_LT(index, GetParameterCount());
   2103     return OperandAt(index + 2);
   2104   }
   2105 
   2106   HValue* Canonicalize() override;
   2107 
   2108   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2109 
   2110  private:
   2111   // The argument count includes the receiver.
   2112   HCallWithDescriptor(Code::Kind kind, HValue* context, HValue* target,
   2113                       int argument_count, CallInterfaceDescriptor descriptor,
   2114                       const Vector<HValue*>& operands,
   2115                       TailCallMode syntactic_tail_call_mode,
   2116                       TailCallMode tail_call_mode, Zone* zone)
   2117       : descriptor_(descriptor),
   2118         values_(GetParameterCount() + 2, zone),  // +2 for context and target.
   2119         argument_count_(argument_count),
   2120         bit_field_(
   2121             TailCallModeField::encode(tail_call_mode) |
   2122             SyntacticTailCallModeField::encode(syntactic_tail_call_mode) |
   2123             KindField::encode(kind)) {
   2124     DCHECK_EQ(operands.length(), GetParameterCount());
   2125     // We can only tail call without any stack arguments.
   2126     DCHECK(tail_call_mode != TailCallMode::kAllow || argument_count == 0);
   2127     AddOperand(target, zone);
   2128     AddOperand(context, zone);
   2129     for (int i = 0; i < operands.length(); i++) {
   2130       AddOperand(operands[i], zone);
   2131     }
   2132     this->set_representation(Representation::Tagged());
   2133     this->SetAllSideEffects();
   2134   }
   2135 
   2136   void AddOperand(HValue* v, Zone* zone) {
   2137     values_.Add(NULL, zone);
   2138     SetOperandAt(values_.length() - 1, v);
   2139   }
   2140 
   2141   int GetParameterCount() const { return descriptor_.GetParameterCount(); }
   2142 
   2143   void InternalSetOperandAt(int index, HValue* value) final {
   2144     values_[index] = value;
   2145   }
   2146 
   2147   CallInterfaceDescriptor descriptor_;
   2148   ZoneList<HValue*> values_;
   2149   int argument_count_;
   2150   class TailCallModeField : public BitField<TailCallMode, 0, 1> {};
   2151   class SyntacticTailCallModeField
   2152       : public BitField<TailCallMode, TailCallModeField::kNext, 1> {};
   2153   class KindField
   2154       : public BitField<Code::Kind, SyntacticTailCallModeField::kNext, 5> {};
   2155   uint32_t bit_field_;
   2156 };
   2157 
   2158 
   2159 class HInvokeFunction final : public HBinaryCall {
   2160  public:
   2161   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HInvokeFunction, HValue*,
   2162                                               Handle<JSFunction>, int,
   2163                                               TailCallMode, TailCallMode);
   2164 
   2165   HValue* context() { return first(); }
   2166   HValue* function() { return second(); }
   2167   Handle<JSFunction> known_function() { return known_function_; }
   2168   int formal_parameter_count() const { return formal_parameter_count_; }
   2169 
   2170   bool HasStackCheck() final { return HasStackCheckField::decode(bit_field_); }
   2171 
   2172   // Defines whether this instruction corresponds to a JS call at tail position.
   2173   TailCallMode syntactic_tail_call_mode() const {
   2174     return SyntacticTailCallModeField::decode(bit_field_);
   2175   }
   2176 
   2177   // Defines whether this call should be generated as a tail call.
   2178   TailCallMode tail_call_mode() const {
   2179     return TailCallModeField::decode(bit_field_);
   2180   }
   2181 
   2182   DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
   2183 
   2184   std::ostream& PrintTo(std::ostream& os) const override;      // NOLINT
   2185   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2186 
   2187  private:
   2188   void set_has_stack_check(bool has_stack_check) {
   2189     bit_field_ = HasStackCheckField::update(bit_field_, has_stack_check);
   2190   }
   2191 
   2192   HInvokeFunction(HValue* context, HValue* function,
   2193                   Handle<JSFunction> known_function, int argument_count,
   2194                   TailCallMode syntactic_tail_call_mode,
   2195                   TailCallMode tail_call_mode)
   2196       : HBinaryCall(context, function, argument_count),
   2197         known_function_(known_function),
   2198         bit_field_(
   2199             TailCallModeField::encode(tail_call_mode) |
   2200             SyntacticTailCallModeField::encode(syntactic_tail_call_mode)) {
   2201     DCHECK(tail_call_mode != TailCallMode::kAllow ||
   2202            syntactic_tail_call_mode == TailCallMode::kAllow);
   2203     formal_parameter_count_ =
   2204         known_function.is_null()
   2205             ? 0
   2206             : known_function->shared()->internal_formal_parameter_count();
   2207     set_has_stack_check(
   2208         !known_function.is_null() &&
   2209         (known_function->code()->kind() == Code::FUNCTION ||
   2210          known_function->code()->kind() == Code::OPTIMIZED_FUNCTION));
   2211   }
   2212 
   2213   Handle<JSFunction> known_function_;
   2214   int formal_parameter_count_;
   2215 
   2216   class HasStackCheckField : public BitField<bool, 0, 1> {};
   2217   class TailCallModeField
   2218       : public BitField<TailCallMode, HasStackCheckField::kNext, 1> {};
   2219   class SyntacticTailCallModeField
   2220       : public BitField<TailCallMode, TailCallModeField::kNext, 1> {};
   2221   uint32_t bit_field_;
   2222 };
   2223 
   2224 
   2225 class HCallNewArray final : public HBinaryCall {
   2226  public:
   2227   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HCallNewArray, HValue*, int,
   2228                                               ElementsKind,
   2229                                               Handle<AllocationSite>);
   2230 
   2231   HValue* context() { return first(); }
   2232   HValue* constructor() { return second(); }
   2233 
   2234   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2235 
   2236   ElementsKind elements_kind() const { return elements_kind_; }
   2237   Handle<AllocationSite> site() const { return site_; }
   2238 
   2239   DECLARE_CONCRETE_INSTRUCTION(CallNewArray)
   2240 
   2241  private:
   2242   HCallNewArray(HValue* context, HValue* constructor, int argument_count,
   2243                 ElementsKind elements_kind, Handle<AllocationSite> site)
   2244       : HBinaryCall(context, constructor, argument_count),
   2245         elements_kind_(elements_kind),
   2246         site_(site) {}
   2247 
   2248   ElementsKind elements_kind_;
   2249   Handle<AllocationSite> site_;
   2250 };
   2251 
   2252 
   2253 class HCallRuntime final : public HCall<1> {
   2254  public:
   2255   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallRuntime,
   2256                                               const Runtime::Function*, int);
   2257 
   2258   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2259 
   2260   HValue* context() { return OperandAt(0); }
   2261   const Runtime::Function* function() const { return c_function_; }
   2262   SaveFPRegsMode save_doubles() const { return save_doubles_; }
   2263   void set_save_doubles(SaveFPRegsMode save_doubles) {
   2264     save_doubles_ = save_doubles;
   2265   }
   2266 
   2267   Representation RequiredInputRepresentation(int index) override {
   2268     return Representation::Tagged();
   2269   }
   2270 
   2271   DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
   2272 
   2273  private:
   2274   HCallRuntime(HValue* context, const Runtime::Function* c_function,
   2275                int argument_count)
   2276       : HCall<1>(argument_count),
   2277         c_function_(c_function),
   2278         save_doubles_(kDontSaveFPRegs) {
   2279     SetOperandAt(0, context);
   2280   }
   2281 
   2282   const Runtime::Function* c_function_;
   2283   SaveFPRegsMode save_doubles_;
   2284 };
   2285 
   2286 
   2287 class HUnaryMathOperation final : public HTemplateInstruction<2> {
   2288  public:
   2289   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   2290                            HValue* value, BuiltinFunctionId op);
   2291 
   2292   HValue* context() const { return OperandAt(0); }
   2293   HValue* value() const { return OperandAt(1); }
   2294 
   2295   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2296 
   2297   Representation RequiredInputRepresentation(int index) override {
   2298     if (index == 0) {
   2299       return Representation::Tagged();
   2300     } else {
   2301       switch (op_) {
   2302         case kMathCos:
   2303         case kMathFloor:
   2304         case kMathRound:
   2305         case kMathFround:
   2306         case kMathSin:
   2307         case kMathSqrt:
   2308         case kMathPowHalf:
   2309         case kMathLog:
   2310         case kMathExp:
   2311           return Representation::Double();
   2312         case kMathAbs:
   2313           return representation();
   2314         case kMathClz32:
   2315           return Representation::Integer32();
   2316         default:
   2317           UNREACHABLE();
   2318           return Representation::None();
   2319       }
   2320     }
   2321   }
   2322 
   2323   Range* InferRange(Zone* zone) override;
   2324 
   2325   HValue* Canonicalize() override;
   2326   Representation RepresentationFromUses() override;
   2327   Representation RepresentationFromInputs() override;
   2328 
   2329   BuiltinFunctionId op() const { return op_; }
   2330   const char* OpName() const;
   2331 
   2332   DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
   2333 
   2334  protected:
   2335   bool DataEquals(HValue* other) override {
   2336     HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
   2337     return op_ == b->op();
   2338   }
   2339 
   2340  private:
   2341   // Indicates if we support a double (and int32) output for Math.floor and
   2342   // Math.round.
   2343   bool SupportsFlexibleFloorAndRound() const {
   2344 #if V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_PPC
   2345     return true;
   2346 #elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
   2347     return CpuFeatures::IsSupported(SSE4_1);
   2348 #else
   2349     return false;
   2350 #endif
   2351   }
   2352   HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
   2353       : HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
   2354     SetOperandAt(0, context);
   2355     SetOperandAt(1, value);
   2356     switch (op) {
   2357       case kMathFloor:
   2358       case kMathRound:
   2359         if (SupportsFlexibleFloorAndRound()) {
   2360           SetFlag(kFlexibleRepresentation);
   2361         } else {
   2362           set_representation(Representation::Integer32());
   2363         }
   2364         break;
   2365       case kMathClz32:
   2366         set_representation(Representation::Integer32());
   2367         break;
   2368       case kMathAbs:
   2369         // Not setting representation here: it is None intentionally.
   2370         SetFlag(kFlexibleRepresentation);
   2371         // TODO(svenpanne) This flag is actually only needed if representation()
   2372         // is tagged, and not when it is an unboxed double or unboxed integer.
   2373         SetChangesFlag(kNewSpacePromotion);
   2374         break;
   2375       case kMathCos:
   2376       case kMathFround:
   2377       case kMathLog:
   2378       case kMathExp:
   2379       case kMathSin:
   2380       case kMathSqrt:
   2381       case kMathPowHalf:
   2382         set_representation(Representation::Double());
   2383         break;
   2384       default:
   2385         UNREACHABLE();
   2386     }
   2387     SetFlag(kUseGVN);
   2388     SetFlag(kTruncatingToNumber);
   2389   }
   2390 
   2391   bool IsDeletable() const override {
   2392     // TODO(crankshaft): This should be true, however the semantics of this
   2393     // instruction also include the ToNumber conversion that is mentioned in the
   2394     // spec, which is of course observable.
   2395     return false;
   2396   }
   2397 
   2398   HValue* SimplifiedDividendForMathFloorOfDiv(HDiv* hdiv);
   2399   HValue* SimplifiedDivisorForMathFloorOfDiv(HDiv* hdiv);
   2400 
   2401   BuiltinFunctionId op_;
   2402 };
   2403 
   2404 
   2405 class HLoadRoot final : public HTemplateInstruction<0> {
   2406  public:
   2407   DECLARE_INSTRUCTION_FACTORY_P1(HLoadRoot, Heap::RootListIndex);
   2408   DECLARE_INSTRUCTION_FACTORY_P2(HLoadRoot, Heap::RootListIndex, HType);
   2409 
   2410   Representation RequiredInputRepresentation(int index) override {
   2411     return Representation::None();
   2412   }
   2413 
   2414   Heap::RootListIndex index() const { return index_; }
   2415 
   2416   DECLARE_CONCRETE_INSTRUCTION(LoadRoot)
   2417 
   2418  protected:
   2419   bool DataEquals(HValue* other) override {
   2420     HLoadRoot* b = HLoadRoot::cast(other);
   2421     return index_ == b->index_;
   2422   }
   2423 
   2424  private:
   2425   explicit HLoadRoot(Heap::RootListIndex index, HType type = HType::Tagged())
   2426       : HTemplateInstruction<0>(type), index_(index) {
   2427     SetFlag(kUseGVN);
   2428     // TODO(bmeurer): We'll need kDependsOnRoots once we add the
   2429     // corresponding HStoreRoot instruction.
   2430     SetDependsOnFlag(kCalls);
   2431     set_representation(Representation::Tagged());
   2432   }
   2433 
   2434   bool IsDeletable() const override { return true; }
   2435 
   2436   const Heap::RootListIndex index_;
   2437 };
   2438 
   2439 
   2440 class HCheckMaps final : public HTemplateInstruction<2> {
   2441  public:
   2442   static HCheckMaps* New(Isolate* isolate, Zone* zone, HValue* context,
   2443                          HValue* value, Handle<Map> map,
   2444                          HValue* typecheck = NULL) {
   2445     return new(zone) HCheckMaps(value, new(zone) UniqueSet<Map>(
   2446             Unique<Map>::CreateImmovable(map), zone), typecheck);
   2447   }
   2448   static HCheckMaps* New(Isolate* isolate, Zone* zone, HValue* context,
   2449                          HValue* value, SmallMapList* map_list,
   2450                          HValue* typecheck = NULL) {
   2451     UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone);
   2452     for (int i = 0; i < map_list->length(); ++i) {
   2453       maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone);
   2454     }
   2455     return new(zone) HCheckMaps(value, maps, typecheck);
   2456   }
   2457 
   2458   bool IsStabilityCheck() const {
   2459     return IsStabilityCheckField::decode(bit_field_);
   2460   }
   2461   void MarkAsStabilityCheck() {
   2462     bit_field_ = MapsAreStableField::encode(true) |
   2463                  HasMigrationTargetField::encode(false) |
   2464                  IsStabilityCheckField::encode(true);
   2465     ClearChangesFlag(kNewSpacePromotion);
   2466     ClearDependsOnFlag(kElementsKind);
   2467     ClearDependsOnFlag(kMaps);
   2468   }
   2469 
   2470   bool HasEscapingOperandAt(int index) override { return false; }
   2471   Representation RequiredInputRepresentation(int index) override {
   2472     return Representation::Tagged();
   2473   }
   2474 
   2475   HType CalculateInferredType() override {
   2476     if (value()->type().IsHeapObject()) return value()->type();
   2477     return HType::HeapObject();
   2478   }
   2479 
   2480   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2481 
   2482   HValue* value() const { return OperandAt(0); }
   2483   HValue* typecheck() const { return OperandAt(1); }
   2484 
   2485   const UniqueSet<Map>* maps() const { return maps_; }
   2486   void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; }
   2487 
   2488   bool maps_are_stable() const {
   2489     return MapsAreStableField::decode(bit_field_);
   2490   }
   2491 
   2492   bool HasMigrationTarget() const {
   2493     return HasMigrationTargetField::decode(bit_field_);
   2494   }
   2495 
   2496   HValue* Canonicalize() override;
   2497 
   2498   static HCheckMaps* CreateAndInsertAfter(Zone* zone,
   2499                                           HValue* value,
   2500                                           Unique<Map> map,
   2501                                           bool map_is_stable,
   2502                                           HInstruction* instr) {
   2503     return instr->Append(new(zone) HCheckMaps(
   2504             value, new(zone) UniqueSet<Map>(map, zone), map_is_stable));
   2505   }
   2506 
   2507   static HCheckMaps* CreateAndInsertBefore(Zone* zone,
   2508                                            HValue* value,
   2509                                            const UniqueSet<Map>* maps,
   2510                                            bool maps_are_stable,
   2511                                            HInstruction* instr) {
   2512     return instr->Prepend(new(zone) HCheckMaps(value, maps, maps_are_stable));
   2513   }
   2514 
   2515   DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
   2516 
   2517  protected:
   2518   bool DataEquals(HValue* other) override {
   2519     return this->maps()->Equals(HCheckMaps::cast(other)->maps());
   2520   }
   2521 
   2522   int RedefinedOperandIndex() override { return 0; }
   2523 
   2524  private:
   2525   HCheckMaps(HValue* value, const UniqueSet<Map>* maps, bool maps_are_stable)
   2526       : HTemplateInstruction<2>(HType::HeapObject()),
   2527         maps_(maps),
   2528         bit_field_(HasMigrationTargetField::encode(false) |
   2529                    IsStabilityCheckField::encode(false) |
   2530                    MapsAreStableField::encode(maps_are_stable)) {
   2531     DCHECK_NE(0, maps->size());
   2532     SetOperandAt(0, value);
   2533     // Use the object value for the dependency.
   2534     SetOperandAt(1, value);
   2535     set_representation(Representation::Tagged());
   2536     SetFlag(kUseGVN);
   2537     SetDependsOnFlag(kMaps);
   2538     SetDependsOnFlag(kElementsKind);
   2539   }
   2540 
   2541   HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck)
   2542       : HTemplateInstruction<2>(HType::HeapObject()),
   2543         maps_(maps),
   2544         bit_field_(HasMigrationTargetField::encode(false) |
   2545                    IsStabilityCheckField::encode(false) |
   2546                    MapsAreStableField::encode(true)) {
   2547     DCHECK_NE(0, maps->size());
   2548     SetOperandAt(0, value);
   2549     // Use the object value for the dependency if NULL is passed.
   2550     SetOperandAt(1, typecheck ? typecheck : value);
   2551     set_representation(Representation::Tagged());
   2552     SetFlag(kUseGVN);
   2553     SetDependsOnFlag(kMaps);
   2554     SetDependsOnFlag(kElementsKind);
   2555     for (int i = 0; i < maps->size(); ++i) {
   2556       Handle<Map> map = maps->at(i).handle();
   2557       if (map->is_migration_target()) {
   2558         bit_field_ = HasMigrationTargetField::update(bit_field_, true);
   2559       }
   2560       if (!map->is_stable()) {
   2561         bit_field_ = MapsAreStableField::update(bit_field_, false);
   2562       }
   2563     }
   2564     if (HasMigrationTarget()) SetChangesFlag(kNewSpacePromotion);
   2565   }
   2566 
   2567   class HasMigrationTargetField : public BitField<bool, 0, 1> {};
   2568   class IsStabilityCheckField : public BitField<bool, 1, 1> {};
   2569   class MapsAreStableField : public BitField<bool, 2, 1> {};
   2570 
   2571   const UniqueSet<Map>* maps_;
   2572   uint32_t bit_field_;
   2573 };
   2574 
   2575 
   2576 class HCheckValue final : public HUnaryOperation {
   2577  public:
   2578   static HCheckValue* New(Isolate* isolate, Zone* zone, HValue* context,
   2579                           HValue* value, Handle<JSFunction> func) {
   2580     bool in_new_space = isolate->heap()->InNewSpace(*func);
   2581     // NOTE: We create an uninitialized Unique and initialize it later.
   2582     // This is because a JSFunction can move due to GC during graph creation.
   2583     Unique<JSFunction> target = Unique<JSFunction>::CreateUninitialized(func);
   2584     HCheckValue* check = new(zone) HCheckValue(value, target, in_new_space);
   2585     return check;
   2586   }
   2587   static HCheckValue* New(Isolate* isolate, Zone* zone, HValue* context,
   2588                           HValue* value, Unique<HeapObject> target,
   2589                           bool object_in_new_space) {
   2590     return new(zone) HCheckValue(value, target, object_in_new_space);
   2591   }
   2592 
   2593   void FinalizeUniqueness() override {
   2594     object_ = Unique<HeapObject>(object_.handle());
   2595   }
   2596 
   2597   Representation RequiredInputRepresentation(int index) override {
   2598     return Representation::Tagged();
   2599   }
   2600   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2601 
   2602   HValue* Canonicalize() override;
   2603 
   2604 #ifdef DEBUG
   2605   void Verify() override;
   2606 #endif
   2607 
   2608   Unique<HeapObject> object() const { return object_; }
   2609   bool object_in_new_space() const { return object_in_new_space_; }
   2610 
   2611   DECLARE_CONCRETE_INSTRUCTION(CheckValue)
   2612 
   2613  protected:
   2614   bool DataEquals(HValue* other) override {
   2615     HCheckValue* b = HCheckValue::cast(other);
   2616     return object_ == b->object_;
   2617   }
   2618 
   2619  private:
   2620   HCheckValue(HValue* value, Unique<HeapObject> object,
   2621                bool object_in_new_space)
   2622       : HUnaryOperation(value, value->type()),
   2623         object_(object),
   2624         object_in_new_space_(object_in_new_space) {
   2625     set_representation(Representation::Tagged());
   2626     SetFlag(kUseGVN);
   2627   }
   2628 
   2629   Unique<HeapObject> object_;
   2630   bool object_in_new_space_;
   2631 };
   2632 
   2633 
   2634 class HCheckInstanceType final : public HUnaryOperation {
   2635  public:
   2636   enum Check {
   2637     IS_JS_RECEIVER,
   2638     IS_JS_ARRAY,
   2639     IS_JS_FUNCTION,
   2640     IS_JS_DATE,
   2641     IS_STRING,
   2642     IS_INTERNALIZED_STRING,
   2643     LAST_INTERVAL_CHECK = IS_JS_DATE
   2644   };
   2645 
   2646   DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue*, Check);
   2647 
   2648   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2649 
   2650   Representation RequiredInputRepresentation(int index) override {
   2651     return Representation::Tagged();
   2652   }
   2653 
   2654   HType CalculateInferredType() override {
   2655     switch (check_) {
   2656       case IS_JS_RECEIVER: return HType::JSReceiver();
   2657       case IS_JS_ARRAY: return HType::JSArray();
   2658       case IS_JS_FUNCTION:
   2659         return HType::JSObject();
   2660       case IS_JS_DATE: return HType::JSObject();
   2661       case IS_STRING: return HType::String();
   2662       case IS_INTERNALIZED_STRING: return HType::String();
   2663     }
   2664     UNREACHABLE();
   2665     return HType::Tagged();
   2666   }
   2667 
   2668   HValue* Canonicalize() override;
   2669 
   2670   bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
   2671   void GetCheckInterval(InstanceType* first, InstanceType* last);
   2672   void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
   2673 
   2674   Check check() const { return check_; }
   2675 
   2676   DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
   2677 
   2678  protected:
   2679   // TODO(ager): It could be nice to allow the ommision of instance
   2680   // type checks if we have already performed an instance type check
   2681   // with a larger range.
   2682   bool DataEquals(HValue* other) override {
   2683     HCheckInstanceType* b = HCheckInstanceType::cast(other);
   2684     return check_ == b->check_;
   2685   }
   2686 
   2687   int RedefinedOperandIndex() override { return 0; }
   2688 
   2689  private:
   2690   const char* GetCheckName() const;
   2691 
   2692   HCheckInstanceType(HValue* value, Check check)
   2693       : HUnaryOperation(value, HType::HeapObject()), check_(check) {
   2694     set_representation(Representation::Tagged());
   2695     SetFlag(kUseGVN);
   2696   }
   2697 
   2698   const Check check_;
   2699 };
   2700 
   2701 
   2702 class HCheckSmi final : public HUnaryOperation {
   2703  public:
   2704   DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue*);
   2705 
   2706   Representation RequiredInputRepresentation(int index) override {
   2707     return Representation::Tagged();
   2708   }
   2709 
   2710   HValue* Canonicalize() override {
   2711     HType value_type = value()->type();
   2712     if (value_type.IsSmi()) {
   2713       return NULL;
   2714     }
   2715     return this;
   2716   }
   2717 
   2718   DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
   2719 
   2720  protected:
   2721   bool DataEquals(HValue* other) override { return true; }
   2722 
   2723  private:
   2724   explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
   2725     set_representation(Representation::Smi());
   2726     SetFlag(kUseGVN);
   2727   }
   2728 };
   2729 
   2730 
   2731 class HCheckArrayBufferNotNeutered final : public HUnaryOperation {
   2732  public:
   2733   DECLARE_INSTRUCTION_FACTORY_P1(HCheckArrayBufferNotNeutered, HValue*);
   2734 
   2735   bool HasEscapingOperandAt(int index) override { return false; }
   2736   Representation RequiredInputRepresentation(int index) override {
   2737     return Representation::Tagged();
   2738   }
   2739 
   2740   HType CalculateInferredType() override {
   2741     if (value()->type().IsHeapObject()) return value()->type();
   2742     return HType::HeapObject();
   2743   }
   2744 
   2745   DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered)
   2746 
   2747  protected:
   2748   bool DataEquals(HValue* other) override { return true; }
   2749   int RedefinedOperandIndex() override { return 0; }
   2750 
   2751  private:
   2752   explicit HCheckArrayBufferNotNeutered(HValue* value)
   2753       : HUnaryOperation(value) {
   2754     set_representation(Representation::Tagged());
   2755     SetFlag(kUseGVN);
   2756     SetDependsOnFlag(kCalls);
   2757   }
   2758 };
   2759 
   2760 
   2761 class HCheckHeapObject final : public HUnaryOperation {
   2762  public:
   2763   DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
   2764 
   2765   bool HasEscapingOperandAt(int index) override { return false; }
   2766   Representation RequiredInputRepresentation(int index) override {
   2767     return Representation::Tagged();
   2768   }
   2769 
   2770   HType CalculateInferredType() override {
   2771     if (value()->type().IsHeapObject()) return value()->type();
   2772     return HType::HeapObject();
   2773   }
   2774 
   2775 #ifdef DEBUG
   2776   void Verify() override;
   2777 #endif
   2778 
   2779   HValue* Canonicalize() override {
   2780     return value()->type().IsHeapObject() ? NULL : this;
   2781   }
   2782 
   2783   DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
   2784 
   2785  protected:
   2786   bool DataEquals(HValue* other) override { return true; }
   2787 
   2788  private:
   2789   explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) {
   2790     set_representation(Representation::Tagged());
   2791     SetFlag(kUseGVN);
   2792   }
   2793 };
   2794 
   2795 
   2796 class HPhi final : public HValue {
   2797  public:
   2798   HPhi(int merged_index, Zone* zone)
   2799       : inputs_(2, zone), merged_index_(merged_index) {
   2800     DCHECK(merged_index >= 0 || merged_index == kInvalidMergedIndex);
   2801     SetFlag(kFlexibleRepresentation);
   2802   }
   2803 
   2804   Representation RepresentationFromInputs() override;
   2805 
   2806   Range* InferRange(Zone* zone) override;
   2807   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   2808   Representation RequiredInputRepresentation(int index) override {
   2809     return representation();
   2810   }
   2811   Representation KnownOptimalRepresentation() override {
   2812     return representation();
   2813   }
   2814   HType CalculateInferredType() override;
   2815   int OperandCount() const override { return inputs_.length(); }
   2816   HValue* OperandAt(int index) const override { return inputs_[index]; }
   2817   HValue* GetRedundantReplacement();
   2818   void AddInput(HValue* value);
   2819   bool HasRealUses();
   2820 
   2821   bool IsReceiver() const { return merged_index_ == 0; }
   2822   bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
   2823 
   2824   SourcePosition position() const override;
   2825 
   2826   int merged_index() const { return merged_index_; }
   2827 
   2828   std::ostream& PrintTo(std::ostream& os) const override;  // NOLINT
   2829 
   2830 #ifdef DEBUG
   2831   void Verify() override;
   2832 #endif
   2833 
   2834   void InitRealUses(int id);
   2835   void AddNonPhiUsesFrom(HPhi* other);
   2836 
   2837   Representation representation_from_indirect_uses() const {
   2838     return representation_from_indirect_uses_;
   2839   }
   2840 
   2841   bool has_type_feedback_from_uses() const {
   2842     return has_type_feedback_from_uses_;
   2843   }
   2844 
   2845   int phi_id() { return phi_id_; }
   2846 
   2847   static HPhi* cast(HValue* value) {
   2848     DCHECK(value->IsPhi());
   2849     return reinterpret_cast<HPhi*>(value);
   2850   }
   2851   Opcode opcode() const override { return HValue::kPhi; }
   2852 
   2853   void SimplifyConstantInputs();
   2854 
   2855   // Marker value representing an invalid merge index.
   2856   static const int kInvalidMergedIndex = -1;
   2857 
   2858  protected:
   2859   void DeleteFromGraph() override;
   2860   void InternalSetOperandAt(int index, HValue* value) override {
   2861     inputs_[index] = value;
   2862   }
   2863 
   2864  private:
   2865   Representation representation_from_non_phi_uses() const {
   2866     return representation_from_non_phi_uses_;
   2867   }
   2868 
   2869   ZoneList<HValue*> inputs_;
   2870   int merged_index_ = 0;
   2871 
   2872   int phi_id_ = -1;
   2873 
   2874   Representation representation_from_indirect_uses_ = Representation::None();
   2875   Representation representation_from_non_phi_uses_ = Representation::None();
   2876   bool has_type_feedback_from_uses_ = false;
   2877 
   2878   bool IsDeletable() const override { return !IsReceiver(); }
   2879 };
   2880 
   2881 
   2882 // Common base class for HArgumentsObject and HCapturedObject.
   2883 class HDematerializedObject : public HInstruction {
   2884  public:
   2885   HDematerializedObject(int count, Zone* zone) : values_(count, zone) {}
   2886 
   2887   int OperandCount() const final { return values_.length(); }
   2888   HValue* OperandAt(int index) const final { return values_[index]; }
   2889 
   2890   bool HasEscapingOperandAt(int index) final { return false; }
   2891   Representation RequiredInputRepresentation(int index) final {
   2892     return Representation::None();
   2893   }
   2894 
   2895  protected:
   2896   void InternalSetOperandAt(int index, HValue* value) final {
   2897     values_[index] = value;
   2898   }
   2899 
   2900   // List of values tracked by this marker.
   2901   ZoneList<HValue*> values_;
   2902 };
   2903 
   2904 
   2905 class HArgumentsObject final : public HDematerializedObject {
   2906  public:
   2907   static HArgumentsObject* New(Isolate* isolate, Zone* zone, HValue* context,
   2908                                int count) {
   2909     return new(zone) HArgumentsObject(count, zone);
   2910   }
   2911 
   2912   // The values contain a list of all elements in the arguments object
   2913   // including the receiver object, which is skipped when materializing.
   2914   const ZoneList<HValue*>* arguments_values() const { return &values_; }
   2915   int arguments_count() const { return values_.length(); }
   2916 
   2917   void AddArgument(HValue* argument, Zone* zone) {
   2918     values_.Add(NULL, zone);  // Resize list.
   2919     SetOperandAt(values_.length() - 1, argument);
   2920   }
   2921 
   2922   DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
   2923 
   2924  private:
   2925   HArgumentsObject(int count, Zone* zone)
   2926       : HDematerializedObject(count, zone) {
   2927     set_representation(Representation::Tagged());
   2928     SetFlag(kIsArguments);
   2929   }
   2930 };
   2931 
   2932 
   2933 class HCapturedObject final : public HDematerializedObject {
   2934  public:
   2935   HCapturedObject(int length, int id, Zone* zone)
   2936       : HDematerializedObject(length, zone), capture_id_(id) {
   2937     set_representation(Representation::Tagged());
   2938     values_.AddBlock(NULL, length, zone);  // Resize list.
   2939   }
   2940 
   2941   // The values contain a list of all in-object properties inside the
   2942   // captured object and is index by field index. Properties in the
   2943   // properties or elements backing store are not tracked here.
   2944   const ZoneList<HValue*>* values() const { return &values_; }
   2945   int length() const { return values_.length(); }
   2946   int capture_id() const { return capture_id_; }
   2947 
   2948   // Shortcut for the map value of this captured object.
   2949   HValue* map_value() const { return values()->first(); }
   2950 
   2951   void ReuseSideEffectsFromStore(HInstruction* store) {
   2952     DCHECK(store->HasObservableSideEffects());
   2953     DCHECK(store->IsStoreNamedField());
   2954     changes_flags_.Add(store->ChangesFlags());
   2955   }
   2956 
   2957   // Replay effects of this instruction on the given environment.
   2958   void ReplayEnvironment(HEnvironment* env);
   2959 
   2960   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   2961 
   2962   DECLARE_CONCRETE_INSTRUCTION(CapturedObject)
   2963 
   2964  private:
   2965   int capture_id_;
   2966 
   2967   // Note that we cannot DCE captured objects as they are used to replay
   2968   // the environment. This method is here as an explicit reminder.
   2969   // TODO(mstarzinger): Turn HSimulates into full snapshots maybe?
   2970   bool IsDeletable() const final { return false; }
   2971 };
   2972 
   2973 
   2974 class HConstant final : public HTemplateInstruction<0> {
   2975  public:
   2976   enum Special { kHoleNaN };
   2977 
   2978   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Special);
   2979   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, int32_t);
   2980   DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation);
   2981   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double);
   2982   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle<Object>);
   2983   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);
   2984 
   2985   static HConstant* CreateAndInsertAfter(Isolate* isolate, Zone* zone,
   2986                                          HValue* context, int32_t value,
   2987                                          Representation representation,
   2988                                          HInstruction* instruction) {
   2989     return instruction->Append(
   2990         HConstant::New(isolate, zone, context, value, representation));
   2991   }
   2992 
   2993   Handle<Map> GetMonomorphicJSObjectMap() override {
   2994     Handle<Object> object = object_.handle();
   2995     if (!object.is_null() && object->IsHeapObject()) {
   2996       return v8::internal::handle(HeapObject::cast(*object)->map());
   2997     }
   2998     return Handle<Map>();
   2999   }
   3000 
   3001   static HConstant* CreateAndInsertBefore(Isolate* isolate, Zone* zone,
   3002                                           HValue* context, int32_t value,
   3003                                           Representation representation,
   3004                                           HInstruction* instruction) {
   3005     return instruction->Prepend(
   3006         HConstant::New(isolate, zone, context, value, representation));
   3007   }
   3008 
   3009   static HConstant* CreateAndInsertBefore(Zone* zone,
   3010                                           Unique<Map> map,
   3011                                           bool map_is_stable,
   3012                                           HInstruction* instruction) {
   3013     return instruction->Prepend(new(zone) HConstant(
   3014         map, Unique<Map>(Handle<Map>::null()), map_is_stable,
   3015         Representation::Tagged(), HType::HeapObject(), true,
   3016         false, false, MAP_TYPE));
   3017   }
   3018 
   3019   static HConstant* CreateAndInsertAfter(Zone* zone,
   3020                                          Unique<Map> map,
   3021                                          bool map_is_stable,
   3022                                          HInstruction* instruction) {
   3023     return instruction->Append(new(zone) HConstant(
   3024             map, Unique<Map>(Handle<Map>::null()), map_is_stable,
   3025             Representation::Tagged(), HType::HeapObject(), true,
   3026             false, false, MAP_TYPE));
   3027   }
   3028 
   3029   Handle<Object> handle(Isolate* isolate) {
   3030     if (object_.handle().is_null()) {
   3031       // Default arguments to is_not_in_new_space depend on this heap number
   3032       // to be tenured so that it's guaranteed not to be located in new space.
   3033       object_ = Unique<Object>::CreateUninitialized(
   3034           isolate->factory()->NewNumber(double_value_, TENURED));
   3035     }
   3036     AllowDeferredHandleDereference smi_check;
   3037     DCHECK(HasInteger32Value() || !object_.handle()->IsSmi());
   3038     return object_.handle();
   3039   }
   3040 
   3041   bool IsSpecialDouble() const {
   3042     return HasDoubleValue() &&
   3043            (bit_cast<int64_t>(double_value_) == bit_cast<int64_t>(-0.0) ||
   3044             std::isnan(double_value_));
   3045   }
   3046 
   3047   bool NotInNewSpace() const {
   3048     return IsNotInNewSpaceField::decode(bit_field_);
   3049   }
   3050 
   3051   bool ImmortalImmovable() const;
   3052 
   3053   bool IsCell() const {
   3054     InstanceType instance_type = GetInstanceType();
   3055     return instance_type == CELL_TYPE;
   3056   }
   3057 
   3058   Representation RequiredInputRepresentation(int index) override {
   3059     return Representation::None();
   3060   }
   3061 
   3062   Representation KnownOptimalRepresentation() override {
   3063     if (HasSmiValue() && SmiValuesAre31Bits()) return Representation::Smi();
   3064     if (HasInteger32Value()) return Representation::Integer32();
   3065     if (HasNumberValue()) return Representation::Double();
   3066     if (HasExternalReferenceValue()) return Representation::External();
   3067     return Representation::Tagged();
   3068   }
   3069 
   3070   bool EmitAtUses() override;
   3071   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3072   HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
   3073   Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone);
   3074   Maybe<HConstant*> CopyToTruncatedNumber(Isolate* isolate, Zone* zone);
   3075   bool HasInteger32Value() const {
   3076     return HasInt32ValueField::decode(bit_field_);
   3077   }
   3078   int32_t Integer32Value() const {
   3079     DCHECK(HasInteger32Value());
   3080     return int32_value_;
   3081   }
   3082   bool HasSmiValue() const { return HasSmiValueField::decode(bit_field_); }
   3083   bool HasDoubleValue() const {
   3084     return HasDoubleValueField::decode(bit_field_);
   3085   }
   3086   double DoubleValue() const {
   3087     DCHECK(HasDoubleValue());
   3088     return double_value_;
   3089   }
   3090   uint64_t DoubleValueAsBits() const {
   3091     uint64_t bits;
   3092     DCHECK(HasDoubleValue());
   3093     STATIC_ASSERT(sizeof(bits) == sizeof(double_value_));
   3094     std::memcpy(&bits, &double_value_, sizeof(bits));
   3095     return bits;
   3096   }
   3097   bool IsTheHole() const {
   3098     if (HasDoubleValue() && DoubleValueAsBits() == kHoleNanInt64) {
   3099       return true;
   3100     }
   3101     return object_.IsInitialized() &&
   3102            object_.IsKnownGlobal(isolate()->heap()->the_hole_value());
   3103   }
   3104   bool HasNumberValue() const { return HasDoubleValue(); }
   3105   int32_t NumberValueAsInteger32() const {
   3106     DCHECK(HasNumberValue());
   3107     // Irrespective of whether a numeric HConstant can be safely
   3108     // represented as an int32, we store the (in some cases lossy)
   3109     // representation of the number in int32_value_.
   3110     return int32_value_;
   3111   }
   3112   bool HasStringValue() const {
   3113     if (HasNumberValue()) return false;
   3114     DCHECK(!object_.handle().is_null());
   3115     return GetInstanceType() < FIRST_NONSTRING_TYPE;
   3116   }
   3117   Handle<String> StringValue() const {
   3118     DCHECK(HasStringValue());
   3119     return Handle<String>::cast(object_.handle());
   3120   }
   3121   bool HasInternalizedStringValue() const {
   3122     return HasStringValue() && StringShape(GetInstanceType()).IsInternalized();
   3123   }
   3124 
   3125   bool HasExternalReferenceValue() const {
   3126     return HasExternalReferenceValueField::decode(bit_field_);
   3127   }
   3128   ExternalReference ExternalReferenceValue() const {
   3129     return external_reference_value_;
   3130   }
   3131 
   3132   bool HasBooleanValue() const { return type_.IsBoolean(); }
   3133   bool BooleanValue() const { return BooleanValueField::decode(bit_field_); }
   3134   bool IsCallable() const { return IsCallableField::decode(bit_field_); }
   3135   bool IsUndetectable() const {
   3136     return IsUndetectableField::decode(bit_field_);
   3137   }
   3138   InstanceType GetInstanceType() const {
   3139     return InstanceTypeField::decode(bit_field_);
   3140   }
   3141 
   3142   bool HasMapValue() const { return GetInstanceType() == MAP_TYPE; }
   3143   Unique<Map> MapValue() const {
   3144     DCHECK(HasMapValue());
   3145     return Unique<Map>::cast(GetUnique());
   3146   }
   3147   bool HasStableMapValue() const {
   3148     DCHECK(HasMapValue() || !HasStableMapValueField::decode(bit_field_));
   3149     return HasStableMapValueField::decode(bit_field_);
   3150   }
   3151 
   3152   bool HasObjectMap() const { return !object_map_.IsNull(); }
   3153   Unique<Map> ObjectMap() const {
   3154     DCHECK(HasObjectMap());
   3155     return object_map_;
   3156   }
   3157 
   3158   intptr_t Hashcode() override {
   3159     if (HasInteger32Value()) {
   3160       return static_cast<intptr_t>(int32_value_);
   3161     } else if (HasDoubleValue()) {
   3162       uint64_t bits = DoubleValueAsBits();
   3163       if (sizeof(bits) > sizeof(intptr_t)) {
   3164         bits ^= (bits >> 32);
   3165       }
   3166       return static_cast<intptr_t>(bits);
   3167     } else if (HasExternalReferenceValue()) {
   3168       return reinterpret_cast<intptr_t>(external_reference_value_.address());
   3169     } else {
   3170       DCHECK(!object_.handle().is_null());
   3171       return object_.Hashcode();
   3172     }
   3173   }
   3174 
   3175   void FinalizeUniqueness() override {
   3176     if (!HasDoubleValue() && !HasExternalReferenceValue()) {
   3177       DCHECK(!object_.handle().is_null());
   3178       object_ = Unique<Object>(object_.handle());
   3179     }
   3180   }
   3181 
   3182   Unique<Object> GetUnique() const {
   3183     return object_;
   3184   }
   3185 
   3186   bool EqualsUnique(Unique<Object> other) const {
   3187     return object_.IsInitialized() && object_ == other;
   3188   }
   3189 
   3190   bool DataEquals(HValue* other) override {
   3191     HConstant* other_constant = HConstant::cast(other);
   3192     if (HasInteger32Value()) {
   3193       return other_constant->HasInteger32Value() &&
   3194              int32_value_ == other_constant->int32_value_;
   3195     } else if (HasDoubleValue()) {
   3196       return other_constant->HasDoubleValue() &&
   3197              std::memcmp(&double_value_, &other_constant->double_value_,
   3198                          sizeof(double_value_)) == 0;
   3199     } else if (HasExternalReferenceValue()) {
   3200       return other_constant->HasExternalReferenceValue() &&
   3201              external_reference_value_ ==
   3202                  other_constant->external_reference_value_;
   3203     } else {
   3204       if (other_constant->HasInteger32Value() ||
   3205           other_constant->HasDoubleValue() ||
   3206           other_constant->HasExternalReferenceValue()) {
   3207         return false;
   3208       }
   3209       DCHECK(!object_.handle().is_null());
   3210       return other_constant->object_ == object_;
   3211     }
   3212   }
   3213 
   3214 #ifdef DEBUG
   3215   void Verify() override {}
   3216 #endif
   3217 
   3218   DECLARE_CONCRETE_INSTRUCTION(Constant)
   3219 
   3220  protected:
   3221   Range* InferRange(Zone* zone) override;
   3222 
   3223  private:
   3224   friend class HGraph;
   3225   explicit HConstant(Special special);
   3226   explicit HConstant(Handle<Object> handle,
   3227                      Representation r = Representation::None());
   3228   HConstant(int32_t value,
   3229             Representation r = Representation::None(),
   3230             bool is_not_in_new_space = true,
   3231             Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
   3232   HConstant(double value,
   3233             Representation r = Representation::None(),
   3234             bool is_not_in_new_space = true,
   3235             Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
   3236   HConstant(Unique<Object> object,
   3237             Unique<Map> object_map,
   3238             bool has_stable_map_value,
   3239             Representation r,
   3240             HType type,
   3241             bool is_not_in_new_space,
   3242             bool boolean_value,
   3243             bool is_undetectable,
   3244             InstanceType instance_type);
   3245 
   3246   explicit HConstant(ExternalReference reference);
   3247 
   3248   void Initialize(Representation r);
   3249 
   3250   bool IsDeletable() const override { return true; }
   3251 
   3252   // If object_ is a map, this indicates whether the map is stable.
   3253   class HasStableMapValueField : public BitField<bool, 0, 1> {};
   3254 
   3255   // We store the HConstant in the most specific form safely possible.
   3256   // These flags tell us if the respective member fields hold valid, safe
   3257   // representations of the constant. More specific flags imply more general
   3258   // flags, but not the converse (i.e. smi => int32 => double).
   3259   class HasSmiValueField : public BitField<bool, 1, 1> {};
   3260   class HasInt32ValueField : public BitField<bool, 2, 1> {};
   3261   class HasDoubleValueField : public BitField<bool, 3, 1> {};
   3262 
   3263   class HasExternalReferenceValueField : public BitField<bool, 4, 1> {};
   3264   class IsNotInNewSpaceField : public BitField<bool, 5, 1> {};
   3265   class BooleanValueField : public BitField<bool, 6, 1> {};
   3266   class IsUndetectableField : public BitField<bool, 7, 1> {};
   3267   class IsCallableField : public BitField<bool, 8, 1> {};
   3268 
   3269   static const InstanceType kUnknownInstanceType = FILLER_TYPE;
   3270   class InstanceTypeField : public BitField<InstanceType, 16, 8> {};
   3271 
   3272   // If this is a numerical constant, object_ either points to the
   3273   // HeapObject the constant originated from or is null.  If the
   3274   // constant is non-numeric, object_ always points to a valid
   3275   // constant HeapObject.
   3276   Unique<Object> object_;
   3277 
   3278   // If object_ is a heap object, this points to the stable map of the object.
   3279   Unique<Map> object_map_;
   3280 
   3281   uint32_t bit_field_;
   3282 
   3283   int32_t int32_value_;
   3284   double double_value_;
   3285   ExternalReference external_reference_value_;
   3286 };
   3287 
   3288 
   3289 class HBinaryOperation : public HTemplateInstruction<3> {
   3290  public:
   3291   HBinaryOperation(HValue* context, HValue* left, HValue* right,
   3292                    HType type = HType::Tagged())
   3293       : HTemplateInstruction<3>(type),
   3294         observed_output_representation_(Representation::None()) {
   3295     DCHECK(left != NULL && right != NULL);
   3296     SetOperandAt(0, context);
   3297     SetOperandAt(1, left);
   3298     SetOperandAt(2, right);
   3299     observed_input_representation_[0] = Representation::None();
   3300     observed_input_representation_[1] = Representation::None();
   3301   }
   3302 
   3303   HValue* context() const { return OperandAt(0); }
   3304   HValue* left() const { return OperandAt(1); }
   3305   HValue* right() const { return OperandAt(2); }
   3306 
   3307   // True if switching left and right operands likely generates better code.
   3308   bool AreOperandsBetterSwitched() {
   3309     if (!IsCommutative()) return false;
   3310 
   3311     // Constant operands are better off on the right, they can be inlined in
   3312     // many situations on most platforms.
   3313     if (left()->IsConstant()) return true;
   3314     if (right()->IsConstant()) return false;
   3315 
   3316     // Otherwise, if there is only one use of the right operand, it would be
   3317     // better off on the left for platforms that only have 2-arg arithmetic
   3318     // ops (e.g ia32, x64) that clobber the left operand.
   3319     return right()->HasOneUse();
   3320   }
   3321 
   3322   HValue* BetterLeftOperand() {
   3323     return AreOperandsBetterSwitched() ? right() : left();
   3324   }
   3325 
   3326   HValue* BetterRightOperand() {
   3327     return AreOperandsBetterSwitched() ? left() : right();
   3328   }
   3329 
   3330   void set_observed_input_representation(int index, Representation rep) {
   3331     DCHECK(index >= 1 && index <= 2);
   3332     observed_input_representation_[index - 1] = rep;
   3333   }
   3334 
   3335   virtual void initialize_output_representation(Representation observed) {
   3336     observed_output_representation_ = observed;
   3337   }
   3338 
   3339   Representation observed_input_representation(int index) override {
   3340     if (index == 0) return Representation::Tagged();
   3341     return observed_input_representation_[index - 1];
   3342   }
   3343 
   3344   void UpdateRepresentation(Representation new_rep,
   3345                             HInferRepresentationPhase* h_infer,
   3346                             const char* reason) override {
   3347     Representation rep = !FLAG_smi_binop && new_rep.IsSmi()
   3348         ? Representation::Integer32() : new_rep;
   3349     HValue::UpdateRepresentation(rep, h_infer, reason);
   3350   }
   3351 
   3352   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   3353   Representation RepresentationFromInputs() override;
   3354   Representation RepresentationFromOutput();
   3355   void AssumeRepresentation(Representation r) override;
   3356 
   3357   virtual bool IsCommutative() const { return false; }
   3358 
   3359   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3360 
   3361   Representation RequiredInputRepresentation(int index) override {
   3362     if (index == 0) return Representation::Tagged();
   3363     return representation();
   3364   }
   3365 
   3366   bool RightIsPowerOf2() {
   3367     if (!right()->IsInteger32Constant()) return false;
   3368     int32_t value = right()->GetInteger32Constant();
   3369     if (value < 0) {
   3370       return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(-value));
   3371     }
   3372     return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(value));
   3373   }
   3374 
   3375   DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
   3376 
   3377  private:
   3378   bool IgnoreObservedOutputRepresentation(Representation current_rep);
   3379 
   3380   Representation observed_input_representation_[2];
   3381   Representation observed_output_representation_;
   3382 };
   3383 
   3384 
   3385 class HWrapReceiver final : public HTemplateInstruction<2> {
   3386  public:
   3387   DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
   3388 
   3389   bool DataEquals(HValue* other) override { return true; }
   3390 
   3391   Representation RequiredInputRepresentation(int index) override {
   3392     return Representation::Tagged();
   3393   }
   3394 
   3395   HValue* receiver() const { return OperandAt(0); }
   3396   HValue* function() const { return OperandAt(1); }
   3397 
   3398   HValue* Canonicalize() override;
   3399 
   3400   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3401   bool known_function() const { return known_function_; }
   3402 
   3403   DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
   3404 
   3405  private:
   3406   HWrapReceiver(HValue* receiver, HValue* function) {
   3407     known_function_ = function->IsConstant() &&
   3408         HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
   3409     set_representation(Representation::Tagged());
   3410     SetOperandAt(0, receiver);
   3411     SetOperandAt(1, function);
   3412     SetFlag(kUseGVN);
   3413   }
   3414 
   3415   bool known_function_;
   3416 };
   3417 
   3418 
   3419 class HApplyArguments final : public HTemplateInstruction<4> {
   3420  public:
   3421   DECLARE_INSTRUCTION_FACTORY_P5(HApplyArguments, HValue*, HValue*, HValue*,
   3422                                  HValue*, TailCallMode);
   3423 
   3424   Representation RequiredInputRepresentation(int index) override {
   3425     // The length is untagged, all other inputs are tagged.
   3426     return (index == 2)
   3427         ? Representation::Integer32()
   3428         : Representation::Tagged();
   3429   }
   3430 
   3431   HValue* function() { return OperandAt(0); }
   3432   HValue* receiver() { return OperandAt(1); }
   3433   HValue* length() { return OperandAt(2); }
   3434   HValue* elements() { return OperandAt(3); }
   3435 
   3436   TailCallMode tail_call_mode() const {
   3437     return TailCallModeField::decode(bit_field_);
   3438   }
   3439 
   3440   DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
   3441 
   3442  private:
   3443   HApplyArguments(HValue* function, HValue* receiver, HValue* length,
   3444                   HValue* elements, TailCallMode tail_call_mode)
   3445       : bit_field_(TailCallModeField::encode(tail_call_mode)) {
   3446     set_representation(Representation::Tagged());
   3447     SetOperandAt(0, function);
   3448     SetOperandAt(1, receiver);
   3449     SetOperandAt(2, length);
   3450     SetOperandAt(3, elements);
   3451     SetAllSideEffects();
   3452   }
   3453 
   3454   class TailCallModeField : public BitField<TailCallMode, 0, 1> {};
   3455   uint32_t bit_field_;
   3456 };
   3457 
   3458 
   3459 class HArgumentsElements final : public HTemplateInstruction<0> {
   3460  public:
   3461   DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
   3462   DECLARE_INSTRUCTION_FACTORY_P2(HArgumentsElements, bool, bool);
   3463 
   3464   DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
   3465 
   3466   Representation RequiredInputRepresentation(int index) override {
   3467     return Representation::None();
   3468   }
   3469 
   3470   bool from_inlined() const { return from_inlined_; }
   3471   bool arguments_adaptor() const { return arguments_adaptor_; }
   3472 
   3473  protected:
   3474   bool DataEquals(HValue* other) override { return true; }
   3475 
   3476  private:
   3477   explicit HArgumentsElements(bool from_inlined, bool arguments_adaptor = true)
   3478       : from_inlined_(from_inlined), arguments_adaptor_(arguments_adaptor) {
   3479     // The value produced by this instruction is a pointer into the stack
   3480     // that looks as if it was a smi because of alignment.
   3481     set_representation(Representation::Tagged());
   3482     SetFlag(kUseGVN);
   3483   }
   3484 
   3485   bool IsDeletable() const override { return true; }
   3486 
   3487   bool from_inlined_;
   3488   bool arguments_adaptor_;
   3489 };
   3490 
   3491 
   3492 class HArgumentsLength final : public HUnaryOperation {
   3493  public:
   3494   DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue*);
   3495 
   3496   Representation RequiredInputRepresentation(int index) override {
   3497     return Representation::Tagged();
   3498   }
   3499 
   3500   DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
   3501 
   3502  protected:
   3503   bool DataEquals(HValue* other) override { return true; }
   3504 
   3505  private:
   3506   explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
   3507     set_representation(Representation::Integer32());
   3508     SetFlag(kUseGVN);
   3509   }
   3510 
   3511   bool IsDeletable() const override { return true; }
   3512 };
   3513 
   3514 
   3515 class HAccessArgumentsAt final : public HTemplateInstruction<3> {
   3516  public:
   3517   DECLARE_INSTRUCTION_FACTORY_P3(HAccessArgumentsAt, HValue*, HValue*, HValue*);
   3518 
   3519   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3520 
   3521   Representation RequiredInputRepresentation(int index) override {
   3522     // The arguments elements is considered tagged.
   3523     return index == 0
   3524         ? Representation::Tagged()
   3525         : Representation::Integer32();
   3526   }
   3527 
   3528   HValue* arguments() const { return OperandAt(0); }
   3529   HValue* length() const { return OperandAt(1); }
   3530   HValue* index() const { return OperandAt(2); }
   3531 
   3532   DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
   3533 
   3534  private:
   3535   HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
   3536     set_representation(Representation::Tagged());
   3537     SetFlag(kUseGVN);
   3538     SetOperandAt(0, arguments);
   3539     SetOperandAt(1, length);
   3540     SetOperandAt(2, index);
   3541   }
   3542 
   3543   bool DataEquals(HValue* other) override { return true; }
   3544 };
   3545 
   3546 
   3547 class HBoundsCheck final : public HTemplateInstruction<2> {
   3548  public:
   3549   DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
   3550 
   3551   bool skip_check() const { return skip_check_; }
   3552   void set_skip_check() { skip_check_ = true; }
   3553 
   3554   HValue* base() const { return base_; }
   3555   int offset() const { return offset_; }
   3556   int scale() const { return scale_; }
   3557 
   3558   Representation RequiredInputRepresentation(int index) override {
   3559     return representation();
   3560   }
   3561 
   3562   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3563   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   3564 
   3565   HValue* index() const { return OperandAt(0); }
   3566   HValue* length() const { return OperandAt(1); }
   3567   bool allow_equality() const { return allow_equality_; }
   3568   void set_allow_equality(bool v) { allow_equality_ = v; }
   3569 
   3570   int RedefinedOperandIndex() override { return 0; }
   3571   bool IsPurelyInformativeDefinition() override { return skip_check(); }
   3572 
   3573   DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
   3574 
   3575  protected:
   3576   Range* InferRange(Zone* zone) override;
   3577 
   3578   bool DataEquals(HValue* other) override { return true; }
   3579   bool skip_check_;
   3580   HValue* base_;
   3581   int offset_;
   3582   int scale_;
   3583   bool allow_equality_;
   3584 
   3585  private:
   3586   // Normally HBoundsCheck should be created using the
   3587   // HGraphBuilder::AddBoundsCheck() helper.
   3588   // However when building stubs, where we know that the arguments are Int32,
   3589   // it makes sense to invoke this constructor directly.
   3590   HBoundsCheck(HValue* index, HValue* length)
   3591     : skip_check_(false),
   3592       base_(NULL), offset_(0), scale_(0),
   3593       allow_equality_(false) {
   3594     SetOperandAt(0, index);
   3595     SetOperandAt(1, length);
   3596     SetFlag(kFlexibleRepresentation);
   3597     SetFlag(kUseGVN);
   3598   }
   3599 
   3600   bool IsDeletable() const override { return skip_check() && !FLAG_debug_code; }
   3601 };
   3602 
   3603 
   3604 class HBitwiseBinaryOperation : public HBinaryOperation {
   3605  public:
   3606   HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
   3607                           HType type = HType::TaggedNumber())
   3608       : HBinaryOperation(context, left, right, type) {
   3609     SetFlag(kFlexibleRepresentation);
   3610     SetFlag(kTruncatingToInt32);
   3611     SetFlag(kTruncatingToNumber);
   3612     SetAllSideEffects();
   3613   }
   3614 
   3615   void RepresentationChanged(Representation to) override {
   3616     if (to.IsTagged() &&
   3617         (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
   3618       SetAllSideEffects();
   3619       ClearFlag(kUseGVN);
   3620     } else {
   3621       ClearAllSideEffects();
   3622       SetFlag(kUseGVN);
   3623     }
   3624     if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
   3625   }
   3626 
   3627   void UpdateRepresentation(Representation new_rep,
   3628                             HInferRepresentationPhase* h_infer,
   3629                             const char* reason) override {
   3630     // We only generate either int32 or generic tagged bitwise operations.
   3631     if (new_rep.IsDouble()) new_rep = Representation::Integer32();
   3632     HBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   3633   }
   3634 
   3635   Representation observed_input_representation(int index) override {
   3636     Representation r = HBinaryOperation::observed_input_representation(index);
   3637     if (r.IsDouble()) return Representation::Integer32();
   3638     return r;
   3639   }
   3640 
   3641   void initialize_output_representation(Representation observed) override {
   3642     if (observed.IsDouble()) observed = Representation::Integer32();
   3643     HBinaryOperation::initialize_output_representation(observed);
   3644   }
   3645 
   3646   DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
   3647 
   3648  private:
   3649   bool IsDeletable() const override { return true; }
   3650 };
   3651 
   3652 
   3653 class HMathFloorOfDiv final : public HBinaryOperation {
   3654  public:
   3655   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HMathFloorOfDiv,
   3656                                               HValue*,
   3657                                               HValue*);
   3658 
   3659   DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
   3660 
   3661  protected:
   3662   bool DataEquals(HValue* other) override { return true; }
   3663 
   3664  private:
   3665   HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
   3666       : HBinaryOperation(context, left, right) {
   3667     set_representation(Representation::Integer32());
   3668     SetFlag(kUseGVN);
   3669     SetFlag(kCanOverflow);
   3670     SetFlag(kCanBeDivByZero);
   3671     SetFlag(kLeftCanBeMinInt);
   3672     SetFlag(kLeftCanBeNegative);
   3673     SetFlag(kLeftCanBePositive);
   3674     SetFlag(kTruncatingToNumber);
   3675   }
   3676 
   3677   Range* InferRange(Zone* zone) override;
   3678 
   3679   bool IsDeletable() const override { return true; }
   3680 };
   3681 
   3682 
   3683 class HArithmeticBinaryOperation : public HBinaryOperation {
   3684  public:
   3685   HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right,
   3686                              HType type = HType::TaggedNumber())
   3687       : HBinaryOperation(context, left, right, type) {
   3688     SetAllSideEffects();
   3689     SetFlag(kFlexibleRepresentation);
   3690     SetFlag(kTruncatingToNumber);
   3691   }
   3692 
   3693   void RepresentationChanged(Representation to) override {
   3694     if (to.IsTagged() &&
   3695         (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
   3696       SetAllSideEffects();
   3697       ClearFlag(kUseGVN);
   3698     } else {
   3699       ClearAllSideEffects();
   3700       SetFlag(kUseGVN);
   3701     }
   3702     if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
   3703   }
   3704 
   3705   DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
   3706 
   3707  private:
   3708   bool IsDeletable() const override { return true; }
   3709 };
   3710 
   3711 
   3712 class HCompareGeneric final : public HBinaryOperation {
   3713  public:
   3714   static HCompareGeneric* New(Isolate* isolate, Zone* zone, HValue* context,
   3715                               HValue* left, HValue* right, Token::Value token) {
   3716     return new (zone) HCompareGeneric(context, left, right, token);
   3717   }
   3718 
   3719   Representation RequiredInputRepresentation(int index) override {
   3720     return index == 0
   3721         ? Representation::Tagged()
   3722         : representation();
   3723   }
   3724 
   3725   Token::Value token() const { return token_; }
   3726   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3727 
   3728   DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
   3729 
   3730  private:
   3731   HCompareGeneric(HValue* context, HValue* left, HValue* right,
   3732                   Token::Value token)
   3733       : HBinaryOperation(context, left, right, HType::Boolean()),
   3734         token_(token) {
   3735     DCHECK(Token::IsCompareOp(token));
   3736     set_representation(Representation::Tagged());
   3737     SetAllSideEffects();
   3738   }
   3739 
   3740   Token::Value token_;
   3741 };
   3742 
   3743 
   3744 class HCompareNumericAndBranch : public HTemplateControlInstruction<2, 2> {
   3745  public:
   3746   static HCompareNumericAndBranch* New(Isolate* isolate, Zone* zone,
   3747                                        HValue* context, HValue* left,
   3748                                        HValue* right, Token::Value token,
   3749                                        HBasicBlock* true_target = NULL,
   3750                                        HBasicBlock* false_target = NULL) {
   3751     return new (zone)
   3752         HCompareNumericAndBranch(left, right, token, true_target, false_target);
   3753   }
   3754 
   3755   HValue* left() const { return OperandAt(0); }
   3756   HValue* right() const { return OperandAt(1); }
   3757   Token::Value token() const { return token_; }
   3758 
   3759   void set_observed_input_representation(Representation left,
   3760                                          Representation right) {
   3761       observed_input_representation_[0] = left;
   3762       observed_input_representation_[1] = right;
   3763   }
   3764 
   3765   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   3766 
   3767   Representation RequiredInputRepresentation(int index) override {
   3768     return representation();
   3769   }
   3770   Representation observed_input_representation(int index) override {
   3771     return observed_input_representation_[index];
   3772   }
   3773 
   3774   bool KnownSuccessorBlock(HBasicBlock** block) override;
   3775 
   3776   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3777 
   3778   DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
   3779 
   3780  private:
   3781   HCompareNumericAndBranch(HValue* left, HValue* right, Token::Value token,
   3782                            HBasicBlock* true_target, HBasicBlock* false_target)
   3783       : token_(token) {
   3784     SetFlag(kFlexibleRepresentation);
   3785     DCHECK(Token::IsCompareOp(token));
   3786     SetOperandAt(0, left);
   3787     SetOperandAt(1, right);
   3788     SetSuccessorAt(0, true_target);
   3789     SetSuccessorAt(1, false_target);
   3790   }
   3791 
   3792   Representation observed_input_representation_[2];
   3793   Token::Value token_;
   3794 };
   3795 
   3796 
   3797 class HCompareHoleAndBranch final : public HUnaryControlInstruction {
   3798  public:
   3799   DECLARE_INSTRUCTION_FACTORY_P1(HCompareHoleAndBranch, HValue*);
   3800   DECLARE_INSTRUCTION_FACTORY_P3(HCompareHoleAndBranch, HValue*,
   3801                                  HBasicBlock*, HBasicBlock*);
   3802 
   3803   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   3804 
   3805   Representation RequiredInputRepresentation(int index) override {
   3806     return representation();
   3807   }
   3808 
   3809   DECLARE_CONCRETE_INSTRUCTION(CompareHoleAndBranch)
   3810 
   3811  private:
   3812   HCompareHoleAndBranch(HValue* value,
   3813                         HBasicBlock* true_target = NULL,
   3814                         HBasicBlock* false_target = NULL)
   3815       : HUnaryControlInstruction(value, true_target, false_target) {
   3816     SetFlag(kFlexibleRepresentation);
   3817   }
   3818 };
   3819 
   3820 
   3821 class HCompareObjectEqAndBranch : public HTemplateControlInstruction<2, 2> {
   3822  public:
   3823   DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue*, HValue*);
   3824   DECLARE_INSTRUCTION_FACTORY_P4(HCompareObjectEqAndBranch, HValue*, HValue*,
   3825                                  HBasicBlock*, HBasicBlock*);
   3826 
   3827   bool KnownSuccessorBlock(HBasicBlock** block) override;
   3828 
   3829   static const int kNoKnownSuccessorIndex = -1;
   3830   int known_successor_index() const { return known_successor_index_; }
   3831   void set_known_successor_index(int known_successor_index) {
   3832     known_successor_index_ = known_successor_index;
   3833   }
   3834 
   3835   HValue* left() const { return OperandAt(0); }
   3836   HValue* right() const { return OperandAt(1); }
   3837 
   3838   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3839 
   3840   Representation RequiredInputRepresentation(int index) override {
   3841     return Representation::Tagged();
   3842   }
   3843 
   3844   Representation observed_input_representation(int index) override {
   3845     return Representation::Tagged();
   3846   }
   3847 
   3848   DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
   3849 
   3850  private:
   3851   HCompareObjectEqAndBranch(HValue* left,
   3852                             HValue* right,
   3853                             HBasicBlock* true_target = NULL,
   3854                             HBasicBlock* false_target = NULL)
   3855       : known_successor_index_(kNoKnownSuccessorIndex) {
   3856     SetOperandAt(0, left);
   3857     SetOperandAt(1, right);
   3858     SetSuccessorAt(0, true_target);
   3859     SetSuccessorAt(1, false_target);
   3860   }
   3861 
   3862   int known_successor_index_;
   3863 };
   3864 
   3865 
   3866 class HIsStringAndBranch final : public HUnaryControlInstruction {
   3867  public:
   3868   DECLARE_INSTRUCTION_FACTORY_P1(HIsStringAndBranch, HValue*);
   3869   DECLARE_INSTRUCTION_FACTORY_P3(HIsStringAndBranch, HValue*,
   3870                                  HBasicBlock*, HBasicBlock*);
   3871 
   3872   Representation RequiredInputRepresentation(int index) override {
   3873     return Representation::Tagged();
   3874   }
   3875 
   3876   bool KnownSuccessorBlock(HBasicBlock** block) override;
   3877 
   3878   static const int kNoKnownSuccessorIndex = -1;
   3879   int known_successor_index() const { return known_successor_index_; }
   3880   void set_known_successor_index(int known_successor_index) {
   3881     known_successor_index_ = known_successor_index;
   3882   }
   3883 
   3884   DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
   3885 
   3886  protected:
   3887   int RedefinedOperandIndex() override { return 0; }
   3888 
   3889  private:
   3890   HIsStringAndBranch(HValue* value, HBasicBlock* true_target = NULL,
   3891                      HBasicBlock* false_target = NULL)
   3892       : HUnaryControlInstruction(value, true_target, false_target),
   3893         known_successor_index_(kNoKnownSuccessorIndex) {
   3894     set_representation(Representation::Tagged());
   3895   }
   3896 
   3897   int known_successor_index_;
   3898 };
   3899 
   3900 
   3901 class HIsSmiAndBranch final : public HUnaryControlInstruction {
   3902  public:
   3903   DECLARE_INSTRUCTION_FACTORY_P1(HIsSmiAndBranch, HValue*);
   3904   DECLARE_INSTRUCTION_FACTORY_P3(HIsSmiAndBranch, HValue*,
   3905                                  HBasicBlock*, HBasicBlock*);
   3906 
   3907   DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
   3908 
   3909   Representation RequiredInputRepresentation(int index) override {
   3910     return Representation::Tagged();
   3911   }
   3912 
   3913  protected:
   3914   bool DataEquals(HValue* other) override { return true; }
   3915   int RedefinedOperandIndex() override { return 0; }
   3916 
   3917  private:
   3918   HIsSmiAndBranch(HValue* value,
   3919                   HBasicBlock* true_target = NULL,
   3920                   HBasicBlock* false_target = NULL)
   3921       : HUnaryControlInstruction(value, true_target, false_target) {
   3922     set_representation(Representation::Tagged());
   3923   }
   3924 };
   3925 
   3926 
   3927 class HIsUndetectableAndBranch final : public HUnaryControlInstruction {
   3928  public:
   3929   DECLARE_INSTRUCTION_FACTORY_P1(HIsUndetectableAndBranch, HValue*);
   3930   DECLARE_INSTRUCTION_FACTORY_P3(HIsUndetectableAndBranch, HValue*,
   3931                                  HBasicBlock*, HBasicBlock*);
   3932 
   3933   Representation RequiredInputRepresentation(int index) override {
   3934     return Representation::Tagged();
   3935   }
   3936 
   3937   bool KnownSuccessorBlock(HBasicBlock** block) override;
   3938 
   3939   DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
   3940 
   3941  private:
   3942   HIsUndetectableAndBranch(HValue* value,
   3943                            HBasicBlock* true_target = NULL,
   3944                            HBasicBlock* false_target = NULL)
   3945       : HUnaryControlInstruction(value, true_target, false_target) {}
   3946 };
   3947 
   3948 
   3949 class HStringCompareAndBranch final : public HTemplateControlInstruction<2, 3> {
   3950  public:
   3951   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HStringCompareAndBranch,
   3952                                               HValue*,
   3953                                               HValue*,
   3954                                               Token::Value);
   3955 
   3956   HValue* context() const { return OperandAt(0); }
   3957   HValue* left() const { return OperandAt(1); }
   3958   HValue* right() const { return OperandAt(2); }
   3959   Token::Value token() const { return token_; }
   3960 
   3961   std::ostream& PrintDataTo(std::ostream& os) const final;  // NOLINT
   3962 
   3963   Representation RequiredInputRepresentation(int index) final {
   3964     return Representation::Tagged();
   3965   }
   3966 
   3967   DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
   3968 
   3969  private:
   3970   HStringCompareAndBranch(HValue* context, HValue* left, HValue* right,
   3971                           Token::Value token)
   3972       : token_(token) {
   3973     DCHECK(Token::IsCompareOp(token));
   3974     SetOperandAt(0, context);
   3975     SetOperandAt(1, left);
   3976     SetOperandAt(2, right);
   3977     set_representation(Representation::Tagged());
   3978     SetChangesFlag(kNewSpacePromotion);
   3979     SetDependsOnFlag(kStringChars);
   3980     SetDependsOnFlag(kStringLengths);
   3981   }
   3982 
   3983   Token::Value const token_;
   3984 };
   3985 
   3986 
   3987 class HHasInstanceTypeAndBranch final : public HUnaryControlInstruction {
   3988  public:
   3989   DECLARE_INSTRUCTION_FACTORY_P2(
   3990       HHasInstanceTypeAndBranch, HValue*, InstanceType);
   3991   DECLARE_INSTRUCTION_FACTORY_P3(
   3992       HHasInstanceTypeAndBranch, HValue*, InstanceType, InstanceType);
   3993 
   3994   InstanceType from() { return from_; }
   3995   InstanceType to() { return to_; }
   3996 
   3997   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   3998 
   3999   Representation RequiredInputRepresentation(int index) override {
   4000     return Representation::Tagged();
   4001   }
   4002 
   4003   bool KnownSuccessorBlock(HBasicBlock** block) override;
   4004 
   4005   DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
   4006 
   4007  private:
   4008   HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
   4009       : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
   4010   HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
   4011       : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
   4012     DCHECK(to == LAST_TYPE);  // Others not implemented yet in backend.
   4013   }
   4014 
   4015   InstanceType from_;
   4016   InstanceType to_;  // Inclusive range, not all combinations work.
   4017 };
   4018 
   4019 class HClassOfTestAndBranch final : public HUnaryControlInstruction {
   4020  public:
   4021   DECLARE_INSTRUCTION_FACTORY_P2(HClassOfTestAndBranch, HValue*,
   4022                                  Handle<String>);
   4023 
   4024   DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
   4025 
   4026   Representation RequiredInputRepresentation(int index) override {
   4027     return Representation::Tagged();
   4028   }
   4029 
   4030   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4031 
   4032   Handle<String> class_name() const { return class_name_; }
   4033 
   4034  private:
   4035   HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
   4036       : HUnaryControlInstruction(value, NULL, NULL),
   4037         class_name_(class_name) { }
   4038 
   4039   Handle<String> class_name_;
   4040 };
   4041 
   4042 
   4043 class HTypeofIsAndBranch final : public HUnaryControlInstruction {
   4044  public:
   4045   DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle<String>);
   4046 
   4047   Handle<String> type_literal() const { return type_literal_.handle(); }
   4048   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4049 
   4050   DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
   4051 
   4052   Representation RequiredInputRepresentation(int index) override {
   4053     return Representation::None();
   4054   }
   4055 
   4056   bool KnownSuccessorBlock(HBasicBlock** block) override;
   4057 
   4058   void FinalizeUniqueness() override {
   4059     type_literal_ = Unique<String>(type_literal_.handle());
   4060   }
   4061 
   4062  private:
   4063   HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
   4064       : HUnaryControlInstruction(value, NULL, NULL),
   4065         type_literal_(Unique<String>::CreateUninitialized(type_literal)) { }
   4066 
   4067   Unique<String> type_literal_;
   4068 };
   4069 
   4070 
   4071 class HHasInPrototypeChainAndBranch final
   4072     : public HTemplateControlInstruction<2, 2> {
   4073  public:
   4074   DECLARE_INSTRUCTION_FACTORY_P2(HHasInPrototypeChainAndBranch, HValue*,
   4075                                  HValue*);
   4076 
   4077   HValue* object() const { return OperandAt(0); }
   4078   HValue* prototype() const { return OperandAt(1); }
   4079 
   4080   Representation RequiredInputRepresentation(int index) override {
   4081     return Representation::Tagged();
   4082   }
   4083 
   4084   bool ObjectNeedsSmiCheck() const {
   4085     return !object()->type().IsHeapObject() &&
   4086            !object()->representation().IsHeapObject();
   4087   }
   4088 
   4089   DECLARE_CONCRETE_INSTRUCTION(HasInPrototypeChainAndBranch)
   4090 
   4091  private:
   4092   HHasInPrototypeChainAndBranch(HValue* object, HValue* prototype) {
   4093     SetOperandAt(0, object);
   4094     SetOperandAt(1, prototype);
   4095     SetDependsOnFlag(kCalls);
   4096   }
   4097 };
   4098 
   4099 
   4100 class HPower final : public HTemplateInstruction<2> {
   4101  public:
   4102   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4103                            HValue* left, HValue* right);
   4104 
   4105   HValue* left() { return OperandAt(0); }
   4106   HValue* right() const { return OperandAt(1); }
   4107 
   4108   Representation RequiredInputRepresentation(int index) override {
   4109     return index == 0
   4110       ? Representation::Double()
   4111       : Representation::None();
   4112   }
   4113   Representation observed_input_representation(int index) override {
   4114     return RequiredInputRepresentation(index);
   4115   }
   4116 
   4117   DECLARE_CONCRETE_INSTRUCTION(Power)
   4118 
   4119  protected:
   4120   bool DataEquals(HValue* other) override { return true; }
   4121 
   4122  private:
   4123   HPower(HValue* left, HValue* right) {
   4124     SetOperandAt(0, left);
   4125     SetOperandAt(1, right);
   4126     set_representation(Representation::Double());
   4127     SetFlag(kUseGVN);
   4128     SetChangesFlag(kNewSpacePromotion);
   4129   }
   4130 
   4131   bool IsDeletable() const override {
   4132     return !right()->representation().IsTagged();
   4133   }
   4134 };
   4135 
   4136 
   4137 enum ExternalAddType {
   4138   AddOfExternalAndTagged,
   4139   AddOfExternalAndInt32,
   4140   NoExternalAdd
   4141 };
   4142 
   4143 
   4144 class HAdd final : public HArithmeticBinaryOperation {
   4145  public:
   4146   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4147                            HValue* left, HValue* right);
   4148   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4149                            HValue* left, HValue* right,
   4150                            ExternalAddType external_add_type);
   4151 
   4152   // Add is only commutative if two integer values are added and not if two
   4153   // tagged values are added (because it might be a String concatenation).
   4154   // We also do not commute (pointer + offset).
   4155   bool IsCommutative() const override {
   4156     return !representation().IsTagged() && !representation().IsExternal();
   4157   }
   4158 
   4159   HValue* Canonicalize() override;
   4160 
   4161   void RepresentationChanged(Representation to) override {
   4162     if (to.IsTagged() &&
   4163         (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() ||
   4164          left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) {
   4165       SetAllSideEffects();
   4166       ClearFlag(kUseGVN);
   4167     } else {
   4168       ClearAllSideEffects();
   4169       SetFlag(kUseGVN);
   4170     }
   4171     if (to.IsTagged()) {
   4172       SetChangesFlag(kNewSpacePromotion);
   4173       ClearFlag(kTruncatingToNumber);
   4174     }
   4175     if (!right()->type().IsTaggedNumber() &&
   4176         !right()->representation().IsDouble() &&
   4177         !right()->representation().IsSmiOrInteger32()) {
   4178       ClearFlag(kTruncatingToNumber);
   4179     }
   4180   }
   4181 
   4182   Representation RepresentationFromInputs() override;
   4183 
   4184   Representation RequiredInputRepresentation(int index) override;
   4185 
   4186   bool IsConsistentExternalRepresentation() {
   4187     return left()->representation().IsExternal() &&
   4188            ((external_add_type_ == AddOfExternalAndInt32 &&
   4189              right()->representation().IsInteger32()) ||
   4190             (external_add_type_ == AddOfExternalAndTagged &&
   4191              right()->representation().IsTagged()));
   4192   }
   4193 
   4194   ExternalAddType external_add_type() const { return external_add_type_; }
   4195 
   4196   DECLARE_CONCRETE_INSTRUCTION(Add)
   4197 
   4198  protected:
   4199   bool DataEquals(HValue* other) override { return true; }
   4200 
   4201   Range* InferRange(Zone* zone) override;
   4202 
   4203  private:
   4204   HAdd(HValue* context, HValue* left, HValue* right,
   4205        ExternalAddType external_add_type = NoExternalAdd)
   4206       : HArithmeticBinaryOperation(context, left, right, HType::Tagged()),
   4207         external_add_type_(external_add_type) {
   4208     SetFlag(kCanOverflow);
   4209     switch (external_add_type_) {
   4210       case AddOfExternalAndTagged:
   4211         DCHECK(left->representation().IsExternal());
   4212         DCHECK(right->representation().IsTagged());
   4213         SetDependsOnFlag(kNewSpacePromotion);
   4214         ClearFlag(HValue::kCanOverflow);
   4215         SetFlag(kHasNoObservableSideEffects);
   4216         break;
   4217 
   4218       case NoExternalAdd:
   4219         // This is a bit of a hack: The call to this constructor is generated
   4220         // by a macro that also supports sub and mul, so it doesn't pass in
   4221         // a value for external_add_type but uses the default.
   4222         if (left->representation().IsExternal()) {
   4223           external_add_type_ = AddOfExternalAndInt32;
   4224         }
   4225         break;
   4226 
   4227       case AddOfExternalAndInt32:
   4228         // See comment above.
   4229         UNREACHABLE();
   4230         break;
   4231     }
   4232   }
   4233 
   4234   ExternalAddType external_add_type_;
   4235 };
   4236 
   4237 
   4238 class HSub final : public HArithmeticBinaryOperation {
   4239  public:
   4240   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4241                            HValue* left, HValue* right);
   4242 
   4243   HValue* Canonicalize() override;
   4244 
   4245   DECLARE_CONCRETE_INSTRUCTION(Sub)
   4246 
   4247  protected:
   4248   bool DataEquals(HValue* other) override { return true; }
   4249 
   4250   Range* InferRange(Zone* zone) override;
   4251 
   4252  private:
   4253   HSub(HValue* context, HValue* left, HValue* right)
   4254       : HArithmeticBinaryOperation(context, left, right) {
   4255     SetFlag(kCanOverflow);
   4256   }
   4257 };
   4258 
   4259 
   4260 class HMul final : public HArithmeticBinaryOperation {
   4261  public:
   4262   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4263                            HValue* left, HValue* right);
   4264 
   4265   static HInstruction* NewImul(Isolate* isolate, Zone* zone, HValue* context,
   4266                                HValue* left, HValue* right) {
   4267     HInstruction* instr = HMul::New(isolate, zone, context, left, right);
   4268     if (!instr->IsMul()) return instr;
   4269     HMul* mul = HMul::cast(instr);
   4270     // TODO(mstarzinger): Prevent bailout on minus zero for imul.
   4271     mul->AssumeRepresentation(Representation::Integer32());
   4272     mul->ClearFlag(HValue::kCanOverflow);
   4273     return mul;
   4274   }
   4275 
   4276   HValue* Canonicalize() override;
   4277 
   4278   // Only commutative if it is certain that not two objects are multiplicated.
   4279   bool IsCommutative() const override { return !representation().IsTagged(); }
   4280 
   4281   void UpdateRepresentation(Representation new_rep,
   4282                             HInferRepresentationPhase* h_infer,
   4283                             const char* reason) override {
   4284     HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4285   }
   4286 
   4287   bool MulMinusOne();
   4288 
   4289   DECLARE_CONCRETE_INSTRUCTION(Mul)
   4290 
   4291  protected:
   4292   bool DataEquals(HValue* other) override { return true; }
   4293 
   4294   Range* InferRange(Zone* zone) override;
   4295 
   4296  private:
   4297   HMul(HValue* context, HValue* left, HValue* right)
   4298       : HArithmeticBinaryOperation(context, left, right) {
   4299     SetFlag(kCanOverflow);
   4300   }
   4301 };
   4302 
   4303 
   4304 class HMod final : public HArithmeticBinaryOperation {
   4305  public:
   4306   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4307                            HValue* left, HValue* right);
   4308 
   4309   HValue* Canonicalize() override;
   4310 
   4311   void UpdateRepresentation(Representation new_rep,
   4312                             HInferRepresentationPhase* h_infer,
   4313                             const char* reason) override {
   4314     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
   4315     HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4316   }
   4317 
   4318   DECLARE_CONCRETE_INSTRUCTION(Mod)
   4319 
   4320  protected:
   4321   bool DataEquals(HValue* other) override { return true; }
   4322 
   4323   Range* InferRange(Zone* zone) override;
   4324 
   4325  private:
   4326   HMod(HValue* context, HValue* left, HValue* right)
   4327       : HArithmeticBinaryOperation(context, left, right) {
   4328     SetFlag(kCanBeDivByZero);
   4329     SetFlag(kCanOverflow);
   4330     SetFlag(kLeftCanBeNegative);
   4331   }
   4332 };
   4333 
   4334 
   4335 class HDiv final : public HArithmeticBinaryOperation {
   4336  public:
   4337   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4338                            HValue* left, HValue* right);
   4339 
   4340   HValue* Canonicalize() override;
   4341 
   4342   void UpdateRepresentation(Representation new_rep,
   4343                             HInferRepresentationPhase* h_infer,
   4344                             const char* reason) override {
   4345     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
   4346     HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4347   }
   4348 
   4349   DECLARE_CONCRETE_INSTRUCTION(Div)
   4350 
   4351  protected:
   4352   bool DataEquals(HValue* other) override { return true; }
   4353 
   4354   Range* InferRange(Zone* zone) override;
   4355 
   4356  private:
   4357   HDiv(HValue* context, HValue* left, HValue* right)
   4358       : HArithmeticBinaryOperation(context, left, right) {
   4359     SetFlag(kCanBeDivByZero);
   4360     SetFlag(kCanOverflow);
   4361   }
   4362 };
   4363 
   4364 
   4365 class HMathMinMax final : public HArithmeticBinaryOperation {
   4366  public:
   4367   enum Operation { kMathMin, kMathMax };
   4368 
   4369   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4370                            HValue* left, HValue* right, Operation op);
   4371 
   4372   Representation observed_input_representation(int index) override {
   4373     return RequiredInputRepresentation(index);
   4374   }
   4375 
   4376   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
   4377 
   4378   Representation RepresentationFromInputs() override {
   4379     Representation left_rep = left()->representation();
   4380     Representation right_rep = right()->representation();
   4381     Representation result = Representation::Smi();
   4382     result = result.generalize(left_rep);
   4383     result = result.generalize(right_rep);
   4384     if (result.IsTagged()) return Representation::Double();
   4385     return result;
   4386   }
   4387 
   4388   bool IsCommutative() const override { return true; }
   4389 
   4390   Operation operation() { return operation_; }
   4391 
   4392   DECLARE_CONCRETE_INSTRUCTION(MathMinMax)
   4393 
   4394  protected:
   4395   bool DataEquals(HValue* other) override {
   4396     return other->IsMathMinMax() &&
   4397         HMathMinMax::cast(other)->operation_ == operation_;
   4398   }
   4399 
   4400   Range* InferRange(Zone* zone) override;
   4401 
   4402  private:
   4403   HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
   4404       : HArithmeticBinaryOperation(context, left, right), operation_(op) {}
   4405 
   4406   Operation operation_;
   4407 };
   4408 
   4409 
   4410 class HBitwise final : public HBitwiseBinaryOperation {
   4411  public:
   4412   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4413                            Token::Value op, HValue* left, HValue* right);
   4414 
   4415   Token::Value op() const { return op_; }
   4416 
   4417   bool IsCommutative() const override { return true; }
   4418 
   4419   HValue* Canonicalize() override;
   4420 
   4421   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4422 
   4423   DECLARE_CONCRETE_INSTRUCTION(Bitwise)
   4424 
   4425  protected:
   4426   bool DataEquals(HValue* other) override {
   4427     return op() == HBitwise::cast(other)->op();
   4428   }
   4429 
   4430   Range* InferRange(Zone* zone) override;
   4431 
   4432  private:
   4433   HBitwise(HValue* context, Token::Value op, HValue* left, HValue* right)
   4434       : HBitwiseBinaryOperation(context, left, right), op_(op) {
   4435     DCHECK(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
   4436     // BIT_AND with a smi-range positive value will always unset the
   4437     // entire sign-extension of the smi-sign.
   4438     if (op == Token::BIT_AND &&
   4439         ((left->IsConstant() &&
   4440           left->representation().IsSmi() &&
   4441           HConstant::cast(left)->Integer32Value() >= 0) ||
   4442          (right->IsConstant() &&
   4443           right->representation().IsSmi() &&
   4444           HConstant::cast(right)->Integer32Value() >= 0))) {
   4445       SetFlag(kTruncatingToSmi);
   4446       SetFlag(kTruncatingToInt32);
   4447     // BIT_OR with a smi-range negative value will always set the entire
   4448     // sign-extension of the smi-sign.
   4449     } else if (op == Token::BIT_OR &&
   4450         ((left->IsConstant() &&
   4451           left->representation().IsSmi() &&
   4452           HConstant::cast(left)->Integer32Value() < 0) ||
   4453          (right->IsConstant() &&
   4454           right->representation().IsSmi() &&
   4455           HConstant::cast(right)->Integer32Value() < 0))) {
   4456       SetFlag(kTruncatingToSmi);
   4457       SetFlag(kTruncatingToInt32);
   4458     }
   4459   }
   4460 
   4461   Token::Value op_;
   4462 };
   4463 
   4464 
   4465 class HShl final : public HBitwiseBinaryOperation {
   4466  public:
   4467   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4468                            HValue* left, HValue* right);
   4469 
   4470   Range* InferRange(Zone* zone) override;
   4471 
   4472   void UpdateRepresentation(Representation new_rep,
   4473                             HInferRepresentationPhase* h_infer,
   4474                             const char* reason) override {
   4475     if (new_rep.IsSmi() &&
   4476         !(right()->IsInteger32Constant() &&
   4477           right()->GetInteger32Constant() >= 0)) {
   4478       new_rep = Representation::Integer32();
   4479     }
   4480     HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4481   }
   4482 
   4483   DECLARE_CONCRETE_INSTRUCTION(Shl)
   4484 
   4485  protected:
   4486   bool DataEquals(HValue* other) override { return true; }
   4487 
   4488  private:
   4489   HShl(HValue* context, HValue* left, HValue* right)
   4490       : HBitwiseBinaryOperation(context, left, right) {}
   4491 };
   4492 
   4493 
   4494 class HShr final : public HBitwiseBinaryOperation {
   4495  public:
   4496   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4497                            HValue* left, HValue* right);
   4498 
   4499   Range* InferRange(Zone* zone) override;
   4500 
   4501   void UpdateRepresentation(Representation new_rep,
   4502                             HInferRepresentationPhase* h_infer,
   4503                             const char* reason) override {
   4504     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
   4505     HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4506   }
   4507 
   4508   DECLARE_CONCRETE_INSTRUCTION(Shr)
   4509 
   4510  protected:
   4511   bool DataEquals(HValue* other) override { return true; }
   4512 
   4513  private:
   4514   HShr(HValue* context, HValue* left, HValue* right)
   4515       : HBitwiseBinaryOperation(context, left, right) {}
   4516 };
   4517 
   4518 
   4519 class HSar final : public HBitwiseBinaryOperation {
   4520  public:
   4521   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4522                            HValue* left, HValue* right);
   4523 
   4524   Range* InferRange(Zone* zone) override;
   4525 
   4526   void UpdateRepresentation(Representation new_rep,
   4527                             HInferRepresentationPhase* h_infer,
   4528                             const char* reason) override {
   4529     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
   4530     HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4531   }
   4532 
   4533   DECLARE_CONCRETE_INSTRUCTION(Sar)
   4534 
   4535  protected:
   4536   bool DataEquals(HValue* other) override { return true; }
   4537 
   4538  private:
   4539   HSar(HValue* context, HValue* left, HValue* right)
   4540       : HBitwiseBinaryOperation(context, left, right) {}
   4541 };
   4542 
   4543 
   4544 class HRor final : public HBitwiseBinaryOperation {
   4545  public:
   4546   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   4547                            HValue* left, HValue* right) {
   4548     return new (zone) HRor(context, left, right);
   4549   }
   4550 
   4551   void UpdateRepresentation(Representation new_rep,
   4552                             HInferRepresentationPhase* h_infer,
   4553                             const char* reason) override {
   4554     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
   4555     HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
   4556   }
   4557 
   4558   DECLARE_CONCRETE_INSTRUCTION(Ror)
   4559 
   4560  protected:
   4561   bool DataEquals(HValue* other) override { return true; }
   4562 
   4563  private:
   4564   HRor(HValue* context, HValue* left, HValue* right)
   4565       : HBitwiseBinaryOperation(context, left, right) {
   4566     ChangeRepresentation(Representation::Integer32());
   4567   }
   4568 };
   4569 
   4570 
   4571 class HOsrEntry final : public HTemplateInstruction<0> {
   4572  public:
   4573   DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId);
   4574 
   4575   BailoutId ast_id() const { return ast_id_; }
   4576 
   4577   Representation RequiredInputRepresentation(int index) override {
   4578     return Representation::None();
   4579   }
   4580 
   4581   DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
   4582 
   4583  private:
   4584   explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
   4585     SetChangesFlag(kOsrEntries);
   4586     SetChangesFlag(kNewSpacePromotion);
   4587   }
   4588 
   4589   BailoutId ast_id_;
   4590 };
   4591 
   4592 
   4593 class HParameter final : public HTemplateInstruction<0> {
   4594  public:
   4595   enum ParameterKind {
   4596     STACK_PARAMETER,
   4597     REGISTER_PARAMETER
   4598   };
   4599 
   4600   DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned);
   4601   DECLARE_INSTRUCTION_FACTORY_P2(HParameter, unsigned, ParameterKind);
   4602   DECLARE_INSTRUCTION_FACTORY_P3(HParameter, unsigned, ParameterKind,
   4603                                  Representation);
   4604 
   4605   unsigned index() const { return index_; }
   4606   ParameterKind kind() const { return kind_; }
   4607 
   4608   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4609 
   4610   Representation RequiredInputRepresentation(int index) override {
   4611     return Representation::None();
   4612   }
   4613 
   4614   Representation KnownOptimalRepresentation() override {
   4615     // If a parameter is an input to a phi, that phi should not
   4616     // choose any more optimistic representation than Tagged.
   4617     return Representation::Tagged();
   4618   }
   4619 
   4620   DECLARE_CONCRETE_INSTRUCTION(Parameter)
   4621 
   4622  private:
   4623   explicit HParameter(unsigned index,
   4624                       ParameterKind kind = STACK_PARAMETER)
   4625       : index_(index),
   4626         kind_(kind) {
   4627     set_representation(Representation::Tagged());
   4628   }
   4629 
   4630   explicit HParameter(unsigned index,
   4631                       ParameterKind kind,
   4632                       Representation r)
   4633       : index_(index),
   4634         kind_(kind) {
   4635     set_representation(r);
   4636   }
   4637 
   4638   unsigned index_;
   4639   ParameterKind kind_;
   4640 };
   4641 
   4642 
   4643 class HUnknownOSRValue final : public HTemplateInstruction<0> {
   4644  public:
   4645   DECLARE_INSTRUCTION_FACTORY_P2(HUnknownOSRValue, HEnvironment*, int);
   4646 
   4647   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4648 
   4649   Representation RequiredInputRepresentation(int index) override {
   4650     return Representation::None();
   4651   }
   4652 
   4653   void set_incoming_value(HPhi* value) { incoming_value_ = value; }
   4654   HPhi* incoming_value() { return incoming_value_; }
   4655   HEnvironment *environment() { return environment_; }
   4656   int index() { return index_; }
   4657 
   4658   Representation KnownOptimalRepresentation() override {
   4659     if (incoming_value_ == NULL) return Representation::None();
   4660     return incoming_value_->KnownOptimalRepresentation();
   4661   }
   4662 
   4663   DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
   4664 
   4665  private:
   4666   HUnknownOSRValue(HEnvironment* environment, int index)
   4667       : environment_(environment),
   4668         index_(index),
   4669         incoming_value_(NULL) {
   4670     set_representation(Representation::Tagged());
   4671   }
   4672 
   4673   HEnvironment* environment_;
   4674   int index_;
   4675   HPhi* incoming_value_;
   4676 };
   4677 
   4678 class HAllocate final : public HTemplateInstruction<3> {
   4679  public:
   4680   static bool CompatibleInstanceTypes(InstanceType type1,
   4681                                       InstanceType type2) {
   4682     return ComputeFlags(TENURED, type1) == ComputeFlags(TENURED, type2) &&
   4683         ComputeFlags(NOT_TENURED, type1) == ComputeFlags(NOT_TENURED, type2);
   4684   }
   4685 
   4686   static HAllocate* New(
   4687       Isolate* isolate, Zone* zone, HValue* context, HValue* size, HType type,
   4688       PretenureFlag pretenure_flag, InstanceType instance_type,
   4689       HValue* dominator,
   4690       Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null()) {
   4691     return new (zone) HAllocate(context, size, type, pretenure_flag,
   4692                                 instance_type, dominator, allocation_site);
   4693   }
   4694 
   4695   // Maximum instance size for which allocations will be inlined.
   4696   static const int kMaxInlineSize = 64 * kPointerSize;
   4697 
   4698   HValue* context() const { return OperandAt(0); }
   4699   HValue* size() const { return OperandAt(1); }
   4700   HValue* allocation_folding_dominator() const { return OperandAt(2); }
   4701 
   4702   Representation RequiredInputRepresentation(int index) override {
   4703     if (index == 0) {
   4704       return Representation::Tagged();
   4705     } else {
   4706       return Representation::Integer32();
   4707     }
   4708   }
   4709 
   4710   Handle<Map> GetMonomorphicJSObjectMap() override {
   4711     return known_initial_map_;
   4712   }
   4713 
   4714   void set_known_initial_map(Handle<Map> known_initial_map) {
   4715     known_initial_map_ = known_initial_map;
   4716   }
   4717 
   4718   bool IsNewSpaceAllocation() const {
   4719     return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
   4720   }
   4721 
   4722   bool IsOldSpaceAllocation() const {
   4723     return (flags_ & ALLOCATE_IN_OLD_SPACE) != 0;
   4724   }
   4725 
   4726   bool MustAllocateDoubleAligned() const {
   4727     return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
   4728   }
   4729 
   4730   bool MustPrefillWithFiller() const {
   4731     return (flags_ & PREFILL_WITH_FILLER) != 0;
   4732   }
   4733 
   4734   void MakePrefillWithFiller() {
   4735     flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
   4736   }
   4737 
   4738   void MakeDoubleAligned() {
   4739     flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
   4740   }
   4741 
   4742   void MakeAllocationFoldingDominator() {
   4743     flags_ =
   4744         static_cast<HAllocate::Flags>(flags_ | ALLOCATION_FOLDING_DOMINATOR);
   4745   }
   4746 
   4747   bool IsAllocationFoldingDominator() const {
   4748     return (flags_ & ALLOCATION_FOLDING_DOMINATOR) != 0;
   4749   }
   4750 
   4751   void MakeFoldedAllocation(HAllocate* dominator) {
   4752     flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATION_FOLDED);
   4753     ClearFlag(kTrackSideEffectDominators);
   4754     ClearChangesFlag(kNewSpacePromotion);
   4755     SetOperandAt(2, dominator);
   4756   }
   4757 
   4758   bool IsAllocationFolded() const { return (flags_ & ALLOCATION_FOLDED) != 0; }
   4759 
   4760   bool HandleSideEffectDominator(GVNFlag side_effect,
   4761                                  HValue* dominator) override;
   4762 
   4763   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4764 
   4765   DECLARE_CONCRETE_INSTRUCTION(Allocate)
   4766 
   4767  private:
   4768   enum Flags {
   4769     ALLOCATE_IN_NEW_SPACE = 1 << 0,
   4770     ALLOCATE_IN_OLD_SPACE = 1 << 2,
   4771     ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
   4772     PREFILL_WITH_FILLER = 1 << 4,
   4773     ALLOCATION_FOLDING_DOMINATOR = 1 << 5,
   4774     ALLOCATION_FOLDED = 1 << 6
   4775   };
   4776 
   4777   HAllocate(
   4778       HValue* context, HValue* size, HType type, PretenureFlag pretenure_flag,
   4779       InstanceType instance_type, HValue* dominator,
   4780       Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null())
   4781       : HTemplateInstruction<3>(type),
   4782         flags_(ComputeFlags(pretenure_flag, instance_type)) {
   4783     SetOperandAt(0, context);
   4784     UpdateSize(size);
   4785     SetOperandAt(2, dominator);
   4786     set_representation(Representation::Tagged());
   4787     SetFlag(kTrackSideEffectDominators);
   4788     SetChangesFlag(kNewSpacePromotion);
   4789     SetDependsOnFlag(kNewSpacePromotion);
   4790 
   4791     if (FLAG_trace_pretenuring) {
   4792       PrintF("HAllocate with AllocationSite %p %s\n",
   4793              allocation_site.is_null()
   4794                  ? static_cast<void*>(NULL)
   4795                  : static_cast<void*>(*allocation_site),
   4796              pretenure_flag == TENURED ? "tenured" : "not tenured");
   4797     }
   4798   }
   4799 
   4800   static Flags ComputeFlags(PretenureFlag pretenure_flag,
   4801                             InstanceType instance_type) {
   4802     Flags flags = pretenure_flag == TENURED ? ALLOCATE_IN_OLD_SPACE
   4803                                             : ALLOCATE_IN_NEW_SPACE;
   4804     if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
   4805       flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED);
   4806     }
   4807     // We have to fill the allocated object with one word fillers if we do
   4808     // not use allocation folding since some allocations may depend on each
   4809     // other, i.e., have a pointer to each other. A GC in between these
   4810     // allocations may leave such objects behind in a not completely initialized
   4811     // state.
   4812     if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
   4813       flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER);
   4814     }
   4815     return flags;
   4816   }
   4817 
   4818   void UpdateSize(HValue* size) {
   4819     SetOperandAt(1, size);
   4820   }
   4821 
   4822   bool IsFoldable(HAllocate* allocate) {
   4823     return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) ||
   4824            (IsOldSpaceAllocation() && allocate->IsOldSpaceAllocation());
   4825   }
   4826 
   4827   Flags flags_;
   4828   Handle<Map> known_initial_map_;
   4829 };
   4830 
   4831 
   4832 class HStoreCodeEntry final : public HTemplateInstruction<2> {
   4833  public:
   4834   static HStoreCodeEntry* New(Isolate* isolate, Zone* zone, HValue* context,
   4835                               HValue* function, HValue* code) {
   4836     return new(zone) HStoreCodeEntry(function, code);
   4837   }
   4838 
   4839   Representation RequiredInputRepresentation(int index) override {
   4840     return Representation::Tagged();
   4841   }
   4842 
   4843   HValue* function() { return OperandAt(0); }
   4844   HValue* code_object() { return OperandAt(1); }
   4845 
   4846   DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry)
   4847 
   4848  private:
   4849   HStoreCodeEntry(HValue* function, HValue* code) {
   4850     SetOperandAt(0, function);
   4851     SetOperandAt(1, code);
   4852   }
   4853 };
   4854 
   4855 
   4856 class HInnerAllocatedObject final : public HTemplateInstruction<2> {
   4857  public:
   4858   static HInnerAllocatedObject* New(Isolate* isolate, Zone* zone,
   4859                                     HValue* context, HValue* value,
   4860                                     HValue* offset, HType type) {
   4861     return new(zone) HInnerAllocatedObject(value, offset, type);
   4862   }
   4863 
   4864   HValue* base_object() const { return OperandAt(0); }
   4865   HValue* offset() const { return OperandAt(1); }
   4866 
   4867   Representation RequiredInputRepresentation(int index) override {
   4868     return index == 0 ? Representation::Tagged() : Representation::Integer32();
   4869   }
   4870 
   4871   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4872 
   4873   DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
   4874 
   4875  private:
   4876   HInnerAllocatedObject(HValue* value,
   4877                         HValue* offset,
   4878                         HType type) : HTemplateInstruction<2>(type) {
   4879     DCHECK(value->IsAllocate());
   4880     DCHECK(type.IsHeapObject());
   4881     SetOperandAt(0, value);
   4882     SetOperandAt(1, offset);
   4883     set_representation(Representation::Tagged());
   4884   }
   4885 };
   4886 
   4887 
   4888 inline bool StoringValueNeedsWriteBarrier(HValue* value) {
   4889   return !value->type().IsSmi()
   4890       && !value->type().IsNull()
   4891       && !value->type().IsBoolean()
   4892       && !value->type().IsUndefined()
   4893       && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
   4894 }
   4895 
   4896 
   4897 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
   4898                                             HValue* value,
   4899                                             HValue* dominator) {
   4900   // There may be multiple inner allocates dominated by one allocate.
   4901   while (object->IsInnerAllocatedObject()) {
   4902     object = HInnerAllocatedObject::cast(object)->base_object();
   4903   }
   4904 
   4905   if (object->IsAllocate()) {
   4906     HAllocate* allocate = HAllocate::cast(object);
   4907     if (allocate->IsAllocationFolded()) {
   4908       HValue* dominator = allocate->allocation_folding_dominator();
   4909       // There is no guarantee that all allocations are folded together because
   4910       // GVN performs a fixpoint.
   4911       if (HAllocate::cast(dominator)->IsAllocationFoldingDominator()) {
   4912         object = dominator;
   4913       }
   4914     }
   4915   }
   4916 
   4917   if (object->IsConstant() &&
   4918       HConstant::cast(object)->HasExternalReferenceValue()) {
   4919     // Stores to external references require no write barriers
   4920     return false;
   4921   }
   4922   // We definitely need a write barrier unless the object is the allocation
   4923   // dominator.
   4924   if (object == dominator && object->IsAllocate()) {
   4925     // Stores to new space allocations require no write barriers.
   4926     if (HAllocate::cast(object)->IsNewSpaceAllocation()) {
   4927       return false;
   4928     }
   4929   }
   4930   return true;
   4931 }
   4932 
   4933 
   4934 inline PointersToHereCheck PointersToHereCheckForObject(HValue* object,
   4935                                                         HValue* dominator) {
   4936   while (object->IsInnerAllocatedObject()) {
   4937     object = HInnerAllocatedObject::cast(object)->base_object();
   4938   }
   4939   if (object == dominator &&
   4940       object->IsAllocate() &&
   4941       HAllocate::cast(object)->IsNewSpaceAllocation()) {
   4942     return kPointersToHereAreAlwaysInteresting;
   4943   }
   4944   return kPointersToHereMaybeInteresting;
   4945 }
   4946 
   4947 
   4948 class HLoadContextSlot final : public HUnaryOperation {
   4949  public:
   4950   enum Mode {
   4951     // Perform a normal load of the context slot without checking its value.
   4952     kNoCheck,
   4953     // Load and check the value of the context slot. Deoptimize if it's the
   4954     // hole value. This is used for checking for loading of uninitialized
   4955     // harmony bindings where we deoptimize into full-codegen generated code
   4956     // which will subsequently throw a reference error.
   4957     kCheckDeoptimize
   4958   };
   4959 
   4960   HLoadContextSlot(HValue* context, int slot_index, Mode mode)
   4961       : HUnaryOperation(context), slot_index_(slot_index), mode_(mode) {
   4962     set_representation(Representation::Tagged());
   4963     SetFlag(kUseGVN);
   4964     SetDependsOnFlag(kContextSlots);
   4965   }
   4966 
   4967   int slot_index() const { return slot_index_; }
   4968   Mode mode() const { return mode_; }
   4969 
   4970   bool DeoptimizesOnHole() {
   4971     return mode_ == kCheckDeoptimize;
   4972   }
   4973 
   4974   bool RequiresHoleCheck() const {
   4975     return mode_ != kNoCheck;
   4976   }
   4977 
   4978   Representation RequiredInputRepresentation(int index) override {
   4979     return Representation::Tagged();
   4980   }
   4981 
   4982   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   4983 
   4984   DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
   4985 
   4986  protected:
   4987   bool DataEquals(HValue* other) override {
   4988     HLoadContextSlot* b = HLoadContextSlot::cast(other);
   4989     return (slot_index() == b->slot_index());
   4990   }
   4991 
   4992  private:
   4993   bool IsDeletable() const override { return !RequiresHoleCheck(); }
   4994 
   4995   int slot_index_;
   4996   Mode mode_;
   4997 };
   4998 
   4999 
   5000 class HStoreContextSlot final : public HTemplateInstruction<2> {
   5001  public:
   5002   enum Mode {
   5003     // Perform a normal store to the context slot without checking its previous
   5004     // value.
   5005     kNoCheck,
   5006     // Check the previous value of the context slot and deoptimize if it's the
   5007     // hole value. This is used for checking for assignments to uninitialized
   5008     // harmony bindings where we deoptimize into full-codegen generated code
   5009     // which will subsequently throw a reference error.
   5010     kCheckDeoptimize
   5011   };
   5012 
   5013   DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
   5014                                  Mode, HValue*);
   5015 
   5016   HValue* context() const { return OperandAt(0); }
   5017   HValue* value() const { return OperandAt(1); }
   5018   int slot_index() const { return slot_index_; }
   5019   Mode mode() const { return mode_; }
   5020 
   5021   bool NeedsWriteBarrier() {
   5022     return StoringValueNeedsWriteBarrier(value());
   5023   }
   5024 
   5025   bool DeoptimizesOnHole() {
   5026     return mode_ == kCheckDeoptimize;
   5027   }
   5028 
   5029   bool RequiresHoleCheck() {
   5030     return mode_ != kNoCheck;
   5031   }
   5032 
   5033   Representation RequiredInputRepresentation(int index) override {
   5034     return Representation::Tagged();
   5035   }
   5036 
   5037   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5038 
   5039   DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
   5040 
   5041  private:
   5042   HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
   5043       : slot_index_(slot_index), mode_(mode) {
   5044     SetOperandAt(0, context);
   5045     SetOperandAt(1, value);
   5046     SetChangesFlag(kContextSlots);
   5047   }
   5048 
   5049   int slot_index_;
   5050   Mode mode_;
   5051 };
   5052 
   5053 
   5054 // Represents an access to a portion of an object, such as the map pointer,
   5055 // array elements pointer, etc, but not accesses to array elements themselves.
   5056 class HObjectAccess final {
   5057  public:
   5058   inline bool IsInobject() const {
   5059     return portion() != kBackingStore && portion() != kExternalMemory;
   5060   }
   5061 
   5062   inline bool IsExternalMemory() const {
   5063     return portion() == kExternalMemory;
   5064   }
   5065 
   5066   inline bool IsStringLength() const {
   5067     return portion() == kStringLengths;
   5068   }
   5069 
   5070   inline bool IsMap() const {
   5071     return portion() == kMaps;
   5072   }
   5073 
   5074   inline int offset() const {
   5075     return OffsetField::decode(value_);
   5076   }
   5077 
   5078   inline Representation representation() const {
   5079     return Representation::FromKind(RepresentationField::decode(value_));
   5080   }
   5081 
   5082   inline Handle<Name> name() const { return name_; }
   5083 
   5084   inline bool immutable() const {
   5085     return ImmutableField::decode(value_);
   5086   }
   5087 
   5088   // Returns true if access is being made to an in-object property that
   5089   // was already added to the object.
   5090   inline bool existing_inobject_property() const {
   5091     return ExistingInobjectPropertyField::decode(value_);
   5092   }
   5093 
   5094   inline HObjectAccess WithRepresentation(Representation representation) {
   5095     return HObjectAccess(portion(), offset(), representation, name(),
   5096                          immutable(), existing_inobject_property());
   5097   }
   5098 
   5099   static HObjectAccess ForHeapNumberValue() {
   5100     return HObjectAccess(
   5101         kDouble, HeapNumber::kValueOffset, Representation::Double());
   5102   }
   5103 
   5104   static HObjectAccess ForHeapNumberValueLowestBits() {
   5105     return HObjectAccess(kDouble,
   5106                          HeapNumber::kValueOffset,
   5107                          Representation::Integer32());
   5108   }
   5109 
   5110   static HObjectAccess ForHeapNumberValueHighestBits() {
   5111     return HObjectAccess(kDouble,
   5112                          HeapNumber::kValueOffset + kIntSize,
   5113                          Representation::Integer32());
   5114   }
   5115 
   5116   static HObjectAccess ForOddballToNumber(
   5117       Representation representation = Representation::Tagged()) {
   5118     return HObjectAccess(kInobject, Oddball::kToNumberOffset, representation);
   5119   }
   5120 
   5121   static HObjectAccess ForOddballTypeOf() {
   5122     return HObjectAccess(kInobject, Oddball::kTypeOfOffset,
   5123                          Representation::HeapObject());
   5124   }
   5125 
   5126   static HObjectAccess ForElementsPointer() {
   5127     return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
   5128   }
   5129 
   5130   static HObjectAccess ForLiteralsPointer() {
   5131     return HObjectAccess(kInobject, JSFunction::kLiteralsOffset);
   5132   }
   5133 
   5134   static HObjectAccess ForNextFunctionLinkPointer() {
   5135     return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
   5136   }
   5137 
   5138   static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
   5139     return HObjectAccess(
   5140         kArrayLengths,
   5141         JSArray::kLengthOffset,
   5142         IsFastElementsKind(elements_kind)
   5143             ? Representation::Smi() : Representation::Tagged());
   5144   }
   5145 
   5146   static HObjectAccess ForAllocationSiteOffset(int offset);
   5147 
   5148   static HObjectAccess ForAllocationSiteList() {
   5149     return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
   5150                          Handle<Name>::null(), false, false);
   5151   }
   5152 
   5153   static HObjectAccess ForFixedArrayLength() {
   5154     return HObjectAccess(
   5155         kArrayLengths,
   5156         FixedArray::kLengthOffset,
   5157         Representation::Smi());
   5158   }
   5159 
   5160   static HObjectAccess ForFixedTypedArrayBaseBasePointer() {
   5161     return HObjectAccess(kInobject, FixedTypedArrayBase::kBasePointerOffset,
   5162                          Representation::Tagged());
   5163   }
   5164 
   5165   static HObjectAccess ForFixedTypedArrayBaseExternalPointer() {
   5166     return HObjectAccess::ForObservableJSObjectOffset(
   5167         FixedTypedArrayBase::kExternalPointerOffset,
   5168         Representation::External());
   5169   }
   5170 
   5171   static HObjectAccess ForStringHashField() {
   5172     return HObjectAccess(kInobject,
   5173                          String::kHashFieldOffset,
   5174                          Representation::Integer32());
   5175   }
   5176 
   5177   static HObjectAccess ForStringLength() {
   5178     STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
   5179     return HObjectAccess(
   5180         kStringLengths,
   5181         String::kLengthOffset,
   5182         Representation::Smi());
   5183   }
   5184 
   5185   static HObjectAccess ForConsStringFirst() {
   5186     return HObjectAccess(kInobject, ConsString::kFirstOffset);
   5187   }
   5188 
   5189   static HObjectAccess ForConsStringSecond() {
   5190     return HObjectAccess(kInobject, ConsString::kSecondOffset);
   5191   }
   5192 
   5193   static HObjectAccess ForPropertiesPointer() {
   5194     return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
   5195   }
   5196 
   5197   static HObjectAccess ForPrototypeOrInitialMap() {
   5198     return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
   5199   }
   5200 
   5201   static HObjectAccess ForSharedFunctionInfoPointer() {
   5202     return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
   5203   }
   5204 
   5205   static HObjectAccess ForCodeEntryPointer() {
   5206     return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
   5207   }
   5208 
   5209   static HObjectAccess ForCodeOffset() {
   5210     return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
   5211   }
   5212 
   5213   static HObjectAccess ForOptimizedCodeMap() {
   5214     return HObjectAccess(kInobject,
   5215                          SharedFunctionInfo::kOptimizedCodeMapOffset);
   5216   }
   5217 
   5218   static HObjectAccess ForFunctionContextPointer() {
   5219     return HObjectAccess(kInobject, JSFunction::kContextOffset);
   5220   }
   5221 
   5222   static HObjectAccess ForMap() {
   5223     return HObjectAccess(kMaps, JSObject::kMapOffset);
   5224   }
   5225 
   5226   static HObjectAccess ForPrototype() {
   5227     return HObjectAccess(kMaps, Map::kPrototypeOffset);
   5228   }
   5229 
   5230   static HObjectAccess ForMapAsInteger32() {
   5231     return HObjectAccess(kMaps, JSObject::kMapOffset,
   5232                          Representation::Integer32());
   5233   }
   5234 
   5235   static HObjectAccess ForMapInObjectPropertiesOrConstructorFunctionIndex() {
   5236     return HObjectAccess(
   5237         kInobject, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset,
   5238         Representation::UInteger8());
   5239   }
   5240 
   5241   static HObjectAccess ForMapInstanceType() {
   5242     return HObjectAccess(kInobject,
   5243                          Map::kInstanceTypeOffset,
   5244                          Representation::UInteger8());
   5245   }
   5246 
   5247   static HObjectAccess ForMapInstanceSize() {
   5248     return HObjectAccess(kInobject,
   5249                          Map::kInstanceSizeOffset,
   5250                          Representation::UInteger8());
   5251   }
   5252 
   5253   static HObjectAccess ForMapBitField() {
   5254     return HObjectAccess(kInobject,
   5255                          Map::kBitFieldOffset,
   5256                          Representation::UInteger8());
   5257   }
   5258 
   5259   static HObjectAccess ForMapBitField2() {
   5260     return HObjectAccess(kInobject,
   5261                          Map::kBitField2Offset,
   5262                          Representation::UInteger8());
   5263   }
   5264 
   5265   static HObjectAccess ForMapBitField3() {
   5266     return HObjectAccess(kInobject, Map::kBitField3Offset,
   5267                          Representation::Integer32());
   5268   }
   5269 
   5270   static HObjectAccess ForMapDescriptors() {
   5271     return HObjectAccess(kInobject, Map::kDescriptorsOffset);
   5272   }
   5273 
   5274   static HObjectAccess ForNameHashField() {
   5275     return HObjectAccess(kInobject,
   5276                          Name::kHashFieldOffset,
   5277                          Representation::Integer32());
   5278   }
   5279 
   5280   static HObjectAccess ForMapInstanceTypeAndBitField() {
   5281     STATIC_ASSERT((Map::kInstanceTypeAndBitFieldOffset & 1) == 0);
   5282     // Ensure the two fields share one 16-bit word, endian-independent.
   5283     STATIC_ASSERT((Map::kBitFieldOffset & ~1) ==
   5284                   (Map::kInstanceTypeOffset & ~1));
   5285     return HObjectAccess(kInobject,
   5286                          Map::kInstanceTypeAndBitFieldOffset,
   5287                          Representation::UInteger16());
   5288   }
   5289 
   5290   static HObjectAccess ForPropertyCellValue() {
   5291     return HObjectAccess(kInobject, PropertyCell::kValueOffset);
   5292   }
   5293 
   5294   static HObjectAccess ForPropertyCellDetails() {
   5295     return HObjectAccess(kInobject, PropertyCell::kDetailsOffset,
   5296                          Representation::Smi());
   5297   }
   5298 
   5299   static HObjectAccess ForCellValue() {
   5300     return HObjectAccess(kInobject, Cell::kValueOffset);
   5301   }
   5302 
   5303   static HObjectAccess ForWeakCellValue() {
   5304     return HObjectAccess(kInobject, WeakCell::kValueOffset);
   5305   }
   5306 
   5307   static HObjectAccess ForWeakCellNext() {
   5308     return HObjectAccess(kInobject, WeakCell::kNextOffset);
   5309   }
   5310 
   5311   static HObjectAccess ForAllocationMementoSite() {
   5312     return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
   5313   }
   5314 
   5315   static HObjectAccess ForCounter() {
   5316     return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
   5317                          Handle<Name>::null(), false, false);
   5318   }
   5319 
   5320   static HObjectAccess ForExternalUInteger8() {
   5321     return HObjectAccess(kExternalMemory, 0, Representation::UInteger8(),
   5322                          Handle<Name>::null(), false, false);
   5323   }
   5324 
   5325   static HObjectAccess ForBoundTargetFunction() {
   5326     return HObjectAccess(kInobject,
   5327                          JSBoundFunction::kBoundTargetFunctionOffset);
   5328   }
   5329 
   5330   static HObjectAccess ForBoundThis() {
   5331     return HObjectAccess(kInobject, JSBoundFunction::kBoundThisOffset);
   5332   }
   5333 
   5334   static HObjectAccess ForBoundArguments() {
   5335     return HObjectAccess(kInobject, JSBoundFunction::kBoundArgumentsOffset);
   5336   }
   5337 
   5338   // Create an access to an offset in a fixed array header.
   5339   static HObjectAccess ForFixedArrayHeader(int offset);
   5340 
   5341   // Create an access to an in-object property in a JSObject.
   5342   // This kind of access must be used when the object |map| is known and
   5343   // in-object properties are being accessed. Accesses of the in-object
   5344   // properties can have different semantics depending on whether corresponding
   5345   // property was added to the map or not.
   5346   static HObjectAccess ForMapAndOffset(Handle<Map> map, int offset,
   5347       Representation representation = Representation::Tagged());
   5348 
   5349   // Create an access to an in-object property in a JSObject.
   5350   // This kind of access can be used for accessing object header fields or
   5351   // in-object properties if the map of the object is not known.
   5352   static HObjectAccess ForObservableJSObjectOffset(int offset,
   5353       Representation representation = Representation::Tagged()) {
   5354     return ForMapAndOffset(Handle<Map>::null(), offset, representation);
   5355   }
   5356 
   5357   // Create an access to an in-object property in a JSArray.
   5358   static HObjectAccess ForJSArrayOffset(int offset);
   5359 
   5360   static HObjectAccess ForContextSlot(int index);
   5361 
   5362   static HObjectAccess ForScriptContext(int index);
   5363 
   5364   // Create an access to the backing store of an object.
   5365   static HObjectAccess ForBackingStoreOffset(int offset,
   5366       Representation representation = Representation::Tagged());
   5367 
   5368   // Create an access to a resolved field (in-object or backing store).
   5369   static HObjectAccess ForField(Handle<Map> map, int index,
   5370                                 Representation representation,
   5371                                 Handle<Name> name);
   5372 
   5373   static HObjectAccess ForJSTypedArrayLength() {
   5374     return HObjectAccess::ForObservableJSObjectOffset(
   5375         JSTypedArray::kLengthOffset);
   5376   }
   5377 
   5378   static HObjectAccess ForJSArrayBufferBackingStore() {
   5379     return HObjectAccess::ForObservableJSObjectOffset(
   5380         JSArrayBuffer::kBackingStoreOffset, Representation::External());
   5381   }
   5382 
   5383   static HObjectAccess ForJSArrayBufferByteLength() {
   5384     return HObjectAccess::ForObservableJSObjectOffset(
   5385         JSArrayBuffer::kByteLengthOffset, Representation::Tagged());
   5386   }
   5387 
   5388   static HObjectAccess ForJSArrayBufferBitField() {
   5389     return HObjectAccess::ForObservableJSObjectOffset(
   5390         JSArrayBuffer::kBitFieldOffset, Representation::Integer32());
   5391   }
   5392 
   5393   static HObjectAccess ForJSArrayBufferBitFieldSlot() {
   5394     return HObjectAccess::ForObservableJSObjectOffset(
   5395         JSArrayBuffer::kBitFieldSlot, Representation::Smi());
   5396   }
   5397 
   5398   static HObjectAccess ForJSArrayBufferViewBuffer() {
   5399     return HObjectAccess::ForObservableJSObjectOffset(
   5400         JSArrayBufferView::kBufferOffset);
   5401   }
   5402 
   5403   static HObjectAccess ForJSArrayBufferViewByteOffset() {
   5404     return HObjectAccess::ForObservableJSObjectOffset(
   5405         JSArrayBufferView::kByteOffsetOffset);
   5406   }
   5407 
   5408   static HObjectAccess ForJSArrayBufferViewByteLength() {
   5409     return HObjectAccess::ForObservableJSObjectOffset(
   5410         JSArrayBufferView::kByteLengthOffset);
   5411   }
   5412 
   5413   static HObjectAccess ForJSGlobalObjectNativeContext() {
   5414     return HObjectAccess(kInobject, JSGlobalObject::kNativeContextOffset);
   5415   }
   5416 
   5417   static HObjectAccess ForJSRegExpFlags() {
   5418     return HObjectAccess(kInobject, JSRegExp::kFlagsOffset);
   5419   }
   5420 
   5421   static HObjectAccess ForJSRegExpSource() {
   5422     return HObjectAccess(kInobject, JSRegExp::kSourceOffset);
   5423   }
   5424 
   5425   static HObjectAccess ForJSCollectionTable() {
   5426     return HObjectAccess::ForObservableJSObjectOffset(
   5427         JSCollection::kTableOffset);
   5428   }
   5429 
   5430   template <typename CollectionType>
   5431   static HObjectAccess ForOrderedHashTableNumberOfBuckets() {
   5432     return HObjectAccess(kInobject, CollectionType::kNumberOfBucketsOffset,
   5433                          Representation::Smi());
   5434   }
   5435 
   5436   template <typename CollectionType>
   5437   static HObjectAccess ForOrderedHashTableNumberOfElements() {
   5438     return HObjectAccess(kInobject, CollectionType::kNumberOfElementsOffset,
   5439                          Representation::Smi());
   5440   }
   5441 
   5442   template <typename CollectionType>
   5443   static HObjectAccess ForOrderedHashTableNumberOfDeletedElements() {
   5444     return HObjectAccess(kInobject,
   5445                          CollectionType::kNumberOfDeletedElementsOffset,
   5446                          Representation::Smi());
   5447   }
   5448 
   5449   template <typename CollectionType>
   5450   static HObjectAccess ForOrderedHashTableNextTable() {
   5451     return HObjectAccess(kInobject, CollectionType::kNextTableOffset);
   5452   }
   5453 
   5454   template <typename CollectionType>
   5455   static HObjectAccess ForOrderedHashTableBucket(int bucket) {
   5456     return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
   5457                                         (bucket * kPointerSize),
   5458                          Representation::Smi());
   5459   }
   5460 
   5461   // Access into the data table of an OrderedHashTable with a
   5462   // known-at-compile-time bucket count.
   5463   template <typename CollectionType, int kBucketCount>
   5464   static HObjectAccess ForOrderedHashTableDataTableIndex(int index) {
   5465     return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
   5466                                         (kBucketCount * kPointerSize) +
   5467                                         (index * kPointerSize));
   5468   }
   5469 
   5470   inline bool Equals(HObjectAccess that) const {
   5471     return value_ == that.value_;  // portion and offset must match
   5472   }
   5473 
   5474  protected:
   5475   void SetGVNFlags(HValue *instr, PropertyAccessType access_type);
   5476 
   5477  private:
   5478   // internal use only; different parts of an object or array
   5479   enum Portion {
   5480     kMaps,             // map of an object
   5481     kArrayLengths,     // the length of an array
   5482     kStringLengths,    // the length of a string
   5483     kElementsPointer,  // elements pointer
   5484     kBackingStore,     // some field in the backing store
   5485     kDouble,           // some double field
   5486     kInobject,         // some other in-object field
   5487     kExternalMemory    // some field in external memory
   5488   };
   5489 
   5490   HObjectAccess() : value_(0) {}
   5491 
   5492   HObjectAccess(Portion portion, int offset,
   5493                 Representation representation = Representation::Tagged(),
   5494                 Handle<Name> name = Handle<Name>::null(),
   5495                 bool immutable = false, bool existing_inobject_property = true)
   5496       : value_(PortionField::encode(portion) |
   5497                RepresentationField::encode(representation.kind()) |
   5498                ImmutableField::encode(immutable ? 1 : 0) |
   5499                ExistingInobjectPropertyField::encode(
   5500                    existing_inobject_property ? 1 : 0) |
   5501                OffsetField::encode(offset)),
   5502         name_(name) {
   5503     // assert that the fields decode correctly
   5504     DCHECK(this->offset() == offset);
   5505     DCHECK(this->portion() == portion);
   5506     DCHECK(this->immutable() == immutable);
   5507     DCHECK(this->existing_inobject_property() == existing_inobject_property);
   5508     DCHECK(RepresentationField::decode(value_) == representation.kind());
   5509     DCHECK(!this->existing_inobject_property() || IsInobject());
   5510   }
   5511 
   5512   class PortionField : public BitField<Portion, 0, 3> {};
   5513   class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
   5514   class ImmutableField : public BitField<bool, 7, 1> {};
   5515   class ExistingInobjectPropertyField : public BitField<bool, 8, 1> {};
   5516   class OffsetField : public BitField<int, 9, 23> {};
   5517 
   5518   uint32_t value_;  // encodes portion, representation, immutable, and offset
   5519   Handle<Name> name_;
   5520 
   5521   friend class HLoadNamedField;
   5522   friend class HStoreNamedField;
   5523   friend class SideEffectsTracker;
   5524   friend std::ostream& operator<<(std::ostream& os,
   5525                                   const HObjectAccess& access);
   5526 
   5527   inline Portion portion() const {
   5528     return PortionField::decode(value_);
   5529   }
   5530 };
   5531 
   5532 
   5533 std::ostream& operator<<(std::ostream& os, const HObjectAccess& access);
   5534 
   5535 
   5536 class HLoadNamedField final : public HTemplateInstruction<2> {
   5537  public:
   5538   DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*,
   5539                                  HValue*, HObjectAccess);
   5540   DECLARE_INSTRUCTION_FACTORY_P5(HLoadNamedField, HValue*, HValue*,
   5541                                  HObjectAccess, const UniqueSet<Map>*, HType);
   5542 
   5543   HValue* object() const { return OperandAt(0); }
   5544   HValue* dependency() const {
   5545     DCHECK(HasDependency());
   5546     return OperandAt(1);
   5547   }
   5548   bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
   5549   HObjectAccess access() const { return access_; }
   5550   Representation field_representation() const {
   5551       return access_.representation();
   5552   }
   5553 
   5554   const UniqueSet<Map>* maps() const { return maps_; }
   5555 
   5556   bool HasEscapingOperandAt(int index) override { return false; }
   5557   bool HasOutOfBoundsAccess(int size) override {
   5558     return !access().IsInobject() || access().offset() >= size;
   5559   }
   5560   Representation RequiredInputRepresentation(int index) override {
   5561     if (index == 0) {
   5562       // object must be external in case of external memory access
   5563       return access().IsExternalMemory() ? Representation::External()
   5564                                          : Representation::Tagged();
   5565     }
   5566     DCHECK(index == 1);
   5567     return Representation::None();
   5568   }
   5569   Range* InferRange(Zone* zone) override;
   5570   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5571 
   5572   bool CanBeReplacedWith(HValue* other) const {
   5573     if (!CheckFlag(HValue::kCantBeReplaced)) return false;
   5574     if (!type().Equals(other->type())) return false;
   5575     if (!representation().Equals(other->representation())) return false;
   5576     if (!other->IsLoadNamedField()) return true;
   5577     HLoadNamedField* that = HLoadNamedField::cast(other);
   5578     if (this->maps_ == that->maps_) return true;
   5579     if (this->maps_ == NULL || that->maps_ == NULL) return false;
   5580     return this->maps_->IsSubset(that->maps_);
   5581   }
   5582 
   5583   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
   5584 
   5585  protected:
   5586   bool DataEquals(HValue* other) override {
   5587     HLoadNamedField* that = HLoadNamedField::cast(other);
   5588     if (!this->access_.Equals(that->access_)) return false;
   5589     if (this->maps_ == that->maps_) return true;
   5590     return (this->maps_ != NULL &&
   5591             that->maps_ != NULL &&
   5592             this->maps_->Equals(that->maps_));
   5593   }
   5594 
   5595  private:
   5596   HLoadNamedField(HValue* object,
   5597                   HValue* dependency,
   5598                   HObjectAccess access)
   5599       : access_(access), maps_(NULL) {
   5600     DCHECK_NOT_NULL(object);
   5601     SetOperandAt(0, object);
   5602     SetOperandAt(1, dependency ? dependency : object);
   5603 
   5604     Representation representation = access.representation();
   5605     if (representation.IsInteger8() ||
   5606         representation.IsUInteger8() ||
   5607         representation.IsInteger16() ||
   5608         representation.IsUInteger16()) {
   5609       set_representation(Representation::Integer32());
   5610     } else if (representation.IsSmi()) {
   5611       set_type(HType::Smi());
   5612       if (SmiValuesAre32Bits()) {
   5613         set_representation(Representation::Integer32());
   5614       } else {
   5615         set_representation(representation);
   5616       }
   5617     } else if (representation.IsDouble() ||
   5618                representation.IsExternal() ||
   5619                representation.IsInteger32()) {
   5620       set_representation(representation);
   5621     } else if (representation.IsHeapObject()) {
   5622       set_type(HType::HeapObject());
   5623       set_representation(Representation::Tagged());
   5624     } else {
   5625       set_representation(Representation::Tagged());
   5626     }
   5627     access.SetGVNFlags(this, LOAD);
   5628   }
   5629 
   5630   HLoadNamedField(HValue* object,
   5631                   HValue* dependency,
   5632                   HObjectAccess access,
   5633                   const UniqueSet<Map>* maps,
   5634                   HType type)
   5635       : HTemplateInstruction<2>(type), access_(access), maps_(maps) {
   5636     DCHECK_NOT_NULL(maps);
   5637     DCHECK_NE(0, maps->size());
   5638 
   5639     DCHECK_NOT_NULL(object);
   5640     SetOperandAt(0, object);
   5641     SetOperandAt(1, dependency ? dependency : object);
   5642 
   5643     DCHECK(access.representation().IsHeapObject());
   5644     DCHECK(type.IsHeapObject());
   5645     set_representation(Representation::Tagged());
   5646 
   5647     access.SetGVNFlags(this, LOAD);
   5648   }
   5649 
   5650   bool IsDeletable() const override { return true; }
   5651 
   5652   HObjectAccess access_;
   5653   const UniqueSet<Map>* maps_;
   5654 };
   5655 
   5656 
   5657 class HLoadFunctionPrototype final : public HUnaryOperation {
   5658  public:
   5659   DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);
   5660 
   5661   HValue* function() { return OperandAt(0); }
   5662 
   5663   Representation RequiredInputRepresentation(int index) override {
   5664     return Representation::Tagged();
   5665   }
   5666 
   5667   DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
   5668 
   5669  protected:
   5670   bool DataEquals(HValue* other) override { return true; }
   5671 
   5672  private:
   5673   explicit HLoadFunctionPrototype(HValue* function)
   5674       : HUnaryOperation(function) {
   5675     set_representation(Representation::Tagged());
   5676     SetFlag(kUseGVN);
   5677     SetDependsOnFlag(kCalls);
   5678   }
   5679 };
   5680 
   5681 class ArrayInstructionInterface {
   5682  public:
   5683   virtual HValue* GetKey() = 0;
   5684   virtual void SetKey(HValue* key) = 0;
   5685   virtual ElementsKind elements_kind() const = 0;
   5686   // TryIncreaseBaseOffset returns false if overflow would result.
   5687   virtual bool TryIncreaseBaseOffset(uint32_t increase_by_value) = 0;
   5688   virtual bool IsDehoisted() const = 0;
   5689   virtual void SetDehoisted(bool is_dehoisted) = 0;
   5690   virtual ~ArrayInstructionInterface() { }
   5691 
   5692   static Representation KeyedAccessIndexRequirement(Representation r) {
   5693     return r.IsInteger32() || SmiValuesAre32Bits()
   5694         ? Representation::Integer32() : Representation::Smi();
   5695   }
   5696 };
   5697 
   5698 
   5699 static const int kDefaultKeyedHeaderOffsetSentinel = -1;
   5700 
   5701 enum LoadKeyedHoleMode {
   5702   NEVER_RETURN_HOLE,
   5703   ALLOW_RETURN_HOLE,
   5704   CONVERT_HOLE_TO_UNDEFINED
   5705 };
   5706 
   5707 
   5708 class HLoadKeyed final : public HTemplateInstruction<4>,
   5709                          public ArrayInstructionInterface {
   5710  public:
   5711   DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
   5712                                  ElementsKind);
   5713   DECLARE_INSTRUCTION_FACTORY_P6(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
   5714                                  ElementsKind, LoadKeyedHoleMode);
   5715   DECLARE_INSTRUCTION_FACTORY_P7(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
   5716                                  ElementsKind, LoadKeyedHoleMode, int);
   5717 
   5718   bool is_fixed_typed_array() const {
   5719     return IsFixedTypedArrayElementsKind(elements_kind());
   5720   }
   5721   HValue* elements() const { return OperandAt(0); }
   5722   HValue* key() const { return OperandAt(1); }
   5723   HValue* dependency() const {
   5724     DCHECK(HasDependency());
   5725     return OperandAt(2);
   5726   }
   5727   bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
   5728   HValue* backing_store_owner() const {
   5729     DCHECK(HasBackingStoreOwner());
   5730     return OperandAt(3);
   5731   }
   5732   bool HasBackingStoreOwner() const { return OperandAt(0) != OperandAt(3); }
   5733   uint32_t base_offset() const { return BaseOffsetField::decode(bit_field_); }
   5734   bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
   5735   HValue* GetKey() override { return key(); }
   5736   void SetKey(HValue* key) override { SetOperandAt(1, key); }
   5737   bool IsDehoisted() const override {
   5738     return IsDehoistedField::decode(bit_field_);
   5739   }
   5740   void SetDehoisted(bool is_dehoisted) override {
   5741     bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
   5742   }
   5743   ElementsKind elements_kind() const override {
   5744     return ElementsKindField::decode(bit_field_);
   5745   }
   5746   LoadKeyedHoleMode hole_mode() const {
   5747     return HoleModeField::decode(bit_field_);
   5748   }
   5749 
   5750   Representation RequiredInputRepresentation(int index) override {
   5751     // kind_fast:                 tagged[int32] (none)
   5752     // kind_double:               tagged[int32] (none)
   5753     // kind_fixed_typed_array:    external[int32] (none)
   5754     // kind_external:             external[int32] (none)
   5755     if (index == 0) {
   5756       return is_fixed_typed_array() ? Representation::External()
   5757                                     : Representation::Tagged();
   5758     }
   5759     if (index == 1) {
   5760       return ArrayInstructionInterface::KeyedAccessIndexRequirement(
   5761           OperandAt(1)->representation());
   5762     }
   5763     if (index == 2) {
   5764       return Representation::None();
   5765     }
   5766     DCHECK_EQ(3, index);
   5767     return HasBackingStoreOwner() ? Representation::Tagged()
   5768                                   : Representation::None();
   5769   }
   5770 
   5771   Representation observed_input_representation(int index) override {
   5772     return RequiredInputRepresentation(index);
   5773   }
   5774 
   5775   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5776 
   5777   bool UsesMustHandleHole() const;
   5778   bool AllUsesCanTreatHoleAsNaN() const;
   5779   bool RequiresHoleCheck() const;
   5780 
   5781   Range* InferRange(Zone* zone) override;
   5782 
   5783   DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)
   5784 
   5785  protected:
   5786   bool DataEquals(HValue* other) override {
   5787     if (!other->IsLoadKeyed()) return false;
   5788     HLoadKeyed* other_load = HLoadKeyed::cast(other);
   5789 
   5790     if (base_offset() != other_load->base_offset()) return false;
   5791     return elements_kind() == other_load->elements_kind();
   5792   }
   5793 
   5794  private:
   5795   HLoadKeyed(HValue* obj, HValue* key, HValue* dependency,
   5796              HValue* backing_store_owner, ElementsKind elements_kind,
   5797              LoadKeyedHoleMode mode = NEVER_RETURN_HOLE,
   5798              int offset = kDefaultKeyedHeaderOffsetSentinel)
   5799       : bit_field_(0) {
   5800     offset = offset == kDefaultKeyedHeaderOffsetSentinel
   5801         ? GetDefaultHeaderSizeForElementsKind(elements_kind)
   5802         : offset;
   5803     bit_field_ = ElementsKindField::encode(elements_kind) |
   5804         HoleModeField::encode(mode) |
   5805         BaseOffsetField::encode(offset);
   5806 
   5807     SetOperandAt(0, obj);
   5808     SetOperandAt(1, key);
   5809     SetOperandAt(2, dependency != nullptr ? dependency : obj);
   5810     SetOperandAt(3, backing_store_owner != nullptr ? backing_store_owner : obj);
   5811     DCHECK_EQ(HasBackingStoreOwner(), is_fixed_typed_array());
   5812 
   5813     if (!is_fixed_typed_array()) {
   5814       // I can detect the case between storing double (holey and fast) and
   5815       // smi/object by looking at elements_kind_.
   5816       DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
   5817              IsFastDoubleElementsKind(elements_kind));
   5818 
   5819       if (IsFastSmiOrObjectElementsKind(elements_kind)) {
   5820         if (IsFastSmiElementsKind(elements_kind) &&
   5821             (!IsHoleyElementsKind(elements_kind) ||
   5822              mode == NEVER_RETURN_HOLE)) {
   5823           set_type(HType::Smi());
   5824           if (SmiValuesAre32Bits() && !RequiresHoleCheck()) {
   5825             set_representation(Representation::Integer32());
   5826           } else {
   5827             set_representation(Representation::Smi());
   5828           }
   5829         } else {
   5830           set_representation(Representation::Tagged());
   5831         }
   5832 
   5833         SetDependsOnFlag(kArrayElements);
   5834       } else {
   5835         set_representation(Representation::Double());
   5836         SetDependsOnFlag(kDoubleArrayElements);
   5837       }
   5838     } else {
   5839       if (elements_kind == FLOAT32_ELEMENTS ||
   5840           elements_kind == FLOAT64_ELEMENTS) {
   5841         set_representation(Representation::Double());
   5842       } else {
   5843         set_representation(Representation::Integer32());
   5844       }
   5845 
   5846       if (is_fixed_typed_array()) {
   5847         SetDependsOnFlag(kExternalMemory);
   5848         SetDependsOnFlag(kTypedArrayElements);
   5849       } else {
   5850         UNREACHABLE();
   5851       }
   5852       // Native code could change the specialized array.
   5853       SetDependsOnFlag(kCalls);
   5854     }
   5855 
   5856     SetFlag(kUseGVN);
   5857   }
   5858 
   5859   bool IsDeletable() const override { return !RequiresHoleCheck(); }
   5860 
   5861   // Establish some checks around our packed fields
   5862   enum LoadKeyedBits {
   5863     kBitsForElementsKind = 5,
   5864     kBitsForHoleMode = 2,
   5865     kBitsForBaseOffset = 24,
   5866     kBitsForIsDehoisted = 1,
   5867 
   5868     kStartElementsKind = 0,
   5869     kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
   5870     kStartBaseOffset = kStartHoleMode + kBitsForHoleMode,
   5871     kStartIsDehoisted = kStartBaseOffset + kBitsForBaseOffset
   5872   };
   5873 
   5874   STATIC_ASSERT((kBitsForElementsKind + kBitsForHoleMode + kBitsForBaseOffset +
   5875                  kBitsForIsDehoisted) <= sizeof(uint32_t) * 8);
   5876   STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
   5877   class ElementsKindField:
   5878     public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
   5879     {};  // NOLINT
   5880   class HoleModeField:
   5881     public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
   5882     {};  // NOLINT
   5883   class BaseOffsetField:
   5884     public BitField<uint32_t, kStartBaseOffset, kBitsForBaseOffset>
   5885     {};  // NOLINT
   5886   class IsDehoistedField:
   5887     public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
   5888     {};  // NOLINT
   5889   uint32_t bit_field_;
   5890 };
   5891 
   5892 
   5893 // Indicates whether the store is a store to an entry that was previously
   5894 // initialized or not.
   5895 enum StoreFieldOrKeyedMode {
   5896   // The entry could be either previously initialized or not.
   5897   INITIALIZING_STORE,
   5898   // At the time of this store it is guaranteed that the entry is already
   5899   // initialized.
   5900   STORE_TO_INITIALIZED_ENTRY
   5901 };
   5902 
   5903 
   5904 class HStoreNamedField final : public HTemplateInstruction<3> {
   5905  public:
   5906   DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
   5907                                  HObjectAccess, HValue*);
   5908   DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue*,
   5909                                  HObjectAccess, HValue*, StoreFieldOrKeyedMode);
   5910 
   5911   DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
   5912 
   5913   bool HasEscapingOperandAt(int index) override { return index == 1; }
   5914   bool HasOutOfBoundsAccess(int size) override {
   5915     return !access().IsInobject() || access().offset() >= size;
   5916   }
   5917   Representation RequiredInputRepresentation(int index) override {
   5918     if (index == 0 && access().IsExternalMemory()) {
   5919       // object must be external in case of external memory access
   5920       return Representation::External();
   5921     } else if (index == 1) {
   5922       if (field_representation().IsInteger8() ||
   5923           field_representation().IsUInteger8() ||
   5924           field_representation().IsInteger16() ||
   5925           field_representation().IsUInteger16() ||
   5926           field_representation().IsInteger32()) {
   5927         return Representation::Integer32();
   5928       } else if (field_representation().IsDouble()) {
   5929         return field_representation();
   5930       } else if (field_representation().IsSmi()) {
   5931         if (SmiValuesAre32Bits() &&
   5932             store_mode() == STORE_TO_INITIALIZED_ENTRY) {
   5933           return Representation::Integer32();
   5934         }
   5935         return field_representation();
   5936       } else if (field_representation().IsExternal()) {
   5937         return Representation::External();
   5938       }
   5939     }
   5940     return Representation::Tagged();
   5941   }
   5942   bool HandleSideEffectDominator(GVNFlag side_effect,
   5943                                  HValue* dominator) override {
   5944     DCHECK(side_effect == kNewSpacePromotion);
   5945     if (!FLAG_use_write_barrier_elimination) return false;
   5946     dominator_ = dominator;
   5947     return false;
   5948   }
   5949   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   5950 
   5951   HValue* object() const { return OperandAt(0); }
   5952   HValue* value() const { return OperandAt(1); }
   5953   HValue* transition() const { return OperandAt(2); }
   5954 
   5955   HObjectAccess access() const { return access_; }
   5956   HValue* dominator() const { return dominator_; }
   5957   bool has_transition() const { return HasTransitionField::decode(bit_field_); }
   5958   StoreFieldOrKeyedMode store_mode() const {
   5959     return StoreModeField::decode(bit_field_);
   5960   }
   5961 
   5962   Handle<Map> transition_map() const {
   5963     if (has_transition()) {
   5964       return Handle<Map>::cast(
   5965           HConstant::cast(transition())->handle(isolate()));
   5966     } else {
   5967       return Handle<Map>();
   5968     }
   5969   }
   5970 
   5971   void SetTransition(HConstant* transition) {
   5972     DCHECK(!has_transition());  // Only set once.
   5973     SetOperandAt(2, transition);
   5974     bit_field_ = HasTransitionField::update(bit_field_, true);
   5975     SetChangesFlag(kMaps);
   5976   }
   5977 
   5978   bool NeedsWriteBarrier() const {
   5979     DCHECK(!field_representation().IsDouble() ||
   5980            (FLAG_unbox_double_fields && access_.IsInobject()) ||
   5981            !has_transition());
   5982     if (field_representation().IsDouble()) return false;
   5983     if (field_representation().IsSmi()) return false;
   5984     if (field_representation().IsInteger32()) return false;
   5985     if (field_representation().IsExternal()) return false;
   5986     return StoringValueNeedsWriteBarrier(value()) &&
   5987         ReceiverObjectNeedsWriteBarrier(object(), value(), dominator());
   5988   }
   5989 
   5990   bool NeedsWriteBarrierForMap() {
   5991     return ReceiverObjectNeedsWriteBarrier(object(), transition(),
   5992                                            dominator());
   5993   }
   5994 
   5995   SmiCheck SmiCheckForWriteBarrier() const {
   5996     if (field_representation().IsHeapObject()) return OMIT_SMI_CHECK;
   5997     if (value()->type().IsHeapObject()) return OMIT_SMI_CHECK;
   5998     return INLINE_SMI_CHECK;
   5999   }
   6000 
   6001   PointersToHereCheck PointersToHereCheckForValue() const {
   6002     return PointersToHereCheckForObject(value(), dominator());
   6003   }
   6004 
   6005   Representation field_representation() const {
   6006     return access_.representation();
   6007   }
   6008 
   6009   void UpdateValue(HValue* value) {
   6010     SetOperandAt(1, value);
   6011   }
   6012 
   6013   bool CanBeReplacedWith(HStoreNamedField* that) const {
   6014     if (!this->access().Equals(that->access())) return false;
   6015     if (SmiValuesAre32Bits() &&
   6016         this->field_representation().IsSmi() &&
   6017         this->store_mode() == INITIALIZING_STORE &&
   6018         that->store_mode() == STORE_TO_INITIALIZED_ENTRY) {
   6019       // We cannot replace an initializing store to a smi field with a store to
   6020       // an initialized entry on 64-bit architectures (with 32-bit smis).
   6021       return false;
   6022     }
   6023     return true;
   6024   }
   6025 
   6026  private:
   6027   HStoreNamedField(HValue* obj, HObjectAccess access, HValue* val,
   6028                    StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
   6029       : access_(access),
   6030         dominator_(NULL),
   6031         bit_field_(HasTransitionField::encode(false) |
   6032                    StoreModeField::encode(store_mode)) {
   6033     // Stores to a non existing in-object property are allowed only to the
   6034     // newly allocated objects (via HAllocate or HInnerAllocatedObject).
   6035     DCHECK(!access.IsInobject() || access.existing_inobject_property() ||
   6036            obj->IsAllocate() || obj->IsInnerAllocatedObject());
   6037     SetOperandAt(0, obj);
   6038     SetOperandAt(1, val);
   6039     SetOperandAt(2, obj);
   6040     access.SetGVNFlags(this, STORE);
   6041   }
   6042 
   6043   class HasTransitionField : public BitField<bool, 0, 1> {};
   6044   class StoreModeField : public BitField<StoreFieldOrKeyedMode, 1, 1> {};
   6045 
   6046   HObjectAccess access_;
   6047   HValue* dominator_;
   6048   uint32_t bit_field_;
   6049 };
   6050 
   6051 class HStoreKeyed final : public HTemplateInstruction<4>,
   6052                           public ArrayInstructionInterface {
   6053  public:
   6054   DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*,
   6055                                  HValue*, ElementsKind);
   6056   DECLARE_INSTRUCTION_FACTORY_P6(HStoreKeyed, HValue*, HValue*, HValue*,
   6057                                  HValue*, ElementsKind, StoreFieldOrKeyedMode);
   6058   DECLARE_INSTRUCTION_FACTORY_P7(HStoreKeyed, HValue*, HValue*, HValue*,
   6059                                  HValue*, ElementsKind, StoreFieldOrKeyedMode,
   6060                                  int);
   6061 
   6062   Representation RequiredInputRepresentation(int index) override {
   6063     // kind_fast:               tagged[int32] = tagged
   6064     // kind_double:             tagged[int32] = double
   6065     // kind_smi   :             tagged[int32] = smi
   6066     // kind_fixed_typed_array:  tagged[int32] = (double | int32)
   6067     // kind_external:           external[int32] = (double | int32)
   6068     if (index == 0) {
   6069       return is_fixed_typed_array() ? Representation::External()
   6070                                     : Representation::Tagged();
   6071     } else if (index == 1) {
   6072       return ArrayInstructionInterface::KeyedAccessIndexRequirement(
   6073           OperandAt(1)->representation());
   6074     } else if (index == 2) {
   6075       return RequiredValueRepresentation(elements_kind(), store_mode());
   6076     }
   6077 
   6078     DCHECK_EQ(3, index);
   6079     return HasBackingStoreOwner() ? Representation::Tagged()
   6080                                   : Representation::None();
   6081   }
   6082 
   6083   static Representation RequiredValueRepresentation(
   6084       ElementsKind kind, StoreFieldOrKeyedMode mode) {
   6085     if (IsDoubleOrFloatElementsKind(kind)) {
   6086       return Representation::Double();
   6087     }
   6088 
   6089     if (kind == FAST_SMI_ELEMENTS && SmiValuesAre32Bits() &&
   6090         mode == STORE_TO_INITIALIZED_ENTRY) {
   6091       return Representation::Integer32();
   6092     }
   6093 
   6094     if (IsFastSmiElementsKind(kind)) {
   6095       return Representation::Smi();
   6096     }
   6097 
   6098     if (IsFixedTypedArrayElementsKind(kind)) {
   6099       return Representation::Integer32();
   6100     }
   6101     return Representation::Tagged();
   6102   }
   6103 
   6104   bool is_fixed_typed_array() const {
   6105     return IsFixedTypedArrayElementsKind(elements_kind());
   6106   }
   6107 
   6108   Representation observed_input_representation(int index) override {
   6109     if (index != 2) return RequiredInputRepresentation(index);
   6110     if (IsUninitialized()) {
   6111       return Representation::None();
   6112     }
   6113     Representation r =
   6114         RequiredValueRepresentation(elements_kind(), store_mode());
   6115     // For fast object elements kinds, don't assume anything.
   6116     if (r.IsTagged()) return Representation::None();
   6117     return r;
   6118   }
   6119 
   6120   HValue* elements() const { return OperandAt(0); }
   6121   HValue* key() const { return OperandAt(1); }
   6122   HValue* value() const { return OperandAt(2); }
   6123   HValue* backing_store_owner() const {
   6124     DCHECK(HasBackingStoreOwner());
   6125     return OperandAt(3);
   6126   }
   6127   bool HasBackingStoreOwner() const { return OperandAt(0) != OperandAt(3); }
   6128   bool value_is_smi() const { return IsFastSmiElementsKind(elements_kind()); }
   6129   StoreFieldOrKeyedMode store_mode() const {
   6130     return StoreModeField::decode(bit_field_);
   6131   }
   6132   ElementsKind elements_kind() const override {
   6133     return ElementsKindField::decode(bit_field_);
   6134   }
   6135   uint32_t base_offset() const { return base_offset_; }
   6136   bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
   6137   HValue* GetKey() override { return key(); }
   6138   void SetKey(HValue* key) override { SetOperandAt(1, key); }
   6139   bool IsDehoisted() const override {
   6140     return IsDehoistedField::decode(bit_field_);
   6141   }
   6142   void SetDehoisted(bool is_dehoisted) override {
   6143     bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
   6144   }
   6145   bool IsUninitialized() { return IsUninitializedField::decode(bit_field_); }
   6146   void SetUninitialized(bool is_uninitialized) {
   6147     bit_field_ = IsUninitializedField::update(bit_field_, is_uninitialized);
   6148   }
   6149 
   6150   bool IsConstantHoleStore() {
   6151     return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
   6152   }
   6153 
   6154   bool HandleSideEffectDominator(GVNFlag side_effect,
   6155                                  HValue* dominator) override {
   6156     DCHECK(side_effect == kNewSpacePromotion);
   6157     dominator_ = dominator;
   6158     return false;
   6159   }
   6160 
   6161   HValue* dominator() const { return dominator_; }
   6162 
   6163   bool NeedsWriteBarrier() {
   6164     if (value_is_smi()) {
   6165       return false;
   6166     } else {
   6167       return StoringValueNeedsWriteBarrier(value()) &&
   6168           ReceiverObjectNeedsWriteBarrier(elements(), value(), dominator());
   6169     }
   6170   }
   6171 
   6172   PointersToHereCheck PointersToHereCheckForValue() const {
   6173     return PointersToHereCheckForObject(value(), dominator());
   6174   }
   6175 
   6176   bool NeedsCanonicalization();
   6177 
   6178   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6179 
   6180   DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
   6181 
   6182  private:
   6183   HStoreKeyed(HValue* obj, HValue* key, HValue* val,
   6184               HValue* backing_store_owner, ElementsKind elements_kind,
   6185               StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE,
   6186               int offset = kDefaultKeyedHeaderOffsetSentinel)
   6187       : base_offset_(offset == kDefaultKeyedHeaderOffsetSentinel
   6188                          ? GetDefaultHeaderSizeForElementsKind(elements_kind)
   6189                          : offset),
   6190         bit_field_(IsDehoistedField::encode(false) |
   6191                    IsUninitializedField::encode(false) |
   6192                    StoreModeField::encode(store_mode) |
   6193                    ElementsKindField::encode(elements_kind)),
   6194         dominator_(NULL) {
   6195     SetOperandAt(0, obj);
   6196     SetOperandAt(1, key);
   6197     SetOperandAt(2, val);
   6198     SetOperandAt(3, backing_store_owner != nullptr ? backing_store_owner : obj);
   6199     DCHECK_EQ(HasBackingStoreOwner(), is_fixed_typed_array());
   6200 
   6201     if (IsFastObjectElementsKind(elements_kind)) {
   6202       SetFlag(kTrackSideEffectDominators);
   6203       SetDependsOnFlag(kNewSpacePromotion);
   6204     }
   6205     if (IsFastDoubleElementsKind(elements_kind)) {
   6206       SetChangesFlag(kDoubleArrayElements);
   6207     } else if (IsFastSmiElementsKind(elements_kind)) {
   6208       SetChangesFlag(kArrayElements);
   6209     } else if (is_fixed_typed_array()) {
   6210       SetChangesFlag(kTypedArrayElements);
   6211       SetChangesFlag(kExternalMemory);
   6212       SetFlag(kTruncatingToNumber);
   6213     } else {
   6214       SetChangesFlag(kArrayElements);
   6215     }
   6216 
   6217     // {UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
   6218     if (elements_kind >= UINT8_ELEMENTS && elements_kind <= INT32_ELEMENTS) {
   6219       SetFlag(kTruncatingToInt32);
   6220     }
   6221   }
   6222 
   6223   class IsDehoistedField : public BitField<bool, 0, 1> {};
   6224   class IsUninitializedField : public BitField<bool, 1, 1> {};
   6225   class StoreModeField : public BitField<StoreFieldOrKeyedMode, 2, 1> {};
   6226   class ElementsKindField : public BitField<ElementsKind, 3, 5> {};
   6227 
   6228   uint32_t base_offset_;
   6229   uint32_t bit_field_;
   6230   HValue* dominator_;
   6231 };
   6232 
   6233 class HTransitionElementsKind final : public HTemplateInstruction<2> {
   6234  public:
   6235   inline static HTransitionElementsKind* New(Isolate* isolate, Zone* zone,
   6236                                              HValue* context, HValue* object,
   6237                                              Handle<Map> original_map,
   6238                                              Handle<Map> transitioned_map) {
   6239     return new(zone) HTransitionElementsKind(context, object,
   6240                                              original_map, transitioned_map);
   6241   }
   6242 
   6243   Representation RequiredInputRepresentation(int index) override {
   6244     return Representation::Tagged();
   6245   }
   6246 
   6247   HValue* object() const { return OperandAt(0); }
   6248   HValue* context() const { return OperandAt(1); }
   6249   Unique<Map> original_map() const { return original_map_; }
   6250   Unique<Map> transitioned_map() const { return transitioned_map_; }
   6251   ElementsKind from_kind() const {
   6252     return FromElementsKindField::decode(bit_field_);
   6253   }
   6254   ElementsKind to_kind() const {
   6255     return ToElementsKindField::decode(bit_field_);
   6256   }
   6257   bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }
   6258 
   6259   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6260 
   6261   DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
   6262 
   6263  protected:
   6264   bool DataEquals(HValue* other) override {
   6265     HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
   6266     return original_map_ == instr->original_map_ &&
   6267            transitioned_map_ == instr->transitioned_map_;
   6268   }
   6269 
   6270   int RedefinedOperandIndex() override { return 0; }
   6271 
   6272  private:
   6273   HTransitionElementsKind(HValue* context, HValue* object,
   6274                           Handle<Map> original_map,
   6275                           Handle<Map> transitioned_map)
   6276       : original_map_(Unique<Map>(original_map)),
   6277         transitioned_map_(Unique<Map>(transitioned_map)),
   6278         bit_field_(
   6279             FromElementsKindField::encode(original_map->elements_kind()) |
   6280             ToElementsKindField::encode(transitioned_map->elements_kind()) |
   6281             MapIsStableField::encode(transitioned_map->is_stable())) {
   6282     SetOperandAt(0, object);
   6283     SetOperandAt(1, context);
   6284     SetFlag(kUseGVN);
   6285     SetChangesFlag(kElementsKind);
   6286     if (!IsSimpleMapChangeTransition(from_kind(), to_kind())) {
   6287       SetChangesFlag(kElementsPointer);
   6288       SetChangesFlag(kNewSpacePromotion);
   6289     }
   6290     set_representation(Representation::Tagged());
   6291   }
   6292 
   6293   class FromElementsKindField : public BitField<ElementsKind, 0, 5> {};
   6294   class ToElementsKindField : public BitField<ElementsKind, 5, 5> {};
   6295   class MapIsStableField : public BitField<bool, 10, 1> {};
   6296 
   6297   Unique<Map> original_map_;
   6298   Unique<Map> transitioned_map_;
   6299   uint32_t bit_field_;
   6300 };
   6301 
   6302 
   6303 class HStringAdd final : public HBinaryOperation {
   6304  public:
   6305   static HInstruction* New(
   6306       Isolate* isolate, Zone* zone, HValue* context, HValue* left,
   6307       HValue* right, PretenureFlag pretenure_flag = NOT_TENURED,
   6308       StringAddFlags flags = STRING_ADD_CHECK_BOTH,
   6309       Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null());
   6310 
   6311   StringAddFlags flags() const { return flags_; }
   6312   PretenureFlag pretenure_flag() const { return pretenure_flag_; }
   6313 
   6314   Representation RequiredInputRepresentation(int index) override {
   6315     return Representation::Tagged();
   6316   }
   6317 
   6318   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6319 
   6320   DECLARE_CONCRETE_INSTRUCTION(StringAdd)
   6321 
   6322  protected:
   6323   bool DataEquals(HValue* other) override {
   6324     return flags_ == HStringAdd::cast(other)->flags_ &&
   6325         pretenure_flag_ == HStringAdd::cast(other)->pretenure_flag_;
   6326   }
   6327 
   6328  private:
   6329   HStringAdd(HValue* context, HValue* left, HValue* right,
   6330              PretenureFlag pretenure_flag, StringAddFlags flags,
   6331              Handle<AllocationSite> allocation_site)
   6332       : HBinaryOperation(context, left, right, HType::String()),
   6333         flags_(flags),
   6334         pretenure_flag_(pretenure_flag) {
   6335     set_representation(Representation::Tagged());
   6336     if ((flags & STRING_ADD_CONVERT) == STRING_ADD_CONVERT) {
   6337       SetAllSideEffects();
   6338       ClearFlag(kUseGVN);
   6339     } else {
   6340       SetChangesFlag(kNewSpacePromotion);
   6341       SetFlag(kUseGVN);
   6342     }
   6343     SetDependsOnFlag(kMaps);
   6344     if (FLAG_trace_pretenuring) {
   6345       PrintF("HStringAdd with AllocationSite %p %s\n",
   6346              allocation_site.is_null()
   6347                  ? static_cast<void*>(NULL)
   6348                  : static_cast<void*>(*allocation_site),
   6349              pretenure_flag == TENURED ? "tenured" : "not tenured");
   6350     }
   6351   }
   6352 
   6353   bool IsDeletable() const final {
   6354     return (flags_ & STRING_ADD_CONVERT) != STRING_ADD_CONVERT;
   6355   }
   6356 
   6357   const StringAddFlags flags_;
   6358   const PretenureFlag pretenure_flag_;
   6359 };
   6360 
   6361 
   6362 class HStringCharCodeAt final : public HTemplateInstruction<3> {
   6363  public:
   6364   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HStringCharCodeAt,
   6365                                               HValue*,
   6366                                               HValue*);
   6367 
   6368   Representation RequiredInputRepresentation(int index) override {
   6369     // The index is supposed to be Integer32.
   6370     return index == 2
   6371         ? Representation::Integer32()
   6372         : Representation::Tagged();
   6373   }
   6374 
   6375   HValue* context() const { return OperandAt(0); }
   6376   HValue* string() const { return OperandAt(1); }
   6377   HValue* index() const { return OperandAt(2); }
   6378 
   6379   DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
   6380 
   6381  protected:
   6382   bool DataEquals(HValue* other) override { return true; }
   6383 
   6384   Range* InferRange(Zone* zone) override {
   6385     return new(zone) Range(0, String::kMaxUtf16CodeUnit);
   6386   }
   6387 
   6388  private:
   6389   HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
   6390     SetOperandAt(0, context);
   6391     SetOperandAt(1, string);
   6392     SetOperandAt(2, index);
   6393     set_representation(Representation::Integer32());
   6394     SetFlag(kUseGVN);
   6395     SetDependsOnFlag(kMaps);
   6396     SetDependsOnFlag(kStringChars);
   6397     SetChangesFlag(kNewSpacePromotion);
   6398   }
   6399 
   6400   // No side effects: runtime function assumes string + number inputs.
   6401   bool IsDeletable() const override { return true; }
   6402 };
   6403 
   6404 
   6405 class HStringCharFromCode final : public HTemplateInstruction<2> {
   6406  public:
   6407   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   6408                            HValue* char_code);
   6409 
   6410   Representation RequiredInputRepresentation(int index) override {
   6411     return index == 0
   6412         ? Representation::Tagged()
   6413         : Representation::Integer32();
   6414   }
   6415 
   6416   HValue* context() const { return OperandAt(0); }
   6417   HValue* value() const { return OperandAt(1); }
   6418 
   6419   bool DataEquals(HValue* other) override { return true; }
   6420 
   6421   DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
   6422 
   6423  private:
   6424   HStringCharFromCode(HValue* context, HValue* char_code)
   6425       : HTemplateInstruction<2>(HType::String()) {
   6426     SetOperandAt(0, context);
   6427     SetOperandAt(1, char_code);
   6428     set_representation(Representation::Tagged());
   6429     SetFlag(kUseGVN);
   6430     SetChangesFlag(kNewSpacePromotion);
   6431   }
   6432 
   6433   bool IsDeletable() const override {
   6434     return !value()->ToNumberCanBeObserved();
   6435   }
   6436 };
   6437 
   6438 
   6439 class HTypeof final : public HTemplateInstruction<2> {
   6440  public:
   6441   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HTypeof, HValue*);
   6442 
   6443   HValue* context() const { return OperandAt(0); }
   6444   HValue* value() const { return OperandAt(1); }
   6445 
   6446   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6447 
   6448   Representation RequiredInputRepresentation(int index) override {
   6449     return Representation::Tagged();
   6450   }
   6451 
   6452   DECLARE_CONCRETE_INSTRUCTION(Typeof)
   6453 
   6454  private:
   6455   explicit HTypeof(HValue* context, HValue* value) {
   6456     SetOperandAt(0, context);
   6457     SetOperandAt(1, value);
   6458     set_representation(Representation::Tagged());
   6459   }
   6460 
   6461   bool IsDeletable() const override { return true; }
   6462 };
   6463 
   6464 
   6465 class HTrapAllocationMemento final : public HTemplateInstruction<1> {
   6466  public:
   6467   DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
   6468 
   6469   Representation RequiredInputRepresentation(int index) override {
   6470     return Representation::Tagged();
   6471   }
   6472 
   6473   HValue* object() { return OperandAt(0); }
   6474 
   6475   DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
   6476 
   6477  private:
   6478   explicit HTrapAllocationMemento(HValue* obj) {
   6479     SetOperandAt(0, obj);
   6480   }
   6481 };
   6482 
   6483 
   6484 class HMaybeGrowElements final : public HTemplateInstruction<5> {
   6485  public:
   6486   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(HMaybeGrowElements, HValue*,
   6487                                               HValue*, HValue*, HValue*, bool,
   6488                                               ElementsKind);
   6489 
   6490   Representation RequiredInputRepresentation(int index) override {
   6491     if (index < 3) {
   6492       return Representation::Tagged();
   6493     }
   6494     DCHECK(index == 3 || index == 4);
   6495     return Representation::Integer32();
   6496   }
   6497 
   6498   HValue* context() const { return OperandAt(0); }
   6499   HValue* object() const { return OperandAt(1); }
   6500   HValue* elements() const { return OperandAt(2); }
   6501   HValue* key() const { return OperandAt(3); }
   6502   HValue* current_capacity() const { return OperandAt(4); }
   6503 
   6504   bool is_js_array() const { return is_js_array_; }
   6505   ElementsKind kind() const { return kind_; }
   6506 
   6507   DECLARE_CONCRETE_INSTRUCTION(MaybeGrowElements)
   6508 
   6509  protected:
   6510   bool DataEquals(HValue* other) override { return true; }
   6511 
   6512  private:
   6513   explicit HMaybeGrowElements(HValue* context, HValue* object, HValue* elements,
   6514                               HValue* key, HValue* current_capacity,
   6515                               bool is_js_array, ElementsKind kind) {
   6516     is_js_array_ = is_js_array;
   6517     kind_ = kind;
   6518 
   6519     SetOperandAt(0, context);
   6520     SetOperandAt(1, object);
   6521     SetOperandAt(2, elements);
   6522     SetOperandAt(3, key);
   6523     SetOperandAt(4, current_capacity);
   6524 
   6525     SetFlag(kUseGVN);
   6526     SetChangesFlag(kElementsPointer);
   6527     SetChangesFlag(kNewSpacePromotion);
   6528     set_representation(Representation::Tagged());
   6529   }
   6530 
   6531   bool is_js_array_;
   6532   ElementsKind kind_;
   6533 };
   6534 
   6535 
   6536 class HSeqStringGetChar final : public HTemplateInstruction<2> {
   6537  public:
   6538   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
   6539                            String::Encoding encoding, HValue* string,
   6540                            HValue* index);
   6541 
   6542   Representation RequiredInputRepresentation(int index) override {
   6543     return (index == 0) ? Representation::Tagged()
   6544                         : Representation::Integer32();
   6545   }
   6546 
   6547   String::Encoding encoding() const { return encoding_; }
   6548   HValue* string() const { return OperandAt(0); }
   6549   HValue* index() const { return OperandAt(1); }
   6550 
   6551   DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)
   6552 
   6553  protected:
   6554   bool DataEquals(HValue* other) override {
   6555     return encoding() == HSeqStringGetChar::cast(other)->encoding();
   6556   }
   6557 
   6558   Range* InferRange(Zone* zone) override {
   6559     if (encoding() == String::ONE_BYTE_ENCODING) {
   6560       return new(zone) Range(0, String::kMaxOneByteCharCode);
   6561     } else {
   6562       DCHECK_EQ(String::TWO_BYTE_ENCODING, encoding());
   6563       return  new(zone) Range(0, String::kMaxUtf16CodeUnit);
   6564     }
   6565   }
   6566 
   6567  private:
   6568   HSeqStringGetChar(String::Encoding encoding,
   6569                     HValue* string,
   6570                     HValue* index) : encoding_(encoding) {
   6571     SetOperandAt(0, string);
   6572     SetOperandAt(1, index);
   6573     set_representation(Representation::Integer32());
   6574     SetFlag(kUseGVN);
   6575     SetDependsOnFlag(kStringChars);
   6576   }
   6577 
   6578   bool IsDeletable() const override { return true; }
   6579 
   6580   String::Encoding encoding_;
   6581 };
   6582 
   6583 
   6584 class HSeqStringSetChar final : public HTemplateInstruction<4> {
   6585  public:
   6586   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(
   6587       HSeqStringSetChar, String::Encoding,
   6588       HValue*, HValue*, HValue*);
   6589 
   6590   String::Encoding encoding() { return encoding_; }
   6591   HValue* context() { return OperandAt(0); }
   6592   HValue* string() { return OperandAt(1); }
   6593   HValue* index() { return OperandAt(2); }
   6594   HValue* value() { return OperandAt(3); }
   6595 
   6596   Representation RequiredInputRepresentation(int index) override {
   6597     return (index <= 1) ? Representation::Tagged()
   6598                         : Representation::Integer32();
   6599   }
   6600 
   6601   DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
   6602 
   6603  private:
   6604   HSeqStringSetChar(HValue* context,
   6605                     String::Encoding encoding,
   6606                     HValue* string,
   6607                     HValue* index,
   6608                     HValue* value) : encoding_(encoding) {
   6609     SetOperandAt(0, context);
   6610     SetOperandAt(1, string);
   6611     SetOperandAt(2, index);
   6612     SetOperandAt(3, value);
   6613     set_representation(Representation::Tagged());
   6614     SetChangesFlag(kStringChars);
   6615   }
   6616 
   6617   String::Encoding encoding_;
   6618 };
   6619 
   6620 
   6621 class HCheckMapValue final : public HTemplateInstruction<2> {
   6622  public:
   6623   DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);
   6624 
   6625   Representation RequiredInputRepresentation(int index) override {
   6626     return Representation::Tagged();
   6627   }
   6628 
   6629   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6630 
   6631   HType CalculateInferredType() override {
   6632     if (value()->type().IsHeapObject()) return value()->type();
   6633     return HType::HeapObject();
   6634   }
   6635 
   6636   HValue* value() const { return OperandAt(0); }
   6637   HValue* map() const { return OperandAt(1); }
   6638 
   6639   HValue* Canonicalize() override;
   6640 
   6641   DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
   6642 
   6643  protected:
   6644   int RedefinedOperandIndex() override { return 0; }
   6645 
   6646   bool DataEquals(HValue* other) override { return true; }
   6647 
   6648  private:
   6649   HCheckMapValue(HValue* value, HValue* map)
   6650       : HTemplateInstruction<2>(HType::HeapObject()) {
   6651     SetOperandAt(0, value);
   6652     SetOperandAt(1, map);
   6653     set_representation(Representation::Tagged());
   6654     SetFlag(kUseGVN);
   6655     SetDependsOnFlag(kMaps);
   6656     SetDependsOnFlag(kElementsKind);
   6657   }
   6658 };
   6659 
   6660 
   6661 class HForInPrepareMap final : public HTemplateInstruction<2> {
   6662  public:
   6663   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HForInPrepareMap, HValue*);
   6664 
   6665   Representation RequiredInputRepresentation(int index) override {
   6666     return Representation::Tagged();
   6667   }
   6668 
   6669   HValue* context() const { return OperandAt(0); }
   6670   HValue* enumerable() const { return OperandAt(1); }
   6671 
   6672   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6673 
   6674   HType CalculateInferredType() override { return HType::Tagged(); }
   6675 
   6676   DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
   6677 
   6678  private:
   6679   HForInPrepareMap(HValue* context,
   6680                    HValue* object) {
   6681     SetOperandAt(0, context);
   6682     SetOperandAt(1, object);
   6683     set_representation(Representation::Tagged());
   6684     SetAllSideEffects();
   6685   }
   6686 };
   6687 
   6688 
   6689 class HForInCacheArray final : public HTemplateInstruction<2> {
   6690  public:
   6691   DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
   6692 
   6693   Representation RequiredInputRepresentation(int index) override {
   6694     return Representation::Tagged();
   6695   }
   6696 
   6697   HValue* enumerable() const { return OperandAt(0); }
   6698   HValue* map() const { return OperandAt(1); }
   6699   int idx() const { return idx_; }
   6700 
   6701   HForInCacheArray* index_cache() {
   6702     return index_cache_;
   6703   }
   6704 
   6705   void set_index_cache(HForInCacheArray* index_cache) {
   6706     index_cache_ = index_cache;
   6707   }
   6708 
   6709   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6710 
   6711   HType CalculateInferredType() override { return HType::Tagged(); }
   6712 
   6713   DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
   6714 
   6715  private:
   6716   HForInCacheArray(HValue* enumerable,
   6717                    HValue* keys,
   6718                    int idx) : idx_(idx) {
   6719     SetOperandAt(0, enumerable);
   6720     SetOperandAt(1, keys);
   6721     set_representation(Representation::Tagged());
   6722   }
   6723 
   6724   int idx_;
   6725   HForInCacheArray* index_cache_;
   6726 };
   6727 
   6728 
   6729 class HLoadFieldByIndex final : public HTemplateInstruction<2> {
   6730  public:
   6731   DECLARE_INSTRUCTION_FACTORY_P2(HLoadFieldByIndex, HValue*, HValue*);
   6732 
   6733   HLoadFieldByIndex(HValue* object,
   6734                     HValue* index) {
   6735     SetOperandAt(0, object);
   6736     SetOperandAt(1, index);
   6737     SetChangesFlag(kNewSpacePromotion);
   6738     set_representation(Representation::Tagged());
   6739   }
   6740 
   6741   Representation RequiredInputRepresentation(int index) override {
   6742     if (index == 1) {
   6743       return Representation::Smi();
   6744     } else {
   6745       return Representation::Tagged();
   6746     }
   6747   }
   6748 
   6749   HValue* object() const { return OperandAt(0); }
   6750   HValue* index() const { return OperandAt(1); }
   6751 
   6752   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
   6753 
   6754   HType CalculateInferredType() override { return HType::Tagged(); }
   6755 
   6756   DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
   6757 
   6758  private:
   6759   bool IsDeletable() const override { return true; }
   6760 };
   6761 
   6762 #undef DECLARE_INSTRUCTION
   6763 #undef DECLARE_CONCRETE_INSTRUCTION
   6764 
   6765 }  // namespace internal
   6766 }  // namespace v8
   6767 
   6768 #endif  // V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_
   6769