// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_
#define V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_

#include <cstring>
#include <iosfwd>

#include "src/allocation.h"
#include "src/base/bits.h"
#include "src/bit-vector.h"
#include "src/code-stubs.h"
#include "src/conversions.h"
#include "src/crankshaft/hydrogen-types.h"
#include "src/crankshaft/unique.h"
#include "src/deoptimizer.h"
#include "src/small-pointer-list.h"
#include "src/utils.h"
#include "src/zone.h"

namespace v8 {
namespace internal {

// Forward declarations.
struct ChangesOf;
class HBasicBlock;
class HDiv;
class HEnvironment;
class HInferRepresentationPhase;
class HInstruction;
class HLoopInformation;
class HStoreNamedField;
class HValue;
class LInstruction;
class LChunkBuilder;

#define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V) \
  V(ArithmeticBinaryOperation)                \
  V(BinaryOperation)                          \
  V(BitwiseBinaryOperation)                   \
  V(ControlInstruction)                       \
  V(Instruction)


#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
  V(AbnormalExit)                             \
  V(AccessArgumentsAt)                        \
  V(Add)                                      \
  V(Allocate)                                 \
  V(ApplyArguments)                           \
  V(ArgumentsElements)                        \
  V(ArgumentsLength)                          \
  V(ArgumentsObject)                          \
  V(Bitwise)                                  \
  V(BlockEntry)                               \
  V(BoundsCheck)                              \
  V(Branch)                                   \
  V(CallWithDescriptor)                       \
  V(CallNewArray)                             \
  V(CallRuntime)                              \
  V(CapturedObject)                           \
  V(Change)                                   \
  V(CheckArrayBufferNotNeutered)              \
  V(CheckHeapObject)                          \
  V(CheckInstanceType)                        \
  V(CheckMaps)                                \
  V(CheckMapValue)                            \
  V(CheckSmi)                                 \
  V(CheckValue)                               \
  V(ClampToUint8)                             \
  V(ClassOfTestAndBranch)                     \
  V(CompareNumericAndBranch)                  \
  V(CompareHoleAndBranch)                     \
  V(CompareGeneric)                           \
  V(CompareObjectEqAndBranch)                 \
  V(CompareMap)                               \
  V(Constant)                                 \
  V(ConstructDouble)                          \
  V(Context)                                  \
  V(DebugBreak)                               \
  V(DeclareGlobals)                           \
  V(Deoptimize)                               \
  V(Div)                                      \
  V(DoubleBits)                               \
  V(DummyUse)                                 \
  V(EnterInlined)                             \
  V(EnvironmentMarker)                        \
  V(ForceRepresentation)                      \
  V(ForInCacheArray)                          \
  V(ForInPrepareMap)                          \
  V(GetCachedArrayIndex)                      \
  V(Goto)                                     \
  V(HasCachedArrayIndexAndBranch)             \
  V(HasInstanceTypeAndBranch)                 \
  V(InnerAllocatedObject)                     \
  V(InstanceOf)                               \
  V(InvokeFunction)                           \
  V(HasInPrototypeChainAndBranch)             \
  V(IsStringAndBranch)                        \
  V(IsSmiAndBranch)                           \
  V(IsUndetectableAndBranch)                  \
  V(LeaveInlined)                             \
  V(LoadContextSlot)                          \
  V(LoadFieldByIndex)                         \
  V(LoadFunctionPrototype)                    \
  V(LoadGlobalGeneric)                        \
  V(LoadKeyed)                                \
  V(LoadKeyedGeneric)                         \
  V(LoadNamedField)                           \
  V(LoadNamedGeneric)                         \
  V(LoadRoot)                                 \
  V(MathFloorOfDiv)                           \
  V(MathMinMax)                               \
  V(MaybeGrowElements)                        \
  V(Mod)                                      \
  V(Mul)                                      \
  V(OsrEntry)                                 \
  V(Parameter)                                \
  V(Power)                                    \
  V(Prologue)                                 \
  V(PushArguments)                            \
  V(Return)                                   \
  V(Ror)                                      \
  V(Sar)                                      \
  V(SeqStringGetChar)                         \
  V(SeqStringSetChar)                         \
  V(Shl)                                      \
  V(Shr)                                      \
  V(Simulate)                                 \
  V(StackCheck)                               \
  V(StoreCodeEntry)                           \
  V(StoreContextSlot)                         \
  V(StoreKeyed)                               \
  V(StoreKeyedGeneric)                        \
  V(StoreNamedField)                          \
  V(StoreNamedGeneric)                        \
  V(StringAdd)                                \
  V(StringCharCodeAt)                         \
  V(StringCharFromCode)                       \
  V(StringCompareAndBranch)                   \
  V(Sub)                                      \
  V(ThisFunction)                             \
  V(TransitionElementsKind)                   \
  V(TrapAllocationMemento)                    \
  V(Typeof)                                   \
  V(TypeofIsAndBranch)                        \
  V(UnaryMathOperation)                       \
  V(UnknownOSRValue)                          \
  V(UseConst)                                 \
  V(WrapReceiver)

#define GVN_TRACKED_FLAG_LIST(V)               \
  V(NewSpacePromotion)

#define GVN_UNTRACKED_FLAG_LIST(V)             \
  V(ArrayElements)                             \
  V(ArrayLengths)                              \
  V(StringLengths)                             \
  V(BackingStoreFields)                        \
  V(Calls)                                     \
  V(ContextSlots)                              \
  V(DoubleArrayElements)                       \
  V(DoubleFields)                              \
  V(ElementsKind)                              \
  V(ElementsPointer)                           \
  V(GlobalVars)                                \
  V(InobjectFields)                            \
  V(Maps)                                      \
  V(OsrEntries)                                \
  V(ExternalMemory)                            \
  V(StringChars)                               \
  V(TypedArrayElements)


#define DECLARE_ABSTRACT_INSTRUCTION(type)     \
  bool Is##type() const final { return true; } \
  static H##type* cast(HValue* value) {        \
    DCHECK(value->Is##type());                 \
    return reinterpret_cast<H##type*>(value);  \
  }


#define DECLARE_CONCRETE_INSTRUCTION(type)                      \
  LInstruction* CompileToLithium(LChunkBuilder* builder) final; \
  static H##type* cast(HValue* value) {                         \
    DCHECK(value->Is##type());                                  \
    return reinterpret_cast<H##type*>(value);                   \
  }                                                             \
  Opcode opcode() const final { return HValue::k##type; }


enum PropertyAccessType { LOAD, STORE };


class Range final : public ZoneObject {
 public:
  Range()
      : lower_(kMinInt),
        upper_(kMaxInt),
        next_(NULL),
        can_be_minus_zero_(false) { }

  Range(int32_t lower, int32_t upper)
      : lower_(lower),
        upper_(upper),
        next_(NULL),
        can_be_minus_zero_(false) { }

  int32_t upper() const { return upper_; }
  int32_t lower() const { return lower_; }
  Range* next() const { return next_; }
  Range* CopyClearLower(Zone* zone) const {
    return new(zone) Range(kMinInt, upper_);
  }
  Range* CopyClearUpper(Zone* zone) const {
    return new(zone) Range(lower_, kMaxInt);
  }
  Range* Copy(Zone* zone) const {
    Range* result = new(zone) Range(lower_, upper_);
    result->set_can_be_minus_zero(CanBeMinusZero());
    return result;
  }
  int32_t Mask() const;
  void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
  bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
  bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
  bool CanBeNegative() const { return lower_ < 0; }
  bool CanBePositive() const { return upper_ > 0; }
  bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
  bool IsMostGeneric() const {
    return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
  }
  bool IsInSmiRange() const {
    return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
  }
  void ClampToSmi() {
    lower_ = Max(lower_, Smi::kMinValue);
    upper_ = Min(upper_, Smi::kMaxValue);
  }
  void KeepOrder();
#ifdef DEBUG
  void Verify() const;
#endif

  void StackUpon(Range* other) {
    Intersect(other);
    next_ = other;
  }

  void Intersect(Range* other);
  void Union(Range* other);
  void CombinedMax(Range* other);
  void CombinedMin(Range* other);

  void AddConstant(int32_t value);
  void Sar(int32_t value);
  void Shl(int32_t value);
  bool AddAndCheckOverflow(const Representation& r, Range* other);
  bool SubAndCheckOverflow(const Representation& r, Range* other);
  bool MulAndCheckOverflow(const Representation& r, Range* other);

 private:
  int32_t lower_;
  int32_t upper_;
  Range* next_;
  bool can_be_minus_zero_;
};


class HUseListNode: public ZoneObject {
 public:
  HUseListNode(HValue* value, int index, HUseListNode* tail)
      : tail_(tail), value_(value), index_(index) {
  }

  HUseListNode* tail();
  HValue* value() const { return value_; }
  int index() const { return index_; }

  void set_tail(HUseListNode* list) { tail_ = list; }

#ifdef DEBUG
  void Zap() {
    tail_ = reinterpret_cast<HUseListNode*>(1);
    value_ = NULL;
    index_ = -1;
  }
#endif

 private:
  HUseListNode* tail_;
  HValue* value_;
  int index_;
};


// We reuse use list nodes behind the scenes as uses are added and deleted.
// This class is the safe way to iterate uses while deleting them.
class HUseIterator final BASE_EMBEDDED {
 public:
  bool Done() { return current_ == NULL; }
  void Advance();

  HValue* value() {
    DCHECK(!Done());
    return value_;
  }

  int index() {
    DCHECK(!Done());
    return index_;
  }

 private:
  explicit HUseIterator(HUseListNode* head);

  HUseListNode* current_;
  HUseListNode* next_;
  HValue* value_;
  int index_;

  friend class HValue;
};


// All tracked flags should appear before untracked ones.
enum GVNFlag {
  // Declare global value numbering flags.
#define DECLARE_FLAG(Type) k##Type,
  GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
  GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
#undef DECLARE_FLAG
#define COUNT_FLAG(Type) + 1
  kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG),
  kNumberOfUntrackedSideEffects = 0 GVN_UNTRACKED_FLAG_LIST(COUNT_FLAG),
#undef COUNT_FLAG
  kNumberOfFlags = kNumberOfTrackedSideEffects + kNumberOfUntrackedSideEffects
};


static inline GVNFlag GVNFlagFromInt(int i) {
  DCHECK(i >= 0);
  DCHECK(i < kNumberOfFlags);
  return static_cast<GVNFlag>(i);
}


class DecompositionResult final BASE_EMBEDDED {
 public:
  DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}

  HValue* base() { return base_; }
  int offset() { return offset_; }
  int scale() { return scale_; }

  bool Apply(HValue* other_base, int other_offset, int other_scale = 0) {
    if (base_ == NULL) {
      base_ = other_base;
      offset_ = other_offset;
      scale_ = other_scale;
      return true;
    } else {
      if (scale_ == 0) {
        base_ = other_base;
        offset_ += other_offset;
        scale_ = other_scale;
        return true;
      } else {
        return false;
      }
    }
  }

  void SwapValues(HValue** other_base, int* other_offset, int* other_scale) {
    swap(&base_, other_base);
    swap(&offset_, other_offset);
    swap(&scale_, other_scale);
  }

 private:
  template <class T> void swap(T* a, T* b) {
    T c(*a);
    *a = *b;
    *b = c;
  }

  HValue* base_;
  int offset_;
  int scale_;
};


typedef EnumSet<GVNFlag, int32_t> GVNFlagSet;


class HValue : public ZoneObject {
 public:
  static const int kNoNumber = -1;

  enum Flag {
    kFlexibleRepresentation,
    kCannotBeTagged,
    // Participate in Global Value Numbering, i.e. elimination of
    // unnecessary recomputations. If an instruction sets this flag, it must
    // implement DataEquals(), which will be used to determine if other
    // occurrences of the instruction are indeed the same.
    kUseGVN,
    // Track instructions that are dominating side effects. If an instruction
    // sets this flag, it must implement HandleSideEffectDominator() and should
    // indicate which side effects to track by setting GVN flags.
    kTrackSideEffectDominators,
    kCanOverflow,
    kBailoutOnMinusZero,
    kCanBeDivByZero,
    kLeftCanBeMinInt,
    kLeftCanBeNegative,
    kLeftCanBePositive,
    kAllowUndefinedAsNaN,
    kIsArguments,
    kTruncatingToInt32,
    kAllUsesTruncatingToInt32,
    kTruncatingToSmi,
    kAllUsesTruncatingToSmi,
    // Set after an instruction is killed.
    kIsDead,
    // Instructions that are allowed to produce full range unsigned integer
    // values are marked with kUint32 flag. If arithmetic shift or a load from
    // EXTERNAL_UINT32_ELEMENTS array is not marked with this flag
    // it will deoptimize if result does not fit into signed integer range.
    // HGraph::ComputeSafeUint32Operations is responsible for setting this
    // flag.
    kUint32,
    kHasNoObservableSideEffects,
    // Indicates an instruction shouldn't be replaced by optimization, this flag
    // is useful to set in cases where recomputing a value is cheaper than
    // extending the value's live range and spilling it.
    kCantBeReplaced,
    // Indicates the instruction is live during dead code elimination.
    kIsLive,

    // HEnvironmentMarkers are deleted before dead code
    // elimination takes place, so they can repurpose the kIsLive flag:
    kEndsLiveRange = kIsLive,

    // TODO(everyone): Don't forget to update this!
    kLastFlag = kIsLive
  };

  STATIC_ASSERT(kLastFlag < kBitsPerInt);

  static HValue* cast(HValue* value) { return value; }

  enum Opcode {
    // Declare a unique enum value for each hydrogen instruction.
  #define DECLARE_OPCODE(type) k##type,
    HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
    kPhi
  #undef DECLARE_OPCODE
  };
  virtual Opcode opcode() const = 0;

  // Declare a non-virtual predicates for each concrete HInstruction or HValue.
  #define DECLARE_PREDICATE(type) \
    bool Is##type() const { return opcode() == k##type; }
    HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
  #undef DECLARE_PREDICATE
    bool IsPhi() const { return opcode() == kPhi; }

  // Declare virtual predicates for abstract HInstruction or HValue
  #define DECLARE_PREDICATE(type) \
    virtual bool Is##type() const { return false; }
    HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
  #undef DECLARE_PREDICATE

  bool IsBitwiseBinaryShift() {
    return IsShl() || IsShr() || IsSar();
  }

  explicit HValue(HType type = HType::Tagged())
      : block_(NULL),
        id_(kNoNumber),
        type_(type),
        use_list_(NULL),
        range_(NULL),
#ifdef DEBUG
        range_poisoned_(false),
#endif
        flags_(0) {}
  virtual ~HValue() {}

  virtual SourcePosition position() const { return SourcePosition::Unknown(); }
  virtual SourcePosition operand_position(int index) const {
    return position();
  }

  HBasicBlock* block() const { return block_; }
  void SetBlock(HBasicBlock* block);

  // Note: Never call this method for an unlinked value.
  Isolate* isolate() const;

  int id() const { return id_; }
  void set_id(int id) { id_ = id; }

  HUseIterator uses() const { return HUseIterator(use_list_); }

  virtual bool EmitAtUses() { return false; }

  Representation representation() const { return representation_; }
  void ChangeRepresentation(Representation r) {
    DCHECK(CheckFlag(kFlexibleRepresentation));
    DCHECK(!CheckFlag(kCannotBeTagged) || !r.IsTagged());
    RepresentationChanged(r);
    representation_ = r;
    if (r.IsTagged()) {
      // Tagged is the bottom of the lattice, don't go any further.
      ClearFlag(kFlexibleRepresentation);
    }
  }
  virtual void AssumeRepresentation(Representation r);

  virtual Representation KnownOptimalRepresentation() {
    Representation r = representation();
    if (r.IsTagged()) {
      HType t = type();
      if (t.IsSmi()) return Representation::Smi();
      if (t.IsHeapNumber()) return Representation::Double();
      if (t.IsHeapObject()) return r;
      return Representation::None();
    }
    return r;
  }

  HType type() const { return type_; }
  void set_type(HType new_type) {
    DCHECK(new_type.IsSubtypeOf(type_));
    type_ = new_type;
  }

  // There are HInstructions that do not really change a value, they
  // only add pieces of information to it (like bounds checks, map checks,
  // smi checks...).
  // We call these instructions "informative definitions", or "iDef".
  // One of the iDef operands is special because it is the value that is
  // "transferred" to the output, we call it the "redefined operand".
  // If an HValue is an iDef it must override RedefinedOperandIndex() so that
  // it does not return kNoRedefinedOperand;
  static const int kNoRedefinedOperand = -1;
  virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
  bool IsInformativeDefinition() {
    return RedefinedOperandIndex() != kNoRedefinedOperand;
  }
  HValue* RedefinedOperand() {
    int index = RedefinedOperandIndex();
    return index == kNoRedefinedOperand ? NULL : OperandAt(index);
  }

  bool CanReplaceWithDummyUses();

  virtual int argument_delta() const { return 0; }

  // A purely informative definition is an idef that will not emit code and
  // should therefore be removed from the graph in the RestoreActualValues
  // phase (so that live ranges will be shorter).
  virtual bool IsPurelyInformativeDefinition() { return false; }

  // This method must always return the original HValue SSA definition,
  // regardless of any chain of iDefs of this value.
  HValue* ActualValue() {
    HValue* value = this;
    int index;
    while ((index = value->RedefinedOperandIndex()) != kNoRedefinedOperand) {
      value = value->OperandAt(index);
    }
    return value;
  }

  bool IsInteger32Constant();
  int32_t GetInteger32Constant();
  bool EqualsInteger32Constant(int32_t value);

  bool IsDefinedAfter(HBasicBlock* other) const;

  // Operands.
  virtual int OperandCount() const = 0;
  virtual HValue* OperandAt(int index) const = 0;
  void SetOperandAt(int index, HValue* value);

  void DeleteAndReplaceWith(HValue* other);
  void ReplaceAllUsesWith(HValue* other);
  bool HasNoUses() const { return use_list_ == NULL; }
  bool HasOneUse() const {
    return use_list_ != NULL && use_list_->tail() == NULL;
  }
  bool HasMultipleUses() const {
    return use_list_ != NULL && use_list_->tail() != NULL;
  }
  int UseCount() const;

  // Mark this HValue as dead and to be removed from other HValues' use lists.
  void Kill();

  int flags() const { return flags_; }
  void SetFlag(Flag f) { flags_ |= (1 << f); }
  void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
  bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
  void CopyFlag(Flag f, HValue* other) {
    if (other->CheckFlag(f)) SetFlag(f);
  }

  // Returns true if the flag specified is set for all uses, false otherwise.
  bool CheckUsesForFlag(Flag f) const;
  // Same as before and the first one without the flag is returned in value.
  bool CheckUsesForFlag(Flag f, HValue** value) const;
  // Returns true if the flag specified is set for all uses, and this set
  // of uses is non-empty.
  bool HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const;

  GVNFlagSet ChangesFlags() const { return changes_flags_; }
  GVNFlagSet DependsOnFlags() const { return depends_on_flags_; }
  void SetChangesFlag(GVNFlag f) { changes_flags_.Add(f); }
  void SetDependsOnFlag(GVNFlag f) { depends_on_flags_.Add(f); }
  void ClearChangesFlag(GVNFlag f) { changes_flags_.Remove(f); }
  void ClearDependsOnFlag(GVNFlag f) { depends_on_flags_.Remove(f); }
  bool CheckChangesFlag(GVNFlag f) const {
    return changes_flags_.Contains(f);
  }
  bool CheckDependsOnFlag(GVNFlag f) const {
    return depends_on_flags_.Contains(f);
  }
  void SetAllSideEffects() { changes_flags_.Add(AllSideEffectsFlagSet()); }
  void ClearAllSideEffects() {
    changes_flags_.Remove(AllSideEffectsFlagSet());
  }
  bool HasSideEffects() const {
    return changes_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
  }
  bool HasObservableSideEffects() const {
    return !CheckFlag(kHasNoObservableSideEffects) &&
        changes_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
  }

  GVNFlagSet SideEffectFlags() const {
    GVNFlagSet result = ChangesFlags();
    result.Intersect(AllSideEffectsFlagSet());
    return result;
  }

  GVNFlagSet ObservableChangesFlags() const {
    GVNFlagSet result = ChangesFlags();
    result.Intersect(AllObservableSideEffectsFlagSet());
    return result;
  }

  Range* range() const {
    DCHECK(!range_poisoned_);
    return range_;
  }
  bool HasRange() const {
    DCHECK(!range_poisoned_);
    return range_ != NULL;
  }
#ifdef DEBUG
  void PoisonRange() { range_poisoned_ = true; }
#endif
  void AddNewRange(Range* r, Zone* zone);
  void RemoveLastAddedRange();
  void ComputeInitialRange(Zone* zone);

  // Escape analysis helpers.
  virtual bool HasEscapingOperandAt(int index) { return true; }
  virtual bool HasOutOfBoundsAccess(int size) { return false; }

  // Representation helpers.
  virtual Representation observed_input_representation(int index) {
    return Representation::None();
  }
  virtual Representation RequiredInputRepresentation(int index) = 0;
  virtual void InferRepresentation(HInferRepresentationPhase* h_infer);

  // This gives the instruction an opportunity to replace itself with an
  // instruction that does the same in some better way.  To replace an
  // instruction with a new one, first add the new instruction to the graph,
  // then return it.  Return NULL to have the instruction deleted.
  virtual HValue* Canonicalize() { return this; }

  bool Equals(HValue* other);
  virtual intptr_t Hashcode();

  // Compute unique ids upfront that is safe wrt GC and concurrent compilation.
  virtual void FinalizeUniqueness() { }

  // Printing support.
  virtual std::ostream& PrintTo(std::ostream& os) const = 0;  // NOLINT

  const char* Mnemonic() const;

  // Type information helpers.
  bool HasMonomorphicJSObjectType();

  // TODO(mstarzinger): For now instructions can override this function to
  // specify statically known types, once HType can convey more information
  // it should be based on the HType.
  virtual Handle<Map> GetMonomorphicJSObjectMap() { return Handle<Map>(); }

  // Updated the inferred type of this instruction and returns true if
  // it has changed.
  bool UpdateInferredType();

  virtual HType CalculateInferredType();

  // This function must be overridden for instructions which have the
  // kTrackSideEffectDominators flag set, to track instructions that are
  // dominating side effects.
  // It returns true if it removed an instruction which had side effects.
  virtual bool HandleSideEffectDominator(GVNFlag side_effect,
                                         HValue* dominator) {
    UNREACHABLE();
    return false;
  }

  // Check if this instruction has some reason that prevents elimination.
  bool CannotBeEliminated() const {
    return HasObservableSideEffects() || !IsDeletable();
  }

#ifdef DEBUG
  virtual void Verify() = 0;
#endif

  // Returns true conservatively if the program might be able to observe a
  // ToString() operation on this value.
  bool ToStringCanBeObserved() const {
    return ToStringOrToNumberCanBeObserved();
  }

  // Returns true conservatively if the program might be able to observe a
  // ToNumber() operation on this value.
  bool ToNumberCanBeObserved() const {
    return ToStringOrToNumberCanBeObserved();
  }

  MinusZeroMode GetMinusZeroMode() {
    return CheckFlag(kBailoutOnMinusZero)
        ? FAIL_ON_MINUS_ZERO : TREAT_MINUS_ZERO_AS_ZERO;
  }

 protected:
  // This function must be overridden for instructions with flag kUseGVN, to
  // compare the non-Operand parts of the instruction.
  virtual bool DataEquals(HValue* other) {
    UNREACHABLE();
    return false;
  }

  bool ToStringOrToNumberCanBeObserved() const {
    if (type().IsTaggedPrimitive()) return false;
    if (type().IsJSReceiver()) return true;
    return !representation().IsSmiOrInteger32() && !representation().IsDouble();
  }

  virtual Representation RepresentationFromInputs() {
    return representation();
  }
  virtual Representation RepresentationFromUses();
  Representation RepresentationFromUseRequirements();
  bool HasNonSmiUse();
  virtual void UpdateRepresentation(Representation new_rep,
                                    HInferRepresentationPhase* h_infer,
                                    const char* reason);
  void AddDependantsToWorklist(HInferRepresentationPhase* h_infer);

  virtual void RepresentationChanged(Representation to) { }

  virtual Range* InferRange(Zone* zone);
  virtual void DeleteFromGraph() = 0;
  virtual void InternalSetOperandAt(int index, HValue* value) = 0;
  void clear_block() {
    DCHECK(block_ != NULL);
    block_ = NULL;
  }

  void set_representation(Representation r) {
    DCHECK(representation_.IsNone() && !r.IsNone());
    representation_ = r;
  }

  static GVNFlagSet AllFlagSet() {
    GVNFlagSet result;
#define ADD_FLAG(Type) result.Add(k##Type);
  GVN_TRACKED_FLAG_LIST(ADD_FLAG)
  GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
#undef ADD_FLAG
    return result;
  }

  // A flag mask to mark an instruction as having arbitrary side effects.
  static GVNFlagSet AllSideEffectsFlagSet() {
    GVNFlagSet result = AllFlagSet();
    result.Remove(kOsrEntries);
    return result;
  }
  friend std::ostream& operator<<(std::ostream& os, const ChangesOf& v);

  // A flag mask of all side effects that can make observable changes in
  // an executing program (i.e. are not safe to repeat, move or remove);
  static GVNFlagSet AllObservableSideEffectsFlagSet() {
    GVNFlagSet result = AllFlagSet();
    result.Remove(kNewSpacePromotion);
    result.Remove(kElementsKind);
    result.Remove(kElementsPointer);
    result.Remove(kMaps);
    return result;
  }

  // Remove the matching use from the use list if present.  Returns the
  // removed list node or NULL.
  HUseListNode* RemoveUse(HValue* value, int index);

  void RegisterUse(int index, HValue* new_value);

  HBasicBlock* block_;

  // The id of this instruction in the hydrogen graph, assigned when first
  // added to the graph. Reflects creation order.
  int id_;

  Representation representation_;
  HType type_;
  HUseListNode* use_list_;
  Range* range_;
#ifdef DEBUG
  bool range_poisoned_;
#endif
  int flags_;
  GVNFlagSet changes_flags_;
  GVNFlagSet depends_on_flags_;

 private:
  virtual bool IsDeletable() const { return false; }

  DISALLOW_COPY_AND_ASSIGN(HValue);
};

// Support for printing various aspects of an HValue.
struct NameOf {
  explicit NameOf(const HValue* const v) : value(v) {}
  const HValue* value;
};


struct TypeOf {
  explicit TypeOf(const HValue* const v) : value(v) {}
  const HValue* value;
};


struct ChangesOf {
  explicit ChangesOf(const HValue* const v) : value(v) {}
  const HValue* value;
};


std::ostream& operator<<(std::ostream& os, const HValue& v);
std::ostream& operator<<(std::ostream& os, const NameOf& v);
std::ostream& operator<<(std::ostream& os, const TypeOf& v);
std::ostream& operator<<(std::ostream& os, const ChangesOf& v);


#define DECLARE_INSTRUCTION_FACTORY_P0(I)                        \
  static I* New(Isolate* isolate, Zone* zone, HValue* context) { \
    return new (zone) I();                                       \
  }

#define DECLARE_INSTRUCTION_FACTORY_P1(I, P1)                           \
  static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1) { \
    return new (zone) I(p1);                                            \
  }

#define DECLARE_INSTRUCTION_FACTORY_P2(I, P1, P2)                              \
  static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2) { \
    return new (zone) I(p1, p2);                                               \
  }

#define DECLARE_INSTRUCTION_FACTORY_P3(I, P1, P2, P3)                        \
  static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
                P3 p3) {                                                     \
    return new (zone) I(p1, p2, p3);                                         \
  }

#define DECLARE_INSTRUCTION_FACTORY_P4(I, P1, P2, P3, P4)                    \
  static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
                P3 p3, P4 p4) {                                              \
    return new (zone) I(p1, p2, p3, p4);                                     \
  }

#define DECLARE_INSTRUCTION_FACTORY_P5(I, P1, P2, P3, P4, P5)                \
  static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
                P3 p3, P4 p4, P5 p5) {                                       \
    return new (zone) I(p1, p2, p3, p4, p5);                                 \
  }

#define DECLARE_INSTRUCTION_FACTORY_P6(I, P1, P2, P3, P4, P5, P6)            \
  static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
                P3 p3, P4 p4, P5 p5, P6 p6) {                                \
    return new (zone) I(p1, p2, p3, p4, p5, p6);                             \
  }

#define DECLARE_INSTRUCTION_FACTORY_P7(I, P1, P2, P3, P4, P5, P6, P7)        \
  static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
                P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {                         \
    return new (zone) I(p1, p2, p3, p4, p5, p6, p7);                         \
  }

#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(I)           \
  static I* New(Isolate* isolate, Zone* zone, HValue* context) { \
    return new (zone) I(context);                                \
  }

#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(I, P1)              \
  static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1) { \
    return new (zone) I(context, p1);                                   \
  }

#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(I, P1, P2)                 \
  static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2) { \
    return new (zone) I(context, p1, p2);                                      \
  }

#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(I, P1, P2, P3)           \
  static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
                P3 p3) {                                                     \
    return new (zone) I(context, p1, p2, p3);                                \
  }

#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(I, P1, P2, P3, P4)       \
  static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
                P3 p3, P4 p4) {                                              \
    return new (zone) I(context, p1, p2, p3, p4);                            \
  }

#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(I, P1, P2, P3, P4, P5)   \
  static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
                P3 p3, P4 p4, P5 p5) {                                       \
    return new (zone) I(context, p1, p2, p3, p4, p5);                        \
  }

#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(I, P1, P2, P3, P4, P5, P6) \
  static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2,   \
                P3 p3, P4 p4, P5 p5, P6 p6) {                                  \
    return new (zone) I(context, p1, p2, p3, p4, p5, p6);                      \
  }


// A helper class to represent per-operand position information attached to
// the HInstruction in the compact form. Uses tagging to distinguish between
// case when only instruction's position is available and case when operands'
// positions are also available.
// In the first case it contains intruction's position as a tagged value.
// In the second case it points to an array which contains instruction's
// position and operands' positions.
class HPositionInfo {
 public:
  explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { }

  SourcePosition position() const {
    if (has_operand_positions()) {
      return operand_positions()[kInstructionPosIndex];
    }
    return SourcePosition::FromRaw(static_cast<int>(UntagPosition(data_)));
  }

  void set_position(SourcePosition pos) {
    if (has_operand_positions()) {
      operand_positions()[kInstructionPosIndex] = pos;
    } else {
      data_ = TagPosition(pos.raw());
    }
  }

  void ensure_storage_for_operand_positions(Zone* zone, int operand_count) {
    if (has_operand_positions()) {
      return;
    }

    const int length = kFirstOperandPosIndex + operand_count;
    SourcePosition* positions = zone->NewArray<SourcePosition>(length);
    for (int i = 0; i < length; i++) {
      positions[i] = SourcePosition::Unknown();
    }

    const SourcePosition pos = position();
    data_ = reinterpret_cast<intptr_t>(positions);
    set_position(pos);

    DCHECK(has_operand_positions());
  }

  SourcePosition operand_position(int idx) const {
    if (!has_operand_positions()) {
      return position();
    }
    return *operand_position_slot(idx);
  }

  void set_operand_position(int idx, SourcePosition pos) {
    *operand_position_slot(idx) = pos;
  }

 private:
  static const intptr_t kInstructionPosIndex = 0;
  static const intptr_t kFirstOperandPosIndex = 1;

  SourcePosition* operand_position_slot(int idx) const {
    DCHECK(has_operand_positions());
    return &(operand_positions()[kFirstOperandPosIndex + idx]);
  }

  bool has_operand_positions() const {
    return !IsTaggedPosition(data_);
  }

  SourcePosition* operand_positions() const {
    DCHECK(has_operand_positions());
    return reinterpret_cast<SourcePosition*>(data_);
  }

  static const intptr_t kPositionTag = 1;
  static const intptr_t kPositionShift = 1;
  static bool IsTaggedPosition(intptr_t val) {
    return (val & kPositionTag) != 0;
  }
  static intptr_t UntagPosition(intptr_t val) {
    DCHECK(IsTaggedPosition(val));
    return val >> kPositionShift;
  }
  static intptr_t TagPosition(intptr_t val) {
    const intptr_t result = (val << kPositionShift) | kPositionTag;
    DCHECK(UntagPosition(result) == val);
    return result;
  }

  intptr_t data_;
};


class HInstruction : public HValue {
 public:
  HInstruction* next() const { return next_; }
  HInstruction* previous() const { return previous_; }

  std::ostream& PrintTo(std::ostream& os) const override;          // NOLINT
  virtual std::ostream& PrintDataTo(std::ostream& os) const;       // NOLINT

  bool IsLinked() const { return block() != NULL; }
  void Unlink();

  void InsertBefore(HInstruction* next);

  template<class T> T* Prepend(T* instr) {
    instr->InsertBefore(this);
    return instr;
  }

  void InsertAfter(HInstruction* previous);

  template<class T> T* Append(T* instr) {
    instr->InsertAfter(this);
    return instr;
  }

  // The position is a write-once variable.
  SourcePosition position() const override {
    return SourcePosition(position_.position());
  }
  bool has_position() const {
    return !position().IsUnknown();
  }
  void set_position(SourcePosition position) {
    DCHECK(!has_position());
    DCHECK(!position.IsUnknown());
    position_.set_position(position);
  }

  SourcePosition operand_position(int index) const override {
    const SourcePosition pos = position_.operand_position(index);
    return pos.IsUnknown() ? position() : pos;
  }
  void set_operand_position(Zone* zone, int index, SourcePosition pos) {
    DCHECK(0 <= index && index < OperandCount());
    position_.ensure_storage_for_operand_positions(zone, OperandCount());
    position_.set_operand_position(index, pos);
  }

  bool Dominates(HInstruction* other);
  bool CanTruncateToSmi() const { return CheckFlag(kTruncatingToSmi); }
  bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }

  virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;

#ifdef DEBUG
  void Verify() override;
#endif

  bool CanDeoptimize();

  virtual bool HasStackCheck() { return false; }

  DECLARE_ABSTRACT_INSTRUCTION(Instruction)

 protected:
  explicit HInstruction(HType type = HType::Tagged())
      : HValue(type),
        next_(NULL),
        previous_(NULL),
        position_(RelocInfo::kNoPosition) {
    SetDependsOnFlag(kOsrEntries);
  }

  void DeleteFromGraph() override { Unlink(); }

 private:
  void InitializeAsFirst(HBasicBlock* block) {
    DCHECK(!IsLinked());
    SetBlock(block);
  }

  HInstruction* next_;
  HInstruction* previous_;
  HPositionInfo position_;

  friend class HBasicBlock;
};


template<int V>
class HTemplateInstruction : public HInstruction {
 public:
  int OperandCount() const final { return V; }
  HValue* OperandAt(int i) const final { return inputs_[i]; }

 protected:
  explicit HTemplateInstruction(HType type = HType::Tagged())
      : HInstruction(type) {}

  void InternalSetOperandAt(int i, HValue* value) final { inputs_[i] = value; }

 private:
  EmbeddedContainer<HValue*, V> inputs_;
};


class HControlInstruction : public HInstruction {
 public:
  virtual HBasicBlock* SuccessorAt(int i) const = 0;
  virtual int SuccessorCount() const = 0;
  virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  virtual bool KnownSuccessorBlock(HBasicBlock** block) {
    *block = NULL;
    return false;
  }

  HBasicBlock* FirstSuccessor() {
    return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
  }
  HBasicBlock* SecondSuccessor() {
    return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
  }

  void Not() {
    HBasicBlock* swap = SuccessorAt(0);
    SetSuccessorAt(0, SuccessorAt(1));
    SetSuccessorAt(1, swap);
  }

  DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
};


class HSuccessorIterator final BASE_EMBEDDED {
 public:
  explicit HSuccessorIterator(const HControlInstruction* instr)
      : instr_(instr), current_(0) {}

  bool Done() { return current_ >= instr_->SuccessorCount(); }
  HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
  void Advance() { current_++; }

 private:
  const HControlInstruction* instr_;
  int current_;
};


template<int S, int V>
class HTemplateControlInstruction : public HControlInstruction {
 public:
  int SuccessorCount() const override { return S; }
  HBasicBlock* SuccessorAt(int i) const override { return successors_[i]; }
  void SetSuccessorAt(int i, HBasicBlock* block) override {
    successors_[i] = block;
  }

  int OperandCount() const override { return V; }
  HValue* OperandAt(int i) const override { return inputs_[i]; }


 protected:
  void InternalSetOperandAt(int i, HValue* value) override {
    inputs_[i] = value;
  }

 private:
  EmbeddedContainer<HBasicBlock*, S> successors_;
  EmbeddedContainer<HValue*, V> inputs_;
};


class HBlockEntry final : public HTemplateInstruction<0> {
 public:
  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
};


class HDummyUse final : public HTemplateInstruction<1> {
 public:
  explicit HDummyUse(HValue* value)
      : HTemplateInstruction<1>(HType::Smi()) {
    SetOperandAt(0, value);
    // Pretend to be a Smi so that the HChange instructions inserted
    // before any use generate as little code as possible.
    set_representation(Representation::Tagged());
  }

  HValue* value() const { return OperandAt(0); }

  bool HasEscapingOperandAt(int index) override { return false; }
  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(DummyUse);
};


// Inserts an int3/stop break instruction for debugging purposes.
class HDebugBreak final : public HTemplateInstruction<0> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P0(HDebugBreak);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  DECLARE_CONCRETE_INSTRUCTION(DebugBreak)
};


class HPrologue final : public HTemplateInstruction<0> {
 public:
  static HPrologue* New(Zone* zone) { return new (zone) HPrologue(); }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  DECLARE_CONCRETE_INSTRUCTION(Prologue)
};


class HGoto final : public HTemplateControlInstruction<1, 0> {
 public:
  explicit HGoto(HBasicBlock* target) {
    SetSuccessorAt(0, target);
  }

  bool KnownSuccessorBlock(HBasicBlock** block) override {
    *block = FirstSuccessor();
    return true;
  }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(Goto)
};


class HDeoptimize final : public HTemplateControlInstruction<1, 0> {
 public:
  static HDeoptimize* New(Isolate* isolate, Zone* zone, HValue* context,
                          Deoptimizer::DeoptReason reason,
                          Deoptimizer::BailoutType type,
                          HBasicBlock* unreachable_continuation) {
    return new(zone) HDeoptimize(reason, type, unreachable_continuation);
  }

  bool KnownSuccessorBlock(HBasicBlock** block) override {
    *block = NULL;
    return true;
  }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  Deoptimizer::DeoptReason reason() const { return reason_; }
  Deoptimizer::BailoutType type() { return type_; }

  DECLARE_CONCRETE_INSTRUCTION(Deoptimize)

 private:
  explicit HDeoptimize(Deoptimizer::DeoptReason reason,
                       Deoptimizer::BailoutType type,
                       HBasicBlock* unreachable_continuation)
      : reason_(reason), type_(type) {
    SetSuccessorAt(0, unreachable_continuation);
  }

  Deoptimizer::DeoptReason reason_;
  Deoptimizer::BailoutType type_;
};


class HUnaryControlInstruction : public HTemplateControlInstruction<2, 1> {
 public:
  HUnaryControlInstruction(HValue* value,
                           HBasicBlock* true_target,
                           HBasicBlock* false_target) {
    SetOperandAt(0, value);
    SetSuccessorAt(0, true_target);
    SetSuccessorAt(1, false_target);
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  HValue* value() const { return OperandAt(0); }
};


class HBranch final : public HUnaryControlInstruction {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HBranch, HValue*);
  DECLARE_INSTRUCTION_FACTORY_P2(HBranch, HValue*, ToBooleanICStub::Types);
  DECLARE_INSTRUCTION_FACTORY_P4(HBranch, HValue*, ToBooleanICStub::Types,
                                 HBasicBlock*, HBasicBlock*);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }
  Representation observed_input_representation(int index) override;

  bool KnownSuccessorBlock(HBasicBlock** block) override;

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  ToBooleanICStub::Types expected_input_types() const {
    return expected_input_types_;
  }

  DECLARE_CONCRETE_INSTRUCTION(Branch)

 private:
  HBranch(HValue* value, ToBooleanICStub::Types expected_input_types =
                             ToBooleanICStub::Types(),
          HBasicBlock* true_target = NULL, HBasicBlock* false_target = NULL)
      : HUnaryControlInstruction(value, true_target, false_target),
        expected_input_types_(expected_input_types) {
    SetFlag(kAllowUndefinedAsNaN);
  }

  ToBooleanICStub::Types expected_input_types_;
};


class HCompareMap final : public HUnaryControlInstruction {
 public:
  DECLARE_INSTRUCTION_FACTORY_P2(HCompareMap, HValue*, Handle<Map>);
  DECLARE_INSTRUCTION_FACTORY_P4(HCompareMap, HValue*, Handle<Map>,
                                 HBasicBlock*, HBasicBlock*);

  bool KnownSuccessorBlock(HBasicBlock** block) override {
    if (known_successor_index() != kNoKnownSuccessorIndex) {
      *block = SuccessorAt(known_successor_index());
      return true;
    }
    *block = NULL;
    return false;
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  static const int kNoKnownSuccessorIndex = -1;
  int known_successor_index() const {
    return KnownSuccessorIndexField::decode(bit_field_) -
           kInternalKnownSuccessorOffset;
  }
  void set_known_successor_index(int index) {
    DCHECK(index >= 0 - kInternalKnownSuccessorOffset);
    bit_field_ = KnownSuccessorIndexField::update(
        bit_field_, index + kInternalKnownSuccessorOffset);
  }

  Unique<Map> map() const { return map_; }
  bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  DECLARE_CONCRETE_INSTRUCTION(CompareMap)

 protected:
  int RedefinedOperandIndex() override { return 0; }

 private:
  HCompareMap(HValue* value, Handle<Map> map, HBasicBlock* true_target = NULL,
              HBasicBlock* false_target = NULL)
      : HUnaryControlInstruction(value, true_target, false_target),
        bit_field_(KnownSuccessorIndexField::encode(
                       kNoKnownSuccessorIndex + kInternalKnownSuccessorOffset) |
                   MapIsStableField::encode(map->is_stable())),
        map_(Unique<Map>::CreateImmovable(map)) {
    set_representation(Representation::Tagged());
  }

  // BitFields can only store unsigned values, so use an offset.
  // Adding kInternalKnownSuccessorOffset must yield an unsigned value.
  static const int kInternalKnownSuccessorOffset = 1;
  STATIC_ASSERT(kNoKnownSuccessorIndex + kInternalKnownSuccessorOffset >= 0);

  class KnownSuccessorIndexField : public BitField<int, 0, 31> {};
  class MapIsStableField : public BitField<bool, 31, 1> {};

  uint32_t bit_field_;
  Unique<Map> map_;
};


class HContext final : public HTemplateInstruction<0> {
 public:
  static HContext* New(Zone* zone) {
    return new(zone) HContext();
  }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  DECLARE_CONCRETE_INSTRUCTION(Context)

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  HContext() {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
  }

  bool IsDeletable() const override { return true; }
};


class HReturn final : public HTemplateControlInstruction<0, 3> {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HReturn, HValue*, HValue*);
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HReturn, HValue*);

  Representation RequiredInputRepresentation(int index) override {
    // TODO(titzer): require an Int32 input for faster returns.
    if (index == 2) return Representation::Smi();
    return Representation::Tagged();
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  HValue* value() const { return OperandAt(0); }
  HValue* context() const { return OperandAt(1); }
  HValue* parameter_count() const { return OperandAt(2); }

  DECLARE_CONCRETE_INSTRUCTION(Return)

 private:
  HReturn(HValue* context, HValue* value, HValue* parameter_count = 0) {
    SetOperandAt(0, value);
    SetOperandAt(1, context);
    SetOperandAt(2, parameter_count);
  }
};


class HAbnormalExit final : public HTemplateControlInstruction<0, 0> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P0(HAbnormalExit);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
 private:
  HAbnormalExit() {}
};


class HUnaryOperation : public HTemplateInstruction<1> {
 public:
  explicit HUnaryOperation(HValue* value, HType type = HType::Tagged())
      : HTemplateInstruction<1>(type) {
    SetOperandAt(0, value);
  }

  static HUnaryOperation* cast(HValue* value) {
    return reinterpret_cast<HUnaryOperation*>(value);
  }

  HValue* value() const { return OperandAt(0); }
  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
};


class HUseConst final : public HUnaryOperation {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue*);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  DECLARE_CONCRETE_INSTRUCTION(UseConst)

 private:
    explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
};


class HForceRepresentation final : public HTemplateInstruction<1> {
 public:
  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
                           HValue* value,
                           Representation required_representation);

  HValue* value() const { return OperandAt(0); }

  Representation observed_input_representation(int index) override {
    // We haven't actually *observed* this, but it's closer to the truth
    // than 'None'.
    return representation();  // Same as the output representation.
  }
  Representation RequiredInputRepresentation(int index) override {
    return representation();  // Same as the output representation.
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)

 private:
  HForceRepresentation(HValue* value, Representation required_representation) {
    SetOperandAt(0, value);
    set_representation(required_representation);
  }
};


class HChange final : public HUnaryOperation {
 public:
  HChange(HValue* value,
          Representation to,
          bool is_truncating_to_smi,
          bool is_truncating_to_int32)
      : HUnaryOperation(value) {
    DCHECK(!value->representation().IsNone());
    DCHECK(!to.IsNone());
    DCHECK(!value->representation().Equals(to));
    set_representation(to);
    SetFlag(kUseGVN);
    SetFlag(kCanOverflow);
    if (is_truncating_to_smi && to.IsSmi()) {
      SetFlag(kTruncatingToSmi);
      SetFlag(kTruncatingToInt32);
    }
    if (is_truncating_to_int32) SetFlag(kTruncatingToInt32);
    if (value->representation().IsSmi() || value->type().IsSmi()) {
      set_type(HType::Smi());
    } else {
      set_type(HType::TaggedNumber());
      if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
    }
  }

  bool can_convert_undefined_to_nan() {
    return CheckUsesForFlag(kAllowUndefinedAsNaN);
  }

  HType CalculateInferredType() override;
  HValue* Canonicalize() override;

  Representation from() const { return value()->representation(); }
  Representation to() const { return representation(); }
  bool deoptimize_on_minus_zero() const {
    return CheckFlag(kBailoutOnMinusZero);
  }
  Representation RequiredInputRepresentation(int index) override {
    return from();
  }

  Range* InferRange(Zone* zone) override;

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(Change)

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  bool IsDeletable() const override {
    return !from().IsTagged() || value()->type().IsSmi();
  }
};


class HClampToUint8 final : public HUnaryOperation {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HClampToUint8, HValue*);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  explicit HClampToUint8(HValue* value)
      : HUnaryOperation(value) {
    set_representation(Representation::Integer32());
    SetFlag(kAllowUndefinedAsNaN);
    SetFlag(kUseGVN);
  }

  bool IsDeletable() const override { return true; }
};


class HDoubleBits final : public HUnaryOperation {
 public:
  enum Bits { HIGH, LOW };
  DECLARE_INSTRUCTION_FACTORY_P2(HDoubleBits, HValue*, Bits);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Double();
  }

  DECLARE_CONCRETE_INSTRUCTION(DoubleBits)

  Bits bits() { return bits_; }

 protected:
  bool DataEquals(HValue* other) override {
    return other->IsDoubleBits() && HDoubleBits::cast(other)->bits() == bits();
  }

 private:
  HDoubleBits(HValue* value, Bits bits)
      : HUnaryOperation(value), bits_(bits) {
    set_representation(Representation::Integer32());
    SetFlag(kUseGVN);
  }

  bool IsDeletable() const override { return true; }

  Bits bits_;
};


class HConstructDouble final : public HTemplateInstruction<2> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P2(HConstructDouble, HValue*, HValue*);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Integer32();
  }

  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble)

  HValue* hi() { return OperandAt(0); }
  HValue* lo() { return OperandAt(1); }

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  explicit HConstructDouble(HValue* hi, HValue* lo) {
    set_representation(Representation::Double());
    SetFlag(kUseGVN);
    SetOperandAt(0, hi);
    SetOperandAt(1, lo);
  }

  bool IsDeletable() const override { return true; }
};


enum RemovableSimulate {
  REMOVABLE_SIMULATE,
  FIXED_SIMULATE
};


class HSimulate final : public HInstruction {
 public:
  HSimulate(BailoutId ast_id, int pop_count, Zone* zone,
            RemovableSimulate removable)
      : ast_id_(ast_id),
        pop_count_(pop_count),
        values_(2, zone),
        assigned_indexes_(2, zone),
        zone_(zone),
        bit_field_(RemovableField::encode(removable) |
                   DoneWithReplayField::encode(false)) {}
  ~HSimulate() {}

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  bool HasAstId() const { return !ast_id_.IsNone(); }
  BailoutId ast_id() const { return ast_id_; }
  void set_ast_id(BailoutId id) {
    DCHECK(!HasAstId());
    ast_id_ = id;
  }

  int pop_count() const { return pop_count_; }
  const ZoneList<HValue*>* values() const { return &values_; }
  int GetAssignedIndexAt(int index) const {
    DCHECK(HasAssignedIndexAt(index));
    return assigned_indexes_[index];
  }
  bool HasAssignedIndexAt(int index) const {
    return assigned_indexes_[index] != kNoIndex;
  }
  void AddAssignedValue(int index, HValue* value) {
    AddValue(index, value);
  }
  void AddPushedValue(HValue* value) {
    AddValue(kNoIndex, value);
  }
  int ToOperandIndex(int environment_index) {
    for (int i = 0; i < assigned_indexes_.length(); ++i) {
      if (assigned_indexes_[i] == environment_index) return i;
    }
    return -1;
  }
  int OperandCount() const override { return values_.length(); }
  HValue* OperandAt(int index) const override { return values_[index]; }

  bool HasEscapingOperandAt(int index) override { return false; }
  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  void MergeWith(ZoneList<HSimulate*>* list);
  bool is_candidate_for_removal() {
    return RemovableField::decode(bit_field_) == REMOVABLE_SIMULATE;
  }

  // Replay effects of this instruction on the given environment.
  void ReplayEnvironment(HEnvironment* env);

  DECLARE_CONCRETE_INSTRUCTION(Simulate)

#ifdef DEBUG
  void Verify() override;
  void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
  Handle<JSFunction> closure() const { return closure_; }
#endif

 protected:
  void InternalSetOperandAt(int index, HValue* value) override {
    values_[index] = value;
  }

 private:
  static const int kNoIndex = -1;
  void AddValue(int index, HValue* value) {
    assigned_indexes_.Add(index, zone_);
    // Resize the list of pushed values.
    values_.Add(NULL, zone_);
    // Set the operand through the base method in HValue to make sure that the
    // use lists are correctly updated.
    SetOperandAt(values_.length() - 1, value);
  }
  bool HasValueForIndex(int index) {
    for (int i = 0; i < assigned_indexes_.length(); ++i) {
      if (assigned_indexes_[i] == index) return true;
    }
    return false;
  }
  bool is_done_with_replay() const {
    return DoneWithReplayField::decode(bit_field_);
  }
  void set_done_with_replay() {
    bit_field_ = DoneWithReplayField::update(bit_field_, true);
  }

  class RemovableField : public BitField<RemovableSimulate, 0, 1> {};
  class DoneWithReplayField : public BitField<bool, 1, 1> {};

  BailoutId ast_id_;
  int pop_count_;
  ZoneList<HValue*> values_;
  ZoneList<int> assigned_indexes_;
  Zone* zone_;
  uint32_t bit_field_;

#ifdef DEBUG
  Handle<JSFunction> closure_;
#endif
};


class HEnvironmentMarker final : public HTemplateInstruction<1> {
 public:
  enum Kind { BIND, LOOKUP };

  DECLARE_INSTRUCTION_FACTORY_P2(HEnvironmentMarker, Kind, int);

  Kind kind() const { return kind_; }
  int index() const { return index_; }
  HSimulate* next_simulate() { return next_simulate_; }
  void set_next_simulate(HSimulate* simulate) {
    next_simulate_ = simulate;
  }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

#ifdef DEBUG
  void set_closure(Handle<JSFunction> closure) {
    DCHECK(closure_.is_null());
    DCHECK(!closure.is_null());
    closure_ = closure;
  }
  Handle<JSFunction> closure() const { return closure_; }
#endif

  DECLARE_CONCRETE_INSTRUCTION(EnvironmentMarker);

 private:
  HEnvironmentMarker(Kind kind, int index)
      : kind_(kind), index_(index), next_simulate_(NULL) { }

  Kind kind_;
  int index_;
  HSimulate* next_simulate_;

#ifdef DEBUG
  Handle<JSFunction> closure_;
#endif
};


class HStackCheck final : public HTemplateInstruction<1> {
 public:
  enum Type {
    kFunctionEntry,
    kBackwardsBranch
  };

  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HStackCheck, Type);

  HValue* context() { return OperandAt(0); }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  void Eliminate() {
    // The stack check eliminator might try to eliminate the same stack
    // check instruction multiple times.
    if (IsLinked()) {
      DeleteAndReplaceWith(NULL);
    }
  }

  bool is_function_entry() { return type_ == kFunctionEntry; }
  bool is_backwards_branch() { return type_ == kBackwardsBranch; }

  DECLARE_CONCRETE_INSTRUCTION(StackCheck)

 private:
  HStackCheck(HValue* context, Type type) : type_(type) {
    SetOperandAt(0, context);
    SetChangesFlag(kNewSpacePromotion);
  }

  Type type_;
};


enum InliningKind {
  NORMAL_RETURN,          // Drop the function from the environment on return.
  CONSTRUCT_CALL_RETURN,  // Either use allocated receiver or return value.
  GETTER_CALL_RETURN,     // Returning from a getter, need to restore context.
  SETTER_CALL_RETURN      // Use the RHS of the assignment as the return value.
};


class HArgumentsObject;
class HConstant;


class HEnterInlined final : public HTemplateInstruction<0> {
 public:
  static HEnterInlined* New(Isolate* isolate, Zone* zone, HValue* context,
                            BailoutId return_id, Handle<JSFunction> closure,
                            HConstant* closure_context, int arguments_count,
                            FunctionLiteral* function,
                            InliningKind inlining_kind, Variable* arguments_var,
                            HArgumentsObject* arguments_object,
                            TailCallMode syntactic_tail_call_mode) {
    return new (zone)
        HEnterInlined(return_id, closure, closure_context, arguments_count,
                      function, inlining_kind, arguments_var, arguments_object,
                      syntactic_tail_call_mode, zone);
  }

  void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
  ZoneList<HBasicBlock*>* return_targets() { return &return_targets_; }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  Handle<SharedFunctionInfo> shared() const { return shared_; }
  Handle<JSFunction> closure() const { return closure_; }
  HConstant* closure_context() const { return closure_context_; }
  int arguments_count() const { return arguments_count_; }
  bool arguments_pushed() const { return arguments_pushed_; }
  void set_arguments_pushed() { arguments_pushed_ = true; }
  FunctionLiteral* function() const { return function_; }
  InliningKind inlining_kind() const { return inlining_kind_; }
  TailCallMode syntactic_tail_call_mode() const {
    return syntactic_tail_call_mode_;
  }
  BailoutId ReturnId() const { return return_id_; }
  int inlining_id() const { return inlining_id_; }
  void set_inlining_id(int inlining_id) { inlining_id_ = inlining_id; }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  Variable* arguments_var() { return arguments_var_; }
  HArgumentsObject* arguments_object() { return arguments_object_; }

  DECLARE_CONCRETE_INSTRUCTION(EnterInlined)

 private:
  HEnterInlined(BailoutId return_id, Handle<JSFunction> closure,
                HConstant* closure_context, int arguments_count,
                FunctionLiteral* function, InliningKind inlining_kind,
                Variable* arguments_var, HArgumentsObject* arguments_object,
                TailCallMode syntactic_tail_call_mode, Zone* zone)
      : return_id_(return_id),
        shared_(handle(closure->shared())),
        closure_(closure),
        closure_context_(closure_context),
        arguments_count_(arguments_count),
        arguments_pushed_(false),
        function_(function),
        inlining_kind_(inlining_kind),
        syntactic_tail_call_mode_(syntactic_tail_call_mode),
        inlining_id_(0),
        arguments_var_(arguments_var),
        arguments_object_(arguments_object),
        return_targets_(2, zone) {}

  BailoutId return_id_;
  Handle<SharedFunctionInfo> shared_;
  Handle<JSFunction> closure_;
  HConstant* closure_context_;
  int arguments_count_;
  bool arguments_pushed_;
  FunctionLiteral* function_;
  InliningKind inlining_kind_;
  TailCallMode syntactic_tail_call_mode_;
  int inlining_id_;
  Variable* arguments_var_;
  HArgumentsObject* arguments_object_;
  ZoneList<HBasicBlock*> return_targets_;
};


class HLeaveInlined final : public HTemplateInstruction<0> {
 public:
  HLeaveInlined(HEnterInlined* entry,
                int drop_count)
      : entry_(entry),
        drop_count_(drop_count) { }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  int argument_delta() const override {
    return entry_->arguments_pushed() ? -drop_count_ : 0;
  }

  DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)

 private:
  HEnterInlined* entry_;
  int drop_count_;
};


class HPushArguments final : public HInstruction {
 public:
  static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context) {
    return new(zone) HPushArguments(zone);
  }
  static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
                             HValue* arg1) {
    HPushArguments* instr = new(zone) HPushArguments(zone);
    instr->AddInput(arg1);
    return instr;
  }
  static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
                             HValue* arg1, HValue* arg2) {
    HPushArguments* instr = new(zone) HPushArguments(zone);
    instr->AddInput(arg1);
    instr->AddInput(arg2);
    return instr;
  }
  static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
                             HValue* arg1, HValue* arg2, HValue* arg3) {
    HPushArguments* instr = new(zone) HPushArguments(zone);
    instr->AddInput(arg1);
    instr->AddInput(arg2);
    instr->AddInput(arg3);
    return instr;
  }
  static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
                             HValue* arg1, HValue* arg2, HValue* arg3,
                             HValue* arg4) {
    HPushArguments* instr = new(zone) HPushArguments(zone);
    instr->AddInput(arg1);
    instr->AddInput(arg2);
    instr->AddInput(arg3);
    instr->AddInput(arg4);
    return instr;
  }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  int argument_delta() const override { return inputs_.length(); }
  HValue* argument(int i) { return OperandAt(i); }

  int OperandCount() const final { return inputs_.length(); }
  HValue* OperandAt(int i) const final { return inputs_[i]; }

  void AddInput(HValue* value);

  DECLARE_CONCRETE_INSTRUCTION(PushArguments)

 protected:
  void InternalSetOperandAt(int i, HValue* value) final { inputs_[i] = value; }

 private:
  explicit HPushArguments(Zone* zone)
      : HInstruction(HType::Tagged()), inputs_(4, zone) {
    set_representation(Representation::Tagged());
  }

  ZoneList<HValue*> inputs_;
};


class HThisFunction final : public HTemplateInstruction<0> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P0(HThisFunction);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  DECLARE_CONCRETE_INSTRUCTION(ThisFunction)

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  HThisFunction() {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
  }

  bool IsDeletable() const override { return true; }
};


class HDeclareGlobals final : public HUnaryOperation {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HDeclareGlobals,
                                              Handle<FixedArray>,
                                              int);

  HValue* context() { return OperandAt(0); }
  Handle<FixedArray> pairs() const { return pairs_; }
  int flags() const { return flags_; }

  DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

 private:
  HDeclareGlobals(HValue* context,
                  Handle<FixedArray> pairs,
                  int flags)
      : HUnaryOperation(context),
        pairs_(pairs),
        flags_(flags) {
    set_representation(Representation::Tagged());
    SetAllSideEffects();
  }

  Handle<FixedArray> pairs_;
  int flags_;
};


template <int V>
class HCall : public HTemplateInstruction<V> {
 public:
  // The argument count includes the receiver.
  explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
    this->set_representation(Representation::Tagged());
    this->SetAllSideEffects();
  }

  HType CalculateInferredType() final { return HType::Tagged(); }

  virtual int argument_count() const {
    return argument_count_;
  }

  int argument_delta() const override { return -argument_count(); }

 private:
  int argument_count_;
};


class HUnaryCall : public HCall<1> {
 public:
  HUnaryCall(HValue* value, int argument_count)
      : HCall<1>(argument_count) {
    SetOperandAt(0, value);
  }

  Representation RequiredInputRepresentation(int index) final {
    return Representation::Tagged();
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  HValue* value() const { return OperandAt(0); }
};


class HBinaryCall : public HCall<2> {
 public:
  HBinaryCall(HValue* first, HValue* second, int argument_count)
      : HCall<2>(argument_count) {
    SetOperandAt(0, first);
    SetOperandAt(1, second);
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  Representation RequiredInputRepresentation(int index) final {
    return Representation::Tagged();
  }

  HValue* first() const { return OperandAt(0); }
  HValue* second() const { return OperandAt(1); }
};


class HCallWithDescriptor final : public HInstruction {
 public:
  static HCallWithDescriptor* New(
      Isolate* isolate, Zone* zone, HValue* context, HValue* target,
      int argument_count, CallInterfaceDescriptor descriptor,
      const Vector<HValue*>& operands,
      TailCallMode syntactic_tail_call_mode = TailCallMode::kDisallow,
      TailCallMode tail_call_mode = TailCallMode::kDisallow) {
    HCallWithDescriptor* res = new (zone)
        HCallWithDescriptor(target, argument_count, descriptor, operands,
                            syntactic_tail_call_mode, tail_call_mode, zone);
    return res;
  }

  int OperandCount() const final { return values_.length(); }
  HValue* OperandAt(int index) const final { return values_[index]; }

  Representation RequiredInputRepresentation(int index) final {
    if (index == 0 || index == 1) {
      // Target + context
      return Representation::Tagged();
    } else {
      int par_index = index - 2;
      DCHECK(par_index < GetParameterCount());
      return RepresentationFromType(descriptor_.GetParameterType(par_index));
    }
  }

  DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor)

  HType CalculateInferredType() final { return HType::Tagged(); }

  // Defines whether this instruction corresponds to a JS call at tail position.
  TailCallMode syntactic_tail_call_mode() const {
    return SyntacticTailCallModeField::decode(bit_field_);
  }

  // Defines whether this call should be generated as a tail call.
  TailCallMode tail_call_mode() const {
    return TailCallModeField::decode(bit_field_);
  }
  bool IsTailCall() const { return tail_call_mode() == TailCallMode::kAllow; }

  virtual int argument_count() const {
    return argument_count_;
  }

  int argument_delta() const override { return -argument_count_; }

  CallInterfaceDescriptor descriptor() const { return descriptor_; }

  HValue* target() {
    return OperandAt(0);
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

 private:
  // The argument count includes the receiver.
  HCallWithDescriptor(HValue* target, int argument_count,
                      CallInterfaceDescriptor descriptor,
                      const Vector<HValue*>& operands,
                      TailCallMode syntactic_tail_call_mode,
                      TailCallMode tail_call_mode, Zone* zone)
      : descriptor_(descriptor),
        values_(GetParameterCount() + 1, zone),
        argument_count_(argument_count),
        bit_field_(
            TailCallModeField::encode(tail_call_mode) |
            SyntacticTailCallModeField::encode(syntactic_tail_call_mode)) {
    DCHECK_EQ(operands.length(), GetParameterCount());
    // We can only tail call without any stack arguments.
    DCHECK(tail_call_mode != TailCallMode::kAllow || argument_count == 0);
    AddOperand(target, zone);
    for (int i = 0; i < operands.length(); i++) {
      AddOperand(operands[i], zone);
    }
    this->set_representation(Representation::Tagged());
    this->SetAllSideEffects();
  }

  void AddOperand(HValue* v, Zone* zone) {
    values_.Add(NULL, zone);
    SetOperandAt(values_.length() - 1, v);
  }

  int GetParameterCount() const {
    return descriptor_.GetRegisterParameterCount() + 1;
  }

  void InternalSetOperandAt(int index, HValue* value) final {
    values_[index] = value;
  }

  CallInterfaceDescriptor descriptor_;
  ZoneList<HValue*> values_;
  int argument_count_;
  class TailCallModeField : public BitField<TailCallMode, 0, 1> {};
  class SyntacticTailCallModeField
      : public BitField<TailCallMode, TailCallModeField::kNext, 1> {};
  uint32_t bit_field_;
};


class HInvokeFunction final : public HBinaryCall {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HInvokeFunction, HValue*,
                                              Handle<JSFunction>, int,
                                              TailCallMode, TailCallMode);

  HValue* context() { return first(); }
  HValue* function() { return second(); }
  Handle<JSFunction> known_function() { return known_function_; }
  int formal_parameter_count() const { return formal_parameter_count_; }

  bool HasStackCheck() final { return HasStackCheckField::decode(bit_field_); }

  // Defines whether this instruction corresponds to a JS call at tail position.
  TailCallMode syntactic_tail_call_mode() const {
    return SyntacticTailCallModeField::decode(bit_field_);
  }

  // Defines whether this call should be generated as a tail call.
  TailCallMode tail_call_mode() const {
    return TailCallModeField::decode(bit_field_);
  }

  DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)

  std::ostream& PrintTo(std::ostream& os) const override;      // NOLINT
  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

 private:
  void set_has_stack_check(bool has_stack_check) {
    bit_field_ = HasStackCheckField::update(bit_field_, has_stack_check);
  }

  HInvokeFunction(HValue* context, HValue* function,
                  Handle<JSFunction> known_function, int argument_count,
                  TailCallMode syntactic_tail_call_mode,
                  TailCallMode tail_call_mode)
      : HBinaryCall(context, function, argument_count),
        known_function_(known_function),
        bit_field_(
            TailCallModeField::encode(tail_call_mode) |
            SyntacticTailCallModeField::encode(syntactic_tail_call_mode)) {
    DCHECK(tail_call_mode != TailCallMode::kAllow ||
           syntactic_tail_call_mode == TailCallMode::kAllow);
    formal_parameter_count_ =
        known_function.is_null()
            ? 0
            : known_function->shared()->internal_formal_parameter_count();
    set_has_stack_check(
        !known_function.is_null() &&
        (known_function->code()->kind() == Code::FUNCTION ||
         known_function->code()->kind() == Code::OPTIMIZED_FUNCTION));
  }

  Handle<JSFunction> known_function_;
  int formal_parameter_count_;

  class HasStackCheckField : public BitField<bool, 0, 1> {};
  class TailCallModeField
      : public BitField<TailCallMode, HasStackCheckField::kNext, 1> {};
  class SyntacticTailCallModeField
      : public BitField<TailCallMode, TailCallModeField::kNext, 1> {};
  uint32_t bit_field_;
};


class HCallNewArray final : public HBinaryCall {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HCallNewArray, HValue*, int,
                                              ElementsKind,
                                              Handle<AllocationSite>);

  HValue* context() { return first(); }
  HValue* constructor() { return second(); }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  ElementsKind elements_kind() const { return elements_kind_; }
  Handle<AllocationSite> site() const { return site_; }

  DECLARE_CONCRETE_INSTRUCTION(CallNewArray)

 private:
  HCallNewArray(HValue* context, HValue* constructor, int argument_count,
                ElementsKind elements_kind, Handle<AllocationSite> site)
      : HBinaryCall(context, constructor, argument_count),
        elements_kind_(elements_kind),
        site_(site) {}

  ElementsKind elements_kind_;
  Handle<AllocationSite> site_;
};


class HCallRuntime final : public HCall<1> {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallRuntime,
                                              const Runtime::Function*, int);

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  HValue* context() { return OperandAt(0); }
  const Runtime::Function* function() const { return c_function_; }
  SaveFPRegsMode save_doubles() const { return save_doubles_; }
  void set_save_doubles(SaveFPRegsMode save_doubles) {
    save_doubles_ = save_doubles;
  }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  DECLARE_CONCRETE_INSTRUCTION(CallRuntime)

 private:
  HCallRuntime(HValue* context, const Runtime::Function* c_function,
               int argument_count)
      : HCall<1>(argument_count),
        c_function_(c_function),
        save_doubles_(kDontSaveFPRegs) {
    SetOperandAt(0, context);
  }

  const Runtime::Function* c_function_;
  SaveFPRegsMode save_doubles_;
};


class HUnaryMathOperation final : public HTemplateInstruction<2> {
 public:
  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
                           HValue* value, BuiltinFunctionId op);

  HValue* context() const { return OperandAt(0); }
  HValue* value() const { return OperandAt(1); }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  Representation RequiredInputRepresentation(int index) override {
    if (index == 0) {
      return Representation::Tagged();
    } else {
      switch (op_) {
        case kMathFloor:
        case kMathRound:
        case kMathFround:
        case kMathSqrt:
        case kMathPowHalf:
        case kMathLog:
        case kMathExp:
          return Representation::Double();
        case kMathAbs:
          return representation();
        case kMathClz32:
          return Representation::Integer32();
        default:
          UNREACHABLE();
          return Representation::None();
      }
    }
  }

  Range* InferRange(Zone* zone) override;

  HValue* Canonicalize() override;
  Representation RepresentationFromUses() override;
  Representation RepresentationFromInputs() override;

  BuiltinFunctionId op() const { return op_; }
  const char* OpName() const;

  DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)

 protected:
  bool DataEquals(HValue* other) override {
    HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
    return op_ == b->op();
  }

 private:
  // Indicates if we support a double (and int32) output for Math.floor and
  // Math.round.
  bool SupportsFlexibleFloorAndRound() const {
#if V8_TARGET_ARCH_ARM64
    return true;
#elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
    return CpuFeatures::IsSupported(SSE4_1);
#else
    return false;
#endif
  }
  HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
      : HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
    SetOperandAt(0, context);
    SetOperandAt(1, value);
    switch (op) {
      case kMathFloor:
      case kMathRound:
        if (SupportsFlexibleFloorAndRound()) {
          SetFlag(kFlexibleRepresentation);
        } else {
          set_representation(Representation::Integer32());
        }
        break;
      case kMathClz32:
        set_representation(Representation::Integer32());
        break;
      case kMathAbs:
        // Not setting representation here: it is None intentionally.
        SetFlag(kFlexibleRepresentation);
        // TODO(svenpanne) This flag is actually only needed if representation()
        // is tagged, and not when it is an unboxed double or unboxed integer.
        SetChangesFlag(kNewSpacePromotion);
        break;
      case kMathFround:
      case kMathLog:
      case kMathExp:
      case kMathSqrt:
      case kMathPowHalf:
        set_representation(Representation::Double());
        break;
      default:
        UNREACHABLE();
    }
    SetFlag(kUseGVN);
    SetFlag(kAllowUndefinedAsNaN);
  }

  bool IsDeletable() const override {
    // TODO(crankshaft): This should be true, however the semantics of this
    // instruction also include the ToNumber conversion that is mentioned in the
    // spec, which is of course observable.
    return false;
  }

  HValue* SimplifiedDividendForMathFloorOfDiv(HDiv* hdiv);
  HValue* SimplifiedDivisorForMathFloorOfDiv(HDiv* hdiv);

  BuiltinFunctionId op_;
};


class HLoadRoot final : public HTemplateInstruction<0> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HLoadRoot, Heap::RootListIndex);
  DECLARE_INSTRUCTION_FACTORY_P2(HLoadRoot, Heap::RootListIndex, HType);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  Heap::RootListIndex index() const { return index_; }

  DECLARE_CONCRETE_INSTRUCTION(LoadRoot)

 protected:
  bool DataEquals(HValue* other) override {
    HLoadRoot* b = HLoadRoot::cast(other);
    return index_ == b->index_;
  }

 private:
  explicit HLoadRoot(Heap::RootListIndex index, HType type = HType::Tagged())
      : HTemplateInstruction<0>(type), index_(index) {
    SetFlag(kUseGVN);
    // TODO(bmeurer): We'll need kDependsOnRoots once we add the
    // corresponding HStoreRoot instruction.
    SetDependsOnFlag(kCalls);
    set_representation(Representation::Tagged());
  }

  bool IsDeletable() const override { return true; }

  const Heap::RootListIndex index_;
};


class HCheckMaps final : public HTemplateInstruction<2> {
 public:
  static HCheckMaps* New(Isolate* isolate, Zone* zone, HValue* context,
                         HValue* value, Handle<Map> map,
                         HValue* typecheck = NULL) {
    return new(zone) HCheckMaps(value, new(zone) UniqueSet<Map>(
            Unique<Map>::CreateImmovable(map), zone), typecheck);
  }
  static HCheckMaps* New(Isolate* isolate, Zone* zone, HValue* context,
                         HValue* value, SmallMapList* map_list,
                         HValue* typecheck = NULL) {
    UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone);
    for (int i = 0; i < map_list->length(); ++i) {
      maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone);
    }
    return new(zone) HCheckMaps(value, maps, typecheck);
  }

  bool IsStabilityCheck() const {
    return IsStabilityCheckField::decode(bit_field_);
  }
  void MarkAsStabilityCheck() {
    bit_field_ = MapsAreStableField::encode(true) |
                 HasMigrationTargetField::encode(false) |
                 IsStabilityCheckField::encode(true);
    ClearChangesFlag(kNewSpacePromotion);
    ClearDependsOnFlag(kElementsKind);
    ClearDependsOnFlag(kMaps);
  }

  bool HasEscapingOperandAt(int index) override { return false; }
  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  HType CalculateInferredType() override {
    if (value()->type().IsHeapObject()) return value()->type();
    return HType::HeapObject();
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  HValue* value() const { return OperandAt(0); }
  HValue* typecheck() const { return OperandAt(1); }

  const UniqueSet<Map>* maps() const { return maps_; }
  void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; }

  bool maps_are_stable() const {
    return MapsAreStableField::decode(bit_field_);
  }

  bool HasMigrationTarget() const {
    return HasMigrationTargetField::decode(bit_field_);
  }

  HValue* Canonicalize() override;

  static HCheckMaps* CreateAndInsertAfter(Zone* zone,
                                          HValue* value,
                                          Unique<Map> map,
                                          bool map_is_stable,
                                          HInstruction* instr) {
    return instr->Append(new(zone) HCheckMaps(
            value, new(zone) UniqueSet<Map>(map, zone), map_is_stable));
  }

  static HCheckMaps* CreateAndInsertBefore(Zone* zone,
                                           HValue* value,
                                           const UniqueSet<Map>* maps,
                                           bool maps_are_stable,
                                           HInstruction* instr) {
    return instr->Prepend(new(zone) HCheckMaps(value, maps, maps_are_stable));
  }

  DECLARE_CONCRETE_INSTRUCTION(CheckMaps)

 protected:
  bool DataEquals(HValue* other) override {
    return this->maps()->Equals(HCheckMaps::cast(other)->maps());
  }

  int RedefinedOperandIndex() override { return 0; }

 private:
  HCheckMaps(HValue* value, const UniqueSet<Map>* maps, bool maps_are_stable)
      : HTemplateInstruction<2>(HType::HeapObject()),
        maps_(maps),
        bit_field_(HasMigrationTargetField::encode(false) |
                   IsStabilityCheckField::encode(false) |
                   MapsAreStableField::encode(maps_are_stable)) {
    DCHECK_NE(0, maps->size());
    SetOperandAt(0, value);
    // Use the object value for the dependency.
    SetOperandAt(1, value);
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
    SetDependsOnFlag(kMaps);
    SetDependsOnFlag(kElementsKind);
  }

  HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck)
      : HTemplateInstruction<2>(HType::HeapObject()),
        maps_(maps),
        bit_field_(HasMigrationTargetField::encode(false) |
                   IsStabilityCheckField::encode(false) |
                   MapsAreStableField::encode(true)) {
    DCHECK_NE(0, maps->size());
    SetOperandAt(0, value);
    // Use the object value for the dependency if NULL is passed.
    SetOperandAt(1, typecheck ? typecheck : value);
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
    SetDependsOnFlag(kMaps);
    SetDependsOnFlag(kElementsKind);
    for (int i = 0; i < maps->size(); ++i) {
      Handle<Map> map = maps->at(i).handle();
      if (map->is_migration_target()) {
        bit_field_ = HasMigrationTargetField::update(bit_field_, true);
      }
      if (!map->is_stable()) {
        bit_field_ = MapsAreStableField::update(bit_field_, false);
      }
    }
    if (HasMigrationTarget()) SetChangesFlag(kNewSpacePromotion);
  }

  class HasMigrationTargetField : public BitField<bool, 0, 1> {};
  class IsStabilityCheckField : public BitField<bool, 1, 1> {};
  class MapsAreStableField : public BitField<bool, 2, 1> {};

  const UniqueSet<Map>* maps_;
  uint32_t bit_field_;
};


class HCheckValue final : public HUnaryOperation {
 public:
  static HCheckValue* New(Isolate* isolate, Zone* zone, HValue* context,
                          HValue* value, Handle<JSFunction> func) {
    bool in_new_space = isolate->heap()->InNewSpace(*func);
    // NOTE: We create an uninitialized Unique and initialize it later.
    // This is because a JSFunction can move due to GC during graph creation.
    Unique<JSFunction> target = Unique<JSFunction>::CreateUninitialized(func);
    HCheckValue* check = new(zone) HCheckValue(value, target, in_new_space);
    return check;
  }
  static HCheckValue* New(Isolate* isolate, Zone* zone, HValue* context,
                          HValue* value, Unique<HeapObject> target,
                          bool object_in_new_space) {
    return new(zone) HCheckValue(value, target, object_in_new_space);
  }

  void FinalizeUniqueness() override {
    object_ = Unique<HeapObject>(object_.handle());
  }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }
  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  HValue* Canonicalize() override;

#ifdef DEBUG
  void Verify() override;
#endif

  Unique<HeapObject> object() const { return object_; }
  bool object_in_new_space() const { return object_in_new_space_; }

  DECLARE_CONCRETE_INSTRUCTION(CheckValue)

 protected:
  bool DataEquals(HValue* other) override {
    HCheckValue* b = HCheckValue::cast(other);
    return object_ == b->object_;
  }

 private:
  HCheckValue(HValue* value, Unique<HeapObject> object,
               bool object_in_new_space)
      : HUnaryOperation(value, value->type()),
        object_(object),
        object_in_new_space_(object_in_new_space) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
  }

  Unique<HeapObject> object_;
  bool object_in_new_space_;
};


class HCheckInstanceType final : public HUnaryOperation {
 public:
  enum Check {
    IS_JS_RECEIVER,
    IS_JS_ARRAY,
    IS_JS_DATE,
    IS_STRING,
    IS_INTERNALIZED_STRING,
    LAST_INTERVAL_CHECK = IS_JS_DATE
  };

  DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue*, Check);

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  HType CalculateInferredType() override {
    switch (check_) {
      case IS_JS_RECEIVER: return HType::JSReceiver();
      case IS_JS_ARRAY: return HType::JSArray();
      case IS_JS_DATE: return HType::JSObject();
      case IS_STRING: return HType::String();
      case IS_INTERNALIZED_STRING: return HType::String();
    }
    UNREACHABLE();
    return HType::Tagged();
  }

  HValue* Canonicalize() override;

  bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
  void GetCheckInterval(InstanceType* first, InstanceType* last);
  void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);

  Check check() const { return check_; }

  DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)

 protected:
  // TODO(ager): It could be nice to allow the ommision of instance
  // type checks if we have already performed an instance type check
  // with a larger range.
  bool DataEquals(HValue* other) override {
    HCheckInstanceType* b = HCheckInstanceType::cast(other);
    return check_ == b->check_;
  }

  int RedefinedOperandIndex() override { return 0; }

 private:
  const char* GetCheckName() const;

  HCheckInstanceType(HValue* value, Check check)
      : HUnaryOperation(value, HType::HeapObject()), check_(check) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
  }

  const Check check_;
};


class HCheckSmi final : public HUnaryOperation {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue*);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  HValue* Canonicalize() override {
    HType value_type = value()->type();
    if (value_type.IsSmi()) {
      return NULL;
    }
    return this;
  }

  DECLARE_CONCRETE_INSTRUCTION(CheckSmi)

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
    set_representation(Representation::Smi());
    SetFlag(kUseGVN);
  }
};


class HCheckArrayBufferNotNeutered final : public HUnaryOperation {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HCheckArrayBufferNotNeutered, HValue*);

  bool HasEscapingOperandAt(int index) override { return false; }
  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  HType CalculateInferredType() override {
    if (value()->type().IsHeapObject()) return value()->type();
    return HType::HeapObject();
  }

  DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered)

 protected:
  bool DataEquals(HValue* other) override { return true; }
  int RedefinedOperandIndex() override { return 0; }

 private:
  explicit HCheckArrayBufferNotNeutered(HValue* value)
      : HUnaryOperation(value) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
    SetDependsOnFlag(kCalls);
  }
};


class HCheckHeapObject final : public HUnaryOperation {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);

  bool HasEscapingOperandAt(int index) override { return false; }
  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  HType CalculateInferredType() override {
    if (value()->type().IsHeapObject()) return value()->type();
    return HType::HeapObject();
  }

#ifdef DEBUG
  void Verify() override;
#endif

  HValue* Canonicalize() override {
    return value()->type().IsHeapObject() ? NULL : this;
  }

  DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
  }
};


class HPhi final : public HValue {
 public:
  HPhi(int merged_index, Zone* zone)
      : inputs_(2, zone), merged_index_(merged_index) {
    DCHECK(merged_index >= 0 || merged_index == kInvalidMergedIndex);
    SetFlag(kFlexibleRepresentation);
    SetFlag(kAllowUndefinedAsNaN);
  }

  Representation RepresentationFromInputs() override;

  Range* InferRange(Zone* zone) override;
  void InferRepresentation(HInferRepresentationPhase* h_infer) override;
  Representation RequiredInputRepresentation(int index) override {
    return representation();
  }
  Representation KnownOptimalRepresentation() override {
    return representation();
  }
  HType CalculateInferredType() override;
  int OperandCount() const override { return inputs_.length(); }
  HValue* OperandAt(int index) const override { return inputs_[index]; }
  HValue* GetRedundantReplacement();
  void AddInput(HValue* value);
  bool HasRealUses();

  bool IsReceiver() const { return merged_index_ == 0; }
  bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }

  SourcePosition position() const override;

  int merged_index() const { return merged_index_; }

  std::ostream& PrintTo(std::ostream& os) const override;  // NOLINT

#ifdef DEBUG
  void Verify() override;
#endif

  void InitRealUses(int id);
  void AddNonPhiUsesFrom(HPhi* other);

  Representation representation_from_indirect_uses() const {
    return representation_from_indirect_uses_;
  }

  bool has_type_feedback_from_uses() const {
    return has_type_feedback_from_uses_;
  }

  int phi_id() { return phi_id_; }

  static HPhi* cast(HValue* value) {
    DCHECK(value->IsPhi());
    return reinterpret_cast<HPhi*>(value);
  }
  Opcode opcode() const override { return HValue::kPhi; }

  void SimplifyConstantInputs();

  // Marker value representing an invalid merge index.
  static const int kInvalidMergedIndex = -1;

 protected:
  void DeleteFromGraph() override;
  void InternalSetOperandAt(int index, HValue* value) override {
    inputs_[index] = value;
  }

 private:
  Representation representation_from_non_phi_uses() const {
    return representation_from_non_phi_uses_;
  }

  ZoneList<HValue*> inputs_;
  int merged_index_ = 0;

  int phi_id_ = -1;

  Representation representation_from_indirect_uses_ = Representation::None();
  Representation representation_from_non_phi_uses_ = Representation::None();
  bool has_type_feedback_from_uses_ = false;

  bool IsDeletable() const override { return !IsReceiver(); }
};


// Common base class for HArgumentsObject and HCapturedObject.
class HDematerializedObject : public HInstruction {
 public:
  HDematerializedObject(int count, Zone* zone) : values_(count, zone) {}

  int OperandCount() const final { return values_.length(); }
  HValue* OperandAt(int index) const final { return values_[index]; }

  bool HasEscapingOperandAt(int index) final { return false; }
  Representation RequiredInputRepresentation(int index) final {
    return Representation::None();
  }

 protected:
  void InternalSetOperandAt(int index, HValue* value) final {
    values_[index] = value;
  }

  // List of values tracked by this marker.
  ZoneList<HValue*> values_;
};


class HArgumentsObject final : public HDematerializedObject {
 public:
  static HArgumentsObject* New(Isolate* isolate, Zone* zone, HValue* context,
                               int count) {
    return new(zone) HArgumentsObject(count, zone);
  }

  // The values contain a list of all elements in the arguments object
  // including the receiver object, which is skipped when materializing.
  const ZoneList<HValue*>* arguments_values() const { return &values_; }
  int arguments_count() const { return values_.length(); }

  void AddArgument(HValue* argument, Zone* zone) {
    values_.Add(NULL, zone);  // Resize list.
    SetOperandAt(values_.length() - 1, argument);
  }

  DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)

 private:
  HArgumentsObject(int count, Zone* zone)
      : HDematerializedObject(count, zone) {
    set_representation(Representation::Tagged());
    SetFlag(kIsArguments);
  }
};


class HCapturedObject final : public HDematerializedObject {
 public:
  HCapturedObject(int length, int id, Zone* zone)
      : HDematerializedObject(length, zone), capture_id_(id) {
    set_representation(Representation::Tagged());
    values_.AddBlock(NULL, length, zone);  // Resize list.
  }

  // The values contain a list of all in-object properties inside the
  // captured object and is index by field index. Properties in the
  // properties or elements backing store are not tracked here.
  const ZoneList<HValue*>* values() const { return &values_; }
  int length() const { return values_.length(); }
  int capture_id() const { return capture_id_; }

  // Shortcut for the map value of this captured object.
  HValue* map_value() const { return values()->first(); }

  void ReuseSideEffectsFromStore(HInstruction* store) {
    DCHECK(store->HasObservableSideEffects());
    DCHECK(store->IsStoreNamedField());
    changes_flags_.Add(store->ChangesFlags());
  }

  // Replay effects of this instruction on the given environment.
  void ReplayEnvironment(HEnvironment* env);

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(CapturedObject)

 private:
  int capture_id_;

  // Note that we cannot DCE captured objects as they are used to replay
  // the environment. This method is here as an explicit reminder.
  // TODO(mstarzinger): Turn HSimulates into full snapshots maybe?
  bool IsDeletable() const final { return false; }
};


class HConstant final : public HTemplateInstruction<0> {
 public:
  enum Special { kHoleNaN };

  DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Special);
  DECLARE_INSTRUCTION_FACTORY_P1(HConstant, int32_t);
  DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation);
  DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double);
  DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle<Object>);
  DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);

  static HConstant* CreateAndInsertAfter(Isolate* isolate, Zone* zone,
                                         HValue* context, int32_t value,
                                         Representation representation,
                                         HInstruction* instruction) {
    return instruction->Append(
        HConstant::New(isolate, zone, context, value, representation));
  }

  Handle<Map> GetMonomorphicJSObjectMap() override {
    Handle<Object> object = object_.handle();
    if (!object.is_null() && object->IsHeapObject()) {
      return v8::internal::handle(HeapObject::cast(*object)->map());
    }
    return Handle<Map>();
  }

  static HConstant* CreateAndInsertBefore(Isolate* isolate, Zone* zone,
                                          HValue* context, int32_t value,
                                          Representation representation,
                                          HInstruction* instruction) {
    return instruction->Prepend(
        HConstant::New(isolate, zone, context, value, representation));
  }

  static HConstant* CreateAndInsertBefore(Zone* zone,
                                          Unique<Map> map,
                                          bool map_is_stable,
                                          HInstruction* instruction) {
    return instruction->Prepend(new(zone) HConstant(
        map, Unique<Map>(Handle<Map>::null()), map_is_stable,
        Representation::Tagged(), HType::HeapObject(), true,
        false, false, MAP_TYPE));
  }

  static HConstant* CreateAndInsertAfter(Zone* zone,
                                         Unique<Map> map,
                                         bool map_is_stable,
                                         HInstruction* instruction) {
    return instruction->Append(new(zone) HConstant(
            map, Unique<Map>(Handle<Map>::null()), map_is_stable,
            Representation::Tagged(), HType::HeapObject(), true,
            false, false, MAP_TYPE));
  }

  Handle<Object> handle(Isolate* isolate) {
    if (object_.handle().is_null()) {
      // Default arguments to is_not_in_new_space depend on this heap number
      // to be tenured so that it's guaranteed not to be located in new space.
      object_ = Unique<Object>::CreateUninitialized(
          isolate->factory()->NewNumber(double_value_, TENURED));
    }
    AllowDeferredHandleDereference smi_check;
    DCHECK(HasInteger32Value() || !object_.handle()->IsSmi());
    return object_.handle();
  }

  bool IsSpecialDouble() const {
    return HasDoubleValue() &&
           (bit_cast<int64_t>(double_value_) == bit_cast<int64_t>(-0.0) ||
            std::isnan(double_value_));
  }

  bool NotInNewSpace() const {
    return IsNotInNewSpaceField::decode(bit_field_);
  }

  bool ImmortalImmovable() const;

  bool IsCell() const {
    InstanceType instance_type = GetInstanceType();
    return instance_type == CELL_TYPE;
  }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  Representation KnownOptimalRepresentation() override {
    if (HasSmiValue() && SmiValuesAre31Bits()) return Representation::Smi();
    if (HasInteger32Value()) return Representation::Integer32();
    if (HasNumberValue()) return Representation::Double();
    if (HasExternalReferenceValue()) return Representation::External();
    return Representation::Tagged();
  }

  bool EmitAtUses() override;
  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
  HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
  Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone);
  Maybe<HConstant*> CopyToTruncatedNumber(Isolate* isolate, Zone* zone);
  bool HasInteger32Value() const {
    return HasInt32ValueField::decode(bit_field_);
  }
  int32_t Integer32Value() const {
    DCHECK(HasInteger32Value());
    return int32_value_;
  }
  bool HasSmiValue() const { return HasSmiValueField::decode(bit_field_); }
  bool HasDoubleValue() const {
    return HasDoubleValueField::decode(bit_field_);
  }
  double DoubleValue() const {
    DCHECK(HasDoubleValue());
    return double_value_;
  }
  uint64_t DoubleValueAsBits() const {
    uint64_t bits;
    DCHECK(HasDoubleValue());
    STATIC_ASSERT(sizeof(bits) == sizeof(double_value_));
    std::memcpy(&bits, &double_value_, sizeof(bits));
    return bits;
  }
  bool IsTheHole() const {
    if (HasDoubleValue() && DoubleValueAsBits() == kHoleNanInt64) {
      return true;
    }
    return object_.IsInitialized() &&
           object_.IsKnownGlobal(isolate()->heap()->the_hole_value());
  }
  bool HasNumberValue() const { return HasDoubleValue(); }
  int32_t NumberValueAsInteger32() const {
    DCHECK(HasNumberValue());
    // Irrespective of whether a numeric HConstant can be safely
    // represented as an int32, we store the (in some cases lossy)
    // representation of the number in int32_value_.
    return int32_value_;
  }
  bool HasStringValue() const {
    if (HasNumberValue()) return false;
    DCHECK(!object_.handle().is_null());
    return GetInstanceType() < FIRST_NONSTRING_TYPE;
  }
  Handle<String> StringValue() const {
    DCHECK(HasStringValue());
    return Handle<String>::cast(object_.handle());
  }
  bool HasInternalizedStringValue() const {
    return HasStringValue() && StringShape(GetInstanceType()).IsInternalized();
  }

  bool HasExternalReferenceValue() const {
    return HasExternalReferenceValueField::decode(bit_field_);
  }
  ExternalReference ExternalReferenceValue() const {
    return external_reference_value_;
  }

  bool HasBooleanValue() const { return type_.IsBoolean(); }
  bool BooleanValue() const { return BooleanValueField::decode(bit_field_); }
  bool IsCallable() const { return IsCallableField::decode(bit_field_); }
  bool IsUndetectable() const {
    return IsUndetectableField::decode(bit_field_);
  }
  InstanceType GetInstanceType() const {
    return InstanceTypeField::decode(bit_field_);
  }

  bool HasMapValue() const { return GetInstanceType() == MAP_TYPE; }
  Unique<Map> MapValue() const {
    DCHECK(HasMapValue());
    return Unique<Map>::cast(GetUnique());
  }
  bool HasStableMapValue() const {
    DCHECK(HasMapValue() || !HasStableMapValueField::decode(bit_field_));
    return HasStableMapValueField::decode(bit_field_);
  }

  bool HasObjectMap() const { return !object_map_.IsNull(); }
  Unique<Map> ObjectMap() const {
    DCHECK(HasObjectMap());
    return object_map_;
  }

  intptr_t Hashcode() override {
    if (HasInteger32Value()) {
      return static_cast<intptr_t>(int32_value_);
    } else if (HasDoubleValue()) {
      uint64_t bits = DoubleValueAsBits();
      if (sizeof(bits) > sizeof(intptr_t)) {
        bits ^= (bits >> 32);
      }
      return static_cast<intptr_t>(bits);
    } else if (HasExternalReferenceValue()) {
      return reinterpret_cast<intptr_t>(external_reference_value_.address());
    } else {
      DCHECK(!object_.handle().is_null());
      return object_.Hashcode();
    }
  }

  void FinalizeUniqueness() override {
    if (!HasDoubleValue() && !HasExternalReferenceValue()) {
      DCHECK(!object_.handle().is_null());
      object_ = Unique<Object>(object_.handle());
    }
  }

  Unique<Object> GetUnique() const {
    return object_;
  }

  bool EqualsUnique(Unique<Object> other) const {
    return object_.IsInitialized() && object_ == other;
  }

  bool DataEquals(HValue* other) override {
    HConstant* other_constant = HConstant::cast(other);
    if (HasInteger32Value()) {
      return other_constant->HasInteger32Value() &&
             int32_value_ == other_constant->int32_value_;
    } else if (HasDoubleValue()) {
      return other_constant->HasDoubleValue() &&
             std::memcmp(&double_value_, &other_constant->double_value_,
                         sizeof(double_value_)) == 0;
    } else if (HasExternalReferenceValue()) {
      return other_constant->HasExternalReferenceValue() &&
             external_reference_value_ ==
                 other_constant->external_reference_value_;
    } else {
      if (other_constant->HasInteger32Value() ||
          other_constant->HasDoubleValue() ||
          other_constant->HasExternalReferenceValue()) {
        return false;
      }
      DCHECK(!object_.handle().is_null());
      return other_constant->object_ == object_;
    }
  }

#ifdef DEBUG
  void Verify() override {}
#endif

  DECLARE_CONCRETE_INSTRUCTION(Constant)

 protected:
  Range* InferRange(Zone* zone) override;

 private:
  friend class HGraph;
  explicit HConstant(Special special);
  explicit HConstant(Handle<Object> handle,
                     Representation r = Representation::None());
  HConstant(int32_t value,
            Representation r = Representation::None(),
            bool is_not_in_new_space = true,
            Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
  HConstant(double value,
            Representation r = Representation::None(),
            bool is_not_in_new_space = true,
            Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
  HConstant(Unique<Object> object,
            Unique<Map> object_map,
            bool has_stable_map_value,
            Representation r,
            HType type,
            bool is_not_in_new_space,
            bool boolean_value,
            bool is_undetectable,
            InstanceType instance_type);

  explicit HConstant(ExternalReference reference);

  void Initialize(Representation r);

  bool IsDeletable() const override { return true; }

  // If object_ is a map, this indicates whether the map is stable.
  class HasStableMapValueField : public BitField<bool, 0, 1> {};

  // We store the HConstant in the most specific form safely possible.
  // These flags tell us if the respective member fields hold valid, safe
  // representations of the constant. More specific flags imply more general
  // flags, but not the converse (i.e. smi => int32 => double).
  class HasSmiValueField : public BitField<bool, 1, 1> {};
  class HasInt32ValueField : public BitField<bool, 2, 1> {};
  class HasDoubleValueField : public BitField<bool, 3, 1> {};

  class HasExternalReferenceValueField : public BitField<bool, 4, 1> {};
  class IsNotInNewSpaceField : public BitField<bool, 5, 1> {};
  class BooleanValueField : public BitField<bool, 6, 1> {};
  class IsUndetectableField : public BitField<bool, 7, 1> {};
  class IsCallableField : public BitField<bool, 8, 1> {};

  static const InstanceType kUnknownInstanceType = FILLER_TYPE;
  class InstanceTypeField : public BitField<InstanceType, 16, 8> {};

  // If this is a numerical constant, object_ either points to the
  // HeapObject the constant originated from or is null.  If the
  // constant is non-numeric, object_ always points to a valid
  // constant HeapObject.
  Unique<Object> object_;

  // If object_ is a heap object, this points to the stable map of the object.
  Unique<Map> object_map_;

  uint32_t bit_field_;

  int32_t int32_value_;
  double double_value_;
  ExternalReference external_reference_value_;
};


class HBinaryOperation : public HTemplateInstruction<3> {
 public:
  HBinaryOperation(HValue* context, HValue* left, HValue* right,
                   HType type = HType::Tagged())
      : HTemplateInstruction<3>(type),
        observed_output_representation_(Representation::None()) {
    DCHECK(left != NULL && right != NULL);
    SetOperandAt(0, context);
    SetOperandAt(1, left);
    SetOperandAt(2, right);
    observed_input_representation_[0] = Representation::None();
    observed_input_representation_[1] = Representation::None();
  }

  HValue* context() const { return OperandAt(0); }
  HValue* left() const { return OperandAt(1); }
  HValue* right() const { return OperandAt(2); }

  // True if switching left and right operands likely generates better code.
  bool AreOperandsBetterSwitched() {
    if (!IsCommutative()) return false;

    // Constant operands are better off on the right, they can be inlined in
    // many situations on most platforms.
    if (left()->IsConstant()) return true;
    if (right()->IsConstant()) return false;

    // Otherwise, if there is only one use of the right operand, it would be
    // better off on the left for platforms that only have 2-arg arithmetic
    // ops (e.g ia32, x64) that clobber the left operand.
    return right()->HasOneUse();
  }

  HValue* BetterLeftOperand() {
    return AreOperandsBetterSwitched() ? right() : left();
  }

  HValue* BetterRightOperand() {
    return AreOperandsBetterSwitched() ? left() : right();
  }

  void set_observed_input_representation(int index, Representation rep) {
    DCHECK(index >= 1 && index <= 2);
    observed_input_representation_[index - 1] = rep;
  }

  virtual void initialize_output_representation(Representation observed) {
    observed_output_representation_ = observed;
  }

  Representation observed_input_representation(int index) override {
    if (index == 0) return Representation::Tagged();
    return observed_input_representation_[index - 1];
  }

  void UpdateRepresentation(Representation new_rep,
                            HInferRepresentationPhase* h_infer,
                            const char* reason) override {
    Representation rep = !FLAG_smi_binop && new_rep.IsSmi()
        ? Representation::Integer32() : new_rep;
    HValue::UpdateRepresentation(rep, h_infer, reason);
  }

  void InferRepresentation(HInferRepresentationPhase* h_infer) override;
  Representation RepresentationFromInputs() override;
  Representation RepresentationFromOutput();
  void AssumeRepresentation(Representation r) override;

  virtual bool IsCommutative() const { return false; }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  Representation RequiredInputRepresentation(int index) override {
    if (index == 0) return Representation::Tagged();
    return representation();
  }

  void SetOperandPositions(Zone* zone, SourcePosition left_pos,
                           SourcePosition right_pos) {
    set_operand_position(zone, 1, left_pos);
    set_operand_position(zone, 2, right_pos);
  }

  bool RightIsPowerOf2() {
    if (!right()->IsInteger32Constant()) return false;
    int32_t value = right()->GetInteger32Constant();
    if (value < 0) {
      return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(-value));
    }
    return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(value));
  }

  DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)

 private:
  bool IgnoreObservedOutputRepresentation(Representation current_rep);

  Representation observed_input_representation_[2];
  Representation observed_output_representation_;
};


class HWrapReceiver final : public HTemplateInstruction<2> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);

  bool DataEquals(HValue* other) override { return true; }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  HValue* receiver() const { return OperandAt(0); }
  HValue* function() const { return OperandAt(1); }

  HValue* Canonicalize() override;

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
  bool known_function() const { return known_function_; }

  DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)

 private:
  HWrapReceiver(HValue* receiver, HValue* function) {
    known_function_ = function->IsConstant() &&
        HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
    set_representation(Representation::Tagged());
    SetOperandAt(0, receiver);
    SetOperandAt(1, function);
    SetFlag(kUseGVN);
  }

  bool known_function_;
};


class HApplyArguments final : public HTemplateInstruction<4> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P5(HApplyArguments, HValue*, HValue*, HValue*,
                                 HValue*, TailCallMode);

  Representation RequiredInputRepresentation(int index) override {
    // The length is untagged, all other inputs are tagged.
    return (index == 2)
        ? Representation::Integer32()
        : Representation::Tagged();
  }

  HValue* function() { return OperandAt(0); }
  HValue* receiver() { return OperandAt(1); }
  HValue* length() { return OperandAt(2); }
  HValue* elements() { return OperandAt(3); }

  TailCallMode tail_call_mode() const {
    return TailCallModeField::decode(bit_field_);
  }

  DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)

 private:
  HApplyArguments(HValue* function, HValue* receiver, HValue* length,
                  HValue* elements, TailCallMode tail_call_mode)
      : bit_field_(TailCallModeField::encode(tail_call_mode)) {
    set_representation(Representation::Tagged());
    SetOperandAt(0, function);
    SetOperandAt(1, receiver);
    SetOperandAt(2, length);
    SetOperandAt(3, elements);
    SetAllSideEffects();
  }

  class TailCallModeField : public BitField<TailCallMode, 0, 1> {};
  uint32_t bit_field_;
};


class HArgumentsElements final : public HTemplateInstruction<0> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
  DECLARE_INSTRUCTION_FACTORY_P2(HArgumentsElements, bool, bool);

  DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  bool from_inlined() const { return from_inlined_; }
  bool arguments_adaptor() const { return arguments_adaptor_; }

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  explicit HArgumentsElements(bool from_inlined, bool arguments_adaptor = true)
      : from_inlined_(from_inlined), arguments_adaptor_(arguments_adaptor) {
    // The value produced by this instruction is a pointer into the stack
    // that looks as if it was a smi because of alignment.
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
  }

  bool IsDeletable() const override { return true; }

  bool from_inlined_;
  bool arguments_adaptor_;
};


class HArgumentsLength final : public HUnaryOperation {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue*);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
    set_representation(Representation::Integer32());
    SetFlag(kUseGVN);
  }

  bool IsDeletable() const override { return true; }
};


class HAccessArgumentsAt final : public HTemplateInstruction<3> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P3(HAccessArgumentsAt, HValue*, HValue*, HValue*);

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  Representation RequiredInputRepresentation(int index) override {
    // The arguments elements is considered tagged.
    return index == 0
        ? Representation::Tagged()
        : Representation::Integer32();
  }

  HValue* arguments() const { return OperandAt(0); }
  HValue* length() const { return OperandAt(1); }
  HValue* index() const { return OperandAt(2); }

  DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)

 private:
  HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
    SetOperandAt(0, arguments);
    SetOperandAt(1, length);
    SetOperandAt(2, index);
  }

  bool DataEquals(HValue* other) override { return true; }
};


class HBoundsCheck final : public HTemplateInstruction<2> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);

  bool skip_check() const { return skip_check_; }
  void set_skip_check() { skip_check_ = true; }

  HValue* base() const { return base_; }
  int offset() const { return offset_; }
  int scale() const { return scale_; }

  Representation RequiredInputRepresentation(int index) override {
    return representation();
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
  void InferRepresentation(HInferRepresentationPhase* h_infer) override;

  HValue* index() const { return OperandAt(0); }
  HValue* length() const { return OperandAt(1); }
  bool allow_equality() const { return allow_equality_; }
  void set_allow_equality(bool v) { allow_equality_ = v; }

  int RedefinedOperandIndex() override { return 0; }
  bool IsPurelyInformativeDefinition() override { return skip_check(); }

  DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)

 protected:
  Range* InferRange(Zone* zone) override;

  bool DataEquals(HValue* other) override { return true; }
  bool skip_check_;
  HValue* base_;
  int offset_;
  int scale_;
  bool allow_equality_;

 private:
  // Normally HBoundsCheck should be created using the
  // HGraphBuilder::AddBoundsCheck() helper.
  // However when building stubs, where we know that the arguments are Int32,
  // it makes sense to invoke this constructor directly.
  HBoundsCheck(HValue* index, HValue* length)
    : skip_check_(false),
      base_(NULL), offset_(0), scale_(0),
      allow_equality_(false) {
    SetOperandAt(0, index);
    SetOperandAt(1, length);
    SetFlag(kFlexibleRepresentation);
    SetFlag(kUseGVN);
  }

  bool IsDeletable() const override { return skip_check() && !FLAG_debug_code; }
};


class HBitwiseBinaryOperation : public HBinaryOperation {
 public:
  HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
                          HType type = HType::TaggedNumber())
      : HBinaryOperation(context, left, right, type) {
    SetFlag(kFlexibleRepresentation);
    SetFlag(kTruncatingToInt32);
    SetAllSideEffects();
  }

  void RepresentationChanged(Representation to) override {
    if (to.IsTagged() &&
        (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
      SetAllSideEffects();
      ClearFlag(kUseGVN);
    } else {
      ClearAllSideEffects();
      SetFlag(kUseGVN);
    }
    if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
  }

  void UpdateRepresentation(Representation new_rep,
                            HInferRepresentationPhase* h_infer,
                            const char* reason) override {
    // We only generate either int32 or generic tagged bitwise operations.
    if (new_rep.IsDouble()) new_rep = Representation::Integer32();
    HBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
  }

  Representation observed_input_representation(int index) override {
    Representation r = HBinaryOperation::observed_input_representation(index);
    if (r.IsDouble()) return Representation::Integer32();
    return r;
  }

  void initialize_output_representation(Representation observed) override {
    if (observed.IsDouble()) observed = Representation::Integer32();
    HBinaryOperation::initialize_output_representation(observed);
  }

  DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)

 private:
  bool IsDeletable() const override { return true; }
};


class HMathFloorOfDiv final : public HBinaryOperation {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HMathFloorOfDiv,
                                              HValue*,
                                              HValue*);

  DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
      : HBinaryOperation(context, left, right) {
    set_representation(Representation::Integer32());
    SetFlag(kUseGVN);
    SetFlag(kCanOverflow);
    SetFlag(kCanBeDivByZero);
    SetFlag(kLeftCanBeMinInt);
    SetFlag(kLeftCanBeNegative);
    SetFlag(kLeftCanBePositive);
    SetFlag(kAllowUndefinedAsNaN);
  }

  Range* InferRange(Zone* zone) override;

  bool IsDeletable() const override { return true; }
};


class HArithmeticBinaryOperation : public HBinaryOperation {
 public:
  HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right)
      : HBinaryOperation(context, left, right, HType::TaggedNumber()) {
    SetAllSideEffects();
    SetFlag(kFlexibleRepresentation);
    SetFlag(kAllowUndefinedAsNaN);
  }

  void RepresentationChanged(Representation to) override {
    if (to.IsTagged() &&
        (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
      SetAllSideEffects();
      ClearFlag(kUseGVN);
    } else {
      ClearAllSideEffects();
      SetFlag(kUseGVN);
    }
    if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
  }

  DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)

 private:
  bool IsDeletable() const override { return true; }
};


class HCompareGeneric final : public HBinaryOperation {
 public:
  static HCompareGeneric* New(Isolate* isolate, Zone* zone, HValue* context,
                              HValue* left, HValue* right, Token::Value token) {
    return new (zone) HCompareGeneric(context, left, right, token);
  }

  Representation RequiredInputRepresentation(int index) override {
    return index == 0
        ? Representation::Tagged()
        : representation();
  }

  Token::Value token() const { return token_; }
  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)

 private:
  HCompareGeneric(HValue* context, HValue* left, HValue* right,
                  Token::Value token)
      : HBinaryOperation(context, left, right, HType::Boolean()),
        token_(token) {
    DCHECK(Token::IsCompareOp(token));
    set_representation(Representation::Tagged());
    SetAllSideEffects();
  }

  Token::Value token_;
};


class HCompareNumericAndBranch : public HTemplateControlInstruction<2, 2> {
 public:
  static HCompareNumericAndBranch* New(Isolate* isolate, Zone* zone,
                                       HValue* context, HValue* left,
                                       HValue* right, Token::Value token,
                                       HBasicBlock* true_target = NULL,
                                       HBasicBlock* false_target = NULL) {
    return new (zone)
        HCompareNumericAndBranch(left, right, token, true_target, false_target);
  }

  HValue* left() const { return OperandAt(0); }
  HValue* right() const { return OperandAt(1); }
  Token::Value token() const { return token_; }

  void set_observed_input_representation(Representation left,
                                         Representation right) {
      observed_input_representation_[0] = left;
      observed_input_representation_[1] = right;
  }

  void InferRepresentation(HInferRepresentationPhase* h_infer) override;

  Representation RequiredInputRepresentation(int index) override {
    return representation();
  }
  Representation observed_input_representation(int index) override {
    return observed_input_representation_[index];
  }

  bool KnownSuccessorBlock(HBasicBlock** block) override;

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  void SetOperandPositions(Zone* zone, SourcePosition left_pos,
                           SourcePosition right_pos) {
    set_operand_position(zone, 0, left_pos);
    set_operand_position(zone, 1, right_pos);
  }

  DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)

 private:
  HCompareNumericAndBranch(HValue* left, HValue* right, Token::Value token,
                           HBasicBlock* true_target, HBasicBlock* false_target)
      : token_(token) {
    SetFlag(kFlexibleRepresentation);
    DCHECK(Token::IsCompareOp(token));
    SetOperandAt(0, left);
    SetOperandAt(1, right);
    SetSuccessorAt(0, true_target);
    SetSuccessorAt(1, false_target);
  }

  Representation observed_input_representation_[2];
  Token::Value token_;
};


class HCompareHoleAndBranch final : public HUnaryControlInstruction {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HCompareHoleAndBranch, HValue*);
  DECLARE_INSTRUCTION_FACTORY_P3(HCompareHoleAndBranch, HValue*,
                                 HBasicBlock*, HBasicBlock*);

  void InferRepresentation(HInferRepresentationPhase* h_infer) override;

  Representation RequiredInputRepresentation(int index) override {
    return representation();
  }

  DECLARE_CONCRETE_INSTRUCTION(CompareHoleAndBranch)

 private:
  HCompareHoleAndBranch(HValue* value,
                        HBasicBlock* true_target = NULL,
                        HBasicBlock* false_target = NULL)
      : HUnaryControlInstruction(value, true_target, false_target) {
    SetFlag(kFlexibleRepresentation);
    SetFlag(kAllowUndefinedAsNaN);
  }
};


class HCompareObjectEqAndBranch : public HTemplateControlInstruction<2, 2> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue*, HValue*);
  DECLARE_INSTRUCTION_FACTORY_P4(HCompareObjectEqAndBranch, HValue*, HValue*,
                                 HBasicBlock*, HBasicBlock*);

  bool KnownSuccessorBlock(HBasicBlock** block) override;

  static const int kNoKnownSuccessorIndex = -1;
  int known_successor_index() const { return known_successor_index_; }
  void set_known_successor_index(int known_successor_index) {
    known_successor_index_ = known_successor_index;
  }

  HValue* left() const { return OperandAt(0); }
  HValue* right() const { return OperandAt(1); }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  Representation observed_input_representation(int index) override {
    return Representation::Tagged();
  }

  DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)

 private:
  HCompareObjectEqAndBranch(HValue* left,
                            HValue* right,
                            HBasicBlock* true_target = NULL,
                            HBasicBlock* false_target = NULL)
      : known_successor_index_(kNoKnownSuccessorIndex) {
    SetOperandAt(0, left);
    SetOperandAt(1, right);
    SetSuccessorAt(0, true_target);
    SetSuccessorAt(1, false_target);
  }

  int known_successor_index_;
};


class HIsStringAndBranch final : public HUnaryControlInstruction {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HIsStringAndBranch, HValue*);
  DECLARE_INSTRUCTION_FACTORY_P3(HIsStringAndBranch, HValue*,
                                 HBasicBlock*, HBasicBlock*);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  bool KnownSuccessorBlock(HBasicBlock** block) override;

  static const int kNoKnownSuccessorIndex = -1;
  int known_successor_index() const { return known_successor_index_; }
  void set_known_successor_index(int known_successor_index) {
    known_successor_index_ = known_successor_index;
  }

  DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)

 protected:
  int RedefinedOperandIndex() override { return 0; }

 private:
  HIsStringAndBranch(HValue* value, HBasicBlock* true_target = NULL,
                     HBasicBlock* false_target = NULL)
      : HUnaryControlInstruction(value, true_target, false_target),
        known_successor_index_(kNoKnownSuccessorIndex) {
    set_representation(Representation::Tagged());
  }

  int known_successor_index_;
};


class HIsSmiAndBranch final : public HUnaryControlInstruction {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HIsSmiAndBranch, HValue*);
  DECLARE_INSTRUCTION_FACTORY_P3(HIsSmiAndBranch, HValue*,
                                 HBasicBlock*, HBasicBlock*);

  DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

 protected:
  bool DataEquals(HValue* other) override { return true; }
  int RedefinedOperandIndex() override { return 0; }

 private:
  HIsSmiAndBranch(HValue* value,
                  HBasicBlock* true_target = NULL,
                  HBasicBlock* false_target = NULL)
      : HUnaryControlInstruction(value, true_target, false_target) {
    set_representation(Representation::Tagged());
  }
};


class HIsUndetectableAndBranch final : public HUnaryControlInstruction {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HIsUndetectableAndBranch, HValue*);
  DECLARE_INSTRUCTION_FACTORY_P3(HIsUndetectableAndBranch, HValue*,
                                 HBasicBlock*, HBasicBlock*);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  bool KnownSuccessorBlock(HBasicBlock** block) override;

  DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)

 private:
  HIsUndetectableAndBranch(HValue* value,
                           HBasicBlock* true_target = NULL,
                           HBasicBlock* false_target = NULL)
      : HUnaryControlInstruction(value, true_target, false_target) {}
};


class HStringCompareAndBranch final : public HTemplateControlInstruction<2, 3> {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HStringCompareAndBranch,
                                              HValue*,
                                              HValue*,
                                              Token::Value);

  HValue* context() const { return OperandAt(0); }
  HValue* left() const { return OperandAt(1); }
  HValue* right() const { return OperandAt(2); }
  Token::Value token() const { return token_; }

  std::ostream& PrintDataTo(std::ostream& os) const final;  // NOLINT

  Representation RequiredInputRepresentation(int index) final {
    return Representation::Tagged();
  }

  DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)

 private:
  HStringCompareAndBranch(HValue* context, HValue* left, HValue* right,
                          Token::Value token)
      : token_(token) {
    DCHECK(Token::IsCompareOp(token));
    SetOperandAt(0, context);
    SetOperandAt(1, left);
    SetOperandAt(2, right);
    set_representation(Representation::Tagged());
    SetChangesFlag(kNewSpacePromotion);
    SetDependsOnFlag(kStringChars);
    SetDependsOnFlag(kStringLengths);
  }

  Token::Value const token_;
};


class HHasInstanceTypeAndBranch final : public HUnaryControlInstruction {
 public:
  DECLARE_INSTRUCTION_FACTORY_P2(
      HHasInstanceTypeAndBranch, HValue*, InstanceType);
  DECLARE_INSTRUCTION_FACTORY_P3(
      HHasInstanceTypeAndBranch, HValue*, InstanceType, InstanceType);

  InstanceType from() { return from_; }
  InstanceType to() { return to_; }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  bool KnownSuccessorBlock(HBasicBlock** block) override;

  DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)

 private:
  HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
      : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
  HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
      : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
    DCHECK(to == LAST_TYPE);  // Others not implemented yet in backend.
  }

  InstanceType from_;
  InstanceType to_;  // Inclusive range, not all combinations work.
};


class HHasCachedArrayIndexAndBranch final : public HUnaryControlInstruction {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HHasCachedArrayIndexAndBranch, HValue*);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
 private:
  explicit HHasCachedArrayIndexAndBranch(HValue* value)
      : HUnaryControlInstruction(value, NULL, NULL) { }
};


class HGetCachedArrayIndex final : public HUnaryOperation {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HGetCachedArrayIndex, HValue*);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
  }

  bool IsDeletable() const override { return true; }
};


class HClassOfTestAndBranch final : public HUnaryControlInstruction {
 public:
  DECLARE_INSTRUCTION_FACTORY_P2(HClassOfTestAndBranch, HValue*,
                                 Handle<String>);

  DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  Handle<String> class_name() const { return class_name_; }

 private:
  HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
      : HUnaryControlInstruction(value, NULL, NULL),
        class_name_(class_name) { }

  Handle<String> class_name_;
};


class HTypeofIsAndBranch final : public HUnaryControlInstruction {
 public:
  DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle<String>);

  Handle<String> type_literal() const { return type_literal_.handle(); }
  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  bool KnownSuccessorBlock(HBasicBlock** block) override;

  void FinalizeUniqueness() override {
    type_literal_ = Unique<String>(type_literal_.handle());
  }

 private:
  HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
      : HUnaryControlInstruction(value, NULL, NULL),
        type_literal_(Unique<String>::CreateUninitialized(type_literal)) { }

  Unique<String> type_literal_;
};


class HInstanceOf final : public HBinaryOperation {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOf, HValue*, HValue*);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(InstanceOf)

 private:
  HInstanceOf(HValue* context, HValue* left, HValue* right)
      : HBinaryOperation(context, left, right, HType::Boolean()) {
    set_representation(Representation::Tagged());
    SetAllSideEffects();
  }
};


class HHasInPrototypeChainAndBranch final
    : public HTemplateControlInstruction<2, 2> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P2(HHasInPrototypeChainAndBranch, HValue*,
                                 HValue*);

  HValue* object() const { return OperandAt(0); }
  HValue* prototype() const { return OperandAt(1); }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  bool ObjectNeedsSmiCheck() const {
    return !object()->type().IsHeapObject() &&
           !object()->representation().IsHeapObject();
  }

  DECLARE_CONCRETE_INSTRUCTION(HasInPrototypeChainAndBranch)

 private:
  HHasInPrototypeChainAndBranch(HValue* object, HValue* prototype) {
    SetOperandAt(0, object);
    SetOperandAt(1, prototype);
    SetDependsOnFlag(kCalls);
  }
};


class HPower final : public HTemplateInstruction<2> {
 public:
  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
                           HValue* left, HValue* right);

  HValue* left() { return OperandAt(0); }
  HValue* right() const { return OperandAt(1); }

  Representation RequiredInputRepresentation(int index) override {
    return index == 0
      ? Representation::Double()
      : Representation::None();
  }
  Representation observed_input_representation(int index) override {
    return RequiredInputRepresentation(index);
  }

  DECLARE_CONCRETE_INSTRUCTION(Power)

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  HPower(HValue* left, HValue* right) {
    SetOperandAt(0, left);
    SetOperandAt(1, right);
    set_representation(Representation::Double());
    SetFlag(kUseGVN);
    SetChangesFlag(kNewSpacePromotion);
  }

  bool IsDeletable() const override {
    return !right()->representation().IsTagged();
  }
};


enum ExternalAddType {
  AddOfExternalAndTagged,
  AddOfExternalAndInt32,
  NoExternalAdd
};


class HAdd final : public HArithmeticBinaryOperation {
 public:
  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
                           HValue* left, HValue* right);
  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
                           HValue* left, HValue* right,
                           ExternalAddType external_add_type);

  // Add is only commutative if two integer values are added and not if two
  // tagged values are added (because it might be a String concatenation).
  // We also do not commute (pointer + offset).
  bool IsCommutative() const override {
    return !representation().IsTagged() && !representation().IsExternal();
  }

  HValue* Canonicalize() override;

  void RepresentationChanged(Representation to) override {
    if (to.IsTagged() &&
        (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() ||
         left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) {
      SetAllSideEffects();
      ClearFlag(kUseGVN);
    } else {
      ClearAllSideEffects();
      SetFlag(kUseGVN);
    }
    if (to.IsTagged()) {
      SetChangesFlag(kNewSpacePromotion);
      ClearFlag(kAllowUndefinedAsNaN);
    }
  }

  Representation RepresentationFromInputs() override;

  Representation RequiredInputRepresentation(int index) override;

  bool IsConsistentExternalRepresentation() {
    return left()->representation().IsExternal() &&
           ((external_add_type_ == AddOfExternalAndInt32 &&
             right()->representation().IsInteger32()) ||
            (external_add_type_ == AddOfExternalAndTagged &&
             right()->representation().IsTagged()));
  }

  ExternalAddType external_add_type() const { return external_add_type_; }

  DECLARE_CONCRETE_INSTRUCTION(Add)

 protected:
  bool DataEquals(HValue* other) override { return true; }

  Range* InferRange(Zone* zone) override;

 private:
  HAdd(HValue* context, HValue* left, HValue* right,
       ExternalAddType external_add_type = NoExternalAdd)
      : HArithmeticBinaryOperation(context, left, right),
        external_add_type_(external_add_type) {
    SetFlag(kCanOverflow);
    switch (external_add_type_) {
      case AddOfExternalAndTagged:
        DCHECK(left->representation().IsExternal());
        DCHECK(right->representation().IsTagged());
        SetDependsOnFlag(kNewSpacePromotion);
        ClearFlag(HValue::kCanOverflow);
        SetFlag(kHasNoObservableSideEffects);
        break;

      case NoExternalAdd:
        // This is a bit of a hack: The call to this constructor is generated
        // by a macro that also supports sub and mul, so it doesn't pass in
        // a value for external_add_type but uses the default.
        if (left->representation().IsExternal()) {
          external_add_type_ = AddOfExternalAndInt32;
        }
        break;

      case AddOfExternalAndInt32:
        // See comment above.
        UNREACHABLE();
        break;
    }
  }

  ExternalAddType external_add_type_;
};


class HSub final : public HArithmeticBinaryOperation {
 public:
  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
                           HValue* left, HValue* right);

  HValue* Canonicalize() override;

  DECLARE_CONCRETE_INSTRUCTION(Sub)

 protected:
  bool DataEquals(HValue* other) override { return true; }

  Range* InferRange(Zone* zone) override;

 private:
  HSub(HValue* context, HValue* left, HValue* right)
      : HArithmeticBinaryOperation(context, left, right) {
    SetFlag(kCanOverflow);
  }
};


class HMul final : public HArithmeticBinaryOperation {
 public:
  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
                           HValue* left, HValue* right);

  static HInstruction* NewImul(Isolate* isolate, Zone* zone, HValue* context,
                               HValue* left, HValue* right) {
    HInstruction* instr = HMul::New(isolate, zone, context, left, right);
    if (!instr->IsMul()) return instr;
    HMul* mul = HMul::cast(instr);
    // TODO(mstarzinger): Prevent bailout on minus zero for imul.
    mul->AssumeRepresentation(Representation::Integer32());
    mul->ClearFlag(HValue::kCanOverflow);
    return mul;
  }

  HValue* Canonicalize() override;

  // Only commutative if it is certain that not two objects are multiplicated.
  bool IsCommutative() const override { return !representation().IsTagged(); }

  void UpdateRepresentation(Representation new_rep,
                            HInferRepresentationPhase* h_infer,
                            const char* reason) override {
    HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
  }

  bool MulMinusOne();

  DECLARE_CONCRETE_INSTRUCTION(Mul)

 protected:
  bool DataEquals(HValue* other) override { return true; }

  Range* InferRange(Zone* zone) override;

 private:
  HMul(HValue* context, HValue* left, HValue* right)
      : HArithmeticBinaryOperation(context, left, right) {
    SetFlag(kCanOverflow);
  }
};


class HMod final : public HArithmeticBinaryOperation {
 public:
  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
                           HValue* left, HValue* right);

  HValue* Canonicalize() override;

  void UpdateRepresentation(Representation new_rep,
                            HInferRepresentationPhase* h_infer,
                            const char* reason) override {
    if (new_rep.IsSmi()) new_rep = Representation::Integer32();
    HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
  }

  DECLARE_CONCRETE_INSTRUCTION(Mod)

 protected:
  bool DataEquals(HValue* other) override { return true; }

  Range* InferRange(Zone* zone) override;

 private:
  HMod(HValue* context, HValue* left, HValue* right)
      : HArithmeticBinaryOperation(context, left, right) {
    SetFlag(kCanBeDivByZero);
    SetFlag(kCanOverflow);
    SetFlag(kLeftCanBeNegative);
  }
};


class HDiv final : public HArithmeticBinaryOperation {
 public:
  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
                           HValue* left, HValue* right);

  HValue* Canonicalize() override;

  void UpdateRepresentation(Representation new_rep,
                            HInferRepresentationPhase* h_infer,
                            const char* reason) override {
    if (new_rep.IsSmi()) new_rep = Representation::Integer32();
    HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
  }

  DECLARE_CONCRETE_INSTRUCTION(Div)

 protected:
  bool DataEquals(HValue* other) override { return true; }

  Range* InferRange(Zone* zone) override;

 private:
  HDiv(HValue* context, HValue* left, HValue* right)
      : HArithmeticBinaryOperation(context, left, right) {
    SetFlag(kCanBeDivByZero);
    SetFlag(kCanOverflow);
  }
};


class HMathMinMax final : public HArithmeticBinaryOperation {
 public:
  enum Operation { kMathMin, kMathMax };

  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
                           HValue* left, HValue* right, Operation op);

  Representation observed_input_representation(int index) override {
    return RequiredInputRepresentation(index);
  }

  void InferRepresentation(HInferRepresentationPhase* h_infer) override;

  Representation RepresentationFromInputs() override {
    Representation left_rep = left()->representation();
    Representation right_rep = right()->representation();
    Representation result = Representation::Smi();
    result = result.generalize(left_rep);
    result = result.generalize(right_rep);
    if (result.IsTagged()) return Representation::Double();
    return result;
  }

  bool IsCommutative() const override { return true; }

  Operation operation() { return operation_; }

  DECLARE_CONCRETE_INSTRUCTION(MathMinMax)

 protected:
  bool DataEquals(HValue* other) override {
    return other->IsMathMinMax() &&
        HMathMinMax::cast(other)->operation_ == operation_;
  }

  Range* InferRange(Zone* zone) override;

 private:
  HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
      : HArithmeticBinaryOperation(context, left, right), operation_(op) {}

  Operation operation_;
};


class HBitwise final : public HBitwiseBinaryOperation {
 public:
  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
                           Token::Value op, HValue* left, HValue* right);

  Token::Value op() const { return op_; }

  bool IsCommutative() const override { return true; }

  HValue* Canonicalize() override;

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(Bitwise)

 protected:
  bool DataEquals(HValue* other) override {
    return op() == HBitwise::cast(other)->op();
  }

  Range* InferRange(Zone* zone) override;

 private:
  HBitwise(HValue* context, Token::Value op, HValue* left, HValue* right)
      : HBitwiseBinaryOperation(context, left, right), op_(op) {
    DCHECK(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
    // BIT_AND with a smi-range positive value will always unset the
    // entire sign-extension of the smi-sign.
    if (op == Token::BIT_AND &&
        ((left->IsConstant() &&
          left->representation().IsSmi() &&
          HConstant::cast(left)->Integer32Value() >= 0) ||
         (right->IsConstant() &&
          right->representation().IsSmi() &&
          HConstant::cast(right)->Integer32Value() >= 0))) {
      SetFlag(kTruncatingToSmi);
      SetFlag(kTruncatingToInt32);
    // BIT_OR with a smi-range negative value will always set the entire
    // sign-extension of the smi-sign.
    } else if (op == Token::BIT_OR &&
        ((left->IsConstant() &&
          left->representation().IsSmi() &&
          HConstant::cast(left)->Integer32Value() < 0) ||
         (right->IsConstant() &&
          right->representation().IsSmi() &&
          HConstant::cast(right)->Integer32Value() < 0))) {
      SetFlag(kTruncatingToSmi);
      SetFlag(kTruncatingToInt32);
    }
  }

  Token::Value op_;
};


class HShl final : public HBitwiseBinaryOperation {
 public:
  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
                           HValue* left, HValue* right);

  Range* InferRange(Zone* zone) override;

  void UpdateRepresentation(Representation new_rep,
                            HInferRepresentationPhase* h_infer,
                            const char* reason) override {
    if (new_rep.IsSmi() &&
        !(right()->IsInteger32Constant() &&
          right()->GetInteger32Constant() >= 0)) {
      new_rep = Representation::Integer32();
    }
    HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
  }

  DECLARE_CONCRETE_INSTRUCTION(Shl)

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  HShl(HValue* context, HValue* left, HValue* right)
      : HBitwiseBinaryOperation(context, left, right) {}
};


class HShr final : public HBitwiseBinaryOperation {
 public:
  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
                           HValue* left, HValue* right);

  Range* InferRange(Zone* zone) override;

  void UpdateRepresentation(Representation new_rep,
                            HInferRepresentationPhase* h_infer,
                            const char* reason) override {
    if (new_rep.IsSmi()) new_rep = Representation::Integer32();
    HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
  }

  DECLARE_CONCRETE_INSTRUCTION(Shr)

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  HShr(HValue* context, HValue* left, HValue* right)
      : HBitwiseBinaryOperation(context, left, right) {}
};


class HSar final : public HBitwiseBinaryOperation {
 public:
  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
                           HValue* left, HValue* right);

  Range* InferRange(Zone* zone) override;

  void UpdateRepresentation(Representation new_rep,
                            HInferRepresentationPhase* h_infer,
                            const char* reason) override {
    if (new_rep.IsSmi()) new_rep = Representation::Integer32();
    HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
  }

  DECLARE_CONCRETE_INSTRUCTION(Sar)

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  HSar(HValue* context, HValue* left, HValue* right)
      : HBitwiseBinaryOperation(context, left, right) {}
};


class HRor final : public HBitwiseBinaryOperation {
 public:
  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
                           HValue* left, HValue* right) {
    return new (zone) HRor(context, left, right);
  }

  void UpdateRepresentation(Representation new_rep,
                            HInferRepresentationPhase* h_infer,
                            const char* reason) override {
    if (new_rep.IsSmi()) new_rep = Representation::Integer32();
    HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
  }

  DECLARE_CONCRETE_INSTRUCTION(Ror)

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  HRor(HValue* context, HValue* left, HValue* right)
      : HBitwiseBinaryOperation(context, left, right) {
    ChangeRepresentation(Representation::Integer32());
  }
};


class HOsrEntry final : public HTemplateInstruction<0> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId);

  BailoutId ast_id() const { return ast_id_; }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  DECLARE_CONCRETE_INSTRUCTION(OsrEntry)

 private:
  explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
    SetChangesFlag(kOsrEntries);
    SetChangesFlag(kNewSpacePromotion);
  }

  BailoutId ast_id_;
};


class HParameter final : public HTemplateInstruction<0> {
 public:
  enum ParameterKind {
    STACK_PARAMETER,
    REGISTER_PARAMETER
  };

  DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned);
  DECLARE_INSTRUCTION_FACTORY_P2(HParameter, unsigned, ParameterKind);
  DECLARE_INSTRUCTION_FACTORY_P3(HParameter, unsigned, ParameterKind,
                                 Representation);

  unsigned index() const { return index_; }
  ParameterKind kind() const { return kind_; }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  Representation KnownOptimalRepresentation() override {
    // If a parameter is an input to a phi, that phi should not
    // choose any more optimistic representation than Tagged.
    return Representation::Tagged();
  }

  DECLARE_CONCRETE_INSTRUCTION(Parameter)

 private:
  explicit HParameter(unsigned index,
                      ParameterKind kind = STACK_PARAMETER)
      : index_(index),
        kind_(kind) {
    set_representation(Representation::Tagged());
  }

  explicit HParameter(unsigned index,
                      ParameterKind kind,
                      Representation r)
      : index_(index),
        kind_(kind) {
    set_representation(r);
  }

  unsigned index_;
  ParameterKind kind_;
};


class HUnknownOSRValue final : public HTemplateInstruction<0> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P2(HUnknownOSRValue, HEnvironment*, int);

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  Representation RequiredInputRepresentation(int index) override {
    return Representation::None();
  }

  void set_incoming_value(HPhi* value) { incoming_value_ = value; }
  HPhi* incoming_value() { return incoming_value_; }
  HEnvironment *environment() { return environment_; }
  int index() { return index_; }

  Representation KnownOptimalRepresentation() override {
    if (incoming_value_ == NULL) return Representation::None();
    return incoming_value_->KnownOptimalRepresentation();
  }

  DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)

 private:
  HUnknownOSRValue(HEnvironment* environment, int index)
      : environment_(environment),
        index_(index),
        incoming_value_(NULL) {
    set_representation(Representation::Tagged());
  }

  HEnvironment* environment_;
  int index_;
  HPhi* incoming_value_;
};


class HLoadGlobalGeneric final : public HTemplateInstruction<2> {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadGlobalGeneric, HValue*,
                                              Handle<String>, TypeofMode);

  HValue* context() { return OperandAt(0); }
  HValue* global_object() { return OperandAt(1); }
  Handle<String> name() const { return name_; }
  TypeofMode typeof_mode() const { return typeof_mode_; }
  FeedbackVectorSlot slot() const { return slot_; }
  Handle<TypeFeedbackVector> feedback_vector() const {
    return feedback_vector_;
  }
  bool HasVectorAndSlot() const { return true; }
  void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
                        FeedbackVectorSlot slot) {
    feedback_vector_ = vector;
    slot_ = slot;
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)

 private:
  HLoadGlobalGeneric(HValue* context, HValue* global_object,
                     Handle<String> name, TypeofMode typeof_mode)
      : name_(name), typeof_mode_(typeof_mode) {
    SetOperandAt(0, context);
    SetOperandAt(1, global_object);
    set_representation(Representation::Tagged());
    SetAllSideEffects();
  }

  Handle<String> name_;
  TypeofMode typeof_mode_;
  Handle<TypeFeedbackVector> feedback_vector_;
  FeedbackVectorSlot slot_;
};


class HAllocate final : public HTemplateInstruction<2> {
 public:
  static bool CompatibleInstanceTypes(InstanceType type1,
                                      InstanceType type2) {
    return ComputeFlags(TENURED, type1) == ComputeFlags(TENURED, type2) &&
        ComputeFlags(NOT_TENURED, type1) == ComputeFlags(NOT_TENURED, type2);
  }

  static HAllocate* New(
      Isolate* isolate, Zone* zone, HValue* context, HValue* size, HType type,
      PretenureFlag pretenure_flag, InstanceType instance_type,
      Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null()) {
    return new(zone) HAllocate(context, size, type, pretenure_flag,
        instance_type, allocation_site);
  }

  // Maximum instance size for which allocations will be inlined.
  static const int kMaxInlineSize = 64 * kPointerSize;

  HValue* context() const { return OperandAt(0); }
  HValue* size() const { return OperandAt(1); }

  bool has_size_upper_bound() { return size_upper_bound_ != NULL; }
  HConstant* size_upper_bound() { return size_upper_bound_; }
  void set_size_upper_bound(HConstant* value) {
    DCHECK(size_upper_bound_ == NULL);
    size_upper_bound_ = value;
  }

  Representation RequiredInputRepresentation(int index) override {
    if (index == 0) {
      return Representation::Tagged();
    } else {
      return Representation::Integer32();
    }
  }

  Handle<Map> GetMonomorphicJSObjectMap() override {
    return known_initial_map_;
  }

  void set_known_initial_map(Handle<Map> known_initial_map) {
    known_initial_map_ = known_initial_map;
  }

  bool IsNewSpaceAllocation() const {
    return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
  }

  bool IsOldSpaceAllocation() const {
    return (flags_ & ALLOCATE_IN_OLD_SPACE) != 0;
  }

  bool MustAllocateDoubleAligned() const {
    return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
  }

  bool MustPrefillWithFiller() const {
    return (flags_ & PREFILL_WITH_FILLER) != 0;
  }

  void MakePrefillWithFiller() {
    flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
  }

  bool MustClearNextMapWord() const {
    return (flags_ & CLEAR_NEXT_MAP_WORD) != 0;
  }

  void MakeDoubleAligned() {
    flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
  }

  bool HandleSideEffectDominator(GVNFlag side_effect,
                                 HValue* dominator) override;

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(Allocate)

 private:
  enum Flags {
    ALLOCATE_IN_NEW_SPACE = 1 << 0,
    ALLOCATE_IN_OLD_SPACE = 1 << 2,
    ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
    PREFILL_WITH_FILLER = 1 << 4,
    CLEAR_NEXT_MAP_WORD = 1 << 5
  };

  HAllocate(HValue* context,
            HValue* size,
            HType type,
            PretenureFlag pretenure_flag,
            InstanceType instance_type,
            Handle<AllocationSite> allocation_site =
                Handle<AllocationSite>::null())
      : HTemplateInstruction<2>(type),
        flags_(ComputeFlags(pretenure_flag, instance_type)),
        dominating_allocate_(NULL),
        filler_free_space_size_(NULL),
        size_upper_bound_(NULL) {
    SetOperandAt(0, context);
    UpdateSize(size);
    set_representation(Representation::Tagged());
    SetFlag(kTrackSideEffectDominators);
    SetChangesFlag(kNewSpacePromotion);
    SetDependsOnFlag(kNewSpacePromotion);

    if (FLAG_trace_pretenuring) {
      PrintF("HAllocate with AllocationSite %p %s\n",
             allocation_site.is_null()
                 ? static_cast<void*>(NULL)
                 : static_cast<void*>(*allocation_site),
             pretenure_flag == TENURED ? "tenured" : "not tenured");
    }
  }

  static Flags ComputeFlags(PretenureFlag pretenure_flag,
                            InstanceType instance_type) {
    Flags flags = pretenure_flag == TENURED ? ALLOCATE_IN_OLD_SPACE
                                            : ALLOCATE_IN_NEW_SPACE;
    if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
      flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED);
    }
    // We have to fill the allocated object with one word fillers if we do
    // not use allocation folding since some allocations may depend on each
    // other, i.e., have a pointer to each other. A GC in between these
    // allocations may leave such objects behind in a not completely initialized
    // state.
    if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
      flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER);
    }
    if (pretenure_flag == NOT_TENURED &&
        AllocationSite::CanTrack(instance_type)) {
      flags = static_cast<Flags>(flags | CLEAR_NEXT_MAP_WORD);
    }
    return flags;
  }

  void UpdateClearNextMapWord(bool clear_next_map_word) {
    flags_ = static_cast<Flags>(clear_next_map_word
                                ? flags_ | CLEAR_NEXT_MAP_WORD
                                : flags_ & ~CLEAR_NEXT_MAP_WORD);
  }

  void UpdateSize(HValue* size) {
    SetOperandAt(1, size);
    if (size->IsInteger32Constant()) {
      size_upper_bound_ = HConstant::cast(size);
    } else {
      size_upper_bound_ = NULL;
    }
  }

  HAllocate* GetFoldableDominator(HAllocate* dominator);

  void UpdateFreeSpaceFiller(int32_t filler_size);

  void CreateFreeSpaceFiller(int32_t filler_size);

  bool IsFoldable(HAllocate* allocate) {
    return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) ||
           (IsOldSpaceAllocation() && allocate->IsOldSpaceAllocation());
  }

  void ClearNextMapWord(int offset);

  Flags flags_;
  Handle<Map> known_initial_map_;
  HAllocate* dominating_allocate_;
  HStoreNamedField* filler_free_space_size_;
  HConstant* size_upper_bound_;
};


class HStoreCodeEntry final : public HTemplateInstruction<2> {
 public:
  static HStoreCodeEntry* New(Isolate* isolate, Zone* zone, HValue* context,
                              HValue* function, HValue* code) {
    return new(zone) HStoreCodeEntry(function, code);
  }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  HValue* function() { return OperandAt(0); }
  HValue* code_object() { return OperandAt(1); }

  DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry)

 private:
  HStoreCodeEntry(HValue* function, HValue* code) {
    SetOperandAt(0, function);
    SetOperandAt(1, code);
  }
};


class HInnerAllocatedObject final : public HTemplateInstruction<2> {
 public:
  static HInnerAllocatedObject* New(Isolate* isolate, Zone* zone,
                                    HValue* context, HValue* value,
                                    HValue* offset, HType type) {
    return new(zone) HInnerAllocatedObject(value, offset, type);
  }

  HValue* base_object() const { return OperandAt(0); }
  HValue* offset() const { return OperandAt(1); }

  Representation RequiredInputRepresentation(int index) override {
    return index == 0 ? Representation::Tagged() : Representation::Integer32();
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)

 private:
  HInnerAllocatedObject(HValue* value,
                        HValue* offset,
                        HType type) : HTemplateInstruction<2>(type) {
    DCHECK(value->IsAllocate());
    DCHECK(type.IsHeapObject());
    SetOperandAt(0, value);
    SetOperandAt(1, offset);
    set_representation(Representation::Tagged());
  }
};


inline bool StoringValueNeedsWriteBarrier(HValue* value) {
  return !value->type().IsSmi()
      && !value->type().IsNull()
      && !value->type().IsBoolean()
      && !value->type().IsUndefined()
      && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
}


inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
                                            HValue* value,
                                            HValue* dominator) {
  while (object->IsInnerAllocatedObject()) {
    object = HInnerAllocatedObject::cast(object)->base_object();
  }
  if (object->IsConstant() &&
      HConstant::cast(object)->HasExternalReferenceValue()) {
    // Stores to external references require no write barriers
    return false;
  }
  // We definitely need a write barrier unless the object is the allocation
  // dominator.
  if (object == dominator && object->IsAllocate()) {
    // Stores to new space allocations require no write barriers.
    if (HAllocate::cast(object)->IsNewSpaceAllocation()) {
      return false;
    }
  }
  return true;
}


inline PointersToHereCheck PointersToHereCheckForObject(HValue* object,
                                                        HValue* dominator) {
  while (object->IsInnerAllocatedObject()) {
    object = HInnerAllocatedObject::cast(object)->base_object();
  }
  if (object == dominator &&
      object->IsAllocate() &&
      HAllocate::cast(object)->IsNewSpaceAllocation()) {
    return kPointersToHereAreAlwaysInteresting;
  }
  return kPointersToHereMaybeInteresting;
}


class HLoadContextSlot final : public HUnaryOperation {
 public:
  enum Mode {
    // Perform a normal load of the context slot without checking its value.
    kNoCheck,
    // Load and check the value of the context slot. Deoptimize if it's the
    // hole value. This is used for checking for loading of uninitialized
    // harmony bindings where we deoptimize into full-codegen generated code
    // which will subsequently throw a reference error.
    kCheckDeoptimize,
    // Load and check the value of the context slot. Return undefined if it's
    // the hole value. This is used for non-harmony const assignments
    kCheckReturnUndefined
  };

  HLoadContextSlot(HValue* context, int slot_index, Mode mode)
      : HUnaryOperation(context), slot_index_(slot_index), mode_(mode) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
    SetDependsOnFlag(kContextSlots);
  }

  int slot_index() const { return slot_index_; }
  Mode mode() const { return mode_; }

  bool DeoptimizesOnHole() {
    return mode_ == kCheckDeoptimize;
  }

  bool RequiresHoleCheck() const {
    return mode_ != kNoCheck;
  }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)

 protected:
  bool DataEquals(HValue* other) override {
    HLoadContextSlot* b = HLoadContextSlot::cast(other);
    return (slot_index() == b->slot_index());
  }

 private:
  bool IsDeletable() const override { return !RequiresHoleCheck(); }

  int slot_index_;
  Mode mode_;
};


class HStoreContextSlot final : public HTemplateInstruction<2> {
 public:
  enum Mode {
    // Perform a normal store to the context slot without checking its previous
    // value.
    kNoCheck,
    // Check the previous value of the context slot and deoptimize if it's the
    // hole value. This is used for checking for assignments to uninitialized
    // harmony bindings where we deoptimize into full-codegen generated code
    // which will subsequently throw a reference error.
    kCheckDeoptimize,
    // Check the previous value and ignore assignment if it isn't a hole value
    kCheckIgnoreAssignment
  };

  DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
                                 Mode, HValue*);

  HValue* context() const { return OperandAt(0); }
  HValue* value() const { return OperandAt(1); }
  int slot_index() const { return slot_index_; }
  Mode mode() const { return mode_; }

  bool NeedsWriteBarrier() {
    return StoringValueNeedsWriteBarrier(value());
  }

  bool DeoptimizesOnHole() {
    return mode_ == kCheckDeoptimize;
  }

  bool RequiresHoleCheck() {
    return mode_ != kNoCheck;
  }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)

 private:
  HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
      : slot_index_(slot_index), mode_(mode) {
    SetOperandAt(0, context);
    SetOperandAt(1, value);
    SetChangesFlag(kContextSlots);
  }

  int slot_index_;
  Mode mode_;
};


// Represents an access to a portion of an object, such as the map pointer,
// array elements pointer, etc, but not accesses to array elements themselves.
class HObjectAccess final {
 public:
  inline bool IsInobject() const {
    return portion() != kBackingStore && portion() != kExternalMemory;
  }

  inline bool IsExternalMemory() const {
    return portion() == kExternalMemory;
  }

  inline bool IsStringLength() const {
    return portion() == kStringLengths;
  }

  inline bool IsMap() const {
    return portion() == kMaps;
  }

  inline int offset() const {
    return OffsetField::decode(value_);
  }

  inline Representation representation() const {
    return Representation::FromKind(RepresentationField::decode(value_));
  }

  inline Handle<Name> name() const { return name_; }

  inline bool immutable() const {
    return ImmutableField::decode(value_);
  }

  // Returns true if access is being made to an in-object property that
  // was already added to the object.
  inline bool existing_inobject_property() const {
    return ExistingInobjectPropertyField::decode(value_);
  }

  inline HObjectAccess WithRepresentation(Representation representation) {
    return HObjectAccess(portion(), offset(), representation, name(),
                         immutable(), existing_inobject_property());
  }

  static HObjectAccess ForHeapNumberValue() {
    return HObjectAccess(
        kDouble, HeapNumber::kValueOffset, Representation::Double());
  }

  static HObjectAccess ForHeapNumberValueLowestBits() {
    return HObjectAccess(kDouble,
                         HeapNumber::kValueOffset,
                         Representation::Integer32());
  }

  static HObjectAccess ForHeapNumberValueHighestBits() {
    return HObjectAccess(kDouble,
                         HeapNumber::kValueOffset + kIntSize,
                         Representation::Integer32());
  }

  static HObjectAccess ForOddballToNumber(
      Representation representation = Representation::Tagged()) {
    return HObjectAccess(kInobject, Oddball::kToNumberOffset, representation);
  }

  static HObjectAccess ForOddballTypeOf() {
    return HObjectAccess(kInobject, Oddball::kTypeOfOffset,
                         Representation::HeapObject());
  }

  static HObjectAccess ForElementsPointer() {
    return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
  }

  static HObjectAccess ForLiteralsPointer() {
    return HObjectAccess(kInobject, JSFunction::kLiteralsOffset);
  }

  static HObjectAccess ForNextFunctionLinkPointer() {
    return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
  }

  static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
    return HObjectAccess(
        kArrayLengths,
        JSArray::kLengthOffset,
        IsFastElementsKind(elements_kind)
            ? Representation::Smi() : Representation::Tagged());
  }

  static HObjectAccess ForAllocationSiteOffset(int offset);

  static HObjectAccess ForAllocationSiteList() {
    return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
                         Handle<Name>::null(), false, false);
  }

  static HObjectAccess ForFixedArrayLength() {
    return HObjectAccess(
        kArrayLengths,
        FixedArray::kLengthOffset,
        Representation::Smi());
  }

  static HObjectAccess ForFixedTypedArrayBaseBasePointer() {
    return HObjectAccess(kInobject, FixedTypedArrayBase::kBasePointerOffset,
                         Representation::Tagged());
  }

  static HObjectAccess ForFixedTypedArrayBaseExternalPointer() {
    return HObjectAccess::ForObservableJSObjectOffset(
        FixedTypedArrayBase::kExternalPointerOffset,
        Representation::External());
  }

  static HObjectAccess ForStringHashField() {
    return HObjectAccess(kInobject,
                         String::kHashFieldOffset,
                         Representation::Integer32());
  }

  static HObjectAccess ForStringLength() {
    STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
    return HObjectAccess(
        kStringLengths,
        String::kLengthOffset,
        Representation::Smi());
  }

  static HObjectAccess ForConsStringFirst() {
    return HObjectAccess(kInobject, ConsString::kFirstOffset);
  }

  static HObjectAccess ForConsStringSecond() {
    return HObjectAccess(kInobject, ConsString::kSecondOffset);
  }

  static HObjectAccess ForPropertiesPointer() {
    return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
  }

  static HObjectAccess ForPrototypeOrInitialMap() {
    return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
  }

  static HObjectAccess ForSharedFunctionInfoPointer() {
    return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
  }

  static HObjectAccess ForCodeEntryPointer() {
    return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
  }

  static HObjectAccess ForCodeOffset() {
    return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
  }

  static HObjectAccess ForOptimizedCodeMap() {
    return HObjectAccess(kInobject,
                         SharedFunctionInfo::kOptimizedCodeMapOffset);
  }

  static HObjectAccess ForOptimizedCodeMapSharedCode() {
    return HObjectAccess(kInobject, FixedArray::OffsetOfElementAt(
                                        SharedFunctionInfo::kSharedCodeIndex));
  }

  static HObjectAccess ForFunctionContextPointer() {
    return HObjectAccess(kInobject, JSFunction::kContextOffset);
  }

  static HObjectAccess ForMap() {
    return HObjectAccess(kMaps, JSObject::kMapOffset);
  }

  static HObjectAccess ForPrototype() {
    return HObjectAccess(kMaps, Map::kPrototypeOffset);
  }

  static HObjectAccess ForMapAsInteger32() {
    return HObjectAccess(kMaps, JSObject::kMapOffset,
                         Representation::Integer32());
  }

  static HObjectAccess ForMapInObjectPropertiesOrConstructorFunctionIndex() {
    return HObjectAccess(
        kInobject, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset,
        Representation::UInteger8());
  }

  static HObjectAccess ForMapInstanceType() {
    return HObjectAccess(kInobject,
                         Map::kInstanceTypeOffset,
                         Representation::UInteger8());
  }

  static HObjectAccess ForMapInstanceSize() {
    return HObjectAccess(kInobject,
                         Map::kInstanceSizeOffset,
                         Representation::UInteger8());
  }

  static HObjectAccess ForMapBitField() {
    return HObjectAccess(kInobject,
                         Map::kBitFieldOffset,
                         Representation::UInteger8());
  }

  static HObjectAccess ForMapBitField2() {
    return HObjectAccess(kInobject,
                         Map::kBitField2Offset,
                         Representation::UInteger8());
  }

  static HObjectAccess ForMapBitField3() {
    return HObjectAccess(kInobject, Map::kBitField3Offset,
                         Representation::Integer32());
  }

  static HObjectAccess ForMapDescriptors() {
    return HObjectAccess(kInobject, Map::kDescriptorsOffset);
  }

  static HObjectAccess ForNameHashField() {
    return HObjectAccess(kInobject,
                         Name::kHashFieldOffset,
                         Representation::Integer32());
  }

  static HObjectAccess ForMapInstanceTypeAndBitField() {
    STATIC_ASSERT((Map::kInstanceTypeAndBitFieldOffset & 1) == 0);
    // Ensure the two fields share one 16-bit word, endian-independent.
    STATIC_ASSERT((Map::kBitFieldOffset & ~1) ==
                  (Map::kInstanceTypeOffset & ~1));
    return HObjectAccess(kInobject,
                         Map::kInstanceTypeAndBitFieldOffset,
                         Representation::UInteger16());
  }

  static HObjectAccess ForPropertyCellValue() {
    return HObjectAccess(kInobject, PropertyCell::kValueOffset);
  }

  static HObjectAccess ForPropertyCellDetails() {
    return HObjectAccess(kInobject, PropertyCell::kDetailsOffset,
                         Representation::Smi());
  }

  static HObjectAccess ForCellValue() {
    return HObjectAccess(kInobject, Cell::kValueOffset);
  }

  static HObjectAccess ForWeakCellValue() {
    return HObjectAccess(kInobject, WeakCell::kValueOffset);
  }

  static HObjectAccess ForWeakCellNext() {
    return HObjectAccess(kInobject, WeakCell::kNextOffset);
  }

  static HObjectAccess ForAllocationMementoSite() {
    return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
  }

  static HObjectAccess ForCounter() {
    return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
                         Handle<Name>::null(), false, false);
  }

  static HObjectAccess ForExternalUInteger8() {
    return HObjectAccess(kExternalMemory, 0, Representation::UInteger8(),
                         Handle<Name>::null(), false, false);
  }

  // Create an access to an offset in a fixed array header.
  static HObjectAccess ForFixedArrayHeader(int offset);

  // Create an access to an in-object property in a JSObject.
  // This kind of access must be used when the object |map| is known and
  // in-object properties are being accessed. Accesses of the in-object
  // properties can have different semantics depending on whether corresponding
  // property was added to the map or not.
  static HObjectAccess ForMapAndOffset(Handle<Map> map, int offset,
      Representation representation = Representation::Tagged());

  // Create an access to an in-object property in a JSObject.
  // This kind of access can be used for accessing object header fields or
  // in-object properties if the map of the object is not known.
  static HObjectAccess ForObservableJSObjectOffset(int offset,
      Representation representation = Representation::Tagged()) {
    return ForMapAndOffset(Handle<Map>::null(), offset, representation);
  }

  // Create an access to an in-object property in a JSArray.
  static HObjectAccess ForJSArrayOffset(int offset);

  static HObjectAccess ForContextSlot(int index);

  static HObjectAccess ForScriptContext(int index);

  // Create an access to the backing store of an object.
  static HObjectAccess ForBackingStoreOffset(int offset,
      Representation representation = Representation::Tagged());

  // Create an access to a resolved field (in-object or backing store).
  static HObjectAccess ForField(Handle<Map> map, int index,
                                Representation representation,
                                Handle<Name> name);

  static HObjectAccess ForJSTypedArrayLength() {
    return HObjectAccess::ForObservableJSObjectOffset(
        JSTypedArray::kLengthOffset);
  }

  static HObjectAccess ForJSArrayBufferBackingStore() {
    return HObjectAccess::ForObservableJSObjectOffset(
        JSArrayBuffer::kBackingStoreOffset, Representation::External());
  }

  static HObjectAccess ForJSArrayBufferByteLength() {
    return HObjectAccess::ForObservableJSObjectOffset(
        JSArrayBuffer::kByteLengthOffset, Representation::Tagged());
  }

  static HObjectAccess ForJSArrayBufferBitField() {
    return HObjectAccess::ForObservableJSObjectOffset(
        JSArrayBuffer::kBitFieldOffset, Representation::Integer32());
  }

  static HObjectAccess ForJSArrayBufferBitFieldSlot() {
    return HObjectAccess::ForObservableJSObjectOffset(
        JSArrayBuffer::kBitFieldSlot, Representation::Smi());
  }

  static HObjectAccess ForJSArrayBufferViewBuffer() {
    return HObjectAccess::ForObservableJSObjectOffset(
        JSArrayBufferView::kBufferOffset);
  }

  static HObjectAccess ForJSArrayBufferViewByteOffset() {
    return HObjectAccess::ForObservableJSObjectOffset(
        JSArrayBufferView::kByteOffsetOffset);
  }

  static HObjectAccess ForJSArrayBufferViewByteLength() {
    return HObjectAccess::ForObservableJSObjectOffset(
        JSArrayBufferView::kByteLengthOffset);
  }

  static HObjectAccess ForJSGlobalObjectNativeContext() {
    return HObjectAccess(kInobject, JSGlobalObject::kNativeContextOffset);
  }

  static HObjectAccess ForJSRegExpFlags() {
    return HObjectAccess(kInobject, JSRegExp::kFlagsOffset);
  }

  static HObjectAccess ForJSRegExpSource() {
    return HObjectAccess(kInobject, JSRegExp::kSourceOffset);
  }

  static HObjectAccess ForJSCollectionTable() {
    return HObjectAccess::ForObservableJSObjectOffset(
        JSCollection::kTableOffset);
  }

  template <typename CollectionType>
  static HObjectAccess ForOrderedHashTableNumberOfBuckets() {
    return HObjectAccess(kInobject, CollectionType::kNumberOfBucketsOffset,
                         Representation::Smi());
  }

  template <typename CollectionType>
  static HObjectAccess ForOrderedHashTableNumberOfElements() {
    return HObjectAccess(kInobject, CollectionType::kNumberOfElementsOffset,
                         Representation::Smi());
  }

  template <typename CollectionType>
  static HObjectAccess ForOrderedHashTableNumberOfDeletedElements() {
    return HObjectAccess(kInobject,
                         CollectionType::kNumberOfDeletedElementsOffset,
                         Representation::Smi());
  }

  template <typename CollectionType>
  static HObjectAccess ForOrderedHashTableNextTable() {
    return HObjectAccess(kInobject, CollectionType::kNextTableOffset);
  }

  template <typename CollectionType>
  static HObjectAccess ForOrderedHashTableBucket(int bucket) {
    return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
                                        (bucket * kPointerSize),
                         Representation::Smi());
  }

  // Access into the data table of an OrderedHashTable with a
  // known-at-compile-time bucket count.
  template <typename CollectionType, int kBucketCount>
  static HObjectAccess ForOrderedHashTableDataTableIndex(int index) {
    return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
                                        (kBucketCount * kPointerSize) +
                                        (index * kPointerSize));
  }

  inline bool Equals(HObjectAccess that) const {
    return value_ == that.value_;  // portion and offset must match
  }

 protected:
  void SetGVNFlags(HValue *instr, PropertyAccessType access_type);

 private:
  // internal use only; different parts of an object or array
  enum Portion {
    kMaps,             // map of an object
    kArrayLengths,     // the length of an array
    kStringLengths,    // the length of a string
    kElementsPointer,  // elements pointer
    kBackingStore,     // some field in the backing store
    kDouble,           // some double field
    kInobject,         // some other in-object field
    kExternalMemory    // some field in external memory
  };

  HObjectAccess() : value_(0) {}

  HObjectAccess(Portion portion, int offset,
                Representation representation = Representation::Tagged(),
                Handle<Name> name = Handle<Name>::null(),
                bool immutable = false, bool existing_inobject_property = true)
      : value_(PortionField::encode(portion) |
               RepresentationField::encode(representation.kind()) |
               ImmutableField::encode(immutable ? 1 : 0) |
               ExistingInobjectPropertyField::encode(
                   existing_inobject_property ? 1 : 0) |
               OffsetField::encode(offset)),
        name_(name) {
    // assert that the fields decode correctly
    DCHECK(this->offset() == offset);
    DCHECK(this->portion() == portion);
    DCHECK(this->immutable() == immutable);
    DCHECK(this->existing_inobject_property() == existing_inobject_property);
    DCHECK(RepresentationField::decode(value_) == representation.kind());
    DCHECK(!this->existing_inobject_property() || IsInobject());
  }

  class PortionField : public BitField<Portion, 0, 3> {};
  class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
  class ImmutableField : public BitField<bool, 7, 1> {};
  class ExistingInobjectPropertyField : public BitField<bool, 8, 1> {};
  class OffsetField : public BitField<int, 9, 23> {};

  uint32_t value_;  // encodes portion, representation, immutable, and offset
  Handle<Name> name_;

  friend class HLoadNamedField;
  friend class HStoreNamedField;
  friend class SideEffectsTracker;
  friend std::ostream& operator<<(std::ostream& os,
                                  const HObjectAccess& access);

  inline Portion portion() const {
    return PortionField::decode(value_);
  }
};


std::ostream& operator<<(std::ostream& os, const HObjectAccess& access);


class HLoadNamedField final : public HTemplateInstruction<2> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*,
                                 HValue*, HObjectAccess);
  DECLARE_INSTRUCTION_FACTORY_P5(HLoadNamedField, HValue*, HValue*,
                                 HObjectAccess, const UniqueSet<Map>*, HType);

  HValue* object() const { return OperandAt(0); }
  HValue* dependency() const {
    DCHECK(HasDependency());
    return OperandAt(1);
  }
  bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
  HObjectAccess access() const { return access_; }
  Representation field_representation() const {
      return access_.representation();
  }

  const UniqueSet<Map>* maps() const { return maps_; }

  bool HasEscapingOperandAt(int index) override { return false; }
  bool HasOutOfBoundsAccess(int size) override {
    return !access().IsInobject() || access().offset() >= size;
  }
  Representation RequiredInputRepresentation(int index) override {
    if (index == 0) {
      // object must be external in case of external memory access
      return access().IsExternalMemory() ? Representation::External()
                                         : Representation::Tagged();
    }
    DCHECK(index == 1);
    return Representation::None();
  }
  Range* InferRange(Zone* zone) override;
  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  bool CanBeReplacedWith(HValue* other) const {
    if (!CheckFlag(HValue::kCantBeReplaced)) return false;
    if (!type().Equals(other->type())) return false;
    if (!representation().Equals(other->representation())) return false;
    if (!other->IsLoadNamedField()) return true;
    HLoadNamedField* that = HLoadNamedField::cast(other);
    if (this->maps_ == that->maps_) return true;
    if (this->maps_ == NULL || that->maps_ == NULL) return false;
    return this->maps_->IsSubset(that->maps_);
  }

  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)

 protected:
  bool DataEquals(HValue* other) override {
    HLoadNamedField* that = HLoadNamedField::cast(other);
    if (!this->access_.Equals(that->access_)) return false;
    if (this->maps_ == that->maps_) return true;
    return (this->maps_ != NULL &&
            that->maps_ != NULL &&
            this->maps_->Equals(that->maps_));
  }

 private:
  HLoadNamedField(HValue* object,
                  HValue* dependency,
                  HObjectAccess access)
      : access_(access), maps_(NULL) {
    DCHECK_NOT_NULL(object);
    SetOperandAt(0, object);
    SetOperandAt(1, dependency ? dependency : object);

    Representation representation = access.representation();
    if (representation.IsInteger8() ||
        representation.IsUInteger8() ||
        representation.IsInteger16() ||
        representation.IsUInteger16()) {
      set_representation(Representation::Integer32());
    } else if (representation.IsSmi()) {
      set_type(HType::Smi());
      if (SmiValuesAre32Bits()) {
        set_representation(Representation::Integer32());
      } else {
        set_representation(representation);
      }
    } else if (representation.IsDouble() ||
               representation.IsExternal() ||
               representation.IsInteger32()) {
      set_representation(representation);
    } else if (representation.IsHeapObject()) {
      set_type(HType::HeapObject());
      set_representation(Representation::Tagged());
    } else {
      set_representation(Representation::Tagged());
    }
    access.SetGVNFlags(this, LOAD);
  }

  HLoadNamedField(HValue* object,
                  HValue* dependency,
                  HObjectAccess access,
                  const UniqueSet<Map>* maps,
                  HType type)
      : HTemplateInstruction<2>(type), access_(access), maps_(maps) {
    DCHECK_NOT_NULL(maps);
    DCHECK_NE(0, maps->size());

    DCHECK_NOT_NULL(object);
    SetOperandAt(0, object);
    SetOperandAt(1, dependency ? dependency : object);

    DCHECK(access.representation().IsHeapObject());
    DCHECK(type.IsHeapObject());
    set_representation(Representation::Tagged());

    access.SetGVNFlags(this, LOAD);
  }

  bool IsDeletable() const override { return true; }

  HObjectAccess access_;
  const UniqueSet<Map>* maps_;
};


class HLoadNamedGeneric final : public HTemplateInstruction<2> {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadNamedGeneric, HValue*,
                                              Handle<Name>, InlineCacheState);

  HValue* context() const { return OperandAt(0); }
  HValue* object() const { return OperandAt(1); }
  Handle<Name> name() const { return name_; }

  InlineCacheState initialization_state() const {
    return initialization_state_;
  }
  FeedbackVectorSlot slot() const { return slot_; }
  Handle<TypeFeedbackVector> feedback_vector() const {
    return feedback_vector_;
  }
  bool HasVectorAndSlot() const { return true; }
  void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
                        FeedbackVectorSlot slot) {
    feedback_vector_ = vector;
    slot_ = slot;
  }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)

 private:
  HLoadNamedGeneric(HValue* context, HValue* object, Handle<Name> name,
                    InlineCacheState initialization_state)
      : name_(name),
        initialization_state_(initialization_state) {
    SetOperandAt(0, context);
    SetOperandAt(1, object);
    set_representation(Representation::Tagged());
    SetAllSideEffects();
  }

  Handle<Name> name_;
  Handle<TypeFeedbackVector> feedback_vector_;
  FeedbackVectorSlot slot_;
  InlineCacheState initialization_state_;
};


class HLoadFunctionPrototype final : public HUnaryOperation {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);

  HValue* function() { return OperandAt(0); }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  explicit HLoadFunctionPrototype(HValue* function)
      : HUnaryOperation(function) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
    SetDependsOnFlag(kCalls);
  }
};

class ArrayInstructionInterface {
 public:
  virtual HValue* GetKey() = 0;
  virtual void SetKey(HValue* key) = 0;
  virtual ElementsKind elements_kind() const = 0;
  // TryIncreaseBaseOffset returns false if overflow would result.
  virtual bool TryIncreaseBaseOffset(uint32_t increase_by_value) = 0;
  virtual bool IsDehoisted() const = 0;
  virtual void SetDehoisted(bool is_dehoisted) = 0;
  virtual ~ArrayInstructionInterface() { }

  static Representation KeyedAccessIndexRequirement(Representation r) {
    return r.IsInteger32() || SmiValuesAre32Bits()
        ? Representation::Integer32() : Representation::Smi();
  }
};


static const int kDefaultKeyedHeaderOffsetSentinel = -1;

enum LoadKeyedHoleMode {
  NEVER_RETURN_HOLE,
  ALLOW_RETURN_HOLE,
  CONVERT_HOLE_TO_UNDEFINED
};


class HLoadKeyed final : public HTemplateInstruction<4>,
                         public ArrayInstructionInterface {
 public:
  DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
                                 ElementsKind);
  DECLARE_INSTRUCTION_FACTORY_P6(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
                                 ElementsKind, LoadKeyedHoleMode);
  DECLARE_INSTRUCTION_FACTORY_P7(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
                                 ElementsKind, LoadKeyedHoleMode, int);

  bool is_fixed_typed_array() const {
    return IsFixedTypedArrayElementsKind(elements_kind());
  }
  HValue* elements() const { return OperandAt(0); }
  HValue* key() const { return OperandAt(1); }
  HValue* dependency() const {
    DCHECK(HasDependency());
    return OperandAt(2);
  }
  bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
  HValue* backing_store_owner() const {
    DCHECK(HasBackingStoreOwner());
    return OperandAt(3);
  }
  bool HasBackingStoreOwner() const { return OperandAt(0) != OperandAt(3); }
  uint32_t base_offset() const { return BaseOffsetField::decode(bit_field_); }
  bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
  HValue* GetKey() override { return key(); }
  void SetKey(HValue* key) override { SetOperandAt(1, key); }
  bool IsDehoisted() const override {
    return IsDehoistedField::decode(bit_field_);
  }
  void SetDehoisted(bool is_dehoisted) override {
    bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
  }
  ElementsKind elements_kind() const override {
    return ElementsKindField::decode(bit_field_);
  }
  LoadKeyedHoleMode hole_mode() const {
    return HoleModeField::decode(bit_field_);
  }

  Representation RequiredInputRepresentation(int index) override {
    // kind_fast:                 tagged[int32] (none)
    // kind_double:               tagged[int32] (none)
    // kind_fixed_typed_array:    external[int32] (none)
    // kind_external:             external[int32] (none)
    if (index == 0) {
      return is_fixed_typed_array() ? Representation::External()
                                    : Representation::Tagged();
    }
    if (index == 1) {
      return ArrayInstructionInterface::KeyedAccessIndexRequirement(
          OperandAt(1)->representation());
    }
    if (index == 2) {
      return Representation::None();
    }
    DCHECK_EQ(3, index);
    return HasBackingStoreOwner() ? Representation::Tagged()
                                  : Representation::None();
  }

  Representation observed_input_representation(int index) override {
    return RequiredInputRepresentation(index);
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  bool UsesMustHandleHole() const;
  bool AllUsesCanTreatHoleAsNaN() const;
  bool RequiresHoleCheck() const;

  Range* InferRange(Zone* zone) override;

  DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)

 protected:
  bool DataEquals(HValue* other) override {
    if (!other->IsLoadKeyed()) return false;
    HLoadKeyed* other_load = HLoadKeyed::cast(other);

    if (base_offset() != other_load->base_offset()) return false;
    return elements_kind() == other_load->elements_kind();
  }

 private:
  HLoadKeyed(HValue* obj, HValue* key, HValue* dependency,
             HValue* backing_store_owner, ElementsKind elements_kind,
             LoadKeyedHoleMode mode = NEVER_RETURN_HOLE,
             int offset = kDefaultKeyedHeaderOffsetSentinel)
      : bit_field_(0) {
    offset = offset == kDefaultKeyedHeaderOffsetSentinel
        ? GetDefaultHeaderSizeForElementsKind(elements_kind)
        : offset;
    bit_field_ = ElementsKindField::encode(elements_kind) |
        HoleModeField::encode(mode) |
        BaseOffsetField::encode(offset);

    SetOperandAt(0, obj);
    SetOperandAt(1, key);
    SetOperandAt(2, dependency != nullptr ? dependency : obj);
    SetOperandAt(3, backing_store_owner != nullptr ? backing_store_owner : obj);
    DCHECK_EQ(HasBackingStoreOwner(), is_fixed_typed_array());

    if (!is_fixed_typed_array()) {
      // I can detect the case between storing double (holey and fast) and
      // smi/object by looking at elements_kind_.
      DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
             IsFastDoubleElementsKind(elements_kind));

      if (IsFastSmiOrObjectElementsKind(elements_kind)) {
        if (IsFastSmiElementsKind(elements_kind) &&
            (!IsHoleyElementsKind(elements_kind) ||
             mode == NEVER_RETURN_HOLE)) {
          set_type(HType::Smi());
          if (SmiValuesAre32Bits() && !RequiresHoleCheck()) {
            set_representation(Representation::Integer32());
          } else {
            set_representation(Representation::Smi());
          }
        } else {
          set_representation(Representation::Tagged());
        }

        SetDependsOnFlag(kArrayElements);
      } else {
        set_representation(Representation::Double());
        SetDependsOnFlag(kDoubleArrayElements);
      }
    } else {
      if (elements_kind == FLOAT32_ELEMENTS ||
          elements_kind == FLOAT64_ELEMENTS) {
        set_representation(Representation::Double());
      } else {
        set_representation(Representation::Integer32());
      }

      if (is_fixed_typed_array()) {
        SetDependsOnFlag(kExternalMemory);
        SetDependsOnFlag(kTypedArrayElements);
      } else {
        UNREACHABLE();
      }
      // Native code could change the specialized array.
      SetDependsOnFlag(kCalls);
    }

    SetFlag(kUseGVN);
  }

  bool IsDeletable() const override { return !RequiresHoleCheck(); }

  // Establish some checks around our packed fields
  enum LoadKeyedBits {
    kBitsForElementsKind = 5,
    kBitsForHoleMode = 2,
    kBitsForBaseOffset = 24,
    kBitsForIsDehoisted = 1,

    kStartElementsKind = 0,
    kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
    kStartBaseOffset = kStartHoleMode + kBitsForHoleMode,
    kStartIsDehoisted = kStartBaseOffset + kBitsForBaseOffset
  };

  STATIC_ASSERT((kBitsForElementsKind + kBitsForHoleMode + kBitsForBaseOffset +
                 kBitsForIsDehoisted) <= sizeof(uint32_t) * 8);
  STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
  class ElementsKindField:
    public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
    {};  // NOLINT
  class HoleModeField:
    public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
    {};  // NOLINT
  class BaseOffsetField:
    public BitField<uint32_t, kStartBaseOffset, kBitsForBaseOffset>
    {};  // NOLINT
  class IsDehoistedField:
    public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
    {};  // NOLINT
  uint32_t bit_field_;
};


class HLoadKeyedGeneric final : public HTemplateInstruction<3> {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadKeyedGeneric, HValue*,
                                              HValue*, InlineCacheState);
  HValue* object() const { return OperandAt(0); }
  HValue* key() const { return OperandAt(1); }
  HValue* context() const { return OperandAt(2); }
  InlineCacheState initialization_state() const {
    return initialization_state_;
  }
  FeedbackVectorSlot slot() const { return slot_; }
  Handle<TypeFeedbackVector> feedback_vector() const {
    return feedback_vector_;
  }
  bool HasVectorAndSlot() const {
    DCHECK(initialization_state_ == MEGAMORPHIC || !feedback_vector_.is_null());
    return !feedback_vector_.is_null();
  }
  void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
                        FeedbackVectorSlot slot) {
    feedback_vector_ = vector;
    slot_ = slot;
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  Representation RequiredInputRepresentation(int index) override {
    // tagged[tagged]
    return Representation::Tagged();
  }

  HValue* Canonicalize() override;

  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)

 private:
  HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key,
                    InlineCacheState initialization_state)
      : initialization_state_(initialization_state) {
    set_representation(Representation::Tagged());
    SetOperandAt(0, obj);
    SetOperandAt(1, key);
    SetOperandAt(2, context);
    SetAllSideEffects();
  }

  Handle<TypeFeedbackVector> feedback_vector_;
  FeedbackVectorSlot slot_;
  InlineCacheState initialization_state_;
};


// Indicates whether the store is a store to an entry that was previously
// initialized or not.
enum StoreFieldOrKeyedMode {
  // The entry could be either previously initialized or not.
  INITIALIZING_STORE,
  // At the time of this store it is guaranteed that the entry is already
  // initialized.
  STORE_TO_INITIALIZED_ENTRY
};


class HStoreNamedField final : public HTemplateInstruction<3> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
                                 HObjectAccess, HValue*);
  DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue*,
                                 HObjectAccess, HValue*, StoreFieldOrKeyedMode);

  DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)

  bool HasEscapingOperandAt(int index) override { return index == 1; }
  bool HasOutOfBoundsAccess(int size) override {
    return !access().IsInobject() || access().offset() >= size;
  }
  Representation RequiredInputRepresentation(int index) override {
    if (index == 0 && access().IsExternalMemory()) {
      // object must be external in case of external memory access
      return Representation::External();
    } else if (index == 1) {
      if (field_representation().IsInteger8() ||
          field_representation().IsUInteger8() ||
          field_representation().IsInteger16() ||
          field_representation().IsUInteger16() ||
          field_representation().IsInteger32()) {
        return Representation::Integer32();
      } else if (field_representation().IsDouble()) {
        return field_representation();
      } else if (field_representation().IsSmi()) {
        if (SmiValuesAre32Bits() &&
            store_mode() == STORE_TO_INITIALIZED_ENTRY) {
          return Representation::Integer32();
        }
        return field_representation();
      } else if (field_representation().IsExternal()) {
        return Representation::External();
      }
    }
    return Representation::Tagged();
  }
  bool HandleSideEffectDominator(GVNFlag side_effect,
                                 HValue* dominator) override {
    DCHECK(side_effect == kNewSpacePromotion);
    if (!FLAG_use_write_barrier_elimination) return false;
    dominator_ = dominator;
    return false;
  }
  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  HValue* object() const { return OperandAt(0); }
  HValue* value() const { return OperandAt(1); }
  HValue* transition() const { return OperandAt(2); }

  HObjectAccess access() const { return access_; }
  HValue* dominator() const { return dominator_; }
  bool has_transition() const { return HasTransitionField::decode(bit_field_); }
  StoreFieldOrKeyedMode store_mode() const {
    return StoreModeField::decode(bit_field_);
  }

  Handle<Map> transition_map() const {
    if (has_transition()) {
      return Handle<Map>::cast(
          HConstant::cast(transition())->handle(isolate()));
    } else {
      return Handle<Map>();
    }
  }

  void SetTransition(HConstant* transition) {
    DCHECK(!has_transition());  // Only set once.
    SetOperandAt(2, transition);
    bit_field_ = HasTransitionField::update(bit_field_, true);
    SetChangesFlag(kMaps);
  }

  bool NeedsWriteBarrier() const {
    DCHECK(!field_representation().IsDouble() ||
           (FLAG_unbox_double_fields && access_.IsInobject()) ||
           !has_transition());
    if (field_representation().IsDouble()) return false;
    if (field_representation().IsSmi()) return false;
    if (field_representation().IsInteger32()) return false;
    if (field_representation().IsExternal()) return false;
    return StoringValueNeedsWriteBarrier(value()) &&
        ReceiverObjectNeedsWriteBarrier(object(), value(), dominator());
  }

  bool NeedsWriteBarrierForMap() {
    return ReceiverObjectNeedsWriteBarrier(object(), transition(),
                                           dominator());
  }

  SmiCheck SmiCheckForWriteBarrier() const {
    if (field_representation().IsHeapObject()) return OMIT_SMI_CHECK;
    if (value()->type().IsHeapObject()) return OMIT_SMI_CHECK;
    return INLINE_SMI_CHECK;
  }

  PointersToHereCheck PointersToHereCheckForValue() const {
    return PointersToHereCheckForObject(value(), dominator());
  }

  Representation field_representation() const {
    return access_.representation();
  }

  void UpdateValue(HValue* value) {
    SetOperandAt(1, value);
  }

  bool CanBeReplacedWith(HStoreNamedField* that) const {
    if (!this->access().Equals(that->access())) return false;
    if (SmiValuesAre32Bits() &&
        this->field_representation().IsSmi() &&
        this->store_mode() == INITIALIZING_STORE &&
        that->store_mode() == STORE_TO_INITIALIZED_ENTRY) {
      // We cannot replace an initializing store to a smi field with a store to
      // an initialized entry on 64-bit architectures (with 32-bit smis).
      return false;
    }
    return true;
  }

 private:
  HStoreNamedField(HValue* obj, HObjectAccess access, HValue* val,
                   StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
      : access_(access),
        dominator_(NULL),
        bit_field_(HasTransitionField::encode(false) |
                   StoreModeField::encode(store_mode)) {
    // Stores to a non existing in-object property are allowed only to the
    // newly allocated objects (via HAllocate or HInnerAllocatedObject).
    DCHECK(!access.IsInobject() || access.existing_inobject_property() ||
           obj->IsAllocate() || obj->IsInnerAllocatedObject());
    SetOperandAt(0, obj);
    SetOperandAt(1, val);
    SetOperandAt(2, obj);
    access.SetGVNFlags(this, STORE);
  }

  class HasTransitionField : public BitField<bool, 0, 1> {};
  class StoreModeField : public BitField<StoreFieldOrKeyedMode, 1, 1> {};

  HObjectAccess access_;
  HValue* dominator_;
  uint32_t bit_field_;
};


class HStoreNamedGeneric final : public HTemplateInstruction<3> {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HStoreNamedGeneric, HValue*,
                                              Handle<Name>, HValue*,
                                              LanguageMode, InlineCacheState);
  HValue* object() const { return OperandAt(0); }
  HValue* value() const { return OperandAt(1); }
  HValue* context() const { return OperandAt(2); }
  Handle<Name> name() const { return name_; }
  LanguageMode language_mode() const { return language_mode_; }
  InlineCacheState initialization_state() const {
    return initialization_state_;
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  FeedbackVectorSlot slot() const { return slot_; }
  Handle<TypeFeedbackVector> feedback_vector() const {
    return feedback_vector_;
  }
  bool HasVectorAndSlot() const { return true; }
  void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
                        FeedbackVectorSlot slot) {
    feedback_vector_ = vector;
    slot_ = slot;
  }

  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)

 private:
  HStoreNamedGeneric(HValue* context, HValue* object, Handle<Name> name,
                     HValue* value, LanguageMode language_mode,
                     InlineCacheState initialization_state)
      : name_(name),
        language_mode_(language_mode),
        initialization_state_(initialization_state) {
    SetOperandAt(0, object);
    SetOperandAt(1, value);
    SetOperandAt(2, context);
    SetAllSideEffects();
  }

  Handle<Name> name_;
  Handle<TypeFeedbackVector> feedback_vector_;
  FeedbackVectorSlot slot_;
  LanguageMode language_mode_;
  InlineCacheState initialization_state_;
};


class HStoreKeyed final : public HTemplateInstruction<4>,
                          public ArrayInstructionInterface {
 public:
  DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*,
                                 HValue*, ElementsKind);
  DECLARE_INSTRUCTION_FACTORY_P6(HStoreKeyed, HValue*, HValue*, HValue*,
                                 HValue*, ElementsKind, StoreFieldOrKeyedMode);
  DECLARE_INSTRUCTION_FACTORY_P7(HStoreKeyed, HValue*, HValue*, HValue*,
                                 HValue*, ElementsKind, StoreFieldOrKeyedMode,
                                 int);

  Representation RequiredInputRepresentation(int index) override {
    // kind_fast:               tagged[int32] = tagged
    // kind_double:             tagged[int32] = double
    // kind_smi   :             tagged[int32] = smi
    // kind_fixed_typed_array:  tagged[int32] = (double | int32)
    // kind_external:           external[int32] = (double | int32)
    if (index == 0) {
      return is_fixed_typed_array() ? Representation::External()
                                    : Representation::Tagged();
    } else if (index == 1) {
      return ArrayInstructionInterface::KeyedAccessIndexRequirement(
          OperandAt(1)->representation());
    } else if (index == 2) {
      return RequiredValueRepresentation(elements_kind(), store_mode());
    }

    DCHECK_EQ(3, index);
    return HasBackingStoreOwner() ? Representation::Tagged()
                                  : Representation::None();
  }

  static Representation RequiredValueRepresentation(
      ElementsKind kind, StoreFieldOrKeyedMode mode) {
    if (IsDoubleOrFloatElementsKind(kind)) {
      return Representation::Double();
    }

    if (kind == FAST_SMI_ELEMENTS && SmiValuesAre32Bits() &&
        mode == STORE_TO_INITIALIZED_ENTRY) {
      return Representation::Integer32();
    }

    if (IsFastSmiElementsKind(kind)) {
      return Representation::Smi();
    }

    if (IsFixedTypedArrayElementsKind(kind)) {
      return Representation::Integer32();
    }
    return Representation::Tagged();
  }

  bool is_fixed_typed_array() const {
    return IsFixedTypedArrayElementsKind(elements_kind());
  }

  Representation observed_input_representation(int index) override {
    if (index != 2) return RequiredInputRepresentation(index);
    if (IsUninitialized()) {
      return Representation::None();
    }
    Representation r =
        RequiredValueRepresentation(elements_kind(), store_mode());
    // For fast object elements kinds, don't assume anything.
    if (r.IsTagged()) return Representation::None();
    return r;
  }

  HValue* elements() const { return OperandAt(0); }
  HValue* key() const { return OperandAt(1); }
  HValue* value() const { return OperandAt(2); }
  HValue* backing_store_owner() const {
    DCHECK(HasBackingStoreOwner());
    return OperandAt(3);
  }
  bool HasBackingStoreOwner() const { return OperandAt(0) != OperandAt(3); }
  bool value_is_smi() const { return IsFastSmiElementsKind(elements_kind()); }
  StoreFieldOrKeyedMode store_mode() const {
    return StoreModeField::decode(bit_field_);
  }
  ElementsKind elements_kind() const override {
    return ElementsKindField::decode(bit_field_);
  }
  uint32_t base_offset() const { return base_offset_; }
  bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
  HValue* GetKey() override { return key(); }
  void SetKey(HValue* key) override { SetOperandAt(1, key); }
  bool IsDehoisted() const override {
    return IsDehoistedField::decode(bit_field_);
  }
  void SetDehoisted(bool is_dehoisted) override {
    bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
  }
  bool IsUninitialized() { return IsUninitializedField::decode(bit_field_); }
  void SetUninitialized(bool is_uninitialized) {
    bit_field_ = IsUninitializedField::update(bit_field_, is_uninitialized);
  }

  bool IsConstantHoleStore() {
    return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
  }

  bool HandleSideEffectDominator(GVNFlag side_effect,
                                 HValue* dominator) override {
    DCHECK(side_effect == kNewSpacePromotion);
    dominator_ = dominator;
    return false;
  }

  HValue* dominator() const { return dominator_; }

  bool NeedsWriteBarrier() {
    if (value_is_smi()) {
      return false;
    } else {
      return StoringValueNeedsWriteBarrier(value()) &&
          ReceiverObjectNeedsWriteBarrier(elements(), value(), dominator());
    }
  }

  PointersToHereCheck PointersToHereCheckForValue() const {
    return PointersToHereCheckForObject(value(), dominator());
  }

  bool NeedsCanonicalization();

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)

 private:
  HStoreKeyed(HValue* obj, HValue* key, HValue* val,
              HValue* backing_store_owner, ElementsKind elements_kind,
              StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE,
              int offset = kDefaultKeyedHeaderOffsetSentinel)
      : base_offset_(offset == kDefaultKeyedHeaderOffsetSentinel
                         ? GetDefaultHeaderSizeForElementsKind(elements_kind)
                         : offset),
        bit_field_(IsDehoistedField::encode(false) |
                   IsUninitializedField::encode(false) |
                   StoreModeField::encode(store_mode) |
                   ElementsKindField::encode(elements_kind)),
        dominator_(NULL) {
    SetOperandAt(0, obj);
    SetOperandAt(1, key);
    SetOperandAt(2, val);
    SetOperandAt(3, backing_store_owner != nullptr ? backing_store_owner : obj);
    DCHECK_EQ(HasBackingStoreOwner(), is_fixed_typed_array());

    if (IsFastObjectElementsKind(elements_kind)) {
      SetFlag(kTrackSideEffectDominators);
      SetDependsOnFlag(kNewSpacePromotion);
    }
    if (IsFastDoubleElementsKind(elements_kind)) {
      SetChangesFlag(kDoubleArrayElements);
    } else if (IsFastSmiElementsKind(elements_kind)) {
      SetChangesFlag(kArrayElements);
    } else if (is_fixed_typed_array()) {
      SetChangesFlag(kTypedArrayElements);
      SetChangesFlag(kExternalMemory);
      SetFlag(kAllowUndefinedAsNaN);
    } else {
      SetChangesFlag(kArrayElements);
    }

    // {UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
    if (elements_kind >= UINT8_ELEMENTS && elements_kind <= INT32_ELEMENTS) {
      SetFlag(kTruncatingToInt32);
    }
  }

  class IsDehoistedField : public BitField<bool, 0, 1> {};
  class IsUninitializedField : public BitField<bool, 1, 1> {};
  class StoreModeField : public BitField<StoreFieldOrKeyedMode, 2, 1> {};
  class ElementsKindField : public BitField<ElementsKind, 3, 5> {};

  uint32_t base_offset_;
  uint32_t bit_field_;
  HValue* dominator_;
};


class HStoreKeyedGeneric final : public HTemplateInstruction<4> {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HStoreKeyedGeneric, HValue*,
                                              HValue*, HValue*, LanguageMode,
                                              InlineCacheState);

  HValue* object() const { return OperandAt(0); }
  HValue* key() const { return OperandAt(1); }
  HValue* value() const { return OperandAt(2); }
  HValue* context() const { return OperandAt(3); }
  LanguageMode language_mode() const { return language_mode_; }
  InlineCacheState initialization_state() const {
    return initialization_state_;
  }

  Representation RequiredInputRepresentation(int index) override {
    // tagged[tagged] = tagged
    return Representation::Tagged();
  }

  FeedbackVectorSlot slot() const { return slot_; }
  Handle<TypeFeedbackVector> feedback_vector() const {
    return feedback_vector_;
  }
  bool HasVectorAndSlot() const {
    return !feedback_vector_.is_null();
  }
  void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
                        FeedbackVectorSlot slot) {
    feedback_vector_ = vector;
    slot_ = slot;
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)

 private:
  HStoreKeyedGeneric(HValue* context, HValue* object, HValue* key,
                     HValue* value, LanguageMode language_mode,
                     InlineCacheState initialization_state)
      : language_mode_(language_mode),
        initialization_state_(initialization_state) {
    SetOperandAt(0, object);
    SetOperandAt(1, key);
    SetOperandAt(2, value);
    SetOperandAt(3, context);
    SetAllSideEffects();
  }

  Handle<TypeFeedbackVector> feedback_vector_;
  FeedbackVectorSlot slot_;
  LanguageMode language_mode_;
  InlineCacheState initialization_state_;
};


class HTransitionElementsKind final : public HTemplateInstruction<2> {
 public:
  inline static HTransitionElementsKind* New(Isolate* isolate, Zone* zone,
                                             HValue* context, HValue* object,
                                             Handle<Map> original_map,
                                             Handle<Map> transitioned_map) {
    return new(zone) HTransitionElementsKind(context, object,
                                             original_map, transitioned_map);
  }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  HValue* object() const { return OperandAt(0); }
  HValue* context() const { return OperandAt(1); }
  Unique<Map> original_map() const { return original_map_; }
  Unique<Map> transitioned_map() const { return transitioned_map_; }
  ElementsKind from_kind() const {
    return FromElementsKindField::decode(bit_field_);
  }
  ElementsKind to_kind() const {
    return ToElementsKindField::decode(bit_field_);
  }
  bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)

 protected:
  bool DataEquals(HValue* other) override {
    HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
    return original_map_ == instr->original_map_ &&
           transitioned_map_ == instr->transitioned_map_;
  }

  int RedefinedOperandIndex() override { return 0; }

 private:
  HTransitionElementsKind(HValue* context, HValue* object,
                          Handle<Map> original_map,
                          Handle<Map> transitioned_map)
      : original_map_(Unique<Map>(original_map)),
        transitioned_map_(Unique<Map>(transitioned_map)),
        bit_field_(
            FromElementsKindField::encode(original_map->elements_kind()) |
            ToElementsKindField::encode(transitioned_map->elements_kind()) |
            MapIsStableField::encode(transitioned_map->is_stable())) {
    SetOperandAt(0, object);
    SetOperandAt(1, context);
    SetFlag(kUseGVN);
    SetChangesFlag(kElementsKind);
    if (!IsSimpleMapChangeTransition(from_kind(), to_kind())) {
      SetChangesFlag(kElementsPointer);
      SetChangesFlag(kNewSpacePromotion);
    }
    set_representation(Representation::Tagged());
  }

  class FromElementsKindField : public BitField<ElementsKind, 0, 5> {};
  class ToElementsKindField : public BitField<ElementsKind, 5, 5> {};
  class MapIsStableField : public BitField<bool, 10, 1> {};

  Unique<Map> original_map_;
  Unique<Map> transitioned_map_;
  uint32_t bit_field_;
};


class HStringAdd final : public HBinaryOperation {
 public:
  static HInstruction* New(
      Isolate* isolate, Zone* zone, HValue* context, HValue* left,
      HValue* right, PretenureFlag pretenure_flag = NOT_TENURED,
      StringAddFlags flags = STRING_ADD_CHECK_BOTH,
      Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null());

  StringAddFlags flags() const { return flags_; }
  PretenureFlag pretenure_flag() const { return pretenure_flag_; }

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  DECLARE_CONCRETE_INSTRUCTION(StringAdd)

 protected:
  bool DataEquals(HValue* other) override {
    return flags_ == HStringAdd::cast(other)->flags_ &&
        pretenure_flag_ == HStringAdd::cast(other)->pretenure_flag_;
  }

 private:
  HStringAdd(HValue* context, HValue* left, HValue* right,
             PretenureFlag pretenure_flag, StringAddFlags flags,
             Handle<AllocationSite> allocation_site)
      : HBinaryOperation(context, left, right, HType::String()),
        flags_(flags),
        pretenure_flag_(pretenure_flag) {
    set_representation(Representation::Tagged());
    if ((flags & STRING_ADD_CONVERT) == STRING_ADD_CONVERT) {
      SetAllSideEffects();
      ClearFlag(kUseGVN);
    } else {
      SetChangesFlag(kNewSpacePromotion);
      SetFlag(kUseGVN);
    }
    SetDependsOnFlag(kMaps);
    if (FLAG_trace_pretenuring) {
      PrintF("HStringAdd with AllocationSite %p %s\n",
             allocation_site.is_null()
                 ? static_cast<void*>(NULL)
                 : static_cast<void*>(*allocation_site),
             pretenure_flag == TENURED ? "tenured" : "not tenured");
    }
  }

  bool IsDeletable() const final {
    return (flags_ & STRING_ADD_CONVERT) != STRING_ADD_CONVERT;
  }

  const StringAddFlags flags_;
  const PretenureFlag pretenure_flag_;
};


class HStringCharCodeAt final : public HTemplateInstruction<3> {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HStringCharCodeAt,
                                              HValue*,
                                              HValue*);

  Representation RequiredInputRepresentation(int index) override {
    // The index is supposed to be Integer32.
    return index == 2
        ? Representation::Integer32()
        : Representation::Tagged();
  }

  HValue* context() const { return OperandAt(0); }
  HValue* string() const { return OperandAt(1); }
  HValue* index() const { return OperandAt(2); }

  DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)

 protected:
  bool DataEquals(HValue* other) override { return true; }

  Range* InferRange(Zone* zone) override {
    return new(zone) Range(0, String::kMaxUtf16CodeUnit);
  }

 private:
  HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
    SetOperandAt(0, context);
    SetOperandAt(1, string);
    SetOperandAt(2, index);
    set_representation(Representation::Integer32());
    SetFlag(kUseGVN);
    SetDependsOnFlag(kMaps);
    SetDependsOnFlag(kStringChars);
    SetChangesFlag(kNewSpacePromotion);
  }

  // No side effects: runtime function assumes string + number inputs.
  bool IsDeletable() const override { return true; }
};


class HStringCharFromCode final : public HTemplateInstruction<2> {
 public:
  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
                           HValue* char_code);

  Representation RequiredInputRepresentation(int index) override {
    return index == 0
        ? Representation::Tagged()
        : Representation::Integer32();
  }

  HValue* context() const { return OperandAt(0); }
  HValue* value() const { return OperandAt(1); }

  bool DataEquals(HValue* other) override { return true; }

  DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)

 private:
  HStringCharFromCode(HValue* context, HValue* char_code)
      : HTemplateInstruction<2>(HType::String()) {
    SetOperandAt(0, context);
    SetOperandAt(1, char_code);
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
    SetChangesFlag(kNewSpacePromotion);
  }

  bool IsDeletable() const override {
    return !value()->ToNumberCanBeObserved();
  }
};


class HTypeof final : public HTemplateInstruction<2> {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HTypeof, HValue*);

  HValue* context() const { return OperandAt(0); }
  HValue* value() const { return OperandAt(1); }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  DECLARE_CONCRETE_INSTRUCTION(Typeof)

 private:
  explicit HTypeof(HValue* context, HValue* value) {
    SetOperandAt(0, context);
    SetOperandAt(1, value);
    set_representation(Representation::Tagged());
  }

  bool IsDeletable() const override { return true; }
};


class HTrapAllocationMemento final : public HTemplateInstruction<1> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  HValue* object() { return OperandAt(0); }

  DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)

 private:
  explicit HTrapAllocationMemento(HValue* obj) {
    SetOperandAt(0, obj);
  }
};


class HMaybeGrowElements final : public HTemplateInstruction<5> {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(HMaybeGrowElements, HValue*,
                                              HValue*, HValue*, HValue*, bool,
                                              ElementsKind);

  Representation RequiredInputRepresentation(int index) override {
    if (index < 3) {
      return Representation::Tagged();
    }
    DCHECK(index == 3 || index == 4);
    return Representation::Integer32();
  }

  HValue* context() const { return OperandAt(0); }
  HValue* object() const { return OperandAt(1); }
  HValue* elements() const { return OperandAt(2); }
  HValue* key() const { return OperandAt(3); }
  HValue* current_capacity() const { return OperandAt(4); }

  bool is_js_array() const { return is_js_array_; }
  ElementsKind kind() const { return kind_; }

  DECLARE_CONCRETE_INSTRUCTION(MaybeGrowElements)

 protected:
  bool DataEquals(HValue* other) override { return true; }

 private:
  explicit HMaybeGrowElements(HValue* context, HValue* object, HValue* elements,
                              HValue* key, HValue* current_capacity,
                              bool is_js_array, ElementsKind kind) {
    is_js_array_ = is_js_array;
    kind_ = kind;

    SetOperandAt(0, context);
    SetOperandAt(1, object);
    SetOperandAt(2, elements);
    SetOperandAt(3, key);
    SetOperandAt(4, current_capacity);

    SetFlag(kUseGVN);
    SetChangesFlag(kElementsPointer);
    SetChangesFlag(kNewSpacePromotion);
    set_representation(Representation::Tagged());
  }

  bool is_js_array_;
  ElementsKind kind_;
};


class HSeqStringGetChar final : public HTemplateInstruction<2> {
 public:
  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
                           String::Encoding encoding, HValue* string,
                           HValue* index);

  Representation RequiredInputRepresentation(int index) override {
    return (index == 0) ? Representation::Tagged()
                        : Representation::Integer32();
  }

  String::Encoding encoding() const { return encoding_; }
  HValue* string() const { return OperandAt(0); }
  HValue* index() const { return OperandAt(1); }

  DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)

 protected:
  bool DataEquals(HValue* other) override {
    return encoding() == HSeqStringGetChar::cast(other)->encoding();
  }

  Range* InferRange(Zone* zone) override {
    if (encoding() == String::ONE_BYTE_ENCODING) {
      return new(zone) Range(0, String::kMaxOneByteCharCode);
    } else {
      DCHECK_EQ(String::TWO_BYTE_ENCODING, encoding());
      return  new(zone) Range(0, String::kMaxUtf16CodeUnit);
    }
  }

 private:
  HSeqStringGetChar(String::Encoding encoding,
                    HValue* string,
                    HValue* index) : encoding_(encoding) {
    SetOperandAt(0, string);
    SetOperandAt(1, index);
    set_representation(Representation::Integer32());
    SetFlag(kUseGVN);
    SetDependsOnFlag(kStringChars);
  }

  bool IsDeletable() const override { return true; }

  String::Encoding encoding_;
};


class HSeqStringSetChar final : public HTemplateInstruction<4> {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(
      HSeqStringSetChar, String::Encoding,
      HValue*, HValue*, HValue*);

  String::Encoding encoding() { return encoding_; }
  HValue* context() { return OperandAt(0); }
  HValue* string() { return OperandAt(1); }
  HValue* index() { return OperandAt(2); }
  HValue* value() { return OperandAt(3); }

  Representation RequiredInputRepresentation(int index) override {
    return (index <= 1) ? Representation::Tagged()
                        : Representation::Integer32();
  }

  DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)

 private:
  HSeqStringSetChar(HValue* context,
                    String::Encoding encoding,
                    HValue* string,
                    HValue* index,
                    HValue* value) : encoding_(encoding) {
    SetOperandAt(0, context);
    SetOperandAt(1, string);
    SetOperandAt(2, index);
    SetOperandAt(3, value);
    set_representation(Representation::Tagged());
    SetChangesFlag(kStringChars);
  }

  String::Encoding encoding_;
};


class HCheckMapValue final : public HTemplateInstruction<2> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  HType CalculateInferredType() override {
    if (value()->type().IsHeapObject()) return value()->type();
    return HType::HeapObject();
  }

  HValue* value() const { return OperandAt(0); }
  HValue* map() const { return OperandAt(1); }

  HValue* Canonicalize() override;

  DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)

 protected:
  int RedefinedOperandIndex() override { return 0; }

  bool DataEquals(HValue* other) override { return true; }

 private:
  HCheckMapValue(HValue* value, HValue* map)
      : HTemplateInstruction<2>(HType::HeapObject()) {
    SetOperandAt(0, value);
    SetOperandAt(1, map);
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
    SetDependsOnFlag(kMaps);
    SetDependsOnFlag(kElementsKind);
  }
};


class HForInPrepareMap final : public HTemplateInstruction<2> {
 public:
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HForInPrepareMap, HValue*);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  HValue* context() const { return OperandAt(0); }
  HValue* enumerable() const { return OperandAt(1); }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  HType CalculateInferredType() override { return HType::Tagged(); }

  DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);

 private:
  HForInPrepareMap(HValue* context,
                   HValue* object) {
    SetOperandAt(0, context);
    SetOperandAt(1, object);
    set_representation(Representation::Tagged());
    SetAllSideEffects();
  }
};


class HForInCacheArray final : public HTemplateInstruction<2> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);

  Representation RequiredInputRepresentation(int index) override {
    return Representation::Tagged();
  }

  HValue* enumerable() const { return OperandAt(0); }
  HValue* map() const { return OperandAt(1); }
  int idx() const { return idx_; }

  HForInCacheArray* index_cache() {
    return index_cache_;
  }

  void set_index_cache(HForInCacheArray* index_cache) {
    index_cache_ = index_cache;
  }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  HType CalculateInferredType() override { return HType::Tagged(); }

  DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);

 private:
  HForInCacheArray(HValue* enumerable,
                   HValue* keys,
                   int idx) : idx_(idx) {
    SetOperandAt(0, enumerable);
    SetOperandAt(1, keys);
    set_representation(Representation::Tagged());
  }

  int idx_;
  HForInCacheArray* index_cache_;
};


class HLoadFieldByIndex final : public HTemplateInstruction<2> {
 public:
  DECLARE_INSTRUCTION_FACTORY_P2(HLoadFieldByIndex, HValue*, HValue*);

  HLoadFieldByIndex(HValue* object,
                    HValue* index) {
    SetOperandAt(0, object);
    SetOperandAt(1, index);
    SetChangesFlag(kNewSpacePromotion);
    set_representation(Representation::Tagged());
  }

  Representation RequiredInputRepresentation(int index) override {
    if (index == 1) {
      return Representation::Smi();
    } else {
      return Representation::Tagged();
    }
  }

  HValue* object() const { return OperandAt(0); }
  HValue* index() const { return OperandAt(1); }

  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT

  HType CalculateInferredType() override { return HType::Tagged(); }

  DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);

 private:
  bool IsDeletable() const override { return true; }
};

#undef DECLARE_INSTRUCTION
#undef DECLARE_CONCRETE_INSTRUCTION

}  // namespace internal
}  // namespace v8

#endif  // V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_
