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