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