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