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