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