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