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