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_ ||