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