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