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