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