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