Home | History | Annotate | Download | only in src
      1 // Copyright 2011 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 "code-stubs.h"
     34 #include "small-pointer-list.h"
     35 #include "string-stream.h"
     36 #include "zone.h"
     37 
     38 namespace v8 {
     39 namespace internal {
     40 
     41 // Forward declarations.
     42 class HBasicBlock;
     43 class HEnvironment;
     44 class HInstruction;
     45 class HLoopInformation;
     46 class HValue;
     47 class LInstruction;
     48 class LChunkBuilder;
     49 
     50 
     51 #define HYDROGEN_ALL_INSTRUCTION_LIST(V)       \
     52   V(ArithmeticBinaryOperation)                 \
     53   V(BinaryCall)                                \
     54   V(BinaryOperation)                           \
     55   V(BitwiseBinaryOperation)                    \
     56   V(ControlInstruction)                        \
     57   V(Instruction)                               \
     58   V(Phi)                                       \
     59   V(UnaryCall)                                 \
     60   V(UnaryControlInstruction)                   \
     61   V(UnaryOperation)                            \
     62   HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
     63 
     64 
     65 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)  \
     66   V(AbnormalExit)                              \
     67   V(AccessArgumentsAt)                         \
     68   V(Add)                                       \
     69   V(ApplyArguments)                            \
     70   V(ArgumentsElements)                         \
     71   V(ArgumentsLength)                           \
     72   V(ArgumentsObject)                           \
     73   V(ArrayLiteral)                              \
     74   V(BitAnd)                                    \
     75   V(BitNot)                                    \
     76   V(BitOr)                                     \
     77   V(BitXor)                                    \
     78   V(BlockEntry)                                \
     79   V(BoundsCheck)                               \
     80   V(CallConstantFunction)                      \
     81   V(CallFunction)                              \
     82   V(CallGlobal)                                \
     83   V(CallKeyed)                                 \
     84   V(CallKnownGlobal)                           \
     85   V(CallNamed)                                 \
     86   V(CallNew)                                   \
     87   V(CallRuntime)                               \
     88   V(CallStub)                                  \
     89   V(Change)                                    \
     90   V(CheckFunction)                             \
     91   V(CheckInstanceType)                         \
     92   V(CheckMap)                                  \
     93   V(CheckNonSmi)                               \
     94   V(CheckPrototypeMaps)                        \
     95   V(CheckSmi)                                  \
     96   V(ClassOfTest)                               \
     97   V(Compare)                                   \
     98   V(CompareJSObjectEq)                         \
     99   V(CompareMap)                                \
    100   V(Constant)                                  \
    101   V(Context)                                   \
    102   V(DeleteProperty)                            \
    103   V(Deoptimize)                                \
    104   V(Div)                                       \
    105   V(EnterInlined)                              \
    106   V(ExternalArrayLength)                       \
    107   V(FixedArrayLength)                          \
    108   V(FunctionLiteral)                           \
    109   V(GetCachedArrayIndex)                       \
    110   V(GlobalObject)                              \
    111   V(GlobalReceiver)                            \
    112   V(Goto)                                      \
    113   V(HasInstanceType)                           \
    114   V(HasCachedArrayIndex)                       \
    115   V(InstanceOf)                                \
    116   V(InstanceOfKnownGlobal)                     \
    117   V(IsNull)                                    \
    118   V(IsObject)                                  \
    119   V(IsSmi)                                     \
    120   V(IsConstructCall)                           \
    121   V(JSArrayLength)                             \
    122   V(LeaveInlined)                              \
    123   V(LoadContextSlot)                           \
    124   V(LoadElements)                              \
    125   V(LoadExternalArrayPointer)                  \
    126   V(LoadFunctionPrototype)                     \
    127   V(LoadGlobalCell)                            \
    128   V(LoadGlobalGeneric)                         \
    129   V(LoadKeyedFastElement)                      \
    130   V(LoadKeyedGeneric)                          \
    131   V(LoadKeyedSpecializedArrayElement)          \
    132   V(LoadNamedField)                            \
    133   V(LoadNamedFieldPolymorphic)                 \
    134   V(LoadNamedGeneric)                          \
    135   V(Mod)                                       \
    136   V(Mul)                                       \
    137   V(ObjectLiteral)                             \
    138   V(OsrEntry)                                  \
    139   V(OuterContext)                              \
    140   V(Parameter)                                 \
    141   V(Power)                                     \
    142   V(PushArgument)                              \
    143   V(RegExpLiteral)                             \
    144   V(Return)                                    \
    145   V(Sar)                                       \
    146   V(Shl)                                       \
    147   V(Shr)                                       \
    148   V(Simulate)                                  \
    149   V(StackCheck)                                \
    150   V(StoreContextSlot)                          \
    151   V(StoreGlobalCell)                           \
    152   V(StoreGlobalGeneric)                        \
    153   V(StoreKeyedFastElement)                     \
    154   V(StoreKeyedSpecializedArrayElement)         \
    155   V(StoreKeyedGeneric)                         \
    156   V(StoreNamedField)                           \
    157   V(StoreNamedGeneric)                         \
    158   V(StringCharCodeAt)                          \
    159   V(StringCharFromCode)                        \
    160   V(StringLength)                              \
    161   V(Sub)                                       \
    162   V(Test)                                      \
    163   V(Throw)                                     \
    164   V(ToFastProperties)                          \
    165   V(Typeof)                                    \
    166   V(TypeofIs)                                  \
    167   V(UnaryMathOperation)                        \
    168   V(UnknownOSRValue)                           \
    169   V(ValueOf)
    170 
    171 #define GVN_FLAG_LIST(V)                       \
    172   V(Calls)                                     \
    173   V(InobjectFields)                            \
    174   V(BackingStoreFields)                        \
    175   V(ArrayElements)                             \
    176   V(SpecializedArrayElements)                  \
    177   V(GlobalVars)                                \
    178   V(Maps)                                      \
    179   V(ArrayLengths)                              \
    180   V(ContextSlots)                              \
    181   V(OsrEntries)
    182 
    183 #define DECLARE_INSTRUCTION(type)                   \
    184   virtual bool Is##type() const { return true; }    \
    185   static H##type* cast(HValue* value) {             \
    186     ASSERT(value->Is##type());                      \
    187     return reinterpret_cast<H##type*>(value);       \
    188   }                                                 \
    189   Opcode opcode() const { return HValue::k##type; }
    190 
    191 
    192 #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic)              \
    193   virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
    194   virtual const char* Mnemonic() const { return mnemonic; }       \
    195   DECLARE_INSTRUCTION(type)
    196 
    197 
    198 class Range: public ZoneObject {
    199  public:
    200   Range()
    201       : lower_(kMinInt),
    202         upper_(kMaxInt),
    203         next_(NULL),
    204         can_be_minus_zero_(false) { }
    205 
    206   Range(int32_t lower, int32_t upper)
    207       : lower_(lower),
    208         upper_(upper),
    209         next_(NULL),
    210         can_be_minus_zero_(false) { }
    211 
    212   int32_t upper() const { return upper_; }
    213   int32_t lower() const { return lower_; }
    214   Range* next() const { return next_; }
    215   Range* CopyClearLower() const { return new Range(kMinInt, upper_); }
    216   Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); }
    217   Range* Copy() const { return new Range(lower_, upper_); }
    218   int32_t Mask() const;
    219   void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
    220   bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
    221   bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
    222   bool CanBeNegative() const { return lower_ < 0; }
    223   bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
    224   bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; }
    225   bool IsInSmiRange() const {
    226     return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
    227   }
    228   void KeepOrder();
    229   void Verify() const;
    230 
    231   void StackUpon(Range* other) {
    232     Intersect(other);
    233     next_ = other;
    234   }
    235 
    236   void Intersect(Range* other);
    237   void Union(Range* other);
    238 
    239   void AddConstant(int32_t value);
    240   void Sar(int32_t value);
    241   void Shl(int32_t value);
    242   bool AddAndCheckOverflow(Range* other);
    243   bool SubAndCheckOverflow(Range* other);
    244   bool MulAndCheckOverflow(Range* other);
    245 
    246  private:
    247   int32_t lower_;
    248   int32_t upper_;
    249   Range* next_;
    250   bool can_be_minus_zero_;
    251 };
    252 
    253 
    254 class Representation {
    255  public:
    256   enum Kind {
    257     kNone,
    258     kTagged,
    259     kDouble,
    260     kInteger32,
    261     kExternal,
    262     kNumRepresentations
    263   };
    264 
    265   Representation() : kind_(kNone) { }
    266 
    267   static Representation None() { return Representation(kNone); }
    268   static Representation Tagged() { return Representation(kTagged); }
    269   static Representation Integer32() { return Representation(kInteger32); }
    270   static Representation Double() { return Representation(kDouble); }
    271   static Representation External() { return Representation(kExternal); }
    272 
    273   bool Equals(const Representation& other) {
    274     return kind_ == other.kind_;
    275   }
    276 
    277   Kind kind() const { return static_cast<Kind>(kind_); }
    278   bool IsNone() const { return kind_ == kNone; }
    279   bool IsTagged() const { return kind_ == kTagged; }
    280   bool IsInteger32() const { return kind_ == kInteger32; }
    281   bool IsDouble() const { return kind_ == kDouble; }
    282   bool IsExternal() const { return kind_ == kExternal; }
    283   bool IsSpecialization() const {
    284     return kind_ == kInteger32 || kind_ == kDouble;
    285   }
    286   const char* Mnemonic() const;
    287 
    288  private:
    289   explicit Representation(Kind k) : kind_(k) { }
    290 
    291   // Make sure kind fits in int8.
    292   STATIC_ASSERT(kNumRepresentations <= (1 << kBitsPerByte));
    293 
    294   int8_t kind_;
    295 };
    296 
    297 
    298 class HType {
    299  public:
    300   HType() : type_(kUninitialized) { }
    301 
    302   static HType Tagged() { return HType(kTagged); }
    303   static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
    304   static HType TaggedNumber() { return HType(kTaggedNumber); }
    305   static HType Smi() { return HType(kSmi); }
    306   static HType HeapNumber() { return HType(kHeapNumber); }
    307   static HType String() { return HType(kString); }
    308   static HType Boolean() { return HType(kBoolean); }
    309   static HType NonPrimitive() { return HType(kNonPrimitive); }
    310   static HType JSArray() { return HType(kJSArray); }
    311   static HType JSObject() { return HType(kJSObject); }
    312   static HType Uninitialized() { return HType(kUninitialized); }
    313 
    314   // Return the weakest (least precise) common type.
    315   HType Combine(HType other) {
    316     return HType(static_cast<Type>(type_ & other.type_));
    317   }
    318 
    319   bool Equals(const HType& other) {
    320     return type_ == other.type_;
    321   }
    322 
    323   bool IsSubtypeOf(const HType& other) {
    324     return Combine(other).Equals(other);
    325   }
    326 
    327   bool IsTagged() {
    328     ASSERT(type_ != kUninitialized);
    329     return ((type_ & kTagged) == kTagged);
    330   }
    331 
    332   bool IsTaggedPrimitive() {
    333     ASSERT(type_ != kUninitialized);
    334     return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
    335   }
    336 
    337   bool IsTaggedNumber() {
    338     ASSERT(type_ != kUninitialized);
    339     return ((type_ & kTaggedNumber) == kTaggedNumber);
    340   }
    341 
    342   bool IsSmi() {
    343     ASSERT(type_ != kUninitialized);
    344     return ((type_ & kSmi) == kSmi);
    345   }
    346 
    347   bool IsHeapNumber() {
    348     ASSERT(type_ != kUninitialized);
    349     return ((type_ & kHeapNumber) == kHeapNumber);
    350   }
    351 
    352   bool IsString() {
    353     ASSERT(type_ != kUninitialized);
    354     return ((type_ & kString) == kString);
    355   }
    356 
    357   bool IsBoolean() {
    358     ASSERT(type_ != kUninitialized);
    359     return ((type_ & kBoolean) == kBoolean);
    360   }
    361 
    362   bool IsNonPrimitive() {
    363     ASSERT(type_ != kUninitialized);
    364     return ((type_ & kNonPrimitive) == kNonPrimitive);
    365   }
    366 
    367   bool IsJSArray() {
    368     ASSERT(type_ != kUninitialized);
    369     return ((type_ & kJSArray) == kJSArray);
    370   }
    371 
    372   bool IsJSObject() {
    373     ASSERT(type_ != kUninitialized);
    374     return ((type_ & kJSObject) == kJSObject);
    375   }
    376 
    377   bool IsUninitialized() {
    378     return type_ == kUninitialized;
    379   }
    380 
    381   static HType TypeFromValue(Handle<Object> value);
    382 
    383   const char* ToString();
    384   const char* ToShortString();
    385 
    386  private:
    387   enum Type {
    388     kTagged = 0x1,           // 0000 0000 0000 0001
    389     kTaggedPrimitive = 0x5,  // 0000 0000 0000 0101
    390     kTaggedNumber = 0xd,     // 0000 0000 0000 1101
    391     kSmi = 0x1d,             // 0000 0000 0001 1101
    392     kHeapNumber = 0x2d,      // 0000 0000 0010 1101
    393     kString = 0x45,          // 0000 0000 0100 0101
    394     kBoolean = 0x85,         // 0000 0000 1000 0101
    395     kNonPrimitive = 0x101,   // 0000 0001 0000 0001
    396     kJSObject = 0x301,       // 0000 0011 0000 0001
    397     kJSArray = 0x701,        // 0000 0111 1000 0001
    398     kUninitialized = 0x1fff  // 0001 1111 1111 1111
    399   };
    400 
    401   // Make sure type fits in int16.
    402   STATIC_ASSERT(kUninitialized < (1 << (2 * kBitsPerByte)));
    403 
    404   explicit HType(Type t) : type_(t) { }
    405 
    406   int16_t type_;
    407 };
    408 
    409 
    410 class HValue: public ZoneObject {
    411  public:
    412   static const int kNoNumber = -1;
    413 
    414   // There must be one corresponding kDepends flag for every kChanges flag and
    415   // the order of the kChanges flags must be exactly the same as of the kDepends
    416   // flags.
    417   enum Flag {
    418     // Declare global value numbering flags.
    419   #define DECLARE_DO(type) kChanges##type, kDependsOn##type,
    420     GVN_FLAG_LIST(DECLARE_DO)
    421   #undef DECLARE_DO
    422     kFlexibleRepresentation,
    423     kUseGVN,
    424     kCanOverflow,
    425     kBailoutOnMinusZero,
    426     kCanBeDivByZero,
    427     kDeoptimizeOnUndefined,
    428     kIsArguments,
    429     kTruncatingToInt32,
    430     kLastFlag = kTruncatingToInt32
    431   };
    432 
    433   STATIC_ASSERT(kLastFlag < kBitsPerInt);
    434 
    435   static const int kChangesToDependsFlagsLeftShift = 1;
    436 
    437   static int ChangesFlagsMask() {
    438     int result = 0;
    439     // Create changes mask.
    440 #define DECLARE_DO(type) result |= (1 << kChanges##type);
    441   GVN_FLAG_LIST(DECLARE_DO)
    442 #undef DECLARE_DO
    443     return result;
    444   }
    445 
    446   static int DependsFlagsMask() {
    447     return ConvertChangesToDependsFlags(ChangesFlagsMask());
    448   }
    449 
    450   static int ConvertChangesToDependsFlags(int flags) {
    451     return flags << kChangesToDependsFlagsLeftShift;
    452   }
    453 
    454   static HValue* cast(HValue* value) { return value; }
    455 
    456   enum Opcode {
    457     // Declare a unique enum value for each hydrogen instruction.
    458   #define DECLARE_DO(type) k##type,
    459     HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
    460   #undef DECLARE_DO
    461     kMaxInstructionClass
    462   };
    463 
    464   HValue() : block_(NULL),
    465              id_(kNoNumber),
    466              type_(HType::Tagged()),
    467              range_(NULL),
    468              flags_(0) {}
    469   virtual ~HValue() {}
    470 
    471   HBasicBlock* block() const { return block_; }
    472   void SetBlock(HBasicBlock* block);
    473 
    474   int id() const { return id_; }
    475   void set_id(int id) { id_ = id; }
    476 
    477   SmallPointerList<HValue>* uses() { return &uses_; }
    478 
    479   virtual bool EmitAtUses() { return false; }
    480   Representation representation() const { return representation_; }
    481   void ChangeRepresentation(Representation r) {
    482     // Representation was already set and is allowed to be changed.
    483     ASSERT(!representation_.IsNone());
    484     ASSERT(!r.IsNone());
    485     ASSERT(CheckFlag(kFlexibleRepresentation));
    486     RepresentationChanged(r);
    487     representation_ = r;
    488   }
    489 
    490   HType type() const { return type_; }
    491   void set_type(HType type) {
    492     ASSERT(uses_.length() == 0);
    493     type_ = type;
    494   }
    495 
    496   // An operation needs to override this function iff:
    497   //   1) it can produce an int32 output.
    498   //   2) the true value of its output can potentially be minus zero.
    499   // The implementation must set a flag so that it bails out in the case where
    500   // it would otherwise output what should be a minus zero as an int32 zero.
    501   // If the operation also exists in a form that takes int32 and outputs int32
    502   // then the operation should return its input value so that we can propagate
    503   // back.  There are two operations that need to propagate back to more than
    504   // one input.  They are phi and binary add.  They always return NULL and
    505   // expect the caller to take care of things.
    506   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
    507     visited->Add(id());
    508     return NULL;
    509   }
    510 
    511   bool IsDefinedAfter(HBasicBlock* other) const;
    512 
    513   // Operands.
    514   virtual int OperandCount() = 0;
    515   virtual HValue* OperandAt(int index) = 0;
    516   void SetOperandAt(int index, HValue* value);
    517 
    518   int LookupOperandIndex(int occurrence_index, HValue* op);
    519   bool UsesMultipleTimes(HValue* op);
    520 
    521   void ReplaceAndDelete(HValue* other);
    522   void ReplaceValue(HValue* other);
    523   void ReplaceAtUse(HValue* use, HValue* other);
    524   void ReplaceFirstAtUse(HValue* use, HValue* other, Representation r);
    525   bool HasNoUses() const { return uses_.is_empty(); }
    526   void ClearOperands();
    527   void Delete();
    528 
    529   int flags() const { return flags_; }
    530   void SetFlag(Flag f) { flags_ |= (1 << f); }
    531   void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
    532   bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
    533 
    534   void SetAllSideEffects() { flags_ |= AllSideEffects(); }
    535   void ClearAllSideEffects() { flags_ &= ~AllSideEffects(); }
    536   bool HasSideEffects() const { return (flags_ & AllSideEffects()) != 0; }
    537 
    538   Range* range() const { return range_; }
    539   bool HasRange() const { return range_ != NULL; }
    540   void AddNewRange(Range* r);
    541   void RemoveLastAddedRange();
    542   void ComputeInitialRange();
    543 
    544   // Representation helpers.
    545   virtual Representation RequiredInputRepresentation(int index) const = 0;
    546 
    547   virtual Representation InferredRepresentation() {
    548     return representation();
    549   }
    550 
    551   // This gives the instruction an opportunity to replace itself with an
    552   // instruction that does the same in some better way.  To replace an
    553   // instruction with a new one, first add the new instruction to the graph,
    554   // then return it.  Return NULL to have the instruction deleted.
    555   virtual HValue* Canonicalize() { return this; }
    556 
    557   // Declare virtual type testers.
    558 #define DECLARE_DO(type) virtual bool Is##type() const { return false; }
    559   HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
    560 #undef DECLARE_DO
    561 
    562   bool Equals(HValue* other);
    563   virtual intptr_t Hashcode();
    564 
    565   // Printing support.
    566   virtual void PrintTo(StringStream* stream) = 0;
    567   void PrintNameTo(StringStream* stream);
    568   static void PrintTypeTo(HType type, StringStream* stream);
    569 
    570   virtual const char* Mnemonic() const = 0;
    571   virtual Opcode opcode() const = 0;
    572 
    573   // Updated the inferred type of this instruction and returns true if
    574   // it has changed.
    575   bool UpdateInferredType();
    576 
    577   virtual HType CalculateInferredType();
    578 
    579 #ifdef DEBUG
    580   virtual void Verify() = 0;
    581 #endif
    582 
    583  protected:
    584   // This function must be overridden for instructions with flag kUseGVN, to
    585   // compare the non-Operand parts of the instruction.
    586   virtual bool DataEquals(HValue* other) {
    587     UNREACHABLE();
    588     return false;
    589   }
    590   virtual void RepresentationChanged(Representation to) { }
    591   virtual Range* InferRange();
    592   virtual void DeleteFromGraph() = 0;
    593   virtual void InternalSetOperandAt(int index, HValue* value) = 0;
    594   void clear_block() {
    595     ASSERT(block_ != NULL);
    596     block_ = NULL;
    597   }
    598 
    599   void set_representation(Representation r) {
    600     // Representation is set-once.
    601     ASSERT(representation_.IsNone() && !r.IsNone());
    602     representation_ = r;
    603   }
    604 
    605  private:
    606   // A flag mask to mark an instruction as having arbitrary side effects.
    607   static int AllSideEffects() {
    608     return ChangesFlagsMask() & ~(1 << kChangesOsrEntries);
    609   }
    610 
    611   void InternalReplaceAtUse(HValue* use, HValue* other);
    612   void RegisterUse(int index, HValue* new_value);
    613 
    614   HBasicBlock* block_;
    615 
    616   // The id of this instruction in the hydrogen graph, assigned when first
    617   // added to the graph. Reflects creation order.
    618   int id_;
    619 
    620   Representation representation_;
    621   HType type_;
    622   SmallPointerList<HValue> uses_;
    623   Range* range_;
    624   int flags_;
    625 
    626   DISALLOW_COPY_AND_ASSIGN(HValue);
    627 };
    628 
    629 
    630 class HInstruction: public HValue {
    631  public:
    632   HInstruction* next() const { return next_; }
    633   HInstruction* previous() const { return previous_; }
    634 
    635   virtual void PrintTo(StringStream* stream);
    636   virtual void PrintDataTo(StringStream* stream) { }
    637 
    638   bool IsLinked() const { return block() != NULL; }
    639   void Unlink();
    640   void InsertBefore(HInstruction* next);
    641   void InsertAfter(HInstruction* previous);
    642 
    643   int position() const { return position_; }
    644   bool has_position() const { return position_ != RelocInfo::kNoPosition; }
    645   void set_position(int position) { position_ = position; }
    646 
    647   virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
    648 
    649 #ifdef DEBUG
    650   virtual void Verify();
    651 #endif
    652 
    653   // Returns whether this is some kind of deoptimizing check
    654   // instruction.
    655   virtual bool IsCheckInstruction() const { return false; }
    656 
    657   virtual bool IsCall() { return false; }
    658 
    659   DECLARE_INSTRUCTION(Instruction)
    660 
    661  protected:
    662   HInstruction()
    663       : next_(NULL),
    664         previous_(NULL),
    665         position_(RelocInfo::kNoPosition) {
    666     SetFlag(kDependsOnOsrEntries);
    667   }
    668 
    669   virtual void DeleteFromGraph() { Unlink(); }
    670 
    671  private:
    672   void InitializeAsFirst(HBasicBlock* block) {
    673     ASSERT(!IsLinked());
    674     SetBlock(block);
    675   }
    676 
    677   HInstruction* next_;
    678   HInstruction* previous_;
    679   int position_;
    680 
    681   friend class HBasicBlock;
    682 };
    683 
    684 
    685 class HControlInstruction: public HInstruction {
    686  public:
    687   HControlInstruction(HBasicBlock* first, HBasicBlock* second)
    688       : first_successor_(first), second_successor_(second) {
    689   }
    690 
    691   HBasicBlock* FirstSuccessor() const { return first_successor_; }
    692   HBasicBlock* SecondSuccessor() const { return second_successor_; }
    693 
    694   virtual void PrintDataTo(StringStream* stream);
    695 
    696   DECLARE_INSTRUCTION(ControlInstruction)
    697 
    698  private:
    699   HBasicBlock* first_successor_;
    700   HBasicBlock* second_successor_;
    701 };
    702 
    703 
    704 template<int NumElements>
    705 class HOperandContainer {
    706  public:
    707   HOperandContainer() : elems_() { }
    708 
    709   int length() { return NumElements; }
    710   HValue*& operator[](int i) {
    711     ASSERT(i < length());
    712     return elems_[i];
    713   }
    714 
    715  private:
    716   HValue* elems_[NumElements];
    717 };
    718 
    719 
    720 template<>
    721 class HOperandContainer<0> {
    722  public:
    723   int length() { return 0; }
    724   HValue*& operator[](int i) {
    725     UNREACHABLE();
    726     static HValue* t = 0;
    727     return t;
    728   }
    729 };
    730 
    731 
    732 template<int V>
    733 class HTemplateInstruction : public HInstruction {
    734  public:
    735   int OperandCount() { return V; }
    736   HValue* OperandAt(int i) { return inputs_[i]; }
    737 
    738  protected:
    739   void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
    740 
    741  private:
    742   HOperandContainer<V> inputs_;
    743 };
    744 
    745 
    746 template<int V>
    747 class HTemplateControlInstruction : public HControlInstruction {
    748  public:
    749   HTemplateControlInstruction<V>(HBasicBlock* first, HBasicBlock* second)
    750     : HControlInstruction(first, second) { }
    751   int OperandCount() { return V; }
    752   HValue* OperandAt(int i) { return inputs_[i]; }
    753 
    754  protected:
    755   void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
    756 
    757  private:
    758   HOperandContainer<V> inputs_;
    759 };
    760 
    761 
    762 class HBlockEntry: public HTemplateInstruction<0> {
    763  public:
    764   virtual Representation RequiredInputRepresentation(int index) const {
    765     return Representation::None();
    766   }
    767 
    768   DECLARE_CONCRETE_INSTRUCTION(BlockEntry, "block_entry")
    769 };
    770 
    771 
    772 class HDeoptimize: public HControlInstruction {
    773  public:
    774   explicit HDeoptimize(int environment_length)
    775       : HControlInstruction(NULL, NULL),
    776         values_(environment_length) { }
    777 
    778   virtual Representation RequiredInputRepresentation(int index) const {
    779     return Representation::None();
    780   }
    781 
    782   virtual int OperandCount() { return values_.length(); }
    783   virtual HValue* OperandAt(int index) { return values_[index]; }
    784 
    785   void AddEnvironmentValue(HValue* value) {
    786     values_.Add(NULL);
    787     SetOperandAt(values_.length() - 1, value);
    788   }
    789 
    790   DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
    791 
    792  protected:
    793   virtual void InternalSetOperandAt(int index, HValue* value) {
    794     values_[index] = value;
    795   }
    796 
    797  private:
    798   ZoneList<HValue*> values_;
    799 };
    800 
    801 
    802 class HGoto: public HTemplateControlInstruction<0> {
    803  public:
    804   explicit HGoto(HBasicBlock* target)
    805       : HTemplateControlInstruction<0>(target, NULL),
    806         include_stack_check_(false) { }
    807 
    808   void set_include_stack_check(bool include_stack_check) {
    809     include_stack_check_ = include_stack_check;
    810   }
    811   bool include_stack_check() const { return include_stack_check_; }
    812 
    813   virtual Representation RequiredInputRepresentation(int index) const {
    814     return Representation::None();
    815   }
    816 
    817   DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
    818 
    819  private:
    820   bool include_stack_check_;
    821 };
    822 
    823 
    824 class HUnaryControlInstruction: public HTemplateControlInstruction<1> {
    825  public:
    826   explicit HUnaryControlInstruction(HValue* value,
    827                                     HBasicBlock* true_target,
    828                                     HBasicBlock* false_target)
    829       : HTemplateControlInstruction<1>(true_target, false_target) {
    830     SetOperandAt(0, value);
    831   }
    832 
    833   virtual void PrintDataTo(StringStream* stream);
    834 
    835   HValue* value() { return OperandAt(0); }
    836 
    837   DECLARE_INSTRUCTION(UnaryControlInstruction)
    838 };
    839 
    840 
    841 class HTest: public HUnaryControlInstruction {
    842  public:
    843   HTest(HValue* value, HBasicBlock* true_target, HBasicBlock* false_target)
    844       : HUnaryControlInstruction(value, true_target, false_target) {
    845     ASSERT(true_target != NULL && false_target != NULL);
    846   }
    847 
    848   virtual Representation RequiredInputRepresentation(int index) const {
    849     return Representation::None();
    850   }
    851 
    852   DECLARE_CONCRETE_INSTRUCTION(Test, "test")
    853 };
    854 
    855 
    856 class HCompareMap: public HUnaryControlInstruction {
    857  public:
    858   HCompareMap(HValue* value,
    859               Handle<Map> map,
    860               HBasicBlock* true_target,
    861               HBasicBlock* false_target)
    862       : HUnaryControlInstruction(value, true_target, false_target),
    863         map_(map) {
    864     ASSERT(true_target != NULL);
    865     ASSERT(false_target != NULL);
    866     ASSERT(!map.is_null());
    867   }
    868 
    869   virtual void PrintDataTo(StringStream* stream);
    870 
    871   Handle<Map> map() const { return map_; }
    872 
    873   virtual Representation RequiredInputRepresentation(int index) const {
    874     return Representation::Tagged();
    875   }
    876 
    877   DECLARE_CONCRETE_INSTRUCTION(CompareMap, "compare_map")
    878 
    879  private:
    880   Handle<Map> map_;
    881 };
    882 
    883 
    884 class HReturn: public HUnaryControlInstruction {
    885  public:
    886   explicit HReturn(HValue* value)
    887       : HUnaryControlInstruction(value, NULL, NULL) {
    888   }
    889 
    890   virtual Representation RequiredInputRepresentation(int index) const {
    891     return Representation::Tagged();
    892   }
    893 
    894   DECLARE_CONCRETE_INSTRUCTION(Return, "return")
    895 };
    896 
    897 
    898 class HAbnormalExit: public HTemplateControlInstruction<0> {
    899  public:
    900   HAbnormalExit() : HTemplateControlInstruction<0>(NULL, NULL) { }
    901 
    902   virtual Representation RequiredInputRepresentation(int index) const {
    903     return Representation::None();
    904   }
    905 
    906   DECLARE_CONCRETE_INSTRUCTION(AbnormalExit, "abnormal_exit")
    907 };
    908 
    909 
    910 class HUnaryOperation: public HTemplateInstruction<1> {
    911  public:
    912   explicit HUnaryOperation(HValue* value) {
    913     SetOperandAt(0, value);
    914   }
    915 
    916   HValue* value() { return OperandAt(0); }
    917   virtual void PrintDataTo(StringStream* stream);
    918 
    919   DECLARE_INSTRUCTION(UnaryOperation)
    920 };
    921 
    922 
    923 class HThrow: public HUnaryOperation {
    924  public:
    925   explicit HThrow(HValue* value) : HUnaryOperation(value) {
    926     SetAllSideEffects();
    927   }
    928 
    929   virtual Representation RequiredInputRepresentation(int index) const {
    930     return Representation::Tagged();
    931   }
    932 
    933   DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
    934 };
    935 
    936 
    937 class HChange: public HUnaryOperation {
    938  public:
    939   HChange(HValue* value,
    940           Representation from,
    941           Representation to,
    942           bool is_truncating,
    943           bool deoptimize_on_undefined)
    944       : HUnaryOperation(value),
    945         from_(from),
    946         deoptimize_on_undefined_(deoptimize_on_undefined) {
    947     ASSERT(!from.IsNone() && !to.IsNone());
    948     ASSERT(!from.Equals(to));
    949     set_representation(to);
    950     SetFlag(kUseGVN);
    951     if (is_truncating) SetFlag(kTruncatingToInt32);
    952     if (from.IsInteger32() && to.IsTagged() && value->range() != NULL &&
    953         value->range()->IsInSmiRange()) {
    954       set_type(HType::Smi());
    955     }
    956   }
    957 
    958   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
    959 
    960   Representation from() const { return from_; }
    961   Representation to() const { return representation(); }
    962   bool deoptimize_on_undefined() const { return deoptimize_on_undefined_; }
    963   virtual Representation RequiredInputRepresentation(int index) const {
    964     return from_;
    965   }
    966 
    967   bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
    968 
    969   virtual void PrintDataTo(StringStream* stream);
    970 
    971   DECLARE_CONCRETE_INSTRUCTION(Change,
    972                                CanTruncateToInt32() ? "truncate" : "change")
    973 
    974  protected:
    975   virtual bool DataEquals(HValue* other) {
    976     if (!other->IsChange()) return false;
    977     HChange* change = HChange::cast(other);
    978     return value() == change->value()
    979         && to().Equals(change->to())
    980         && deoptimize_on_undefined() == change->deoptimize_on_undefined();
    981   }
    982 
    983  private:
    984   Representation from_;
    985   bool deoptimize_on_undefined_;
    986 };
    987 
    988 
    989 class HSimulate: public HInstruction {
    990  public:
    991   HSimulate(int ast_id, int pop_count)
    992       : ast_id_(ast_id),
    993         pop_count_(pop_count),
    994         values_(2),
    995         assigned_indexes_(2) {}
    996   virtual ~HSimulate() {}
    997 
    998   virtual void PrintDataTo(StringStream* stream);
    999 
   1000   bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; }
   1001   int ast_id() const { return ast_id_; }
   1002   void set_ast_id(int id) {
   1003     ASSERT(!HasAstId());
   1004     ast_id_ = id;
   1005   }
   1006 
   1007   int pop_count() const { return pop_count_; }
   1008   const ZoneList<HValue*>* values() const { return &values_; }
   1009   int GetAssignedIndexAt(int index) const {
   1010     ASSERT(HasAssignedIndexAt(index));
   1011     return assigned_indexes_[index];
   1012   }
   1013   bool HasAssignedIndexAt(int index) const {
   1014     return assigned_indexes_[index] != kNoIndex;
   1015   }
   1016   void AddAssignedValue(int index, HValue* value) {
   1017     AddValue(index, value);
   1018   }
   1019   void AddPushedValue(HValue* value) {
   1020     AddValue(kNoIndex, value);
   1021   }
   1022   virtual int OperandCount() { return values_.length(); }
   1023   virtual HValue* OperandAt(int index) { return values_[index]; }
   1024 
   1025   virtual Representation RequiredInputRepresentation(int index) const {
   1026     return Representation::None();
   1027   }
   1028 
   1029   DECLARE_CONCRETE_INSTRUCTION(Simulate, "simulate")
   1030 
   1031 #ifdef DEBUG
   1032   virtual void Verify();
   1033 #endif
   1034 
   1035  protected:
   1036   virtual void InternalSetOperandAt(int index, HValue* value) {
   1037     values_[index] = value;
   1038   }
   1039 
   1040  private:
   1041   static const int kNoIndex = -1;
   1042   void AddValue(int index, HValue* value) {
   1043     assigned_indexes_.Add(index);
   1044     // Resize the list of pushed values.
   1045     values_.Add(NULL);
   1046     // Set the operand through the base method in HValue to make sure that the
   1047     // use lists are correctly updated.
   1048     SetOperandAt(values_.length() - 1, value);
   1049   }
   1050   int ast_id_;
   1051   int pop_count_;
   1052   ZoneList<HValue*> values_;
   1053   ZoneList<int> assigned_indexes_;
   1054 };
   1055 
   1056 
   1057 class HStackCheck: public HTemplateInstruction<0> {
   1058  public:
   1059   HStackCheck() { }
   1060 
   1061   virtual Representation RequiredInputRepresentation(int index) const {
   1062     return Representation::None();
   1063   }
   1064 
   1065   DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack_check")
   1066 };
   1067 
   1068 
   1069 class HEnterInlined: public HTemplateInstruction<0> {
   1070  public:
   1071   HEnterInlined(Handle<JSFunction> closure, FunctionLiteral* function)
   1072       : closure_(closure), function_(function) {
   1073   }
   1074 
   1075   virtual void PrintDataTo(StringStream* stream);
   1076 
   1077   Handle<JSFunction> closure() const { return closure_; }
   1078   FunctionLiteral* function() const { return function_; }
   1079 
   1080   virtual Representation RequiredInputRepresentation(int index) const {
   1081     return Representation::None();
   1082   }
   1083 
   1084   DECLARE_CONCRETE_INSTRUCTION(EnterInlined, "enter_inlined")
   1085 
   1086  private:
   1087   Handle<JSFunction> closure_;
   1088   FunctionLiteral* function_;
   1089 };
   1090 
   1091 
   1092 class HLeaveInlined: public HTemplateInstruction<0> {
   1093  public:
   1094   HLeaveInlined() {}
   1095 
   1096   virtual Representation RequiredInputRepresentation(int index) const {
   1097     return Representation::None();
   1098   }
   1099 
   1100   DECLARE_CONCRETE_INSTRUCTION(LeaveInlined, "leave_inlined")
   1101 };
   1102 
   1103 
   1104 class HPushArgument: public HUnaryOperation {
   1105  public:
   1106   explicit HPushArgument(HValue* value) : HUnaryOperation(value) {
   1107     set_representation(Representation::Tagged());
   1108   }
   1109 
   1110   virtual Representation RequiredInputRepresentation(int index) const {
   1111     return Representation::Tagged();
   1112   }
   1113 
   1114   HValue* argument() { return OperandAt(0); }
   1115 
   1116   DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push_argument")
   1117 };
   1118 
   1119 
   1120 class HContext: public HTemplateInstruction<0> {
   1121  public:
   1122   HContext() {
   1123     set_representation(Representation::Tagged());
   1124     SetFlag(kUseGVN);
   1125   }
   1126 
   1127   virtual Representation RequiredInputRepresentation(int index) const {
   1128     return Representation::None();
   1129   }
   1130 
   1131   DECLARE_CONCRETE_INSTRUCTION(Context, "context");
   1132 
   1133  protected:
   1134   virtual bool DataEquals(HValue* other) { return true; }
   1135 };
   1136 
   1137 
   1138 class HOuterContext: public HUnaryOperation {
   1139  public:
   1140   explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
   1141     set_representation(Representation::Tagged());
   1142     SetFlag(kUseGVN);
   1143   }
   1144 
   1145   DECLARE_CONCRETE_INSTRUCTION(OuterContext, "outer_context");
   1146 
   1147   virtual Representation RequiredInputRepresentation(int index) const {
   1148     return Representation::Tagged();
   1149   }
   1150 
   1151  protected:
   1152   virtual bool DataEquals(HValue* other) { return true; }
   1153 };
   1154 
   1155 
   1156 class HGlobalObject: public HUnaryOperation {
   1157  public:
   1158   explicit HGlobalObject(HValue* context) : HUnaryOperation(context) {
   1159     set_representation(Representation::Tagged());
   1160     SetFlag(kUseGVN);
   1161   }
   1162 
   1163   DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global_object")
   1164 
   1165   virtual Representation RequiredInputRepresentation(int index) const {
   1166     return Representation::Tagged();
   1167   }
   1168 
   1169  protected:
   1170   virtual bool DataEquals(HValue* other) { return true; }
   1171 };
   1172 
   1173 
   1174 class HGlobalReceiver: public HUnaryOperation {
   1175  public:
   1176   explicit HGlobalReceiver(HValue* global_object)
   1177       : HUnaryOperation(global_object) {
   1178     set_representation(Representation::Tagged());
   1179     SetFlag(kUseGVN);
   1180   }
   1181 
   1182   DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global_receiver")
   1183 
   1184   virtual Representation RequiredInputRepresentation(int index) const {
   1185     return Representation::Tagged();
   1186   }
   1187 
   1188  protected:
   1189   virtual bool DataEquals(HValue* other) { return true; }
   1190 };
   1191 
   1192 
   1193 template <int V>
   1194 class HCall: public HTemplateInstruction<V> {
   1195  public:
   1196   // The argument count includes the receiver.
   1197   explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
   1198     this->set_representation(Representation::Tagged());
   1199     this->SetAllSideEffects();
   1200   }
   1201 
   1202   virtual HType CalculateInferredType() { return HType::Tagged(); }
   1203 
   1204   virtual int argument_count() const { return argument_count_; }
   1205 
   1206   virtual bool IsCall() { return true; }
   1207 
   1208  private:
   1209   int argument_count_;
   1210 };
   1211 
   1212 
   1213 class HUnaryCall: public HCall<1> {
   1214  public:
   1215   HUnaryCall(HValue* value, int argument_count)
   1216       : HCall<1>(argument_count) {
   1217     SetOperandAt(0, value);
   1218   }
   1219 
   1220   virtual Representation RequiredInputRepresentation(int index) const {
   1221     return Representation::Tagged();
   1222   }
   1223 
   1224   virtual void PrintDataTo(StringStream* stream);
   1225 
   1226   HValue* value() { return OperandAt(0); }
   1227 
   1228   DECLARE_INSTRUCTION(UnaryCall)
   1229 };
   1230 
   1231 
   1232 class HBinaryCall: public HCall<2> {
   1233  public:
   1234   HBinaryCall(HValue* first, HValue* second, int argument_count)
   1235       : HCall<2>(argument_count) {
   1236     SetOperandAt(0, first);
   1237     SetOperandAt(1, second);
   1238   }
   1239 
   1240   virtual void PrintDataTo(StringStream* stream);
   1241 
   1242   virtual Representation RequiredInputRepresentation(int index) const {
   1243     return Representation::Tagged();
   1244   }
   1245 
   1246   HValue* first() { return OperandAt(0); }
   1247   HValue* second() { return OperandAt(1); }
   1248 
   1249   DECLARE_INSTRUCTION(BinaryCall)
   1250 };
   1251 
   1252 
   1253 class HCallConstantFunction: public HCall<0> {
   1254  public:
   1255   HCallConstantFunction(Handle<JSFunction> function, int argument_count)
   1256       : HCall<0>(argument_count), function_(function) { }
   1257 
   1258   Handle<JSFunction> function() const { return function_; }
   1259 
   1260   bool IsApplyFunction() const {
   1261     return function_->code() ==
   1262         Isolate::Current()->builtins()->builtin(Builtins::kFunctionApply);
   1263   }
   1264 
   1265   virtual void PrintDataTo(StringStream* stream);
   1266 
   1267   virtual Representation RequiredInputRepresentation(int index) const {
   1268     return Representation::None();
   1269   }
   1270 
   1271   DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call_constant_function")
   1272 
   1273  private:
   1274   Handle<JSFunction> function_;
   1275 };
   1276 
   1277 
   1278 class HCallKeyed: public HBinaryCall {
   1279  public:
   1280   HCallKeyed(HValue* context, HValue* key, int argument_count)
   1281       : HBinaryCall(context, key, argument_count) {
   1282   }
   1283 
   1284   virtual Representation RequiredInputRepresentation(int index) const {
   1285     return Representation::Tagged();
   1286   }
   1287 
   1288   HValue* context() { return first(); }
   1289   HValue* key() { return second(); }
   1290 
   1291   DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed")
   1292 };
   1293 
   1294 
   1295 class HCallNamed: public HUnaryCall {
   1296  public:
   1297   HCallNamed(HValue* context, Handle<String> name, int argument_count)
   1298       : HUnaryCall(context, argument_count), name_(name) {
   1299   }
   1300 
   1301   virtual void PrintDataTo(StringStream* stream);
   1302 
   1303   HValue* context() { return value(); }
   1304   Handle<String> name() const { return name_; }
   1305 
   1306   DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named")
   1307 
   1308   virtual Representation RequiredInputRepresentation(int index) const {
   1309     return Representation::Tagged();
   1310   }
   1311 
   1312  private:
   1313   Handle<String> name_;
   1314 };
   1315 
   1316 
   1317 class HCallFunction: public HUnaryCall {
   1318  public:
   1319   HCallFunction(HValue* context, int argument_count)
   1320       : HUnaryCall(context, argument_count) {
   1321   }
   1322 
   1323   HValue* context() { return value(); }
   1324 
   1325   virtual Representation RequiredInputRepresentation(int index) const {
   1326     return Representation::Tagged();
   1327   }
   1328 
   1329   DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function")
   1330 };
   1331 
   1332 
   1333 class HCallGlobal: public HUnaryCall {
   1334  public:
   1335   HCallGlobal(HValue* context, Handle<String> name, int argument_count)
   1336       : HUnaryCall(context, argument_count), name_(name) {
   1337   }
   1338 
   1339   virtual void PrintDataTo(StringStream* stream);
   1340 
   1341   HValue* context() { return value(); }
   1342   Handle<String> name() const { return name_; }
   1343 
   1344   virtual Representation RequiredInputRepresentation(int index) const {
   1345     return Representation::Tagged();
   1346   }
   1347 
   1348   DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global")
   1349 
   1350  private:
   1351   Handle<String> name_;
   1352 };
   1353 
   1354 
   1355 class HCallKnownGlobal: public HCall<0> {
   1356  public:
   1357   HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
   1358       : HCall<0>(argument_count), target_(target) { }
   1359 
   1360   virtual void PrintDataTo(StringStream* stream);
   1361 
   1362   Handle<JSFunction> target() const { return target_; }
   1363 
   1364   virtual Representation RequiredInputRepresentation(int index) const {
   1365     return Representation::None();
   1366   }
   1367 
   1368   DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global")
   1369 
   1370  private:
   1371   Handle<JSFunction> target_;
   1372 };
   1373 
   1374 
   1375 class HCallNew: public HBinaryCall {
   1376  public:
   1377   HCallNew(HValue* context, HValue* constructor, int argument_count)
   1378       : HBinaryCall(context, constructor, argument_count) {
   1379   }
   1380 
   1381   virtual Representation RequiredInputRepresentation(int index) const {
   1382     return Representation::Tagged();
   1383   }
   1384 
   1385   HValue* context() { return first(); }
   1386   HValue* constructor() { return second(); }
   1387 
   1388   DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new")
   1389 };
   1390 
   1391 
   1392 class HCallRuntime: public HCall<0> {
   1393  public:
   1394   HCallRuntime(Handle<String> name,
   1395                const Runtime::Function* c_function,
   1396                int argument_count)
   1397       : HCall<0>(argument_count), c_function_(c_function), name_(name) { }
   1398   virtual void PrintDataTo(StringStream* stream);
   1399 
   1400   const Runtime::Function* function() const { return c_function_; }
   1401   Handle<String> name() const { return name_; }
   1402 
   1403   virtual Representation RequiredInputRepresentation(int index) const {
   1404     return Representation::None();
   1405   }
   1406 
   1407   DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call_runtime")
   1408 
   1409  private:
   1410   const Runtime::Function* c_function_;
   1411   Handle<String> name_;
   1412 };
   1413 
   1414 
   1415 class HJSArrayLength: public HUnaryOperation {
   1416  public:
   1417   explicit HJSArrayLength(HValue* value) : HUnaryOperation(value) {
   1418     // The length of an array is stored as a tagged value in the array
   1419     // object. It is guaranteed to be 32 bit integer, but it can be
   1420     // represented as either a smi or heap number.
   1421     set_representation(Representation::Tagged());
   1422     SetFlag(kUseGVN);
   1423     SetFlag(kDependsOnArrayLengths);
   1424     SetFlag(kDependsOnMaps);
   1425   }
   1426 
   1427   virtual Representation RequiredInputRepresentation(int index) const {
   1428     return Representation::Tagged();
   1429   }
   1430 
   1431   DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js_array_length")
   1432 
   1433  protected:
   1434   virtual bool DataEquals(HValue* other) { return true; }
   1435 };
   1436 
   1437 
   1438 class HFixedArrayLength: public HUnaryOperation {
   1439  public:
   1440   explicit HFixedArrayLength(HValue* value) : HUnaryOperation(value) {
   1441     set_representation(Representation::Tagged());
   1442     SetFlag(kUseGVN);
   1443     SetFlag(kDependsOnArrayLengths);
   1444   }
   1445 
   1446   virtual Representation RequiredInputRepresentation(int index) const {
   1447     return Representation::Tagged();
   1448   }
   1449 
   1450   DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed_array_length")
   1451 
   1452  protected:
   1453   virtual bool DataEquals(HValue* other) { return true; }
   1454 };
   1455 
   1456 
   1457 class HExternalArrayLength: public HUnaryOperation {
   1458  public:
   1459   explicit HExternalArrayLength(HValue* value) : HUnaryOperation(value) {
   1460     set_representation(Representation::Integer32());
   1461     // The result of this instruction is idempotent as long as its inputs don't
   1462     // change.  The length of a pixel array cannot change once set, so it's not
   1463     // necessary to introduce a kDependsOnArrayLengths or any other dependency.
   1464     SetFlag(kUseGVN);
   1465   }
   1466 
   1467   virtual Representation RequiredInputRepresentation(int index) const {
   1468     return Representation::Tagged();
   1469   }
   1470 
   1471   DECLARE_CONCRETE_INSTRUCTION(ExternalArrayLength, "external_array_length")
   1472 
   1473  protected:
   1474   virtual bool DataEquals(HValue* other) { return true; }
   1475 };
   1476 
   1477 
   1478 class HBitNot: public HUnaryOperation {
   1479  public:
   1480   explicit HBitNot(HValue* value) : HUnaryOperation(value) {
   1481     set_representation(Representation::Integer32());
   1482     SetFlag(kUseGVN);
   1483     SetFlag(kTruncatingToInt32);
   1484   }
   1485 
   1486   virtual Representation RequiredInputRepresentation(int index) const {
   1487     return Representation::Integer32();
   1488   }
   1489   virtual HType CalculateInferredType();
   1490 
   1491   DECLARE_CONCRETE_INSTRUCTION(BitNot, "bit_not")
   1492 
   1493  protected:
   1494   virtual bool DataEquals(HValue* other) { return true; }
   1495 };
   1496 
   1497 
   1498 class HUnaryMathOperation: public HUnaryOperation {
   1499  public:
   1500   HUnaryMathOperation(HValue* value, BuiltinFunctionId op)
   1501       : HUnaryOperation(value), op_(op) {
   1502     switch (op) {
   1503       case kMathFloor:
   1504       case kMathRound:
   1505       case kMathCeil:
   1506         set_representation(Representation::Integer32());
   1507         break;
   1508       case kMathAbs:
   1509         set_representation(Representation::Tagged());
   1510         SetFlag(kFlexibleRepresentation);
   1511         break;
   1512       case kMathSqrt:
   1513       case kMathPowHalf:
   1514       case kMathLog:
   1515       case kMathSin:
   1516       case kMathCos:
   1517         set_representation(Representation::Double());
   1518         break;
   1519       default:
   1520         UNREACHABLE();
   1521     }
   1522     SetFlag(kUseGVN);
   1523   }
   1524 
   1525   virtual void PrintDataTo(StringStream* stream);
   1526 
   1527   virtual HType CalculateInferredType();
   1528 
   1529   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
   1530 
   1531   virtual Representation RequiredInputRepresentation(int index) const {
   1532     switch (op_) {
   1533       case kMathFloor:
   1534       case kMathRound:
   1535       case kMathCeil:
   1536       case kMathSqrt:
   1537       case kMathPowHalf:
   1538       case kMathLog:
   1539       case kMathSin:
   1540       case kMathCos:
   1541         return Representation::Double();
   1542       case kMathAbs:
   1543         return representation();
   1544       default:
   1545         UNREACHABLE();
   1546         return Representation::None();
   1547     }
   1548   }
   1549 
   1550   virtual HValue* Canonicalize() {
   1551     // If the input is integer32 then we replace the floor instruction
   1552     // with its inputs.  This happens before the representation changes are
   1553     // introduced.
   1554     if (op() == kMathFloor) {
   1555       if (value()->representation().IsInteger32()) return value();
   1556     }
   1557     return this;
   1558   }
   1559 
   1560   BuiltinFunctionId op() const { return op_; }
   1561   const char* OpName() const;
   1562 
   1563   DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary_math_operation")
   1564 
   1565  protected:
   1566   virtual bool DataEquals(HValue* other) {
   1567     HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
   1568     return op_ == b->op();
   1569   }
   1570 
   1571  private:
   1572   BuiltinFunctionId op_;
   1573 };
   1574 
   1575 
   1576 class HLoadElements: public HUnaryOperation {
   1577  public:
   1578   explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
   1579     set_representation(Representation::Tagged());
   1580     SetFlag(kUseGVN);
   1581     SetFlag(kDependsOnMaps);
   1582   }
   1583 
   1584   virtual Representation RequiredInputRepresentation(int index) const {
   1585     return Representation::Tagged();
   1586   }
   1587 
   1588   DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements")
   1589 
   1590  protected:
   1591   virtual bool DataEquals(HValue* other) { return true; }
   1592 };
   1593 
   1594 
   1595 class HLoadExternalArrayPointer: public HUnaryOperation {
   1596  public:
   1597   explicit HLoadExternalArrayPointer(HValue* value)
   1598       : HUnaryOperation(value) {
   1599     set_representation(Representation::External());
   1600     // The result of this instruction is idempotent as long as its inputs don't
   1601     // change.  The external array of a specialized array elements object cannot
   1602     // change once set, so it's no necessary to introduce any additional
   1603     // dependencies on top of the inputs.
   1604     SetFlag(kUseGVN);
   1605   }
   1606 
   1607   virtual Representation RequiredInputRepresentation(int index) const {
   1608     return Representation::Tagged();
   1609   }
   1610 
   1611   DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer,
   1612                                "load-external-array-pointer")
   1613 
   1614  protected:
   1615   virtual bool DataEquals(HValue* other) { return true; }
   1616 };
   1617 
   1618 
   1619 class HCheckMap: public HUnaryOperation {
   1620  public:
   1621   HCheckMap(HValue* value, Handle<Map> map)
   1622       : HUnaryOperation(value), map_(map) {
   1623     set_representation(Representation::Tagged());
   1624     SetFlag(kUseGVN);
   1625     SetFlag(kDependsOnMaps);
   1626   }
   1627 
   1628   virtual bool IsCheckInstruction() const { return true; }
   1629 
   1630   virtual Representation RequiredInputRepresentation(int index) const {
   1631     return Representation::Tagged();
   1632   }
   1633   virtual void PrintDataTo(StringStream* stream);
   1634   virtual HType CalculateInferredType();
   1635 
   1636 #ifdef DEBUG
   1637   virtual void Verify();
   1638 #endif
   1639 
   1640   Handle<Map> map() const { return map_; }
   1641 
   1642   DECLARE_CONCRETE_INSTRUCTION(CheckMap, "check_map")
   1643 
   1644  protected:
   1645   virtual bool DataEquals(HValue* other) {
   1646     HCheckMap* b = HCheckMap::cast(other);
   1647     return map_.is_identical_to(b->map());
   1648   }
   1649 
   1650  private:
   1651   Handle<Map> map_;
   1652 };
   1653 
   1654 
   1655 class HCheckFunction: public HUnaryOperation {
   1656  public:
   1657   HCheckFunction(HValue* value, Handle<JSFunction> function)
   1658       : HUnaryOperation(value), target_(function) {
   1659     set_representation(Representation::Tagged());
   1660     SetFlag(kUseGVN);
   1661   }
   1662 
   1663   virtual bool IsCheckInstruction() const { return true; }
   1664 
   1665   virtual Representation RequiredInputRepresentation(int index) const {
   1666     return Representation::Tagged();
   1667   }
   1668   virtual void PrintDataTo(StringStream* stream);
   1669   virtual HType CalculateInferredType();
   1670 
   1671 #ifdef DEBUG
   1672   virtual void Verify();
   1673 #endif
   1674 
   1675   Handle<JSFunction> target() const { return target_; }
   1676 
   1677   DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check_function")
   1678 
   1679  protected:
   1680   virtual bool DataEquals(HValue* other) {
   1681     HCheckFunction* b = HCheckFunction::cast(other);
   1682     return target_.is_identical_to(b->target());
   1683   }
   1684 
   1685  private:
   1686   Handle<JSFunction> target_;
   1687 };
   1688 
   1689 
   1690 class HCheckInstanceType: public HUnaryOperation {
   1691  public:
   1692   // Check that the instance type is in the range [first, last] where
   1693   // both first and last are included.
   1694   HCheckInstanceType(HValue* value, InstanceType first, InstanceType last)
   1695       : HUnaryOperation(value), first_(first), last_(last) {
   1696     ASSERT(first <= last);
   1697     set_representation(Representation::Tagged());
   1698     SetFlag(kUseGVN);
   1699     if ((FIRST_STRING_TYPE < first && last <= LAST_STRING_TYPE) ||
   1700         (FIRST_STRING_TYPE <= first && last < LAST_STRING_TYPE)) {
   1701       // A particular string instance type can change because of GC or
   1702       // externalization, but the value still remains a string.
   1703       SetFlag(kDependsOnMaps);
   1704     }
   1705   }
   1706 
   1707   virtual bool IsCheckInstruction() const { return true; }
   1708 
   1709   virtual Representation RequiredInputRepresentation(int index) const {
   1710     return Representation::Tagged();
   1711   }
   1712 
   1713 #ifdef DEBUG
   1714   virtual void Verify();
   1715 #endif
   1716 
   1717   static HCheckInstanceType* NewIsJSObjectOrJSFunction(HValue* value);
   1718 
   1719   InstanceType first() const { return first_; }
   1720   InstanceType last() const { return last_; }
   1721 
   1722   DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check_instance_type")
   1723 
   1724  protected:
   1725   // TODO(ager): It could be nice to allow the ommision of instance
   1726   // type checks if we have already performed an instance type check
   1727   // with a larger range.
   1728   virtual bool DataEquals(HValue* other) {
   1729     HCheckInstanceType* b = HCheckInstanceType::cast(other);
   1730     return (first_ == b->first()) && (last_ == b->last());
   1731   }
   1732 
   1733  private:
   1734   InstanceType first_;
   1735   InstanceType last_;
   1736 };
   1737 
   1738 
   1739 class HCheckNonSmi: public HUnaryOperation {
   1740  public:
   1741   explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
   1742     set_representation(Representation::Tagged());
   1743     SetFlag(kUseGVN);
   1744   }
   1745 
   1746   virtual bool IsCheckInstruction() const { return true; }
   1747 
   1748   virtual Representation RequiredInputRepresentation(int index) const {
   1749     return Representation::Tagged();
   1750   }
   1751 
   1752   virtual HType CalculateInferredType();
   1753 
   1754 #ifdef DEBUG
   1755   virtual void Verify();
   1756 #endif
   1757 
   1758   DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check_non_smi")
   1759 
   1760  protected:
   1761   virtual bool DataEquals(HValue* other) { return true; }
   1762 };
   1763 
   1764 
   1765 class HCheckPrototypeMaps: public HTemplateInstruction<0> {
   1766  public:
   1767   HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
   1768       : prototype_(prototype), holder_(holder) {
   1769     SetFlag(kUseGVN);
   1770     SetFlag(kDependsOnMaps);
   1771   }
   1772 
   1773   virtual bool IsCheckInstruction() const { return true; }
   1774 
   1775 #ifdef DEBUG
   1776   virtual void Verify();
   1777 #endif
   1778 
   1779   Handle<JSObject> prototype() const { return prototype_; }
   1780   Handle<JSObject> holder() const { return holder_; }
   1781 
   1782   DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check_prototype_maps")
   1783 
   1784   virtual Representation RequiredInputRepresentation(int index) const {
   1785     return Representation::None();
   1786   }
   1787 
   1788   virtual intptr_t Hashcode() {
   1789     ASSERT(!HEAP->IsAllocationAllowed());
   1790     intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
   1791     hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
   1792     return hash;
   1793   }
   1794 
   1795  protected:
   1796   virtual bool DataEquals(HValue* other) {
   1797     HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
   1798     return prototype_.is_identical_to(b->prototype()) &&
   1799         holder_.is_identical_to(b->holder());
   1800   }
   1801 
   1802  private:
   1803   Handle<JSObject> prototype_;
   1804   Handle<JSObject> holder_;
   1805 };
   1806 
   1807 
   1808 class HCheckSmi: public HUnaryOperation {
   1809  public:
   1810   explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
   1811     set_representation(Representation::Tagged());
   1812     SetFlag(kUseGVN);
   1813   }
   1814 
   1815   virtual bool IsCheckInstruction() const { return true; }
   1816 
   1817   virtual Representation RequiredInputRepresentation(int index) const {
   1818     return Representation::Tagged();
   1819   }
   1820   virtual HType CalculateInferredType();
   1821 
   1822 #ifdef DEBUG
   1823   virtual void Verify();
   1824 #endif
   1825 
   1826   DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check_smi")
   1827 
   1828  protected:
   1829   virtual bool DataEquals(HValue* other) { return true; }
   1830 };
   1831 
   1832 
   1833 class HPhi: public HValue {
   1834  public:
   1835   explicit HPhi(int merged_index)
   1836       : inputs_(2),
   1837         merged_index_(merged_index),
   1838         phi_id_(-1),
   1839         is_live_(false) {
   1840     for (int i = 0; i < Representation::kNumRepresentations; i++) {
   1841       non_phi_uses_[i] = 0;
   1842       indirect_uses_[i] = 0;
   1843     }
   1844     ASSERT(merged_index >= 0);
   1845     set_representation(Representation::Tagged());
   1846     SetFlag(kFlexibleRepresentation);
   1847   }
   1848 
   1849   virtual Representation InferredRepresentation() {
   1850     bool double_occurred = false;
   1851     bool int32_occurred = false;
   1852     for (int i = 0; i < OperandCount(); ++i) {
   1853       HValue* value = OperandAt(i);
   1854       if (value->representation().IsDouble()) double_occurred = true;
   1855       if (value->representation().IsInteger32()) int32_occurred = true;
   1856       if (value->representation().IsTagged()) return Representation::Tagged();
   1857     }
   1858 
   1859     if (double_occurred) return Representation::Double();
   1860     if (int32_occurred) return Representation::Integer32();
   1861     return Representation::None();
   1862   }
   1863 
   1864   virtual Range* InferRange();
   1865   virtual Representation RequiredInputRepresentation(int index) const {
   1866     return representation();
   1867   }
   1868   virtual HType CalculateInferredType();
   1869   virtual int OperandCount() { return inputs_.length(); }
   1870   virtual HValue* OperandAt(int index) { return inputs_[index]; }
   1871   HValue* GetRedundantReplacement();
   1872   void AddInput(HValue* value);
   1873   bool HasRealUses();
   1874 
   1875   bool IsReceiver() { return merged_index_ == 0; }
   1876 
   1877   int merged_index() const { return merged_index_; }
   1878 
   1879   virtual const char* Mnemonic() const { return "phi"; }
   1880 
   1881   virtual void PrintTo(StringStream* stream);
   1882 
   1883 #ifdef DEBUG
   1884   virtual void Verify();
   1885 #endif
   1886 
   1887   DECLARE_INSTRUCTION(Phi)
   1888 
   1889   void InitRealUses(int id);
   1890   void AddNonPhiUsesFrom(HPhi* other);
   1891   void AddIndirectUsesTo(int* use_count);
   1892 
   1893   int tagged_non_phi_uses() const {
   1894     return non_phi_uses_[Representation::kTagged];
   1895   }
   1896   int int32_non_phi_uses() const {
   1897     return non_phi_uses_[Representation::kInteger32];
   1898   }
   1899   int double_non_phi_uses() const {
   1900     return non_phi_uses_[Representation::kDouble];
   1901   }
   1902   int tagged_indirect_uses() const {
   1903     return indirect_uses_[Representation::kTagged];
   1904   }
   1905   int int32_indirect_uses() const {
   1906     return indirect_uses_[Representation::kInteger32];
   1907   }
   1908   int double_indirect_uses() const {
   1909     return indirect_uses_[Representation::kDouble];
   1910   }
   1911   int phi_id() { return phi_id_; }
   1912   bool is_live() { return is_live_; }
   1913   void set_is_live(bool b) { is_live_ = b; }
   1914 
   1915  protected:
   1916   virtual void DeleteFromGraph();
   1917   virtual void InternalSetOperandAt(int index, HValue* value) {
   1918     inputs_[index] = value;
   1919   }
   1920 
   1921  private:
   1922   ZoneList<HValue*> inputs_;
   1923   int merged_index_;
   1924 
   1925   int non_phi_uses_[Representation::kNumRepresentations];
   1926   int indirect_uses_[Representation::kNumRepresentations];
   1927   int phi_id_;
   1928   bool is_live_;
   1929 };
   1930 
   1931 
   1932 class HArgumentsObject: public HTemplateInstruction<0> {
   1933  public:
   1934   HArgumentsObject() {
   1935     set_representation(Representation::Tagged());
   1936     SetFlag(kIsArguments);
   1937   }
   1938 
   1939   virtual Representation RequiredInputRepresentation(int index) const {
   1940     return Representation::None();
   1941   }
   1942 
   1943   DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject, "arguments-object")
   1944 };
   1945 
   1946 
   1947 class HConstant: public HTemplateInstruction<0> {
   1948  public:
   1949   HConstant(Handle<Object> handle, Representation r);
   1950 
   1951   Handle<Object> handle() const { return handle_; }
   1952 
   1953   bool InOldSpace() const { return !HEAP->InNewSpace(*handle_); }
   1954 
   1955   virtual Representation RequiredInputRepresentation(int index) const {
   1956     return Representation::None();
   1957   }
   1958 
   1959   virtual bool EmitAtUses() { return !representation().IsDouble(); }
   1960   virtual void PrintDataTo(StringStream* stream);
   1961   virtual HType CalculateInferredType();
   1962   bool IsInteger() const { return handle_->IsSmi(); }
   1963   HConstant* CopyToRepresentation(Representation r) const;
   1964   HConstant* CopyToTruncatedInt32() const;
   1965   bool HasInteger32Value() const { return has_int32_value_; }
   1966   int32_t Integer32Value() const {
   1967     ASSERT(HasInteger32Value());
   1968     return int32_value_;
   1969   }
   1970   bool HasDoubleValue() const { return has_double_value_; }
   1971   double DoubleValue() const {
   1972     ASSERT(HasDoubleValue());
   1973     return double_value_;
   1974   }
   1975   bool HasStringValue() const { return handle_->IsString(); }
   1976 
   1977   bool ToBoolean() const;
   1978 
   1979   virtual intptr_t Hashcode() {
   1980     ASSERT(!HEAP->allow_allocation(false));
   1981     return reinterpret_cast<intptr_t>(*handle());
   1982   }
   1983 
   1984 #ifdef DEBUG
   1985   virtual void Verify() { }
   1986 #endif
   1987 
   1988   DECLARE_CONCRETE_INSTRUCTION(Constant, "constant")
   1989 
   1990  protected:
   1991   virtual Range* InferRange();
   1992 
   1993   virtual bool DataEquals(HValue* other) {
   1994     HConstant* other_constant = HConstant::cast(other);
   1995     return handle().is_identical_to(other_constant->handle());
   1996   }
   1997 
   1998  private:
   1999   Handle<Object> handle_;
   2000   HType constant_type_;
   2001 
   2002   // The following two values represent the int32 and the double value of the
   2003   // given constant if there is a lossless conversion between the constant
   2004   // and the specific representation.
   2005   bool has_int32_value_;
   2006   int32_t int32_value_;
   2007   bool has_double_value_;
   2008   double double_value_;
   2009 };
   2010 
   2011 
   2012 class HBinaryOperation: public HTemplateInstruction<2> {
   2013  public:
   2014   HBinaryOperation(HValue* left, HValue* right) {
   2015     ASSERT(left != NULL && right != NULL);
   2016     SetOperandAt(0, left);
   2017     SetOperandAt(1, right);
   2018   }
   2019 
   2020   HValue* left() { return OperandAt(0); }
   2021   HValue* right() { return OperandAt(1); }
   2022 
   2023   // TODO(kasperl): Move these helpers to the IA-32 Lithium
   2024   // instruction sequence builder.
   2025   HValue* LeastConstantOperand() {
   2026     if (IsCommutative() && left()->IsConstant()) return right();
   2027     return left();
   2028   }
   2029   HValue* MostConstantOperand() {
   2030     if (IsCommutative() && left()->IsConstant()) return left();
   2031     return right();
   2032   }
   2033 
   2034   virtual bool IsCommutative() const { return false; }
   2035 
   2036   virtual void PrintDataTo(StringStream* stream);
   2037 
   2038   DECLARE_INSTRUCTION(BinaryOperation)
   2039 };
   2040 
   2041 
   2042 class HApplyArguments: public HTemplateInstruction<4> {
   2043  public:
   2044   HApplyArguments(HValue* function,
   2045                   HValue* receiver,
   2046                   HValue* length,
   2047                   HValue* elements) {
   2048     set_representation(Representation::Tagged());
   2049     SetOperandAt(0, function);
   2050     SetOperandAt(1, receiver);
   2051     SetOperandAt(2, length);
   2052     SetOperandAt(3, elements);
   2053     SetAllSideEffects();
   2054   }
   2055 
   2056   virtual Representation RequiredInputRepresentation(int index) const {
   2057     // The length is untagged, all other inputs are tagged.
   2058     return (index == 2)
   2059         ? Representation::Integer32()
   2060         : Representation::Tagged();
   2061   }
   2062 
   2063   HValue* function() { return OperandAt(0); }
   2064   HValue* receiver() { return OperandAt(1); }
   2065   HValue* length() { return OperandAt(2); }
   2066   HValue* elements() { return OperandAt(3); }
   2067 
   2068   DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply_arguments")
   2069 };
   2070 
   2071 
   2072 class HArgumentsElements: public HTemplateInstruction<0> {
   2073  public:
   2074   HArgumentsElements() {
   2075     // The value produced by this instruction is a pointer into the stack
   2076     // that looks as if it was a smi because of alignment.
   2077     set_representation(Representation::Tagged());
   2078     SetFlag(kUseGVN);
   2079   }
   2080 
   2081   DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments_elements")
   2082 
   2083   virtual Representation RequiredInputRepresentation(int index) const {
   2084     return Representation::None();
   2085   }
   2086 
   2087  protected:
   2088   virtual bool DataEquals(HValue* other) { return true; }
   2089 };
   2090 
   2091 
   2092 class HArgumentsLength: public HUnaryOperation {
   2093  public:
   2094   explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
   2095     set_representation(Representation::Integer32());
   2096     SetFlag(kUseGVN);
   2097   }
   2098 
   2099   virtual Representation RequiredInputRepresentation(int index) const {
   2100     return Representation::Tagged();
   2101   }
   2102 
   2103   DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments_length")
   2104 
   2105  protected:
   2106   virtual bool DataEquals(HValue* other) { return true; }
   2107 };
   2108 
   2109 
   2110 class HAccessArgumentsAt: public HTemplateInstruction<3> {
   2111  public:
   2112   HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
   2113     set_representation(Representation::Tagged());
   2114     SetFlag(kUseGVN);
   2115     SetOperandAt(0, arguments);
   2116     SetOperandAt(1, length);
   2117     SetOperandAt(2, index);
   2118   }
   2119 
   2120   virtual void PrintDataTo(StringStream* stream);
   2121 
   2122   virtual Representation RequiredInputRepresentation(int index) const {
   2123     // The arguments elements is considered tagged.
   2124     return index == 0
   2125         ? Representation::Tagged()
   2126         : Representation::Integer32();
   2127   }
   2128 
   2129   HValue* arguments() { return OperandAt(0); }
   2130   HValue* length() { return OperandAt(1); }
   2131   HValue* index() { return OperandAt(2); }
   2132 
   2133   DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access_arguments_at")
   2134 
   2135   virtual bool DataEquals(HValue* other) { return true; }
   2136 };
   2137 
   2138 
   2139 class HBoundsCheck: public HBinaryOperation {
   2140  public:
   2141   HBoundsCheck(HValue* index, HValue* length)
   2142       : HBinaryOperation(index, length) {
   2143     set_representation(Representation::Integer32());
   2144     SetFlag(kUseGVN);
   2145   }
   2146 
   2147   virtual bool IsCheckInstruction() const { return true; }
   2148 
   2149   virtual Representation RequiredInputRepresentation(int index) const {
   2150     return Representation::Integer32();
   2151   }
   2152 
   2153 #ifdef DEBUG
   2154   virtual void Verify();
   2155 #endif
   2156 
   2157   HValue* index() { return left(); }
   2158   HValue* length() { return right(); }
   2159 
   2160   DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds_check")
   2161 
   2162  protected:
   2163   virtual bool DataEquals(HValue* other) { return true; }
   2164 };
   2165 
   2166 
   2167 class HBitwiseBinaryOperation: public HBinaryOperation {
   2168  public:
   2169   HBitwiseBinaryOperation(HValue* left, HValue* right)
   2170       : HBinaryOperation(left, right) {
   2171     set_representation(Representation::Tagged());
   2172     SetFlag(kFlexibleRepresentation);
   2173     SetAllSideEffects();
   2174   }
   2175 
   2176   virtual Representation RequiredInputRepresentation(int index) const {
   2177     return representation();
   2178   }
   2179 
   2180   virtual void RepresentationChanged(Representation to) {
   2181     if (!to.IsTagged()) {
   2182       ASSERT(to.IsInteger32());
   2183       ClearAllSideEffects();
   2184       SetFlag(kTruncatingToInt32);
   2185       SetFlag(kUseGVN);
   2186     }
   2187   }
   2188 
   2189   virtual HType CalculateInferredType();
   2190 
   2191   DECLARE_INSTRUCTION(BitwiseBinaryOperation)
   2192 };
   2193 
   2194 
   2195 class HArithmeticBinaryOperation: public HBinaryOperation {
   2196  public:
   2197   HArithmeticBinaryOperation(HValue* left, HValue* right)
   2198       : HBinaryOperation(left, right) {
   2199     set_representation(Representation::Tagged());
   2200     SetFlag(kFlexibleRepresentation);
   2201     SetAllSideEffects();
   2202   }
   2203 
   2204   virtual void RepresentationChanged(Representation to) {
   2205     if (!to.IsTagged()) {
   2206       ClearAllSideEffects();
   2207       SetFlag(kUseGVN);
   2208     }
   2209   }
   2210 
   2211   virtual HType CalculateInferredType();
   2212   virtual Representation RequiredInputRepresentation(int index) const {
   2213     return representation();
   2214   }
   2215   virtual Representation InferredRepresentation() {
   2216     if (left()->representation().Equals(right()->representation())) {
   2217       return left()->representation();
   2218     }
   2219     return HValue::InferredRepresentation();
   2220   }
   2221 
   2222   DECLARE_INSTRUCTION(ArithmeticBinaryOperation)
   2223 };
   2224 
   2225 
   2226 class HCompare: public HBinaryOperation {
   2227  public:
   2228   HCompare(HValue* left, HValue* right, Token::Value token)
   2229       : HBinaryOperation(left, right), token_(token) {
   2230     ASSERT(Token::IsCompareOp(token));
   2231     set_representation(Representation::Tagged());
   2232     SetAllSideEffects();
   2233   }
   2234 
   2235   void SetInputRepresentation(Representation r);
   2236 
   2237   virtual bool EmitAtUses() {
   2238     return !HasSideEffects() && (uses()->length() <= 1);
   2239   }
   2240 
   2241   virtual Representation RequiredInputRepresentation(int index) const {
   2242     return input_representation_;
   2243   }
   2244   Representation GetInputRepresentation() const {
   2245     return input_representation_;
   2246   }
   2247   Token::Value token() const { return token_; }
   2248   virtual void PrintDataTo(StringStream* stream);
   2249 
   2250   virtual HType CalculateInferredType();
   2251 
   2252   virtual intptr_t Hashcode() {
   2253     return HValue::Hashcode() * 7 + token_;
   2254   }
   2255 
   2256   DECLARE_CONCRETE_INSTRUCTION(Compare, "compare")
   2257 
   2258  protected:
   2259   virtual bool DataEquals(HValue* other) {
   2260     HCompare* comp = HCompare::cast(other);
   2261     return token_ == comp->token();
   2262   }
   2263 
   2264  private:
   2265   Representation input_representation_;
   2266   Token::Value token_;
   2267 };
   2268 
   2269 
   2270 class HCompareJSObjectEq: public HBinaryOperation {
   2271  public:
   2272   HCompareJSObjectEq(HValue* left, HValue* right)
   2273       : HBinaryOperation(left, right) {
   2274     set_representation(Representation::Tagged());
   2275     SetFlag(kUseGVN);
   2276     SetFlag(kDependsOnMaps);
   2277   }
   2278 
   2279   virtual bool EmitAtUses() {
   2280     return !HasSideEffects() && (uses()->length() <= 1);
   2281   }
   2282 
   2283   virtual Representation RequiredInputRepresentation(int index) const {
   2284     return Representation::Tagged();
   2285   }
   2286   virtual HType CalculateInferredType();
   2287 
   2288   DECLARE_CONCRETE_INSTRUCTION(CompareJSObjectEq, "compare-js-object-eq")
   2289 
   2290  protected:
   2291   virtual bool DataEquals(HValue* other) { return true; }
   2292 };
   2293 
   2294 
   2295 class HUnaryPredicate: public HUnaryOperation {
   2296  public:
   2297   explicit HUnaryPredicate(HValue* value) : HUnaryOperation(value) {
   2298     set_representation(Representation::Tagged());
   2299     SetFlag(kUseGVN);
   2300   }
   2301 
   2302   virtual bool EmitAtUses() {
   2303     return !HasSideEffects() && (uses()->length() <= 1);
   2304   }
   2305 
   2306   virtual Representation RequiredInputRepresentation(int index) const {
   2307     return Representation::Tagged();
   2308   }
   2309   virtual HType CalculateInferredType();
   2310 };
   2311 
   2312 
   2313 class HIsNull: public HUnaryPredicate {
   2314  public:
   2315   HIsNull(HValue* value, bool is_strict)
   2316       : HUnaryPredicate(value), is_strict_(is_strict) { }
   2317 
   2318   bool is_strict() const { return is_strict_; }
   2319 
   2320   DECLARE_CONCRETE_INSTRUCTION(IsNull, "is_null")
   2321 
   2322  protected:
   2323   virtual bool DataEquals(HValue* other) {
   2324     HIsNull* b = HIsNull::cast(other);
   2325     return is_strict_ == b->is_strict();
   2326   }
   2327 
   2328  private:
   2329   bool is_strict_;
   2330 };
   2331 
   2332 
   2333 class HIsObject: public HUnaryPredicate {
   2334  public:
   2335   explicit HIsObject(HValue* value) : HUnaryPredicate(value) { }
   2336 
   2337   DECLARE_CONCRETE_INSTRUCTION(IsObject, "is_object")
   2338 
   2339  protected:
   2340   virtual bool DataEquals(HValue* other) { return true; }
   2341 };
   2342 
   2343 
   2344 class HIsSmi: public HUnaryPredicate {
   2345  public:
   2346   explicit HIsSmi(HValue* value) : HUnaryPredicate(value) { }
   2347 
   2348   DECLARE_CONCRETE_INSTRUCTION(IsSmi, "is_smi")
   2349 
   2350  protected:
   2351   virtual bool DataEquals(HValue* other) { return true; }
   2352 };
   2353 
   2354 
   2355 class HIsConstructCall: public HTemplateInstruction<0> {
   2356  public:
   2357   HIsConstructCall() {
   2358     set_representation(Representation::Tagged());
   2359     SetFlag(kUseGVN);
   2360   }
   2361 
   2362   virtual bool EmitAtUses() {
   2363     return !HasSideEffects() && (uses()->length() <= 1);
   2364   }
   2365 
   2366   virtual Representation RequiredInputRepresentation(int index) const {
   2367     return Representation::None();
   2368   }
   2369 
   2370   DECLARE_CONCRETE_INSTRUCTION(IsConstructCall, "is_construct_call")
   2371 
   2372  protected:
   2373   virtual bool DataEquals(HValue* other) { return true; }
   2374 };
   2375 
   2376 
   2377 class HHasInstanceType: public HUnaryPredicate {
   2378  public:
   2379   HHasInstanceType(HValue* value, InstanceType type)
   2380       : HUnaryPredicate(value), from_(type), to_(type) { }
   2381   HHasInstanceType(HValue* value, InstanceType from, InstanceType to)
   2382       : HUnaryPredicate(value), from_(from), to_(to) {
   2383     ASSERT(to == LAST_TYPE);  // Others not implemented yet in backend.
   2384   }
   2385 
   2386   InstanceType from() { return from_; }
   2387   InstanceType to() { return to_; }
   2388 
   2389   virtual void PrintDataTo(StringStream* stream);
   2390 
   2391   DECLARE_CONCRETE_INSTRUCTION(HasInstanceType, "has_instance_type")
   2392 
   2393  protected:
   2394   virtual bool DataEquals(HValue* other) {
   2395     HHasInstanceType* b = HHasInstanceType::cast(other);
   2396     return (from_ == b->from()) && (to_ == b->to());
   2397   }
   2398 
   2399  private:
   2400   InstanceType from_;
   2401   InstanceType to_;  // Inclusive range, not all combinations work.
   2402 };
   2403 
   2404 
   2405 class HHasCachedArrayIndex: public HUnaryPredicate {
   2406  public:
   2407   explicit HHasCachedArrayIndex(HValue* value) : HUnaryPredicate(value) { }
   2408 
   2409   DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndex, "has_cached_array_index")
   2410 
   2411  protected:
   2412   virtual bool DataEquals(HValue* other) { return true; }
   2413 };
   2414 
   2415 
   2416 class HGetCachedArrayIndex: public HUnaryPredicate {
   2417  public:
   2418   explicit HGetCachedArrayIndex(HValue* value) : HUnaryPredicate(value) { }
   2419 
   2420   DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get_cached_array_index")
   2421 
   2422  protected:
   2423   virtual bool DataEquals(HValue* other) { return true; }
   2424 };
   2425 
   2426 
   2427 class HClassOfTest: public HUnaryPredicate {
   2428  public:
   2429   HClassOfTest(HValue* value, Handle<String> class_name)
   2430       : HUnaryPredicate(value), class_name_(class_name) { }
   2431 
   2432   DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class_of_test")
   2433 
   2434   virtual void PrintDataTo(StringStream* stream);
   2435 
   2436   Handle<String> class_name() const { return class_name_; }
   2437 
   2438  protected:
   2439   virtual bool DataEquals(HValue* other) {
   2440     HClassOfTest* b = HClassOfTest::cast(other);
   2441     return class_name_.is_identical_to(b->class_name_);
   2442   }
   2443 
   2444  private:
   2445   Handle<String> class_name_;
   2446 };
   2447 
   2448 
   2449 class HTypeofIs: public HUnaryPredicate {
   2450  public:
   2451   HTypeofIs(HValue* value, Handle<String> type_literal)
   2452       : HUnaryPredicate(value), type_literal_(type_literal) { }
   2453 
   2454   Handle<String> type_literal() { return type_literal_; }
   2455   virtual void PrintDataTo(StringStream* stream);
   2456 
   2457   DECLARE_CONCRETE_INSTRUCTION(TypeofIs, "typeof_is")
   2458 
   2459  protected:
   2460   virtual bool DataEquals(HValue* other) {
   2461     HTypeofIs* b = HTypeofIs::cast(other);
   2462     return type_literal_.is_identical_to(b->type_literal_);
   2463   }
   2464 
   2465  private:
   2466   Handle<String> type_literal_;
   2467 };
   2468 
   2469 
   2470 class HInstanceOf: public HTemplateInstruction<3> {
   2471  public:
   2472   HInstanceOf(HValue* context, HValue* left, HValue* right) {
   2473     SetOperandAt(0, context);
   2474     SetOperandAt(1, left);
   2475     SetOperandAt(2, right);
   2476     set_representation(Representation::Tagged());
   2477     SetAllSideEffects();
   2478   }
   2479 
   2480   HValue* context() { return OperandAt(0); }
   2481   HValue* left() { return OperandAt(1); }
   2482   HValue* right() { return OperandAt(2); }
   2483 
   2484   virtual bool EmitAtUses() {
   2485     return !HasSideEffects() && (uses()->length() <= 1);
   2486   }
   2487 
   2488   virtual Representation RequiredInputRepresentation(int index) const {
   2489     return Representation::Tagged();
   2490   }
   2491 
   2492   virtual void PrintDataTo(StringStream* stream);
   2493 
   2494   DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance_of")
   2495 };
   2496 
   2497 
   2498 class HInstanceOfKnownGlobal: public HUnaryOperation {
   2499  public:
   2500   HInstanceOfKnownGlobal(HValue* left, Handle<JSFunction> right)
   2501       : HUnaryOperation(left), function_(right) {
   2502     set_representation(Representation::Tagged());
   2503     SetAllSideEffects();
   2504   }
   2505 
   2506   Handle<JSFunction> function() { return function_; }
   2507 
   2508   virtual Representation RequiredInputRepresentation(int index) const {
   2509     return Representation::Tagged();
   2510   }
   2511 
   2512   DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
   2513                                "instance_of_known_global")
   2514 
   2515  private:
   2516   Handle<JSFunction> function_;
   2517 };
   2518 
   2519 
   2520 class HPower: public HBinaryOperation {
   2521  public:
   2522   HPower(HValue* left, HValue* right)
   2523       : HBinaryOperation(left, right) {
   2524     set_representation(Representation::Double());
   2525     SetFlag(kUseGVN);
   2526   }
   2527 
   2528   virtual Representation RequiredInputRepresentation(int index) const {
   2529     return (index == 1) ? Representation::None() : Representation::Double();
   2530   }
   2531 
   2532   DECLARE_CONCRETE_INSTRUCTION(Power, "power")
   2533 
   2534  protected:
   2535   virtual bool DataEquals(HValue* other) { return true; }
   2536 };
   2537 
   2538 
   2539 class HAdd: public HArithmeticBinaryOperation {
   2540  public:
   2541   HAdd(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
   2542     SetFlag(kCanOverflow);
   2543   }
   2544 
   2545   // Add is only commutative if two integer values are added and not if two
   2546   // tagged values are added (because it might be a String concatenation).
   2547   virtual bool IsCommutative() const {
   2548     return !representation().IsTagged();
   2549   }
   2550 
   2551   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
   2552 
   2553   virtual HType CalculateInferredType();
   2554 
   2555   DECLARE_CONCRETE_INSTRUCTION(Add, "add")
   2556 
   2557  protected:
   2558   virtual bool DataEquals(HValue* other) { return true; }
   2559 
   2560   virtual Range* InferRange();
   2561 };
   2562 
   2563 
   2564 class HSub: public HArithmeticBinaryOperation {
   2565  public:
   2566   HSub(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
   2567     SetFlag(kCanOverflow);
   2568   }
   2569 
   2570   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
   2571 
   2572   DECLARE_CONCRETE_INSTRUCTION(Sub, "sub")
   2573 
   2574  protected:
   2575   virtual bool DataEquals(HValue* other) { return true; }
   2576 
   2577   virtual Range* InferRange();
   2578 };
   2579 
   2580 
   2581 class HMul: public HArithmeticBinaryOperation {
   2582  public:
   2583   HMul(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
   2584     SetFlag(kCanOverflow);
   2585   }
   2586 
   2587   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
   2588 
   2589   // Only commutative if it is certain that not two objects are multiplicated.
   2590   virtual bool IsCommutative() const {
   2591     return !representation().IsTagged();
   2592   }
   2593 
   2594   DECLARE_CONCRETE_INSTRUCTION(Mul, "mul")
   2595 
   2596  protected:
   2597   virtual bool DataEquals(HValue* other) { return true; }
   2598 
   2599   virtual Range* InferRange();
   2600 };
   2601 
   2602 
   2603 class HMod: public HArithmeticBinaryOperation {
   2604  public:
   2605   HMod(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
   2606     SetFlag(kCanBeDivByZero);
   2607   }
   2608 
   2609   bool HasPowerOf2Divisor() {
   2610     if (right()->IsConstant() &&
   2611         HConstant::cast(right())->HasInteger32Value()) {
   2612       int32_t value = HConstant::cast(right())->Integer32Value();
   2613       return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
   2614     }
   2615 
   2616     return false;
   2617   }
   2618 
   2619   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
   2620 
   2621   DECLARE_CONCRETE_INSTRUCTION(Mod, "mod")
   2622 
   2623  protected:
   2624   virtual bool DataEquals(HValue* other) { return true; }
   2625 
   2626   virtual Range* InferRange();
   2627 };
   2628 
   2629 
   2630 class HDiv: public HArithmeticBinaryOperation {
   2631  public:
   2632   HDiv(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
   2633     SetFlag(kCanBeDivByZero);
   2634     SetFlag(kCanOverflow);
   2635   }
   2636 
   2637   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
   2638 
   2639   DECLARE_CONCRETE_INSTRUCTION(Div, "div")
   2640 
   2641  protected:
   2642   virtual bool DataEquals(HValue* other) { return true; }
   2643 
   2644   virtual Range* InferRange();
   2645 };
   2646 
   2647 
   2648 class HBitAnd: public HBitwiseBinaryOperation {
   2649  public:
   2650   HBitAnd(HValue* left, HValue* right)
   2651       : HBitwiseBinaryOperation(left, right) { }
   2652 
   2653   virtual bool IsCommutative() const { return true; }
   2654   virtual HType CalculateInferredType();
   2655 
   2656   DECLARE_CONCRETE_INSTRUCTION(BitAnd, "bit_and")
   2657 
   2658  protected:
   2659   virtual bool DataEquals(HValue* other) { return true; }
   2660 
   2661   virtual Range* InferRange();
   2662 };
   2663 
   2664 
   2665 class HBitXor: public HBitwiseBinaryOperation {
   2666  public:
   2667   HBitXor(HValue* left, HValue* right)
   2668       : HBitwiseBinaryOperation(left, right) { }
   2669 
   2670   virtual bool IsCommutative() const { return true; }
   2671   virtual HType CalculateInferredType();
   2672 
   2673   DECLARE_CONCRETE_INSTRUCTION(BitXor, "bit_xor")
   2674 
   2675  protected:
   2676   virtual bool DataEquals(HValue* other) { return true; }
   2677 };
   2678 
   2679 
   2680 class HBitOr: public HBitwiseBinaryOperation {
   2681  public:
   2682   HBitOr(HValue* left, HValue* right)
   2683       : HBitwiseBinaryOperation(left, right) { }
   2684 
   2685   virtual bool IsCommutative() const { return true; }
   2686   virtual HType CalculateInferredType();
   2687 
   2688   DECLARE_CONCRETE_INSTRUCTION(BitOr, "bit_or")
   2689 
   2690  protected:
   2691   virtual bool DataEquals(HValue* other) { return true; }
   2692 
   2693   virtual Range* InferRange();
   2694 };
   2695 
   2696 
   2697 class HShl: public HBitwiseBinaryOperation {
   2698  public:
   2699   HShl(HValue* left, HValue* right)
   2700       : HBitwiseBinaryOperation(left, right) { }
   2701 
   2702   virtual Range* InferRange();
   2703   virtual HType CalculateInferredType();
   2704 
   2705   DECLARE_CONCRETE_INSTRUCTION(Shl, "shl")
   2706 
   2707  protected:
   2708   virtual bool DataEquals(HValue* other) { return true; }
   2709 };
   2710 
   2711 
   2712 class HShr: public HBitwiseBinaryOperation {
   2713  public:
   2714   HShr(HValue* left, HValue* right)
   2715       : HBitwiseBinaryOperation(left, right) { }
   2716 
   2717   virtual HType CalculateInferredType();
   2718 
   2719   DECLARE_CONCRETE_INSTRUCTION(Shr, "shr")
   2720 
   2721  protected:
   2722   virtual bool DataEquals(HValue* other) { return true; }
   2723 };
   2724 
   2725 
   2726 class HSar: public HBitwiseBinaryOperation {
   2727  public:
   2728   HSar(HValue* left, HValue* right)
   2729       : HBitwiseBinaryOperation(left, right) { }
   2730 
   2731   virtual Range* InferRange();
   2732   virtual HType CalculateInferredType();
   2733 
   2734   DECLARE_CONCRETE_INSTRUCTION(Sar, "sar")
   2735 
   2736  protected:
   2737   virtual bool DataEquals(HValue* other) { return true; }
   2738 };
   2739 
   2740 
   2741 class HOsrEntry: public HTemplateInstruction<0> {
   2742  public:
   2743   explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
   2744     SetFlag(kChangesOsrEntries);
   2745   }
   2746 
   2747   int ast_id() const { return ast_id_; }
   2748 
   2749   virtual Representation RequiredInputRepresentation(int index) const {
   2750     return Representation::None();
   2751   }
   2752 
   2753   DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr_entry")
   2754 
   2755  private:
   2756   int ast_id_;
   2757 };
   2758 
   2759 
   2760 class HParameter: public HTemplateInstruction<0> {
   2761  public:
   2762   explicit HParameter(unsigned index) : index_(index) {
   2763     set_representation(Representation::Tagged());
   2764   }
   2765 
   2766   unsigned index() const { return index_; }
   2767 
   2768   virtual void PrintDataTo(StringStream* stream);
   2769 
   2770   virtual Representation RequiredInputRepresentation(int index) const {
   2771     return Representation::None();
   2772   }
   2773 
   2774   DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
   2775 
   2776  private:
   2777   unsigned index_;
   2778 };
   2779 
   2780 
   2781 class HCallStub: public HUnaryCall {
   2782  public:
   2783   HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
   2784       : HUnaryCall(context, argument_count),
   2785         major_key_(major_key),
   2786         transcendental_type_(TranscendentalCache::kNumberOfCaches) {
   2787   }
   2788 
   2789   CodeStub::Major major_key() { return major_key_; }
   2790 
   2791   HValue* context() { return value(); }
   2792 
   2793   void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
   2794     transcendental_type_ = transcendental_type;
   2795   }
   2796   TranscendentalCache::Type transcendental_type() {
   2797     return transcendental_type_;
   2798   }
   2799 
   2800   virtual void PrintDataTo(StringStream* stream);
   2801 
   2802   virtual Representation RequiredInputRepresentation(int index) const {
   2803     return Representation::Tagged();
   2804   }
   2805 
   2806   DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub")
   2807 
   2808  private:
   2809   CodeStub::Major major_key_;
   2810   TranscendentalCache::Type transcendental_type_;
   2811 };
   2812 
   2813 
   2814 class HUnknownOSRValue: public HTemplateInstruction<0> {
   2815  public:
   2816   HUnknownOSRValue() { set_representation(Representation::Tagged()); }
   2817 
   2818   virtual Representation RequiredInputRepresentation(int index) const {
   2819     return Representation::None();
   2820   }
   2821 
   2822   DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown_osr_value")
   2823 };
   2824 
   2825 
   2826 class HLoadGlobalCell: public HTemplateInstruction<0> {
   2827  public:
   2828   HLoadGlobalCell(Handle<JSGlobalPropertyCell> cell, bool check_hole_value)
   2829       : cell_(cell), check_hole_value_(check_hole_value) {
   2830     set_representation(Representation::Tagged());
   2831     SetFlag(kUseGVN);
   2832     SetFlag(kDependsOnGlobalVars);
   2833   }
   2834 
   2835   Handle<JSGlobalPropertyCell>  cell() const { return cell_; }
   2836   bool check_hole_value() const { return check_hole_value_; }
   2837 
   2838   virtual void PrintDataTo(StringStream* stream);
   2839 
   2840   virtual intptr_t Hashcode() {
   2841     ASSERT(!HEAP->allow_allocation(false));
   2842     return reinterpret_cast<intptr_t>(*cell_);
   2843   }
   2844 
   2845   virtual Representation RequiredInputRepresentation(int index) const {
   2846     return Representation::None();
   2847   }
   2848 
   2849   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell, "load_global_cell")
   2850 
   2851  protected:
   2852   virtual bool DataEquals(HValue* other) {
   2853     HLoadGlobalCell* b = HLoadGlobalCell::cast(other);
   2854     return cell_.is_identical_to(b->cell());
   2855   }
   2856 
   2857  private:
   2858   Handle<JSGlobalPropertyCell> cell_;
   2859   bool check_hole_value_;
   2860 };
   2861 
   2862 
   2863 class HLoadGlobalGeneric: public HBinaryOperation {
   2864  public:
   2865   HLoadGlobalGeneric(HValue* context,
   2866                      HValue* global_object,
   2867                      Handle<Object> name,
   2868                      bool for_typeof)
   2869       : HBinaryOperation(context, global_object),
   2870         name_(name),
   2871         for_typeof_(for_typeof) {
   2872     set_representation(Representation::Tagged());
   2873     SetAllSideEffects();
   2874   }
   2875 
   2876   HValue* context() { return OperandAt(0); }
   2877   HValue* global_object() { return OperandAt(1); }
   2878   Handle<Object> name() const { return name_; }
   2879   bool for_typeof() const { return for_typeof_; }
   2880 
   2881   virtual void PrintDataTo(StringStream* stream);
   2882 
   2883   virtual Representation RequiredInputRepresentation(int index) const {
   2884     return Representation::Tagged();
   2885   }
   2886 
   2887   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load_global_generic")
   2888 
   2889  private:
   2890   Handle<Object> name_;
   2891   bool for_typeof_;
   2892 };
   2893 
   2894 
   2895 class HStoreGlobalCell: public HUnaryOperation {
   2896  public:
   2897   HStoreGlobalCell(HValue* value,
   2898                    Handle<JSGlobalPropertyCell> cell,
   2899                    bool check_hole_value)
   2900       : HUnaryOperation(value),
   2901         cell_(cell),
   2902         check_hole_value_(check_hole_value) {
   2903     SetFlag(kChangesGlobalVars);
   2904   }
   2905 
   2906   Handle<JSGlobalPropertyCell> cell() const { return cell_; }
   2907   bool check_hole_value() const { return check_hole_value_; }
   2908 
   2909   virtual Representation RequiredInputRepresentation(int index) const {
   2910     return Representation::Tagged();
   2911   }
   2912   virtual void PrintDataTo(StringStream* stream);
   2913 
   2914   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store_global_cell")
   2915 
   2916  private:
   2917   Handle<JSGlobalPropertyCell> cell_;
   2918   bool check_hole_value_;
   2919 };
   2920 
   2921 
   2922 class HStoreGlobalGeneric: public HTemplateInstruction<3> {
   2923  public:
   2924   HStoreGlobalGeneric(HValue* context,
   2925                       HValue* global_object,
   2926                       Handle<Object> name,
   2927                       HValue* value,
   2928                       bool strict_mode)
   2929       : name_(name),
   2930         strict_mode_(strict_mode) {
   2931     SetOperandAt(0, context);
   2932     SetOperandAt(1, global_object);
   2933     SetOperandAt(2, value);
   2934     set_representation(Representation::Tagged());
   2935     SetAllSideEffects();
   2936   }
   2937 
   2938   HValue* context() { return OperandAt(0); }
   2939   HValue* global_object() { return OperandAt(1); }
   2940   Handle<Object> name() const { return name_; }
   2941   HValue* value() { return OperandAt(2); }
   2942   bool strict_mode() { return strict_mode_; }
   2943 
   2944   virtual void PrintDataTo(StringStream* stream);
   2945 
   2946   virtual Representation RequiredInputRepresentation(int index) const {
   2947     return Representation::Tagged();
   2948   }
   2949 
   2950   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric, "store_global_generic")
   2951 
   2952  private:
   2953   Handle<Object> name_;
   2954   bool strict_mode_;
   2955 };
   2956 
   2957 
   2958 class HLoadContextSlot: public HUnaryOperation {
   2959  public:
   2960   HLoadContextSlot(HValue* context , int slot_index)
   2961       : HUnaryOperation(context), slot_index_(slot_index) {
   2962     set_representation(Representation::Tagged());
   2963     SetFlag(kUseGVN);
   2964     SetFlag(kDependsOnContextSlots);
   2965   }
   2966 
   2967   int slot_index() const { return slot_index_; }
   2968 
   2969   virtual Representation RequiredInputRepresentation(int index) const {
   2970     return Representation::Tagged();
   2971   }
   2972 
   2973   virtual void PrintDataTo(StringStream* stream);
   2974 
   2975   DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load_context_slot")
   2976 
   2977  protected:
   2978   virtual bool DataEquals(HValue* other) {
   2979     HLoadContextSlot* b = HLoadContextSlot::cast(other);
   2980     return (slot_index() == b->slot_index());
   2981   }
   2982 
   2983  private:
   2984   int slot_index_;
   2985 };
   2986 
   2987 
   2988 static inline bool StoringValueNeedsWriteBarrier(HValue* value) {
   2989   return !value->type().IsSmi() &&
   2990       !(value->IsConstant() && HConstant::cast(value)->InOldSpace());
   2991 }
   2992 
   2993 
   2994 class HStoreContextSlot: public HBinaryOperation {
   2995  public:
   2996   HStoreContextSlot(HValue* context, int slot_index, HValue* value)
   2997       : HBinaryOperation(context, value), slot_index_(slot_index) {
   2998     SetFlag(kChangesContextSlots);
   2999   }
   3000 
   3001   HValue* context() { return OperandAt(0); }
   3002   HValue* value() { return OperandAt(1); }
   3003   int slot_index() const { return slot_index_; }
   3004 
   3005   bool NeedsWriteBarrier() {
   3006     return StoringValueNeedsWriteBarrier(value());
   3007   }
   3008 
   3009   virtual Representation RequiredInputRepresentation(int index) const {
   3010     return Representation::Tagged();
   3011   }
   3012 
   3013   virtual void PrintDataTo(StringStream* stream);
   3014 
   3015   DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store_context_slot")
   3016 
   3017  private:
   3018   int slot_index_;
   3019 };
   3020 
   3021 
   3022 class HLoadNamedField: public HUnaryOperation {
   3023  public:
   3024   HLoadNamedField(HValue* object, bool is_in_object, int offset)
   3025       : HUnaryOperation(object),
   3026         is_in_object_(is_in_object),
   3027         offset_(offset) {
   3028     set_representation(Representation::Tagged());
   3029     SetFlag(kUseGVN);
   3030     SetFlag(kDependsOnMaps);
   3031     if (is_in_object) {
   3032       SetFlag(kDependsOnInobjectFields);
   3033     } else {
   3034       SetFlag(kDependsOnBackingStoreFields);
   3035     }
   3036   }
   3037 
   3038   HValue* object() { return OperandAt(0); }
   3039   bool is_in_object() const { return is_in_object_; }
   3040   int offset() const { return offset_; }
   3041 
   3042   virtual Representation RequiredInputRepresentation(int index) const {
   3043     return Representation::Tagged();
   3044   }
   3045   virtual void PrintDataTo(StringStream* stream);
   3046 
   3047   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load_named_field")
   3048 
   3049  protected:
   3050   virtual bool DataEquals(HValue* other) {
   3051     HLoadNamedField* b = HLoadNamedField::cast(other);
   3052     return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
   3053   }
   3054 
   3055  private:
   3056   bool is_in_object_;
   3057   int offset_;
   3058 };
   3059 
   3060 
   3061 class HLoadNamedFieldPolymorphic: public HUnaryOperation {
   3062  public:
   3063   HLoadNamedFieldPolymorphic(HValue* object,
   3064                              ZoneMapList* types,
   3065                              Handle<String> name);
   3066 
   3067   HValue* object() { return OperandAt(0); }
   3068   ZoneMapList* types() { return &types_; }
   3069   Handle<String> name() { return name_; }
   3070   bool need_generic() { return need_generic_; }
   3071 
   3072   virtual Representation RequiredInputRepresentation(int index) const {
   3073     return Representation::Tagged();
   3074   }
   3075 
   3076   DECLARE_CONCRETE_INSTRUCTION(LoadNamedFieldPolymorphic,
   3077                                "load_named_field_polymorphic")
   3078 
   3079   static const int kMaxLoadPolymorphism = 4;
   3080 
   3081  protected:
   3082   virtual bool DataEquals(HValue* value);
   3083 
   3084  private:
   3085   ZoneMapList types_;
   3086   Handle<String> name_;
   3087   bool need_generic_;
   3088 };
   3089 
   3090 
   3091 
   3092 class HLoadNamedGeneric: public HBinaryOperation {
   3093  public:
   3094   HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
   3095       : HBinaryOperation(context, object), name_(name) {
   3096     set_representation(Representation::Tagged());
   3097     SetAllSideEffects();
   3098   }
   3099 
   3100   HValue* context() { return OperandAt(0); }
   3101   HValue* object() { return OperandAt(1); }
   3102   Handle<Object> name() const { return name_; }
   3103 
   3104   virtual Representation RequiredInputRepresentation(int index) const {
   3105     return Representation::Tagged();
   3106   }
   3107 
   3108   DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load_named_generic")
   3109 
   3110  private:
   3111   Handle<Object> name_;
   3112 };
   3113 
   3114 
   3115 class HLoadFunctionPrototype: public HUnaryOperation {
   3116  public:
   3117   explicit HLoadFunctionPrototype(HValue* function)
   3118       : HUnaryOperation(function) {
   3119     set_representation(Representation::Tagged());
   3120     SetFlag(kUseGVN);
   3121     SetFlag(kDependsOnCalls);
   3122   }
   3123 
   3124   HValue* function() { return OperandAt(0); }
   3125 
   3126   virtual Representation RequiredInputRepresentation(int index) const {
   3127     return Representation::Tagged();
   3128   }
   3129 
   3130   DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load_function_prototype")
   3131 
   3132  protected:
   3133   virtual bool DataEquals(HValue* other) { return true; }
   3134 };
   3135 
   3136 
   3137 class HLoadKeyedFastElement: public HBinaryOperation {
   3138  public:
   3139   HLoadKeyedFastElement(HValue* obj, HValue* key) : HBinaryOperation(obj, key) {
   3140     set_representation(Representation::Tagged());
   3141     SetFlag(kDependsOnArrayElements);
   3142     SetFlag(kUseGVN);
   3143   }
   3144 
   3145   HValue* object() { return OperandAt(0); }
   3146   HValue* key() { return OperandAt(1); }
   3147 
   3148   virtual Representation RequiredInputRepresentation(int index) const {
   3149     // The key is supposed to be Integer32.
   3150     return (index == 1) ? Representation::Integer32()
   3151         : Representation::Tagged();
   3152   }
   3153 
   3154   virtual void PrintDataTo(StringStream* stream);
   3155 
   3156   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement,
   3157                                "load_keyed_fast_element")
   3158 
   3159  protected:
   3160   virtual bool DataEquals(HValue* other) { return true; }
   3161 };
   3162 
   3163 
   3164 class HLoadKeyedSpecializedArrayElement: public HBinaryOperation {
   3165  public:
   3166   HLoadKeyedSpecializedArrayElement(HValue* external_elements,
   3167                                     HValue* key,
   3168                                     ExternalArrayType array_type)
   3169       : HBinaryOperation(external_elements, key),
   3170         array_type_(array_type) {
   3171     if (array_type == kExternalFloatArray) {
   3172       set_representation(Representation::Double());
   3173     } else {
   3174       set_representation(Representation::Integer32());
   3175     }
   3176     SetFlag(kDependsOnSpecializedArrayElements);
   3177     // Native code could change the specialized array.
   3178     SetFlag(kDependsOnCalls);
   3179     SetFlag(kUseGVN);
   3180   }
   3181 
   3182   virtual void PrintDataTo(StringStream* stream);
   3183 
   3184   virtual Representation RequiredInputRepresentation(int index) const {
   3185     // The key is supposed to be Integer32, but the base pointer
   3186     // for the element load is a naked pointer.
   3187     return (index == 1) ? Representation::Integer32()
   3188         : Representation::External();
   3189   }
   3190 
   3191   HValue* external_pointer() { return OperandAt(0); }
   3192   HValue* key() { return OperandAt(1); }
   3193   ExternalArrayType array_type() const { return array_type_; }
   3194 
   3195   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement,
   3196                                "load_keyed_specialized_array_element")
   3197 
   3198  protected:
   3199   virtual bool DataEquals(HValue* other) {
   3200     if (!other->IsLoadKeyedSpecializedArrayElement()) return false;
   3201     HLoadKeyedSpecializedArrayElement* cast_other =
   3202         HLoadKeyedSpecializedArrayElement::cast(other);
   3203     return array_type_ == cast_other->array_type();
   3204   }
   3205 
   3206  private:
   3207   ExternalArrayType array_type_;
   3208 };
   3209 
   3210 
   3211 class HLoadKeyedGeneric: public HTemplateInstruction<3> {
   3212  public:
   3213   HLoadKeyedGeneric(HContext* context, HValue* obj, HValue* key) {
   3214     set_representation(Representation::Tagged());
   3215     SetOperandAt(0, obj);
   3216     SetOperandAt(1, key);
   3217     SetOperandAt(2, context);
   3218     SetAllSideEffects();
   3219   }
   3220 
   3221   HValue* object() { return OperandAt(0); }
   3222   HValue* key() { return OperandAt(1); }
   3223   HValue* context() { return OperandAt(2); }
   3224 
   3225   virtual void PrintDataTo(StringStream* stream);
   3226 
   3227   virtual Representation RequiredInputRepresentation(int index) const {
   3228     return Representation::Tagged();
   3229   }
   3230 
   3231   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load_keyed_generic")
   3232 };
   3233 
   3234 
   3235 class HStoreNamedField: public HBinaryOperation {
   3236  public:
   3237   HStoreNamedField(HValue* obj,
   3238                    Handle<String> name,
   3239                    HValue* val,
   3240                    bool in_object,
   3241                    int offset)
   3242       : HBinaryOperation(obj, val),
   3243         name_(name),
   3244         is_in_object_(in_object),
   3245         offset_(offset) {
   3246     if (is_in_object_) {
   3247       SetFlag(kChangesInobjectFields);
   3248     } else {
   3249       SetFlag(kChangesBackingStoreFields);
   3250     }
   3251   }
   3252 
   3253   DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store_named_field")
   3254 
   3255   virtual Representation RequiredInputRepresentation(int index) const {
   3256     return Representation::Tagged();
   3257   }
   3258   virtual void PrintDataTo(StringStream* stream);
   3259 
   3260   HValue* object() { return OperandAt(0); }
   3261   HValue* value() { return OperandAt(1); }
   3262 
   3263   Handle<String> name() const { return name_; }
   3264   bool is_in_object() const { return is_in_object_; }
   3265   int offset() const { return offset_; }
   3266   Handle<Map> transition() const { return transition_; }
   3267   void set_transition(Handle<Map> map) { transition_ = map; }
   3268 
   3269   bool NeedsWriteBarrier() {
   3270     return StoringValueNeedsWriteBarrier(value());
   3271   }
   3272 
   3273  private:
   3274   Handle<String> name_;
   3275   bool is_in_object_;
   3276   int offset_;
   3277   Handle<Map> transition_;
   3278 };
   3279 
   3280 
   3281 class HStoreNamedGeneric: public HTemplateInstruction<3> {
   3282  public:
   3283   HStoreNamedGeneric(HValue* context,
   3284                      HValue* object,
   3285                      Handle<String> name,
   3286                      HValue* value,
   3287                      bool strict_mode)
   3288       : name_(name),
   3289         strict_mode_(strict_mode) {
   3290     SetOperandAt(0, object);
   3291     SetOperandAt(1, value);
   3292     SetOperandAt(2, context);
   3293     SetAllSideEffects();
   3294   }
   3295 
   3296   HValue* object() { return OperandAt(0); }
   3297   HValue* value() { return OperandAt(1); }
   3298   HValue* context() { return OperandAt(2); }
   3299   Handle<String> name() { return name_; }
   3300   bool strict_mode() { return strict_mode_; }
   3301 
   3302   virtual void PrintDataTo(StringStream* stream);
   3303 
   3304   virtual Representation RequiredInputRepresentation(int index) const {
   3305     return Representation::Tagged();
   3306   }
   3307 
   3308   DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store_named_generic")
   3309 
   3310  private:
   3311   Handle<String> name_;
   3312   bool strict_mode_;
   3313 };
   3314 
   3315 
   3316 class HStoreKeyedFastElement: public HTemplateInstruction<3> {
   3317  public:
   3318   HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val) {
   3319     SetOperandAt(0, obj);
   3320     SetOperandAt(1, key);
   3321     SetOperandAt(2, val);
   3322     SetFlag(kChangesArrayElements);
   3323   }
   3324 
   3325   virtual Representation RequiredInputRepresentation(int index) const {
   3326     // The key is supposed to be Integer32.
   3327     return (index == 1) ? Representation::Integer32()
   3328         : Representation::Tagged();
   3329   }
   3330 
   3331   HValue* object() { return OperandAt(0); }
   3332   HValue* key() { return OperandAt(1); }
   3333   HValue* value() { return OperandAt(2); }
   3334 
   3335   bool NeedsWriteBarrier() {
   3336     return StoringValueNeedsWriteBarrier(value());
   3337   }
   3338 
   3339   virtual void PrintDataTo(StringStream* stream);
   3340 
   3341   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
   3342                                "store_keyed_fast_element")
   3343 };
   3344 
   3345 
   3346 class HStoreKeyedSpecializedArrayElement: public HTemplateInstruction<3> {
   3347  public:
   3348   HStoreKeyedSpecializedArrayElement(HValue* external_elements,
   3349                                      HValue* key,
   3350                                      HValue* val,
   3351                                      ExternalArrayType array_type)
   3352       : array_type_(array_type) {
   3353     SetFlag(kChangesSpecializedArrayElements);
   3354     SetOperandAt(0, external_elements);
   3355     SetOperandAt(1, key);
   3356     SetOperandAt(2, val);
   3357   }
   3358 
   3359   virtual void PrintDataTo(StringStream* stream);
   3360 
   3361   virtual Representation RequiredInputRepresentation(int index) const {
   3362     if (index == 0) {
   3363       return Representation::External();
   3364     } else {
   3365       if (index == 2 && array_type() == kExternalFloatArray) {
   3366         return Representation::Double();
   3367       } else {
   3368         return Representation::Integer32();
   3369       }
   3370     }
   3371   }
   3372 
   3373   HValue* external_pointer() { return OperandAt(0); }
   3374   HValue* key() { return OperandAt(1); }
   3375   HValue* value() { return OperandAt(2); }
   3376   ExternalArrayType array_type() const { return array_type_; }
   3377 
   3378   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement,
   3379                                "store_keyed_specialized_array_element")
   3380  private:
   3381   ExternalArrayType array_type_;
   3382 };
   3383 
   3384 
   3385 class HStoreKeyedGeneric: public HTemplateInstruction<4> {
   3386  public:
   3387   HStoreKeyedGeneric(HValue* context,
   3388                      HValue* object,
   3389                      HValue* key,
   3390                      HValue* value,
   3391                      bool strict_mode)
   3392       : strict_mode_(strict_mode) {
   3393     SetOperandAt(0, object);
   3394     SetOperandAt(1, key);
   3395     SetOperandAt(2, value);
   3396     SetOperandAt(3, context);
   3397     SetAllSideEffects();
   3398   }
   3399 
   3400   HValue* object() { return OperandAt(0); }
   3401   HValue* key() { return OperandAt(1); }
   3402   HValue* value() { return OperandAt(2); }
   3403   HValue* context() { return OperandAt(3); }
   3404   bool strict_mode() { return strict_mode_; }
   3405 
   3406   virtual Representation RequiredInputRepresentation(int index) const {
   3407     return Representation::Tagged();
   3408   }
   3409 
   3410   virtual void PrintDataTo(StringStream* stream);
   3411 
   3412   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store_keyed_generic")
   3413 
   3414  private:
   3415   bool strict_mode_;
   3416 };
   3417 
   3418 
   3419 class HStringCharCodeAt: public HBinaryOperation {
   3420  public:
   3421   HStringCharCodeAt(HValue* string, HValue* index)
   3422       : HBinaryOperation(string, index) {
   3423     set_representation(Representation::Integer32());
   3424     SetFlag(kUseGVN);
   3425     SetFlag(kDependsOnMaps);
   3426   }
   3427 
   3428   virtual Representation RequiredInputRepresentation(int index) const {
   3429     // The index is supposed to be Integer32.
   3430     return (index == 1) ? Representation::Integer32()
   3431         : Representation::Tagged();
   3432   }
   3433 
   3434   HValue* string() { return OperandAt(0); }
   3435   HValue* index() { return OperandAt(1); }
   3436 
   3437   DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string_char_code_at")
   3438 
   3439  protected:
   3440   virtual bool DataEquals(HValue* other) { return true; }
   3441 
   3442   virtual Range* InferRange() {
   3443     return new Range(0, String::kMaxUC16CharCode);
   3444   }
   3445 };
   3446 
   3447 
   3448 class HStringCharFromCode: public HUnaryOperation {
   3449  public:
   3450   explicit HStringCharFromCode(HValue* char_code) : HUnaryOperation(char_code) {
   3451     set_representation(Representation::Tagged());
   3452     SetFlag(kUseGVN);
   3453   }
   3454 
   3455   virtual Representation RequiredInputRepresentation(int index) const {
   3456     return Representation::Integer32();
   3457   }
   3458 
   3459   virtual bool DataEquals(HValue* other) { return true; }
   3460 
   3461   DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string_char_from_code")
   3462 };
   3463 
   3464 
   3465 class HStringLength: public HUnaryOperation {
   3466  public:
   3467   explicit HStringLength(HValue* string) : HUnaryOperation(string) {
   3468     set_representation(Representation::Tagged());
   3469     SetFlag(kUseGVN);
   3470     SetFlag(kDependsOnMaps);
   3471   }
   3472 
   3473   virtual Representation RequiredInputRepresentation(int index) const {
   3474     return Representation::Tagged();
   3475   }
   3476 
   3477   virtual HType CalculateInferredType() {
   3478     STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
   3479     return HType::Smi();
   3480   }
   3481 
   3482   DECLARE_CONCRETE_INSTRUCTION(StringLength, "string_length")
   3483 
   3484  protected:
   3485   virtual bool DataEquals(HValue* other) { return true; }
   3486 
   3487   virtual Range* InferRange() {
   3488     return new Range(0, String::kMaxLength);
   3489   }
   3490 };
   3491 
   3492 
   3493 template <int V>
   3494 class HMaterializedLiteral: public HTemplateInstruction<V> {
   3495  public:
   3496   HMaterializedLiteral<V>(int index, int depth)
   3497       : literal_index_(index), depth_(depth) {
   3498     this->set_representation(Representation::Tagged());
   3499   }
   3500 
   3501   int literal_index() const { return literal_index_; }
   3502   int depth() const { return depth_; }
   3503 
   3504  private:
   3505   int literal_index_;
   3506   int depth_;
   3507 };
   3508 
   3509 
   3510 class HArrayLiteral: public HMaterializedLiteral<0> {
   3511  public:
   3512   HArrayLiteral(Handle<FixedArray> constant_elements,
   3513                 int length,
   3514                 int literal_index,
   3515                 int depth)
   3516       : HMaterializedLiteral<0>(literal_index, depth),
   3517         length_(length),
   3518         constant_elements_(constant_elements) {}
   3519 
   3520   Handle<FixedArray> constant_elements() const { return constant_elements_; }
   3521   int length() const { return length_; }
   3522 
   3523   bool IsCopyOnWrite() const;
   3524 
   3525   virtual Representation RequiredInputRepresentation(int index) const {
   3526     return Representation::None();
   3527   }
   3528 
   3529   DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral, "array_literal")
   3530 
   3531  private:
   3532   int length_;
   3533   Handle<FixedArray> constant_elements_;
   3534 };
   3535 
   3536 
   3537 class HObjectLiteral: public HMaterializedLiteral<1> {
   3538  public:
   3539   HObjectLiteral(HValue* context,
   3540                  Handle<FixedArray> constant_properties,
   3541                  bool fast_elements,
   3542                  int literal_index,
   3543                  int depth,
   3544                  bool has_function)
   3545       : HMaterializedLiteral<1>(literal_index, depth),
   3546         constant_properties_(constant_properties),
   3547         fast_elements_(fast_elements),
   3548         has_function_(has_function) {
   3549     SetOperandAt(0, context);
   3550   }
   3551 
   3552   HValue* context() { return OperandAt(0); }
   3553   Handle<FixedArray> constant_properties() const {
   3554     return constant_properties_;
   3555   }
   3556   bool fast_elements() const { return fast_elements_; }
   3557   bool has_function() const { return has_function_; }
   3558 
   3559   virtual Representation RequiredInputRepresentation(int index) const {
   3560     return Representation::Tagged();
   3561   }
   3562 
   3563   DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object_literal")
   3564 
   3565  private:
   3566   Handle<FixedArray> constant_properties_;
   3567   bool fast_elements_;
   3568   bool has_function_;
   3569 };
   3570 
   3571 
   3572 class HRegExpLiteral: public HMaterializedLiteral<0> {
   3573  public:
   3574   HRegExpLiteral(Handle<String> pattern,
   3575                  Handle<String> flags,
   3576                  int literal_index)
   3577       : HMaterializedLiteral<0>(literal_index, 0),
   3578         pattern_(pattern),
   3579         flags_(flags) { }
   3580 
   3581   Handle<String> pattern() { return pattern_; }
   3582   Handle<String> flags() { return flags_; }
   3583 
   3584   virtual Representation RequiredInputRepresentation(int index) const {
   3585     return Representation::None();
   3586   }
   3587 
   3588   DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp_literal")
   3589 
   3590  private:
   3591   Handle<String> pattern_;
   3592   Handle<String> flags_;
   3593 };
   3594 
   3595 
   3596 class HFunctionLiteral: public HTemplateInstruction<0> {
   3597  public:
   3598   HFunctionLiteral(Handle<SharedFunctionInfo> shared, bool pretenure)
   3599       : shared_info_(shared), pretenure_(pretenure) {
   3600     set_representation(Representation::Tagged());
   3601   }
   3602 
   3603   virtual Representation RequiredInputRepresentation(int index) const {
   3604     return Representation::None();
   3605   }
   3606 
   3607   DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function_literal")
   3608 
   3609   Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
   3610   bool pretenure() const { return pretenure_; }
   3611 
   3612  private:
   3613   Handle<SharedFunctionInfo> shared_info_;
   3614   bool pretenure_;
   3615 };
   3616 
   3617 
   3618 class HTypeof: public HUnaryOperation {
   3619  public:
   3620   explicit HTypeof(HValue* value) : HUnaryOperation(value) {
   3621     set_representation(Representation::Tagged());
   3622   }
   3623 
   3624   virtual Representation RequiredInputRepresentation(int index) const {
   3625     return Representation::Tagged();
   3626   }
   3627 
   3628   DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
   3629 };
   3630 
   3631 
   3632 class HToFastProperties: public HUnaryOperation {
   3633  public:
   3634   explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
   3635     // This instruction is not marked as having side effects, but
   3636     // changes the map of the input operand. Use it only when creating
   3637     // object literals.
   3638     ASSERT(value->IsObjectLiteral());
   3639     set_representation(Representation::Tagged());
   3640   }
   3641 
   3642   virtual Representation RequiredInputRepresentation(int index) const {
   3643     return Representation::Tagged();
   3644   }
   3645 
   3646   DECLARE_CONCRETE_INSTRUCTION(ToFastProperties, "to_fast_properties")
   3647 };
   3648 
   3649 
   3650 class HValueOf: public HUnaryOperation {
   3651  public:
   3652   explicit HValueOf(HValue* value) : HUnaryOperation(value) {
   3653     set_representation(Representation::Tagged());
   3654   }
   3655 
   3656   virtual Representation RequiredInputRepresentation(int index) const {
   3657     return Representation::Tagged();
   3658   }
   3659 
   3660   DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value_of")
   3661 };
   3662 
   3663 
   3664 class HDeleteProperty: public HBinaryOperation {
   3665  public:
   3666   HDeleteProperty(HValue* obj, HValue* key)
   3667       : HBinaryOperation(obj, key) {
   3668     set_representation(Representation::Tagged());
   3669     SetAllSideEffects();
   3670   }
   3671 
   3672   virtual Representation RequiredInputRepresentation(int index) const {
   3673     return Representation::Tagged();
   3674   }
   3675 
   3676   DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete_property")
   3677 
   3678   HValue* object() { return left(); }
   3679   HValue* key() { return right(); }
   3680 };
   3681 
   3682 #undef DECLARE_INSTRUCTION
   3683 #undef DECLARE_CONCRETE_INSTRUCTION
   3684 
   3685 } }  // namespace v8::internal
   3686 
   3687 #endif  // V8_HYDROGEN_INSTRUCTIONS_H_
   3688