[stubs] Refactor StringCompareStub and use it for HStringCompareAndBranch.
[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<String> name() const {
5916     return name_;
5917   }
5918
5919   inline bool immutable() const {
5920     return ImmutableField::decode(value_);
5921   }
5922
5923   // Returns true if access is being made to an in-object property that
5924   // was already added to the object.
5925   inline bool existing_inobject_property() const {
5926     return ExistingInobjectPropertyField::decode(value_);
5927   }
5928
5929   inline HObjectAccess WithRepresentation(Representation representation) {
5930     return HObjectAccess(portion(), offset(), representation, name(),
5931                          immutable(), existing_inobject_property());
5932   }
5933
5934   static HObjectAccess ForHeapNumberValue() {
5935     return HObjectAccess(
5936         kDouble, HeapNumber::kValueOffset, Representation::Double());
5937   }
5938
5939   static HObjectAccess ForHeapNumberValueLowestBits() {
5940     return HObjectAccess(kDouble,
5941                          HeapNumber::kValueOffset,
5942                          Representation::Integer32());
5943   }
5944
5945   static HObjectAccess ForHeapNumberValueHighestBits() {
5946     return HObjectAccess(kDouble,
5947                          HeapNumber::kValueOffset + kIntSize,
5948                          Representation::Integer32());
5949   }
5950
5951   static HObjectAccess ForOddballTypeOf() {
5952     return HObjectAccess(kInobject, Oddball::kTypeOfOffset,
5953                          Representation::HeapObject());
5954   }
5955
5956   static HObjectAccess ForElementsPointer() {
5957     return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
5958   }
5959
5960   static HObjectAccess ForLiteralsPointer() {
5961     return HObjectAccess(kInobject, JSFunction::kLiteralsOffset);
5962   }
5963
5964   static HObjectAccess ForNextFunctionLinkPointer() {
5965     return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
5966   }
5967
5968   static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
5969     return HObjectAccess(
5970         kArrayLengths,
5971         JSArray::kLengthOffset,
5972         IsFastElementsKind(elements_kind)
5973             ? Representation::Smi() : Representation::Tagged());
5974   }
5975
5976   static HObjectAccess ForAllocationSiteOffset(int offset);
5977
5978   static HObjectAccess ForAllocationSiteList() {
5979     return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
5980                          Handle<String>::null(), false, false);
5981   }
5982
5983   static HObjectAccess ForFixedArrayLength() {
5984     return HObjectAccess(
5985         kArrayLengths,
5986         FixedArray::kLengthOffset,
5987         Representation::Smi());
5988   }
5989
5990   static HObjectAccess ForFixedTypedArrayBaseBasePointer() {
5991     return HObjectAccess(kInobject, FixedTypedArrayBase::kBasePointerOffset,
5992                          Representation::Tagged());
5993   }
5994
5995   static HObjectAccess ForFixedTypedArrayBaseExternalPointer() {
5996     return HObjectAccess::ForObservableJSObjectOffset(
5997         FixedTypedArrayBase::kExternalPointerOffset,
5998         Representation::External());
5999   }
6000
6001   static HObjectAccess ForStringHashField() {
6002     return HObjectAccess(kInobject,
6003                          String::kHashFieldOffset,
6004                          Representation::Integer32());
6005   }
6006
6007   static HObjectAccess ForStringLength() {
6008     STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
6009     return HObjectAccess(
6010         kStringLengths,
6011         String::kLengthOffset,
6012         Representation::Smi());
6013   }
6014
6015   static HObjectAccess ForConsStringFirst() {
6016     return HObjectAccess(kInobject, ConsString::kFirstOffset);
6017   }
6018
6019   static HObjectAccess ForConsStringSecond() {
6020     return HObjectAccess(kInobject, ConsString::kSecondOffset);
6021   }
6022
6023   static HObjectAccess ForPropertiesPointer() {
6024     return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
6025   }
6026
6027   static HObjectAccess ForPrototypeOrInitialMap() {
6028     return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
6029   }
6030
6031   static HObjectAccess ForSharedFunctionInfoPointer() {
6032     return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
6033   }
6034
6035   static HObjectAccess ForCodeEntryPointer() {
6036     return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
6037   }
6038
6039   static HObjectAccess ForCodeOffset() {
6040     return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
6041   }
6042
6043   static HObjectAccess ForOptimizedCodeMap() {
6044     return HObjectAccess(kInobject,
6045                          SharedFunctionInfo::kOptimizedCodeMapOffset);
6046   }
6047
6048   static HObjectAccess ForOptimizedCodeMapSharedCode() {
6049     return HObjectAccess(kInobject, FixedArray::OffsetOfElementAt(
6050                                         SharedFunctionInfo::kSharedCodeIndex));
6051   }
6052
6053   static HObjectAccess ForFunctionContextPointer() {
6054     return HObjectAccess(kInobject, JSFunction::kContextOffset);
6055   }
6056
6057   static HObjectAccess ForMap() {
6058     return HObjectAccess(kMaps, JSObject::kMapOffset);
6059   }
6060
6061   static HObjectAccess ForPrototype() {
6062     return HObjectAccess(kMaps, Map::kPrototypeOffset);
6063   }
6064
6065   static HObjectAccess ForMapAsInteger32() {
6066     return HObjectAccess(kMaps, JSObject::kMapOffset,
6067                          Representation::Integer32());
6068   }
6069
6070   static HObjectAccess ForMapInObjectPropertiesOrConstructorFunctionIndex() {
6071     return HObjectAccess(
6072         kInobject, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset,
6073         Representation::UInteger8());
6074   }
6075
6076   static HObjectAccess ForMapInstanceType() {
6077     return HObjectAccess(kInobject,
6078                          Map::kInstanceTypeOffset,
6079                          Representation::UInteger8());
6080   }
6081
6082   static HObjectAccess ForMapInstanceSize() {
6083     return HObjectAccess(kInobject,
6084                          Map::kInstanceSizeOffset,
6085                          Representation::UInteger8());
6086   }
6087
6088   static HObjectAccess ForMapBitField() {
6089     return HObjectAccess(kInobject,
6090                          Map::kBitFieldOffset,
6091                          Representation::UInteger8());
6092   }
6093
6094   static HObjectAccess ForMapBitField2() {
6095     return HObjectAccess(kInobject,
6096                          Map::kBitField2Offset,
6097                          Representation::UInteger8());
6098   }
6099
6100   static HObjectAccess ForNameHashField() {
6101     return HObjectAccess(kInobject,
6102                          Name::kHashFieldOffset,
6103                          Representation::Integer32());
6104   }
6105
6106   static HObjectAccess ForMapInstanceTypeAndBitField() {
6107     STATIC_ASSERT((Map::kInstanceTypeAndBitFieldOffset & 1) == 0);
6108     // Ensure the two fields share one 16-bit word, endian-independent.
6109     STATIC_ASSERT((Map::kBitFieldOffset & ~1) ==
6110                   (Map::kInstanceTypeOffset & ~1));
6111     return HObjectAccess(kInobject,
6112                          Map::kInstanceTypeAndBitFieldOffset,
6113                          Representation::UInteger16());
6114   }
6115
6116   static HObjectAccess ForPropertyCellValue() {
6117     return HObjectAccess(kInobject, PropertyCell::kValueOffset);
6118   }
6119
6120   static HObjectAccess ForPropertyCellDetails() {
6121     return HObjectAccess(kInobject, PropertyCell::kDetailsOffset,
6122                          Representation::Smi());
6123   }
6124
6125   static HObjectAccess ForCellValue() {
6126     return HObjectAccess(kInobject, Cell::kValueOffset);
6127   }
6128
6129   static HObjectAccess ForWeakCellValue() {
6130     return HObjectAccess(kInobject, WeakCell::kValueOffset);
6131   }
6132
6133   static HObjectAccess ForWeakCellNext() {
6134     return HObjectAccess(kInobject, WeakCell::kNextOffset);
6135   }
6136
6137   static HObjectAccess ForAllocationMementoSite() {
6138     return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
6139   }
6140
6141   static HObjectAccess ForCounter() {
6142     return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
6143                          Handle<String>::null(), false, false);
6144   }
6145
6146   static HObjectAccess ForExternalUInteger8() {
6147     return HObjectAccess(kExternalMemory, 0, Representation::UInteger8(),
6148                          Handle<String>::null(), false, false);
6149   }
6150
6151   // Create an access to an offset in a fixed array header.
6152   static HObjectAccess ForFixedArrayHeader(int offset);
6153
6154   // Create an access to an in-object property in a JSObject.
6155   // This kind of access must be used when the object |map| is known and
6156   // in-object properties are being accessed. Accesses of the in-object
6157   // properties can have different semantics depending on whether corresponding
6158   // property was added to the map or not.
6159   static HObjectAccess ForMapAndOffset(Handle<Map> map, int offset,
6160       Representation representation = Representation::Tagged());
6161
6162   // Create an access to an in-object property in a JSObject.
6163   // This kind of access can be used for accessing object header fields or
6164   // in-object properties if the map of the object is not known.
6165   static HObjectAccess ForObservableJSObjectOffset(int offset,
6166       Representation representation = Representation::Tagged()) {
6167     return ForMapAndOffset(Handle<Map>::null(), offset, representation);
6168   }
6169
6170   // Create an access to an in-object property in a JSArray.
6171   static HObjectAccess ForJSArrayOffset(int offset);
6172
6173   static HObjectAccess ForContextSlot(int index);
6174
6175   static HObjectAccess ForScriptContext(int index);
6176
6177   // Create an access to the backing store of an object.
6178   static HObjectAccess ForBackingStoreOffset(int offset,
6179       Representation representation = Representation::Tagged());
6180
6181   // Create an access to a resolved field (in-object or backing store).
6182   static HObjectAccess ForField(Handle<Map> map, int index,
6183                                 Representation representation,
6184                                 Handle<String> name);
6185
6186   static HObjectAccess ForJSTypedArrayLength() {
6187     return HObjectAccess::ForObservableJSObjectOffset(
6188         JSTypedArray::kLengthOffset);
6189   }
6190
6191   static HObjectAccess ForJSArrayBufferBackingStore() {
6192     return HObjectAccess::ForObservableJSObjectOffset(
6193         JSArrayBuffer::kBackingStoreOffset, Representation::External());
6194   }
6195
6196   static HObjectAccess ForJSArrayBufferByteLength() {
6197     return HObjectAccess::ForObservableJSObjectOffset(
6198         JSArrayBuffer::kByteLengthOffset, Representation::Tagged());
6199   }
6200
6201   static HObjectAccess ForJSArrayBufferBitField() {
6202     return HObjectAccess::ForObservableJSObjectOffset(
6203         JSArrayBuffer::kBitFieldOffset, Representation::Integer32());
6204   }
6205
6206   static HObjectAccess ForJSArrayBufferBitFieldSlot() {
6207     return HObjectAccess::ForObservableJSObjectOffset(
6208         JSArrayBuffer::kBitFieldSlot, Representation::Smi());
6209   }
6210
6211   static HObjectAccess ForJSArrayBufferViewBuffer() {
6212     return HObjectAccess::ForObservableJSObjectOffset(
6213         JSArrayBufferView::kBufferOffset);
6214   }
6215
6216   static HObjectAccess ForJSArrayBufferViewByteOffset() {
6217     return HObjectAccess::ForObservableJSObjectOffset(
6218         JSArrayBufferView::kByteOffsetOffset);
6219   }
6220
6221   static HObjectAccess ForJSArrayBufferViewByteLength() {
6222     return HObjectAccess::ForObservableJSObjectOffset(
6223         JSArrayBufferView::kByteLengthOffset);
6224   }
6225
6226   static HObjectAccess ForGlobalObjectNativeContext() {
6227     return HObjectAccess(kInobject, GlobalObject::kNativeContextOffset);
6228   }
6229
6230   static HObjectAccess ForJSCollectionTable() {
6231     return HObjectAccess::ForObservableJSObjectOffset(
6232         JSCollection::kTableOffset);
6233   }
6234
6235   template <typename CollectionType>
6236   static HObjectAccess ForOrderedHashTableNumberOfBuckets() {
6237     return HObjectAccess(kInobject, CollectionType::kNumberOfBucketsOffset,
6238                          Representation::Smi());
6239   }
6240
6241   template <typename CollectionType>
6242   static HObjectAccess ForOrderedHashTableNumberOfElements() {
6243     return HObjectAccess(kInobject, CollectionType::kNumberOfElementsOffset,
6244                          Representation::Smi());
6245   }
6246
6247   template <typename CollectionType>
6248   static HObjectAccess ForOrderedHashTableNumberOfDeletedElements() {
6249     return HObjectAccess(kInobject,
6250                          CollectionType::kNumberOfDeletedElementsOffset,
6251                          Representation::Smi());
6252   }
6253
6254   template <typename CollectionType>
6255   static HObjectAccess ForOrderedHashTableNextTable() {
6256     return HObjectAccess(kInobject, CollectionType::kNextTableOffset);
6257   }
6258
6259   template <typename CollectionType>
6260   static HObjectAccess ForOrderedHashTableBucket(int bucket) {
6261     return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
6262                                         (bucket * kPointerSize),
6263                          Representation::Smi());
6264   }
6265
6266   // Access into the data table of an OrderedHashTable with a
6267   // known-at-compile-time bucket count.
6268   template <typename CollectionType, int kBucketCount>
6269   static HObjectAccess ForOrderedHashTableDataTableIndex(int index) {
6270     return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
6271                                         (kBucketCount * kPointerSize) +
6272                                         (index * kPointerSize));
6273   }
6274
6275   inline bool Equals(HObjectAccess that) const {
6276     return value_ == that.value_;  // portion and offset must match
6277   }
6278
6279  protected:
6280   void SetGVNFlags(HValue *instr, PropertyAccessType access_type);
6281
6282  private:
6283   // internal use only; different parts of an object or array
6284   enum Portion {
6285     kMaps,             // map of an object
6286     kArrayLengths,     // the length of an array
6287     kStringLengths,    // the length of a string
6288     kElementsPointer,  // elements pointer
6289     kBackingStore,     // some field in the backing store
6290     kDouble,           // some double field
6291     kInobject,         // some other in-object field
6292     kExternalMemory    // some field in external memory
6293   };
6294
6295   HObjectAccess() : value_(0) {}
6296
6297   HObjectAccess(Portion portion, int offset,
6298                 Representation representation = Representation::Tagged(),
6299                 Handle<String> name = Handle<String>::null(),
6300                 bool immutable = false,
6301                 bool existing_inobject_property = true)
6302     : value_(PortionField::encode(portion) |
6303              RepresentationField::encode(representation.kind()) |
6304              ImmutableField::encode(immutable ? 1 : 0) |
6305              ExistingInobjectPropertyField::encode(
6306                  existing_inobject_property ? 1 : 0) |
6307              OffsetField::encode(offset)),
6308       name_(name) {
6309     // assert that the fields decode correctly
6310     DCHECK(this->offset() == offset);
6311     DCHECK(this->portion() == portion);
6312     DCHECK(this->immutable() == immutable);
6313     DCHECK(this->existing_inobject_property() == existing_inobject_property);
6314     DCHECK(RepresentationField::decode(value_) == representation.kind());
6315     DCHECK(!this->existing_inobject_property() || IsInobject());
6316   }
6317
6318   class PortionField : public BitField<Portion, 0, 3> {};
6319   class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
6320   class ImmutableField : public BitField<bool, 7, 1> {};
6321   class ExistingInobjectPropertyField : public BitField<bool, 8, 1> {};
6322   class OffsetField : public BitField<int, 9, 23> {};
6323
6324   uint32_t value_;  // encodes portion, representation, immutable, and offset
6325   Handle<String> name_;
6326
6327   friend class HLoadNamedField;
6328   friend class HStoreNamedField;
6329   friend class SideEffectsTracker;
6330   friend std::ostream& operator<<(std::ostream& os,
6331                                   const HObjectAccess& access);
6332
6333   inline Portion portion() const {
6334     return PortionField::decode(value_);
6335   }
6336 };
6337
6338
6339 std::ostream& operator<<(std::ostream& os, const HObjectAccess& access);
6340
6341
6342 class HLoadNamedField final : public HTemplateInstruction<2> {
6343  public:
6344   DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*,
6345                                  HValue*, HObjectAccess);
6346   DECLARE_INSTRUCTION_FACTORY_P5(HLoadNamedField, HValue*, HValue*,
6347                                  HObjectAccess, const UniqueSet<Map>*, HType);
6348
6349   HValue* object() const { return OperandAt(0); }
6350   HValue* dependency() const {
6351     DCHECK(HasDependency());
6352     return OperandAt(1);
6353   }
6354   bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
6355   HObjectAccess access() const { return access_; }
6356   Representation field_representation() const {
6357       return access_.representation();
6358   }
6359
6360   const UniqueSet<Map>* maps() const { return maps_; }
6361
6362   bool HasEscapingOperandAt(int index) override { return false; }
6363   bool HasOutOfBoundsAccess(int size) override {
6364     return !access().IsInobject() || access().offset() >= size;
6365   }
6366   Representation RequiredInputRepresentation(int index) override {
6367     if (index == 0) {
6368       // object must be external in case of external memory access
6369       return access().IsExternalMemory() ? Representation::External()
6370                                          : Representation::Tagged();
6371     }
6372     DCHECK(index == 1);
6373     return Representation::None();
6374   }
6375   Range* InferRange(Zone* zone) override;
6376   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6377
6378   bool CanBeReplacedWith(HValue* other) const {
6379     if (!CheckFlag(HValue::kCantBeReplaced)) return false;
6380     if (!type().Equals(other->type())) return false;
6381     if (!representation().Equals(other->representation())) return false;
6382     if (!other->IsLoadNamedField()) return true;
6383     HLoadNamedField* that = HLoadNamedField::cast(other);
6384     if (this->maps_ == that->maps_) return true;
6385     if (this->maps_ == NULL || that->maps_ == NULL) return false;
6386     return this->maps_->IsSubset(that->maps_);
6387   }
6388
6389   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
6390
6391  protected:
6392   bool DataEquals(HValue* other) override {
6393     HLoadNamedField* that = HLoadNamedField::cast(other);
6394     if (!this->access_.Equals(that->access_)) return false;
6395     if (this->maps_ == that->maps_) return true;
6396     return (this->maps_ != NULL &&
6397             that->maps_ != NULL &&
6398             this->maps_->Equals(that->maps_));
6399   }
6400
6401  private:
6402   HLoadNamedField(HValue* object,
6403                   HValue* dependency,
6404                   HObjectAccess access)
6405       : access_(access), maps_(NULL) {
6406     DCHECK_NOT_NULL(object);
6407     SetOperandAt(0, object);
6408     SetOperandAt(1, dependency ? dependency : object);
6409
6410     Representation representation = access.representation();
6411     if (representation.IsInteger8() ||
6412         representation.IsUInteger8() ||
6413         representation.IsInteger16() ||
6414         representation.IsUInteger16()) {
6415       set_representation(Representation::Integer32());
6416     } else if (representation.IsSmi()) {
6417       set_type(HType::Smi());
6418       if (SmiValuesAre32Bits()) {
6419         set_representation(Representation::Integer32());
6420       } else {
6421         set_representation(representation);
6422       }
6423     } else if (representation.IsDouble() ||
6424                representation.IsExternal() ||
6425                representation.IsInteger32()) {
6426       set_representation(representation);
6427     } else if (representation.IsHeapObject()) {
6428       set_type(HType::HeapObject());
6429       set_representation(Representation::Tagged());
6430     } else {
6431       set_representation(Representation::Tagged());
6432     }
6433     access.SetGVNFlags(this, LOAD);
6434   }
6435
6436   HLoadNamedField(HValue* object,
6437                   HValue* dependency,
6438                   HObjectAccess access,
6439                   const UniqueSet<Map>* maps,
6440                   HType type)
6441       : HTemplateInstruction<2>(type), access_(access), maps_(maps) {
6442     DCHECK_NOT_NULL(maps);
6443     DCHECK_NE(0, maps->size());
6444
6445     DCHECK_NOT_NULL(object);
6446     SetOperandAt(0, object);
6447     SetOperandAt(1, dependency ? dependency : object);
6448
6449     DCHECK(access.representation().IsHeapObject());
6450     DCHECK(type.IsHeapObject());
6451     set_representation(Representation::Tagged());
6452
6453     access.SetGVNFlags(this, LOAD);
6454   }
6455
6456   bool IsDeletable() const override { return true; }
6457
6458   HObjectAccess access_;
6459   const UniqueSet<Map>* maps_;
6460 };
6461
6462
6463 class HLoadNamedGeneric final : public HTemplateInstruction<2> {
6464  public:
6465   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadNamedGeneric, HValue*,
6466                                               Handle<Name>, LanguageMode,
6467                                               InlineCacheState);
6468
6469   HValue* context() const { return OperandAt(0); }
6470   HValue* object() const { return OperandAt(1); }
6471   Handle<Name> name() const { return name_; }
6472
6473   InlineCacheState initialization_state() const {
6474     return initialization_state_;
6475   }
6476   FeedbackVectorICSlot slot() const { return slot_; }
6477   Handle<TypeFeedbackVector> feedback_vector() const {
6478     return feedback_vector_;
6479   }
6480   bool HasVectorAndSlot() const { return true; }
6481   void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
6482                         FeedbackVectorICSlot slot) {
6483     feedback_vector_ = vector;
6484     slot_ = slot;
6485   }
6486
6487   Representation RequiredInputRepresentation(int index) override {
6488     return Representation::Tagged();
6489   }
6490
6491   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6492
6493   DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
6494
6495   LanguageMode language_mode() const { return language_mode_; }
6496
6497  private:
6498   HLoadNamedGeneric(HValue* context, HValue* object, Handle<Name> name,
6499                     LanguageMode language_mode,
6500                     InlineCacheState initialization_state)
6501       : name_(name),
6502         slot_(FeedbackVectorICSlot::Invalid()),
6503         language_mode_(language_mode),
6504         initialization_state_(initialization_state) {
6505     SetOperandAt(0, context);
6506     SetOperandAt(1, object);
6507     set_representation(Representation::Tagged());
6508     SetAllSideEffects();
6509   }
6510
6511   Handle<Name> name_;
6512   Handle<TypeFeedbackVector> feedback_vector_;
6513   FeedbackVectorICSlot slot_;
6514   LanguageMode language_mode_;
6515   InlineCacheState initialization_state_;
6516 };
6517
6518
6519 class HLoadFunctionPrototype final : public HUnaryOperation {
6520  public:
6521   DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);
6522
6523   HValue* function() { return OperandAt(0); }
6524
6525   Representation RequiredInputRepresentation(int index) override {
6526     return Representation::Tagged();
6527   }
6528
6529   DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
6530
6531  protected:
6532   bool DataEquals(HValue* other) override { return true; }
6533
6534  private:
6535   explicit HLoadFunctionPrototype(HValue* function)
6536       : HUnaryOperation(function) {
6537     set_representation(Representation::Tagged());
6538     SetFlag(kUseGVN);
6539     SetDependsOnFlag(kCalls);
6540   }
6541 };
6542
6543 class ArrayInstructionInterface {
6544  public:
6545   virtual HValue* GetKey() = 0;
6546   virtual void SetKey(HValue* key) = 0;
6547   virtual ElementsKind elements_kind() const = 0;
6548   // TryIncreaseBaseOffset returns false if overflow would result.
6549   virtual bool TryIncreaseBaseOffset(uint32_t increase_by_value) = 0;
6550   virtual bool IsDehoisted() const = 0;
6551   virtual void SetDehoisted(bool is_dehoisted) = 0;
6552   virtual ~ArrayInstructionInterface() { }
6553
6554   static Representation KeyedAccessIndexRequirement(Representation r) {
6555     return r.IsInteger32() || SmiValuesAre32Bits()
6556         ? Representation::Integer32() : Representation::Smi();
6557   }
6558 };
6559
6560
6561 static const int kDefaultKeyedHeaderOffsetSentinel = -1;
6562
6563 enum LoadKeyedHoleMode {
6564   NEVER_RETURN_HOLE,
6565   ALLOW_RETURN_HOLE,
6566   CONVERT_HOLE_TO_UNDEFINED
6567 };
6568
6569
6570 class HLoadKeyed final : public HTemplateInstruction<3>,
6571                          public ArrayInstructionInterface {
6572  public:
6573   DECLARE_INSTRUCTION_FACTORY_P4(HLoadKeyed, HValue*, HValue*, HValue*,
6574                                  ElementsKind);
6575   DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*,
6576                                  ElementsKind, LoadKeyedHoleMode);
6577   DECLARE_INSTRUCTION_FACTORY_P6(HLoadKeyed, HValue*, HValue*, HValue*,
6578                                  ElementsKind, LoadKeyedHoleMode, int);
6579
6580   bool is_fixed_typed_array() const {
6581     return IsFixedTypedArrayElementsKind(elements_kind());
6582   }
6583   HValue* elements() const { return OperandAt(0); }
6584   HValue* key() const { return OperandAt(1); }
6585   HValue* dependency() const {
6586     DCHECK(HasDependency());
6587     return OperandAt(2);
6588   }
6589   bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
6590   uint32_t base_offset() const { return BaseOffsetField::decode(bit_field_); }
6591   bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
6592   HValue* GetKey() override { return key(); }
6593   void SetKey(HValue* key) override { SetOperandAt(1, key); }
6594   bool IsDehoisted() const override {
6595     return IsDehoistedField::decode(bit_field_);
6596   }
6597   void SetDehoisted(bool is_dehoisted) override {
6598     bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
6599   }
6600   ElementsKind elements_kind() const override {
6601     return ElementsKindField::decode(bit_field_);
6602   }
6603   LoadKeyedHoleMode hole_mode() const {
6604     return HoleModeField::decode(bit_field_);
6605   }
6606
6607   Representation RequiredInputRepresentation(int index) override {
6608     // kind_fast:                 tagged[int32] (none)
6609     // kind_double:               tagged[int32] (none)
6610     // kind_fixed_typed_array:    external[int32] (none)
6611     // kind_external:             external[int32] (none)
6612     if (index == 0) {
6613       return is_fixed_typed_array() ? Representation::External()
6614                                     : Representation::Tagged();
6615     }
6616     if (index == 1) {
6617       return ArrayInstructionInterface::KeyedAccessIndexRequirement(
6618           OperandAt(1)->representation());
6619     }
6620     return Representation::None();
6621   }
6622
6623   Representation observed_input_representation(int index) override {
6624     return RequiredInputRepresentation(index);
6625   }
6626
6627   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6628
6629   bool UsesMustHandleHole() const;
6630   bool AllUsesCanTreatHoleAsNaN() const;
6631   bool RequiresHoleCheck() const;
6632
6633   Range* InferRange(Zone* zone) override;
6634
6635   DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)
6636
6637  protected:
6638   bool DataEquals(HValue* other) override {
6639     if (!other->IsLoadKeyed()) return false;
6640     HLoadKeyed* other_load = HLoadKeyed::cast(other);
6641
6642     if (base_offset() != other_load->base_offset()) return false;
6643     return elements_kind() == other_load->elements_kind();
6644   }
6645
6646  private:
6647   HLoadKeyed(HValue* obj, HValue* key, HValue* dependency,
6648              ElementsKind elements_kind,
6649              LoadKeyedHoleMode mode = NEVER_RETURN_HOLE,
6650              int offset = kDefaultKeyedHeaderOffsetSentinel)
6651       : bit_field_(0) {
6652     offset = offset == kDefaultKeyedHeaderOffsetSentinel
6653         ? GetDefaultHeaderSizeForElementsKind(elements_kind)
6654         : offset;
6655     bit_field_ = ElementsKindField::encode(elements_kind) |
6656         HoleModeField::encode(mode) |
6657         BaseOffsetField::encode(offset);
6658
6659     SetOperandAt(0, obj);
6660     SetOperandAt(1, key);
6661     SetOperandAt(2, dependency != NULL ? dependency : obj);
6662
6663     if (!is_fixed_typed_array()) {
6664       // I can detect the case between storing double (holey and fast) and
6665       // smi/object by looking at elements_kind_.
6666       DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
6667              IsFastDoubleElementsKind(elements_kind));
6668
6669       if (IsFastSmiOrObjectElementsKind(elements_kind)) {
6670         if (IsFastSmiElementsKind(elements_kind) &&
6671             (!IsHoleyElementsKind(elements_kind) ||
6672              mode == NEVER_RETURN_HOLE)) {
6673           set_type(HType::Smi());
6674           if (SmiValuesAre32Bits() && !RequiresHoleCheck()) {
6675             set_representation(Representation::Integer32());
6676           } else {
6677             set_representation(Representation::Smi());
6678           }
6679         } else {
6680           set_representation(Representation::Tagged());
6681         }
6682
6683         SetDependsOnFlag(kArrayElements);
6684       } else {
6685         set_representation(Representation::Double());
6686         SetDependsOnFlag(kDoubleArrayElements);
6687       }
6688     } else {
6689       if (elements_kind == FLOAT32_ELEMENTS ||
6690           elements_kind == FLOAT64_ELEMENTS) {
6691         set_representation(Representation::Double());
6692       } else {
6693         set_representation(Representation::Integer32());
6694       }
6695
6696       if (is_fixed_typed_array()) {
6697         SetDependsOnFlag(kExternalMemory);
6698         SetDependsOnFlag(kTypedArrayElements);
6699       } else {
6700         UNREACHABLE();
6701       }
6702       // Native code could change the specialized array.
6703       SetDependsOnFlag(kCalls);
6704     }
6705
6706     SetFlag(kUseGVN);
6707   }
6708
6709   bool IsDeletable() const override { return !RequiresHoleCheck(); }
6710
6711   // Establish some checks around our packed fields
6712   enum LoadKeyedBits {
6713     kBitsForElementsKind = 5,
6714     kBitsForHoleMode = 2,
6715     kBitsForBaseOffset = 24,
6716     kBitsForIsDehoisted = 1,
6717
6718     kStartElementsKind = 0,
6719     kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
6720     kStartBaseOffset = kStartHoleMode + kBitsForHoleMode,
6721     kStartIsDehoisted = kStartBaseOffset + kBitsForBaseOffset
6722   };
6723
6724   STATIC_ASSERT((kBitsForElementsKind + kBitsForHoleMode + kBitsForBaseOffset +
6725                  kBitsForIsDehoisted) <= sizeof(uint32_t) * 8);
6726   STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
6727   class ElementsKindField:
6728     public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
6729     {};  // NOLINT
6730   class HoleModeField:
6731     public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
6732     {};  // NOLINT
6733   class BaseOffsetField:
6734     public BitField<uint32_t, kStartBaseOffset, kBitsForBaseOffset>
6735     {};  // NOLINT
6736   class IsDehoistedField:
6737     public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
6738     {};  // NOLINT
6739   uint32_t bit_field_;
6740 };
6741
6742
6743 class HLoadKeyedGeneric final : public HTemplateInstruction<3> {
6744  public:
6745   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadKeyedGeneric, HValue*,
6746                                               HValue*, LanguageMode,
6747                                               InlineCacheState);
6748   HValue* object() const { return OperandAt(0); }
6749   HValue* key() const { return OperandAt(1); }
6750   HValue* context() const { return OperandAt(2); }
6751   InlineCacheState initialization_state() const {
6752     return initialization_state_;
6753   }
6754   FeedbackVectorICSlot slot() const { return slot_; }
6755   Handle<TypeFeedbackVector> feedback_vector() const {
6756     return feedback_vector_;
6757   }
6758   bool HasVectorAndSlot() const {
6759     DCHECK(initialization_state_ == MEGAMORPHIC || !feedback_vector_.is_null());
6760     return !feedback_vector_.is_null();
6761   }
6762   void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
6763                         FeedbackVectorICSlot slot) {
6764     feedback_vector_ = vector;
6765     slot_ = slot;
6766   }
6767
6768   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6769
6770   Representation RequiredInputRepresentation(int index) override {
6771     // tagged[tagged]
6772     return Representation::Tagged();
6773   }
6774
6775   HValue* Canonicalize() override;
6776
6777   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
6778
6779   LanguageMode language_mode() const { return language_mode_; }
6780
6781  private:
6782   HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key,
6783                     LanguageMode language_mode,
6784                     InlineCacheState initialization_state)
6785       : slot_(FeedbackVectorICSlot::Invalid()),
6786         initialization_state_(initialization_state),
6787         language_mode_(language_mode) {
6788     set_representation(Representation::Tagged());
6789     SetOperandAt(0, obj);
6790     SetOperandAt(1, key);
6791     SetOperandAt(2, context);
6792     SetAllSideEffects();
6793   }
6794
6795   Handle<TypeFeedbackVector> feedback_vector_;
6796   FeedbackVectorICSlot slot_;
6797   InlineCacheState initialization_state_;
6798   LanguageMode language_mode_;
6799 };
6800
6801
6802 // Indicates whether the store is a store to an entry that was previously
6803 // initialized or not.
6804 enum StoreFieldOrKeyedMode {
6805   // The entry could be either previously initialized or not.
6806   INITIALIZING_STORE,
6807   // At the time of this store it is guaranteed that the entry is already
6808   // initialized.
6809   STORE_TO_INITIALIZED_ENTRY
6810 };
6811
6812
6813 class HStoreNamedField final : public HTemplateInstruction<3> {
6814  public:
6815   DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
6816                                  HObjectAccess, HValue*);
6817   DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue*,
6818                                  HObjectAccess, HValue*, StoreFieldOrKeyedMode);
6819
6820   DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
6821
6822   bool HasEscapingOperandAt(int index) override { return index == 1; }
6823   bool HasOutOfBoundsAccess(int size) override {
6824     return !access().IsInobject() || access().offset() >= size;
6825   }
6826   Representation RequiredInputRepresentation(int index) override {
6827     if (index == 0 && access().IsExternalMemory()) {
6828       // object must be external in case of external memory access
6829       return Representation::External();
6830     } else if (index == 1) {
6831       if (field_representation().IsInteger8() ||
6832           field_representation().IsUInteger8() ||
6833           field_representation().IsInteger16() ||
6834           field_representation().IsUInteger16() ||
6835           field_representation().IsInteger32()) {
6836         return Representation::Integer32();
6837       } else if (field_representation().IsDouble()) {
6838         return field_representation();
6839       } else if (field_representation().IsSmi()) {
6840         if (SmiValuesAre32Bits() &&
6841             store_mode() == STORE_TO_INITIALIZED_ENTRY) {
6842           return Representation::Integer32();
6843         }
6844         return field_representation();
6845       } else if (field_representation().IsExternal()) {
6846         return Representation::External();
6847       }
6848     }
6849     return Representation::Tagged();
6850   }
6851   virtual bool HandleSideEffectDominator(GVNFlag side_effect,
6852                                          HValue* dominator) override {
6853     DCHECK(side_effect == kNewSpacePromotion);
6854     if (!FLAG_use_write_barrier_elimination) return false;
6855     dominator_ = dominator;
6856     return false;
6857   }
6858   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6859
6860   HValue* object() const { return OperandAt(0); }
6861   HValue* value() const { return OperandAt(1); }
6862   HValue* transition() const { return OperandAt(2); }
6863
6864   HObjectAccess access() const { return access_; }
6865   HValue* dominator() const { return dominator_; }
6866   bool has_transition() const { return HasTransitionField::decode(bit_field_); }
6867   StoreFieldOrKeyedMode store_mode() const {
6868     return StoreModeField::decode(bit_field_);
6869   }
6870
6871   Handle<Map> transition_map() const {
6872     if (has_transition()) {
6873       return Handle<Map>::cast(
6874           HConstant::cast(transition())->handle(isolate()));
6875     } else {
6876       return Handle<Map>();
6877     }
6878   }
6879
6880   void SetTransition(HConstant* transition) {
6881     DCHECK(!has_transition());  // Only set once.
6882     SetOperandAt(2, transition);
6883     bit_field_ = HasTransitionField::update(bit_field_, true);
6884     SetChangesFlag(kMaps);
6885   }
6886
6887   bool NeedsWriteBarrier() const {
6888     DCHECK(!field_representation().IsDouble() ||
6889            (FLAG_unbox_double_fields && access_.IsInobject()) ||
6890            !has_transition());
6891     if (field_representation().IsDouble()) return false;
6892     if (field_representation().IsSmi()) return false;
6893     if (field_representation().IsInteger32()) return false;
6894     if (field_representation().IsExternal()) return false;
6895     return StoringValueNeedsWriteBarrier(value()) &&
6896         ReceiverObjectNeedsWriteBarrier(object(), value(), dominator());
6897   }
6898
6899   bool NeedsWriteBarrierForMap() {
6900     return ReceiverObjectNeedsWriteBarrier(object(), transition(),
6901                                            dominator());
6902   }
6903
6904   SmiCheck SmiCheckForWriteBarrier() const {
6905     if (field_representation().IsHeapObject()) return OMIT_SMI_CHECK;
6906     if (value()->type().IsHeapObject()) return OMIT_SMI_CHECK;
6907     return INLINE_SMI_CHECK;
6908   }
6909
6910   PointersToHereCheck PointersToHereCheckForValue() const {
6911     return PointersToHereCheckForObject(value(), dominator());
6912   }
6913
6914   Representation field_representation() const {
6915     return access_.representation();
6916   }
6917
6918   void UpdateValue(HValue* value) {
6919     SetOperandAt(1, value);
6920   }
6921
6922   bool CanBeReplacedWith(HStoreNamedField* that) const {
6923     if (!this->access().Equals(that->access())) return false;
6924     if (SmiValuesAre32Bits() &&
6925         this->field_representation().IsSmi() &&
6926         this->store_mode() == INITIALIZING_STORE &&
6927         that->store_mode() == STORE_TO_INITIALIZED_ENTRY) {
6928       // We cannot replace an initializing store to a smi field with a store to
6929       // an initialized entry on 64-bit architectures (with 32-bit smis).
6930       return false;
6931     }
6932     return true;
6933   }
6934
6935  private:
6936   HStoreNamedField(HValue* obj, HObjectAccess access, HValue* val,
6937                    StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
6938       : access_(access),
6939         dominator_(NULL),
6940         bit_field_(HasTransitionField::encode(false) |
6941                    StoreModeField::encode(store_mode)) {
6942     // Stores to a non existing in-object property are allowed only to the
6943     // newly allocated objects (via HAllocate or HInnerAllocatedObject).
6944     DCHECK(!access.IsInobject() || access.existing_inobject_property() ||
6945            obj->IsAllocate() || obj->IsInnerAllocatedObject());
6946     SetOperandAt(0, obj);
6947     SetOperandAt(1, val);
6948     SetOperandAt(2, obj);
6949     access.SetGVNFlags(this, STORE);
6950   }
6951
6952   class HasTransitionField : public BitField<bool, 0, 1> {};
6953   class StoreModeField : public BitField<StoreFieldOrKeyedMode, 1, 1> {};
6954
6955   HObjectAccess access_;
6956   HValue* dominator_;
6957   uint32_t bit_field_;
6958 };
6959
6960
6961 class HStoreNamedGeneric final : public HTemplateInstruction<3> {
6962  public:
6963   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HStoreNamedGeneric, HValue*,
6964                                               Handle<Name>, HValue*,
6965                                               LanguageMode, InlineCacheState);
6966   HValue* object() const { return OperandAt(0); }
6967   HValue* value() const { return OperandAt(1); }
6968   HValue* context() const { return OperandAt(2); }
6969   Handle<Name> name() const { return name_; }
6970   LanguageMode language_mode() const { return language_mode_; }
6971   InlineCacheState initialization_state() const {
6972     return initialization_state_;
6973   }
6974
6975   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6976
6977   Representation RequiredInputRepresentation(int index) override {
6978     return Representation::Tagged();
6979   }
6980
6981   FeedbackVectorICSlot slot() const { return slot_; }
6982   Handle<TypeFeedbackVector> feedback_vector() const {
6983     return feedback_vector_;
6984   }
6985   bool HasVectorAndSlot() const { return FLAG_vector_stores; }
6986   void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
6987                         FeedbackVectorICSlot slot) {
6988     feedback_vector_ = vector;
6989     slot_ = slot;
6990   }
6991
6992   DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
6993
6994  private:
6995   HStoreNamedGeneric(HValue* context, HValue* object, Handle<Name> name,
6996                      HValue* value, LanguageMode language_mode,
6997                      InlineCacheState initialization_state)
6998       : name_(name),
6999         slot_(FeedbackVectorICSlot::Invalid()),
7000         language_mode_(language_mode),
7001         initialization_state_(initialization_state) {
7002     SetOperandAt(0, object);
7003     SetOperandAt(1, value);
7004     SetOperandAt(2, context);
7005     SetAllSideEffects();
7006   }
7007
7008   Handle<Name> name_;
7009   Handle<TypeFeedbackVector> feedback_vector_;
7010   FeedbackVectorICSlot slot_;
7011   LanguageMode language_mode_;
7012   InlineCacheState initialization_state_;
7013 };
7014
7015
7016 class HStoreGlobalViaContext final : public HTemplateInstruction<2> {
7017  public:
7018   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreGlobalViaContext, HValue*,
7019                                               int, int, LanguageMode);
7020   HValue* context() const { return OperandAt(0); }
7021   HValue* value() const { return OperandAt(1); }
7022   int depth() const { return depth_; }
7023   int slot_index() const { return slot_index_; }
7024   LanguageMode language_mode() const { return language_mode_; }
7025
7026   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
7027
7028   Representation RequiredInputRepresentation(int index) override {
7029     return Representation::Tagged();
7030   }
7031
7032   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalViaContext)
7033
7034  private:
7035   HStoreGlobalViaContext(HValue* context, HValue* value, int depth,
7036                          int slot_index, LanguageMode language_mode)
7037       : depth_(depth), slot_index_(slot_index), language_mode_(language_mode) {
7038     SetOperandAt(0, context);
7039     SetOperandAt(1, value);
7040     SetAllSideEffects();
7041   }
7042
7043   int const depth_;
7044   int const slot_index_;
7045   LanguageMode const language_mode_;
7046 };
7047
7048
7049 class HStoreKeyed final : public HTemplateInstruction<3>,
7050                           public ArrayInstructionInterface {
7051  public:
7052   DECLARE_INSTRUCTION_FACTORY_P4(HStoreKeyed, HValue*, HValue*, HValue*,
7053                                  ElementsKind);
7054   DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*,
7055                                  ElementsKind, StoreFieldOrKeyedMode);
7056   DECLARE_INSTRUCTION_FACTORY_P6(HStoreKeyed, HValue*, HValue*, HValue*,
7057                                  ElementsKind, StoreFieldOrKeyedMode, int);
7058
7059   Representation RequiredInputRepresentation(int index) override {
7060     // kind_fast:               tagged[int32] = tagged
7061     // kind_double:             tagged[int32] = double
7062     // kind_smi   :             tagged[int32] = smi
7063     // kind_fixed_typed_array:  tagged[int32] = (double | int32)
7064     // kind_external:           external[int32] = (double | int32)
7065     if (index == 0) {
7066       return is_fixed_typed_array() ? Representation::External()
7067                                     : Representation::Tagged();
7068     } else if (index == 1) {
7069       return ArrayInstructionInterface::KeyedAccessIndexRequirement(
7070           OperandAt(1)->representation());
7071     }
7072
7073     DCHECK_EQ(index, 2);
7074     return RequiredValueRepresentation(elements_kind(), store_mode());
7075   }
7076
7077   static Representation RequiredValueRepresentation(
7078       ElementsKind kind, StoreFieldOrKeyedMode mode) {
7079     if (IsDoubleOrFloatElementsKind(kind)) {
7080       return Representation::Double();
7081     }
7082
7083     if (kind == FAST_SMI_ELEMENTS && SmiValuesAre32Bits() &&
7084         mode == STORE_TO_INITIALIZED_ENTRY) {
7085       return Representation::Integer32();
7086     }
7087
7088     if (IsFastSmiElementsKind(kind)) {
7089       return Representation::Smi();
7090     }
7091
7092     if (IsFixedTypedArrayElementsKind(kind)) {
7093       return Representation::Integer32();
7094     }
7095     return Representation::Tagged();
7096   }
7097
7098   bool is_fixed_typed_array() const {
7099     return IsFixedTypedArrayElementsKind(elements_kind());
7100   }
7101
7102   Representation observed_input_representation(int index) override {
7103     if (index < 2) return RequiredInputRepresentation(index);
7104     if (IsUninitialized()) {
7105       return Representation::None();
7106     }
7107     Representation r =
7108         RequiredValueRepresentation(elements_kind(), store_mode());
7109     // For fast object elements kinds, don't assume anything.
7110     if (r.IsTagged()) return Representation::None();
7111     return r;
7112   }
7113
7114   HValue* elements() const { return OperandAt(0); }
7115   HValue* key() const { return OperandAt(1); }
7116   HValue* value() const { return OperandAt(2); }
7117   bool value_is_smi() const { return IsFastSmiElementsKind(elements_kind()); }
7118   StoreFieldOrKeyedMode store_mode() const {
7119     return StoreModeField::decode(bit_field_);
7120   }
7121   ElementsKind elements_kind() const override {
7122     return ElementsKindField::decode(bit_field_);
7123   }
7124   uint32_t base_offset() const { return base_offset_; }
7125   bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
7126   HValue* GetKey() override { return key(); }
7127   void SetKey(HValue* key) override { SetOperandAt(1, key); }
7128   bool IsDehoisted() const override {
7129     return IsDehoistedField::decode(bit_field_);
7130   }
7131   void SetDehoisted(bool is_dehoisted) override {
7132     bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
7133   }
7134   bool IsUninitialized() { return IsUninitializedField::decode(bit_field_); }
7135   void SetUninitialized(bool is_uninitialized) {
7136     bit_field_ = IsUninitializedField::update(bit_field_, is_uninitialized);
7137   }
7138
7139   bool IsConstantHoleStore() {
7140     return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
7141   }
7142
7143   virtual bool HandleSideEffectDominator(GVNFlag side_effect,
7144                                          HValue* dominator) override {
7145     DCHECK(side_effect == kNewSpacePromotion);
7146     dominator_ = dominator;
7147     return false;
7148   }
7149
7150   HValue* dominator() const { return dominator_; }
7151
7152   bool NeedsWriteBarrier() {
7153     if (value_is_smi()) {
7154       return false;
7155     } else {
7156       return StoringValueNeedsWriteBarrier(value()) &&
7157           ReceiverObjectNeedsWriteBarrier(elements(), value(), dominator());
7158     }
7159   }
7160
7161   PointersToHereCheck PointersToHereCheckForValue() const {
7162     return PointersToHereCheckForObject(value(), dominator());
7163   }
7164
7165   bool NeedsCanonicalization();
7166
7167   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
7168
7169   DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
7170
7171  private:
7172   HStoreKeyed(HValue* obj, HValue* key, HValue* val, ElementsKind elements_kind,
7173               StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE,
7174               int offset = kDefaultKeyedHeaderOffsetSentinel)
7175       : base_offset_(offset == kDefaultKeyedHeaderOffsetSentinel
7176                          ? GetDefaultHeaderSizeForElementsKind(elements_kind)
7177                          : offset),
7178         bit_field_(IsDehoistedField::encode(false) |
7179                    IsUninitializedField::encode(false) |
7180                    StoreModeField::encode(store_mode) |
7181                    ElementsKindField::encode(elements_kind)),
7182         dominator_(NULL) {
7183     SetOperandAt(0, obj);
7184     SetOperandAt(1, key);
7185     SetOperandAt(2, val);
7186
7187     if (IsFastObjectElementsKind(elements_kind)) {
7188       SetFlag(kTrackSideEffectDominators);
7189       SetDependsOnFlag(kNewSpacePromotion);
7190     }
7191     if (IsFastDoubleElementsKind(elements_kind)) {
7192       SetChangesFlag(kDoubleArrayElements);
7193     } else if (IsFastSmiElementsKind(elements_kind)) {
7194       SetChangesFlag(kArrayElements);
7195     } else if (is_fixed_typed_array()) {
7196       SetChangesFlag(kTypedArrayElements);
7197       SetChangesFlag(kExternalMemory);
7198       SetFlag(kAllowUndefinedAsNaN);
7199     } else {
7200       SetChangesFlag(kArrayElements);
7201     }
7202
7203     // {UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
7204     if (elements_kind >= UINT8_ELEMENTS && elements_kind <= INT32_ELEMENTS) {
7205       SetFlag(kTruncatingToInt32);
7206     }
7207   }
7208
7209   class IsDehoistedField : public BitField<bool, 0, 1> {};
7210   class IsUninitializedField : public BitField<bool, 1, 1> {};
7211   class StoreModeField : public BitField<StoreFieldOrKeyedMode, 2, 1> {};
7212   class ElementsKindField : public BitField<ElementsKind, 3, 5> {};
7213
7214   uint32_t base_offset_;
7215   uint32_t bit_field_;
7216   HValue* dominator_;
7217 };
7218
7219
7220 class HStoreKeyedGeneric final : public HTemplateInstruction<4> {
7221  public:
7222   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HStoreKeyedGeneric, HValue*,
7223                                               HValue*, HValue*, LanguageMode,
7224                                               InlineCacheState);
7225
7226   HValue* object() const { return OperandAt(0); }
7227   HValue* key() const { return OperandAt(1); }
7228   HValue* value() const { return OperandAt(2); }
7229   HValue* context() const { return OperandAt(3); }
7230   LanguageMode language_mode() const { return language_mode_; }
7231   InlineCacheState initialization_state() const {
7232     return initialization_state_;
7233   }
7234
7235   Representation RequiredInputRepresentation(int index) override {
7236     // tagged[tagged] = tagged
7237     return Representation::Tagged();
7238   }
7239
7240   FeedbackVectorICSlot slot() const { return slot_; }
7241   Handle<TypeFeedbackVector> feedback_vector() const {
7242     return feedback_vector_;
7243   }
7244   bool HasVectorAndSlot() const {
7245     DCHECK(!(FLAG_vector_stores && initialization_state_ != MEGAMORPHIC) ||
7246            !feedback_vector_.is_null());
7247     return !feedback_vector_.is_null();
7248   }
7249   void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
7250                         FeedbackVectorICSlot slot) {
7251     feedback_vector_ = vector;
7252     slot_ = slot;
7253   }
7254
7255   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
7256
7257   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
7258
7259  private:
7260   HStoreKeyedGeneric(HValue* context, HValue* object, HValue* key,
7261                      HValue* value, LanguageMode language_mode,
7262                      InlineCacheState initialization_state)
7263       : slot_(FeedbackVectorICSlot::Invalid()),
7264         language_mode_(language_mode),
7265         initialization_state_(initialization_state) {
7266     SetOperandAt(0, object);
7267     SetOperandAt(1, key);
7268     SetOperandAt(2, value);
7269     SetOperandAt(3, context);
7270     SetAllSideEffects();
7271   }
7272
7273   Handle<TypeFeedbackVector> feedback_vector_;
7274   FeedbackVectorICSlot slot_;
7275   LanguageMode language_mode_;
7276   InlineCacheState initialization_state_;
7277 };
7278
7279
7280 class HTransitionElementsKind final : public HTemplateInstruction<2> {
7281  public:
7282   inline static HTransitionElementsKind* New(Isolate* isolate, Zone* zone,
7283                                              HValue* context, HValue* object,
7284                                              Handle<Map> original_map,
7285                                              Handle<Map> transitioned_map) {
7286     return new(zone) HTransitionElementsKind(context, object,
7287                                              original_map, transitioned_map);
7288   }
7289
7290   Representation RequiredInputRepresentation(int index) override {
7291     return Representation::Tagged();
7292   }
7293
7294   HValue* object() const { return OperandAt(0); }
7295   HValue* context() const { return OperandAt(1); }
7296   Unique<Map> original_map() const { return original_map_; }
7297   Unique<Map> transitioned_map() const { return transitioned_map_; }
7298   ElementsKind from_kind() const {
7299     return FromElementsKindField::decode(bit_field_);
7300   }
7301   ElementsKind to_kind() const {
7302     return ToElementsKindField::decode(bit_field_);
7303   }
7304   bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }
7305
7306   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
7307
7308   DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
7309
7310  protected:
7311   bool DataEquals(HValue* other) override {
7312     HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
7313     return original_map_ == instr->original_map_ &&
7314            transitioned_map_ == instr->transitioned_map_;
7315   }
7316
7317   int RedefinedOperandIndex() override { return 0; }
7318
7319  private:
7320   HTransitionElementsKind(HValue* context, HValue* object,
7321                           Handle<Map> original_map,
7322                           Handle<Map> transitioned_map)
7323       : original_map_(Unique<Map>(original_map)),
7324         transitioned_map_(Unique<Map>(transitioned_map)),
7325         bit_field_(
7326             FromElementsKindField::encode(original_map->elements_kind()) |
7327             ToElementsKindField::encode(transitioned_map->elements_kind()) |
7328             MapIsStableField::encode(transitioned_map->is_stable())) {
7329     SetOperandAt(0, object);
7330     SetOperandAt(1, context);
7331     SetFlag(kUseGVN);
7332     SetChangesFlag(kElementsKind);
7333     if (!IsSimpleMapChangeTransition(from_kind(), to_kind())) {
7334       SetChangesFlag(kElementsPointer);
7335       SetChangesFlag(kNewSpacePromotion);
7336     }
7337     set_representation(Representation::Tagged());
7338   }
7339
7340   class FromElementsKindField : public BitField<ElementsKind, 0, 5> {};
7341   class ToElementsKindField : public BitField<ElementsKind, 5, 5> {};
7342   class MapIsStableField : public BitField<bool, 10, 1> {};
7343
7344   Unique<Map> original_map_;
7345   Unique<Map> transitioned_map_;
7346   uint32_t bit_field_;
7347 };
7348
7349
7350 class HStringAdd final : public HBinaryOperation {
7351  public:
7352   static HInstruction* New(
7353       Isolate* isolate, Zone* zone, HValue* context, HValue* left,
7354       HValue* right, Strength strength = Strength::WEAK,
7355       PretenureFlag pretenure_flag = NOT_TENURED,
7356       StringAddFlags flags = STRING_ADD_CHECK_BOTH,
7357       Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null());
7358
7359   StringAddFlags flags() const { return flags_; }
7360   PretenureFlag pretenure_flag() const { return pretenure_flag_; }
7361
7362   Representation RequiredInputRepresentation(int index) override {
7363     return Representation::Tagged();
7364   }
7365
7366   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
7367
7368   DECLARE_CONCRETE_INSTRUCTION(StringAdd)
7369
7370  protected:
7371   bool DataEquals(HValue* other) override {
7372     return flags_ == HStringAdd::cast(other)->flags_ &&
7373         pretenure_flag_ == HStringAdd::cast(other)->pretenure_flag_;
7374   }
7375
7376  private:
7377   HStringAdd(HValue* context, HValue* left, HValue* right, Strength strength,
7378              PretenureFlag pretenure_flag, StringAddFlags flags,
7379              Handle<AllocationSite> allocation_site)
7380       : HBinaryOperation(context, left, right, strength, HType::String()),
7381         flags_(flags),
7382         pretenure_flag_(pretenure_flag) {
7383     set_representation(Representation::Tagged());
7384     SetFlag(kUseGVN);
7385     SetDependsOnFlag(kMaps);
7386     SetChangesFlag(kNewSpacePromotion);
7387     if (FLAG_trace_pretenuring) {
7388       PrintF("HStringAdd with AllocationSite %p %s\n",
7389              allocation_site.is_null()
7390                  ? static_cast<void*>(NULL)
7391                  : static_cast<void*>(*allocation_site),
7392              pretenure_flag == TENURED ? "tenured" : "not tenured");
7393     }
7394   }
7395
7396   // No side-effects except possible allocation:
7397   bool IsDeletable() const override { return true; }
7398
7399   const StringAddFlags flags_;
7400   const PretenureFlag pretenure_flag_;
7401 };
7402
7403
7404 class HStringCharCodeAt final : public HTemplateInstruction<3> {
7405  public:
7406   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HStringCharCodeAt,
7407                                               HValue*,
7408                                               HValue*);
7409
7410   Representation RequiredInputRepresentation(int index) override {
7411     // The index is supposed to be Integer32.
7412     return index == 2
7413         ? Representation::Integer32()
7414         : Representation::Tagged();
7415   }
7416
7417   HValue* context() const { return OperandAt(0); }
7418   HValue* string() const { return OperandAt(1); }
7419   HValue* index() const { return OperandAt(2); }
7420
7421   DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
7422
7423  protected:
7424   bool DataEquals(HValue* other) override { return true; }
7425
7426   Range* InferRange(Zone* zone) override {
7427     return new(zone) Range(0, String::kMaxUtf16CodeUnit);
7428   }
7429
7430  private:
7431   HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
7432     SetOperandAt(0, context);
7433     SetOperandAt(1, string);
7434     SetOperandAt(2, index);
7435     set_representation(Representation::Integer32());
7436     SetFlag(kUseGVN);
7437     SetDependsOnFlag(kMaps);
7438     SetDependsOnFlag(kStringChars);
7439     SetChangesFlag(kNewSpacePromotion);
7440   }
7441
7442   // No side effects: runtime function assumes string + number inputs.
7443   bool IsDeletable() const override { return true; }
7444 };
7445
7446
7447 class HStringCharFromCode final : public HTemplateInstruction<2> {
7448  public:
7449   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
7450                            HValue* char_code);
7451
7452   Representation RequiredInputRepresentation(int index) override {
7453     return index == 0
7454         ? Representation::Tagged()
7455         : Representation::Integer32();
7456   }
7457
7458   HValue* context() const { return OperandAt(0); }
7459   HValue* value() const { return OperandAt(1); }
7460
7461   bool DataEquals(HValue* other) override { return true; }
7462
7463   DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
7464
7465  private:
7466   HStringCharFromCode(HValue* context, HValue* char_code)
7467       : HTemplateInstruction<2>(HType::String()) {
7468     SetOperandAt(0, context);
7469     SetOperandAt(1, char_code);
7470     set_representation(Representation::Tagged());
7471     SetFlag(kUseGVN);
7472     SetChangesFlag(kNewSpacePromotion);
7473   }
7474
7475   bool IsDeletable() const override {
7476     return !value()->ToNumberCanBeObserved();
7477   }
7478 };
7479
7480
7481 template <int V>
7482 class HMaterializedLiteral : public HTemplateInstruction<V> {
7483  public:
7484   HMaterializedLiteral<V>(int index, int depth, AllocationSiteMode mode)
7485       : literal_index_(index), depth_(depth), allocation_site_mode_(mode) {
7486     this->set_representation(Representation::Tagged());
7487   }
7488
7489   HMaterializedLiteral<V>(int index, int depth)
7490       : literal_index_(index), depth_(depth),
7491         allocation_site_mode_(DONT_TRACK_ALLOCATION_SITE) {
7492     this->set_representation(Representation::Tagged());
7493   }
7494
7495   int literal_index() const { return literal_index_; }
7496   int depth() const { return depth_; }
7497   AllocationSiteMode allocation_site_mode() const {
7498     return allocation_site_mode_;
7499   }
7500
7501  private:
7502   bool IsDeletable() const final { return true; }
7503
7504   int literal_index_;
7505   int depth_;
7506   AllocationSiteMode allocation_site_mode_;
7507 };
7508
7509
7510 class HRegExpLiteral final : public HMaterializedLiteral<1> {
7511  public:
7512   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HRegExpLiteral,
7513                                               Handle<FixedArray>,
7514                                               Handle<String>,
7515                                               Handle<String>,
7516                                               int);
7517
7518   HValue* context() { return OperandAt(0); }
7519   Handle<FixedArray> literals() { return literals_; }
7520   Handle<String> pattern() { return pattern_; }
7521   Handle<String> flags() { return flags_; }
7522
7523   Representation RequiredInputRepresentation(int index) override {
7524     return Representation::Tagged();
7525   }
7526
7527   DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
7528
7529  private:
7530   HRegExpLiteral(HValue* context,
7531                  Handle<FixedArray> literals,
7532                  Handle<String> pattern,
7533                  Handle<String> flags,
7534                  int literal_index)
7535       : HMaterializedLiteral<1>(literal_index, 0),
7536         literals_(literals),
7537         pattern_(pattern),
7538         flags_(flags) {
7539     SetOperandAt(0, context);
7540     SetAllSideEffects();
7541     set_type(HType::JSObject());
7542   }
7543
7544   Handle<FixedArray> literals_;
7545   Handle<String> pattern_;
7546   Handle<String> flags_;
7547 };
7548
7549
7550 class HTypeof final : public HTemplateInstruction<2> {
7551  public:
7552   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HTypeof, HValue*);
7553
7554   HValue* context() const { return OperandAt(0); }
7555   HValue* value() const { return OperandAt(1); }
7556
7557   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
7558
7559   Representation RequiredInputRepresentation(int index) override {
7560     return Representation::Tagged();
7561   }
7562
7563   DECLARE_CONCRETE_INSTRUCTION(Typeof)
7564
7565  private:
7566   explicit HTypeof(HValue* context, HValue* value) {
7567     SetOperandAt(0, context);
7568     SetOperandAt(1, value);
7569     set_representation(Representation::Tagged());
7570   }
7571
7572   bool IsDeletable() const override { return true; }
7573 };
7574
7575
7576 class HTrapAllocationMemento final : public HTemplateInstruction<1> {
7577  public:
7578   DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
7579
7580   Representation RequiredInputRepresentation(int index) override {
7581     return Representation::Tagged();
7582   }
7583
7584   HValue* object() { return OperandAt(0); }
7585
7586   DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
7587
7588  private:
7589   explicit HTrapAllocationMemento(HValue* obj) {
7590     SetOperandAt(0, obj);
7591   }
7592 };
7593
7594
7595 class HMaybeGrowElements final : public HTemplateInstruction<5> {
7596  public:
7597   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(HMaybeGrowElements, HValue*,
7598                                               HValue*, HValue*, HValue*, bool,
7599                                               ElementsKind);
7600
7601   Representation RequiredInputRepresentation(int index) override {
7602     if (index < 3) {
7603       return Representation::Tagged();
7604     }
7605     DCHECK(index == 3 || index == 4);
7606     return Representation::Integer32();
7607   }
7608
7609   HValue* context() const { return OperandAt(0); }
7610   HValue* object() const { return OperandAt(1); }
7611   HValue* elements() const { return OperandAt(2); }
7612   HValue* key() const { return OperandAt(3); }
7613   HValue* current_capacity() const { return OperandAt(4); }
7614
7615   bool is_js_array() const { return is_js_array_; }
7616   ElementsKind kind() const { return kind_; }
7617
7618   DECLARE_CONCRETE_INSTRUCTION(MaybeGrowElements)
7619
7620  protected:
7621   bool DataEquals(HValue* other) override { return true; }
7622
7623  private:
7624   explicit HMaybeGrowElements(HValue* context, HValue* object, HValue* elements,
7625                               HValue* key, HValue* current_capacity,
7626                               bool is_js_array, ElementsKind kind) {
7627     is_js_array_ = is_js_array;
7628     kind_ = kind;
7629
7630     SetOperandAt(0, context);
7631     SetOperandAt(1, object);
7632     SetOperandAt(2, elements);
7633     SetOperandAt(3, key);
7634     SetOperandAt(4, current_capacity);
7635
7636     SetFlag(kUseGVN);
7637     SetChangesFlag(kElementsPointer);
7638     SetChangesFlag(kNewSpacePromotion);
7639     set_representation(Representation::Tagged());
7640   }
7641
7642   bool is_js_array_;
7643   ElementsKind kind_;
7644 };
7645
7646
7647 class HToFastProperties final : public HUnaryOperation {
7648  public:
7649   DECLARE_INSTRUCTION_FACTORY_P1(HToFastProperties, HValue*);
7650
7651   Representation RequiredInputRepresentation(int index) override {
7652     return Representation::Tagged();
7653   }
7654
7655   DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
7656
7657  private:
7658   explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
7659     set_representation(Representation::Tagged());
7660     SetChangesFlag(kNewSpacePromotion);
7661
7662     // This instruction is not marked as kChangesMaps, but does
7663     // change the map of the input operand. Use it only when creating
7664     // object literals via a runtime call.
7665     DCHECK(value->IsCallRuntime());
7666 #ifdef DEBUG
7667     const Runtime::Function* function = HCallRuntime::cast(value)->function();
7668     DCHECK(function->function_id == Runtime::kCreateObjectLiteral);
7669 #endif
7670   }
7671
7672   bool IsDeletable() const override { return true; }
7673 };
7674
7675
7676 class HDateField final : public HUnaryOperation {
7677  public:
7678   DECLARE_INSTRUCTION_FACTORY_P2(HDateField, HValue*, Smi*);
7679
7680   Smi* index() const { return index_; }
7681
7682   Representation RequiredInputRepresentation(int index) override {
7683     return Representation::Tagged();
7684   }
7685
7686   DECLARE_CONCRETE_INSTRUCTION(DateField)
7687
7688  private:
7689   HDateField(HValue* date, Smi* index)
7690       : HUnaryOperation(date), index_(index) {
7691     set_representation(Representation::Tagged());
7692   }
7693
7694   Smi* index_;
7695 };
7696
7697
7698 class HSeqStringGetChar final : public HTemplateInstruction<2> {
7699  public:
7700   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
7701                            String::Encoding encoding, HValue* string,
7702                            HValue* index);
7703
7704   Representation RequiredInputRepresentation(int index) override {
7705     return (index == 0) ? Representation::Tagged()
7706                         : Representation::Integer32();
7707   }
7708
7709   String::Encoding encoding() const { return encoding_; }
7710   HValue* string() const { return OperandAt(0); }
7711   HValue* index() const { return OperandAt(1); }
7712
7713   DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)
7714
7715  protected:
7716   bool DataEquals(HValue* other) override {
7717     return encoding() == HSeqStringGetChar::cast(other)->encoding();
7718   }
7719
7720   Range* InferRange(Zone* zone) override {
7721     if (encoding() == String::ONE_BYTE_ENCODING) {
7722       return new(zone) Range(0, String::kMaxOneByteCharCode);
7723     } else {
7724       DCHECK_EQ(String::TWO_BYTE_ENCODING, encoding());
7725       return  new(zone) Range(0, String::kMaxUtf16CodeUnit);
7726     }
7727   }
7728
7729  private:
7730   HSeqStringGetChar(String::Encoding encoding,
7731                     HValue* string,
7732                     HValue* index) : encoding_(encoding) {
7733     SetOperandAt(0, string);
7734     SetOperandAt(1, index);
7735     set_representation(Representation::Integer32());
7736     SetFlag(kUseGVN);
7737     SetDependsOnFlag(kStringChars);
7738   }
7739
7740   bool IsDeletable() const override { return true; }
7741
7742   String::Encoding encoding_;
7743 };
7744
7745
7746 class HSeqStringSetChar final : public HTemplateInstruction<4> {
7747  public:
7748   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(
7749       HSeqStringSetChar, String::Encoding,
7750       HValue*, HValue*, HValue*);
7751
7752   String::Encoding encoding() { return encoding_; }
7753   HValue* context() { return OperandAt(0); }
7754   HValue* string() { return OperandAt(1); }
7755   HValue* index() { return OperandAt(2); }
7756   HValue* value() { return OperandAt(3); }
7757
7758   Representation RequiredInputRepresentation(int index) override {
7759     return (index <= 1) ? Representation::Tagged()
7760                         : Representation::Integer32();
7761   }
7762
7763   DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
7764
7765  private:
7766   HSeqStringSetChar(HValue* context,
7767                     String::Encoding encoding,
7768                     HValue* string,
7769                     HValue* index,
7770                     HValue* value) : encoding_(encoding) {
7771     SetOperandAt(0, context);
7772     SetOperandAt(1, string);
7773     SetOperandAt(2, index);
7774     SetOperandAt(3, value);
7775     set_representation(Representation::Tagged());
7776     SetChangesFlag(kStringChars);
7777   }
7778
7779   String::Encoding encoding_;
7780 };
7781
7782
7783 class HCheckMapValue final : public HTemplateInstruction<2> {
7784  public:
7785   DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);
7786
7787   Representation RequiredInputRepresentation(int index) override {
7788     return Representation::Tagged();
7789   }
7790
7791   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
7792
7793   HType CalculateInferredType() override {
7794     if (value()->type().IsHeapObject()) return value()->type();
7795     return HType::HeapObject();
7796   }
7797
7798   HValue* value() const { return OperandAt(0); }
7799   HValue* map() const { return OperandAt(1); }
7800
7801   HValue* Canonicalize() override;
7802
7803   DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
7804
7805  protected:
7806   int RedefinedOperandIndex() override { return 0; }
7807
7808   bool DataEquals(HValue* other) override { return true; }
7809
7810  private:
7811   HCheckMapValue(HValue* value, HValue* map)
7812       : HTemplateInstruction<2>(HType::HeapObject()) {
7813     SetOperandAt(0, value);
7814     SetOperandAt(1, map);
7815     set_representation(Representation::Tagged());
7816     SetFlag(kUseGVN);
7817     SetDependsOnFlag(kMaps);
7818     SetDependsOnFlag(kElementsKind);
7819   }
7820 };
7821
7822
7823 class HForInPrepareMap final : public HTemplateInstruction<2> {
7824  public:
7825   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HForInPrepareMap, HValue*);
7826
7827   Representation RequiredInputRepresentation(int index) override {
7828     return Representation::Tagged();
7829   }
7830
7831   HValue* context() const { return OperandAt(0); }
7832   HValue* enumerable() const { return OperandAt(1); }
7833
7834   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
7835
7836   HType CalculateInferredType() override { return HType::Tagged(); }
7837
7838   DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
7839
7840  private:
7841   HForInPrepareMap(HValue* context,
7842                    HValue* object) {
7843     SetOperandAt(0, context);
7844     SetOperandAt(1, object);
7845     set_representation(Representation::Tagged());
7846     SetAllSideEffects();
7847   }
7848 };
7849
7850
7851 class HForInCacheArray final : public HTemplateInstruction<2> {
7852  public:
7853   DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
7854
7855   Representation RequiredInputRepresentation(int index) override {
7856     return Representation::Tagged();
7857   }
7858
7859   HValue* enumerable() const { return OperandAt(0); }
7860   HValue* map() const { return OperandAt(1); }
7861   int idx() const { return idx_; }
7862
7863   HForInCacheArray* index_cache() {
7864     return index_cache_;
7865   }
7866
7867   void set_index_cache(HForInCacheArray* index_cache) {
7868     index_cache_ = index_cache;
7869   }
7870
7871   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
7872
7873   HType CalculateInferredType() override { return HType::Tagged(); }
7874
7875   DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
7876
7877  private:
7878   HForInCacheArray(HValue* enumerable,
7879                    HValue* keys,
7880                    int idx) : idx_(idx) {
7881     SetOperandAt(0, enumerable);
7882     SetOperandAt(1, keys);
7883     set_representation(Representation::Tagged());
7884   }
7885
7886   int idx_;
7887   HForInCacheArray* index_cache_;
7888 };
7889
7890
7891 class HLoadFieldByIndex final : public HTemplateInstruction<2> {
7892  public:
7893   DECLARE_INSTRUCTION_FACTORY_P2(HLoadFieldByIndex, HValue*, HValue*);
7894
7895   HLoadFieldByIndex(HValue* object,
7896                     HValue* index) {
7897     SetOperandAt(0, object);
7898     SetOperandAt(1, index);
7899     SetChangesFlag(kNewSpacePromotion);
7900     set_representation(Representation::Tagged());
7901   }
7902
7903   Representation RequiredInputRepresentation(int index) override {
7904     if (index == 1) {
7905       return Representation::Smi();
7906     } else {
7907       return Representation::Tagged();
7908     }
7909   }
7910
7911   HValue* object() const { return OperandAt(0); }
7912   HValue* index() const { return OperandAt(1); }
7913
7914   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
7915
7916   HType CalculateInferredType() override { return HType::Tagged(); }
7917
7918   DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
7919
7920  private:
7921   bool IsDeletable() const override { return true; }
7922 };
7923
7924
7925 class HStoreFrameContext: public HUnaryOperation {
7926  public:
7927   DECLARE_INSTRUCTION_FACTORY_P1(HStoreFrameContext, HValue*);
7928
7929   HValue* context() { return OperandAt(0); }
7930
7931   Representation RequiredInputRepresentation(int index) override {
7932     return Representation::Tagged();
7933   }
7934
7935   DECLARE_CONCRETE_INSTRUCTION(StoreFrameContext)
7936  private:
7937   explicit HStoreFrameContext(HValue* context)
7938       : HUnaryOperation(context) {
7939     set_representation(Representation::Tagged());
7940     SetChangesFlag(kContextSlots);
7941   }
7942 };
7943
7944
7945 class HAllocateBlockContext: public HTemplateInstruction<2> {
7946  public:
7947   DECLARE_INSTRUCTION_FACTORY_P3(HAllocateBlockContext, HValue*,
7948                                  HValue*, Handle<ScopeInfo>);
7949   HValue* context() const { return OperandAt(0); }
7950   HValue* function() const { return OperandAt(1); }
7951   Handle<ScopeInfo> scope_info() const { return scope_info_; }
7952
7953   Representation RequiredInputRepresentation(int index) override {
7954     return Representation::Tagged();
7955   }
7956
7957   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
7958
7959   DECLARE_CONCRETE_INSTRUCTION(AllocateBlockContext)
7960
7961  private:
7962   HAllocateBlockContext(HValue* context,
7963                         HValue* function,
7964                         Handle<ScopeInfo> scope_info)
7965       : scope_info_(scope_info) {
7966     SetOperandAt(0, context);
7967     SetOperandAt(1, function);
7968     set_representation(Representation::Tagged());
7969   }
7970
7971   Handle<ScopeInfo> scope_info_;
7972 };
7973
7974
7975
7976 #undef DECLARE_INSTRUCTION
7977 #undef DECLARE_CONCRETE_INSTRUCTION
7978
7979 } }  // namespace v8::internal
7980
7981 #endif  // V8_HYDROGEN_INSTRUCTIONS_H_