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