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