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