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