// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef V8_HYDROGEN_INSTRUCTIONS_H_
#define V8_HYDROGEN_INSTRUCTIONS_H_

#include "v8.h"
#include "code-stubs.h"
#include "string-stream.h"
#include "zone.h"

namespace v8 {
namespace internal {

// Forward declarations.
class HBasicBlock;
class HEnvironment;
class HInstruction;
class HLoopInformation;
class HValue;
class LInstruction;
class LChunkBuilder;


// Type hierarchy:
//
// HValue
//   HInstruction
//     HAccessArgumentsAt
//     HApplyArguments
//     HArgumentsElements
//     HArgumentsLength
//     HArgumentsObject
//     HBinaryOperation
//       HArithmeticBinaryOperation
//         HAdd
//         HDiv
//         HMod
//         HMul
//         HSub
//       HBitwiseBinaryOperation
//         HBitAnd
//         HBitOr
//         HBitXor
//         HSar
//         HShl
//         HShr
//       HBoundsCheck
//       HCompare
//       HCompareJSObjectEq
//       HInstanceOf
//       HInstanceOfKnownGlobal
//       HLoadKeyed
//         HLoadKeyedFastElement
//         HLoadKeyedGeneric
//       HPower
//       HStoreNamed
//         HStoreNamedField
//         HStoreNamedGeneric
//     HBlockEntry
//     HCall
//       HCallConstantFunction
//       HCallFunction
//       HCallGlobal
//       HCallKeyed
//       HCallKnownGlobal
//       HCallNamed
//       HCallNew
//       HCallRuntime
//     HCallStub
//     HConstant
//     HControlInstruction
//       HDeoptimize
//       HGoto
//       HUnaryControlInstruction
//         HBranch
//         HCompareMapAndBranch
//         HReturn
//         HThrow
//     HEnterInlined
//     HFunctionLiteral
//     HGlobalObject
//     HGlobalReceiver
//     HLeaveInlined
//     HLoadGlobal
//     HMaterializedLiteral
//       HArrayLiteral
//       HObjectLiteral
//       HRegExpLiteral
//     HOsrEntry
//     HParameter
//     HSimulate
//     HStackCheck
//     HStoreKeyed
//       HStoreKeyedFastElement
//       HStoreKeyedGeneric
//     HUnaryOperation
//       HBitNot
//       HChange
//       HCheckFunction
//       HCheckInstanceType
//       HCheckMap
//       HCheckNonSmi
//       HCheckPrototypeMaps
//       HCheckSmi
//       HDeleteProperty
//       HFixedArrayLength
//       HJSArrayLength
//       HLoadElements
//         HTypeofIs
//       HLoadNamedField
//       HLoadNamedGeneric
//       HLoadFunctionPrototype
//       HPushArgument
//       HTypeof
//       HUnaryMathOperation
//       HUnaryPredicate
//         HClassOfTest
//         HHasCachedArrayIndex
//         HHasInstanceType
//         HIsNull
//         HIsObject
//         HIsSmi
//       HValueOf
//     HUnknownOSRValue
//   HPhi

#define HYDROGEN_ALL_INSTRUCTION_LIST(V)       \
  V(ArithmeticBinaryOperation)                 \
  V(BinaryOperation)                           \
  V(BitwiseBinaryOperation)                    \
  V(Call)                                      \
  V(ControlInstruction)                        \
  V(Instruction)                               \
  V(LoadKeyed)                                 \
  V(MaterializedLiteral)                       \
  V(Phi)                                       \
  V(StoreKeyed)                                \
  V(StoreNamed)                                \
  V(UnaryControlInstruction)                   \
  V(UnaryOperation)                            \
  HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)


#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)  \
  V(AccessArgumentsAt)                         \
  V(Add)                                       \
  V(ApplyArguments)                            \
  V(ArgumentsElements)                         \
  V(ArgumentsLength)                           \
  V(ArgumentsObject)                           \
  V(ArrayLiteral)                              \
  V(BitAnd)                                    \
  V(BitNot)                                    \
  V(BitOr)                                     \
  V(BitXor)                                    \
  V(BlockEntry)                                \
  V(BoundsCheck)                               \
  V(Branch)                                    \
  V(CallConstantFunction)                      \
  V(CallFunction)                              \
  V(CallGlobal)                                \
  V(CallKeyed)                                 \
  V(CallKnownGlobal)                           \
  V(CallNamed)                                 \
  V(CallNew)                                   \
  V(CallRuntime)                               \
  V(CallStub)                                  \
  V(Change)                                    \
  V(CheckFunction)                             \
  V(CheckInstanceType)                         \
  V(CheckMap)                                  \
  V(CheckNonSmi)                               \
  V(CheckPrototypeMaps)                        \
  V(CheckSmi)                                  \
  V(Compare)                                   \
  V(CompareJSObjectEq)                         \
  V(CompareMapAndBranch)                       \
  V(Constant)                                  \
  V(DeleteProperty)                            \
  V(Deoptimize)                                \
  V(Div)                                       \
  V(EnterInlined)                              \
  V(FixedArrayLength)                          \
  V(FunctionLiteral)                           \
  V(GlobalObject)                              \
  V(GlobalReceiver)                            \
  V(Goto)                                      \
  V(InstanceOf)                                \
  V(InstanceOfKnownGlobal)                     \
  V(IsNull)                                    \
  V(IsObject)                                  \
  V(IsSmi)                                     \
  V(HasInstanceType)                           \
  V(HasCachedArrayIndex)                       \
  V(JSArrayLength)                             \
  V(ClassOfTest)                               \
  V(LeaveInlined)                              \
  V(LoadElements)                              \
  V(LoadGlobal)                                \
  V(LoadKeyedFastElement)                      \
  V(LoadKeyedGeneric)                          \
  V(LoadNamedField)                            \
  V(LoadNamedGeneric)                          \
  V(LoadFunctionPrototype)                     \
  V(Mod)                                       \
  V(Mul)                                       \
  V(ObjectLiteral)                             \
  V(OsrEntry)                                  \
  V(Parameter)                                 \
  V(Power)                                     \
  V(PushArgument)                              \
  V(RegExpLiteral)                             \
  V(Return)                                    \
  V(Sar)                                       \
  V(Shl)                                       \
  V(Shr)                                       \
  V(Simulate)                                  \
  V(StackCheck)                                \
  V(StoreGlobal)                               \
  V(StoreKeyedFastElement)                     \
  V(StoreKeyedGeneric)                         \
  V(StoreNamedField)                           \
  V(StoreNamedGeneric)                         \
  V(Sub)                                       \
  V(Throw)                                     \
  V(Typeof)                                    \
  V(TypeofIs)                                  \
  V(UnaryMathOperation)                        \
  V(UnknownOSRValue)                           \
  V(ValueOf)

#define GVN_FLAG_LIST(V)                       \
  V(Calls)                                     \
  V(InobjectFields)                            \
  V(BackingStoreFields)                        \
  V(ArrayElements)                             \
  V(GlobalVars)                                \
  V(Maps)                                      \
  V(ArrayLengths)                              \
  V(FunctionPrototypes)                        \
  V(OsrEntries)

#define DECLARE_INSTRUCTION(type)                   \
  virtual bool Is##type() const { return true; }    \
  static H##type* cast(HValue* value) {             \
    ASSERT(value->Is##type());                      \
    return reinterpret_cast<H##type*>(value);       \
  }                                                 \
  Opcode opcode() const { return HValue::k##type; }


#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic)              \
  virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
  virtual const char* Mnemonic() const { return mnemonic; }       \
  DECLARE_INSTRUCTION(type)



template<int kSize>
class HOperandVector : public EmbeddedVector<HValue*, kSize> {
 public:
  HOperandVector() : EmbeddedVector<HValue*, kSize>(NULL) { }
};


class Range: 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) { }

  bool IsInSmiRange() const {
    return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
  }
  void KeepOrder();
  void Verify() const;
  int32_t upper() const { return upper_; }
  int32_t lower() const { return lower_; }
  Range* next() const { return next_; }
  Range* CopyClearLower() const { return new Range(kMinInt, upper_); }
  Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); }
  void ClearLower() { lower_ = kMinInt; }
  void ClearUpper() { upper_ = kMaxInt; }
  Range* Copy() const { return new Range(lower_, upper_); }
  bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; }
  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 Includes(int value) const {
    return lower_ <= value && upper_ >= value;
  }

  void Sar(int32_t value) {
    int32_t bits = value & 0x1F;
    lower_ = lower_ >> bits;
    upper_ = upper_ >> bits;
    set_can_be_minus_zero(false);
  }

  void Shl(int32_t value) {
    int32_t bits = value & 0x1F;
    int old_lower = lower_;
    int old_upper = upper_;
    lower_ = lower_ << bits;
    upper_ = upper_ << bits;
    if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
      upper_ = kMaxInt;
      lower_ = kMinInt;
    }
    set_can_be_minus_zero(false);
  }

  // Adds a constant to the lower and upper bound of the range.
  void AddConstant(int32_t value);

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

  void Intersect(Range* other) {
    upper_ = Min(upper_, other->upper_);
    lower_ = Max(lower_, other->lower_);
    bool b = CanBeMinusZero() && other->CanBeMinusZero();
    set_can_be_minus_zero(b);
  }

  void Union(Range* other) {
    upper_ = Max(upper_, other->upper_);
    lower_ = Min(lower_, other->lower_);
    bool b = CanBeMinusZero() || other->CanBeMinusZero();
    set_can_be_minus_zero(b);
  }

  // Compute a new result range and return true, if the operation
  // can overflow.
  bool AddAndCheckOverflow(Range* other);
  bool SubAndCheckOverflow(Range* other);
  bool MulAndCheckOverflow(Range* other);

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


class Representation {
 public:
  enum Kind {
    kNone,
    kTagged,
    kDouble,
    kInteger32,
    kNumRepresentations
  };

  Representation() : kind_(kNone) { }

  static Representation None() { return Representation(kNone); }
  static Representation Tagged() { return Representation(kTagged); }
  static Representation Integer32() { return Representation(kInteger32); }
  static Representation Double() { return Representation(kDouble); }

  bool Equals(const Representation& other) const {
    return kind_ == other.kind_;
  }

  Kind kind() const { return kind_; }
  bool IsNone() const { return kind_ == kNone; }
  bool IsTagged() const { return kind_ == kTagged; }
  bool IsInteger32() const { return kind_ == kInteger32; }
  bool IsDouble() const { return kind_ == kDouble; }
  bool IsSpecialization() const {
    return kind_ == kInteger32 || kind_ == kDouble;
  }
  const char* Mnemonic() const;

 private:
  explicit Representation(Kind k) : kind_(k) { }

  Kind kind_;
};


class HType {
 public:
  HType() : type_(kUninitialized) { }

  static HType Tagged() { return HType(kTagged); }
  static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
  static HType TaggedNumber() { return HType(kTaggedNumber); }
  static HType Smi() { return HType(kSmi); }
  static HType HeapNumber() { return HType(kHeapNumber); }
  static HType String() { return HType(kString); }
  static HType Boolean() { return HType(kBoolean); }
  static HType NonPrimitive() { return HType(kNonPrimitive); }
  static HType JSArray() { return HType(kJSArray); }
  static HType JSObject() { return HType(kJSObject); }
  static HType Uninitialized() { return HType(kUninitialized); }

  // Return the weakest (least precise) common type.
  HType Combine(HType other) {
    return HType(static_cast<Type>(type_ & other.type_));
  }

  bool Equals(const HType& other) {
    return type_ == other.type_;
  }

  bool IsSubtypeOf(const HType& other) {
    return Combine(other).Equals(other);
  }

  bool IsTagged() {
    ASSERT(type_ != kUninitialized);
    return ((type_ & kTagged) == kTagged);
  }

  bool IsTaggedPrimitive() {
    ASSERT(type_ != kUninitialized);
    return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
  }

  bool IsTaggedNumber() {
    ASSERT(type_ != kUninitialized);
    return ((type_ & kTaggedNumber) == kTaggedNumber);
  }

  bool IsSmi() {
    ASSERT(type_ != kUninitialized);
    return ((type_ & kSmi) == kSmi);
  }

  bool IsHeapNumber() {
    ASSERT(type_ != kUninitialized);
    return ((type_ & kHeapNumber) == kHeapNumber);
  }

  bool IsString() {
    ASSERT(type_ != kUninitialized);
    return ((type_ & kString) == kString);
  }

  bool IsBoolean() {
    ASSERT(type_ != kUninitialized);
    return ((type_ & kBoolean) == kBoolean);
  }

  bool IsNonPrimitive() {
    ASSERT(type_ != kUninitialized);
    return ((type_ & kNonPrimitive) == kNonPrimitive);
  }

  bool IsJSArray() {
    ASSERT(type_ != kUninitialized);
    return ((type_ & kJSArray) == kJSArray);
  }

  bool IsJSObject() {
    ASSERT(type_ != kUninitialized);
    return ((type_ & kJSObject) == kJSObject);
  }

  bool IsUninitialized() {
    return type_ == kUninitialized;
  }

  static HType TypeFromValue(Handle<Object> value);

  const char* ToString();
  const char* ToShortString();

 private:
  enum Type {
    kTagged = 0x1,           // 0000 0000 0000 0001
    kTaggedPrimitive = 0x5,  // 0000 0000 0000 0101
    kTaggedNumber = 0xd,     // 0000 0000 0000 1101
    kSmi = 0x1d,             // 0000 0000 0001 1101
    kHeapNumber = 0x2d,      // 0000 0000 0010 1101
    kString = 0x45,          // 0000 0000 0100 0101
    kBoolean = 0x85,         // 0000 0000 1000 0101
    kNonPrimitive = 0x101,   // 0000 0001 0000 0001
    kJSObject = 0x301,       // 0000 0011 0000 0001
    kJSArray = 0x701,        // 0000 0111 1000 0001
    kUninitialized = 0x1fff  // 0001 1111 1111 1111
  };

  explicit HType(Type t) : type_(t) { }

  Type type_;
};


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

  // There must be one corresponding kDepends flag for every kChanges flag and
  // the order of the kChanges flags must be exactly the same as of the kDepends
  // flags.
  enum Flag {
    // Declare global value numbering flags.
  #define DECLARE_DO(type) kChanges##type, kDependsOn##type,
    GVN_FLAG_LIST(DECLARE_DO)
  #undef DECLARE_DO
    kFlexibleRepresentation,
    kUseGVN,
    kCanOverflow,
    kBailoutOnMinusZero,
    kCanBeDivByZero,
    kIsArguments,
    kTruncatingToInt32,
    kLastFlag = kTruncatingToInt32
  };

  STATIC_ASSERT(kLastFlag < kBitsPerInt);

  static const int kChangesToDependsFlagsLeftShift = 1;

  static int ChangesFlagsMask() {
    int result = 0;
    // Create changes mask.
#define DECLARE_DO(type) result |= (1 << kChanges##type);
  GVN_FLAG_LIST(DECLARE_DO)
#undef DECLARE_DO
    return result;
  }

  static int DependsFlagsMask() {
    return ConvertChangesToDependsFlags(ChangesFlagsMask());
  }

  static int ConvertChangesToDependsFlags(int flags) {
    return flags << kChangesToDependsFlagsLeftShift;
  }

  // A flag mask to mark an instruction as having arbitrary side effects.
  static int AllSideEffects() {
    return ChangesFlagsMask() & ~(1 << kChangesOsrEntries);
  }

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

  enum Opcode {
    // Declare a unique enum value for each hydrogen instruction.
  #define DECLARE_DO(type) k##type,
    HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
  #undef DECLARE_DO
    kMaxInstructionClass
  };

  HValue() : block_(NULL),
             id_(kNoNumber),
             uses_(2),
             type_(HType::Tagged()),
             range_(NULL),
             flags_(0) {}
  virtual ~HValue() {}

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

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

  const ZoneList<HValue*>* uses() const { return &uses_; }

  virtual bool EmitAtUses() const { return false; }
  Representation representation() const { return representation_; }
  void ChangeRepresentation(Representation r) {
    // Representation was already set and is allowed to be changed.
    ASSERT(!representation_.IsNone());
    ASSERT(!r.IsNone());
    ASSERT(CheckFlag(kFlexibleRepresentation));
    RepresentationChanged(r);
    representation_ = r;
  }

  HType type() const { return type_; }
  void set_type(HType type) {
    ASSERT(uses_.length() == 0);
    type_ = type;
  }

  // An operation needs to override this function iff:
  //   1) it can produce an int32 output.
  //   2) the true value of its output can potentially be minus zero.
  // The implementation must set a flag so that it bails out in the case where
  // it would otherwise output what should be a minus zero as an int32 zero.
  // If the operation also exists in a form that takes int32 and outputs int32
  // then the operation should return its input value so that we can propagate
  // back.  There are two operations that need to propagate back to more than
  // one input.  They are phi and binary add.  They always return NULL and
  // expect the caller to take care of things.
  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
    visited->Add(id());
    return NULL;
  }

  bool HasSideEffects() const {
    return (flags_ & AllSideEffects()) != 0;
  }
  bool IsDefinedAfter(HBasicBlock* other) const;

  // Operands.
  virtual int OperandCount() const { return 0; }
  virtual HValue* OperandAt(int index) const {
    UNREACHABLE();
    return NULL;
  }
  void SetOperandAt(int index, HValue* value);

  int LookupOperandIndex(int occurrence_index, HValue* op) const;
  bool UsesMultipleTimes(HValue* op) const;

  void ReplaceAndDelete(HValue* other);
  void ReplaceValue(HValue* other);
  void ReplaceAtUse(HValue* use, HValue* other);
  void ReplaceFirstAtUse(HValue* use, HValue* other, Representation r);
  bool HasNoUses() const { return uses_.is_empty(); }
  void ClearOperands();
  void Delete();

  int flags() const { return flags_; }
  void SetFlagMask(int mask) { flags_ |= mask; }
  void SetFlag(Flag f) { SetFlagMask(1 << f); }
  void ClearFlagMask(int mask) { flags_ &= ~mask; }
  void ClearFlag(Flag f) { ClearFlagMask(1 << f); }
  bool CheckFlag(Flag f) const { return CheckFlagMask(1 << f); }
  bool CheckFlagMask(int mask) const { return (flags_ & mask) != 0; }

  Range* range() const { return range_; }
  bool HasRange() const { return range_ != NULL; }
  void AddNewRange(Range* r);
  void RemoveLastAddedRange();
  void ComputeInitialRange();

  // Representation helpers.
  virtual Representation RequiredInputRepresentation(int index) const {
    return Representation::None();
  }
  virtual Representation InferredRepresentation() const {
    return representation();
  }

  // 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; }

  // Declare virtual type testers.
#define DECLARE_DO(type) virtual bool Is##type() const { return false; }
  HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
#undef DECLARE_DO

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

  // Printing support.
  virtual void PrintTo(StringStream* stream) const = 0;
  void PrintNameTo(StringStream* stream);
  static void PrintTypeTo(HType type, StringStream* stream);

  virtual const char* Mnemonic() const = 0;
  virtual Opcode opcode() const = 0;

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

  virtual HType CalculateInferredType() const;

  // Helper for type conversions used by normal and phi instructions.
  void InsertInputConversion(HInstruction* previous, int index, HType type);

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

 protected:
  virtual bool DataEquals(HValue* other) const { return true; }
  virtual void RepresentationChanged(Representation to) { }
  virtual Range* InferRange();
  virtual void DeleteFromGraph() = 0;
  virtual void InternalSetOperandAt(int index, HValue* value) { UNREACHABLE(); }
  void clear_block() {
    ASSERT(block_ != NULL);
    block_ = NULL;
  }

  void set_representation(Representation r) {
    // Representation is set-once.
    ASSERT(representation_.IsNone() && !r.IsNone());
    representation_ = r;
  }

 private:
  void InternalReplaceAtUse(HValue* use, HValue* other);
  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_;
  ZoneList<HValue*> uses_;
  HType type_;
  Range* range_;
  int flags_;

  DISALLOW_COPY_AND_ASSIGN(HValue);
};


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

  void PrintTo(StringStream* stream) const;
  virtual void PrintDataTo(StringStream* stream) const {}

  bool IsLinked() const { return block() != NULL; }
  void Unlink();
  void InsertBefore(HInstruction* next);
  void InsertAfter(HInstruction* previous);

  int position() const { return position_; }
  bool has_position() const { return position_ != RelocInfo::kNoPosition; }
  void set_position(int position) { position_ = position; }

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

#ifdef DEBUG
  virtual void Verify() const;
#endif

  DECLARE_INSTRUCTION(Instruction)

 protected:
  HInstruction()
      : next_(NULL),
        previous_(NULL),
        position_(RelocInfo::kNoPosition) {
    SetFlag(kDependsOnOsrEntries);
  }

  virtual void DeleteFromGraph() { Unlink(); }

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

  HInstruction* next_;
  HInstruction* previous_;
  int position_;

  friend class HBasicBlock;
};


class HBlockEntry: public HInstruction {
 public:
  DECLARE_CONCRETE_INSTRUCTION(BlockEntry, "block_entry")
};


class HControlInstruction: public HInstruction {
 public:
  virtual HBasicBlock* FirstSuccessor() const { return NULL; }
  virtual HBasicBlock* SecondSuccessor() const { return NULL; }

  DECLARE_INSTRUCTION(ControlInstruction)
};


class HDeoptimize: public HControlInstruction {
 public:
  DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
};


class HGoto: public HControlInstruction {
 public:
  explicit HGoto(HBasicBlock* destination)
      : destination_(destination),
        include_stack_check_(false) {}

  virtual HBasicBlock* FirstSuccessor() const { return destination_; }
  void set_include_stack_check(bool include_stack_check) {
    include_stack_check_ = include_stack_check;
  }
  bool include_stack_check() const { return include_stack_check_; }

  virtual void PrintDataTo(StringStream* stream) const;

  DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")

 private:
  HBasicBlock* destination_;
  bool include_stack_check_;
};


class HUnaryControlInstruction: public HControlInstruction {
 public:
  explicit HUnaryControlInstruction(HValue* value) {
    SetOperandAt(0, value);
  }

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

  HValue* value() const { return OperandAt(0); }
  virtual int OperandCount() const { return 1; }
  virtual HValue* OperandAt(int index) const { return operands_[index]; }

  DECLARE_INSTRUCTION(UnaryControlInstruction)

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

 private:
  HOperandVector<1> operands_;
};


class HBranch: public HUnaryControlInstruction {
 public:
  HBranch(HBasicBlock* true_destination,
          HBasicBlock* false_destination,
          HValue* boolean_value)
      : HUnaryControlInstruction(boolean_value),
        true_destination_(true_destination),
        false_destination_(false_destination) {
    ASSERT(true_destination != NULL && false_destination != NULL);
  }

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

  virtual HBasicBlock* FirstSuccessor() const { return true_destination_; }
  virtual HBasicBlock* SecondSuccessor() const { return false_destination_; }

  virtual void PrintDataTo(StringStream* stream) const;

  DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")

 private:
  HBasicBlock* true_destination_;
  HBasicBlock* false_destination_;
};


class HCompareMapAndBranch: public HUnaryControlInstruction {
 public:
  HCompareMapAndBranch(HValue* result,
                       Handle<Map> map,
                       HBasicBlock* true_destination,
                       HBasicBlock* false_destination)
      : HUnaryControlInstruction(result),
        map_(map),
        true_destination_(true_destination),
        false_destination_(false_destination) {
    ASSERT(true_destination != NULL);
    ASSERT(false_destination != NULL);
    ASSERT(!map.is_null());
  }

  virtual HBasicBlock* FirstSuccessor() const { return true_destination_; }
  virtual HBasicBlock* SecondSuccessor() const { return false_destination_; }

  HBasicBlock* true_destination() const { return true_destination_; }
  HBasicBlock* false_destination() const { return false_destination_; }

  virtual void PrintDataTo(StringStream* stream) const;

  Handle<Map> map() const { return map_; }

  DECLARE_CONCRETE_INSTRUCTION(CompareMapAndBranch, "compare_map_and_branch")

 private:
  Handle<Map> map_;
  HBasicBlock* true_destination_;
  HBasicBlock* false_destination_;
};


class HReturn: public HUnaryControlInstruction {
 public:
  explicit HReturn(HValue* result) : HUnaryControlInstruction(result) { }

  virtual void PrintDataTo(StringStream* stream) const;

  DECLARE_CONCRETE_INSTRUCTION(Return, "return")
};


class HThrow: public HUnaryControlInstruction {
 public:
  explicit HThrow(HValue* value) : HUnaryControlInstruction(value) { }

  virtual void PrintDataTo(StringStream* stream) const;

  DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
};


class HUnaryOperation: public HInstruction {
 public:
  explicit HUnaryOperation(HValue* value) {
    SetOperandAt(0, value);
  }

  HValue* value() const { return OperandAt(0); }
  virtual void PrintDataTo(StringStream* stream) const;
  virtual int OperandCount() const { return 1; }
  virtual HValue* OperandAt(int index) const { return operands_[index]; }

  DECLARE_INSTRUCTION(UnaryOperation)

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

 private:
  HOperandVector<1> operands_;
};


class HChange: public HUnaryOperation {
 public:
  HChange(HValue* value,
          Representation from,
          Representation to)
      : HUnaryOperation(value), from_(from), to_(to) {
    ASSERT(!from.IsNone() && !to.IsNone());
    ASSERT(!from.Equals(to));
    set_representation(to);
    SetFlag(kUseGVN);

    if (from.IsInteger32() && to.IsTagged() && value->range() != NULL &&
        value->range()->IsInSmiRange()) {
      set_type(HType::Smi());
    }
  }

  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);

  Representation from() const { return from_; }
  Representation to() const { return to_; }
  virtual Representation RequiredInputRepresentation(int index) const {
    return from_;
  }

  bool CanTruncateToInt32() const {
    for (int i = 0; i < uses()->length(); ++i) {
      if (!uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) return false;
    }
    return true;
  }

  virtual void PrintDataTo(StringStream* stream) const;

  DECLARE_CONCRETE_INSTRUCTION(Change,
                               CanTruncateToInt32() ? "truncate" : "change")

 protected:
  virtual bool DataEquals(HValue* other) const {
    if (!other->IsChange()) return false;
    HChange* change = HChange::cast(other);
    return value() == change->value()
        && to().Equals(change->to())
        && CanTruncateToInt32() == change->CanTruncateToInt32();
  }

 private:
  Representation from_;
  Representation to_;
};


class HSimulate: public HInstruction {
 public:
  HSimulate(int ast_id, int pop_count, int environment_length)
      : ast_id_(ast_id),
        pop_count_(pop_count),
        environment_length_(environment_length),
        values_(2),
        assigned_indexes_(2) {}
  virtual ~HSimulate() {}

  virtual void PrintDataTo(StringStream* stream) const;

  bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; }
  int ast_id() const { return ast_id_; }
  void set_ast_id(int id) {
    ASSERT(!HasAstId());
    ast_id_ = id;
  }

  int environment_length() const { return environment_length_; }
  int pop_count() const { return pop_count_; }
  const ZoneList<HValue*>* values() const { return &values_; }
  int GetAssignedIndexAt(int index) const {
    ASSERT(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);
  }
  virtual int OperandCount() const { return values_.length(); }
  virtual HValue* OperandAt(int index) const { return values_[index]; }

  DECLARE_CONCRETE_INSTRUCTION(Simulate, "simulate")

#ifdef DEBUG
  virtual void Verify() const;
#endif

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

 private:
  static const int kNoIndex = -1;
  void AddValue(int index, HValue* value) {
    assigned_indexes_.Add(index);
    // Resize the list of pushed values.
    values_.Add(NULL);
    // Set the operand through the base method in HValue to make sure that the
    // use lists are correctly updated.
    SetOperandAt(values_.length() - 1, value);
  }
  int ast_id_;
  int pop_count_;
  int environment_length_;
  ZoneList<HValue*> values_;
  ZoneList<int> assigned_indexes_;
};


class HStackCheck: public HInstruction {
 public:
  HStackCheck() { }

  DECLARE_CONCRETE_INSTRUCTION(Throw, "stack_check")
};


class HEnterInlined: public HInstruction {
 public:
  HEnterInlined(Handle<JSFunction> closure, FunctionLiteral* function)
      : closure_(closure), function_(function) {
  }

  virtual void PrintDataTo(StringStream* stream) const;

  Handle<JSFunction> closure() const { return closure_; }
  FunctionLiteral* function() const { return function_; }

  DECLARE_CONCRETE_INSTRUCTION(EnterInlined, "enter_inlined")

 private:
  Handle<JSFunction> closure_;
  FunctionLiteral* function_;
};


class HLeaveInlined: public HInstruction {
 public:
  HLeaveInlined() {}

  DECLARE_CONCRETE_INSTRUCTION(LeaveInlined, "leave_inlined")
};


class HPushArgument: public HUnaryOperation {
 public:
  explicit HPushArgument(HValue* value)
      : HUnaryOperation(value), argument_index_(-1) {
    set_representation(Representation::Tagged());
  }

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

  virtual void PrintDataTo(StringStream* stream) const;
  HValue* argument() const { return OperandAt(0); }
  int argument_index() const { return argument_index_; }
  void set_argument_index(int index) {
    ASSERT(argument_index_ == -1 || index == argument_index_);
    argument_index_ = index;
  }

  DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push_argument")

 private:
  int argument_index_;
};


class HGlobalObject: public HInstruction {
 public:
  HGlobalObject() {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
    SetFlag(kDependsOnCalls);
  }

  DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global_object")
};


class HGlobalReceiver: public HInstruction {
 public:
  HGlobalReceiver() {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
    SetFlag(kDependsOnCalls);
  }

  DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global_receiver")
};


class HCall: public HInstruction {
 public:
  // Construct a call with uninitialized arguments. The argument count
  // includes the receiver.
  explicit HCall(int count);

  virtual HType CalculateInferredType() const { return HType::Tagged(); }

  // TODO(3190496): This needs a cleanup. We don't want the arguments
  // be operands of the call instruction. This results in bad code quality.
  virtual int argument_count() const { return arguments_.length(); }
  virtual int OperandCount() const { return argument_count(); }
  virtual HValue* OperandAt(int index) const { return arguments_[index]; }
  virtual HPushArgument* PushArgumentAt(int index) const {
    return HPushArgument::cast(OperandAt(index));
  }
  virtual HValue* ArgumentAt(int index) const {
    return PushArgumentAt(index)->argument();
  }
  virtual void SetArgumentAt(int index, HPushArgument* push_argument);

  virtual void PrintDataTo(StringStream* stream) const;

  DECLARE_INSTRUCTION(Call)

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

  int argument_count_;
  Vector<HValue*> arguments_;
};


class HCallConstantFunction: public HCall {
 public:
  HCallConstantFunction(Handle<JSFunction> function, int argument_count)
      : HCall(argument_count), function_(function) { }

  Handle<JSFunction> function() const { return function_; }
  bool IsApplyFunction() const {
    return function_->code() == Builtins::builtin(Builtins::FunctionApply);
  }

  virtual void PrintDataTo(StringStream* stream) const;

  DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call_constant_function")

 private:
  Handle<JSFunction> function_;
};


class HCallKeyed: public HCall {
 public:
  HCallKeyed(HValue* key, int argument_count)
      : HCall(argument_count + 1) {
    SetOperandAt(0, key);
  }

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

  // TODO(3190496): This is a hack to get an additional operand that
  // is not an argument to work with the current setup. This _needs_ a cleanup.
  // (see HCall)
  virtual void PrintDataTo(StringStream* stream) const;
  HValue* key() const { return OperandAt(0); }
  virtual int argument_count() const { return arguments_.length() - 1; }
  virtual int OperandCount() const { return arguments_.length(); }
  virtual HValue* OperandAt(int index) const { return arguments_[index]; }
  virtual HPushArgument* PushArgumentAt(int index) const {
    return HPushArgument::cast(OperandAt(index + 1));
  }
  virtual void SetArgumentAt(int index, HPushArgument* push_argument) {
    HCall::SetArgumentAt(index + 1, push_argument);
  }

  DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed")
};


class HCallNamed: public HCall {
 public:
  HCallNamed(Handle<String> name, int argument_count)
      : HCall(argument_count), name_(name) { }
  virtual void PrintDataTo(StringStream* stream) const;

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

  DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named")

 private:
  Handle<String> name_;
};


class HCallFunction: public HCall {
 public:
  explicit HCallFunction(int argument_count) : HCall(argument_count) { }

  DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function")
};


class HCallGlobal: public HCall {
 public:
  HCallGlobal(Handle<String> name, int argument_count)
      : HCall(argument_count), name_(name) { }

  virtual void PrintDataTo(StringStream* stream) const;

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

  DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global")

 private:
  Handle<String> name_;
};


class HCallKnownGlobal: public HCall {
 public:
  HCallKnownGlobal(Handle<JSFunction> target,
                   int argument_count)
      : HCall(argument_count), target_(target) { }

  Handle<JSFunction> target() const { return target_; }

  DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global")

 private:
  Handle<JSFunction> target_;
};


class HCallNew: public HCall {
 public:
  explicit HCallNew(int argument_count) : HCall(argument_count) { }

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

  HValue* constructor() const { return ArgumentAt(0); }

  DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new")
};


class HCallRuntime: public HCall {
 public:
  HCallRuntime(Handle<String> name,
               Runtime::Function* c_function,
               int argument_count)
      : HCall(argument_count), c_function_(c_function), name_(name) { }
  virtual void PrintDataTo(StringStream* stream) const;

  Runtime::Function* function() const { return c_function_; }
  Handle<String> name() const { return name_; }

  DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call_runtime")

 private:
  Runtime::Function* c_function_;
  Handle<String> name_;
};


class HJSArrayLength: public HUnaryOperation {
 public:
  explicit HJSArrayLength(HValue* value) : HUnaryOperation(value) {
    // The length of an array is stored as a tagged value in the array
    // object. It is guaranteed to be 32 bit integer, but it can be
    // represented as either a smi or heap number.
    set_representation(Representation::Tagged());
    SetFlag(kDependsOnArrayLengths);
    SetFlag(kUseGVN);
  }

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

  DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js_array_length")
};


class HFixedArrayLength: public HUnaryOperation {
 public:
  explicit HFixedArrayLength(HValue* value) : HUnaryOperation(value) {
    set_representation(Representation::Tagged());
    SetFlag(kDependsOnArrayLengths);
    SetFlag(kUseGVN);
  }

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

  DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed_array_length")
};


class HBitNot: public HUnaryOperation {
 public:
  explicit HBitNot(HValue* value) : HUnaryOperation(value) {
    set_representation(Representation::Integer32());
    SetFlag(kUseGVN);
    SetFlag(kTruncatingToInt32);
  }

  virtual Representation RequiredInputRepresentation(int index) const {
    return Representation::Integer32();
  }
  virtual HType CalculateInferredType() const;

  DECLARE_CONCRETE_INSTRUCTION(BitNot, "bit_not")
};


class HUnaryMathOperation: public HUnaryOperation {
 public:
  HUnaryMathOperation(HValue* value, BuiltinFunctionId op)
      : HUnaryOperation(value), op_(op) {
    switch (op) {
      case kMathFloor:
      case kMathRound:
      case kMathCeil:
        set_representation(Representation::Integer32());
        break;
      case kMathAbs:
        set_representation(Representation::Tagged());
        SetFlag(kFlexibleRepresentation);
        break;
      case kMathSqrt:
      case kMathPowHalf:
      case kMathLog:
      case kMathSin:
      case kMathCos:
        set_representation(Representation::Double());
        break;
      default:
        UNREACHABLE();
    }
    SetFlag(kUseGVN);
  }

  virtual void PrintDataTo(StringStream* stream) const;

  virtual HType CalculateInferredType() const;

  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);

  virtual Representation RequiredInputRepresentation(int index) const {
    switch (op_) {
      case kMathFloor:
      case kMathRound:
      case kMathCeil:
      case kMathSqrt:
      case kMathPowHalf:
      case kMathLog:
      case kMathSin:
      case kMathCos:
        return Representation::Double();
        break;
      case kMathAbs:
        return representation();
        break;
      default:
        return Representation::None();
    }
  }

  virtual HValue* Canonicalize() {
    // If the input is integer32 then we replace the floor instruction
    // with its inputs.  This happens before the representation changes are
    // introduced.
    if (op() == kMathFloor) {
      if (value()->representation().IsInteger32()) return value();
    }
    return this;
  }

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

  DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary_math_operation")

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

 private:
  BuiltinFunctionId op_;
};


class HLoadElements: public HUnaryOperation {
 public:
  explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
    SetFlag(kDependsOnMaps);
  }

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

  DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements")
};


class HCheckMap: public HUnaryOperation {
 public:
  HCheckMap(HValue* value, Handle<Map> map)
      : HUnaryOperation(value), map_(map) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
    SetFlag(kDependsOnMaps);
  }

  virtual Representation RequiredInputRepresentation(int index) const {
    return Representation::Tagged();
  }
  virtual void PrintDataTo(StringStream* stream) const;
  virtual HType CalculateInferredType() const;

#ifdef DEBUG
  virtual void Verify() const;
#endif

  Handle<Map> map() const { return map_; }

  DECLARE_CONCRETE_INSTRUCTION(CheckMap, "check_map")

 protected:
  virtual bool DataEquals(HValue* other) const {
    HCheckMap* b = HCheckMap::cast(other);
    return map_.is_identical_to(b->map());
  }

 private:
  Handle<Map> map_;
};


class HCheckFunction: public HUnaryOperation {
 public:
  HCheckFunction(HValue* value, Handle<JSFunction> function)
      : HUnaryOperation(value), target_(function) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
  }

  virtual Representation RequiredInputRepresentation(int index) const {
    return Representation::Tagged();
  }
  virtual void PrintDataTo(StringStream* stream) const;
  virtual HType CalculateInferredType() const;

#ifdef DEBUG
  virtual void Verify() const;
#endif

  Handle<JSFunction> target() const { return target_; }

  DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check_function")

 protected:
  virtual bool DataEquals(HValue* other) const {
    HCheckFunction* b = HCheckFunction::cast(other);
    return target_.is_identical_to(b->target());
  }

 private:
  Handle<JSFunction> target_;
};


class HCheckInstanceType: public HUnaryOperation {
 public:
  // Check that the instance type is in the range [first, last] where
  // both first and last are included.
  HCheckInstanceType(HValue* value, InstanceType first, InstanceType last)
      : HUnaryOperation(value), first_(first), last_(last) {
    ASSERT(first <= last);
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
  }

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

#ifdef DEBUG
  virtual void Verify() const;
#endif

  static HCheckInstanceType* NewIsJSObjectOrJSFunction(HValue* value);

  InstanceType first() const { return first_; }
  InstanceType last() const { return last_; }

  DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check_instance_type")

 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.
  virtual bool DataEquals(HValue* other) const {
    HCheckInstanceType* b = HCheckInstanceType::cast(other);
    return (first_ == b->first()) && (last_ == b->last());
  }

 private:
  InstanceType first_;
  InstanceType last_;
};


class HCheckNonSmi: public HUnaryOperation {
 public:
  explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
  }

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

  virtual HType CalculateInferredType() const;

#ifdef DEBUG
  virtual void Verify() const;
#endif

  DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check_non_smi")
};


class HCheckPrototypeMaps: public HUnaryOperation {
 public:
  HCheckPrototypeMaps(HValue* value,
                      Handle<JSObject> holder,
                      Handle<Map> receiver_map)
      : HUnaryOperation(value),
        holder_(holder),
        receiver_map_(receiver_map) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
    SetFlag(kDependsOnMaps);
  }

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

#ifdef DEBUG
  virtual void Verify() const;
#endif

  Handle<JSObject> holder() const { return holder_; }
  Handle<Map> receiver_map() const { return receiver_map_; }

  DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check_prototype_maps")

 protected:
  virtual bool DataEquals(HValue* other) const {
    HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
    return holder_.is_identical_to(b->holder()) &&
        receiver_map_.is_identical_to(b->receiver_map());
  }

 private:
  Handle<JSObject> holder_;
  Handle<Map> receiver_map_;
};


class HCheckSmi: public HUnaryOperation {
 public:
  explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
  }

  virtual Representation RequiredInputRepresentation(int index) const {
    return Representation::Tagged();
  }
  virtual HType CalculateInferredType() const;

#ifdef DEBUG
  virtual void Verify() const;
#endif

  DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check_smi")
};


class HPhi: public HValue {
 public:
  explicit HPhi(int merged_index)
      : inputs_(2),
        merged_index_(merged_index),
        phi_id_(-1) {
    for (int i = 0; i < Representation::kNumRepresentations; i++) {
      non_phi_uses_[i] = 0;
      indirect_uses_[i] = 0;
    }
    ASSERT(merged_index >= 0);
    set_representation(Representation::Tagged());
    SetFlag(kFlexibleRepresentation);
  }

  virtual Representation InferredRepresentation() const {
    bool double_occurred = false;
    bool int32_occurred = false;
    for (int i = 0; i < OperandCount(); ++i) {
      HValue* value = OperandAt(i);
      if (value->representation().IsDouble()) double_occurred = true;
      if (value->representation().IsInteger32()) int32_occurred = true;
      if (value->representation().IsTagged()) return Representation::Tagged();
    }

    if (double_occurred) return Representation::Double();
    if (int32_occurred) return Representation::Integer32();
    return Representation::None();
  }

  virtual Range* InferRange();
  virtual Representation RequiredInputRepresentation(int index) const {
    return representation();
  }
  virtual HType CalculateInferredType() const;
  virtual int OperandCount() const { return inputs_.length(); }
  virtual HValue* OperandAt(int index) const { return inputs_[index]; }
  HValue* GetRedundantReplacement() const;
  void AddInput(HValue* value);

  bool HasReceiverOperand();

  int merged_index() const { return merged_index_; }

  virtual const char* Mnemonic() const { return "phi"; }

  virtual void PrintTo(StringStream* stream) const;

#ifdef DEBUG
  virtual void Verify() const;
#endif

  DECLARE_INSTRUCTION(Phi)

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

  int tagged_non_phi_uses() const {
    return non_phi_uses_[Representation::kTagged];
  }
  int int32_non_phi_uses() const {
    return non_phi_uses_[Representation::kInteger32];
  }
  int double_non_phi_uses() const {
    return non_phi_uses_[Representation::kDouble];
  }
  int tagged_indirect_uses() const {
    return indirect_uses_[Representation::kTagged];
  }
  int int32_indirect_uses() const {
    return indirect_uses_[Representation::kInteger32];
  }
  int double_indirect_uses() const {
    return indirect_uses_[Representation::kDouble];
  }
  int phi_id() { return phi_id_; }

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

 private:
  ZoneList<HValue*> inputs_;
  int merged_index_;

  int non_phi_uses_[Representation::kNumRepresentations];
  int indirect_uses_[Representation::kNumRepresentations];
  int phi_id_;
};


class HArgumentsObject: public HInstruction {
 public:
  HArgumentsObject() {
    set_representation(Representation::Tagged());
    SetFlag(kIsArguments);
  }

  DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject, "arguments-object")
};


class HConstant: public HInstruction {
 public:
  HConstant(Handle<Object> handle, Representation r);

  Handle<Object> handle() const { return handle_; }

  bool InOldSpace() const { return !Heap::InNewSpace(*handle_); }

  virtual bool EmitAtUses() const { return !representation().IsDouble(); }
  virtual void PrintDataTo(StringStream* stream) const;
  virtual HType CalculateInferredType() const;
  bool IsInteger() const { return handle_->IsSmi(); }
  HConstant* CopyToRepresentation(Representation r) const;
  HConstant* CopyToTruncatedInt32() const;
  bool HasInteger32Value() const { return has_int32_value_; }
  int32_t Integer32Value() const {
    ASSERT(HasInteger32Value());
    return int32_value_;
  }
  bool HasDoubleValue() const { return has_double_value_; }
  double DoubleValue() const {
    ASSERT(HasDoubleValue());
    return double_value_;
  }
  bool HasStringValue() const { return handle_->IsString(); }

  virtual intptr_t Hashcode() const {
    ASSERT(!Heap::allow_allocation(false));
    return reinterpret_cast<intptr_t>(*handle());
  }

#ifdef DEBUG
  virtual void Verify() const { }
#endif

  DECLARE_CONCRETE_INSTRUCTION(Constant, "constant")

 protected:
  virtual Range* InferRange();

  virtual bool DataEquals(HValue* other) const {
    HConstant* other_constant = HConstant::cast(other);
    return handle().is_identical_to(other_constant->handle());
  }

 private:
  Handle<Object> handle_;
  HType constant_type_;

  // The following two values represent the int32 and the double value of the
  // given constant if there is a lossless conversion between the constant
  // and the specific representation.
  bool has_int32_value_;
  int32_t int32_value_;
  bool has_double_value_;
  double double_value_;
};


class HBinaryOperation: public HInstruction {
 public:
  HBinaryOperation(HValue* left, HValue* right) {
    ASSERT(left != NULL && right != NULL);
    SetOperandAt(0, left);
    SetOperandAt(1, right);
  }

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

  // TODO(kasperl): Move these helpers to the IA-32 Lithium
  // instruction sequence builder.
  HValue* LeastConstantOperand() const {
    if (IsCommutative() && left()->IsConstant()) return right();
    return left();
  }
  HValue* MostConstantOperand() const {
    if (IsCommutative() && left()->IsConstant()) return left();
    return right();
  }

  virtual bool IsCommutative() const { return false; }

  virtual void PrintDataTo(StringStream* stream) const;
  virtual int OperandCount() const { return operands_.length(); }
  virtual HValue* OperandAt(int index) const { return operands_[index]; }

  DECLARE_INSTRUCTION(BinaryOperation)

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

 private:
  HOperandVector<2> operands_;
};


class HApplyArguments: public HInstruction {
 public:
  HApplyArguments(HValue* function,
                  HValue* receiver,
                  HValue* length,
                  HValue* elements) {
    set_representation(Representation::Tagged());
    SetOperandAt(0, function);
    SetOperandAt(1, receiver);
    SetOperandAt(2, length);
    SetOperandAt(3, elements);
  }

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

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

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

  DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply_arguments")



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

 private:
  HOperandVector<4> operands_;
};


class HArgumentsElements: public HInstruction {
 public:
  HArgumentsElements() {
    // 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);
  }

  DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments_elements")
};


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

  DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments_length")
};


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

  virtual void PrintDataTo(StringStream* stream) const;

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

  HValue* arguments() const { return operands_[0]; }
  HValue* length() const { return operands_[1]; }
  HValue* index() const { return operands_[2]; }

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

  DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access_arguments_at")

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

 private:
  HOperandVector<3> operands_;
};


class HBoundsCheck: public HBinaryOperation {
 public:
  HBoundsCheck(HValue* index, HValue* length)
      : HBinaryOperation(index, length) {
    SetFlag(kUseGVN);
  }

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

#ifdef DEBUG
  virtual void Verify() const;
#endif

  HValue* index() const { return left(); }
  HValue* length() const { return right(); }

  DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds_check")
};


class HBitwiseBinaryOperation: public HBinaryOperation {
 public:
  HBitwiseBinaryOperation(HValue* left, HValue* right)
      : HBinaryOperation(left, right) {
    // Default to truncating, Integer32, UseGVN.
    set_representation(Representation::Integer32());
    SetFlag(kTruncatingToInt32);
    SetFlag(kUseGVN);
  }

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

  DECLARE_INSTRUCTION(BitwiseBinaryOperation)
};


class HArithmeticBinaryOperation: public HBinaryOperation {
 public:
  HArithmeticBinaryOperation(HValue* left, HValue* right)
      : HBinaryOperation(left, right) {
    set_representation(Representation::Tagged());
    SetFlag(kFlexibleRepresentation);
    SetFlagMask(AllSideEffects());
  }

  virtual void RepresentationChanged(Representation to) {
    if (!to.IsTagged()) {
      ClearFlagMask(AllSideEffects());
      SetFlag(kUseGVN);
    }
  }

  virtual HType CalculateInferredType() const;
  virtual Representation RequiredInputRepresentation(int index) const {
    return representation();
  }
  virtual Representation InferredRepresentation() const {
    if (left()->representation().Equals(right()->representation())) {
      return left()->representation();
    }
    return HValue::InferredRepresentation();
  }

  DECLARE_INSTRUCTION(ArithmeticBinaryOperation)
};


class HCompare: public HBinaryOperation {
 public:
  HCompare(HValue* left, HValue* right, Token::Value token)
      : HBinaryOperation(left, right), token_(token) {
    ASSERT(Token::IsCompareOp(token));
    set_representation(Representation::Tagged());
    SetFlagMask(AllSideEffects());
  }

  void SetInputRepresentation(Representation r);
  virtual bool EmitAtUses() const { return uses()->length() <= 1; }
  virtual Representation RequiredInputRepresentation(int index) const {
    return input_representation_;
  }
  Representation GetInputRepresentation() const {
    return input_representation_;
  }
  Token::Value token() const { return token_; }
  virtual void PrintDataTo(StringStream* stream) const;

  virtual HType CalculateInferredType() const;

  virtual intptr_t Hashcode() const {
    return HValue::Hashcode() * 7 + token_;
  }

  DECLARE_CONCRETE_INSTRUCTION(Compare, "compare")

 protected:
  virtual bool DataEquals(HValue* other) const {
    HCompare* comp = HCompare::cast(other);
    return token_ == comp->token();
  }

 private:
  Representation input_representation_;
  Token::Value token_;
};


class HCompareJSObjectEq: public HBinaryOperation {
 public:
  HCompareJSObjectEq(HValue* left, HValue* right)
      : HBinaryOperation(left, right) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
  }

  virtual bool EmitAtUses() const { return uses()->length() <= 1; }
  virtual Representation RequiredInputRepresentation(int index) const {
    return Representation::Tagged();
  }
  virtual HType CalculateInferredType() const;

  DECLARE_CONCRETE_INSTRUCTION(CompareJSObjectEq, "compare-js-object-eq")
};


class HUnaryPredicate: public HUnaryOperation {
 public:
  explicit HUnaryPredicate(HValue* value) : HUnaryOperation(value) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
  }
  virtual bool EmitAtUses() const { return uses()->length() <= 1; }
  virtual Representation RequiredInputRepresentation(int index) const {
    return Representation::Tagged();
  }
  virtual HType CalculateInferredType() const;
};


class HIsNull: public HUnaryPredicate {
 public:
  HIsNull(HValue* value, bool is_strict)
      : HUnaryPredicate(value), is_strict_(is_strict) { }

  bool is_strict() const { return is_strict_; }

  DECLARE_CONCRETE_INSTRUCTION(IsNull, "is_null")

 protected:
  virtual bool DataEquals(HValue* other) const {
    HIsNull* b = HIsNull::cast(other);
    return is_strict_ == b->is_strict();
  }

 private:
  bool is_strict_;
};


class HIsObject: public HUnaryPredicate {
 public:
  explicit HIsObject(HValue* value) : HUnaryPredicate(value) { }

  DECLARE_CONCRETE_INSTRUCTION(IsObject, "is_object")
};


class HIsSmi: public HUnaryPredicate {
 public:
  explicit HIsSmi(HValue* value) : HUnaryPredicate(value) { }

  DECLARE_CONCRETE_INSTRUCTION(IsSmi, "is_smi")
};


class HHasInstanceType: public HUnaryPredicate {
 public:
  HHasInstanceType(HValue* value, InstanceType type)
      : HUnaryPredicate(value), from_(type), to_(type) { }
  HHasInstanceType(HValue* value, InstanceType from, InstanceType to)
      : HUnaryPredicate(value), from_(from), to_(to) {
    ASSERT(to == LAST_TYPE);  // Others not implemented yet in backend.
  }

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

  virtual void PrintDataTo(StringStream* stream) const;

  DECLARE_CONCRETE_INSTRUCTION(HasInstanceType, "has_instance_type")

 protected:
  virtual bool DataEquals(HValue* other) const {
    HHasInstanceType* b = HHasInstanceType::cast(other);
    return (from_ == b->from()) && (to_ == b->to());
  }

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


class HHasCachedArrayIndex: public HUnaryPredicate {
 public:
  explicit HHasCachedArrayIndex(HValue* value) : HUnaryPredicate(value) { }

  DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndex, "has_cached_array_index")
};


class HClassOfTest: public HUnaryPredicate {
 public:
  HClassOfTest(HValue* value, Handle<String> class_name)
      : HUnaryPredicate(value), class_name_(class_name) { }

  DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class_of_test")

  virtual void PrintDataTo(StringStream* stream) const;

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

 protected:
  virtual bool DataEquals(HValue* other) const {
    HClassOfTest* b = HClassOfTest::cast(other);
    return class_name_.is_identical_to(b->class_name_);
  }

 private:
  Handle<String> class_name_;
};


class HTypeofIs: public HUnaryPredicate {
 public:
  HTypeofIs(HValue* value, Handle<String> type_literal)
      : HUnaryPredicate(value), type_literal_(type_literal) { }

  Handle<String> type_literal() { return type_literal_; }
  virtual void PrintDataTo(StringStream* stream) const;

  DECLARE_CONCRETE_INSTRUCTION(TypeofIs, "typeof_is")

 protected:
  virtual bool DataEquals(HValue* other) const {
    HTypeofIs* b = HTypeofIs::cast(other);
    return type_literal_.is_identical_to(b->type_literal_);
  }

 private:
  Handle<String> type_literal_;
};


class HInstanceOf: public HBinaryOperation {
 public:
  HInstanceOf(HValue* left, HValue* right) : HBinaryOperation(left, right) {
    set_representation(Representation::Tagged());
    SetFlagMask(AllSideEffects());
  }

  virtual bool EmitAtUses() const { return uses()->length() <= 1; }

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

  DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance_of")
};


class HInstanceOfKnownGlobal: public HUnaryOperation {
 public:
  HInstanceOfKnownGlobal(HValue* left, Handle<JSFunction> right)
      : HUnaryOperation(left), function_(right) {
    set_representation(Representation::Tagged());
    SetFlagMask(AllSideEffects());
  }

  Handle<JSFunction> function() { return function_; }

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

  DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
                               "instance_of_known_global")

 private:
  Handle<JSFunction> function_;
};


class HPower: public HBinaryOperation {
 public:
  HPower(HValue* left, HValue* right)
      : HBinaryOperation(left, right) {
    set_representation(Representation::Double());
    SetFlag(kUseGVN);
  }

  virtual Representation RequiredInputRepresentation(int index) const {
    return (index == 1) ? Representation::None() : Representation::Double();
  }

  DECLARE_CONCRETE_INSTRUCTION(Power, "power")
};


class HAdd: public HArithmeticBinaryOperation {
 public:
  HAdd(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
    SetFlag(kCanOverflow);
  }

  // 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).
  virtual bool IsCommutative() const {
    return !representation().IsTagged();
  }

  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);

  virtual HType CalculateInferredType() const;

  DECLARE_CONCRETE_INSTRUCTION(Add, "add")

 protected:
  virtual Range* InferRange();
};


class HSub: public HArithmeticBinaryOperation {
 public:
  HSub(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
    SetFlag(kCanOverflow);
  }

  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);

  DECLARE_CONCRETE_INSTRUCTION(Sub, "sub")

 protected:
  virtual Range* InferRange();
};


class HMul: public HArithmeticBinaryOperation {
 public:
  HMul(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
    SetFlag(kCanOverflow);
  }

  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);

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

  DECLARE_CONCRETE_INSTRUCTION(Mul, "mul")

 protected:
  virtual Range* InferRange();
};


class HMod: public HArithmeticBinaryOperation {
 public:
  HMod(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
    SetFlag(kCanBeDivByZero);
  }

  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);

  DECLARE_CONCRETE_INSTRUCTION(Mod, "mod")

 protected:
  virtual Range* InferRange();
};


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

  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);

  DECLARE_CONCRETE_INSTRUCTION(Div, "div")

 protected:
  virtual Range* InferRange();
};


class HBitAnd: public HBitwiseBinaryOperation {
 public:
  HBitAnd(HValue* left, HValue* right)
      : HBitwiseBinaryOperation(left, right) { }

  virtual bool IsCommutative() const { return true; }
  virtual HType CalculateInferredType() const;

  DECLARE_CONCRETE_INSTRUCTION(BitAnd, "bit_and")

 protected:
  virtual Range* InferRange();
};


class HBitXor: public HBitwiseBinaryOperation {
 public:
  HBitXor(HValue* left, HValue* right)
      : HBitwiseBinaryOperation(left, right) { }

  virtual bool IsCommutative() const { return true; }
  virtual HType CalculateInferredType() const;

  DECLARE_CONCRETE_INSTRUCTION(BitXor, "bit_xor")
};


class HBitOr: public HBitwiseBinaryOperation {
 public:
  HBitOr(HValue* left, HValue* right)
      : HBitwiseBinaryOperation(left, right) { }

  virtual bool IsCommutative() const { return true; }
  virtual HType CalculateInferredType() const;

  DECLARE_CONCRETE_INSTRUCTION(BitOr, "bit_or")

 protected:
  virtual Range* InferRange();
};


class HShl: public HBitwiseBinaryOperation {
 public:
  HShl(HValue* left, HValue* right)
      : HBitwiseBinaryOperation(left, right) { }

  virtual Range* InferRange();
  virtual HType CalculateInferredType() const;

  DECLARE_CONCRETE_INSTRUCTION(Shl, "shl")
};


class HShr: public HBitwiseBinaryOperation {
 public:
  HShr(HValue* left, HValue* right)
      : HBitwiseBinaryOperation(left, right) { }

  virtual HType CalculateInferredType() const;

  DECLARE_CONCRETE_INSTRUCTION(Shr, "shr")
};


class HSar: public HBitwiseBinaryOperation {
 public:
  HSar(HValue* left, HValue* right)
      : HBitwiseBinaryOperation(left, right) { }

  virtual Range* InferRange();
  virtual HType CalculateInferredType() const;

  DECLARE_CONCRETE_INSTRUCTION(Sar, "sar")
};


class HOsrEntry: public HInstruction {
 public:
  explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
    SetFlag(kChangesOsrEntries);
  }

  int ast_id() const { return ast_id_; }

  DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr_entry")

 private:
  int ast_id_;
};


class HParameter: public HInstruction {
 public:
  explicit HParameter(unsigned index) : index_(index) {
    set_representation(Representation::Tagged());
  }

  unsigned index() const { return index_; }

  virtual void PrintDataTo(StringStream* stream) const;

  DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")

 private:
  unsigned index_;
};


class HCallStub: public HInstruction {
 public:
  HCallStub(CodeStub::Major major_key, int argument_count)
      : major_key_(major_key),
        argument_count_(argument_count),
        transcendental_type_(TranscendentalCache::kNumberOfCaches) {
    set_representation(Representation::Tagged());
    SetFlagMask(AllSideEffects());
  }

  CodeStub::Major major_key() { return major_key_; }
  int argument_count() { return argument_count_; }

  void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
    transcendental_type_ = transcendental_type;
  }
  TranscendentalCache::Type transcendental_type() {
    return transcendental_type_;
  }
  virtual void PrintDataTo(StringStream* stream) const;

  DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub")

 private:
  CodeStub::Major major_key_;
  int argument_count_;
  TranscendentalCache::Type transcendental_type_;
};


class HUnknownOSRValue: public HInstruction {
 public:
  HUnknownOSRValue() { set_representation(Representation::Tagged()); }

  DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown_osr_value")
};


class HLoadGlobal: public HInstruction {
 public:
  HLoadGlobal(Handle<JSGlobalPropertyCell> cell, bool check_hole_value)
      : cell_(cell), check_hole_value_(check_hole_value) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
    SetFlag(kDependsOnGlobalVars);
  }

  Handle<JSGlobalPropertyCell>  cell() const { return cell_; }
  bool check_hole_value() const { return check_hole_value_; }

  virtual Representation RequiredInputRepresentation(int index) const {
    return Representation::Tagged();
  }
  virtual void PrintDataTo(StringStream* stream) const;

  virtual intptr_t Hashcode() const {
    ASSERT(!Heap::allow_allocation(false));
    return reinterpret_cast<intptr_t>(*cell_);
  }

  DECLARE_CONCRETE_INSTRUCTION(LoadGlobal, "load_global")

 protected:
  virtual bool DataEquals(HValue* other) const {
    HLoadGlobal* b = HLoadGlobal::cast(other);
    return cell_.is_identical_to(b->cell());
  }

 private:
  Handle<JSGlobalPropertyCell> cell_;
  bool check_hole_value_;
};


class HStoreGlobal: public HUnaryOperation {
 public:
  HStoreGlobal(HValue* value, Handle<JSGlobalPropertyCell> cell)
      : HUnaryOperation(value), cell_(cell) {
    SetFlag(kChangesGlobalVars);
  }

  Handle<JSGlobalPropertyCell> cell() const { return cell_; }

  virtual Representation RequiredInputRepresentation(int index) const {
    return Representation::Tagged();
  }
  virtual void PrintDataTo(StringStream* stream) const;

  DECLARE_CONCRETE_INSTRUCTION(StoreGlobal, "store_global")

 protected:
  virtual bool DataEquals(HValue* other) const {
    HStoreGlobal* b = HStoreGlobal::cast(other);
    return cell_.is_identical_to(b->cell());
  }

 private:
  Handle<JSGlobalPropertyCell> cell_;
};


class HLoadNamedField: public HUnaryOperation {
 public:
  HLoadNamedField(HValue* object, bool is_in_object, int offset)
      : HUnaryOperation(object),
        is_in_object_(is_in_object),
        offset_(offset) {
    set_representation(Representation::Tagged());
    SetFlag(kUseGVN);
    if (is_in_object) {
      SetFlag(kDependsOnInobjectFields);
    } else {
      SetFlag(kDependsOnBackingStoreFields);
    }
  }

  HValue* object() const { return OperandAt(0); }
  bool is_in_object() const { return is_in_object_; }
  int offset() const { return offset_; }

  virtual Representation RequiredInputRepresentation(int index) const {
    return Representation::Tagged();
  }
  virtual void PrintDataTo(StringStream* stream) const;

  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load_named_field")

 protected:
  virtual bool DataEquals(HValue* other) const {
    HLoadNamedField* b = HLoadNamedField::cast(other);
    return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
  }

 private:
  bool is_in_object_;
  int offset_;
};


class HLoadNamedGeneric: public HUnaryOperation {
 public:
  HLoadNamedGeneric(HValue* object, Handle<Object> name)
      : HUnaryOperation(object), name_(name) {
    set_representation(Representation::Tagged());
    SetFlagMask(AllSideEffects());
  }

  HValue* object() const { return OperandAt(0); }
  Handle<Object> name() const { return name_; }

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

  DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load_named_generic")

 protected:
  virtual bool DataEquals(HValue* other) const {
    HLoadNamedGeneric* b = HLoadNamedGeneric::cast(other);
    return name_.is_identical_to(b->name_);
  }

 private:
  Handle<Object> name_;
};


class HLoadFunctionPrototype: public HUnaryOperation {
 public:
  explicit HLoadFunctionPrototype(HValue* function)
      : HUnaryOperation(function) {
    set_representation(Representation::Tagged());
    SetFlagMask(kDependsOnFunctionPrototypes);
  }

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

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

  DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load_function_prototype")

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


class HLoadKeyed: public HBinaryOperation {
 public:
  HLoadKeyed(HValue* obj, HValue* key) : HBinaryOperation(obj, key) {
    set_representation(Representation::Tagged());
  }

  virtual void PrintDataTo(StringStream* stream) const;

  virtual Representation RequiredInputRepresentation(int index) const {
    return Representation::Tagged();
  }
  HValue* object() const { return OperandAt(0); }
  HValue* key() const { return OperandAt(1); }

  DECLARE_INSTRUCTION(LoadKeyed)
};


class HLoadKeyedFastElement: public HLoadKeyed {
 public:
  HLoadKeyedFastElement(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
    SetFlag(kDependsOnArrayElements);
    SetFlag(kUseGVN);
  }

  virtual Representation RequiredInputRepresentation(int index) const {
    // The key is supposed to be Integer32.
    return (index == 1) ? Representation::Integer32()
        : Representation::Tagged();
  }

  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement,
                               "load_keyed_fast_element")
};


class HLoadKeyedGeneric: public HLoadKeyed {
 public:
  HLoadKeyedGeneric(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
    SetFlagMask(AllSideEffects());
  }

  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load_keyed_generic")
};


static inline bool StoringValueNeedsWriteBarrier(HValue* value) {
  return !value->type().IsSmi() &&
      !(value->IsConstant() && HConstant::cast(value)->InOldSpace());
}


class HStoreNamed: public HBinaryOperation {
 public:
  HStoreNamed(HValue* obj, Handle<Object> name, HValue* val)
      : HBinaryOperation(obj, val), name_(name) {
  }

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

  virtual void PrintDataTo(StringStream* stream) const;

  HValue* object() const { return OperandAt(0); }
  Handle<Object> name() const { return name_; }
  HValue* value() const { return OperandAt(1); }
  void set_value(HValue* value) { SetOperandAt(1, value); }

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

  DECLARE_INSTRUCTION(StoreNamed)

 protected:
  virtual bool DataEquals(HValue* other) const {
    HStoreNamed* b = HStoreNamed::cast(other);
    return name_.is_identical_to(b->name_);
  }

 private:
  Handle<Object> name_;
};


class HStoreNamedField: public HStoreNamed {
 public:
  HStoreNamedField(HValue* obj,
                   Handle<Object> name,
                   HValue* val,
                   bool in_object,
                   int offset)
      : HStoreNamed(obj, name, val),
        is_in_object_(in_object),
        offset_(offset) {
    if (is_in_object_) {
      SetFlag(kChangesInobjectFields);
    } else {
      SetFlag(kChangesBackingStoreFields);
    }
  }

  DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store_named_field")

  virtual Representation RequiredInputRepresentation(int index) const {
    return  Representation::Tagged();
  }
  virtual void PrintDataTo(StringStream* stream) const;

  bool is_in_object() const { return is_in_object_; }
  int offset() const { return offset_; }
  Handle<Map> transition() const { return transition_; }
  void set_transition(Handle<Map> map) { transition_ = map; }

 private:
  bool is_in_object_;
  int offset_;
  Handle<Map> transition_;
};


class HStoreNamedGeneric: public HStoreNamed {
 public:
  HStoreNamedGeneric(HValue* obj, Handle<Object> name, HValue* val)
      : HStoreNamed(obj, name, val) {
    SetFlagMask(AllSideEffects());
  }

  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store_named_generic")
};


class HStoreKeyed: public HInstruction {
 public:
  HStoreKeyed(HValue* obj, HValue* key, HValue* val) {
    SetOperandAt(0, obj);
    SetOperandAt(1, key);
    SetOperandAt(2, val);
  }

  virtual void PrintDataTo(StringStream* stream) const;
  virtual int OperandCount() const { return operands_.length(); }
  virtual HValue* OperandAt(int index) const { return operands_[index]; }

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

  HValue* object() const { return OperandAt(0); }
  HValue* key() const { return OperandAt(1); }
  HValue* value() const { return OperandAt(2); }

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

  DECLARE_INSTRUCTION(StoreKeyed)

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

 private:
  HOperandVector<3> operands_;
};


class HStoreKeyedFastElement: public HStoreKeyed {
 public:
  HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val)
      : HStoreKeyed(obj, key, val) {
    SetFlag(kChangesArrayElements);
  }

  virtual Representation RequiredInputRepresentation(int index) const {
    // The key is supposed to be Integer32.
    return (index == 1) ? Representation::Integer32()
        : Representation::Tagged();
  }

  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
                               "store_keyed_fast_element")
};


class HStoreKeyedGeneric: public HStoreKeyed {
 public:
  HStoreKeyedGeneric(HValue* obj, HValue* key, HValue* val)
      : HStoreKeyed(obj, key, val) {
    SetFlagMask(AllSideEffects());
  }

  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store_keyed_generic")
};


class HMaterializedLiteral: public HInstruction {
 public:
  HMaterializedLiteral(int index, int depth)
      : literal_index_(index), depth_(depth) {
    set_representation(Representation::Tagged());
  }

  int literal_index() const { return literal_index_; }
  int depth() const { return depth_; }

  DECLARE_INSTRUCTION(MaterializedLiteral)

 private:
  int literal_index_;
  int depth_;
};


class HArrayLiteral: public HMaterializedLiteral {
 public:
  HArrayLiteral(Handle<FixedArray> constant_elements,
                int length,
                int literal_index,
                int depth)
      : HMaterializedLiteral(literal_index, depth),
        length_(length),
        constant_elements_(constant_elements) {}

  Handle<FixedArray> constant_elements() const { return constant_elements_; }
  int length() const { return length_; }

  bool IsCopyOnWrite() const;

  DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral, "array_literal")

 private:
  int length_;
  Handle<FixedArray> constant_elements_;
};


class HObjectLiteral: public HMaterializedLiteral {
 public:
  HObjectLiteral(Handle<FixedArray> constant_properties,
                 bool fast_elements,
                 int literal_index,
                 int depth)
      : HMaterializedLiteral(literal_index, depth),
        constant_properties_(constant_properties),
        fast_elements_(fast_elements) {}

  Handle<FixedArray> constant_properties() const {
    return constant_properties_;
  }
  bool fast_elements() const { return fast_elements_; }

  DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object_literal")

 private:
  Handle<FixedArray> constant_properties_;
  bool fast_elements_;
};


class HRegExpLiteral: public HMaterializedLiteral {
 public:
  HRegExpLiteral(Handle<String> pattern,
                 Handle<String> flags,
                 int literal_index)
      : HMaterializedLiteral(literal_index, 0),
        pattern_(pattern),
        flags_(flags) { }

  Handle<String> pattern() { return pattern_; }
  Handle<String> flags() { return flags_; }

  DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp_literal")

 private:
  Handle<String> pattern_;
  Handle<String> flags_;
};


class HFunctionLiteral: public HInstruction {
 public:
  HFunctionLiteral(Handle<SharedFunctionInfo> shared, bool pretenure)
      : shared_info_(shared), pretenure_(pretenure) {
    set_representation(Representation::Tagged());
  }

  DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function_literal")

  Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
  bool pretenure() const { return pretenure_; }

 private:
  Handle<SharedFunctionInfo> shared_info_;
  bool pretenure_;
};


class HTypeof: public HUnaryOperation {
 public:
  explicit HTypeof(HValue* value) : HUnaryOperation(value) {
    set_representation(Representation::Tagged());
  }

  DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
};


class HValueOf: public HUnaryOperation {
 public:
  explicit HValueOf(HValue* value) : HUnaryOperation(value) {
    set_representation(Representation::Tagged());
  }

  DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value_of")
};


class HDeleteProperty: public HBinaryOperation {
 public:
  HDeleteProperty(HValue* obj, HValue* key)
      : HBinaryOperation(obj, key) {
    set_representation(Representation::Tagged());
    SetFlagMask(AllSideEffects());
  }

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

  DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete_property")

  HValue* object() const { return left(); }
  HValue* key() const { return right(); }
};

#undef DECLARE_INSTRUCTION
#undef DECLARE_CONCRETE_INSTRUCTION

} }  // namespace v8::internal

#endif  // V8_HYDROGEN_INSTRUCTIONS_H_
