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