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