Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_HYDROGEN_INSTRUCTIONS_H_
     29 #define V8_HYDROGEN_INSTRUCTIONS_H_
     30 
     31 #include "v8.h"
     32 
     33 #include "allocation.h"
     34 #include "code-stubs.h"
     35 #include "data-flow.h"
     36 #include "small-pointer-list.h"
     37 #include "string-stream.h"
     38 #include "v8conversions.h"
     39 #include "v8utils.h"
     40 #include "zone.h"
     41 
     42 namespace v8 {
     43 namespace internal {
     44 
     45 // Forward declarations.
     46 class HBasicBlock;
     47 class HEnvironment;
     48 class HInstruction;
     49 class HLoopInformation;
     50 class HValue;
     51 class LInstruction;
     52 class LChunkBuilder;
     53 
     54 
     55 #define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V)  \
     56   V(BitwiseBinaryOperation)                    \
     57   V(ControlInstruction)                        \
     58   V(Instruction)                               \
     59 
     60 
     61 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)  \
     62   V(AbnormalExit)                              \
     63   V(AccessArgumentsAt)                         \
     64   V(Add)                                       \
     65   V(AllocateObject)                            \
     66   V(ApplyArguments)                            \
     67   V(ArgumentsElements)                         \
     68   V(ArgumentsLength)                           \
     69   V(ArgumentsObject)                           \
     70   V(ArrayLiteral)                              \
     71   V(Bitwise)                                   \
     72   V(BitNot)                                    \
     73   V(BlockEntry)                                \
     74   V(BoundsCheck)                               \
     75   V(Branch)                                    \
     76   V(CallConstantFunction)                      \
     77   V(CallFunction)                              \
     78   V(CallGlobal)                                \
     79   V(CallKeyed)                                 \
     80   V(CallKnownGlobal)                           \
     81   V(CallNamed)                                 \
     82   V(CallNew)                                   \
     83   V(CallRuntime)                               \
     84   V(CallStub)                                  \
     85   V(Change)                                    \
     86   V(CheckFunction)                             \
     87   V(CheckInstanceType)                         \
     88   V(CheckMap)                                  \
     89   V(CheckNonSmi)                               \
     90   V(CheckPrototypeMaps)                        \
     91   V(CheckSmi)                                  \
     92   V(ClampToUint8)                              \
     93   V(ClassOfTestAndBranch)                      \
     94   V(CompareIDAndBranch)                        \
     95   V(CompareGeneric)                            \
     96   V(CompareObjectEqAndBranch)                  \
     97   V(CompareMap)                                \
     98   V(CompareConstantEqAndBranch)                \
     99   V(Constant)                                  \
    100   V(Context)                                   \
    101   V(DeclareGlobals)                            \
    102   V(DeleteProperty)                            \
    103   V(Deoptimize)                                \
    104   V(Div)                                       \
    105   V(ElementsKind)                              \
    106   V(EnterInlined)                              \
    107   V(FastLiteral)                               \
    108   V(FixedArrayBaseLength)                      \
    109   V(ForceRepresentation)                       \
    110   V(FunctionLiteral)                           \
    111   V(GetCachedArrayIndex)                       \
    112   V(GlobalObject)                              \
    113   V(GlobalReceiver)                            \
    114   V(Goto)                                      \
    115   V(HasCachedArrayIndexAndBranch)              \
    116   V(HasInstanceTypeAndBranch)                  \
    117   V(In)                                        \
    118   V(InstanceOf)                                \
    119   V(InstanceOfKnownGlobal)                     \
    120   V(InvokeFunction)                            \
    121   V(IsConstructCallAndBranch)                  \
    122   V(IsNilAndBranch)                            \
    123   V(IsObjectAndBranch)                         \
    124   V(IsStringAndBranch)                         \
    125   V(IsSmiAndBranch)                            \
    126   V(IsUndetectableAndBranch)                   \
    127   V(StringCompareAndBranch)                    \
    128   V(JSArrayLength)                             \
    129   V(LeaveInlined)                              \
    130   V(LoadContextSlot)                           \
    131   V(LoadElements)                              \
    132   V(LoadExternalArrayPointer)                  \
    133   V(LoadFunctionPrototype)                     \
    134   V(LoadGlobalCell)                            \
    135   V(LoadGlobalGeneric)                         \
    136   V(LoadKeyedFastDoubleElement)                \
    137   V(LoadKeyedFastElement)                      \
    138   V(LoadKeyedGeneric)                          \
    139   V(LoadKeyedSpecializedArrayElement)          \
    140   V(LoadNamedField)                            \
    141   V(LoadNamedFieldPolymorphic)                 \
    142   V(LoadNamedGeneric)                          \
    143   V(Mod)                                       \
    144   V(Mul)                                       \
    145   V(ObjectLiteral)                             \
    146   V(OsrEntry)                                  \
    147   V(OuterContext)                              \
    148   V(Parameter)                                 \
    149   V(Power)                                     \
    150   V(PushArgument)                              \
    151   V(Random)                                    \
    152   V(RegExpLiteral)                             \
    153   V(Return)                                    \
    154   V(Sar)                                       \
    155   V(Shl)                                       \
    156   V(Shr)                                       \
    157   V(Simulate)                                  \
    158   V(SoftDeoptimize)                            \
    159   V(StackCheck)                                \
    160   V(StoreContextSlot)                          \
    161   V(StoreGlobalCell)                           \
    162   V(StoreGlobalGeneric)                        \
    163   V(StoreKeyedFastDoubleElement)               \
    164   V(StoreKeyedFastElement)                     \
    165   V(StoreKeyedGeneric)                         \
    166   V(StoreKeyedSpecializedArrayElement)         \
    167   V(StoreNamedField)                           \
    168   V(StoreNamedGeneric)                         \
    169   V(StringAdd)                                 \
    170   V(StringCharCodeAt)                          \
    171   V(StringCharFromCode)                        \
    172   V(StringLength)                              \
    173   V(Sub)                                       \
    174   V(ThisFunction)                              \
    175   V(Throw)                                     \
    176   V(ToFastProperties)                          \
    177   V(TransitionElementsKind)                    \
    178   V(Typeof)                                    \
    179   V(TypeofIsAndBranch)                         \
    180   V(UnaryMathOperation)                        \
    181   V(UnknownOSRValue)                           \
    182   V(UseConst)                                  \
    183   V(ValueOf)                                   \
    184   V(ForInPrepareMap)                           \
    185   V(ForInCacheArray)                           \
    186   V(CheckMapValue)                             \
    187   V(LoadFieldByIndex)                          \
    188   V(DateField)                                 \
    189   V(WrapReceiver)
    190 
    191 #define GVN_FLAG_LIST(V)                       \
    192   V(Calls)                                     \
    193   V(InobjectFields)                            \
    194   V(BackingStoreFields)                        \
    195   V(ElementsKind)                              \
    196   V(ElementsPointer)                           \
    197   V(ArrayElements)                             \
    198   V(DoubleArrayElements)                       \
    199   V(SpecializedArrayElements)                  \
    200   V(GlobalVars)                                \
    201   V(Maps)                                      \
    202   V(ArrayLengths)                              \
    203   V(ContextSlots)                              \
    204   V(OsrEntries)
    205 
    206 #define DECLARE_ABSTRACT_INSTRUCTION(type)          \
    207   virtual bool Is##type() const { return true; }    \
    208   static H##type* cast(HValue* value) {             \
    209     ASSERT(value->Is##type());                      \
    210     return reinterpret_cast<H##type*>(value);       \
    211   }
    212 
    213 
    214 #define DECLARE_CONCRETE_INSTRUCTION(type)                        \
    215   virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
    216   static H##type* cast(HValue* value) {                           \
    217     ASSERT(value->Is##type());                                    \
    218     return reinterpret_cast<H##type*>(value);                     \
    219   }                                                               \
    220   virtual Opcode opcode() const { return HValue::k##type; }
    221 
    222 
    223 class Range: public ZoneObject {
    224  public:
    225   Range()
    226       : lower_(kMinInt),
    227         upper_(kMaxInt),
    228         next_(NULL),
    229         can_be_minus_zero_(false) { }
    230 
    231   Range(int32_t lower, int32_t upper)
    232       : lower_(lower),
    233         upper_(upper),
    234         next_(NULL),
    235         can_be_minus_zero_(false) { }
    236 
    237   int32_t upper() const { return upper_; }
    238   int32_t lower() const { return lower_; }
    239   Range* next() const { return next_; }
    240   Range* CopyClearLower(Zone* zone) const {
    241     return new(zone) Range(kMinInt, upper_);
    242   }
    243   Range* CopyClearUpper(Zone* zone) const {
    244     return new(zone) Range(lower_, kMaxInt);
    245   }
    246   Range* Copy(Zone* zone) const {
    247     Range* result = new(zone) Range(lower_, upper_);
    248     result->set_can_be_minus_zero(CanBeMinusZero());
    249     return result;
    250   }
    251   int32_t Mask() const;
    252   void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
    253   bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
    254   bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
    255   bool CanBeNegative() const { return lower_ < 0; }
    256   bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
    257   bool IsMostGeneric() const {
    258     return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
    259   }
    260   bool IsInSmiRange() const {
    261     return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
    262   }
    263   void KeepOrder();
    264 #ifdef DEBUG
    265   void Verify() const;
    266 #endif
    267 
    268   void StackUpon(Range* other) {
    269     Intersect(other);
    270     next_ = other;
    271   }
    272 
    273   void Intersect(Range* other);
    274   void Union(Range* other);
    275 
    276   void AddConstant(int32_t value);
    277   void Sar(int32_t value);
    278   void Shl(int32_t value);
    279   bool AddAndCheckOverflow(Range* other);
    280   bool SubAndCheckOverflow(Range* other);
    281   bool MulAndCheckOverflow(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 Representation {
    292  public:
    293   enum Kind {
    294     kNone,
    295     kTagged,
    296     kDouble,
    297     kInteger32,
    298     kExternal,
    299     kNumRepresentations
    300   };
    301 
    302   Representation() : kind_(kNone) { }
    303 
    304   static Representation None() { return Representation(kNone); }
    305   static Representation Tagged() { return Representation(kTagged); }
    306   static Representation Integer32() { return Representation(kInteger32); }
    307   static Representation Double() { return Representation(kDouble); }
    308   static Representation External() { return Representation(kExternal); }
    309 
    310   bool Equals(const Representation& other) {
    311     return kind_ == other.kind_;
    312   }
    313 
    314   Kind kind() const { return static_cast<Kind>(kind_); }
    315   bool IsNone() const { return kind_ == kNone; }
    316   bool IsTagged() const { return kind_ == kTagged; }
    317   bool IsInteger32() const { return kind_ == kInteger32; }
    318   bool IsDouble() const { return kind_ == kDouble; }
    319   bool IsExternal() const { return kind_ == kExternal; }
    320   bool IsSpecialization() const {
    321     return kind_ == kInteger32 || kind_ == kDouble;
    322   }
    323   const char* Mnemonic() const;
    324 
    325  private:
    326   explicit Representation(Kind k) : kind_(k) { }
    327 
    328   // Make sure kind fits in int8.
    329   STATIC_ASSERT(kNumRepresentations <= (1 << kBitsPerByte));
    330 
    331   int8_t kind_;
    332 };
    333 
    334 
    335 class HType {
    336  public:
    337   HType() : type_(kUninitialized) { }
    338 
    339   static HType Tagged() { return HType(kTagged); }
    340   static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
    341   static HType TaggedNumber() { return HType(kTaggedNumber); }
    342   static HType Smi() { return HType(kSmi); }
    343   static HType HeapNumber() { return HType(kHeapNumber); }
    344   static HType String() { return HType(kString); }
    345   static HType Boolean() { return HType(kBoolean); }
    346   static HType NonPrimitive() { return HType(kNonPrimitive); }
    347   static HType JSArray() { return HType(kJSArray); }
    348   static HType JSObject() { return HType(kJSObject); }
    349   static HType Uninitialized() { return HType(kUninitialized); }
    350 
    351   // Return the weakest (least precise) common type.
    352   HType Combine(HType other) {
    353     return HType(static_cast<Type>(type_ & other.type_));
    354   }
    355 
    356   bool Equals(const HType& other) {
    357     return type_ == other.type_;
    358   }
    359 
    360   bool IsSubtypeOf(const HType& other) {
    361     return Combine(other).Equals(other);
    362   }
    363 
    364   bool IsTagged() {
    365     ASSERT(type_ != kUninitialized);
    366     return ((type_ & kTagged) == kTagged);
    367   }
    368 
    369   bool IsTaggedPrimitive() {
    370     ASSERT(type_ != kUninitialized);
    371     return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
    372   }
    373 
    374   bool IsTaggedNumber() {
    375     ASSERT(type_ != kUninitialized);
    376     return ((type_ & kTaggedNumber) == kTaggedNumber);
    377   }
    378 
    379   bool IsSmi() {
    380     ASSERT(type_ != kUninitialized);
    381     return ((type_ & kSmi) == kSmi);
    382   }
    383 
    384   bool IsHeapNumber() {
    385     ASSERT(type_ != kUninitialized);
    386     return ((type_ & kHeapNumber) == kHeapNumber);
    387   }
    388 
    389   bool IsString() {
    390     ASSERT(type_ != kUninitialized);
    391     return ((type_ & kString) == kString);
    392   }
    393 
    394   bool IsBoolean() {
    395     ASSERT(type_ != kUninitialized);
    396     return ((type_ & kBoolean) == kBoolean);
    397   }
    398 
    399   bool IsNonPrimitive() {
    400     ASSERT(type_ != kUninitialized);
    401     return ((type_ & kNonPrimitive) == kNonPrimitive);
    402   }
    403 
    404   bool IsJSArray() {
    405     ASSERT(type_ != kUninitialized);
    406     return ((type_ & kJSArray) == kJSArray);
    407   }
    408 
    409   bool IsJSObject() {
    410     ASSERT(type_ != kUninitialized);
    411     return ((type_ & kJSObject) == kJSObject);
    412   }
    413 
    414   bool IsUninitialized() {
    415     return type_ == kUninitialized;
    416   }
    417 
    418   bool IsHeapObject() {
    419     ASSERT(type_ != kUninitialized);
    420     return IsHeapNumber() || IsString() || IsNonPrimitive();
    421   }
    422 
    423   static HType TypeFromValue(Handle<Object> value);
    424 
    425   const char* ToString();
    426 
    427  private:
    428   enum Type {
    429     kTagged = 0x1,           // 0000 0000 0000 0001
    430     kTaggedPrimitive = 0x5,  // 0000 0000 0000 0101
    431     kTaggedNumber = 0xd,     // 0000 0000 0000 1101
    432     kSmi = 0x1d,             // 0000 0000 0001 1101
    433     kHeapNumber = 0x2d,      // 0000 0000 0010 1101
    434     kString = 0x45,          // 0000 0000 0100 0101
    435     kBoolean = 0x85,         // 0000 0000 1000 0101
    436     kNonPrimitive = 0x101,   // 0000 0001 0000 0001
    437     kJSObject = 0x301,       // 0000 0011 0000 0001
    438     kJSArray = 0x701,        // 0000 0111 0000 0001
    439     kUninitialized = 0x1fff  // 0001 1111 1111 1111
    440   };
    441 
    442   // Make sure type fits in int16.
    443   STATIC_ASSERT(kUninitialized < (1 << (2 * kBitsPerByte)));
    444 
    445   explicit HType(Type t) : type_(t) { }
    446 
    447   int16_t type_;
    448 };
    449 
    450 
    451 class HUseListNode: public ZoneObject {
    452  public:
    453   HUseListNode(HValue* value, int index, HUseListNode* tail)
    454       : tail_(tail), value_(value), index_(index) {
    455   }
    456 
    457   HUseListNode* tail();
    458   HValue* value() const { return value_; }
    459   int index() const { return index_; }
    460 
    461   void set_tail(HUseListNode* list) { tail_ = list; }
    462 
    463 #ifdef DEBUG
    464   void Zap() {
    465     tail_ = reinterpret_cast<HUseListNode*>(1);
    466     value_ = NULL;
    467     index_ = -1;
    468   }
    469 #endif
    470 
    471  private:
    472   HUseListNode* tail_;
    473   HValue* value_;
    474   int index_;
    475 };
    476 
    477 
    478 // We reuse use list nodes behind the scenes as uses are added and deleted.
    479 // This class is the safe way to iterate uses while deleting them.
    480 class HUseIterator BASE_EMBEDDED {
    481  public:
    482   bool Done() { return current_ == NULL; }
    483   void Advance();
    484 
    485   HValue* value() {
    486     ASSERT(!Done());
    487     return value_;
    488   }
    489 
    490   int index() {
    491     ASSERT(!Done());
    492     return index_;
    493   }
    494 
    495  private:
    496   explicit HUseIterator(HUseListNode* head);
    497 
    498   HUseListNode* current_;
    499   HUseListNode* next_;
    500   HValue* value_;
    501   int index_;
    502 
    503   friend class HValue;
    504 };
    505 
    506 
    507 // There must be one corresponding kDepends flag for every kChanges flag and
    508 // the order of the kChanges flags must be exactly the same as of the kDepends
    509 // flags.
    510 enum GVNFlag {
    511   // Declare global value numbering flags.
    512 #define DECLARE_FLAG(type) kChanges##type, kDependsOn##type,
    513   GVN_FLAG_LIST(DECLARE_FLAG)
    514 #undef DECLARE_FLAG
    515   kAfterLastFlag,
    516   kLastFlag = kAfterLastFlag - 1
    517 };
    518 
    519 typedef EnumSet<GVNFlag> GVNFlagSet;
    520 
    521 
    522 class HValue: public ZoneObject {
    523  public:
    524   static const int kNoNumber = -1;
    525 
    526   enum Flag {
    527     kFlexibleRepresentation,
    528     // Participate in Global Value Numbering, i.e. elimination of
    529     // unnecessary recomputations. If an instruction sets this flag, it must
    530     // implement DataEquals(), which will be used to determine if other
    531     // occurrences of the instruction are indeed the same.
    532     kUseGVN,
    533     kCanOverflow,
    534     kBailoutOnMinusZero,
    535     kCanBeDivByZero,
    536     kDeoptimizeOnUndefined,
    537     kIsArguments,
    538     kTruncatingToInt32,
    539     kIsDead,
    540     kLastFlag = kIsDead
    541   };
    542 
    543   STATIC_ASSERT(kLastFlag < kBitsPerInt);
    544 
    545   static const int kChangesToDependsFlagsLeftShift = 1;
    546 
    547   static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags) {
    548     return GVNFlagSet(flags.ToIntegral() << kChangesToDependsFlagsLeftShift);
    549   }
    550 
    551   static HValue* cast(HValue* value) { return value; }
    552 
    553   enum Opcode {
    554     // Declare a unique enum value for each hydrogen instruction.
    555   #define DECLARE_OPCODE(type) k##type,
    556     HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
    557     kPhi
    558   #undef DECLARE_OPCODE
    559   };
    560   virtual Opcode opcode() const = 0;
    561 
    562   // Declare a non-virtual predicates for each concrete HInstruction or HValue.
    563   #define DECLARE_PREDICATE(type) \
    564     bool Is##type() const { return opcode() == k##type; }
    565     HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
    566   #undef DECLARE_PREDICATE
    567     bool IsPhi() const { return opcode() == kPhi; }
    568 
    569   // Declare virtual predicates for abstract HInstruction or HValue
    570   #define DECLARE_PREDICATE(type) \
    571     virtual bool Is##type() const { return false; }
    572     HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
    573   #undef DECLARE_PREDICATE
    574 
    575   HValue() : block_(NULL),
    576              id_(kNoNumber),
    577              type_(HType::Tagged()),
    578              use_list_(NULL),
    579              range_(NULL),
    580              flags_(0) {}
    581   virtual ~HValue() {}
    582 
    583   HBasicBlock* block() const { return block_; }
    584   void SetBlock(HBasicBlock* block);
    585   int LoopWeight() const;
    586 
    587   int id() const { return id_; }
    588   void set_id(int id) { id_ = id; }
    589 
    590   HUseIterator uses() const { return HUseIterator(use_list_); }
    591 
    592   virtual bool EmitAtUses() { return false; }
    593   Representation representation() const { return representation_; }
    594   void ChangeRepresentation(Representation r) {
    595     // Representation was already set and is allowed to be changed.
    596     ASSERT(!r.IsNone());
    597     ASSERT(CheckFlag(kFlexibleRepresentation));
    598     RepresentationChanged(r);
    599     representation_ = r;
    600   }
    601   void AssumeRepresentation(Representation r);
    602 
    603   virtual bool IsConvertibleToInteger() const { return true; }
    604 
    605   HType type() const { return type_; }
    606   void set_type(HType new_type) {
    607     ASSERT(new_type.IsSubtypeOf(type_));
    608     type_ = new_type;
    609   }
    610 
    611   // An operation needs to override this function iff:
    612   //   1) it can produce an int32 output.
    613   //   2) the true value of its output can potentially be minus zero.
    614   // The implementation must set a flag so that it bails out in the case where
    615   // it would otherwise output what should be a minus zero as an int32 zero.
    616   // If the operation also exists in a form that takes int32 and outputs int32
    617   // then the operation should return its input value so that we can propagate
    618   // back.  There are three operations that need to propagate back to more than
    619   // one input.  They are phi and binary div and mul.  They always return NULL
    620   // and expect the caller to take care of things.
    621   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
    622     visited->Add(id());
    623     return NULL;
    624   }
    625 
    626   bool IsDefinedAfter(HBasicBlock* other) const;
    627 
    628   // Operands.
    629   virtual int OperandCount() = 0;
    630   virtual HValue* OperandAt(int index) = 0;
    631   void SetOperandAt(int index, HValue* value);
    632 
    633   void DeleteAndReplaceWith(HValue* other);
    634   void ReplaceAllUsesWith(HValue* other);
    635   bool HasNoUses() const { return use_list_ == NULL; }
    636   bool HasMultipleUses() const {
    637     return use_list_ != NULL && use_list_->tail() != NULL;
    638   }
    639   int UseCount() const;
    640 
    641   // Mark this HValue as dead and to be removed from other HValues' use lists.
    642   void Kill();
    643 
    644   int flags() const { return flags_; }
    645   void SetFlag(Flag f) { flags_ |= (1 << f); }
    646   void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
    647   bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
    648 
    649   // Returns true if the flag specified is set for all uses, false otherwise.
    650   bool CheckUsesForFlag(Flag f);
    651 
    652   GVNFlagSet gvn_flags() const { return gvn_flags_; }
    653   void SetGVNFlag(GVNFlag f) { gvn_flags_.Add(f); }
    654   void ClearGVNFlag(GVNFlag f) { gvn_flags_.Remove(f); }
    655   bool CheckGVNFlag(GVNFlag f) const { return gvn_flags_.Contains(f); }
    656   void SetAllSideEffects() { gvn_flags_.Add(AllSideEffectsFlagSet()); }
    657   void ClearAllSideEffects() {
    658     gvn_flags_.Remove(AllSideEffectsFlagSet());
    659   }
    660   bool HasSideEffects() const {
    661     return gvn_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
    662   }
    663   bool HasObservableSideEffects() const {
    664     return gvn_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
    665   }
    666 
    667   GVNFlagSet DependsOnFlags() const {
    668     GVNFlagSet result = gvn_flags_;
    669     result.Intersect(AllDependsOnFlagSet());
    670     return result;
    671   }
    672 
    673   GVNFlagSet SideEffectFlags() const {
    674     GVNFlagSet result = gvn_flags_;
    675     result.Intersect(AllSideEffectsFlagSet());
    676     return result;
    677   }
    678 
    679   GVNFlagSet ChangesFlags() const {
    680     GVNFlagSet result = gvn_flags_;
    681     result.Intersect(AllChangesFlagSet());
    682     return result;
    683   }
    684 
    685   GVNFlagSet ObservableChangesFlags() const {
    686     GVNFlagSet result = gvn_flags_;
    687     result.Intersect(AllChangesFlagSet());
    688     result.Intersect(AllObservableSideEffectsFlagSet());
    689     return result;
    690   }
    691 
    692   Range* range() const { return range_; }
    693   bool HasRange() const { return range_ != NULL; }
    694   void AddNewRange(Range* r, Zone* zone);
    695   void RemoveLastAddedRange();
    696   void ComputeInitialRange(Zone* zone);
    697 
    698   // Representation helpers.
    699   virtual Representation RequiredInputRepresentation(int index) = 0;
    700 
    701   virtual Representation InferredRepresentation() {
    702     return representation();
    703   }
    704 
    705   // This gives the instruction an opportunity to replace itself with an
    706   // instruction that does the same in some better way.  To replace an
    707   // instruction with a new one, first add the new instruction to the graph,
    708   // then return it.  Return NULL to have the instruction deleted.
    709   virtual HValue* Canonicalize() { return this; }
    710 
    711   bool Equals(HValue* other);
    712   virtual intptr_t Hashcode();
    713 
    714   // Printing support.
    715   virtual void PrintTo(StringStream* stream) = 0;
    716   void PrintNameTo(StringStream* stream);
    717   void PrintTypeTo(StringStream* stream);
    718   void PrintRangeTo(StringStream* stream);
    719   void PrintChangesTo(StringStream* stream);
    720 
    721   const char* Mnemonic() const;
    722 
    723   // Updated the inferred type of this instruction and returns true if
    724   // it has changed.
    725   bool UpdateInferredType();
    726 
    727   virtual HType CalculateInferredType();
    728 
    729 #ifdef DEBUG
    730   virtual void Verify() = 0;
    731 #endif
    732 
    733  protected:
    734   // This function must be overridden for instructions with flag kUseGVN, to
    735   // compare the non-Operand parts of the instruction.
    736   virtual bool DataEquals(HValue* other) {
    737     UNREACHABLE();
    738     return false;
    739   }
    740   virtual void RepresentationChanged(Representation to) { }
    741   virtual Range* InferRange(Zone* zone);
    742   virtual void DeleteFromGraph() = 0;
    743   virtual void InternalSetOperandAt(int index, HValue* value) = 0;
    744   void clear_block() {
    745     ASSERT(block_ != NULL);
    746     block_ = NULL;
    747   }
    748 
    749   void set_representation(Representation r) {
    750     // Representation is set-once.
    751     ASSERT(representation_.IsNone() && !r.IsNone());
    752     representation_ = r;
    753   }
    754 
    755   static GVNFlagSet AllDependsOnFlagSet() {
    756     GVNFlagSet result;
    757     // Create changes mask.
    758 #define ADD_FLAG(type) result.Add(kDependsOn##type);
    759   GVN_FLAG_LIST(ADD_FLAG)
    760 #undef ADD_FLAG
    761     return result;
    762   }
    763 
    764   static GVNFlagSet AllChangesFlagSet() {
    765     GVNFlagSet result;
    766     // Create changes mask.
    767 #define ADD_FLAG(type) result.Add(kChanges##type);
    768   GVN_FLAG_LIST(ADD_FLAG)
    769 #undef ADD_FLAG
    770     return result;
    771   }
    772 
    773   // A flag mask to mark an instruction as having arbitrary side effects.
    774   static GVNFlagSet AllSideEffectsFlagSet() {
    775     GVNFlagSet result = AllChangesFlagSet();
    776     result.Remove(kChangesOsrEntries);
    777     return result;
    778   }
    779 
    780   // A flag mask of all side effects that can make observable changes in
    781   // an executing program (i.e. are not safe to repeat, move or remove);
    782   static GVNFlagSet AllObservableSideEffectsFlagSet() {
    783     GVNFlagSet result = AllChangesFlagSet();
    784     result.Remove(kChangesElementsKind);
    785     result.Remove(kChangesElementsPointer);
    786     result.Remove(kChangesMaps);
    787     return result;
    788   }
    789 
    790   // Remove the matching use from the use list if present.  Returns the
    791   // removed list node or NULL.
    792   HUseListNode* RemoveUse(HValue* value, int index);
    793 
    794   void RegisterUse(int index, HValue* new_value);
    795 
    796   HBasicBlock* block_;
    797 
    798   // The id of this instruction in the hydrogen graph, assigned when first
    799   // added to the graph. Reflects creation order.
    800   int id_;
    801 
    802   Representation representation_;
    803   HType type_;
    804   HUseListNode* use_list_;
    805   Range* range_;
    806   int flags_;
    807   GVNFlagSet gvn_flags_;
    808 
    809  private:
    810   DISALLOW_COPY_AND_ASSIGN(HValue);
    811 };
    812 
    813 
    814 class HInstruction: public HValue {
    815  public:
    816   HInstruction* next() const { return next_; }
    817   HInstruction* previous() const { return previous_; }
    818 
    819   virtual void PrintTo(StringStream* stream);
    820   virtual void PrintDataTo(StringStream* stream) { }
    821 
    822   bool IsLinked() const { return block() != NULL; }
    823   void Unlink();
    824   void InsertBefore(HInstruction* next);
    825   void InsertAfter(HInstruction* previous);
    826 
    827   int position() const { return position_; }
    828   bool has_position() const { return position_ != RelocInfo::kNoPosition; }
    829   void set_position(int position) { position_ = position; }
    830 
    831   bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
    832 
    833   virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
    834 
    835 #ifdef DEBUG
    836   virtual void Verify();
    837 #endif
    838 
    839   virtual bool IsCall() { return false; }
    840 
    841   DECLARE_ABSTRACT_INSTRUCTION(Instruction)
    842 
    843  protected:
    844   HInstruction()
    845       : next_(NULL),
    846         previous_(NULL),
    847         position_(RelocInfo::kNoPosition) {
    848     SetGVNFlag(kDependsOnOsrEntries);
    849   }
    850 
    851   virtual void DeleteFromGraph() { Unlink(); }
    852 
    853  private:
    854   void InitializeAsFirst(HBasicBlock* block) {
    855     ASSERT(!IsLinked());
    856     SetBlock(block);
    857   }
    858 
    859   void PrintMnemonicTo(StringStream* stream);
    860 
    861   HInstruction* next_;
    862   HInstruction* previous_;
    863   int position_;
    864 
    865   friend class HBasicBlock;
    866 };
    867 
    868 
    869 template<int V>
    870 class HTemplateInstruction : public HInstruction {
    871  public:
    872   int OperandCount() { return V; }
    873   HValue* OperandAt(int i) { return inputs_[i]; }
    874 
    875  protected:
    876   void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
    877 
    878  private:
    879   EmbeddedContainer<HValue*, V> inputs_;
    880 };
    881 
    882 
    883 class HControlInstruction: public HInstruction {
    884  public:
    885   virtual HBasicBlock* SuccessorAt(int i) = 0;
    886   virtual int SuccessorCount() = 0;
    887   virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
    888 
    889   virtual void PrintDataTo(StringStream* stream);
    890 
    891   HBasicBlock* FirstSuccessor() {
    892     return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
    893   }
    894   HBasicBlock* SecondSuccessor() {
    895     return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
    896   }
    897 
    898   DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
    899 };
    900 
    901 
    902 class HSuccessorIterator BASE_EMBEDDED {
    903  public:
    904   explicit HSuccessorIterator(HControlInstruction* instr)
    905       : instr_(instr), current_(0) { }
    906 
    907   bool Done() { return current_ >= instr_->SuccessorCount(); }
    908   HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
    909   void Advance() { current_++; }
    910 
    911  private:
    912   HControlInstruction* instr_;
    913   int current_;
    914 };
    915 
    916 
    917 template<int S, int V>
    918 class HTemplateControlInstruction: public HControlInstruction {
    919  public:
    920   int SuccessorCount() { return S; }
    921   HBasicBlock* SuccessorAt(int i) { return successors_[i]; }
    922   void SetSuccessorAt(int i, HBasicBlock* block) { successors_[i] = block; }
    923 
    924   int OperandCount() { return V; }
    925   HValue* OperandAt(int i) { return inputs_[i]; }
    926 
    927 
    928  protected:
    929   void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
    930 
    931  private:
    932   EmbeddedContainer<HBasicBlock*, S> successors_;
    933   EmbeddedContainer<HValue*, V> inputs_;
    934 };
    935 
    936 
    937 class HBlockEntry: public HTemplateInstruction<0> {
    938  public:
    939   virtual Representation RequiredInputRepresentation(int index) {
    940     return Representation::None();
    941   }
    942 
    943   DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
    944 };
    945 
    946 
    947 // We insert soft-deoptimize when we hit code with unknown typefeedback,
    948 // so that we get a chance of re-optimizing with useful typefeedback.
    949 // HSoftDeoptimize does not end a basic block as opposed to HDeoptimize.
    950 class HSoftDeoptimize: public HTemplateInstruction<0> {
    951  public:
    952   virtual Representation RequiredInputRepresentation(int index) {
    953     return Representation::None();
    954   }
    955 
    956   DECLARE_CONCRETE_INSTRUCTION(SoftDeoptimize)
    957 };
    958 
    959 
    960 class HDeoptimize: public HControlInstruction {
    961  public:
    962   explicit HDeoptimize(int environment_length) : values_(environment_length) { }
    963 
    964   virtual Representation RequiredInputRepresentation(int index) {
    965     return Representation::None();
    966   }
    967 
    968   virtual int OperandCount() { return values_.length(); }
    969   virtual HValue* OperandAt(int index) { return values_[index]; }
    970   virtual void PrintDataTo(StringStream* stream);
    971 
    972   virtual int SuccessorCount() { return 0; }
    973   virtual HBasicBlock* SuccessorAt(int i) {
    974     UNREACHABLE();
    975     return NULL;
    976   }
    977   virtual void SetSuccessorAt(int i, HBasicBlock* block) {
    978     UNREACHABLE();
    979   }
    980 
    981   void AddEnvironmentValue(HValue* value) {
    982     values_.Add(NULL);
    983     SetOperandAt(values_.length() - 1, value);
    984   }
    985 
    986   DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
    987 
    988   enum UseEnvironment {
    989     kNoUses,
    990     kUseAll
    991   };
    992 
    993  protected:
    994   virtual void InternalSetOperandAt(int index, HValue* value) {
    995     values_[index] = value;
    996   }
    997 
    998  private:
    999   ZoneList<HValue*> values_;
   1000 };
   1001 
   1002 
   1003 class HGoto: public HTemplateControlInstruction<1, 0> {
   1004  public:
   1005   explicit HGoto(HBasicBlock* target) {
   1006     SetSuccessorAt(0, target);
   1007   }
   1008 
   1009   virtual Representation RequiredInputRepresentation(int index) {
   1010     return Representation::None();
   1011   }
   1012 
   1013   virtual void PrintDataTo(StringStream* stream);
   1014 
   1015   DECLARE_CONCRETE_INSTRUCTION(Goto)
   1016 };
   1017 
   1018 
   1019 class HUnaryControlInstruction: public HTemplateControlInstruction<2, 1> {
   1020  public:
   1021   HUnaryControlInstruction(HValue* value,
   1022                            HBasicBlock* true_target,
   1023                            HBasicBlock* false_target) {
   1024     SetOperandAt(0, value);
   1025     SetSuccessorAt(0, true_target);
   1026     SetSuccessorAt(1, false_target);
   1027   }
   1028 
   1029   virtual void PrintDataTo(StringStream* stream);
   1030 
   1031   HValue* value() { return OperandAt(0); }
   1032 };
   1033 
   1034 
   1035 class HBranch: public HUnaryControlInstruction {
   1036  public:
   1037   HBranch(HValue* value,
   1038           HBasicBlock* true_target,
   1039           HBasicBlock* false_target,
   1040           ToBooleanStub::Types expected_input_types = ToBooleanStub::no_types())
   1041       : HUnaryControlInstruction(value, true_target, false_target),
   1042         expected_input_types_(expected_input_types) {
   1043     ASSERT(true_target != NULL && false_target != NULL);
   1044   }
   1045   explicit HBranch(HValue* value)
   1046       : HUnaryControlInstruction(value, NULL, NULL) { }
   1047 
   1048 
   1049   virtual Representation RequiredInputRepresentation(int index) {
   1050     return Representation::None();
   1051   }
   1052 
   1053   ToBooleanStub::Types expected_input_types() const {
   1054     return expected_input_types_;
   1055   }
   1056 
   1057   DECLARE_CONCRETE_INSTRUCTION(Branch)
   1058 
   1059  private:
   1060   ToBooleanStub::Types expected_input_types_;
   1061 };
   1062 
   1063 
   1064 class HCompareMap: public HUnaryControlInstruction {
   1065  public:
   1066   HCompareMap(HValue* value,
   1067               Handle<Map> map,
   1068               HBasicBlock* true_target,
   1069               HBasicBlock* false_target)
   1070       : HUnaryControlInstruction(value, true_target, false_target),
   1071         map_(map) {
   1072     ASSERT(true_target != NULL);
   1073     ASSERT(false_target != NULL);
   1074     ASSERT(!map.is_null());
   1075   }
   1076 
   1077   virtual void PrintDataTo(StringStream* stream);
   1078 
   1079   Handle<Map> map() const { return map_; }
   1080 
   1081   virtual Representation RequiredInputRepresentation(int index) {
   1082     return Representation::Tagged();
   1083   }
   1084 
   1085   DECLARE_CONCRETE_INSTRUCTION(CompareMap)
   1086 
   1087  private:
   1088   Handle<Map> map_;
   1089 };
   1090 
   1091 
   1092 class HReturn: public HTemplateControlInstruction<0, 1> {
   1093  public:
   1094   explicit HReturn(HValue* value) {
   1095     SetOperandAt(0, value);
   1096   }
   1097 
   1098   virtual Representation RequiredInputRepresentation(int index) {
   1099     return Representation::Tagged();
   1100   }
   1101 
   1102   virtual void PrintDataTo(StringStream* stream);
   1103 
   1104   HValue* value() { return OperandAt(0); }
   1105 
   1106   DECLARE_CONCRETE_INSTRUCTION(Return)
   1107 };
   1108 
   1109 
   1110 class HAbnormalExit: public HTemplateControlInstruction<0, 0> {
   1111  public:
   1112   virtual Representation RequiredInputRepresentation(int index) {
   1113     return Representation::None();
   1114   }
   1115 
   1116   DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
   1117 };
   1118 
   1119 
   1120 class HUnaryOperation: public HTemplateInstruction<1> {
   1121  public:
   1122   explicit HUnaryOperation(HValue* value) {
   1123     SetOperandAt(0, value);
   1124   }
   1125 
   1126   static HUnaryOperation* cast(HValue* value) {
   1127     return reinterpret_cast<HUnaryOperation*>(value);
   1128   }
   1129 
   1130   HValue* value() { return OperandAt(0); }
   1131   virtual void PrintDataTo(StringStream* stream);
   1132 };
   1133 
   1134 
   1135 class HThrow: public HTemplateInstruction<2> {
   1136  public:
   1137   HThrow(HValue* context, HValue* value) {
   1138     SetOperandAt(0, context);
   1139     SetOperandAt(1, value);
   1140     SetAllSideEffects();
   1141   }
   1142 
   1143   virtual Representation RequiredInputRepresentation(int index) {
   1144     return Representation::Tagged();
   1145   }
   1146 
   1147   HValue* context() { return OperandAt(0); }
   1148   HValue* value() { return OperandAt(1); }
   1149 
   1150   DECLARE_CONCRETE_INSTRUCTION(Throw)
   1151 };
   1152 
   1153 
   1154 class HUseConst: public HUnaryOperation {
   1155  public:
   1156   explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
   1157 
   1158   virtual Representation RequiredInputRepresentation(int index) {
   1159     return Representation::None();
   1160   }
   1161 
   1162   DECLARE_CONCRETE_INSTRUCTION(UseConst)
   1163 };
   1164 
   1165 
   1166 class HForceRepresentation: public HTemplateInstruction<1> {
   1167  public:
   1168   HForceRepresentation(HValue* value, Representation required_representation) {
   1169     SetOperandAt(0, value);
   1170     set_representation(required_representation);
   1171   }
   1172 
   1173   HValue* value() { return OperandAt(0); }
   1174 
   1175   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
   1176 
   1177   virtual Representation RequiredInputRepresentation(int index) {
   1178     return representation();  // Same as the output representation.
   1179   }
   1180 
   1181   DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
   1182 };
   1183 
   1184 
   1185 class HChange: public HUnaryOperation {
   1186  public:
   1187   HChange(HValue* value,
   1188           Representation to,
   1189           bool is_truncating,
   1190           bool deoptimize_on_undefined)
   1191       : HUnaryOperation(value) {
   1192     ASSERT(!value->representation().IsNone() && !to.IsNone());
   1193     ASSERT(!value->representation().Equals(to));
   1194     set_representation(to);
   1195     set_type(HType::TaggedNumber());
   1196     SetFlag(kUseGVN);
   1197     if (deoptimize_on_undefined) SetFlag(kDeoptimizeOnUndefined);
   1198     if (is_truncating) SetFlag(kTruncatingToInt32);
   1199   }
   1200 
   1201   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
   1202   virtual HType CalculateInferredType();
   1203   virtual HValue* Canonicalize();
   1204 
   1205   Representation from() { return value()->representation(); }
   1206   Representation to() { return representation(); }
   1207   bool deoptimize_on_undefined() const {
   1208     return CheckFlag(kDeoptimizeOnUndefined);
   1209   }
   1210   bool deoptimize_on_minus_zero() const {
   1211     return CheckFlag(kBailoutOnMinusZero);
   1212   }
   1213   virtual Representation RequiredInputRepresentation(int index) {
   1214     return from();
   1215   }
   1216 
   1217   virtual Range* InferRange(Zone* zone);
   1218 
   1219   virtual void PrintDataTo(StringStream* stream);
   1220 
   1221   DECLARE_CONCRETE_INSTRUCTION(Change)
   1222 
   1223  protected:
   1224   virtual bool DataEquals(HValue* other) { return true; }
   1225 };
   1226 
   1227 
   1228 class HClampToUint8: public HUnaryOperation {
   1229  public:
   1230   explicit HClampToUint8(HValue* value)
   1231       : HUnaryOperation(value) {
   1232     set_representation(Representation::Integer32());
   1233     SetFlag(kUseGVN);
   1234   }
   1235 
   1236   virtual Representation RequiredInputRepresentation(int index) {
   1237     return Representation::None();
   1238   }
   1239 
   1240   DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
   1241 
   1242  protected:
   1243   virtual bool DataEquals(HValue* other) { return true; }
   1244 };
   1245 
   1246 
   1247 class HSimulate: public HInstruction {
   1248  public:
   1249   HSimulate(int ast_id, int pop_count)
   1250       : ast_id_(ast_id),
   1251         pop_count_(pop_count),
   1252         values_(2),
   1253         assigned_indexes_(2) {}
   1254   virtual ~HSimulate() {}
   1255 
   1256   virtual void PrintDataTo(StringStream* stream);
   1257 
   1258   bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; }
   1259   int ast_id() const { return ast_id_; }
   1260   void set_ast_id(int id) {
   1261     ASSERT(!HasAstId());
   1262     ast_id_ = id;
   1263   }
   1264 
   1265   int pop_count() const { return pop_count_; }
   1266   const ZoneList<HValue*>* values() const { return &values_; }
   1267   int GetAssignedIndexAt(int index) const {
   1268     ASSERT(HasAssignedIndexAt(index));
   1269     return assigned_indexes_[index];
   1270   }
   1271   bool HasAssignedIndexAt(int index) const {
   1272     return assigned_indexes_[index] != kNoIndex;
   1273   }
   1274   void AddAssignedValue(int index, HValue* value) {
   1275     AddValue(index, value);
   1276   }
   1277   void AddPushedValue(HValue* value) {
   1278     AddValue(kNoIndex, value);
   1279   }
   1280   virtual int OperandCount() { return values_.length(); }
   1281   virtual HValue* OperandAt(int index) { return values_[index]; }
   1282 
   1283   virtual Representation RequiredInputRepresentation(int index) {
   1284     return Representation::None();
   1285   }
   1286 
   1287   DECLARE_CONCRETE_INSTRUCTION(Simulate)
   1288 
   1289 #ifdef DEBUG
   1290   virtual void Verify();
   1291 #endif
   1292 
   1293  protected:
   1294   virtual void InternalSetOperandAt(int index, HValue* value) {
   1295     values_[index] = value;
   1296   }
   1297 
   1298  private:
   1299   static const int kNoIndex = -1;
   1300   void AddValue(int index, HValue* value) {
   1301     assigned_indexes_.Add(index);
   1302     // Resize the list of pushed values.
   1303     values_.Add(NULL);
   1304     // Set the operand through the base method in HValue to make sure that the
   1305     // use lists are correctly updated.
   1306     SetOperandAt(values_.length() - 1, value);
   1307   }
   1308   int ast_id_;
   1309   int pop_count_;
   1310   ZoneList<HValue*> values_;
   1311   ZoneList<int> assigned_indexes_;
   1312 };
   1313 
   1314 
   1315 class HStackCheck: public HTemplateInstruction<1> {
   1316  public:
   1317   enum Type {
   1318     kFunctionEntry,
   1319     kBackwardsBranch
   1320   };
   1321 
   1322   HStackCheck(HValue* context, Type type) : type_(type) {
   1323     SetOperandAt(0, context);
   1324   }
   1325 
   1326   HValue* context() { return OperandAt(0); }
   1327 
   1328   virtual Representation RequiredInputRepresentation(int index) {
   1329     return Representation::Tagged();
   1330   }
   1331 
   1332   void Eliminate() {
   1333     // The stack check eliminator might try to eliminate the same stack
   1334     // check instruction multiple times.
   1335     if (IsLinked()) {
   1336       DeleteFromGraph();
   1337     }
   1338   }
   1339 
   1340   bool is_function_entry() { return type_ == kFunctionEntry; }
   1341   bool is_backwards_branch() { return type_ == kBackwardsBranch; }
   1342 
   1343   DECLARE_CONCRETE_INSTRUCTION(StackCheck)
   1344 
   1345  private:
   1346   Type type_;
   1347 };
   1348 
   1349 
   1350 class HEnterInlined: public HTemplateInstruction<0> {
   1351  public:
   1352   HEnterInlined(Handle<JSFunction> closure,
   1353                 int arguments_count,
   1354                 FunctionLiteral* function,
   1355                 CallKind call_kind,
   1356                 bool is_construct,
   1357                 Variable* arguments)
   1358       : closure_(closure),
   1359         arguments_count_(arguments_count),
   1360         function_(function),
   1361         call_kind_(call_kind),
   1362         is_construct_(is_construct),
   1363         arguments_(arguments) {
   1364   }
   1365 
   1366   virtual void PrintDataTo(StringStream* stream);
   1367 
   1368   Handle<JSFunction> closure() const { return closure_; }
   1369   int arguments_count() const { return arguments_count_; }
   1370   FunctionLiteral* function() const { return function_; }
   1371   CallKind call_kind() const { return call_kind_; }
   1372   bool is_construct() const { return is_construct_; }
   1373 
   1374   virtual Representation RequiredInputRepresentation(int index) {
   1375     return Representation::None();
   1376   }
   1377 
   1378   Variable* arguments() { return arguments_; }
   1379 
   1380   DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
   1381 
   1382  private:
   1383   Handle<JSFunction> closure_;
   1384   int arguments_count_;
   1385   FunctionLiteral* function_;
   1386   CallKind call_kind_;
   1387   bool is_construct_;
   1388   Variable* arguments_;
   1389 };
   1390 
   1391 
   1392 class HLeaveInlined: public HTemplateInstruction<0> {
   1393  public:
   1394   HLeaveInlined() {}
   1395 
   1396   virtual Representation RequiredInputRepresentation(int index) {
   1397     return Representation::None();
   1398   }
   1399 
   1400   DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
   1401 };
   1402 
   1403 
   1404 class HPushArgument: public HUnaryOperation {
   1405  public:
   1406   explicit HPushArgument(HValue* value) : HUnaryOperation(value) {
   1407     set_representation(Representation::Tagged());
   1408   }
   1409 
   1410   virtual Representation RequiredInputRepresentation(int index) {
   1411     return Representation::Tagged();
   1412   }
   1413 
   1414   HValue* argument() { return OperandAt(0); }
   1415 
   1416   DECLARE_CONCRETE_INSTRUCTION(PushArgument)
   1417 };
   1418 
   1419 
   1420 class HThisFunction: public HTemplateInstruction<0> {
   1421  public:
   1422   explicit HThisFunction(Handle<JSFunction> closure) : closure_(closure) {
   1423     set_representation(Representation::Tagged());
   1424     SetFlag(kUseGVN);
   1425   }
   1426 
   1427   virtual Representation RequiredInputRepresentation(int index) {
   1428     return Representation::None();
   1429   }
   1430 
   1431   Handle<JSFunction> closure() const { return closure_; }
   1432 
   1433   DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
   1434 
   1435  protected:
   1436   virtual bool DataEquals(HValue* other) {
   1437     HThisFunction* b = HThisFunction::cast(other);
   1438     return *closure() == *b->closure();
   1439   }
   1440 
   1441  private:
   1442   Handle<JSFunction> closure_;
   1443 };
   1444 
   1445 
   1446 class HContext: public HTemplateInstruction<0> {
   1447  public:
   1448   HContext() {
   1449     set_representation(Representation::Tagged());
   1450     SetFlag(kUseGVN);
   1451   }
   1452 
   1453   virtual Representation RequiredInputRepresentation(int index) {
   1454     return Representation::None();
   1455   }
   1456 
   1457   DECLARE_CONCRETE_INSTRUCTION(Context)
   1458 
   1459  protected:
   1460   virtual bool DataEquals(HValue* other) { return true; }
   1461 };
   1462 
   1463 
   1464 class HOuterContext: public HUnaryOperation {
   1465  public:
   1466   explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
   1467     set_representation(Representation::Tagged());
   1468     SetFlag(kUseGVN);
   1469   }
   1470 
   1471   DECLARE_CONCRETE_INSTRUCTION(OuterContext);
   1472 
   1473   virtual Representation RequiredInputRepresentation(int index) {
   1474     return Representation::Tagged();
   1475   }
   1476 
   1477  protected:
   1478   virtual bool DataEquals(HValue* other) { return true; }
   1479 };
   1480 
   1481 
   1482 class HDeclareGlobals: public HUnaryOperation {
   1483  public:
   1484   HDeclareGlobals(HValue* context,
   1485                   Handle<FixedArray> pairs,
   1486                   int flags)
   1487       : HUnaryOperation(context),
   1488         pairs_(pairs),
   1489         flags_(flags) {
   1490     set_representation(Representation::Tagged());
   1491     SetAllSideEffects();
   1492   }
   1493 
   1494   HValue* context() { return OperandAt(0); }
   1495   Handle<FixedArray> pairs() const { return pairs_; }
   1496   int flags() const { return flags_; }
   1497 
   1498   DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
   1499 
   1500   virtual Representation RequiredInputRepresentation(int index) {
   1501     return Representation::Tagged();
   1502   }
   1503  private:
   1504   Handle<FixedArray> pairs_;
   1505   int flags_;
   1506 };
   1507 
   1508 
   1509 class HGlobalObject: public HUnaryOperation {
   1510  public:
   1511   explicit HGlobalObject(HValue* context) : HUnaryOperation(context) {
   1512     set_representation(Representation::Tagged());
   1513     SetFlag(kUseGVN);
   1514   }
   1515 
   1516   DECLARE_CONCRETE_INSTRUCTION(GlobalObject)
   1517 
   1518   virtual Representation RequiredInputRepresentation(int index) {
   1519     return Representation::Tagged();
   1520   }
   1521 
   1522  protected:
   1523   virtual bool DataEquals(HValue* other) { return true; }
   1524 };
   1525 
   1526 
   1527 class HGlobalReceiver: public HUnaryOperation {
   1528  public:
   1529   explicit HGlobalReceiver(HValue* global_object)
   1530       : HUnaryOperation(global_object) {
   1531     set_representation(Representation::Tagged());
   1532     SetFlag(kUseGVN);
   1533   }
   1534 
   1535   DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver)
   1536 
   1537   virtual Representation RequiredInputRepresentation(int index) {
   1538     return Representation::Tagged();
   1539   }
   1540 
   1541  protected:
   1542   virtual bool DataEquals(HValue* other) { return true; }
   1543 };
   1544 
   1545 
   1546 template <int V>
   1547 class HCall: public HTemplateInstruction<V> {
   1548  public:
   1549   // The argument count includes the receiver.
   1550   explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
   1551     this->set_representation(Representation::Tagged());
   1552     this->SetAllSideEffects();
   1553   }
   1554 
   1555   virtual HType CalculateInferredType() { return HType::Tagged(); }
   1556 
   1557   virtual int argument_count() const { return argument_count_; }
   1558 
   1559   virtual bool IsCall() { return true; }
   1560 
   1561  private:
   1562   int argument_count_;
   1563 };
   1564 
   1565 
   1566 class HUnaryCall: public HCall<1> {
   1567  public:
   1568   HUnaryCall(HValue* value, int argument_count)
   1569       : HCall<1>(argument_count) {
   1570     SetOperandAt(0, value);
   1571   }
   1572 
   1573   virtual Representation RequiredInputRepresentation(int index) {
   1574     return Representation::Tagged();
   1575   }
   1576 
   1577   virtual void PrintDataTo(StringStream* stream);
   1578 
   1579   HValue* value() { return OperandAt(0); }
   1580 };
   1581 
   1582 
   1583 class HBinaryCall: public HCall<2> {
   1584  public:
   1585   HBinaryCall(HValue* first, HValue* second, int argument_count)
   1586       : HCall<2>(argument_count) {
   1587     SetOperandAt(0, first);
   1588     SetOperandAt(1, second);
   1589   }
   1590 
   1591   virtual void PrintDataTo(StringStream* stream);
   1592 
   1593   virtual Representation RequiredInputRepresentation(int index) {
   1594     return Representation::Tagged();
   1595   }
   1596 
   1597   HValue* first() { return OperandAt(0); }
   1598   HValue* second() { return OperandAt(1); }
   1599 };
   1600 
   1601 
   1602 class HInvokeFunction: public HBinaryCall {
   1603  public:
   1604   HInvokeFunction(HValue* context, HValue* function, int argument_count)
   1605       : HBinaryCall(context, function, argument_count) {
   1606   }
   1607 
   1608   virtual Representation RequiredInputRepresentation(int index) {
   1609     return Representation::Tagged();
   1610   }
   1611 
   1612   HValue* context() { return first(); }
   1613   HValue* function() { return second(); }
   1614 
   1615   DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
   1616 };
   1617 
   1618 
   1619 class HCallConstantFunction: public HCall<0> {
   1620  public:
   1621   HCallConstantFunction(Handle<JSFunction> function, int argument_count)
   1622       : HCall<0>(argument_count), function_(function) { }
   1623 
   1624   Handle<JSFunction> function() const { return function_; }
   1625 
   1626   bool IsApplyFunction() const {
   1627     return function_->code() ==
   1628         Isolate::Current()->builtins()->builtin(Builtins::kFunctionApply);
   1629   }
   1630 
   1631   virtual void PrintDataTo(StringStream* stream);
   1632 
   1633   virtual Representation RequiredInputRepresentation(int index) {
   1634     return Representation::None();
   1635   }
   1636 
   1637   DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction)
   1638 
   1639  private:
   1640   Handle<JSFunction> function_;
   1641 };
   1642 
   1643 
   1644 class HCallKeyed: public HBinaryCall {
   1645  public:
   1646   HCallKeyed(HValue* context, HValue* key, int argument_count)
   1647       : HBinaryCall(context, key, argument_count) {
   1648   }
   1649 
   1650   virtual Representation RequiredInputRepresentation(int index) {
   1651     return Representation::Tagged();
   1652   }
   1653 
   1654   HValue* context() { return first(); }
   1655   HValue* key() { return second(); }
   1656 
   1657   DECLARE_CONCRETE_INSTRUCTION(CallKeyed)
   1658 };
   1659 
   1660 
   1661 class HCallNamed: public HUnaryCall {
   1662  public:
   1663   HCallNamed(HValue* context, Handle<String> name, int argument_count)
   1664       : HUnaryCall(context, argument_count), name_(name) {
   1665   }
   1666 
   1667   virtual void PrintDataTo(StringStream* stream);
   1668 
   1669   HValue* context() { return value(); }
   1670   Handle<String> name() const { return name_; }
   1671 
   1672   DECLARE_CONCRETE_INSTRUCTION(CallNamed)
   1673 
   1674   virtual Representation RequiredInputRepresentation(int index) {
   1675     return Representation::Tagged();
   1676   }
   1677 
   1678  private:
   1679   Handle<String> name_;
   1680 };
   1681 
   1682 
   1683 class HCallFunction: public HBinaryCall {
   1684  public:
   1685   HCallFunction(HValue* context, HValue* function, int argument_count)
   1686       : HBinaryCall(context, function, argument_count) {
   1687   }
   1688 
   1689   HValue* context() { return first(); }
   1690   HValue* function() { return second(); }
   1691 
   1692   virtual Representation RequiredInputRepresentation(int index) {
   1693     return Representation::Tagged();
   1694   }
   1695 
   1696   DECLARE_CONCRETE_INSTRUCTION(CallFunction)
   1697 };
   1698 
   1699 
   1700 class HCallGlobal: public HUnaryCall {
   1701  public:
   1702   HCallGlobal(HValue* context, Handle<String> name, int argument_count)
   1703       : HUnaryCall(context, argument_count), name_(name) {
   1704   }
   1705 
   1706   virtual void PrintDataTo(StringStream* stream);
   1707 
   1708   HValue* context() { return value(); }
   1709   Handle<String> name() const { return name_; }
   1710 
   1711   virtual Representation RequiredInputRepresentation(int index) {
   1712     return Representation::Tagged();
   1713   }
   1714 
   1715   DECLARE_CONCRETE_INSTRUCTION(CallGlobal)
   1716 
   1717  private:
   1718   Handle<String> name_;
   1719 };
   1720 
   1721 
   1722 class HCallKnownGlobal: public HCall<0> {
   1723  public:
   1724   HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
   1725       : HCall<0>(argument_count), target_(target) { }
   1726 
   1727   virtual void PrintDataTo(StringStream* stream);
   1728 
   1729   Handle<JSFunction> target() const { return target_; }
   1730 
   1731   virtual Representation RequiredInputRepresentation(int index) {
   1732     return Representation::None();
   1733   }
   1734 
   1735   DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal)
   1736 
   1737  private:
   1738   Handle<JSFunction> target_;
   1739 };
   1740 
   1741 
   1742 class HCallNew: public HBinaryCall {
   1743  public:
   1744   HCallNew(HValue* context, HValue* constructor, int argument_count)
   1745       : HBinaryCall(context, constructor, argument_count) {
   1746   }
   1747 
   1748   virtual Representation RequiredInputRepresentation(int index) {
   1749     return Representation::Tagged();
   1750   }
   1751 
   1752   HValue* context() { return first(); }
   1753   HValue* constructor() { return second(); }
   1754 
   1755   DECLARE_CONCRETE_INSTRUCTION(CallNew)
   1756 };
   1757 
   1758 
   1759 class HCallRuntime: public HCall<1> {
   1760  public:
   1761   HCallRuntime(HValue* context,
   1762                Handle<String> name,
   1763                const Runtime::Function* c_function,
   1764                int argument_count)
   1765       : HCall<1>(argument_count), c_function_(c_function), name_(name) {
   1766     SetOperandAt(0, context);
   1767   }
   1768 
   1769   virtual void PrintDataTo(StringStream* stream);
   1770 
   1771   HValue* context() { return OperandAt(0); }
   1772   const Runtime::Function* function() const { return c_function_; }
   1773   Handle<String> name() const { return name_; }
   1774 
   1775   virtual Representation RequiredInputRepresentation(int index) {
   1776     return Representation::Tagged();
   1777   }
   1778 
   1779   DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
   1780 
   1781  private:
   1782   const Runtime::Function* c_function_;
   1783   Handle<String> name_;
   1784 };
   1785 
   1786 
   1787 class HJSArrayLength: public HTemplateInstruction<2> {
   1788  public:
   1789   HJSArrayLength(HValue* value, HValue* typecheck) {
   1790     // The length of an array is stored as a tagged value in the array
   1791     // object. It is guaranteed to be 32 bit integer, but it can be
   1792     // represented as either a smi or heap number.
   1793     SetOperandAt(0, value);
   1794     SetOperandAt(1, typecheck);
   1795     set_representation(Representation::Tagged());
   1796     SetFlag(kUseGVN);
   1797     SetGVNFlag(kDependsOnArrayLengths);
   1798     SetGVNFlag(kDependsOnMaps);
   1799   }
   1800 
   1801   virtual Representation RequiredInputRepresentation(int index) {
   1802     return Representation::Tagged();
   1803   }
   1804 
   1805   virtual void PrintDataTo(StringStream* stream);
   1806 
   1807   HValue* value() { return OperandAt(0); }
   1808   HValue* typecheck() { return OperandAt(1); }
   1809 
   1810   DECLARE_CONCRETE_INSTRUCTION(JSArrayLength)
   1811 
   1812  protected:
   1813   virtual bool DataEquals(HValue* other) { return true; }
   1814 };
   1815 
   1816 
   1817 class HFixedArrayBaseLength: public HUnaryOperation {
   1818  public:
   1819   explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) {
   1820     set_representation(Representation::Tagged());
   1821     SetFlag(kUseGVN);
   1822     SetGVNFlag(kDependsOnArrayLengths);
   1823   }
   1824 
   1825   virtual Representation RequiredInputRepresentation(int index) {
   1826     return Representation::Tagged();
   1827   }
   1828 
   1829   DECLARE_CONCRETE_INSTRUCTION(FixedArrayBaseLength)
   1830 
   1831  protected:
   1832   virtual bool DataEquals(HValue* other) { return true; }
   1833 };
   1834 
   1835 
   1836 class HElementsKind: public HUnaryOperation {
   1837  public:
   1838   explicit HElementsKind(HValue* value) : HUnaryOperation(value) {
   1839     set_representation(Representation::Integer32());
   1840     SetFlag(kUseGVN);
   1841     SetGVNFlag(kDependsOnElementsKind);
   1842   }
   1843 
   1844   virtual Representation RequiredInputRepresentation(int index) {
   1845     return Representation::Tagged();
   1846   }
   1847 
   1848   DECLARE_CONCRETE_INSTRUCTION(ElementsKind)
   1849 
   1850  protected:
   1851   virtual bool DataEquals(HValue* other) { return true; }
   1852 };
   1853 
   1854 
   1855 class HBitNot: public HUnaryOperation {
   1856  public:
   1857   explicit HBitNot(HValue* value) : HUnaryOperation(value) {
   1858     set_representation(Representation::Integer32());
   1859     SetFlag(kUseGVN);
   1860     SetFlag(kTruncatingToInt32);
   1861   }
   1862 
   1863   virtual Representation RequiredInputRepresentation(int index) {
   1864     return Representation::Integer32();
   1865   }
   1866   virtual HType CalculateInferredType();
   1867 
   1868   DECLARE_CONCRETE_INSTRUCTION(BitNot)
   1869 
   1870  protected:
   1871   virtual bool DataEquals(HValue* other) { return true; }
   1872 };
   1873 
   1874 
   1875 class HUnaryMathOperation: public HTemplateInstruction<2> {
   1876  public:
   1877   HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
   1878       : op_(op) {
   1879     SetOperandAt(0, context);
   1880     SetOperandAt(1, value);
   1881     switch (op) {
   1882       case kMathFloor:
   1883       case kMathRound:
   1884       case kMathCeil:
   1885         set_representation(Representation::Integer32());
   1886         break;
   1887       case kMathAbs:
   1888         set_representation(Representation::Tagged());
   1889         SetFlag(kFlexibleRepresentation);
   1890         break;
   1891       case kMathSqrt:
   1892       case kMathPowHalf:
   1893       case kMathLog:
   1894       case kMathSin:
   1895       case kMathCos:
   1896       case kMathTan:
   1897         set_representation(Representation::Double());
   1898         break;
   1899       default:
   1900         UNREACHABLE();
   1901     }
   1902     SetFlag(kUseGVN);
   1903   }
   1904 
   1905   HValue* context() { return OperandAt(0); }
   1906   HValue* value() { return OperandAt(1); }
   1907 
   1908   virtual void PrintDataTo(StringStream* stream);
   1909 
   1910   virtual HType CalculateInferredType();
   1911 
   1912   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
   1913 
   1914   virtual Representation RequiredInputRepresentation(int index) {
   1915     if (index == 0) {
   1916       return Representation::Tagged();
   1917     } else {
   1918       switch (op_) {
   1919         case kMathFloor:
   1920         case kMathRound:
   1921         case kMathCeil:
   1922         case kMathSqrt:
   1923         case kMathPowHalf:
   1924         case kMathLog:
   1925         case kMathSin:
   1926         case kMathCos:
   1927         case kMathTan:
   1928           return Representation::Double();
   1929         case kMathAbs:
   1930           return representation();
   1931         default:
   1932           UNREACHABLE();
   1933           return Representation::None();
   1934       }
   1935     }
   1936   }
   1937 
   1938   virtual HValue* Canonicalize() {
   1939     // If the input is integer32 then we replace the floor instruction
   1940     // with its inputs.  This happens before the representation changes are
   1941     // introduced.
   1942     if (op() == kMathFloor) {
   1943       if (value()->representation().IsInteger32()) return value();
   1944     }
   1945     return this;
   1946   }
   1947 
   1948   BuiltinFunctionId op() const { return op_; }
   1949   const char* OpName() const;
   1950 
   1951   DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
   1952 
   1953  protected:
   1954   virtual bool DataEquals(HValue* other) {
   1955     HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
   1956     return op_ == b->op();
   1957   }
   1958 
   1959  private:
   1960   BuiltinFunctionId op_;
   1961 };
   1962 
   1963 
   1964 class HLoadElements: public HUnaryOperation {
   1965  public:
   1966   explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
   1967     set_representation(Representation::Tagged());
   1968     SetFlag(kUseGVN);
   1969     SetGVNFlag(kDependsOnElementsPointer);
   1970   }
   1971 
   1972   virtual Representation RequiredInputRepresentation(int index) {
   1973     return Representation::Tagged();
   1974   }
   1975 
   1976   DECLARE_CONCRETE_INSTRUCTION(LoadElements)
   1977 
   1978  protected:
   1979   virtual bool DataEquals(HValue* other) { return true; }
   1980 };
   1981 
   1982 
   1983 class HLoadExternalArrayPointer: public HUnaryOperation {
   1984  public:
   1985   explicit HLoadExternalArrayPointer(HValue* value)
   1986       : HUnaryOperation(value) {
   1987     set_representation(Representation::External());
   1988     // The result of this instruction is idempotent as long as its inputs don't
   1989     // change.  The external array of a specialized array elements object cannot
   1990     // change once set, so it's no necessary to introduce any additional
   1991     // dependencies on top of the inputs.
   1992     SetFlag(kUseGVN);
   1993   }
   1994 
   1995   virtual Representation RequiredInputRepresentation(int index) {
   1996     return Representation::Tagged();
   1997   }
   1998 
   1999   DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer)
   2000 
   2001  protected:
   2002   virtual bool DataEquals(HValue* other) { return true; }
   2003 };
   2004 
   2005 
   2006 class HCheckMap: public HTemplateInstruction<2> {
   2007  public:
   2008   HCheckMap(HValue* value,
   2009             Handle<Map> map,
   2010             HValue* typecheck = NULL,
   2011             CompareMapMode mode = REQUIRE_EXACT_MAP)
   2012       : map_(map),
   2013         mode_(mode) {
   2014     SetOperandAt(0, value);
   2015     // If callers don't depend on a typecheck, they can pass in NULL. In that
   2016     // case we use a copy of the |value| argument as a dummy value.
   2017     SetOperandAt(1, typecheck != NULL ? typecheck : value);
   2018     set_representation(Representation::Tagged());
   2019     SetFlag(kUseGVN);
   2020     SetGVNFlag(kDependsOnMaps);
   2021     // If the map to check doesn't have the untransitioned elements, it must not
   2022     // be hoisted above TransitionElements instructions.
   2023     if (mode == REQUIRE_EXACT_MAP || !map->has_fast_smi_only_elements()) {
   2024       SetGVNFlag(kDependsOnElementsKind);
   2025     }
   2026     has_element_transitions_ =
   2027         map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL) != NULL ||
   2028         map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL) != NULL;
   2029   }
   2030 
   2031   virtual Representation RequiredInputRepresentation(int index) {
   2032     return Representation::Tagged();
   2033   }
   2034   virtual void PrintDataTo(StringStream* stream);
   2035   virtual HType CalculateInferredType();
   2036 
   2037   HValue* value() { return OperandAt(0); }
   2038   Handle<Map> map() const { return map_; }
   2039   CompareMapMode mode() const { return mode_; }
   2040 
   2041   DECLARE_CONCRETE_INSTRUCTION(CheckMap)
   2042 
   2043  protected:
   2044   virtual bool DataEquals(HValue* other) {
   2045     HCheckMap* b = HCheckMap::cast(other);
   2046     // Two CheckMaps instructions are DataEqual if their maps are identical and
   2047     // they have the same mode. The mode comparison can be ignored if the map
   2048     // has no elements transitions.
   2049     return map_.is_identical_to(b->map()) &&
   2050         (b->mode() == mode() || !has_element_transitions_);
   2051   }
   2052 
   2053  private:
   2054   bool has_element_transitions_;
   2055   Handle<Map> map_;
   2056   CompareMapMode mode_;
   2057 };
   2058 
   2059 
   2060 class HCheckFunction: public HUnaryOperation {
   2061  public:
   2062   HCheckFunction(HValue* value, Handle<JSFunction> function)
   2063       : HUnaryOperation(value), target_(function) {
   2064     set_representation(Representation::Tagged());
   2065     SetFlag(kUseGVN);
   2066   }
   2067 
   2068   virtual Representation RequiredInputRepresentation(int index) {
   2069     return Representation::Tagged();
   2070   }
   2071   virtual void PrintDataTo(StringStream* stream);
   2072   virtual HType CalculateInferredType();
   2073 
   2074 #ifdef DEBUG
   2075   virtual void Verify();
   2076 #endif
   2077 
   2078   Handle<JSFunction> target() const { return target_; }
   2079 
   2080   DECLARE_CONCRETE_INSTRUCTION(CheckFunction)
   2081 
   2082  protected:
   2083   virtual bool DataEquals(HValue* other) {
   2084     HCheckFunction* b = HCheckFunction::cast(other);
   2085     return target_.is_identical_to(b->target());
   2086   }
   2087 
   2088  private:
   2089   Handle<JSFunction> target_;
   2090 };
   2091 
   2092 
   2093 class HCheckInstanceType: public HUnaryOperation {
   2094  public:
   2095   static HCheckInstanceType* NewIsSpecObject(HValue* value) {
   2096     return new HCheckInstanceType(value, IS_SPEC_OBJECT);
   2097   }
   2098   static HCheckInstanceType* NewIsJSArray(HValue* value) {
   2099     return new HCheckInstanceType(value, IS_JS_ARRAY);
   2100   }
   2101   static HCheckInstanceType* NewIsString(HValue* value) {
   2102     return new HCheckInstanceType(value, IS_STRING);
   2103   }
   2104   static HCheckInstanceType* NewIsSymbol(HValue* value) {
   2105     return new HCheckInstanceType(value, IS_SYMBOL);
   2106   }
   2107 
   2108   virtual void PrintDataTo(StringStream* stream);
   2109 
   2110   virtual Representation RequiredInputRepresentation(int index) {
   2111     return Representation::Tagged();
   2112   }
   2113 
   2114   virtual HValue* Canonicalize();
   2115 
   2116   bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
   2117   void GetCheckInterval(InstanceType* first, InstanceType* last);
   2118   void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
   2119 
   2120   DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
   2121 
   2122  protected:
   2123   // TODO(ager): It could be nice to allow the ommision of instance
   2124   // type checks if we have already performed an instance type check
   2125   // with a larger range.
   2126   virtual bool DataEquals(HValue* other) {
   2127     HCheckInstanceType* b = HCheckInstanceType::cast(other);
   2128     return check_ == b->check_;
   2129   }
   2130 
   2131  private:
   2132   enum Check {
   2133     IS_SPEC_OBJECT,
   2134     IS_JS_ARRAY,
   2135     IS_STRING,
   2136     IS_SYMBOL,
   2137     LAST_INTERVAL_CHECK = IS_JS_ARRAY
   2138   };
   2139 
   2140   const char* GetCheckName();
   2141 
   2142   HCheckInstanceType(HValue* value, Check check)
   2143       : HUnaryOperation(value), check_(check) {
   2144     set_representation(Representation::Tagged());
   2145     SetFlag(kUseGVN);
   2146   }
   2147 
   2148   const Check check_;
   2149 };
   2150 
   2151 
   2152 class HCheckNonSmi: public HUnaryOperation {
   2153  public:
   2154   explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
   2155     set_representation(Representation::Tagged());
   2156     SetFlag(kUseGVN);
   2157   }
   2158 
   2159   virtual Representation RequiredInputRepresentation(int index) {
   2160     return Representation::Tagged();
   2161   }
   2162 
   2163   virtual HType CalculateInferredType();
   2164 
   2165 #ifdef DEBUG
   2166   virtual void Verify();
   2167 #endif
   2168 
   2169   virtual HValue* Canonicalize() {
   2170     HType value_type = value()->type();
   2171     if (!value_type.IsUninitialized() &&
   2172         (value_type.IsHeapNumber() ||
   2173          value_type.IsString() ||
   2174          value_type.IsBoolean() ||
   2175          value_type.IsNonPrimitive())) {
   2176       return NULL;
   2177     }
   2178     return this;
   2179   }
   2180 
   2181   DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi)
   2182 
   2183  protected:
   2184   virtual bool DataEquals(HValue* other) { return true; }
   2185 };
   2186 
   2187 
   2188 class HCheckPrototypeMaps: public HTemplateInstruction<0> {
   2189  public:
   2190   HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
   2191       : prototype_(prototype), holder_(holder) {
   2192     SetFlag(kUseGVN);
   2193     SetGVNFlag(kDependsOnMaps);
   2194   }
   2195 
   2196 #ifdef DEBUG
   2197   virtual void Verify();
   2198 #endif
   2199 
   2200   Handle<JSObject> prototype() const { return prototype_; }
   2201   Handle<JSObject> holder() const { return holder_; }
   2202 
   2203   DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps)
   2204 
   2205   virtual Representation RequiredInputRepresentation(int index) {
   2206     return Representation::None();
   2207   }
   2208 
   2209   virtual intptr_t Hashcode() {
   2210     ASSERT(!HEAP->IsAllocationAllowed());
   2211     intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
   2212     hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
   2213     return hash;
   2214   }
   2215 
   2216  protected:
   2217   virtual bool DataEquals(HValue* other) {
   2218     HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
   2219     return prototype_.is_identical_to(b->prototype()) &&
   2220         holder_.is_identical_to(b->holder());
   2221   }
   2222 
   2223  private:
   2224   Handle<JSObject> prototype_;
   2225   Handle<JSObject> holder_;
   2226 };
   2227 
   2228 
   2229 class HCheckSmi: public HUnaryOperation {
   2230  public:
   2231   explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
   2232     set_representation(Representation::Tagged());
   2233     SetFlag(kUseGVN);
   2234   }
   2235 
   2236   virtual Representation RequiredInputRepresentation(int index) {
   2237     return Representation::Tagged();
   2238   }
   2239   virtual HType CalculateInferredType();
   2240 
   2241 #ifdef DEBUG
   2242   virtual void Verify();
   2243 #endif
   2244 
   2245   DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
   2246 
   2247  protected:
   2248   virtual bool DataEquals(HValue* other) { return true; }
   2249 };
   2250 
   2251 
   2252 class HPhi: public HValue {
   2253  public:
   2254   explicit HPhi(int merged_index)
   2255       : inputs_(2),
   2256         merged_index_(merged_index),
   2257         phi_id_(-1),
   2258         is_live_(false),
   2259         is_convertible_to_integer_(true) {
   2260     for (int i = 0; i < Representation::kNumRepresentations; i++) {
   2261       non_phi_uses_[i] = 0;
   2262       indirect_uses_[i] = 0;
   2263     }
   2264     ASSERT(merged_index >= 0);
   2265     set_representation(Representation::Tagged());
   2266     SetFlag(kFlexibleRepresentation);
   2267   }
   2268 
   2269   virtual Representation InferredRepresentation();
   2270 
   2271   virtual Range* InferRange(Zone* zone);
   2272   virtual Representation RequiredInputRepresentation(int index) {
   2273     return representation();
   2274   }
   2275   virtual HType CalculateInferredType();
   2276   virtual int OperandCount() { return inputs_.length(); }
   2277   virtual HValue* OperandAt(int index) { return inputs_[index]; }
   2278   HValue* GetRedundantReplacement();
   2279   void AddInput(HValue* value);
   2280   bool HasRealUses();
   2281 
   2282   bool IsReceiver() { return merged_index_ == 0; }
   2283 
   2284   int merged_index() const { return merged_index_; }
   2285 
   2286   virtual void PrintTo(StringStream* stream);
   2287 
   2288 #ifdef DEBUG
   2289   virtual void Verify();
   2290 #endif
   2291 
   2292   void InitRealUses(int id);
   2293   void AddNonPhiUsesFrom(HPhi* other);
   2294   void AddIndirectUsesTo(int* use_count);
   2295 
   2296   int tagged_non_phi_uses() const {
   2297     return non_phi_uses_[Representation::kTagged];
   2298   }
   2299   int int32_non_phi_uses() const {
   2300     return non_phi_uses_[Representation::kInteger32];
   2301   }
   2302   int double_non_phi_uses() const {
   2303     return non_phi_uses_[Representation::kDouble];
   2304   }
   2305   int tagged_indirect_uses() const {
   2306     return indirect_uses_[Representation::kTagged];
   2307   }
   2308   int int32_indirect_uses() const {
   2309     return indirect_uses_[Representation::kInteger32];
   2310   }
   2311   int double_indirect_uses() const {
   2312     return indirect_uses_[Representation::kDouble];
   2313   }
   2314   int phi_id() { return phi_id_; }
   2315   bool is_live() { return is_live_; }
   2316   void set_is_live(bool b) { is_live_ = b; }
   2317 
   2318   static HPhi* cast(HValue* value) {
   2319     ASSERT(value->IsPhi());
   2320     return reinterpret_cast<HPhi*>(value);
   2321   }
   2322   virtual Opcode opcode() const { return HValue::kPhi; }
   2323 
   2324   virtual bool IsConvertibleToInteger() const {
   2325     return is_convertible_to_integer_;
   2326   }
   2327 
   2328   void set_is_convertible_to_integer(bool b) {
   2329     is_convertible_to_integer_ = b;
   2330   }
   2331 
   2332   bool AllOperandsConvertibleToInteger() {
   2333     for (int i = 0; i < OperandCount(); ++i) {
   2334       if (!OperandAt(i)->IsConvertibleToInteger()) return false;
   2335     }
   2336     return true;
   2337   }
   2338 
   2339  protected:
   2340   virtual void DeleteFromGraph();
   2341   virtual void InternalSetOperandAt(int index, HValue* value) {
   2342     inputs_[index] = value;
   2343   }
   2344 
   2345  private:
   2346   ZoneList<HValue*> inputs_;
   2347   int merged_index_;
   2348 
   2349   int non_phi_uses_[Representation::kNumRepresentations];
   2350   int indirect_uses_[Representation::kNumRepresentations];
   2351   int phi_id_;
   2352   bool is_live_;
   2353   bool is_convertible_to_integer_;
   2354 };
   2355 
   2356 
   2357 class HArgumentsObject: public HTemplateInstruction<0> {
   2358  public:
   2359   HArgumentsObject() {
   2360     set_representation(Representation::Tagged());
   2361     SetFlag(kIsArguments);
   2362   }
   2363 
   2364   virtual Representation RequiredInputRepresentation(int index) {
   2365     return Representation::None();
   2366   }
   2367 
   2368   DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
   2369 };
   2370 
   2371 
   2372 class HConstant: public HTemplateInstruction<0> {
   2373  public:
   2374   HConstant(Handle<Object> handle, Representation r);
   2375 
   2376   Handle<Object> handle() const { return handle_; }
   2377 
   2378   bool InOldSpace() const { return !HEAP->InNewSpace(*handle_); }
   2379 
   2380   bool ImmortalImmovable() const {
   2381     Heap* heap = HEAP;
   2382     if (*handle_ == heap->undefined_value()) return true;
   2383     if (*handle_ == heap->null_value()) return true;
   2384     if (*handle_ == heap->true_value()) return true;
   2385     if (*handle_ == heap->false_value()) return true;
   2386     if (*handle_ == heap->the_hole_value()) return true;
   2387     if (*handle_ == heap->minus_zero_value()) return true;
   2388     if (*handle_ == heap->nan_value()) return true;
   2389     if (*handle_ == heap->empty_string()) return true;
   2390     return false;
   2391   }
   2392 
   2393   virtual Representation RequiredInputRepresentation(int index) {
   2394     return Representation::None();
   2395   }
   2396 
   2397   virtual bool IsConvertibleToInteger() const {
   2398     if (handle_->IsSmi()) return true;
   2399     if (handle_->IsHeapNumber() &&
   2400         (HeapNumber::cast(*handle_)->value() ==
   2401          static_cast<double>(NumberToInt32(*handle_)))) return true;
   2402     return false;
   2403   }
   2404 
   2405   virtual bool EmitAtUses() { return !representation().IsDouble(); }
   2406   virtual HValue* Canonicalize();
   2407   virtual void PrintDataTo(StringStream* stream);
   2408   virtual HType CalculateInferredType();
   2409   bool IsInteger() const { return handle_->IsSmi(); }
   2410   HConstant* CopyToRepresentation(Representation r) const;
   2411   HConstant* CopyToTruncatedInt32() const;
   2412   bool HasInteger32Value() const { return has_int32_value_; }
   2413   int32_t Integer32Value() const {
   2414     ASSERT(HasInteger32Value());
   2415     return int32_value_;
   2416   }
   2417   bool HasDoubleValue() const { return has_double_value_; }
   2418   double DoubleValue() const {
   2419     ASSERT(HasDoubleValue());
   2420     return double_value_;
   2421   }
   2422   bool HasNumberValue() const { return has_int32_value_ || has_double_value_; }
   2423   int32_t NumberValueAsInteger32() const {
   2424     ASSERT(HasNumberValue());
   2425     if (has_int32_value_) return int32_value_;
   2426     return DoubleToInt32(double_value_);
   2427   }
   2428   bool HasStringValue() const { return handle_->IsString(); }
   2429 
   2430   bool ToBoolean() const;
   2431 
   2432   virtual intptr_t Hashcode() {
   2433     ASSERT(!HEAP->allow_allocation(false));
   2434     intptr_t hash = reinterpret_cast<intptr_t>(*handle());
   2435     // Prevent smis from having fewer hash values when truncated to
   2436     // the least significant bits.
   2437     const int kShiftSize = kSmiShiftSize + kSmiTagSize;
   2438     STATIC_ASSERT(kShiftSize != 0);
   2439     return hash ^ (hash >> kShiftSize);
   2440   }
   2441 
   2442 #ifdef DEBUG
   2443   virtual void Verify() { }
   2444 #endif
   2445 
   2446   DECLARE_CONCRETE_INSTRUCTION(Constant)
   2447 
   2448  protected:
   2449   virtual Range* InferRange(Zone* zone);
   2450 
   2451   virtual bool DataEquals(HValue* other) {
   2452     HConstant* other_constant = HConstant::cast(other);
   2453     return handle().is_identical_to(other_constant->handle());
   2454   }
   2455 
   2456  private:
   2457   Handle<Object> handle_;
   2458 
   2459   // The following two values represent the int32 and the double value of the
   2460   // given constant if there is a lossless conversion between the constant
   2461   // and the specific representation.
   2462   bool has_int32_value_ : 1;
   2463   bool has_double_value_ : 1;
   2464   int32_t int32_value_;
   2465   double double_value_;
   2466 };
   2467 
   2468 
   2469 class HBinaryOperation: public HTemplateInstruction<3> {
   2470  public:
   2471   HBinaryOperation(HValue* context, HValue* left, HValue* right) {
   2472     ASSERT(left != NULL && right != NULL);
   2473     SetOperandAt(0, context);
   2474     SetOperandAt(1, left);
   2475     SetOperandAt(2, right);
   2476   }
   2477 
   2478   HValue* context() { return OperandAt(0); }
   2479   HValue* left() { return OperandAt(1); }
   2480   HValue* right() { return OperandAt(2); }
   2481 
   2482   // TODO(kasperl): Move these helpers to the IA-32 Lithium
   2483   // instruction sequence builder.
   2484   HValue* LeastConstantOperand() {
   2485     if (IsCommutative() && left()->IsConstant()) return right();
   2486     return left();
   2487   }
   2488   HValue* MostConstantOperand() {
   2489     if (IsCommutative() && left()->IsConstant()) return left();
   2490     return right();
   2491   }
   2492 
   2493   virtual bool IsCommutative() const { return false; }
   2494 
   2495   virtual void PrintDataTo(StringStream* stream);
   2496 };
   2497 
   2498 
   2499 class HWrapReceiver: public HTemplateInstruction<2> {
   2500  public:
   2501   HWrapReceiver(HValue* receiver, HValue* function) {
   2502     set_representation(Representation::Tagged());
   2503     SetOperandAt(0, receiver);
   2504     SetOperandAt(1, function);
   2505   }
   2506 
   2507   virtual Representation RequiredInputRepresentation(int index) {
   2508     return Representation::Tagged();
   2509   }
   2510 
   2511   HValue* receiver() { return OperandAt(0); }
   2512   HValue* function() { return OperandAt(1); }
   2513 
   2514   virtual HValue* Canonicalize();
   2515 
   2516   DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
   2517 };
   2518 
   2519 
   2520 class HApplyArguments: public HTemplateInstruction<4> {
   2521  public:
   2522   HApplyArguments(HValue* function,
   2523                   HValue* receiver,
   2524                   HValue* length,
   2525                   HValue* elements) {
   2526     set_representation(Representation::Tagged());
   2527     SetOperandAt(0, function);
   2528     SetOperandAt(1, receiver);
   2529     SetOperandAt(2, length);
   2530     SetOperandAt(3, elements);
   2531     SetAllSideEffects();
   2532   }
   2533 
   2534   virtual Representation RequiredInputRepresentation(int index) {
   2535     // The length is untagged, all other inputs are tagged.
   2536     return (index == 2)
   2537         ? Representation::Integer32()
   2538         : Representation::Tagged();
   2539   }
   2540 
   2541   HValue* function() { return OperandAt(0); }
   2542   HValue* receiver() { return OperandAt(1); }
   2543   HValue* length() { return OperandAt(2); }
   2544   HValue* elements() { return OperandAt(3); }
   2545 
   2546   DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
   2547 };
   2548 
   2549 
   2550 class HArgumentsElements: public HTemplateInstruction<0> {
   2551  public:
   2552   HArgumentsElements() {
   2553     // The value produced by this instruction is a pointer into the stack
   2554     // that looks as if it was a smi because of alignment.
   2555     set_representation(Representation::Tagged());
   2556     SetFlag(kUseGVN);
   2557   }
   2558 
   2559   DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
   2560 
   2561   virtual Representation RequiredInputRepresentation(int index) {
   2562     return Representation::None();
   2563   }
   2564 
   2565  protected:
   2566   virtual bool DataEquals(HValue* other) { return true; }
   2567 };
   2568 
   2569 
   2570 class HArgumentsLength: public HUnaryOperation {
   2571  public:
   2572   explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
   2573     set_representation(Representation::Integer32());
   2574     SetFlag(kUseGVN);
   2575   }
   2576 
   2577   virtual Representation RequiredInputRepresentation(int index) {
   2578     return Representation::Tagged();
   2579   }
   2580 
   2581   DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
   2582 
   2583  protected:
   2584   virtual bool DataEquals(HValue* other) { return true; }
   2585 };
   2586 
   2587 
   2588 class HAccessArgumentsAt: public HTemplateInstruction<3> {
   2589  public:
   2590   HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
   2591     set_representation(Representation::Tagged());
   2592     SetFlag(kUseGVN);
   2593     SetOperandAt(0, arguments);
   2594     SetOperandAt(1, length);
   2595     SetOperandAt(2, index);
   2596   }
   2597 
   2598   virtual void PrintDataTo(StringStream* stream);
   2599 
   2600   virtual Representation RequiredInputRepresentation(int index) {
   2601     // The arguments elements is considered tagged.
   2602     return index == 0
   2603         ? Representation::Tagged()
   2604         : Representation::Integer32();
   2605   }
   2606 
   2607   HValue* arguments() { return OperandAt(0); }
   2608   HValue* length() { return OperandAt(1); }
   2609   HValue* index() { return OperandAt(2); }
   2610 
   2611   DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
   2612 
   2613   virtual bool DataEquals(HValue* other) { return true; }
   2614 };
   2615 
   2616 
   2617 class HBoundsCheck: public HTemplateInstruction<2> {
   2618  public:
   2619   HBoundsCheck(HValue* index, HValue* length) {
   2620     SetOperandAt(0, index);
   2621     SetOperandAt(1, length);
   2622     set_representation(Representation::Integer32());
   2623     SetFlag(kUseGVN);
   2624   }
   2625 
   2626   virtual Representation RequiredInputRepresentation(int index) {
   2627     return Representation::Integer32();
   2628   }
   2629 
   2630   virtual void PrintDataTo(StringStream* stream);
   2631 
   2632   HValue* index() { return OperandAt(0); }
   2633   HValue* length() { return OperandAt(1); }
   2634 
   2635   DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
   2636 
   2637  protected:
   2638   virtual bool DataEquals(HValue* other) { return true; }
   2639 };
   2640 
   2641 
   2642 class HBitwiseBinaryOperation: public HBinaryOperation {
   2643  public:
   2644   HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right)
   2645       : HBinaryOperation(context, left, right) {
   2646     set_representation(Representation::Tagged());
   2647     SetFlag(kFlexibleRepresentation);
   2648     SetAllSideEffects();
   2649   }
   2650 
   2651   virtual Representation RequiredInputRepresentation(int index) {
   2652     return index == 0
   2653         ? Representation::Tagged()
   2654         : representation();
   2655   }
   2656 
   2657   virtual void RepresentationChanged(Representation to) {
   2658     if (!to.IsTagged()) {
   2659       ASSERT(to.IsInteger32());
   2660       ClearAllSideEffects();
   2661       SetFlag(kTruncatingToInt32);
   2662       SetFlag(kUseGVN);
   2663     }
   2664   }
   2665 
   2666   virtual HType CalculateInferredType();
   2667 
   2668   DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
   2669 };
   2670 
   2671 
   2672 class HArithmeticBinaryOperation: public HBinaryOperation {
   2673  public:
   2674   HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right)
   2675       : HBinaryOperation(context, left, right) {
   2676     set_representation(Representation::Tagged());
   2677     SetFlag(kFlexibleRepresentation);
   2678     SetAllSideEffects();
   2679   }
   2680 
   2681   virtual void RepresentationChanged(Representation to) {
   2682     if (!to.IsTagged()) {
   2683       ClearAllSideEffects();
   2684       SetFlag(kUseGVN);
   2685     }
   2686   }
   2687 
   2688   virtual HType CalculateInferredType();
   2689   virtual Representation RequiredInputRepresentation(int index) {
   2690     return index == 0
   2691         ? Representation::Tagged()
   2692         : representation();
   2693   }
   2694 
   2695   virtual Representation InferredRepresentation() {
   2696     if (left()->representation().Equals(right()->representation())) {
   2697       return left()->representation();
   2698     }
   2699     return HValue::InferredRepresentation();
   2700   }
   2701 };
   2702 
   2703 
   2704 class HCompareGeneric: public HBinaryOperation {
   2705  public:
   2706   HCompareGeneric(HValue* context,
   2707                   HValue* left,
   2708                   HValue* right,
   2709                   Token::Value token)
   2710       : HBinaryOperation(context, left, right), token_(token) {
   2711     ASSERT(Token::IsCompareOp(token));
   2712     set_representation(Representation::Tagged());
   2713     SetAllSideEffects();
   2714   }
   2715 
   2716   virtual Representation RequiredInputRepresentation(int index) {
   2717     return Representation::Tagged();
   2718   }
   2719 
   2720   Representation GetInputRepresentation() const {
   2721     return Representation::Tagged();
   2722   }
   2723 
   2724   Token::Value token() const { return token_; }
   2725   virtual void PrintDataTo(StringStream* stream);
   2726 
   2727   virtual HType CalculateInferredType();
   2728 
   2729   DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
   2730 
   2731  private:
   2732   Token::Value token_;
   2733 };
   2734 
   2735 
   2736 class HCompareIDAndBranch: public HTemplateControlInstruction<2, 2> {
   2737  public:
   2738   HCompareIDAndBranch(HValue* left, HValue* right, Token::Value token)
   2739       : token_(token) {
   2740     ASSERT(Token::IsCompareOp(token));
   2741     SetOperandAt(0, left);
   2742     SetOperandAt(1, right);
   2743   }
   2744 
   2745   HValue* left() { return OperandAt(0); }
   2746   HValue* right() { return OperandAt(1); }
   2747   Token::Value token() const { return token_; }
   2748 
   2749   void SetInputRepresentation(Representation r);
   2750   Representation GetInputRepresentation() const {
   2751     return input_representation_;
   2752   }
   2753 
   2754   virtual Representation RequiredInputRepresentation(int index) {
   2755     return input_representation_;
   2756   }
   2757   virtual void PrintDataTo(StringStream* stream);
   2758 
   2759   DECLARE_CONCRETE_INSTRUCTION(CompareIDAndBranch)
   2760 
   2761  private:
   2762   Representation input_representation_;
   2763   Token::Value token_;
   2764 };
   2765 
   2766 
   2767 class HCompareObjectEqAndBranch: public HTemplateControlInstruction<2, 2> {
   2768  public:
   2769   HCompareObjectEqAndBranch(HValue* left, HValue* right) {
   2770     SetOperandAt(0, left);
   2771     SetOperandAt(1, right);
   2772   }
   2773 
   2774   HValue* left() { return OperandAt(0); }
   2775   HValue* right() { return OperandAt(1); }
   2776 
   2777   virtual void PrintDataTo(StringStream* stream);
   2778 
   2779   virtual Representation RequiredInputRepresentation(int index) {
   2780     return Representation::Tagged();
   2781   }
   2782 
   2783   DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
   2784 };
   2785 
   2786 
   2787 class HCompareConstantEqAndBranch: public HUnaryControlInstruction {
   2788  public:
   2789   HCompareConstantEqAndBranch(HValue* left, int right, Token::Value op)
   2790       : HUnaryControlInstruction(left, NULL, NULL), op_(op), right_(right) {
   2791     ASSERT(op == Token::EQ_STRICT);
   2792   }
   2793 
   2794   Token::Value op() const { return op_; }
   2795   HValue* left() { return value(); }
   2796   int right() const { return right_; }
   2797 
   2798   virtual Representation RequiredInputRepresentation(int index) {
   2799     return Representation::Integer32();
   2800   }
   2801 
   2802   DECLARE_CONCRETE_INSTRUCTION(CompareConstantEqAndBranch);
   2803 
   2804  private:
   2805   const Token::Value op_;
   2806   const int right_;
   2807 };
   2808 
   2809 
   2810 class HIsNilAndBranch: public HUnaryControlInstruction {
   2811  public:
   2812   HIsNilAndBranch(HValue* value, EqualityKind kind, NilValue nil)
   2813       : HUnaryControlInstruction(value, NULL, NULL), kind_(kind), nil_(nil) { }
   2814 
   2815   EqualityKind kind() const { return kind_; }
   2816   NilValue nil() const { return nil_; }
   2817 
   2818   virtual void PrintDataTo(StringStream* stream);
   2819 
   2820   virtual Representation RequiredInputRepresentation(int index) {
   2821     return Representation::Tagged();
   2822   }
   2823 
   2824   DECLARE_CONCRETE_INSTRUCTION(IsNilAndBranch)
   2825 
   2826  private:
   2827   EqualityKind kind_;
   2828   NilValue nil_;
   2829 };
   2830 
   2831 
   2832 class HIsObjectAndBranch: public HUnaryControlInstruction {
   2833  public:
   2834   explicit HIsObjectAndBranch(HValue* value)
   2835     : HUnaryControlInstruction(value, NULL, NULL) { }
   2836 
   2837   virtual Representation RequiredInputRepresentation(int index) {
   2838     return Representation::Tagged();
   2839   }
   2840 
   2841   DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch)
   2842 };
   2843 
   2844 class HIsStringAndBranch: public HUnaryControlInstruction {
   2845  public:
   2846   explicit HIsStringAndBranch(HValue* value)
   2847     : HUnaryControlInstruction(value, NULL, NULL) { }
   2848 
   2849   virtual Representation RequiredInputRepresentation(int index) {
   2850     return Representation::Tagged();
   2851   }
   2852 
   2853   DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
   2854 };
   2855 
   2856 
   2857 class HIsSmiAndBranch: public HUnaryControlInstruction {
   2858  public:
   2859   explicit HIsSmiAndBranch(HValue* value)
   2860       : HUnaryControlInstruction(value, NULL, NULL) { }
   2861 
   2862   DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
   2863 
   2864   virtual Representation RequiredInputRepresentation(int index) {
   2865     return Representation::Tagged();
   2866   }
   2867 
   2868  protected:
   2869   virtual bool DataEquals(HValue* other) { return true; }
   2870 };
   2871 
   2872 
   2873 class HIsUndetectableAndBranch: public HUnaryControlInstruction {
   2874  public:
   2875   explicit HIsUndetectableAndBranch(HValue* value)
   2876       : HUnaryControlInstruction(value, NULL, NULL) { }
   2877 
   2878   virtual Representation RequiredInputRepresentation(int index) {
   2879     return Representation::Tagged();
   2880   }
   2881 
   2882   DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
   2883 };
   2884 
   2885 
   2886 class HStringCompareAndBranch: public HTemplateControlInstruction<2, 3> {
   2887  public:
   2888   HStringCompareAndBranch(HValue* context,
   2889                            HValue* left,
   2890                            HValue* right,
   2891                            Token::Value token)
   2892       : token_(token) {
   2893     ASSERT(Token::IsCompareOp(token));
   2894     SetOperandAt(0, context);
   2895     SetOperandAt(1, left);
   2896     SetOperandAt(2, right);
   2897     set_representation(Representation::Tagged());
   2898   }
   2899 
   2900   HValue* context() { return OperandAt(0); }
   2901   HValue* left() { return OperandAt(1); }
   2902   HValue* right() { return OperandAt(2); }
   2903   Token::Value token() const { return token_; }
   2904 
   2905   virtual void PrintDataTo(StringStream* stream);
   2906 
   2907   virtual Representation RequiredInputRepresentation(int index) {
   2908     return Representation::Tagged();
   2909   }
   2910 
   2911   Representation GetInputRepresentation() const {
   2912     return Representation::Tagged();
   2913   }
   2914 
   2915   DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
   2916 
   2917  private:
   2918   Token::Value token_;
   2919 };
   2920 
   2921 
   2922 class HIsConstructCallAndBranch: public HTemplateControlInstruction<2, 0> {
   2923  public:
   2924   virtual Representation RequiredInputRepresentation(int index) {
   2925     return Representation::None();
   2926   }
   2927 
   2928   DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch)
   2929 };
   2930 
   2931 
   2932 class HHasInstanceTypeAndBranch: public HUnaryControlInstruction {
   2933  public:
   2934   HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
   2935       : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
   2936   HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
   2937       : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
   2938     ASSERT(to == LAST_TYPE);  // Others not implemented yet in backend.
   2939   }
   2940 
   2941   InstanceType from() { return from_; }
   2942   InstanceType to() { return to_; }
   2943 
   2944   virtual void PrintDataTo(StringStream* stream);
   2945 
   2946   virtual Representation RequiredInputRepresentation(int index) {
   2947     return Representation::Tagged();
   2948   }
   2949 
   2950   DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
   2951 
   2952  private:
   2953   InstanceType from_;
   2954   InstanceType to_;  // Inclusive range, not all combinations work.
   2955 };
   2956 
   2957 
   2958 class HHasCachedArrayIndexAndBranch: public HUnaryControlInstruction {
   2959  public:
   2960   explicit HHasCachedArrayIndexAndBranch(HValue* value)
   2961       : HUnaryControlInstruction(value, NULL, NULL) { }
   2962 
   2963   virtual Representation RequiredInputRepresentation(int index) {
   2964     return Representation::Tagged();
   2965   }
   2966 
   2967   DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
   2968 };
   2969 
   2970 
   2971 class HGetCachedArrayIndex: public HUnaryOperation {
   2972  public:
   2973   explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
   2974     set_representation(Representation::Tagged());
   2975     SetFlag(kUseGVN);
   2976   }
   2977 
   2978   virtual Representation RequiredInputRepresentation(int index) {
   2979     return Representation::Tagged();
   2980   }
   2981 
   2982   DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
   2983 
   2984  protected:
   2985   virtual bool DataEquals(HValue* other) { return true; }
   2986 };
   2987 
   2988 
   2989 class HClassOfTestAndBranch: public HUnaryControlInstruction {
   2990  public:
   2991   HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
   2992       : HUnaryControlInstruction(value, NULL, NULL),
   2993         class_name_(class_name) { }
   2994 
   2995   DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
   2996 
   2997   virtual Representation RequiredInputRepresentation(int index) {
   2998     return Representation::Tagged();
   2999   }
   3000 
   3001   virtual void PrintDataTo(StringStream* stream);
   3002 
   3003   Handle<String> class_name() const { return class_name_; }
   3004 
   3005  private:
   3006   Handle<String> class_name_;
   3007 };
   3008 
   3009 
   3010 class HTypeofIsAndBranch: public HUnaryControlInstruction {
   3011  public:
   3012   HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
   3013       : HUnaryControlInstruction(value, NULL, NULL),
   3014         type_literal_(type_literal) { }
   3015 
   3016   Handle<String> type_literal() { return type_literal_; }
   3017   virtual void PrintDataTo(StringStream* stream);
   3018 
   3019   DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
   3020 
   3021   virtual Representation RequiredInputRepresentation(int index) {
   3022     return Representation::Tagged();
   3023   }
   3024 
   3025  private:
   3026   Handle<String> type_literal_;
   3027 };
   3028 
   3029 
   3030 class HInstanceOf: public HBinaryOperation {
   3031  public:
   3032   HInstanceOf(HValue* context, HValue* left, HValue* right)
   3033       : HBinaryOperation(context, left, right) {
   3034     set_representation(Representation::Tagged());
   3035     SetAllSideEffects();
   3036   }
   3037 
   3038   virtual Representation RequiredInputRepresentation(int index) {
   3039     return Representation::Tagged();
   3040   }
   3041 
   3042   virtual HType CalculateInferredType();
   3043 
   3044   virtual void PrintDataTo(StringStream* stream);
   3045 
   3046   DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
   3047 };
   3048 
   3049 
   3050 class HInstanceOfKnownGlobal: public HTemplateInstruction<2> {
   3051  public:
   3052   HInstanceOfKnownGlobal(HValue* context,
   3053                          HValue* left,
   3054                          Handle<JSFunction> right)
   3055       : function_(right) {
   3056     SetOperandAt(0, context);
   3057     SetOperandAt(1, left);
   3058     set_representation(Representation::Tagged());
   3059     SetAllSideEffects();
   3060   }
   3061 
   3062   HValue* context() { return OperandAt(0); }
   3063   HValue* left() { return OperandAt(1); }
   3064   Handle<JSFunction> function() { return function_; }
   3065 
   3066   virtual Representation RequiredInputRepresentation(int index) {
   3067     return Representation::Tagged();
   3068   }
   3069 
   3070   virtual HType CalculateInferredType();
   3071 
   3072   DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal)
   3073 
   3074  private:
   3075   Handle<JSFunction> function_;
   3076 };
   3077 
   3078 
   3079 class HPower: public HTemplateInstruction<2> {
   3080  public:
   3081   HPower(HValue* left, HValue* right) {
   3082     SetOperandAt(0, left);
   3083     SetOperandAt(1, right);
   3084     set_representation(Representation::Double());
   3085     SetFlag(kUseGVN);
   3086   }
   3087 
   3088   HValue* left() { return OperandAt(0); }
   3089   HValue* right() { return OperandAt(1); }
   3090 
   3091   virtual Representation RequiredInputRepresentation(int index) {
   3092     return index == 0
   3093       ? Representation::Double()
   3094       : Representation::None();
   3095   }
   3096 
   3097   DECLARE_CONCRETE_INSTRUCTION(Power)
   3098 
   3099  protected:
   3100   virtual bool DataEquals(HValue* other) { return true; }
   3101 };
   3102 
   3103 
   3104 class HRandom: public HTemplateInstruction<1> {
   3105  public:
   3106   explicit HRandom(HValue* global_object) {
   3107     SetOperandAt(0, global_object);
   3108     set_representation(Representation::Double());
   3109   }
   3110 
   3111   HValue* global_object() { return OperandAt(0); }
   3112 
   3113   virtual Representation RequiredInputRepresentation(int index) {
   3114     return Representation::Tagged();
   3115   }
   3116 
   3117   DECLARE_CONCRETE_INSTRUCTION(Random)
   3118 };
   3119 
   3120 
   3121 class HAdd: public HArithmeticBinaryOperation {
   3122  public:
   3123   HAdd(HValue* context, HValue* left, HValue* right)
   3124       : HArithmeticBinaryOperation(context, left, right) {
   3125     SetFlag(kCanOverflow);
   3126   }
   3127 
   3128   // Add is only commutative if two integer values are added and not if two
   3129   // tagged values are added (because it might be a String concatenation).
   3130   virtual bool IsCommutative() const {
   3131     return !representation().IsTagged();
   3132   }
   3133 
   3134   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
   3135 
   3136   static HInstruction* NewHAdd(Zone* zone,
   3137                                HValue* context,
   3138                                HValue* left,
   3139                                HValue* right);
   3140 
   3141   virtual HType CalculateInferredType();
   3142 
   3143   virtual HValue* Canonicalize();
   3144 
   3145   DECLARE_CONCRETE_INSTRUCTION(Add)
   3146 
   3147  protected:
   3148   virtual bool DataEquals(HValue* other) { return true; }
   3149 
   3150   virtual Range* InferRange(Zone* zone);
   3151 };
   3152 
   3153 
   3154 class HSub: public HArithmeticBinaryOperation {
   3155  public:
   3156   HSub(HValue* context, HValue* left, HValue* right)
   3157       : HArithmeticBinaryOperation(context, left, right) {
   3158     SetFlag(kCanOverflow);
   3159   }
   3160 
   3161   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
   3162 
   3163   virtual HValue* Canonicalize();
   3164 
   3165   static HInstruction* NewHSub(Zone* zone,
   3166                               HValue* context,
   3167                               HValue* left,
   3168                               HValue* right);
   3169 
   3170   DECLARE_CONCRETE_INSTRUCTION(Sub)
   3171 
   3172  protected:
   3173   virtual bool DataEquals(HValue* other) { return true; }
   3174 
   3175   virtual Range* InferRange(Zone* zone);
   3176 };
   3177 
   3178 
   3179 class HMul: public HArithmeticBinaryOperation {
   3180  public:
   3181   HMul(HValue* context, HValue* left, HValue* right)
   3182       : HArithmeticBinaryOperation(context, left, right) {
   3183     SetFlag(kCanOverflow);
   3184   }
   3185 
   3186   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
   3187 
   3188   // Only commutative if it is certain that not two objects are multiplicated.
   3189   virtual bool IsCommutative() const {
   3190     return !representation().IsTagged();
   3191   }
   3192 
   3193   static HInstruction* NewHMul(Zone* zone,
   3194                                HValue* context,
   3195                                HValue* left,
   3196                                HValue* right);
   3197 
   3198   DECLARE_CONCRETE_INSTRUCTION(Mul)
   3199 
   3200  protected:
   3201   virtual bool DataEquals(HValue* other) { return true; }
   3202 
   3203   virtual Range* InferRange(Zone* zone);
   3204 };
   3205 
   3206 
   3207 class HMod: public HArithmeticBinaryOperation {
   3208  public:
   3209   HMod(HValue* context, HValue* left, HValue* right)
   3210       : HArithmeticBinaryOperation(context, left, right) {
   3211     SetFlag(kCanBeDivByZero);
   3212   }
   3213 
   3214   bool HasPowerOf2Divisor() {
   3215     if (right()->IsConstant() &&
   3216         HConstant::cast(right())->HasInteger32Value()) {
   3217       int32_t value = HConstant::cast(right())->Integer32Value();
   3218       return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
   3219     }
   3220 
   3221     return false;
   3222   }
   3223 
   3224   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
   3225 
   3226   static HInstruction* NewHMod(Zone* zone,
   3227                                HValue* context,
   3228                                HValue* left,
   3229                                HValue* right);
   3230 
   3231   DECLARE_CONCRETE_INSTRUCTION(Mod)
   3232 
   3233  protected:
   3234   virtual bool DataEquals(HValue* other) { return true; }
   3235 
   3236   virtual Range* InferRange(Zone* zone);
   3237 };
   3238 
   3239 
   3240 class HDiv: public HArithmeticBinaryOperation {
   3241  public:
   3242   HDiv(HValue* context, HValue* left, HValue* right)
   3243       : HArithmeticBinaryOperation(context, left, right) {
   3244     SetFlag(kCanBeDivByZero);
   3245     SetFlag(kCanOverflow);
   3246   }
   3247 
   3248   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
   3249 
   3250   static HInstruction* NewHDiv(Zone* zone,
   3251                                HValue* context,
   3252                                HValue* left,
   3253                                HValue* right);
   3254 
   3255   DECLARE_CONCRETE_INSTRUCTION(Div)
   3256 
   3257  protected:
   3258   virtual bool DataEquals(HValue* other) { return true; }
   3259 
   3260   virtual Range* InferRange(Zone* zone);
   3261 };
   3262 
   3263 
   3264 class HBitwise: public HBitwiseBinaryOperation {
   3265  public:
   3266   HBitwise(Token::Value op, HValue* context, HValue* left, HValue* right)
   3267       : HBitwiseBinaryOperation(context, left, right), op_(op) {
   3268         ASSERT(op == Token::BIT_AND ||
   3269                op == Token::BIT_OR ||
   3270                op == Token::BIT_XOR);
   3271       }
   3272 
   3273   Token::Value op() const { return op_; }
   3274 
   3275   virtual bool IsCommutative() const { return true; }
   3276 
   3277   virtual HValue* Canonicalize();
   3278 
   3279   static HInstruction* NewHBitwise(Zone* zone,
   3280                                    Token::Value op,
   3281                                    HValue* context,
   3282                                    HValue* left,
   3283                                    HValue* right);
   3284 
   3285   DECLARE_CONCRETE_INSTRUCTION(Bitwise)
   3286 
   3287  protected:
   3288   virtual bool DataEquals(HValue* other) {
   3289     return op() == HBitwise::cast(other)->op();
   3290   }
   3291 
   3292   virtual Range* InferRange(Zone* zone);
   3293 
   3294  private:
   3295   Token::Value op_;
   3296 };
   3297 
   3298 
   3299 class HShl: public HBitwiseBinaryOperation {
   3300  public:
   3301   HShl(HValue* context, HValue* left, HValue* right)
   3302       : HBitwiseBinaryOperation(context, left, right) { }
   3303 
   3304   virtual Range* InferRange(Zone* zone);
   3305 
   3306   static HInstruction* NewHShl(Zone* zone,
   3307                                HValue* context,
   3308                                HValue* left,
   3309                                HValue* right);
   3310 
   3311   DECLARE_CONCRETE_INSTRUCTION(Shl)
   3312 
   3313  protected:
   3314   virtual bool DataEquals(HValue* other) { return true; }
   3315 };
   3316 
   3317 
   3318 class HShr: public HBitwiseBinaryOperation {
   3319  public:
   3320   HShr(HValue* context, HValue* left, HValue* right)
   3321       : HBitwiseBinaryOperation(context, left, right) { }
   3322 
   3323   virtual Range* InferRange(Zone* zone);
   3324 
   3325   static HInstruction* NewHShr(Zone* zone,
   3326                                HValue* context,
   3327                                HValue* left,
   3328                                HValue* right);
   3329 
   3330   DECLARE_CONCRETE_INSTRUCTION(Shr)
   3331 
   3332  protected:
   3333   virtual bool DataEquals(HValue* other) { return true; }
   3334 };
   3335 
   3336 
   3337 class HSar: public HBitwiseBinaryOperation {
   3338  public:
   3339   HSar(HValue* context, HValue* left, HValue* right)
   3340       : HBitwiseBinaryOperation(context, left, right) { }
   3341 
   3342   virtual Range* InferRange(Zone* zone);
   3343 
   3344   static HInstruction* NewHSar(Zone* zone,
   3345                                HValue* context,
   3346                                HValue* left,
   3347                                HValue* right);
   3348 
   3349   DECLARE_CONCRETE_INSTRUCTION(Sar)
   3350 
   3351  protected:
   3352   virtual bool DataEquals(HValue* other) { return true; }
   3353 };
   3354 
   3355 
   3356 class HOsrEntry: public HTemplateInstruction<0> {
   3357  public:
   3358   explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
   3359     SetGVNFlag(kChangesOsrEntries);
   3360   }
   3361 
   3362   int ast_id() const { return ast_id_; }
   3363 
   3364   virtual Representation RequiredInputRepresentation(int index) {
   3365     return Representation::None();
   3366   }
   3367 
   3368   DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
   3369 
   3370  private:
   3371   int ast_id_;
   3372 };
   3373 
   3374 
   3375 class HParameter: public HTemplateInstruction<0> {
   3376  public:
   3377   explicit HParameter(unsigned index) : index_(index) {
   3378     set_representation(Representation::Tagged());
   3379   }
   3380 
   3381   unsigned index() const { return index_; }
   3382 
   3383   virtual void PrintDataTo(StringStream* stream);
   3384 
   3385   virtual Representation RequiredInputRepresentation(int index) {
   3386     return Representation::None();
   3387   }
   3388 
   3389   DECLARE_CONCRETE_INSTRUCTION(Parameter)
   3390 
   3391  private:
   3392   unsigned index_;
   3393 };
   3394 
   3395 
   3396 class HCallStub: public HUnaryCall {
   3397  public:
   3398   HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
   3399       : HUnaryCall(context, argument_count),
   3400         major_key_(major_key),
   3401         transcendental_type_(TranscendentalCache::kNumberOfCaches) {
   3402   }
   3403 
   3404   CodeStub::Major major_key() { return major_key_; }
   3405 
   3406   HValue* context() { return value(); }
   3407 
   3408   void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
   3409     transcendental_type_ = transcendental_type;
   3410   }
   3411   TranscendentalCache::Type transcendental_type() {
   3412     return transcendental_type_;
   3413   }
   3414 
   3415   virtual void PrintDataTo(StringStream* stream);
   3416 
   3417   virtual Representation RequiredInputRepresentation(int index) {
   3418     return Representation::Tagged();
   3419   }
   3420 
   3421   DECLARE_CONCRETE_INSTRUCTION(CallStub)
   3422 
   3423  private:
   3424   CodeStub::Major major_key_;
   3425   TranscendentalCache::Type transcendental_type_;
   3426 };
   3427 
   3428 
   3429 class HUnknownOSRValue: public HTemplateInstruction<0> {
   3430  public:
   3431   HUnknownOSRValue()
   3432       : incoming_value_(NULL) {
   3433     set_representation(Representation::Tagged());
   3434   }
   3435 
   3436   virtual Representation RequiredInputRepresentation(int index) {
   3437     return Representation::None();
   3438   }
   3439 
   3440   void set_incoming_value(HPhi* value) {
   3441     incoming_value_ = value;
   3442   }
   3443 
   3444   HPhi* incoming_value() {
   3445     return incoming_value_;
   3446   }
   3447 
   3448   DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
   3449 
   3450  private:
   3451   HPhi* incoming_value_;
   3452 };
   3453 
   3454 
   3455 class HLoadGlobalCell: public HTemplateInstruction<0> {
   3456  public:
   3457   HLoadGlobalCell(Handle<JSGlobalPropertyCell> cell, PropertyDetails details)
   3458       : cell_(cell), details_(details) {
   3459     set_representation(Representation::Tagged());
   3460     SetFlag(kUseGVN);
   3461     SetGVNFlag(kDependsOnGlobalVars);
   3462   }
   3463 
   3464   Handle<JSGlobalPropertyCell>  cell() const { return cell_; }
   3465   bool RequiresHoleCheck();
   3466 
   3467   virtual void PrintDataTo(StringStream* stream);
   3468 
   3469   virtual intptr_t Hashcode() {
   3470     ASSERT(!HEAP->allow_allocation(false));
   3471     return reinterpret_cast<intptr_t>(*cell_);
   3472   }
   3473 
   3474   virtual Representation RequiredInputRepresentation(int index) {
   3475     return Representation::None();
   3476   }
   3477 
   3478   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell)
   3479 
   3480  protected:
   3481   virtual bool DataEquals(HValue* other) {
   3482     HLoadGlobalCell* b = HLoadGlobalCell::cast(other);
   3483     return cell_.is_identical_to(b->cell());
   3484   }
   3485 
   3486  private:
   3487   Handle<JSGlobalPropertyCell> cell_;
   3488   PropertyDetails details_;
   3489 };
   3490 
   3491 
   3492 class HLoadGlobalGeneric: public HTemplateInstruction<2> {
   3493  public:
   3494   HLoadGlobalGeneric(HValue* context,
   3495                      HValue* global_object,
   3496                      Handle<Object> name,
   3497                      bool for_typeof)
   3498       : name_(name),
   3499         for_typeof_(for_typeof) {
   3500     SetOperandAt(0, context);
   3501     SetOperandAt(1, global_object);
   3502     set_representation(Representation::Tagged());
   3503     SetAllSideEffects();
   3504   }
   3505 
   3506   HValue* context() { return OperandAt(0); }
   3507   HValue* global_object() { return OperandAt(1); }
   3508   Handle<Object> name() const { return name_; }
   3509   bool for_typeof() const { return for_typeof_; }
   3510 
   3511   virtual void PrintDataTo(StringStream* stream);
   3512 
   3513   virtual Representation RequiredInputRepresentation(int index) {
   3514     return Representation::Tagged();
   3515   }
   3516 
   3517   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
   3518 
   3519  private:
   3520   Handle<Object> name_;
   3521   bool for_typeof_;
   3522 };
   3523 
   3524 
   3525 inline bool StoringValueNeedsWriteBarrier(HValue* value) {
   3526   return !value->type().IsBoolean()
   3527       && !value->type().IsSmi()
   3528       && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
   3529 }
   3530 
   3531 
   3532 class HStoreGlobalCell: public HUnaryOperation {
   3533  public:
   3534   HStoreGlobalCell(HValue* value,
   3535                    Handle<JSGlobalPropertyCell> cell,
   3536                    PropertyDetails details)
   3537       : HUnaryOperation(value),
   3538         cell_(cell),
   3539         details_(details) {
   3540     SetGVNFlag(kChangesGlobalVars);
   3541   }
   3542 
   3543   Handle<JSGlobalPropertyCell> cell() const { return cell_; }
   3544   bool RequiresHoleCheck() {
   3545     return !details_.IsDontDelete() || details_.IsReadOnly();
   3546   }
   3547   bool NeedsWriteBarrier() {
   3548     return StoringValueNeedsWriteBarrier(value());
   3549   }
   3550 
   3551   virtual Representation RequiredInputRepresentation(int index) {
   3552     return Representation::Tagged();
   3553   }
   3554   virtual void PrintDataTo(StringStream* stream);
   3555 
   3556   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell)
   3557 
   3558  private:
   3559   Handle<JSGlobalPropertyCell> cell_;
   3560   PropertyDetails details_;
   3561 };
   3562 
   3563 
   3564 class HStoreGlobalGeneric: public HTemplateInstruction<3> {
   3565  public:
   3566   HStoreGlobalGeneric(HValue* context,
   3567                       HValue* global_object,
   3568                       Handle<Object> name,
   3569                       HValue* value,
   3570                       StrictModeFlag strict_mode_flag)
   3571       : name_(name),
   3572         strict_mode_flag_(strict_mode_flag) {
   3573     SetOperandAt(0, context);
   3574     SetOperandAt(1, global_object);
   3575     SetOperandAt(2, value);
   3576     set_representation(Representation::Tagged());
   3577     SetAllSideEffects();
   3578   }
   3579 
   3580   HValue* context() { return OperandAt(0); }
   3581   HValue* global_object() { return OperandAt(1); }
   3582   Handle<Object> name() const { return name_; }
   3583   HValue* value() { return OperandAt(2); }
   3584   StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
   3585 
   3586   virtual void PrintDataTo(StringStream* stream);
   3587 
   3588   virtual Representation RequiredInputRepresentation(int index) {
   3589     return Representation::Tagged();
   3590   }
   3591 
   3592   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric)
   3593 
   3594  private:
   3595   Handle<Object> name_;
   3596   StrictModeFlag strict_mode_flag_;
   3597 };
   3598 
   3599 
   3600 class HLoadContextSlot: public HUnaryOperation {
   3601  public:
   3602   enum Mode {
   3603     // Perform a normal load of the context slot without checking its value.
   3604     kNoCheck,
   3605     // Load and check the value of the context slot. Deoptimize if it's the
   3606     // hole value. This is used for checking for loading of uninitialized
   3607     // harmony bindings where we deoptimize into full-codegen generated code
   3608     // which will subsequently throw a reference error.
   3609     kCheckDeoptimize,
   3610     // Load and check the value of the context slot. Return undefined if it's
   3611     // the hole value. This is used for non-harmony const assignments
   3612     kCheckReturnUndefined
   3613   };
   3614 
   3615   HLoadContextSlot(HValue* context, Variable* var)
   3616       : HUnaryOperation(context), slot_index_(var->index()) {
   3617     ASSERT(var->IsContextSlot());
   3618     switch (var->mode()) {
   3619       case LET:
   3620       case CONST_HARMONY:
   3621         mode_ = kCheckDeoptimize;
   3622         break;
   3623       case CONST:
   3624         mode_ = kCheckReturnUndefined;
   3625         break;
   3626       default:
   3627         mode_ = kNoCheck;
   3628     }
   3629     set_representation(Representation::Tagged());
   3630     SetFlag(kUseGVN);
   3631     SetGVNFlag(kDependsOnContextSlots);
   3632   }
   3633 
   3634   int slot_index() const { return slot_index_; }
   3635   Mode mode() const { return mode_; }
   3636 
   3637   bool DeoptimizesOnHole() {
   3638     return mode_ == kCheckDeoptimize;
   3639   }
   3640 
   3641   bool RequiresHoleCheck() {
   3642     return mode_ != kNoCheck;
   3643   }
   3644 
   3645   virtual Representation RequiredInputRepresentation(int index) {
   3646     return Representation::Tagged();
   3647   }
   3648 
   3649   virtual void PrintDataTo(StringStream* stream);
   3650 
   3651   DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
   3652 
   3653  protected:
   3654   virtual bool DataEquals(HValue* other) {
   3655     HLoadContextSlot* b = HLoadContextSlot::cast(other);
   3656     return (slot_index() == b->slot_index());
   3657   }
   3658 
   3659  private:
   3660   int slot_index_;
   3661   Mode mode_;
   3662 };
   3663 
   3664 
   3665 class HStoreContextSlot: public HTemplateInstruction<2> {
   3666  public:
   3667   enum Mode {
   3668     // Perform a normal store to the context slot without checking its previous
   3669     // value.
   3670     kNoCheck,
   3671     // Check the previous value of the context slot and deoptimize if it's the
   3672     // hole value. This is used for checking for assignments to uninitialized
   3673     // harmony bindings where we deoptimize into full-codegen generated code
   3674     // which will subsequently throw a reference error.
   3675     kCheckDeoptimize,
   3676     // Check the previous value and ignore assignment if it isn't a hole value
   3677     kCheckIgnoreAssignment
   3678   };
   3679 
   3680   HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
   3681       : slot_index_(slot_index), mode_(mode) {
   3682     SetOperandAt(0, context);
   3683     SetOperandAt(1, value);
   3684     SetGVNFlag(kChangesContextSlots);
   3685   }
   3686 
   3687   HValue* context() { return OperandAt(0); }
   3688   HValue* value() { return OperandAt(1); }
   3689   int slot_index() const { return slot_index_; }
   3690   Mode mode() const { return mode_; }
   3691 
   3692   bool NeedsWriteBarrier() {
   3693     return StoringValueNeedsWriteBarrier(value());
   3694   }
   3695 
   3696   bool DeoptimizesOnHole() {
   3697     return mode_ == kCheckDeoptimize;
   3698   }
   3699 
   3700   bool RequiresHoleCheck() {
   3701     return mode_ != kNoCheck;
   3702   }
   3703 
   3704   virtual Representation RequiredInputRepresentation(int index) {
   3705     return Representation::Tagged();
   3706   }
   3707 
   3708   virtual void PrintDataTo(StringStream* stream);
   3709 
   3710   DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
   3711 
   3712  private:
   3713   int slot_index_;
   3714   Mode mode_;
   3715 };
   3716 
   3717 
   3718 class HLoadNamedField: public HUnaryOperation {
   3719  public:
   3720   HLoadNamedField(HValue* object, bool is_in_object, int offset)
   3721       : HUnaryOperation(object),
   3722         is_in_object_(is_in_object),
   3723         offset_(offset) {
   3724     set_representation(Representation::Tagged());
   3725     SetFlag(kUseGVN);
   3726     SetGVNFlag(kDependsOnMaps);
   3727     if (is_in_object) {
   3728       SetGVNFlag(kDependsOnInobjectFields);
   3729     } else {
   3730       SetGVNFlag(kDependsOnBackingStoreFields);
   3731     }
   3732   }
   3733 
   3734   HValue* object() { return OperandAt(0); }
   3735   bool is_in_object() const { return is_in_object_; }
   3736   int offset() const { return offset_; }
   3737 
   3738   virtual Representation RequiredInputRepresentation(int index) {
   3739     return Representation::Tagged();
   3740   }
   3741   virtual void PrintDataTo(StringStream* stream);
   3742 
   3743   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
   3744 
   3745  protected:
   3746   virtual bool DataEquals(HValue* other) {
   3747     HLoadNamedField* b = HLoadNamedField::cast(other);
   3748     return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
   3749   }
   3750 
   3751  private:
   3752   bool is_in_object_;
   3753   int offset_;
   3754 };
   3755 
   3756 
   3757 class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
   3758  public:
   3759   HLoadNamedFieldPolymorphic(HValue* context,
   3760                              HValue* object,
   3761                              SmallMapList* types,
   3762                              Handle<String> name);
   3763 
   3764   HValue* context() { return OperandAt(0); }
   3765   HValue* object() { return OperandAt(1); }
   3766   SmallMapList* types() { return &types_; }
   3767   Handle<String> name() { return name_; }
   3768   bool need_generic() { return need_generic_; }
   3769 
   3770   virtual Representation RequiredInputRepresentation(int index) {
   3771     return Representation::Tagged();
   3772   }
   3773 
   3774   virtual void PrintDataTo(StringStream* stream);
   3775 
   3776   DECLARE_CONCRETE_INSTRUCTION(LoadNamedFieldPolymorphic)
   3777 
   3778   static const int kMaxLoadPolymorphism = 4;
   3779 
   3780  protected:
   3781   virtual bool DataEquals(HValue* value);
   3782 
   3783  private:
   3784   SmallMapList types_;
   3785   Handle<String> name_;
   3786   bool need_generic_;
   3787 };
   3788 
   3789 
   3790 
   3791 class HLoadNamedGeneric: public HTemplateInstruction<2> {
   3792  public:
   3793   HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
   3794       : name_(name) {
   3795     SetOperandAt(0, context);
   3796     SetOperandAt(1, object);
   3797     set_representation(Representation::Tagged());
   3798     SetAllSideEffects();
   3799   }
   3800 
   3801   HValue* context() { return OperandAt(0); }
   3802   HValue* object() { return OperandAt(1); }
   3803   Handle<Object> name() const { return name_; }
   3804 
   3805   virtual Representation RequiredInputRepresentation(int index) {
   3806     return Representation::Tagged();
   3807   }
   3808 
   3809   virtual void PrintDataTo(StringStream* stream);
   3810 
   3811   DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
   3812 
   3813  private:
   3814   Handle<Object> name_;
   3815 };
   3816 
   3817 
   3818 class HLoadFunctionPrototype: public HUnaryOperation {
   3819  public:
   3820   explicit HLoadFunctionPrototype(HValue* function)
   3821       : HUnaryOperation(function) {
   3822     set_representation(Representation::Tagged());
   3823     SetFlag(kUseGVN);
   3824     SetGVNFlag(kDependsOnCalls);
   3825   }
   3826 
   3827   HValue* function() { return OperandAt(0); }
   3828 
   3829   virtual Representation RequiredInputRepresentation(int index) {
   3830     return Representation::Tagged();
   3831   }
   3832 
   3833   DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
   3834 
   3835  protected:
   3836   virtual bool DataEquals(HValue* other) { return true; }
   3837 };
   3838 
   3839 
   3840 class HLoadKeyedFastElement: public HTemplateInstruction<2> {
   3841  public:
   3842   enum HoleCheckMode { PERFORM_HOLE_CHECK, OMIT_HOLE_CHECK };
   3843 
   3844   HLoadKeyedFastElement(HValue* obj,
   3845                         HValue* key,
   3846                         HoleCheckMode hole_check_mode = PERFORM_HOLE_CHECK)
   3847       : hole_check_mode_(hole_check_mode) {
   3848     SetOperandAt(0, obj);
   3849     SetOperandAt(1, key);
   3850     set_representation(Representation::Tagged());
   3851     SetGVNFlag(kDependsOnArrayElements);
   3852     SetFlag(kUseGVN);
   3853   }
   3854 
   3855   HValue* object() { return OperandAt(0); }
   3856   HValue* key() { return OperandAt(1); }
   3857 
   3858   virtual Representation RequiredInputRepresentation(int index) {
   3859     // The key is supposed to be Integer32.
   3860     return index == 0
   3861       ? Representation::Tagged()
   3862       : Representation::Integer32();
   3863   }
   3864 
   3865   virtual void PrintDataTo(StringStream* stream);
   3866 
   3867   bool RequiresHoleCheck();
   3868 
   3869   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement)
   3870 
   3871  protected:
   3872   virtual bool DataEquals(HValue* other) {
   3873     if (!other->IsLoadKeyedFastElement()) return false;
   3874     HLoadKeyedFastElement* other_load = HLoadKeyedFastElement::cast(other);
   3875     return hole_check_mode_ == other_load->hole_check_mode_;
   3876   }
   3877 
   3878  private:
   3879   HoleCheckMode hole_check_mode_;
   3880 };
   3881 
   3882 
   3883 class HLoadKeyedFastDoubleElement: public HTemplateInstruction<2> {
   3884  public:
   3885   HLoadKeyedFastDoubleElement(HValue* elements, HValue* key) {
   3886     SetOperandAt(0, elements);
   3887     SetOperandAt(1, key);
   3888     set_representation(Representation::Double());
   3889     SetGVNFlag(kDependsOnDoubleArrayElements);
   3890     SetFlag(kUseGVN);
   3891   }
   3892 
   3893   HValue* elements() { return OperandAt(0); }
   3894   HValue* key() { return OperandAt(1); }
   3895 
   3896   virtual Representation RequiredInputRepresentation(int index) {
   3897     // The key is supposed to be Integer32.
   3898     return index == 0
   3899       ? Representation::Tagged()
   3900       : Representation::Integer32();
   3901   }
   3902 
   3903   virtual void PrintDataTo(StringStream* stream);
   3904 
   3905   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement)
   3906 
   3907  protected:
   3908   virtual bool DataEquals(HValue* other) { return true; }
   3909 };
   3910 
   3911 
   3912 class HLoadKeyedSpecializedArrayElement: public HTemplateInstruction<2> {
   3913  public:
   3914   HLoadKeyedSpecializedArrayElement(HValue* external_elements,
   3915                                     HValue* key,
   3916                                     ElementsKind elements_kind)
   3917       :  elements_kind_(elements_kind) {
   3918     SetOperandAt(0, external_elements);
   3919     SetOperandAt(1, key);
   3920     if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
   3921         elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
   3922       set_representation(Representation::Double());
   3923     } else {
   3924       set_representation(Representation::Integer32());
   3925     }
   3926     SetGVNFlag(kDependsOnSpecializedArrayElements);
   3927     // Native code could change the specialized array.
   3928     SetGVNFlag(kDependsOnCalls);
   3929     SetFlag(kUseGVN);
   3930   }
   3931 
   3932   virtual void PrintDataTo(StringStream* stream);
   3933 
   3934   virtual Representation RequiredInputRepresentation(int index) {
   3935     // The key is supposed to be Integer32, but the base pointer
   3936     // for the element load is a naked pointer.
   3937     return index == 0
   3938       ? Representation::External()
   3939       : Representation::Integer32();
   3940   }
   3941 
   3942   HValue* external_pointer() { return OperandAt(0); }
   3943   HValue* key() { return OperandAt(1); }
   3944   ElementsKind elements_kind() const { return elements_kind_; }
   3945 
   3946   virtual Range* InferRange(Zone* zone);
   3947 
   3948   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement)
   3949 
   3950  protected:
   3951   virtual bool DataEquals(HValue* other) {
   3952     if (!other->IsLoadKeyedSpecializedArrayElement()) return false;
   3953     HLoadKeyedSpecializedArrayElement* cast_other =
   3954         HLoadKeyedSpecializedArrayElement::cast(other);
   3955     return elements_kind_ == cast_other->elements_kind();
   3956   }
   3957 
   3958  private:
   3959   ElementsKind elements_kind_;
   3960 };
   3961 
   3962 
   3963 class HLoadKeyedGeneric: public HTemplateInstruction<3> {
   3964  public:
   3965   HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key) {
   3966     set_representation(Representation::Tagged());
   3967     SetOperandAt(0, obj);
   3968     SetOperandAt(1, key);
   3969     SetOperandAt(2, context);
   3970     SetAllSideEffects();
   3971   }
   3972 
   3973   HValue* object() { return OperandAt(0); }
   3974   HValue* key() { return OperandAt(1); }
   3975   HValue* context() { return OperandAt(2); }
   3976 
   3977   virtual void PrintDataTo(StringStream* stream);
   3978 
   3979   virtual Representation RequiredInputRepresentation(int index) {
   3980     return Representation::Tagged();
   3981   }
   3982 
   3983   virtual HValue* Canonicalize();
   3984 
   3985   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
   3986 };
   3987 
   3988 
   3989 class HStoreNamedField: public HTemplateInstruction<2> {
   3990  public:
   3991   HStoreNamedField(HValue* obj,
   3992                    Handle<String> name,
   3993                    HValue* val,
   3994                    bool in_object,
   3995                    int offset)
   3996       : name_(name),
   3997         is_in_object_(in_object),
   3998         offset_(offset) {
   3999     SetOperandAt(0, obj);
   4000     SetOperandAt(1, val);
   4001     if (is_in_object_) {
   4002       SetGVNFlag(kChangesInobjectFields);
   4003     } else {
   4004       SetGVNFlag(kChangesBackingStoreFields);
   4005     }
   4006   }
   4007 
   4008   DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
   4009 
   4010   virtual Representation RequiredInputRepresentation(int index) {
   4011     return Representation::Tagged();
   4012   }
   4013   virtual void PrintDataTo(StringStream* stream);
   4014 
   4015   HValue* object() { return OperandAt(0); }
   4016   HValue* value() { return OperandAt(1); }
   4017 
   4018   Handle<String> name() const { return name_; }
   4019   bool is_in_object() const { return is_in_object_; }
   4020   int offset() const { return offset_; }
   4021   Handle<Map> transition() const { return transition_; }
   4022   void set_transition(Handle<Map> map) { transition_ = map; }
   4023 
   4024   bool NeedsWriteBarrier() {
   4025     return StoringValueNeedsWriteBarrier(value());
   4026   }
   4027 
   4028  private:
   4029   Handle<String> name_;
   4030   bool is_in_object_;
   4031   int offset_;
   4032   Handle<Map> transition_;
   4033 };
   4034 
   4035 
   4036 class HStoreNamedGeneric: public HTemplateInstruction<3> {
   4037  public:
   4038   HStoreNamedGeneric(HValue* context,
   4039                      HValue* object,
   4040                      Handle<String> name,
   4041                      HValue* value,
   4042                      StrictModeFlag strict_mode_flag)
   4043       : name_(name),
   4044         strict_mode_flag_(strict_mode_flag) {
   4045     SetOperandAt(0, object);
   4046     SetOperandAt(1, value);
   4047     SetOperandAt(2, context);
   4048     SetAllSideEffects();
   4049   }
   4050 
   4051   HValue* object() { return OperandAt(0); }
   4052   HValue* value() { return OperandAt(1); }
   4053   HValue* context() { return OperandAt(2); }
   4054   Handle<String> name() { return name_; }
   4055   StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
   4056 
   4057   virtual void PrintDataTo(StringStream* stream);
   4058 
   4059   virtual Representation RequiredInputRepresentation(int index) {
   4060     return Representation::Tagged();
   4061   }
   4062 
   4063   DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
   4064 
   4065  private:
   4066   Handle<String> name_;
   4067   StrictModeFlag strict_mode_flag_;
   4068 };
   4069 
   4070 
   4071 class HStoreKeyedFastElement: public HTemplateInstruction<3> {
   4072  public:
   4073   HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val,
   4074                          ElementsKind elements_kind = FAST_ELEMENTS)
   4075       : elements_kind_(elements_kind) {
   4076     SetOperandAt(0, obj);
   4077     SetOperandAt(1, key);
   4078     SetOperandAt(2, val);
   4079     SetGVNFlag(kChangesArrayElements);
   4080   }
   4081 
   4082   virtual Representation RequiredInputRepresentation(int index) {
   4083     // The key is supposed to be Integer32.
   4084     return index == 1
   4085         ? Representation::Integer32()
   4086         : Representation::Tagged();
   4087   }
   4088 
   4089   HValue* object() { return OperandAt(0); }
   4090   HValue* key() { return OperandAt(1); }
   4091   HValue* value() { return OperandAt(2); }
   4092   bool value_is_smi() {
   4093     return elements_kind_ == FAST_SMI_ONLY_ELEMENTS;
   4094   }
   4095 
   4096   bool NeedsWriteBarrier() {
   4097     if (value_is_smi()) {
   4098       return false;
   4099     } else {
   4100       return StoringValueNeedsWriteBarrier(value());
   4101     }
   4102   }
   4103 
   4104   virtual void PrintDataTo(StringStream* stream);
   4105 
   4106   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement)
   4107 
   4108  private:
   4109   ElementsKind elements_kind_;
   4110 };
   4111 
   4112 
   4113 class HStoreKeyedFastDoubleElement: public HTemplateInstruction<3> {
   4114  public:
   4115   HStoreKeyedFastDoubleElement(HValue* elements,
   4116                                HValue* key,
   4117                                HValue* val) {
   4118     SetOperandAt(0, elements);
   4119     SetOperandAt(1, key);
   4120     SetOperandAt(2, val);
   4121     SetGVNFlag(kChangesDoubleArrayElements);
   4122   }
   4123 
   4124   virtual Representation RequiredInputRepresentation(int index) {
   4125     if (index == 1) {
   4126       return Representation::Integer32();
   4127     } else if (index == 2) {
   4128       return Representation::Double();
   4129     } else {
   4130       return Representation::Tagged();
   4131     }
   4132   }
   4133 
   4134   HValue* elements() { return OperandAt(0); }
   4135   HValue* key() { return OperandAt(1); }
   4136   HValue* value() { return OperandAt(2); }
   4137 
   4138   bool NeedsWriteBarrier() {
   4139     return StoringValueNeedsWriteBarrier(value());
   4140   }
   4141 
   4142   virtual void PrintDataTo(StringStream* stream);
   4143 
   4144   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement)
   4145 };
   4146 
   4147 
   4148 class HStoreKeyedSpecializedArrayElement: public HTemplateInstruction<3> {
   4149  public:
   4150   HStoreKeyedSpecializedArrayElement(HValue* external_elements,
   4151                                      HValue* key,
   4152                                      HValue* val,
   4153                                      ElementsKind elements_kind)
   4154       : elements_kind_(elements_kind) {
   4155     SetGVNFlag(kChangesSpecializedArrayElements);
   4156     SetOperandAt(0, external_elements);
   4157     SetOperandAt(1, key);
   4158     SetOperandAt(2, val);
   4159   }
   4160 
   4161   virtual void PrintDataTo(StringStream* stream);
   4162 
   4163   virtual Representation RequiredInputRepresentation(int index) {
   4164     if (index == 0) {
   4165       return Representation::External();
   4166     } else {
   4167       bool float_or_double_elements =
   4168           elements_kind() == EXTERNAL_FLOAT_ELEMENTS ||
   4169           elements_kind() == EXTERNAL_DOUBLE_ELEMENTS;
   4170       if (index == 2 && float_or_double_elements) {
   4171         return Representation::Double();
   4172       } else {
   4173         return Representation::Integer32();
   4174       }
   4175     }
   4176   }
   4177 
   4178   HValue* external_pointer() { return OperandAt(0); }
   4179   HValue* key() { return OperandAt(1); }
   4180   HValue* value() { return OperandAt(2); }
   4181   ElementsKind elements_kind() const { return elements_kind_; }
   4182 
   4183   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement)
   4184 
   4185  private:
   4186   ElementsKind elements_kind_;
   4187 };
   4188 
   4189 
   4190 class HStoreKeyedGeneric: public HTemplateInstruction<4> {
   4191  public:
   4192   HStoreKeyedGeneric(HValue* context,
   4193                      HValue* object,
   4194                      HValue* key,
   4195                      HValue* value,
   4196                      StrictModeFlag strict_mode_flag)
   4197       : strict_mode_flag_(strict_mode_flag) {
   4198     SetOperandAt(0, object);
   4199     SetOperandAt(1, key);
   4200     SetOperandAt(2, value);
   4201     SetOperandAt(3, context);
   4202     SetAllSideEffects();
   4203   }
   4204 
   4205   HValue* object() { return OperandAt(0); }
   4206   HValue* key() { return OperandAt(1); }
   4207   HValue* value() { return OperandAt(2); }
   4208   HValue* context() { return OperandAt(3); }
   4209   StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
   4210 
   4211   virtual Representation RequiredInputRepresentation(int index) {
   4212     return Representation::Tagged();
   4213   }
   4214 
   4215   virtual void PrintDataTo(StringStream* stream);
   4216 
   4217   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
   4218 
   4219  private:
   4220   StrictModeFlag strict_mode_flag_;
   4221 };
   4222 
   4223 
   4224 class HTransitionElementsKind: public HTemplateInstruction<1> {
   4225  public:
   4226   HTransitionElementsKind(HValue* object,
   4227                           Handle<Map> original_map,
   4228                           Handle<Map> transitioned_map)
   4229       : original_map_(original_map),
   4230         transitioned_map_(transitioned_map) {
   4231     SetOperandAt(0, object);
   4232     SetFlag(kUseGVN);
   4233     SetGVNFlag(kChangesElementsKind);
   4234     SetGVNFlag(kChangesElementsPointer);
   4235     set_representation(Representation::Tagged());
   4236   }
   4237 
   4238   virtual Representation RequiredInputRepresentation(int index) {
   4239     return Representation::Tagged();
   4240   }
   4241 
   4242   HValue* object() { return OperandAt(0); }
   4243   Handle<Map> original_map() { return original_map_; }
   4244   Handle<Map> transitioned_map() { return transitioned_map_; }
   4245 
   4246   virtual void PrintDataTo(StringStream* stream);
   4247 
   4248   DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
   4249 
   4250  protected:
   4251   virtual bool DataEquals(HValue* other) {
   4252     HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
   4253     return original_map_.is_identical_to(instr->original_map()) &&
   4254         transitioned_map_.is_identical_to(instr->transitioned_map());
   4255   }
   4256 
   4257  private:
   4258   Handle<Map> original_map_;
   4259   Handle<Map> transitioned_map_;
   4260 };
   4261 
   4262 
   4263 class HStringAdd: public HBinaryOperation {
   4264  public:
   4265   HStringAdd(HValue* context, HValue* left, HValue* right)
   4266       : HBinaryOperation(context, left, right) {
   4267     set_representation(Representation::Tagged());
   4268     SetFlag(kUseGVN);
   4269     SetGVNFlag(kDependsOnMaps);
   4270   }
   4271 
   4272   virtual Representation RequiredInputRepresentation(int index) {
   4273     return Representation::Tagged();
   4274   }
   4275 
   4276   virtual HType CalculateInferredType() {
   4277     return HType::String();
   4278   }
   4279 
   4280   DECLARE_CONCRETE_INSTRUCTION(StringAdd)
   4281 
   4282  protected:
   4283   virtual bool DataEquals(HValue* other) { return true; }
   4284 };
   4285 
   4286 
   4287 class HStringCharCodeAt: public HTemplateInstruction<3> {
   4288  public:
   4289   HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
   4290     SetOperandAt(0, context);
   4291     SetOperandAt(1, string);
   4292     SetOperandAt(2, index);
   4293     set_representation(Representation::Integer32());
   4294     SetFlag(kUseGVN);
   4295     SetGVNFlag(kDependsOnMaps);
   4296   }
   4297 
   4298   virtual Representation RequiredInputRepresentation(int index) {
   4299     // The index is supposed to be Integer32.
   4300     return index == 2
   4301         ? Representation::Integer32()
   4302         : Representation::Tagged();
   4303   }
   4304 
   4305   HValue* context() { return OperandAt(0); }
   4306   HValue* string() { return OperandAt(1); }
   4307   HValue* index() { return OperandAt(2); }
   4308 
   4309   DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
   4310 
   4311  protected:
   4312   virtual bool DataEquals(HValue* other) { return true; }
   4313 
   4314   virtual Range* InferRange(Zone* zone) {
   4315     return new(zone) Range(0, String::kMaxUtf16CodeUnit);
   4316   }
   4317 };
   4318 
   4319 
   4320 class HStringCharFromCode: public HTemplateInstruction<2> {
   4321  public:
   4322   HStringCharFromCode(HValue* context, HValue* char_code) {
   4323     SetOperandAt(0, context);
   4324     SetOperandAt(1, char_code);
   4325     set_representation(Representation::Tagged());
   4326     SetFlag(kUseGVN);
   4327   }
   4328 
   4329   virtual Representation RequiredInputRepresentation(int index) {
   4330     return index == 0
   4331         ? Representation::Tagged()
   4332         : Representation::Integer32();
   4333   }
   4334   virtual HType CalculateInferredType();
   4335 
   4336   HValue* context() { return OperandAt(0); }
   4337   HValue* value() { return OperandAt(1); }
   4338 
   4339   virtual bool DataEquals(HValue* other) { return true; }
   4340 
   4341   DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
   4342 };
   4343 
   4344 
   4345 class HStringLength: public HUnaryOperation {
   4346  public:
   4347   explicit HStringLength(HValue* string) : HUnaryOperation(string) {
   4348     set_representation(Representation::Tagged());
   4349     SetFlag(kUseGVN);
   4350     SetGVNFlag(kDependsOnMaps);
   4351   }
   4352 
   4353   virtual Representation RequiredInputRepresentation(int index) {
   4354     return Representation::Tagged();
   4355   }
   4356 
   4357   virtual HType CalculateInferredType() {
   4358     STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
   4359     return HType::Smi();
   4360   }
   4361 
   4362   DECLARE_CONCRETE_INSTRUCTION(StringLength)
   4363 
   4364  protected:
   4365   virtual bool DataEquals(HValue* other) { return true; }
   4366 
   4367   virtual Range* InferRange(Zone* zone) {
   4368     return new(zone) Range(0, String::kMaxLength);
   4369   }
   4370 };
   4371 
   4372 
   4373 class HAllocateObject: public HTemplateInstruction<1> {
   4374  public:
   4375   HAllocateObject(HValue* context, Handle<JSFunction> constructor)
   4376       : constructor_(constructor) {
   4377     SetOperandAt(0, context);
   4378     set_representation(Representation::Tagged());
   4379   }
   4380 
   4381   HValue* context() { return OperandAt(0); }
   4382   Handle<JSFunction> constructor() { return constructor_; }
   4383 
   4384   virtual Representation RequiredInputRepresentation(int index) {
   4385     return Representation::Tagged();
   4386   }
   4387   virtual HType CalculateInferredType();
   4388 
   4389   DECLARE_CONCRETE_INSTRUCTION(AllocateObject)
   4390 
   4391  private:
   4392   Handle<JSFunction> constructor_;
   4393 };
   4394 
   4395 
   4396 template <int V>
   4397 class HMaterializedLiteral: public HTemplateInstruction<V> {
   4398  public:
   4399   HMaterializedLiteral<V>(int index, int depth)
   4400       : literal_index_(index), depth_(depth) {
   4401     this->set_representation(Representation::Tagged());
   4402   }
   4403 
   4404   int literal_index() const { return literal_index_; }
   4405   int depth() const { return depth_; }
   4406 
   4407  private:
   4408   int literal_index_;
   4409   int depth_;
   4410 };
   4411 
   4412 
   4413 class HFastLiteral: public HMaterializedLiteral<1> {
   4414  public:
   4415   HFastLiteral(HValue* context,
   4416                Handle<JSObject> boilerplate,
   4417                int total_size,
   4418                int literal_index,
   4419                int depth)
   4420       : HMaterializedLiteral<1>(literal_index, depth),
   4421         boilerplate_(boilerplate),
   4422         total_size_(total_size) {
   4423     SetOperandAt(0, context);
   4424   }
   4425 
   4426   // Maximum depth and total number of elements and properties for literal
   4427   // graphs to be considered for fast deep-copying.
   4428   static const int kMaxLiteralDepth = 3;
   4429   static const int kMaxLiteralProperties = 8;
   4430 
   4431   HValue* context() { return OperandAt(0); }
   4432   Handle<JSObject> boilerplate() const { return boilerplate_; }
   4433   int total_size() const { return total_size_; }
   4434 
   4435   virtual Representation RequiredInputRepresentation(int index) {
   4436     return Representation::Tagged();
   4437   }
   4438   virtual HType CalculateInferredType();
   4439 
   4440   DECLARE_CONCRETE_INSTRUCTION(FastLiteral)
   4441 
   4442  private:
   4443   Handle<JSObject> boilerplate_;
   4444   int total_size_;
   4445 };
   4446 
   4447 
   4448 class HArrayLiteral: public HMaterializedLiteral<1> {
   4449  public:
   4450   HArrayLiteral(HValue* context,
   4451                 Handle<HeapObject> boilerplate_object,
   4452                 int length,
   4453                 int literal_index,
   4454                 int depth)
   4455       : HMaterializedLiteral<1>(literal_index, depth),
   4456         length_(length),
   4457         boilerplate_object_(boilerplate_object) {
   4458     SetOperandAt(0, context);
   4459   }
   4460 
   4461   HValue* context() { return OperandAt(0); }
   4462   ElementsKind boilerplate_elements_kind() const {
   4463     if (!boilerplate_object_->IsJSObject()) {
   4464       return FAST_ELEMENTS;
   4465     }
   4466     return Handle<JSObject>::cast(boilerplate_object_)->GetElementsKind();
   4467   }
   4468   Handle<HeapObject> boilerplate_object() const { return boilerplate_object_; }
   4469   int length() const { return length_; }
   4470 
   4471   bool IsCopyOnWrite() const;
   4472 
   4473   virtual Representation RequiredInputRepresentation(int index) {
   4474     return Representation::Tagged();
   4475   }
   4476   virtual HType CalculateInferredType();
   4477 
   4478   DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral)
   4479 
   4480  private:
   4481   int length_;
   4482   Handle<HeapObject> boilerplate_object_;
   4483 };
   4484 
   4485 
   4486 class HObjectLiteral: public HMaterializedLiteral<1> {
   4487  public:
   4488   HObjectLiteral(HValue* context,
   4489                  Handle<FixedArray> constant_properties,
   4490                  bool fast_elements,
   4491                  int literal_index,
   4492                  int depth,
   4493                  bool has_function)
   4494       : HMaterializedLiteral<1>(literal_index, depth),
   4495         constant_properties_(constant_properties),
   4496         fast_elements_(fast_elements),
   4497         has_function_(has_function) {
   4498     SetOperandAt(0, context);
   4499   }
   4500 
   4501   HValue* context() { return OperandAt(0); }
   4502   Handle<FixedArray> constant_properties() const {
   4503     return constant_properties_;
   4504   }
   4505   bool fast_elements() const { return fast_elements_; }
   4506   bool has_function() const { return has_function_; }
   4507 
   4508   virtual Representation RequiredInputRepresentation(int index) {
   4509     return Representation::Tagged();
   4510   }
   4511   virtual HType CalculateInferredType();
   4512 
   4513   DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral)
   4514 
   4515  private:
   4516   Handle<FixedArray> constant_properties_;
   4517   bool fast_elements_;
   4518   bool has_function_;
   4519 };
   4520 
   4521 
   4522 class HRegExpLiteral: public HMaterializedLiteral<1> {
   4523  public:
   4524   HRegExpLiteral(HValue* context,
   4525                  Handle<String> pattern,
   4526                  Handle<String> flags,
   4527                  int literal_index)
   4528       : HMaterializedLiteral<1>(literal_index, 0),
   4529         pattern_(pattern),
   4530         flags_(flags) {
   4531     SetOperandAt(0, context);
   4532     SetAllSideEffects();
   4533   }
   4534 
   4535   HValue* context() { return OperandAt(0); }
   4536   Handle<String> pattern() { return pattern_; }
   4537   Handle<String> flags() { return flags_; }
   4538 
   4539   virtual Representation RequiredInputRepresentation(int index) {
   4540     return Representation::Tagged();
   4541   }
   4542   virtual HType CalculateInferredType();
   4543 
   4544   DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
   4545 
   4546  private:
   4547   Handle<String> pattern_;
   4548   Handle<String> flags_;
   4549 };
   4550 
   4551 
   4552 class HFunctionLiteral: public HTemplateInstruction<1> {
   4553  public:
   4554   HFunctionLiteral(HValue* context,
   4555                    Handle<SharedFunctionInfo> shared,
   4556                    bool pretenure)
   4557       : shared_info_(shared), pretenure_(pretenure) {
   4558     SetOperandAt(0, context);
   4559     set_representation(Representation::Tagged());
   4560   }
   4561 
   4562   HValue* context() { return OperandAt(0); }
   4563 
   4564   virtual Representation RequiredInputRepresentation(int index) {
   4565     return Representation::Tagged();
   4566   }
   4567   virtual HType CalculateInferredType();
   4568 
   4569   DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral)
   4570 
   4571   Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
   4572   bool pretenure() const { return pretenure_; }
   4573 
   4574  private:
   4575   Handle<SharedFunctionInfo> shared_info_;
   4576   bool pretenure_;
   4577 };
   4578 
   4579 
   4580 class HTypeof: public HTemplateInstruction<2> {
   4581  public:
   4582   explicit HTypeof(HValue* context, HValue* value) {
   4583     SetOperandAt(0, context);
   4584     SetOperandAt(1, value);
   4585     set_representation(Representation::Tagged());
   4586   }
   4587 
   4588   HValue* context() { return OperandAt(0); }
   4589   HValue* value() { return OperandAt(1); }
   4590 
   4591   virtual HValue* Canonicalize();
   4592   virtual void PrintDataTo(StringStream* stream);
   4593 
   4594   virtual Representation RequiredInputRepresentation(int index) {
   4595     return Representation::Tagged();
   4596   }
   4597 
   4598   DECLARE_CONCRETE_INSTRUCTION(Typeof)
   4599 };
   4600 
   4601 
   4602 class HToFastProperties: public HUnaryOperation {
   4603  public:
   4604   explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
   4605     // This instruction is not marked as having side effects, but
   4606     // changes the map of the input operand. Use it only when creating
   4607     // object literals.
   4608     ASSERT(value->IsObjectLiteral() || value->IsFastLiteral());
   4609     set_representation(Representation::Tagged());
   4610   }
   4611 
   4612   virtual Representation RequiredInputRepresentation(int index) {
   4613     return Representation::Tagged();
   4614   }
   4615 
   4616   DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
   4617 };
   4618 
   4619 
   4620 class HValueOf: public HUnaryOperation {
   4621  public:
   4622   explicit HValueOf(HValue* value) : HUnaryOperation(value) {
   4623     set_representation(Representation::Tagged());
   4624   }
   4625 
   4626   virtual Representation RequiredInputRepresentation(int index) {
   4627     return Representation::Tagged();
   4628   }
   4629 
   4630   DECLARE_CONCRETE_INSTRUCTION(ValueOf)
   4631 };
   4632 
   4633 
   4634 class HDateField: public HUnaryOperation {
   4635  public:
   4636   HDateField(HValue* date, Smi* index)
   4637       : HUnaryOperation(date), index_(index) {
   4638     set_representation(Representation::Tagged());
   4639   }
   4640 
   4641   Smi* index() const { return index_; }
   4642 
   4643   virtual Representation RequiredInputRepresentation(int index) {
   4644     return Representation::Tagged();
   4645   }
   4646 
   4647   DECLARE_CONCRETE_INSTRUCTION(DateField)
   4648 
   4649  private:
   4650   Smi* index_;
   4651 };
   4652 
   4653 
   4654 class HDeleteProperty: public HBinaryOperation {
   4655  public:
   4656   HDeleteProperty(HValue* context, HValue* obj, HValue* key)
   4657       : HBinaryOperation(context, obj, key) {
   4658     set_representation(Representation::Tagged());
   4659     SetAllSideEffects();
   4660   }
   4661 
   4662   virtual Representation RequiredInputRepresentation(int index) {
   4663     return Representation::Tagged();
   4664   }
   4665 
   4666   virtual HType CalculateInferredType();
   4667 
   4668   DECLARE_CONCRETE_INSTRUCTION(DeleteProperty)
   4669 
   4670   HValue* object() { return left(); }
   4671   HValue* key() { return right(); }
   4672 };
   4673 
   4674 
   4675 class HIn: public HTemplateInstruction<3> {
   4676  public:
   4677   HIn(HValue* context, HValue* key, HValue* object) {
   4678     SetOperandAt(0, context);
   4679     SetOperandAt(1, key);
   4680     SetOperandAt(2, object);
   4681     set_representation(Representation::Tagged());
   4682     SetAllSideEffects();
   4683   }
   4684 
   4685   HValue* context() { return OperandAt(0); }
   4686   HValue* key() { return OperandAt(1); }
   4687   HValue* object() { return OperandAt(2); }
   4688 
   4689   virtual Representation RequiredInputRepresentation(int index) {
   4690     return Representation::Tagged();
   4691   }
   4692 
   4693   virtual HType CalculateInferredType() {
   4694     return HType::Boolean();
   4695   }
   4696 
   4697   virtual void PrintDataTo(StringStream* stream);
   4698 
   4699   DECLARE_CONCRETE_INSTRUCTION(In)
   4700 };
   4701 
   4702 
   4703 class HCheckMapValue: public HTemplateInstruction<2> {
   4704  public:
   4705   HCheckMapValue(HValue* value,
   4706                  HValue* map) {
   4707     SetOperandAt(0, value);
   4708     SetOperandAt(1, map);
   4709     set_representation(Representation::Tagged());
   4710     SetFlag(kUseGVN);
   4711     SetGVNFlag(kDependsOnMaps);
   4712     SetGVNFlag(kDependsOnElementsKind);
   4713   }
   4714 
   4715   virtual Representation RequiredInputRepresentation(int index) {
   4716     return Representation::Tagged();
   4717   }
   4718 
   4719   virtual void PrintDataTo(StringStream* stream);
   4720 
   4721   virtual HType CalculateInferredType() {
   4722     return HType::Tagged();
   4723   }
   4724 
   4725   HValue* value() { return OperandAt(0); }
   4726   HValue* map() { return OperandAt(1); }
   4727 
   4728   DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
   4729 
   4730  protected:
   4731   virtual bool DataEquals(HValue* other) {
   4732     return true;
   4733   }
   4734 };
   4735 
   4736 
   4737 class HForInPrepareMap : public HTemplateInstruction<2> {
   4738  public:
   4739   HForInPrepareMap(HValue* context,
   4740                    HValue* object) {
   4741     SetOperandAt(0, context);
   4742     SetOperandAt(1, object);
   4743     set_representation(Representation::Tagged());
   4744     SetAllSideEffects();
   4745   }
   4746 
   4747   virtual Representation RequiredInputRepresentation(int index) {
   4748     return Representation::Tagged();
   4749   }
   4750 
   4751   HValue* context() { return OperandAt(0); }
   4752   HValue* enumerable() { return OperandAt(1); }
   4753 
   4754   virtual void PrintDataTo(StringStream* stream);
   4755 
   4756   virtual HType CalculateInferredType() {
   4757     return HType::Tagged();
   4758   }
   4759 
   4760   DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
   4761 };
   4762 
   4763 
   4764 class HForInCacheArray : public HTemplateInstruction<2> {
   4765  public:
   4766   HForInCacheArray(HValue* enumerable,
   4767                    HValue* keys,
   4768                    int idx) : idx_(idx) {
   4769     SetOperandAt(0, enumerable);
   4770     SetOperandAt(1, keys);
   4771     set_representation(Representation::Tagged());
   4772   }
   4773 
   4774   virtual Representation RequiredInputRepresentation(int index) {
   4775     return Representation::Tagged();
   4776   }
   4777 
   4778   HValue* enumerable() { return OperandAt(0); }
   4779   HValue* map() { return OperandAt(1); }
   4780   int idx() { return idx_; }
   4781 
   4782   HForInCacheArray* index_cache() {
   4783     return index_cache_;
   4784   }
   4785 
   4786   void set_index_cache(HForInCacheArray* index_cache) {
   4787     index_cache_ = index_cache;
   4788   }
   4789 
   4790   virtual void PrintDataTo(StringStream* stream);
   4791 
   4792   virtual HType CalculateInferredType() {
   4793     return HType::Tagged();
   4794   }
   4795 
   4796   DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
   4797 
   4798  private:
   4799   int idx_;
   4800   HForInCacheArray* index_cache_;
   4801 };
   4802 
   4803 
   4804 class HLoadFieldByIndex : public HTemplateInstruction<2> {
   4805  public:
   4806   HLoadFieldByIndex(HValue* object,
   4807                     HValue* index) {
   4808     SetOperandAt(0, object);
   4809     SetOperandAt(1, index);
   4810     set_representation(Representation::Tagged());
   4811   }
   4812 
   4813   virtual Representation RequiredInputRepresentation(int index) {
   4814     return Representation::Tagged();
   4815   }
   4816 
   4817   HValue* object() { return OperandAt(0); }
   4818   HValue* index() { return OperandAt(1); }
   4819 
   4820   virtual void PrintDataTo(StringStream* stream);
   4821 
   4822   virtual HType CalculateInferredType() {
   4823     return HType::Tagged();
   4824   }
   4825 
   4826   DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
   4827 };
   4828 
   4829 
   4830 #undef DECLARE_INSTRUCTION
   4831 #undef DECLARE_CONCRETE_INSTRUCTION
   4832 
   4833 } }  // namespace v8::internal
   4834 
   4835 #endif  // V8_HYDROGEN_INSTRUCTIONS_H_
   4836