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