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