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