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