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