• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_
6 #define V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_
7 
8 #include <cstring>
9 #include <iosfwd>
10 
11 #include "src/allocation.h"
12 #include "src/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<FeedbackVector>);
1948 
context()1949   HValue* context() { return OperandAt(0); }
declarations()1950   Handle<FixedArray> declarations() const { return declarations_; }
flags()1951   int flags() const { return flags_; }
feedback_vector()1952   Handle<FeedbackVector> feedback_vector() const { return feedback_vector_; }
1953 
DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)1954   DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
1955 
1956   Representation RequiredInputRepresentation(int index) override {
1957     return Representation::Tagged();
1958   }
1959 
1960  private:
HDeclareGlobals(HValue * context,Handle<FixedArray> declarations,int flags,Handle<FeedbackVector> feedback_vector)1961   HDeclareGlobals(HValue* context, Handle<FixedArray> declarations, int flags,
1962                   Handle<FeedbackVector> feedback_vector)
1963       : HUnaryOperation(context),
1964         declarations_(declarations),
1965         feedback_vector_(feedback_vector),
1966         flags_(flags) {
1967     set_representation(Representation::Tagged());
1968     SetAllSideEffects();
1969   }
1970 
1971   Handle<FixedArray> declarations_;
1972   Handle<FeedbackVector> feedback_vector_;
1973   int flags_;
1974 };
1975 
1976 
1977 template <int V>
1978 class HCall : public HTemplateInstruction<V> {
1979  public:
1980   // The argument count includes the receiver.
argument_count_(argument_count)1981   explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
1982     this->set_representation(Representation::Tagged());
1983     this->SetAllSideEffects();
1984   }
1985 
argument_count()1986   virtual int argument_count() const {
1987     return argument_count_;
1988   }
1989 
argument_delta()1990   int argument_delta() const override { return -argument_count(); }
1991 
1992  private:
1993   int argument_count_;
1994 };
1995 
1996 
1997 class HUnaryCall : public HCall<1> {
1998  public:
HUnaryCall(HValue * value,int argument_count)1999   HUnaryCall(HValue* value, int argument_count)
2000       : HCall<1>(argument_count) {
2001     SetOperandAt(0, value);
2002   }
2003 
RequiredInputRepresentation(int index)2004   Representation RequiredInputRepresentation(int index) final {
2005     return Representation::Tagged();
2006   }
2007 
2008   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
2009 
value()2010   HValue* value() const { return OperandAt(0); }
2011 };
2012 
2013 
2014 class HBinaryCall : public HCall<2> {
2015  public:
HBinaryCall(HValue * first,HValue * second,int argument_count)2016   HBinaryCall(HValue* first, HValue* second, int argument_count)
2017       : HCall<2>(argument_count) {
2018     SetOperandAt(0, first);
2019     SetOperandAt(1, second);
2020   }
2021 
2022   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
2023 
RequiredInputRepresentation(int index)2024   Representation RequiredInputRepresentation(int index) final {
2025     return Representation::Tagged();
2026   }
2027 
first()2028   HValue* first() const { return OperandAt(0); }
second()2029   HValue* second() const { return OperandAt(1); }
2030 };
2031 
2032 
2033 class HCallWithDescriptor final : public HInstruction {
2034  public:
2035   static HCallWithDescriptor* New(
2036       Isolate* isolate, Zone* zone, HValue* context, HValue* target,
2037       int argument_count, CallInterfaceDescriptor descriptor,
2038       const Vector<HValue*>& operands,
2039       TailCallMode syntactic_tail_call_mode = TailCallMode::kDisallow,
2040       TailCallMode tail_call_mode = TailCallMode::kDisallow) {
2041     HCallWithDescriptor* res = new (zone) HCallWithDescriptor(
2042         Code::STUB, context, target, argument_count, descriptor, operands,
2043         syntactic_tail_call_mode, tail_call_mode, zone);
2044     return res;
2045   }
2046 
2047   static HCallWithDescriptor* New(
2048       Isolate* isolate, Zone* zone, HValue* context, Code::Kind kind,
2049       HValue* target, int argument_count, CallInterfaceDescriptor descriptor,
2050       const Vector<HValue*>& operands,
2051       TailCallMode syntactic_tail_call_mode = TailCallMode::kDisallow,
2052       TailCallMode tail_call_mode = TailCallMode::kDisallow) {
2053     HCallWithDescriptor* res = new (zone) HCallWithDescriptor(
2054         kind, context, target, argument_count, descriptor, operands,
2055         syntactic_tail_call_mode, tail_call_mode, zone);
2056     return res;
2057   }
2058 
OperandCount()2059   int OperandCount() const final { return values_.length(); }
OperandAt(int index)2060   HValue* OperandAt(int index) const final { return values_[index]; }
2061 
RequiredInputRepresentation(int index)2062   Representation RequiredInputRepresentation(int index) final {
2063     if (index == 0 || index == 1) {
2064       // Target + context
2065       return Representation::Tagged();
2066     } else {
2067       int par_index = index - 2;
2068       DCHECK(par_index < GetParameterCount());
2069       return RepresentationFromMachineType(
2070           descriptor_.GetParameterType(par_index));
2071     }
2072   }
2073 
DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor)2074   DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor)
2075 
2076   // Defines whether this instruction corresponds to a JS call at tail position.
2077   TailCallMode syntactic_tail_call_mode() const {
2078     return SyntacticTailCallModeField::decode(bit_field_);
2079   }
2080 
2081   // Defines whether this call should be generated as a tail call.
tail_call_mode()2082   TailCallMode tail_call_mode() const {
2083     return TailCallModeField::decode(bit_field_);
2084   }
IsTailCall()2085   bool IsTailCall() const { return tail_call_mode() == TailCallMode::kAllow; }
2086 
kind()2087   Code::Kind kind() const { return KindField::decode(bit_field_); }
2088 
argument_count()2089   virtual int argument_count() const {
2090     return argument_count_;
2091   }
2092 
argument_delta()2093   int argument_delta() const override { return -argument_count_; }
2094 
descriptor()2095   CallInterfaceDescriptor descriptor() const { return descriptor_; }
2096 
target()2097   HValue* target() { return OperandAt(0); }
context()2098   HValue* context() { return OperandAt(1); }
parameter(int index)2099   HValue* parameter(int index) {
2100     DCHECK_LT(index, GetParameterCount());
2101     return OperandAt(index + 2);
2102   }
2103 
2104   HValue* Canonicalize() override;
2105 
2106   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
2107 
2108  private:
2109   // 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)2110   HCallWithDescriptor(Code::Kind kind, HValue* context, HValue* target,
2111                       int argument_count, CallInterfaceDescriptor descriptor,
2112                       const Vector<HValue*>& operands,
2113                       TailCallMode syntactic_tail_call_mode,
2114                       TailCallMode tail_call_mode, Zone* zone)
2115       : descriptor_(descriptor),
2116         values_(GetParameterCount() + 2, zone),  // +2 for context and target.
2117         argument_count_(argument_count),
2118         bit_field_(
2119             TailCallModeField::encode(tail_call_mode) |
2120             SyntacticTailCallModeField::encode(syntactic_tail_call_mode) |
2121             KindField::encode(kind)) {
2122     DCHECK_EQ(operands.length(), GetParameterCount());
2123     // We can only tail call without any stack arguments.
2124     DCHECK(tail_call_mode != TailCallMode::kAllow || argument_count == 0);
2125     AddOperand(target, zone);
2126     AddOperand(context, zone);
2127     for (int i = 0; i < operands.length(); i++) {
2128       AddOperand(operands[i], zone);
2129     }
2130     this->set_representation(Representation::Tagged());
2131     this->SetAllSideEffects();
2132   }
2133 
AddOperand(HValue * v,Zone * zone)2134   void AddOperand(HValue* v, Zone* zone) {
2135     values_.Add(NULL, zone);
2136     SetOperandAt(values_.length() - 1, v);
2137   }
2138 
GetParameterCount()2139   int GetParameterCount() const { return descriptor_.GetParameterCount(); }
2140 
InternalSetOperandAt(int index,HValue * value)2141   void InternalSetOperandAt(int index, HValue* value) final {
2142     values_[index] = value;
2143   }
2144 
2145   CallInterfaceDescriptor descriptor_;
2146   ZoneList<HValue*> values_;
2147   int argument_count_;
2148   class TailCallModeField : public BitField<TailCallMode, 0, 1> {};
2149   class SyntacticTailCallModeField
2150       : public BitField<TailCallMode, TailCallModeField::kNext, 1> {};
2151   class KindField
2152       : public BitField<Code::Kind, SyntacticTailCallModeField::kNext, 5> {};
2153   uint32_t bit_field_;
2154 };
2155 
2156 
2157 class HInvokeFunction final : public HBinaryCall {
2158  public:
2159   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HInvokeFunction, HValue*,
2160                                               Handle<JSFunction>, int,
2161                                               TailCallMode, TailCallMode);
2162 
context()2163   HValue* context() { return first(); }
function()2164   HValue* function() { return second(); }
known_function()2165   Handle<JSFunction> known_function() { return known_function_; }
formal_parameter_count()2166   int formal_parameter_count() const { return formal_parameter_count_; }
2167 
HasStackCheck()2168   bool HasStackCheck() final { return HasStackCheckField::decode(bit_field_); }
2169 
2170   // Defines whether this instruction corresponds to a JS call at tail position.
syntactic_tail_call_mode()2171   TailCallMode syntactic_tail_call_mode() const {
2172     return SyntacticTailCallModeField::decode(bit_field_);
2173   }
2174 
2175   // Defines whether this call should be generated as a tail call.
tail_call_mode()2176   TailCallMode tail_call_mode() const {
2177     return TailCallModeField::decode(bit_field_);
2178   }
2179 
2180   DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
2181 
2182   std::ostream& PrintTo(std::ostream& os) const override;      // NOLINT
2183   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
2184 
2185  private:
set_has_stack_check(bool has_stack_check)2186   void set_has_stack_check(bool has_stack_check) {
2187     bit_field_ = HasStackCheckField::update(bit_field_, has_stack_check);
2188   }
2189 
HInvokeFunction(HValue * context,HValue * function,Handle<JSFunction> known_function,int argument_count,TailCallMode syntactic_tail_call_mode,TailCallMode tail_call_mode)2190   HInvokeFunction(HValue* context, HValue* function,
2191                   Handle<JSFunction> known_function, int argument_count,
2192                   TailCallMode syntactic_tail_call_mode,
2193                   TailCallMode tail_call_mode)
2194       : HBinaryCall(context, function, argument_count),
2195         known_function_(known_function),
2196         bit_field_(
2197             TailCallModeField::encode(tail_call_mode) |
2198             SyntacticTailCallModeField::encode(syntactic_tail_call_mode)) {
2199     DCHECK(tail_call_mode != TailCallMode::kAllow ||
2200            syntactic_tail_call_mode == TailCallMode::kAllow);
2201     formal_parameter_count_ =
2202         known_function.is_null()
2203             ? 0
2204             : known_function->shared()->internal_formal_parameter_count();
2205     set_has_stack_check(
2206         !known_function.is_null() &&
2207         (known_function->code()->kind() == Code::FUNCTION ||
2208          known_function->code()->kind() == Code::OPTIMIZED_FUNCTION));
2209   }
2210 
2211   Handle<JSFunction> known_function_;
2212   int formal_parameter_count_;
2213 
2214   class HasStackCheckField : public BitField<bool, 0, 1> {};
2215   class TailCallModeField
2216       : public BitField<TailCallMode, HasStackCheckField::kNext, 1> {};
2217   class SyntacticTailCallModeField
2218       : public BitField<TailCallMode, TailCallModeField::kNext, 1> {};
2219   uint32_t bit_field_;
2220 };
2221 
2222 
2223 class HCallNewArray final : public HBinaryCall {
2224  public:
2225   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HCallNewArray, HValue*, int,
2226                                               ElementsKind,
2227                                               Handle<AllocationSite>);
2228 
context()2229   HValue* context() { return first(); }
constructor()2230   HValue* constructor() { return second(); }
2231 
2232   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
2233 
elements_kind()2234   ElementsKind elements_kind() const { return elements_kind_; }
site()2235   Handle<AllocationSite> site() const { return site_; }
2236 
DECLARE_CONCRETE_INSTRUCTION(CallNewArray)2237   DECLARE_CONCRETE_INSTRUCTION(CallNewArray)
2238 
2239  private:
2240   HCallNewArray(HValue* context, HValue* constructor, int argument_count,
2241                 ElementsKind elements_kind, Handle<AllocationSite> site)
2242       : HBinaryCall(context, constructor, argument_count),
2243         elements_kind_(elements_kind),
2244         site_(site) {}
2245 
2246   ElementsKind elements_kind_;
2247   Handle<AllocationSite> site_;
2248 };
2249 
2250 
2251 class HCallRuntime final : public HCall<1> {
2252  public:
2253   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallRuntime,
2254                                               const Runtime::Function*, int);
2255 
2256   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
2257 
context()2258   HValue* context() { return OperandAt(0); }
function()2259   const Runtime::Function* function() const { return c_function_; }
save_doubles()2260   SaveFPRegsMode save_doubles() const { return save_doubles_; }
set_save_doubles(SaveFPRegsMode save_doubles)2261   void set_save_doubles(SaveFPRegsMode save_doubles) {
2262     save_doubles_ = save_doubles;
2263   }
2264 
RequiredInputRepresentation(int index)2265   Representation RequiredInputRepresentation(int index) override {
2266     return Representation::Tagged();
2267   }
2268 
DECLARE_CONCRETE_INSTRUCTION(CallRuntime)2269   DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
2270 
2271  private:
2272   HCallRuntime(HValue* context, const Runtime::Function* c_function,
2273                int argument_count)
2274       : HCall<1>(argument_count),
2275         c_function_(c_function),
2276         save_doubles_(kDontSaveFPRegs) {
2277     SetOperandAt(0, context);
2278   }
2279 
2280   const Runtime::Function* c_function_;
2281   SaveFPRegsMode save_doubles_;
2282 };
2283 
2284 
2285 class HUnaryMathOperation final : public HTemplateInstruction<2> {
2286  public:
2287   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
2288                            HValue* value, BuiltinFunctionId op);
2289 
context()2290   HValue* context() const { return OperandAt(0); }
value()2291   HValue* value() const { return OperandAt(1); }
2292 
2293   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
2294 
RequiredInputRepresentation(int index)2295   Representation RequiredInputRepresentation(int index) override {
2296     if (index == 0) {
2297       return Representation::Tagged();
2298     } else {
2299       switch (op_) {
2300         case kMathCos:
2301         case kMathFloor:
2302         case kMathRound:
2303         case kMathFround:
2304         case kMathSin:
2305         case kMathSqrt:
2306         case kMathPowHalf:
2307         case kMathLog:
2308         case kMathExp:
2309           return Representation::Double();
2310         case kMathAbs:
2311           return representation();
2312         case kMathClz32:
2313           return Representation::Integer32();
2314         default:
2315           UNREACHABLE();
2316           return Representation::None();
2317       }
2318     }
2319   }
2320 
2321   Range* InferRange(Zone* zone) override;
2322 
2323   HValue* Canonicalize() override;
2324   Representation RepresentationFromUses() override;
2325   Representation RepresentationFromInputs() override;
2326 
op()2327   BuiltinFunctionId op() const { return op_; }
2328   const char* OpName() const;
2329 
DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)2330   DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
2331 
2332  protected:
2333   bool DataEquals(HValue* other) override {
2334     HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
2335     return op_ == b->op();
2336   }
2337 
2338  private:
2339   // Indicates if we support a double (and int32) output for Math.floor and
2340   // Math.round.
SupportsFlexibleFloorAndRound()2341   bool SupportsFlexibleFloorAndRound() const {
2342 #if V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_PPC
2343     return true;
2344 #elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
2345     return CpuFeatures::IsSupported(SSE4_1);
2346 #else
2347     return false;
2348 #endif
2349   }
HUnaryMathOperation(HValue * context,HValue * value,BuiltinFunctionId op)2350   HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
2351       : HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
2352     SetOperandAt(0, context);
2353     SetOperandAt(1, value);
2354     switch (op) {
2355       case kMathFloor:
2356       case kMathRound:
2357         if (SupportsFlexibleFloorAndRound()) {
2358           SetFlag(kFlexibleRepresentation);
2359         } else {
2360           set_representation(Representation::Integer32());
2361         }
2362         break;
2363       case kMathClz32:
2364         set_representation(Representation::Integer32());
2365         break;
2366       case kMathAbs:
2367         // Not setting representation here: it is None intentionally.
2368         SetFlag(kFlexibleRepresentation);
2369         // TODO(svenpanne) This flag is actually only needed if representation()
2370         // is tagged, and not when it is an unboxed double or unboxed integer.
2371         SetChangesFlag(kNewSpacePromotion);
2372         break;
2373       case kMathCos:
2374       case kMathFround:
2375       case kMathLog:
2376       case kMathExp:
2377       case kMathSin:
2378       case kMathSqrt:
2379       case kMathPowHalf:
2380         set_representation(Representation::Double());
2381         break;
2382       default:
2383         UNREACHABLE();
2384     }
2385     SetFlag(kUseGVN);
2386     SetFlag(kTruncatingToNumber);
2387   }
2388 
IsDeletable()2389   bool IsDeletable() const override {
2390     // TODO(crankshaft): This should be true, however the semantics of this
2391     // instruction also include the ToNumber conversion that is mentioned in the
2392     // spec, which is of course observable.
2393     return false;
2394   }
2395 
2396   HValue* SimplifiedDividendForMathFloorOfDiv(HDiv* hdiv);
2397   HValue* SimplifiedDivisorForMathFloorOfDiv(HDiv* hdiv);
2398 
2399   BuiltinFunctionId op_;
2400 };
2401 
2402 
2403 class HLoadRoot final : public HTemplateInstruction<0> {
2404  public:
2405   DECLARE_INSTRUCTION_FACTORY_P1(HLoadRoot, Heap::RootListIndex);
2406   DECLARE_INSTRUCTION_FACTORY_P2(HLoadRoot, Heap::RootListIndex, HType);
2407 
RequiredInputRepresentation(int index)2408   Representation RequiredInputRepresentation(int index) override {
2409     return Representation::None();
2410   }
2411 
index()2412   Heap::RootListIndex index() const { return index_; }
2413 
DECLARE_CONCRETE_INSTRUCTION(LoadRoot)2414   DECLARE_CONCRETE_INSTRUCTION(LoadRoot)
2415 
2416  protected:
2417   bool DataEquals(HValue* other) override {
2418     HLoadRoot* b = HLoadRoot::cast(other);
2419     return index_ == b->index_;
2420   }
2421 
2422  private:
2423   explicit HLoadRoot(Heap::RootListIndex index, HType type = HType::Tagged())
2424       : HTemplateInstruction<0>(type), index_(index) {
2425     SetFlag(kUseGVN);
2426     // TODO(bmeurer): We'll need kDependsOnRoots once we add the
2427     // corresponding HStoreRoot instruction.
2428     SetDependsOnFlag(kCalls);
2429     set_representation(Representation::Tagged());
2430   }
2431 
IsDeletable()2432   bool IsDeletable() const override { return true; }
2433 
2434   const Heap::RootListIndex index_;
2435 };
2436 
2437 
2438 class HCheckMaps final : public HTemplateInstruction<2> {
2439  public:
2440   static HCheckMaps* New(Isolate* isolate, Zone* zone, HValue* context,
2441                          HValue* value, Handle<Map> map,
2442                          HValue* typecheck = NULL) {
2443     return new(zone) HCheckMaps(value, new(zone) UniqueSet<Map>(
2444             Unique<Map>::CreateImmovable(map), zone), typecheck);
2445   }
2446   static HCheckMaps* New(Isolate* isolate, Zone* zone, HValue* context,
2447                          HValue* value, SmallMapList* map_list,
2448                          HValue* typecheck = NULL) {
2449     UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone);
2450     for (int i = 0; i < map_list->length(); ++i) {
2451       maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone);
2452     }
2453     return new(zone) HCheckMaps(value, maps, typecheck);
2454   }
2455 
IsStabilityCheck()2456   bool IsStabilityCheck() const {
2457     return IsStabilityCheckField::decode(bit_field_);
2458   }
MarkAsStabilityCheck()2459   void MarkAsStabilityCheck() {
2460     bit_field_ = MapsAreStableField::encode(true) |
2461                  HasMigrationTargetField::encode(false) |
2462                  IsStabilityCheckField::encode(true);
2463     ClearChangesFlag(kNewSpacePromotion);
2464     ClearDependsOnFlag(kElementsKind);
2465     ClearDependsOnFlag(kMaps);
2466   }
2467 
HasEscapingOperandAt(int index)2468   bool HasEscapingOperandAt(int index) override { return false; }
RequiredInputRepresentation(int index)2469   Representation RequiredInputRepresentation(int index) override {
2470     return Representation::Tagged();
2471   }
2472 
CalculateInferredType()2473   HType CalculateInferredType() override {
2474     if (value()->type().IsHeapObject()) return value()->type();
2475     return HType::HeapObject();
2476   }
2477 
2478   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
2479 
value()2480   HValue* value() const { return OperandAt(0); }
typecheck()2481   HValue* typecheck() const { return OperandAt(1); }
2482 
maps()2483   const UniqueSet<Map>* maps() const { return maps_; }
set_maps(const UniqueSet<Map> * maps)2484   void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; }
2485 
maps_are_stable()2486   bool maps_are_stable() const {
2487     return MapsAreStableField::decode(bit_field_);
2488   }
2489 
HasMigrationTarget()2490   bool HasMigrationTarget() const {
2491     return HasMigrationTargetField::decode(bit_field_);
2492   }
2493 
2494   HValue* Canonicalize() override;
2495 
CreateAndInsertAfter(Zone * zone,HValue * value,Unique<Map> map,bool map_is_stable,HInstruction * instr)2496   static HCheckMaps* CreateAndInsertAfter(Zone* zone,
2497                                           HValue* value,
2498                                           Unique<Map> map,
2499                                           bool map_is_stable,
2500                                           HInstruction* instr) {
2501     return instr->Append(new(zone) HCheckMaps(
2502             value, new(zone) UniqueSet<Map>(map, zone), map_is_stable));
2503   }
2504 
CreateAndInsertBefore(Zone * zone,HValue * value,const UniqueSet<Map> * maps,bool maps_are_stable,HInstruction * instr)2505   static HCheckMaps* CreateAndInsertBefore(Zone* zone,
2506                                            HValue* value,
2507                                            const UniqueSet<Map>* maps,
2508                                            bool maps_are_stable,
2509                                            HInstruction* instr) {
2510     return instr->Prepend(new(zone) HCheckMaps(value, maps, maps_are_stable));
2511   }
2512 
DECLARE_CONCRETE_INSTRUCTION(CheckMaps)2513   DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
2514 
2515  protected:
2516   bool DataEquals(HValue* other) override {
2517     return this->maps()->Equals(HCheckMaps::cast(other)->maps());
2518   }
2519 
RedefinedOperandIndex()2520   int RedefinedOperandIndex() override { return 0; }
2521 
2522  private:
HCheckMaps(HValue * value,const UniqueSet<Map> * maps,bool maps_are_stable)2523   HCheckMaps(HValue* value, const UniqueSet<Map>* maps, bool maps_are_stable)
2524       : HTemplateInstruction<2>(HType::HeapObject()),
2525         maps_(maps),
2526         bit_field_(HasMigrationTargetField::encode(false) |
2527                    IsStabilityCheckField::encode(false) |
2528                    MapsAreStableField::encode(maps_are_stable)) {
2529     DCHECK_NE(0, maps->size());
2530     SetOperandAt(0, value);
2531     // Use the object value for the dependency.
2532     SetOperandAt(1, value);
2533     set_representation(Representation::Tagged());
2534     SetFlag(kUseGVN);
2535     SetDependsOnFlag(kMaps);
2536     SetDependsOnFlag(kElementsKind);
2537   }
2538 
HCheckMaps(HValue * value,const UniqueSet<Map> * maps,HValue * typecheck)2539   HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck)
2540       : HTemplateInstruction<2>(HType::HeapObject()),
2541         maps_(maps),
2542         bit_field_(HasMigrationTargetField::encode(false) |
2543                    IsStabilityCheckField::encode(false) |
2544                    MapsAreStableField::encode(true)) {
2545     DCHECK_NE(0, maps->size());
2546     SetOperandAt(0, value);
2547     // Use the object value for the dependency if NULL is passed.
2548     SetOperandAt(1, typecheck ? typecheck : value);
2549     set_representation(Representation::Tagged());
2550     SetFlag(kUseGVN);
2551     SetDependsOnFlag(kMaps);
2552     SetDependsOnFlag(kElementsKind);
2553     for (int i = 0; i < maps->size(); ++i) {
2554       Handle<Map> map = maps->at(i).handle();
2555       if (map->is_migration_target()) {
2556         bit_field_ = HasMigrationTargetField::update(bit_field_, true);
2557       }
2558       if (!map->is_stable()) {
2559         bit_field_ = MapsAreStableField::update(bit_field_, false);
2560       }
2561     }
2562     if (HasMigrationTarget()) SetChangesFlag(kNewSpacePromotion);
2563   }
2564 
2565   class HasMigrationTargetField : public BitField<bool, 0, 1> {};
2566   class IsStabilityCheckField : public BitField<bool, 1, 1> {};
2567   class MapsAreStableField : public BitField<bool, 2, 1> {};
2568 
2569   const UniqueSet<Map>* maps_;
2570   uint32_t bit_field_;
2571 };
2572 
2573 
2574 class HCheckValue final : public HUnaryOperation {
2575  public:
New(Isolate * isolate,Zone * zone,HValue * context,HValue * value,Handle<JSFunction> func)2576   static HCheckValue* New(Isolate* isolate, Zone* zone, HValue* context,
2577                           HValue* value, Handle<JSFunction> func) {
2578     bool in_new_space = isolate->heap()->InNewSpace(*func);
2579     // NOTE: We create an uninitialized Unique and initialize it later.
2580     // This is because a JSFunction can move due to GC during graph creation.
2581     Unique<JSFunction> target = Unique<JSFunction>::CreateUninitialized(func);
2582     HCheckValue* check = new(zone) HCheckValue(value, target, in_new_space);
2583     return check;
2584   }
New(Isolate * isolate,Zone * zone,HValue * context,HValue * value,Unique<HeapObject> target,bool object_in_new_space)2585   static HCheckValue* New(Isolate* isolate, Zone* zone, HValue* context,
2586                           HValue* value, Unique<HeapObject> target,
2587                           bool object_in_new_space) {
2588     return new(zone) HCheckValue(value, target, object_in_new_space);
2589   }
2590 
FinalizeUniqueness()2591   void FinalizeUniqueness() override {
2592     object_ = Unique<HeapObject>(object_.handle());
2593   }
2594 
RequiredInputRepresentation(int index)2595   Representation RequiredInputRepresentation(int index) override {
2596     return Representation::Tagged();
2597   }
2598   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
2599 
2600   HValue* Canonicalize() override;
2601 
2602 #ifdef DEBUG
2603   void Verify() override;
2604 #endif
2605 
object()2606   Unique<HeapObject> object() const { return object_; }
object_in_new_space()2607   bool object_in_new_space() const { return object_in_new_space_; }
2608 
DECLARE_CONCRETE_INSTRUCTION(CheckValue)2609   DECLARE_CONCRETE_INSTRUCTION(CheckValue)
2610 
2611  protected:
2612   bool DataEquals(HValue* other) override {
2613     HCheckValue* b = HCheckValue::cast(other);
2614     return object_ == b->object_;
2615   }
2616 
2617  private:
HCheckValue(HValue * value,Unique<HeapObject> object,bool object_in_new_space)2618   HCheckValue(HValue* value, Unique<HeapObject> object,
2619                bool object_in_new_space)
2620       : HUnaryOperation(value, value->type()),
2621         object_(object),
2622         object_in_new_space_(object_in_new_space) {
2623     set_representation(Representation::Tagged());
2624     SetFlag(kUseGVN);
2625   }
2626 
2627   Unique<HeapObject> object_;
2628   bool object_in_new_space_;
2629 };
2630 
2631 
2632 class HCheckInstanceType final : public HUnaryOperation {
2633  public:
2634   enum Check {
2635     IS_JS_RECEIVER,
2636     IS_JS_ARRAY,
2637     IS_JS_FUNCTION,
2638     IS_JS_DATE,
2639     IS_STRING,
2640     IS_INTERNALIZED_STRING,
2641     LAST_INTERVAL_CHECK = IS_JS_DATE
2642   };
2643 
2644   DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue*, Check);
2645 
2646   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
2647 
RequiredInputRepresentation(int index)2648   Representation RequiredInputRepresentation(int index) override {
2649     return Representation::Tagged();
2650   }
2651 
CalculateInferredType()2652   HType CalculateInferredType() override {
2653     switch (check_) {
2654       case IS_JS_RECEIVER: return HType::JSReceiver();
2655       case IS_JS_ARRAY: return HType::JSArray();
2656       case IS_JS_FUNCTION:
2657         return HType::JSObject();
2658       case IS_JS_DATE: return HType::JSObject();
2659       case IS_STRING: return HType::String();
2660       case IS_INTERNALIZED_STRING: return HType::String();
2661     }
2662     UNREACHABLE();
2663     return HType::Tagged();
2664   }
2665 
2666   HValue* Canonicalize() override;
2667 
is_interval_check()2668   bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
2669   void GetCheckInterval(InstanceType* first, InstanceType* last);
2670   void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
2671 
check()2672   Check check() const { return check_; }
2673 
DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)2674   DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
2675 
2676  protected:
2677   // TODO(ager): It could be nice to allow the ommision of instance
2678   // type checks if we have already performed an instance type check
2679   // with a larger range.
2680   bool DataEquals(HValue* other) override {
2681     HCheckInstanceType* b = HCheckInstanceType::cast(other);
2682     return check_ == b->check_;
2683   }
2684 
RedefinedOperandIndex()2685   int RedefinedOperandIndex() override { return 0; }
2686 
2687  private:
2688   const char* GetCheckName() const;
2689 
HCheckInstanceType(HValue * value,Check check)2690   HCheckInstanceType(HValue* value, Check check)
2691       : HUnaryOperation(value, HType::HeapObject()), check_(check) {
2692     set_representation(Representation::Tagged());
2693     SetFlag(kUseGVN);
2694   }
2695 
2696   const Check check_;
2697 };
2698 
2699 
2700 class HCheckSmi final : public HUnaryOperation {
2701  public:
2702   DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue*);
2703 
RequiredInputRepresentation(int index)2704   Representation RequiredInputRepresentation(int index) override {
2705     return Representation::Tagged();
2706   }
2707 
Canonicalize()2708   HValue* Canonicalize() override {
2709     HType value_type = value()->type();
2710     if (value_type.IsSmi()) {
2711       return NULL;
2712     }
2713     return this;
2714   }
2715 
DECLARE_CONCRETE_INSTRUCTION(CheckSmi)2716   DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
2717 
2718  protected:
2719   bool DataEquals(HValue* other) override { return true; }
2720 
2721  private:
HCheckSmi(HValue * value)2722   explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
2723     set_representation(Representation::Smi());
2724     SetFlag(kUseGVN);
2725   }
2726 };
2727 
2728 
2729 class HCheckArrayBufferNotNeutered final : public HUnaryOperation {
2730  public:
2731   DECLARE_INSTRUCTION_FACTORY_P1(HCheckArrayBufferNotNeutered, HValue*);
2732 
HasEscapingOperandAt(int index)2733   bool HasEscapingOperandAt(int index) override { return false; }
RequiredInputRepresentation(int index)2734   Representation RequiredInputRepresentation(int index) override {
2735     return Representation::Tagged();
2736   }
2737 
CalculateInferredType()2738   HType CalculateInferredType() override {
2739     if (value()->type().IsHeapObject()) return value()->type();
2740     return HType::HeapObject();
2741   }
2742 
DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered)2743   DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered)
2744 
2745  protected:
2746   bool DataEquals(HValue* other) override { return true; }
RedefinedOperandIndex()2747   int RedefinedOperandIndex() override { return 0; }
2748 
2749  private:
HCheckArrayBufferNotNeutered(HValue * value)2750   explicit HCheckArrayBufferNotNeutered(HValue* value)
2751       : HUnaryOperation(value) {
2752     set_representation(Representation::Tagged());
2753     SetFlag(kUseGVN);
2754     SetDependsOnFlag(kCalls);
2755   }
2756 };
2757 
2758 
2759 class HCheckHeapObject final : public HUnaryOperation {
2760  public:
2761   DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
2762 
HasEscapingOperandAt(int index)2763   bool HasEscapingOperandAt(int index) override { return false; }
RequiredInputRepresentation(int index)2764   Representation RequiredInputRepresentation(int index) override {
2765     return Representation::Tagged();
2766   }
2767 
CalculateInferredType()2768   HType CalculateInferredType() override {
2769     if (value()->type().IsHeapObject()) return value()->type();
2770     return HType::HeapObject();
2771   }
2772 
2773 #ifdef DEBUG
2774   void Verify() override;
2775 #endif
2776 
Canonicalize()2777   HValue* Canonicalize() override {
2778     return value()->type().IsHeapObject() ? NULL : this;
2779   }
2780 
DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)2781   DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
2782 
2783  protected:
2784   bool DataEquals(HValue* other) override { return true; }
2785 
2786  private:
HCheckHeapObject(HValue * value)2787   explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) {
2788     set_representation(Representation::Tagged());
2789     SetFlag(kUseGVN);
2790   }
2791 };
2792 
2793 
2794 class HPhi final : public HValue {
2795  public:
HPhi(int merged_index,Zone * zone)2796   HPhi(int merged_index, Zone* zone)
2797       : inputs_(2, zone), merged_index_(merged_index) {
2798     DCHECK(merged_index >= 0 || merged_index == kInvalidMergedIndex);
2799     SetFlag(kFlexibleRepresentation);
2800   }
2801 
2802   Representation RepresentationFromInputs() override;
2803 
2804   Range* InferRange(Zone* zone) override;
2805   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
RequiredInputRepresentation(int index)2806   Representation RequiredInputRepresentation(int index) override {
2807     return representation();
2808   }
KnownOptimalRepresentation()2809   Representation KnownOptimalRepresentation() override {
2810     return representation();
2811   }
2812   HType CalculateInferredType() override;
OperandCount()2813   int OperandCount() const override { return inputs_.length(); }
OperandAt(int index)2814   HValue* OperandAt(int index) const override { return inputs_[index]; }
2815   HValue* GetRedundantReplacement();
2816   void AddInput(HValue* value);
2817   bool HasRealUses();
2818 
IsReceiver()2819   bool IsReceiver() const { return merged_index_ == 0; }
HasMergedIndex()2820   bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
2821 
2822   SourcePosition position() const override;
2823 
merged_index()2824   int merged_index() const { return merged_index_; }
2825 
2826   std::ostream& PrintTo(std::ostream& os) const override;  // NOLINT
2827 
2828 #ifdef DEBUG
2829   void Verify() override;
2830 #endif
2831 
2832   void InitRealUses(int id);
2833   void AddNonPhiUsesFrom(HPhi* other);
2834 
representation_from_indirect_uses()2835   Representation representation_from_indirect_uses() const {
2836     return representation_from_indirect_uses_;
2837   }
2838 
has_type_feedback_from_uses()2839   bool has_type_feedback_from_uses() const {
2840     return has_type_feedback_from_uses_;
2841   }
2842 
phi_id()2843   int phi_id() { return phi_id_; }
2844 
cast(HValue * value)2845   static HPhi* cast(HValue* value) {
2846     DCHECK(value->IsPhi());
2847     return reinterpret_cast<HPhi*>(value);
2848   }
opcode()2849   Opcode opcode() const override { return HValue::kPhi; }
2850 
2851   void SimplifyConstantInputs();
2852 
2853   // Marker value representing an invalid merge index.
2854   static const int kInvalidMergedIndex = -1;
2855 
2856  protected:
2857   void DeleteFromGraph() override;
InternalSetOperandAt(int index,HValue * value)2858   void InternalSetOperandAt(int index, HValue* value) override {
2859     inputs_[index] = value;
2860   }
2861 
2862  private:
representation_from_non_phi_uses()2863   Representation representation_from_non_phi_uses() const {
2864     return representation_from_non_phi_uses_;
2865   }
2866 
2867   ZoneList<HValue*> inputs_;
2868   int merged_index_ = 0;
2869 
2870   int phi_id_ = -1;
2871 
2872   Representation representation_from_indirect_uses_ = Representation::None();
2873   Representation representation_from_non_phi_uses_ = Representation::None();
2874   bool has_type_feedback_from_uses_ = false;
2875 
IsDeletable()2876   bool IsDeletable() const override { return !IsReceiver(); }
2877 };
2878 
2879 
2880 // Common base class for HArgumentsObject and HCapturedObject.
2881 class HDematerializedObject : public HInstruction {
2882  public:
HDematerializedObject(int count,Zone * zone)2883   HDematerializedObject(int count, Zone* zone) : values_(count, zone) {}
2884 
OperandCount()2885   int OperandCount() const final { return values_.length(); }
OperandAt(int index)2886   HValue* OperandAt(int index) const final { return values_[index]; }
2887 
HasEscapingOperandAt(int index)2888   bool HasEscapingOperandAt(int index) final { return false; }
RequiredInputRepresentation(int index)2889   Representation RequiredInputRepresentation(int index) final {
2890     return Representation::None();
2891   }
2892 
2893  protected:
InternalSetOperandAt(int index,HValue * value)2894   void InternalSetOperandAt(int index, HValue* value) final {
2895     values_[index] = value;
2896   }
2897 
2898   // List of values tracked by this marker.
2899   ZoneList<HValue*> values_;
2900 };
2901 
2902 
2903 class HArgumentsObject final : public HDematerializedObject {
2904  public:
New(Isolate * isolate,Zone * zone,HValue * context,int count)2905   static HArgumentsObject* New(Isolate* isolate, Zone* zone, HValue* context,
2906                                int count) {
2907     return new(zone) HArgumentsObject(count, zone);
2908   }
2909 
2910   // The values contain a list of all elements in the arguments object
2911   // including the receiver object, which is skipped when materializing.
arguments_values()2912   const ZoneList<HValue*>* arguments_values() const { return &values_; }
arguments_count()2913   int arguments_count() const { return values_.length(); }
2914 
AddArgument(HValue * argument,Zone * zone)2915   void AddArgument(HValue* argument, Zone* zone) {
2916     values_.Add(NULL, zone);  // Resize list.
2917     SetOperandAt(values_.length() - 1, argument);
2918   }
2919 
DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)2920   DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
2921 
2922  private:
2923   HArgumentsObject(int count, Zone* zone)
2924       : HDematerializedObject(count, zone) {
2925     set_representation(Representation::Tagged());
2926     SetFlag(kIsArguments);
2927   }
2928 };
2929 
2930 
2931 class HCapturedObject final : public HDematerializedObject {
2932  public:
HCapturedObject(int length,int id,Zone * zone)2933   HCapturedObject(int length, int id, Zone* zone)
2934       : HDematerializedObject(length, zone), capture_id_(id) {
2935     set_representation(Representation::Tagged());
2936     values_.AddBlock(NULL, length, zone);  // Resize list.
2937   }
2938 
2939   // The values contain a list of all in-object properties inside the
2940   // captured object and is index by field index. Properties in the
2941   // properties or elements backing store are not tracked here.
values()2942   const ZoneList<HValue*>* values() const { return &values_; }
length()2943   int length() const { return values_.length(); }
capture_id()2944   int capture_id() const { return capture_id_; }
2945 
2946   // Shortcut for the map value of this captured object.
map_value()2947   HValue* map_value() const { return values()->first(); }
2948 
ReuseSideEffectsFromStore(HInstruction * store)2949   void ReuseSideEffectsFromStore(HInstruction* store) {
2950     DCHECK(store->HasObservableSideEffects());
2951     DCHECK(store->IsStoreNamedField());
2952     changes_flags_.Add(store->ChangesFlags());
2953   }
2954 
2955   // Replay effects of this instruction on the given environment.
2956   void ReplayEnvironment(HEnvironment* env);
2957 
2958   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
2959 
DECLARE_CONCRETE_INSTRUCTION(CapturedObject)2960   DECLARE_CONCRETE_INSTRUCTION(CapturedObject)
2961 
2962  private:
2963   int capture_id_;
2964 
2965   // Note that we cannot DCE captured objects as they are used to replay
2966   // the environment. This method is here as an explicit reminder.
2967   // TODO(mstarzinger): Turn HSimulates into full snapshots maybe?
2968   bool IsDeletable() const final { return false; }
2969 };
2970 
2971 
2972 class HConstant final : public HTemplateInstruction<0> {
2973  public:
2974   enum Special { kHoleNaN };
2975 
2976   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Special);
2977   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, int32_t);
2978   DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation);
2979   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double);
2980   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle<Object>);
2981   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);
2982 
CreateAndInsertAfter(Isolate * isolate,Zone * zone,HValue * context,int32_t value,Representation representation,HInstruction * instruction)2983   static HConstant* CreateAndInsertAfter(Isolate* isolate, Zone* zone,
2984                                          HValue* context, int32_t value,
2985                                          Representation representation,
2986                                          HInstruction* instruction) {
2987     return instruction->Append(
2988         HConstant::New(isolate, zone, context, value, representation));
2989   }
2990 
GetMonomorphicJSObjectMap()2991   Handle<Map> GetMonomorphicJSObjectMap() override {
2992     Handle<Object> object = object_.handle();
2993     if (!object.is_null() && object->IsHeapObject()) {
2994       return v8::internal::handle(HeapObject::cast(*object)->map());
2995     }
2996     return Handle<Map>();
2997   }
2998 
CreateAndInsertBefore(Isolate * isolate,Zone * zone,HValue * context,int32_t value,Representation representation,HInstruction * instruction)2999   static HConstant* CreateAndInsertBefore(Isolate* isolate, Zone* zone,
3000                                           HValue* context, int32_t value,
3001                                           Representation representation,
3002                                           HInstruction* instruction) {
3003     return instruction->Prepend(
3004         HConstant::New(isolate, zone, context, value, representation));
3005   }
3006 
CreateAndInsertBefore(Zone * zone,Unique<Map> map,bool map_is_stable,HInstruction * instruction)3007   static HConstant* CreateAndInsertBefore(Zone* zone,
3008                                           Unique<Map> map,
3009                                           bool map_is_stable,
3010                                           HInstruction* instruction) {
3011     return instruction->Prepend(new(zone) HConstant(
3012         map, Unique<Map>(Handle<Map>::null()), map_is_stable,
3013         Representation::Tagged(), HType::HeapObject(), true,
3014         false, false, MAP_TYPE));
3015   }
3016 
CreateAndInsertAfter(Zone * zone,Unique<Map> map,bool map_is_stable,HInstruction * instruction)3017   static HConstant* CreateAndInsertAfter(Zone* zone,
3018                                          Unique<Map> map,
3019                                          bool map_is_stable,
3020                                          HInstruction* instruction) {
3021     return instruction->Append(new(zone) HConstant(
3022             map, Unique<Map>(Handle<Map>::null()), map_is_stable,
3023             Representation::Tagged(), HType::HeapObject(), true,
3024             false, false, MAP_TYPE));
3025   }
3026 
handle(Isolate * isolate)3027   Handle<Object> handle(Isolate* isolate) {
3028     if (object_.handle().is_null()) {
3029       // Default arguments to is_not_in_new_space depend on this heap number
3030       // to be tenured so that it's guaranteed not to be located in new space.
3031       object_ = Unique<Object>::CreateUninitialized(
3032           isolate->factory()->NewNumber(double_value_, TENURED));
3033     }
3034     AllowDeferredHandleDereference smi_check;
3035     DCHECK(HasInteger32Value() || !object_.handle()->IsSmi());
3036     return object_.handle();
3037   }
3038 
IsSpecialDouble()3039   bool IsSpecialDouble() const {
3040     return HasDoubleValue() &&
3041            (bit_cast<int64_t>(double_value_) == bit_cast<int64_t>(-0.0) ||
3042             std::isnan(double_value_));
3043   }
3044 
NotInNewSpace()3045   bool NotInNewSpace() const {
3046     return IsNotInNewSpaceField::decode(bit_field_);
3047   }
3048 
3049   bool ImmortalImmovable() const;
3050 
IsCell()3051   bool IsCell() const {
3052     InstanceType instance_type = GetInstanceType();
3053     return instance_type == CELL_TYPE;
3054   }
3055 
RequiredInputRepresentation(int index)3056   Representation RequiredInputRepresentation(int index) override {
3057     return Representation::None();
3058   }
3059 
KnownOptimalRepresentation()3060   Representation KnownOptimalRepresentation() override {
3061     if (HasSmiValue() && SmiValuesAre31Bits()) return Representation::Smi();
3062     if (HasInteger32Value()) return Representation::Integer32();
3063     if (HasNumberValue()) return Representation::Double();
3064     if (HasExternalReferenceValue()) return Representation::External();
3065     return Representation::Tagged();
3066   }
3067 
3068   bool EmitAtUses() override;
3069   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
3070   HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
3071   Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone);
3072   Maybe<HConstant*> CopyToTruncatedNumber(Isolate* isolate, Zone* zone);
HasInteger32Value()3073   bool HasInteger32Value() const {
3074     return HasInt32ValueField::decode(bit_field_);
3075   }
Integer32Value()3076   int32_t Integer32Value() const {
3077     DCHECK(HasInteger32Value());
3078     return int32_value_;
3079   }
HasSmiValue()3080   bool HasSmiValue() const { return HasSmiValueField::decode(bit_field_); }
HasDoubleValue()3081   bool HasDoubleValue() const {
3082     return HasDoubleValueField::decode(bit_field_);
3083   }
DoubleValue()3084   double DoubleValue() const {
3085     DCHECK(HasDoubleValue());
3086     return double_value_;
3087   }
DoubleValueAsBits()3088   uint64_t DoubleValueAsBits() const {
3089     DCHECK(HasDoubleValue());
3090     return bit_cast<uint64_t>(double_value_);
3091   }
IsTheHole()3092   bool IsTheHole() const {
3093     if (HasDoubleValue() && DoubleValueAsBits() == kHoleNanInt64) {
3094       return true;
3095     }
3096     return object_.IsInitialized() &&
3097            object_.IsKnownGlobal(isolate()->heap()->the_hole_value());
3098   }
HasNumberValue()3099   bool HasNumberValue() const { return HasDoubleValue(); }
NumberValueAsInteger32()3100   int32_t NumberValueAsInteger32() const {
3101     DCHECK(HasNumberValue());
3102     // Irrespective of whether a numeric HConstant can be safely
3103     // represented as an int32, we store the (in some cases lossy)
3104     // representation of the number in int32_value_.
3105     return int32_value_;
3106   }
HasStringValue()3107   bool HasStringValue() const {
3108     if (HasNumberValue()) return false;
3109     DCHECK(!object_.handle().is_null());
3110     return GetInstanceType() < FIRST_NONSTRING_TYPE;
3111   }
StringValue()3112   Handle<String> StringValue() const {
3113     DCHECK(HasStringValue());
3114     return Handle<String>::cast(object_.handle());
3115   }
HasInternalizedStringValue()3116   bool HasInternalizedStringValue() const {
3117     return HasStringValue() && StringShape(GetInstanceType()).IsInternalized();
3118   }
3119 
HasExternalReferenceValue()3120   bool HasExternalReferenceValue() const {
3121     return HasExternalReferenceValueField::decode(bit_field_);
3122   }
ExternalReferenceValue()3123   ExternalReference ExternalReferenceValue() const {
3124     return external_reference_value_;
3125   }
3126 
HasBooleanValue()3127   bool HasBooleanValue() const { return type_.IsBoolean(); }
BooleanValue()3128   bool BooleanValue() const { return BooleanValueField::decode(bit_field_); }
IsCallable()3129   bool IsCallable() const { return IsCallableField::decode(bit_field_); }
IsUndetectable()3130   bool IsUndetectable() const {
3131     return IsUndetectableField::decode(bit_field_);
3132   }
GetInstanceType()3133   InstanceType GetInstanceType() const {
3134     return InstanceTypeField::decode(bit_field_);
3135   }
3136 
HasMapValue()3137   bool HasMapValue() const { return GetInstanceType() == MAP_TYPE; }
MapValue()3138   Unique<Map> MapValue() const {
3139     DCHECK(HasMapValue());
3140     return Unique<Map>::cast(GetUnique());
3141   }
HasStableMapValue()3142   bool HasStableMapValue() const {
3143     DCHECK(HasMapValue() || !HasStableMapValueField::decode(bit_field_));
3144     return HasStableMapValueField::decode(bit_field_);
3145   }
3146 
HasObjectMap()3147   bool HasObjectMap() const { return !object_map_.IsNull(); }
ObjectMap()3148   Unique<Map> ObjectMap() const {
3149     DCHECK(HasObjectMap());
3150     return object_map_;
3151   }
3152 
Hashcode()3153   intptr_t Hashcode() override {
3154     if (HasInteger32Value()) {
3155       return static_cast<intptr_t>(int32_value_);
3156     } else if (HasDoubleValue()) {
3157       uint64_t bits = DoubleValueAsBits();
3158       if (sizeof(bits) > sizeof(intptr_t)) {
3159         bits ^= (bits >> 32);
3160       }
3161       return static_cast<intptr_t>(bits);
3162     } else if (HasExternalReferenceValue()) {
3163       return reinterpret_cast<intptr_t>(external_reference_value_.address());
3164     } else {
3165       DCHECK(!object_.handle().is_null());
3166       return object_.Hashcode();
3167     }
3168   }
3169 
FinalizeUniqueness()3170   void FinalizeUniqueness() override {
3171     if (!HasDoubleValue() && !HasExternalReferenceValue()) {
3172       DCHECK(!object_.handle().is_null());
3173       object_ = Unique<Object>(object_.handle());
3174     }
3175   }
3176 
GetUnique()3177   Unique<Object> GetUnique() const {
3178     return object_;
3179   }
3180 
EqualsUnique(Unique<Object> other)3181   bool EqualsUnique(Unique<Object> other) const {
3182     return object_.IsInitialized() && object_ == other;
3183   }
3184 
DataEquals(HValue * other)3185   bool DataEquals(HValue* other) override {
3186     HConstant* other_constant = HConstant::cast(other);
3187     if (HasInteger32Value()) {
3188       return other_constant->HasInteger32Value() &&
3189              int32_value_ == other_constant->int32_value_;
3190     } else if (HasDoubleValue()) {
3191       return other_constant->HasDoubleValue() &&
3192              std::memcmp(&double_value_, &other_constant->double_value_,
3193                          sizeof(double_value_)) == 0;
3194     } else if (HasExternalReferenceValue()) {
3195       return other_constant->HasExternalReferenceValue() &&
3196              external_reference_value_ ==
3197                  other_constant->external_reference_value_;
3198     } else {
3199       if (other_constant->HasInteger32Value() ||
3200           other_constant->HasDoubleValue() ||
3201           other_constant->HasExternalReferenceValue()) {
3202         return false;
3203       }
3204       DCHECK(!object_.handle().is_null());
3205       return other_constant->object_ == object_;
3206     }
3207   }
3208 
3209 #ifdef DEBUG
Verify()3210   void Verify() override {}
3211 #endif
3212 
3213   DECLARE_CONCRETE_INSTRUCTION(Constant)
3214 
3215  protected:
3216   Range* InferRange(Zone* zone) override;
3217 
3218  private:
3219   friend class HGraph;
3220   explicit HConstant(Special special);
3221   explicit HConstant(Handle<Object> handle,
3222                      Representation r = Representation::None());
3223   HConstant(int32_t value,
3224             Representation r = Representation::None(),
3225             bool is_not_in_new_space = true,
3226             Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3227   HConstant(double value,
3228             Representation r = Representation::None(),
3229             bool is_not_in_new_space = true,
3230             Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3231   HConstant(Unique<Object> object,
3232             Unique<Map> object_map,
3233             bool has_stable_map_value,
3234             Representation r,
3235             HType type,
3236             bool is_not_in_new_space,
3237             bool boolean_value,
3238             bool is_undetectable,
3239             InstanceType instance_type);
3240 
3241   explicit HConstant(ExternalReference reference);
3242 
3243   void Initialize(Representation r);
3244 
IsDeletable()3245   bool IsDeletable() const override { return true; }
3246 
3247   // If object_ is a map, this indicates whether the map is stable.
3248   class HasStableMapValueField : public BitField<bool, 0, 1> {};
3249 
3250   // We store the HConstant in the most specific form safely possible.
3251   // These flags tell us if the respective member fields hold valid, safe
3252   // representations of the constant. More specific flags imply more general
3253   // flags, but not the converse (i.e. smi => int32 => double).
3254   class HasSmiValueField : public BitField<bool, 1, 1> {};
3255   class HasInt32ValueField : public BitField<bool, 2, 1> {};
3256   class HasDoubleValueField : public BitField<bool, 3, 1> {};
3257 
3258   class HasExternalReferenceValueField : public BitField<bool, 4, 1> {};
3259   class IsNotInNewSpaceField : public BitField<bool, 5, 1> {};
3260   class BooleanValueField : public BitField<bool, 6, 1> {};
3261   class IsUndetectableField : public BitField<bool, 7, 1> {};
3262   class IsCallableField : public BitField<bool, 8, 1> {};
3263 
3264   static const InstanceType kUnknownInstanceType = FILLER_TYPE;
3265   class InstanceTypeField : public BitField<InstanceType, 16, 8> {};
3266 
3267   // If this is a numerical constant, object_ either points to the
3268   // HeapObject the constant originated from or is null.  If the
3269   // constant is non-numeric, object_ always points to a valid
3270   // constant HeapObject.
3271   Unique<Object> object_;
3272 
3273   // If object_ is a heap object, this points to the stable map of the object.
3274   Unique<Map> object_map_;
3275 
3276   uint32_t bit_field_;
3277 
3278   int32_t int32_value_;
3279   double double_value_;
3280   ExternalReference external_reference_value_;
3281 };
3282 
3283 
3284 class HBinaryOperation : public HTemplateInstruction<3> {
3285  public:
3286   HBinaryOperation(HValue* context, HValue* left, HValue* right,
3287                    HType type = HType::Tagged())
3288       : HTemplateInstruction<3>(type),
3289         observed_output_representation_(Representation::None()) {
3290     DCHECK(left != NULL && right != NULL);
3291     SetOperandAt(0, context);
3292     SetOperandAt(1, left);
3293     SetOperandAt(2, right);
3294     observed_input_representation_[0] = Representation::None();
3295     observed_input_representation_[1] = Representation::None();
3296   }
3297 
context()3298   HValue* context() const { return OperandAt(0); }
left()3299   HValue* left() const { return OperandAt(1); }
right()3300   HValue* right() const { return OperandAt(2); }
3301 
3302   // True if switching left and right operands likely generates better code.
AreOperandsBetterSwitched()3303   bool AreOperandsBetterSwitched() {
3304     if (!IsCommutative()) return false;
3305 
3306     // Constant operands are better off on the right, they can be inlined in
3307     // many situations on most platforms.
3308     if (left()->IsConstant()) return true;
3309     if (right()->IsConstant()) return false;
3310 
3311     // Otherwise, if there is only one use of the right operand, it would be
3312     // better off on the left for platforms that only have 2-arg arithmetic
3313     // ops (e.g ia32, x64) that clobber the left operand.
3314     return right()->HasOneUse();
3315   }
3316 
BetterLeftOperand()3317   HValue* BetterLeftOperand() {
3318     return AreOperandsBetterSwitched() ? right() : left();
3319   }
3320 
BetterRightOperand()3321   HValue* BetterRightOperand() {
3322     return AreOperandsBetterSwitched() ? left() : right();
3323   }
3324 
set_observed_input_representation(int index,Representation rep)3325   void set_observed_input_representation(int index, Representation rep) {
3326     DCHECK(index >= 1 && index <= 2);
3327     observed_input_representation_[index - 1] = rep;
3328   }
3329 
initialize_output_representation(Representation observed)3330   virtual void initialize_output_representation(Representation observed) {
3331     observed_output_representation_ = observed;
3332   }
3333 
observed_input_representation(int index)3334   Representation observed_input_representation(int index) override {
3335     if (index == 0) return Representation::Tagged();
3336     return observed_input_representation_[index - 1];
3337   }
3338 
UpdateRepresentation(Representation new_rep,HInferRepresentationPhase * h_infer,const char * reason)3339   void UpdateRepresentation(Representation new_rep,
3340                             HInferRepresentationPhase* h_infer,
3341                             const char* reason) override {
3342     Representation rep = !FLAG_smi_binop && new_rep.IsSmi()
3343         ? Representation::Integer32() : new_rep;
3344     HValue::UpdateRepresentation(rep, h_infer, reason);
3345   }
3346 
3347   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
3348   Representation RepresentationFromInputs() override;
3349   Representation RepresentationFromOutput();
3350   void AssumeRepresentation(Representation r) override;
3351 
IsCommutative()3352   virtual bool IsCommutative() const { return false; }
3353 
3354   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
3355 
RequiredInputRepresentation(int index)3356   Representation RequiredInputRepresentation(int index) override {
3357     if (index == 0) return Representation::Tagged();
3358     return representation();
3359   }
3360 
RightIsPowerOf2()3361   bool RightIsPowerOf2() {
3362     if (!right()->IsInteger32Constant()) return false;
3363     int32_t value = right()->GetInteger32Constant();
3364     if (value < 0) {
3365       return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(-value));
3366     }
3367     return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(value));
3368   }
3369 
3370   DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
3371 
3372  private:
3373   bool IgnoreObservedOutputRepresentation(Representation current_rep);
3374 
3375   Representation observed_input_representation_[2];
3376   Representation observed_output_representation_;
3377 };
3378 
3379 
3380 class HWrapReceiver final : public HTemplateInstruction<2> {
3381  public:
3382   DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
3383 
DataEquals(HValue * other)3384   bool DataEquals(HValue* other) override { return true; }
3385 
RequiredInputRepresentation(int index)3386   Representation RequiredInputRepresentation(int index) override {
3387     return Representation::Tagged();
3388   }
3389 
receiver()3390   HValue* receiver() const { return OperandAt(0); }
function()3391   HValue* function() const { return OperandAt(1); }
3392 
3393   HValue* Canonicalize() override;
3394 
3395   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
known_function()3396   bool known_function() const { return known_function_; }
3397 
DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)3398   DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
3399 
3400  private:
3401   HWrapReceiver(HValue* receiver, HValue* function) {
3402     known_function_ = function->IsConstant() &&
3403         HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
3404     set_representation(Representation::Tagged());
3405     SetOperandAt(0, receiver);
3406     SetOperandAt(1, function);
3407     SetFlag(kUseGVN);
3408   }
3409 
3410   bool known_function_;
3411 };
3412 
3413 
3414 class HApplyArguments final : public HTemplateInstruction<4> {
3415  public:
3416   DECLARE_INSTRUCTION_FACTORY_P5(HApplyArguments, HValue*, HValue*, HValue*,
3417                                  HValue*, TailCallMode);
3418 
RequiredInputRepresentation(int index)3419   Representation RequiredInputRepresentation(int index) override {
3420     // The length is untagged, all other inputs are tagged.
3421     return (index == 2)
3422         ? Representation::Integer32()
3423         : Representation::Tagged();
3424   }
3425 
function()3426   HValue* function() { return OperandAt(0); }
receiver()3427   HValue* receiver() { return OperandAt(1); }
length()3428   HValue* length() { return OperandAt(2); }
elements()3429   HValue* elements() { return OperandAt(3); }
3430 
tail_call_mode()3431   TailCallMode tail_call_mode() const {
3432     return TailCallModeField::decode(bit_field_);
3433   }
3434 
DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)3435   DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
3436 
3437  private:
3438   HApplyArguments(HValue* function, HValue* receiver, HValue* length,
3439                   HValue* elements, TailCallMode tail_call_mode)
3440       : bit_field_(TailCallModeField::encode(tail_call_mode)) {
3441     set_representation(Representation::Tagged());
3442     SetOperandAt(0, function);
3443     SetOperandAt(1, receiver);
3444     SetOperandAt(2, length);
3445     SetOperandAt(3, elements);
3446     SetAllSideEffects();
3447   }
3448 
3449   class TailCallModeField : public BitField<TailCallMode, 0, 1> {};
3450   uint32_t bit_field_;
3451 };
3452 
3453 
3454 class HArgumentsElements final : public HTemplateInstruction<0> {
3455  public:
3456   DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
3457   DECLARE_INSTRUCTION_FACTORY_P2(HArgumentsElements, bool, bool);
3458 
DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)3459   DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
3460 
3461   Representation RequiredInputRepresentation(int index) override {
3462     return Representation::None();
3463   }
3464 
from_inlined()3465   bool from_inlined() const { return from_inlined_; }
arguments_adaptor()3466   bool arguments_adaptor() const { return arguments_adaptor_; }
3467 
3468  protected:
DataEquals(HValue * other)3469   bool DataEquals(HValue* other) override { return true; }
3470 
3471  private:
3472   explicit HArgumentsElements(bool from_inlined, bool arguments_adaptor = true)
from_inlined_(from_inlined)3473       : from_inlined_(from_inlined), arguments_adaptor_(arguments_adaptor) {
3474     // The value produced by this instruction is a pointer into the stack
3475     // that looks as if it was a smi because of alignment.
3476     set_representation(Representation::Tagged());
3477     SetFlag(kUseGVN);
3478   }
3479 
IsDeletable()3480   bool IsDeletable() const override { return true; }
3481 
3482   bool from_inlined_;
3483   bool arguments_adaptor_;
3484 };
3485 
3486 
3487 class HArgumentsLength final : public HUnaryOperation {
3488  public:
3489   DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue*);
3490 
RequiredInputRepresentation(int index)3491   Representation RequiredInputRepresentation(int index) override {
3492     return Representation::Tagged();
3493   }
3494 
DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)3495   DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
3496 
3497  protected:
3498   bool DataEquals(HValue* other) override { return true; }
3499 
3500  private:
HArgumentsLength(HValue * value)3501   explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
3502     set_representation(Representation::Integer32());
3503     SetFlag(kUseGVN);
3504   }
3505 
IsDeletable()3506   bool IsDeletable() const override { return true; }
3507 };
3508 
3509 
3510 class HAccessArgumentsAt final : public HTemplateInstruction<3> {
3511  public:
3512   DECLARE_INSTRUCTION_FACTORY_P3(HAccessArgumentsAt, HValue*, HValue*, HValue*);
3513 
3514   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
3515 
RequiredInputRepresentation(int index)3516   Representation RequiredInputRepresentation(int index) override {
3517     // The arguments elements is considered tagged.
3518     return index == 0
3519         ? Representation::Tagged()
3520         : Representation::Integer32();
3521   }
3522 
arguments()3523   HValue* arguments() const { return OperandAt(0); }
length()3524   HValue* length() const { return OperandAt(1); }
index()3525   HValue* index() const { return OperandAt(2); }
3526 
DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)3527   DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
3528 
3529  private:
3530   HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
3531     set_representation(Representation::Tagged());
3532     SetFlag(kUseGVN);
3533     SetOperandAt(0, arguments);
3534     SetOperandAt(1, length);
3535     SetOperandAt(2, index);
3536   }
3537 
DataEquals(HValue * other)3538   bool DataEquals(HValue* other) override { return true; }
3539 };
3540 
3541 
3542 class HBoundsCheck final : public HTemplateInstruction<2> {
3543  public:
3544   DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
3545 
skip_check()3546   bool skip_check() const { return skip_check_; }
set_skip_check()3547   void set_skip_check() { skip_check_ = true; }
3548 
base()3549   HValue* base() const { return base_; }
offset()3550   int offset() const { return offset_; }
scale()3551   int scale() const { return scale_; }
3552 
RequiredInputRepresentation(int index)3553   Representation RequiredInputRepresentation(int index) override {
3554     return representation();
3555   }
3556 
3557   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
3558   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
3559 
index()3560   HValue* index() const { return OperandAt(0); }
length()3561   HValue* length() const { return OperandAt(1); }
allow_equality()3562   bool allow_equality() const { return allow_equality_; }
set_allow_equality(bool v)3563   void set_allow_equality(bool v) { allow_equality_ = v; }
3564 
RedefinedOperandIndex()3565   int RedefinedOperandIndex() override { return 0; }
IsPurelyInformativeDefinition()3566   bool IsPurelyInformativeDefinition() override { return skip_check(); }
3567 
3568   DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
3569 
3570  protected:
3571   Range* InferRange(Zone* zone) override;
3572 
DataEquals(HValue * other)3573   bool DataEquals(HValue* other) override { return true; }
3574   bool skip_check_;
3575   HValue* base_;
3576   int offset_;
3577   int scale_;
3578   bool allow_equality_;
3579 
3580  private:
3581   // Normally HBoundsCheck should be created using the
3582   // HGraphBuilder::AddBoundsCheck() helper.
3583   // However when building stubs, where we know that the arguments are Int32,
3584   // it makes sense to invoke this constructor directly.
HBoundsCheck(HValue * index,HValue * length)3585   HBoundsCheck(HValue* index, HValue* length)
3586     : skip_check_(false),
3587       base_(NULL), offset_(0), scale_(0),
3588       allow_equality_(false) {
3589     SetOperandAt(0, index);
3590     SetOperandAt(1, length);
3591     SetFlag(kFlexibleRepresentation);
3592     SetFlag(kUseGVN);
3593   }
3594 
IsDeletable()3595   bool IsDeletable() const override { return skip_check() && !FLAG_debug_code; }
3596 };
3597 
3598 
3599 class HBitwiseBinaryOperation : public HBinaryOperation {
3600  public:
3601   HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
3602                           HType type = HType::TaggedNumber())
HBinaryOperation(context,left,right,type)3603       : HBinaryOperation(context, left, right, type) {
3604     SetFlag(kFlexibleRepresentation);
3605     SetFlag(kTruncatingToInt32);
3606     SetFlag(kTruncatingToNumber);
3607     SetAllSideEffects();
3608   }
3609 
RepresentationChanged(Representation to)3610   void RepresentationChanged(Representation to) override {
3611     if (to.IsTagged() &&
3612         (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
3613       SetAllSideEffects();
3614       ClearFlag(kUseGVN);
3615     } else {
3616       ClearAllSideEffects();
3617       SetFlag(kUseGVN);
3618     }
3619     if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
3620   }
3621 
UpdateRepresentation(Representation new_rep,HInferRepresentationPhase * h_infer,const char * reason)3622   void UpdateRepresentation(Representation new_rep,
3623                             HInferRepresentationPhase* h_infer,
3624                             const char* reason) override {
3625     // We only generate either int32 or generic tagged bitwise operations.
3626     if (new_rep.IsDouble()) new_rep = Representation::Integer32();
3627     HBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
3628   }
3629 
observed_input_representation(int index)3630   Representation observed_input_representation(int index) override {
3631     Representation r = HBinaryOperation::observed_input_representation(index);
3632     if (r.IsDouble()) return Representation::Integer32();
3633     return r;
3634   }
3635 
initialize_output_representation(Representation observed)3636   void initialize_output_representation(Representation observed) override {
3637     if (observed.IsDouble()) observed = Representation::Integer32();
3638     HBinaryOperation::initialize_output_representation(observed);
3639   }
3640 
DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)3641   DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
3642 
3643  private:
3644   bool IsDeletable() const override { return true; }
3645 };
3646 
3647 
3648 class HMathFloorOfDiv final : public HBinaryOperation {
3649  public:
3650   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HMathFloorOfDiv,
3651                                               HValue*,
3652                                               HValue*);
3653 
DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)3654   DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
3655 
3656  protected:
3657   bool DataEquals(HValue* other) override { return true; }
3658 
3659  private:
HMathFloorOfDiv(HValue * context,HValue * left,HValue * right)3660   HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
3661       : HBinaryOperation(context, left, right) {
3662     set_representation(Representation::Integer32());
3663     SetFlag(kUseGVN);
3664     SetFlag(kCanOverflow);
3665     SetFlag(kCanBeDivByZero);
3666     SetFlag(kLeftCanBeMinInt);
3667     SetFlag(kLeftCanBeNegative);
3668     SetFlag(kLeftCanBePositive);
3669     SetFlag(kTruncatingToNumber);
3670   }
3671 
3672   Range* InferRange(Zone* zone) override;
3673 
IsDeletable()3674   bool IsDeletable() const override { return true; }
3675 };
3676 
3677 
3678 class HArithmeticBinaryOperation : public HBinaryOperation {
3679  public:
3680   HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right,
3681                              HType type = HType::TaggedNumber())
HBinaryOperation(context,left,right,type)3682       : HBinaryOperation(context, left, right, type) {
3683     SetAllSideEffects();
3684     SetFlag(kFlexibleRepresentation);
3685     SetFlag(kTruncatingToNumber);
3686   }
3687 
RepresentationChanged(Representation to)3688   void RepresentationChanged(Representation to) override {
3689     if (to.IsTagged() &&
3690         (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
3691       SetAllSideEffects();
3692       ClearFlag(kUseGVN);
3693     } else {
3694       ClearAllSideEffects();
3695       SetFlag(kUseGVN);
3696     }
3697     if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
3698   }
3699 
DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)3700   DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
3701 
3702  private:
3703   bool IsDeletable() const override { return true; }
3704 };
3705 
3706 
3707 class HCompareGeneric final : public HBinaryOperation {
3708  public:
New(Isolate * isolate,Zone * zone,HValue * context,HValue * left,HValue * right,Token::Value token)3709   static HCompareGeneric* New(Isolate* isolate, Zone* zone, HValue* context,
3710                               HValue* left, HValue* right, Token::Value token) {
3711     return new (zone) HCompareGeneric(context, left, right, token);
3712   }
3713 
RequiredInputRepresentation(int index)3714   Representation RequiredInputRepresentation(int index) override {
3715     return index == 0
3716         ? Representation::Tagged()
3717         : representation();
3718   }
3719 
token()3720   Token::Value token() const { return token_; }
3721   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
3722 
DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)3723   DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
3724 
3725  private:
3726   HCompareGeneric(HValue* context, HValue* left, HValue* right,
3727                   Token::Value token)
3728       : HBinaryOperation(context, left, right, HType::Boolean()),
3729         token_(token) {
3730     DCHECK(Token::IsCompareOp(token));
3731     set_representation(Representation::Tagged());
3732     SetAllSideEffects();
3733   }
3734 
3735   Token::Value token_;
3736 };
3737 
3738 
3739 class HCompareNumericAndBranch : public HTemplateControlInstruction<2, 2> {
3740  public:
3741   static HCompareNumericAndBranch* New(Isolate* isolate, Zone* zone,
3742                                        HValue* context, HValue* left,
3743                                        HValue* right, Token::Value token,
3744                                        HBasicBlock* true_target = NULL,
3745                                        HBasicBlock* false_target = NULL) {
3746     return new (zone)
3747         HCompareNumericAndBranch(left, right, token, true_target, false_target);
3748   }
3749 
left()3750   HValue* left() const { return OperandAt(0); }
right()3751   HValue* right() const { return OperandAt(1); }
token()3752   Token::Value token() const { return token_; }
3753 
set_observed_input_representation(Representation left,Representation right)3754   void set_observed_input_representation(Representation left,
3755                                          Representation right) {
3756       observed_input_representation_[0] = left;
3757       observed_input_representation_[1] = right;
3758   }
3759 
3760   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
3761 
RequiredInputRepresentation(int index)3762   Representation RequiredInputRepresentation(int index) override {
3763     return representation();
3764   }
observed_input_representation(int index)3765   Representation observed_input_representation(int index) override {
3766     return observed_input_representation_[index];
3767   }
3768 
3769   bool KnownSuccessorBlock(HBasicBlock** block) override;
3770 
3771   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
3772 
DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)3773   DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
3774 
3775  private:
3776   HCompareNumericAndBranch(HValue* left, HValue* right, Token::Value token,
3777                            HBasicBlock* true_target, HBasicBlock* false_target)
3778       : token_(token) {
3779     SetFlag(kFlexibleRepresentation);
3780     DCHECK(Token::IsCompareOp(token));
3781     SetOperandAt(0, left);
3782     SetOperandAt(1, right);
3783     SetSuccessorAt(0, true_target);
3784     SetSuccessorAt(1, false_target);
3785   }
3786 
3787   Representation observed_input_representation_[2];
3788   Token::Value token_;
3789 };
3790 
3791 
3792 class HCompareHoleAndBranch final : public HUnaryControlInstruction {
3793  public:
3794   DECLARE_INSTRUCTION_FACTORY_P1(HCompareHoleAndBranch, HValue*);
3795   DECLARE_INSTRUCTION_FACTORY_P3(HCompareHoleAndBranch, HValue*,
3796                                  HBasicBlock*, HBasicBlock*);
3797 
3798   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
3799 
RequiredInputRepresentation(int index)3800   Representation RequiredInputRepresentation(int index) override {
3801     return representation();
3802   }
3803 
DECLARE_CONCRETE_INSTRUCTION(CompareHoleAndBranch)3804   DECLARE_CONCRETE_INSTRUCTION(CompareHoleAndBranch)
3805 
3806  private:
3807   HCompareHoleAndBranch(HValue* value,
3808                         HBasicBlock* true_target = NULL,
3809                         HBasicBlock* false_target = NULL)
3810       : HUnaryControlInstruction(value, true_target, false_target) {
3811     SetFlag(kFlexibleRepresentation);
3812   }
3813 };
3814 
3815 
3816 class HCompareObjectEqAndBranch : public HTemplateControlInstruction<2, 2> {
3817  public:
3818   DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue*, HValue*);
3819   DECLARE_INSTRUCTION_FACTORY_P4(HCompareObjectEqAndBranch, HValue*, HValue*,
3820                                  HBasicBlock*, HBasicBlock*);
3821 
3822   bool KnownSuccessorBlock(HBasicBlock** block) override;
3823 
3824   static const int kNoKnownSuccessorIndex = -1;
known_successor_index()3825   int known_successor_index() const { return known_successor_index_; }
set_known_successor_index(int known_successor_index)3826   void set_known_successor_index(int known_successor_index) {
3827     known_successor_index_ = known_successor_index;
3828   }
3829 
left()3830   HValue* left() const { return OperandAt(0); }
right()3831   HValue* right() const { return OperandAt(1); }
3832 
3833   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
3834 
RequiredInputRepresentation(int index)3835   Representation RequiredInputRepresentation(int index) override {
3836     return Representation::Tagged();
3837   }
3838 
observed_input_representation(int index)3839   Representation observed_input_representation(int index) override {
3840     return Representation::Tagged();
3841   }
3842 
DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)3843   DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
3844 
3845  private:
3846   HCompareObjectEqAndBranch(HValue* left,
3847                             HValue* right,
3848                             HBasicBlock* true_target = NULL,
3849                             HBasicBlock* false_target = NULL)
3850       : known_successor_index_(kNoKnownSuccessorIndex) {
3851     SetOperandAt(0, left);
3852     SetOperandAt(1, right);
3853     SetSuccessorAt(0, true_target);
3854     SetSuccessorAt(1, false_target);
3855   }
3856 
3857   int known_successor_index_;
3858 };
3859 
3860 
3861 class HIsStringAndBranch final : public HUnaryControlInstruction {
3862  public:
3863   DECLARE_INSTRUCTION_FACTORY_P1(HIsStringAndBranch, HValue*);
3864   DECLARE_INSTRUCTION_FACTORY_P3(HIsStringAndBranch, HValue*,
3865                                  HBasicBlock*, HBasicBlock*);
3866 
RequiredInputRepresentation(int index)3867   Representation RequiredInputRepresentation(int index) override {
3868     return Representation::Tagged();
3869   }
3870 
3871   bool KnownSuccessorBlock(HBasicBlock** block) override;
3872 
3873   static const int kNoKnownSuccessorIndex = -1;
known_successor_index()3874   int known_successor_index() const { return known_successor_index_; }
set_known_successor_index(int known_successor_index)3875   void set_known_successor_index(int known_successor_index) {
3876     known_successor_index_ = known_successor_index;
3877   }
3878 
DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)3879   DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
3880 
3881  protected:
3882   int RedefinedOperandIndex() override { return 0; }
3883 
3884  private:
3885   HIsStringAndBranch(HValue* value, HBasicBlock* true_target = NULL,
3886                      HBasicBlock* false_target = NULL)
HUnaryControlInstruction(value,true_target,false_target)3887       : HUnaryControlInstruction(value, true_target, false_target),
3888         known_successor_index_(kNoKnownSuccessorIndex) {
3889     set_representation(Representation::Tagged());
3890   }
3891 
3892   int known_successor_index_;
3893 };
3894 
3895 
3896 class HIsSmiAndBranch final : public HUnaryControlInstruction {
3897  public:
3898   DECLARE_INSTRUCTION_FACTORY_P1(HIsSmiAndBranch, HValue*);
3899   DECLARE_INSTRUCTION_FACTORY_P3(HIsSmiAndBranch, HValue*,
3900                                  HBasicBlock*, HBasicBlock*);
3901 
DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)3902   DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
3903 
3904   Representation RequiredInputRepresentation(int index) override {
3905     return Representation::Tagged();
3906   }
3907 
3908  protected:
DataEquals(HValue * other)3909   bool DataEquals(HValue* other) override { return true; }
RedefinedOperandIndex()3910   int RedefinedOperandIndex() override { return 0; }
3911 
3912  private:
3913   HIsSmiAndBranch(HValue* value,
3914                   HBasicBlock* true_target = NULL,
3915                   HBasicBlock* false_target = NULL)
HUnaryControlInstruction(value,true_target,false_target)3916       : HUnaryControlInstruction(value, true_target, false_target) {
3917     set_representation(Representation::Tagged());
3918   }
3919 };
3920 
3921 
3922 class HIsUndetectableAndBranch final : public HUnaryControlInstruction {
3923  public:
3924   DECLARE_INSTRUCTION_FACTORY_P1(HIsUndetectableAndBranch, HValue*);
3925   DECLARE_INSTRUCTION_FACTORY_P3(HIsUndetectableAndBranch, HValue*,
3926                                  HBasicBlock*, HBasicBlock*);
3927 
RequiredInputRepresentation(int index)3928   Representation RequiredInputRepresentation(int index) override {
3929     return Representation::Tagged();
3930   }
3931 
3932   bool KnownSuccessorBlock(HBasicBlock** block) override;
3933 
DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)3934   DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
3935 
3936  private:
3937   HIsUndetectableAndBranch(HValue* value,
3938                            HBasicBlock* true_target = NULL,
3939                            HBasicBlock* false_target = NULL)
3940       : HUnaryControlInstruction(value, true_target, false_target) {}
3941 };
3942 
3943 
3944 class HStringCompareAndBranch final : public HTemplateControlInstruction<2, 3> {
3945  public:
3946   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HStringCompareAndBranch,
3947                                               HValue*,
3948                                               HValue*,
3949                                               Token::Value);
3950 
context()3951   HValue* context() const { return OperandAt(0); }
left()3952   HValue* left() const { return OperandAt(1); }
right()3953   HValue* right() const { return OperandAt(2); }
token()3954   Token::Value token() const { return token_; }
3955 
3956   std::ostream& PrintDataTo(std::ostream& os) const final;  // NOLINT
3957 
RequiredInputRepresentation(int index)3958   Representation RequiredInputRepresentation(int index) final {
3959     return Representation::Tagged();
3960   }
3961 
DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)3962   DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
3963 
3964  private:
3965   HStringCompareAndBranch(HValue* context, HValue* left, HValue* right,
3966                           Token::Value token)
3967       : token_(token) {
3968     DCHECK(Token::IsCompareOp(token));
3969     SetOperandAt(0, context);
3970     SetOperandAt(1, left);
3971     SetOperandAt(2, right);
3972     set_representation(Representation::Tagged());
3973     SetChangesFlag(kNewSpacePromotion);
3974     SetDependsOnFlag(kStringChars);
3975     SetDependsOnFlag(kStringLengths);
3976   }
3977 
3978   Token::Value const token_;
3979 };
3980 
3981 
3982 class HHasInstanceTypeAndBranch final : public HUnaryControlInstruction {
3983  public:
3984   DECLARE_INSTRUCTION_FACTORY_P2(
3985       HHasInstanceTypeAndBranch, HValue*, InstanceType);
3986   DECLARE_INSTRUCTION_FACTORY_P3(
3987       HHasInstanceTypeAndBranch, HValue*, InstanceType, InstanceType);
3988 
from()3989   InstanceType from() { return from_; }
to()3990   InstanceType to() { return to_; }
3991 
3992   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
3993 
RequiredInputRepresentation(int index)3994   Representation RequiredInputRepresentation(int index) override {
3995     return Representation::Tagged();
3996   }
3997 
3998   bool KnownSuccessorBlock(HBasicBlock** block) override;
3999 
DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)4000   DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
4001 
4002  private:
4003   HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
4004       : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
HHasInstanceTypeAndBranch(HValue * value,InstanceType from,InstanceType to)4005   HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
4006       : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
4007     DCHECK(to == LAST_TYPE);  // Others not implemented yet in backend.
4008   }
4009 
4010   InstanceType from_;
4011   InstanceType to_;  // Inclusive range, not all combinations work.
4012 };
4013 
4014 class HClassOfTestAndBranch final : public HUnaryControlInstruction {
4015  public:
4016   DECLARE_INSTRUCTION_FACTORY_P2(HClassOfTestAndBranch, HValue*,
4017                                  Handle<String>);
4018 
DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)4019   DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
4020 
4021   Representation RequiredInputRepresentation(int index) override {
4022     return Representation::Tagged();
4023   }
4024 
4025   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
4026 
class_name()4027   Handle<String> class_name() const { return class_name_; }
4028 
4029  private:
HClassOfTestAndBranch(HValue * value,Handle<String> class_name)4030   HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
4031       : HUnaryControlInstruction(value, NULL, NULL),
4032         class_name_(class_name) { }
4033 
4034   Handle<String> class_name_;
4035 };
4036 
4037 
4038 class HTypeofIsAndBranch final : public HUnaryControlInstruction {
4039  public:
4040   DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle<String>);
4041 
type_literal()4042   Handle<String> type_literal() const { return type_literal_.handle(); }
4043   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
4044 
DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)4045   DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
4046 
4047   Representation RequiredInputRepresentation(int index) override {
4048     return Representation::None();
4049   }
4050 
4051   bool KnownSuccessorBlock(HBasicBlock** block) override;
4052 
FinalizeUniqueness()4053   void FinalizeUniqueness() override {
4054     type_literal_ = Unique<String>(type_literal_.handle());
4055   }
4056 
4057  private:
HTypeofIsAndBranch(HValue * value,Handle<String> type_literal)4058   HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
4059       : HUnaryControlInstruction(value, NULL, NULL),
4060         type_literal_(Unique<String>::CreateUninitialized(type_literal)) { }
4061 
4062   Unique<String> type_literal_;
4063 };
4064 
4065 
4066 class HHasInPrototypeChainAndBranch final
4067     : public HTemplateControlInstruction<2, 2> {
4068  public:
4069   DECLARE_INSTRUCTION_FACTORY_P2(HHasInPrototypeChainAndBranch, HValue*,
4070                                  HValue*);
4071 
object()4072   HValue* object() const { return OperandAt(0); }
prototype()4073   HValue* prototype() const { return OperandAt(1); }
4074 
RequiredInputRepresentation(int index)4075   Representation RequiredInputRepresentation(int index) override {
4076     return Representation::Tagged();
4077   }
4078 
ObjectNeedsSmiCheck()4079   bool ObjectNeedsSmiCheck() const {
4080     return !object()->type().IsHeapObject() &&
4081            !object()->representation().IsHeapObject();
4082   }
4083 
DECLARE_CONCRETE_INSTRUCTION(HasInPrototypeChainAndBranch)4084   DECLARE_CONCRETE_INSTRUCTION(HasInPrototypeChainAndBranch)
4085 
4086  private:
4087   HHasInPrototypeChainAndBranch(HValue* object, HValue* prototype) {
4088     SetOperandAt(0, object);
4089     SetOperandAt(1, prototype);
4090     SetDependsOnFlag(kCalls);
4091   }
4092 };
4093 
4094 
4095 class HPower final : public HTemplateInstruction<2> {
4096  public:
4097   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4098                            HValue* left, HValue* right);
4099 
left()4100   HValue* left() { return OperandAt(0); }
right()4101   HValue* right() const { return OperandAt(1); }
4102 
RequiredInputRepresentation(int index)4103   Representation RequiredInputRepresentation(int index) override {
4104     return index == 0
4105       ? Representation::Double()
4106       : Representation::None();
4107   }
observed_input_representation(int index)4108   Representation observed_input_representation(int index) override {
4109     return RequiredInputRepresentation(index);
4110   }
4111 
DECLARE_CONCRETE_INSTRUCTION(Power)4112   DECLARE_CONCRETE_INSTRUCTION(Power)
4113 
4114  protected:
4115   bool DataEquals(HValue* other) override { return true; }
4116 
4117  private:
HPower(HValue * left,HValue * right)4118   HPower(HValue* left, HValue* right) {
4119     SetOperandAt(0, left);
4120     SetOperandAt(1, right);
4121     set_representation(Representation::Double());
4122     SetFlag(kUseGVN);
4123     SetChangesFlag(kNewSpacePromotion);
4124   }
4125 
IsDeletable()4126   bool IsDeletable() const override {
4127     return !right()->representation().IsTagged();
4128   }
4129 };
4130 
4131 
4132 enum ExternalAddType {
4133   AddOfExternalAndTagged,
4134   AddOfExternalAndInt32,
4135   NoExternalAdd
4136 };
4137 
4138 
4139 class HAdd final : public HArithmeticBinaryOperation {
4140  public:
4141   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4142                            HValue* left, HValue* right);
4143   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4144                            HValue* left, HValue* right,
4145                            ExternalAddType external_add_type);
4146 
4147   // Add is only commutative if two integer values are added and not if two
4148   // tagged values are added (because it might be a String concatenation).
4149   // We also do not commute (pointer + offset).
IsCommutative()4150   bool IsCommutative() const override {
4151     return !representation().IsTagged() && !representation().IsExternal();
4152   }
4153 
4154   HValue* Canonicalize() override;
4155 
RepresentationChanged(Representation to)4156   void RepresentationChanged(Representation to) override {
4157     if (to.IsTagged() &&
4158         (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() ||
4159          left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) {
4160       SetAllSideEffects();
4161       ClearFlag(kUseGVN);
4162     } else {
4163       ClearAllSideEffects();
4164       SetFlag(kUseGVN);
4165     }
4166     if (to.IsTagged()) {
4167       SetChangesFlag(kNewSpacePromotion);
4168       ClearFlag(kTruncatingToNumber);
4169     }
4170     if (!right()->type().IsTaggedNumber() &&
4171         !right()->representation().IsDouble() &&
4172         !right()->representation().IsSmiOrInteger32()) {
4173       ClearFlag(kTruncatingToNumber);
4174     }
4175   }
4176 
4177   Representation RepresentationFromInputs() override;
4178 
4179   Representation RequiredInputRepresentation(int index) override;
4180 
IsConsistentExternalRepresentation()4181   bool IsConsistentExternalRepresentation() {
4182     return left()->representation().IsExternal() &&
4183            ((external_add_type_ == AddOfExternalAndInt32 &&
4184              right()->representation().IsInteger32()) ||
4185             (external_add_type_ == AddOfExternalAndTagged &&
4186              right()->representation().IsTagged()));
4187   }
4188 
external_add_type()4189   ExternalAddType external_add_type() const { return external_add_type_; }
4190 
DECLARE_CONCRETE_INSTRUCTION(Add)4191   DECLARE_CONCRETE_INSTRUCTION(Add)
4192 
4193  protected:
4194   bool DataEquals(HValue* other) override { return true; }
4195 
4196   Range* InferRange(Zone* zone) override;
4197 
4198  private:
4199   HAdd(HValue* context, HValue* left, HValue* right,
4200        ExternalAddType external_add_type = NoExternalAdd)
HArithmeticBinaryOperation(context,left,right,HType::Tagged ())4201       : HArithmeticBinaryOperation(context, left, right, HType::Tagged()),
4202         external_add_type_(external_add_type) {
4203     SetFlag(kCanOverflow);
4204     switch (external_add_type_) {
4205       case AddOfExternalAndTagged:
4206         DCHECK(left->representation().IsExternal());
4207         DCHECK(right->representation().IsTagged());
4208         SetDependsOnFlag(kNewSpacePromotion);
4209         ClearFlag(HValue::kCanOverflow);
4210         SetFlag(kHasNoObservableSideEffects);
4211         break;
4212 
4213       case NoExternalAdd:
4214         // This is a bit of a hack: The call to this constructor is generated
4215         // by a macro that also supports sub and mul, so it doesn't pass in
4216         // a value for external_add_type but uses the default.
4217         if (left->representation().IsExternal()) {
4218           external_add_type_ = AddOfExternalAndInt32;
4219         }
4220         break;
4221 
4222       case AddOfExternalAndInt32:
4223         // See comment above.
4224         UNREACHABLE();
4225         break;
4226     }
4227   }
4228 
4229   ExternalAddType external_add_type_;
4230 };
4231 
4232 
4233 class HSub final : public HArithmeticBinaryOperation {
4234  public:
4235   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4236                            HValue* left, HValue* right);
4237 
4238   HValue* Canonicalize() override;
4239 
DECLARE_CONCRETE_INSTRUCTION(Sub)4240   DECLARE_CONCRETE_INSTRUCTION(Sub)
4241 
4242  protected:
4243   bool DataEquals(HValue* other) override { return true; }
4244 
4245   Range* InferRange(Zone* zone) override;
4246 
4247  private:
HSub(HValue * context,HValue * left,HValue * right)4248   HSub(HValue* context, HValue* left, HValue* right)
4249       : HArithmeticBinaryOperation(context, left, right) {
4250     SetFlag(kCanOverflow);
4251   }
4252 };
4253 
4254 
4255 class HMul final : public HArithmeticBinaryOperation {
4256  public:
4257   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4258                            HValue* left, HValue* right);
4259 
NewImul(Isolate * isolate,Zone * zone,HValue * context,HValue * left,HValue * right)4260   static HInstruction* NewImul(Isolate* isolate, Zone* zone, HValue* context,
4261                                HValue* left, HValue* right) {
4262     HInstruction* instr = HMul::New(isolate, zone, context, left, right);
4263     if (!instr->IsMul()) return instr;
4264     HMul* mul = HMul::cast(instr);
4265     // TODO(mstarzinger): Prevent bailout on minus zero for imul.
4266     mul->AssumeRepresentation(Representation::Integer32());
4267     mul->ClearFlag(HValue::kCanOverflow);
4268     return mul;
4269   }
4270 
4271   HValue* Canonicalize() override;
4272 
4273   // Only commutative if it is certain that not two objects are multiplicated.
IsCommutative()4274   bool IsCommutative() const override { return !representation().IsTagged(); }
4275 
UpdateRepresentation(Representation new_rep,HInferRepresentationPhase * h_infer,const char * reason)4276   void UpdateRepresentation(Representation new_rep,
4277                             HInferRepresentationPhase* h_infer,
4278                             const char* reason) override {
4279     HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4280   }
4281 
4282   bool MulMinusOne();
4283 
DECLARE_CONCRETE_INSTRUCTION(Mul)4284   DECLARE_CONCRETE_INSTRUCTION(Mul)
4285 
4286  protected:
4287   bool DataEquals(HValue* other) override { return true; }
4288 
4289   Range* InferRange(Zone* zone) override;
4290 
4291  private:
HMul(HValue * context,HValue * left,HValue * right)4292   HMul(HValue* context, HValue* left, HValue* right)
4293       : HArithmeticBinaryOperation(context, left, right) {
4294     SetFlag(kCanOverflow);
4295   }
4296 };
4297 
4298 
4299 class HMod final : public HArithmeticBinaryOperation {
4300  public:
4301   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4302                            HValue* left, HValue* right);
4303 
4304   HValue* Canonicalize() override;
4305 
UpdateRepresentation(Representation new_rep,HInferRepresentationPhase * h_infer,const char * reason)4306   void UpdateRepresentation(Representation new_rep,
4307                             HInferRepresentationPhase* h_infer,
4308                             const char* reason) override {
4309     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4310     HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4311   }
4312 
DECLARE_CONCRETE_INSTRUCTION(Mod)4313   DECLARE_CONCRETE_INSTRUCTION(Mod)
4314 
4315  protected:
4316   bool DataEquals(HValue* other) override { return true; }
4317 
4318   Range* InferRange(Zone* zone) override;
4319 
4320  private:
HMod(HValue * context,HValue * left,HValue * right)4321   HMod(HValue* context, HValue* left, HValue* right)
4322       : HArithmeticBinaryOperation(context, left, right) {
4323     SetFlag(kCanBeDivByZero);
4324     SetFlag(kCanOverflow);
4325     SetFlag(kLeftCanBeNegative);
4326   }
4327 };
4328 
4329 
4330 class HDiv final : public HArithmeticBinaryOperation {
4331  public:
4332   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4333                            HValue* left, HValue* right);
4334 
4335   HValue* Canonicalize() override;
4336 
UpdateRepresentation(Representation new_rep,HInferRepresentationPhase * h_infer,const char * reason)4337   void UpdateRepresentation(Representation new_rep,
4338                             HInferRepresentationPhase* h_infer,
4339                             const char* reason) override {
4340     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4341     HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4342   }
4343 
DECLARE_CONCRETE_INSTRUCTION(Div)4344   DECLARE_CONCRETE_INSTRUCTION(Div)
4345 
4346  protected:
4347   bool DataEquals(HValue* other) override { return true; }
4348 
4349   Range* InferRange(Zone* zone) override;
4350 
4351  private:
HDiv(HValue * context,HValue * left,HValue * right)4352   HDiv(HValue* context, HValue* left, HValue* right)
4353       : HArithmeticBinaryOperation(context, left, right) {
4354     SetFlag(kCanBeDivByZero);
4355     SetFlag(kCanOverflow);
4356   }
4357 };
4358 
4359 
4360 class HMathMinMax final : public HArithmeticBinaryOperation {
4361  public:
4362   enum Operation { kMathMin, kMathMax };
4363 
4364   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4365                            HValue* left, HValue* right, Operation op);
4366 
observed_input_representation(int index)4367   Representation observed_input_representation(int index) override {
4368     return RequiredInputRepresentation(index);
4369   }
4370 
4371   void InferRepresentation(HInferRepresentationPhase* h_infer) override;
4372 
RepresentationFromInputs()4373   Representation RepresentationFromInputs() override {
4374     Representation left_rep = left()->representation();
4375     Representation right_rep = right()->representation();
4376     Representation result = Representation::Smi();
4377     result = result.generalize(left_rep);
4378     result = result.generalize(right_rep);
4379     if (result.IsTagged()) return Representation::Double();
4380     return result;
4381   }
4382 
IsCommutative()4383   bool IsCommutative() const override { return true; }
4384 
operation()4385   Operation operation() { return operation_; }
4386 
DECLARE_CONCRETE_INSTRUCTION(MathMinMax)4387   DECLARE_CONCRETE_INSTRUCTION(MathMinMax)
4388 
4389  protected:
4390   bool DataEquals(HValue* other) override {
4391     return other->IsMathMinMax() &&
4392         HMathMinMax::cast(other)->operation_ == operation_;
4393   }
4394 
4395   Range* InferRange(Zone* zone) override;
4396 
4397  private:
HMathMinMax(HValue * context,HValue * left,HValue * right,Operation op)4398   HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
4399       : HArithmeticBinaryOperation(context, left, right), operation_(op) {}
4400 
4401   Operation operation_;
4402 };
4403 
4404 
4405 class HBitwise final : public HBitwiseBinaryOperation {
4406  public:
4407   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4408                            Token::Value op, HValue* left, HValue* right);
4409 
op()4410   Token::Value op() const { return op_; }
4411 
IsCommutative()4412   bool IsCommutative() const override { return true; }
4413 
4414   HValue* Canonicalize() override;
4415 
4416   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
4417 
DECLARE_CONCRETE_INSTRUCTION(Bitwise)4418   DECLARE_CONCRETE_INSTRUCTION(Bitwise)
4419 
4420  protected:
4421   bool DataEquals(HValue* other) override {
4422     return op() == HBitwise::cast(other)->op();
4423   }
4424 
4425   Range* InferRange(Zone* zone) override;
4426 
4427  private:
HBitwise(HValue * context,Token::Value op,HValue * left,HValue * right)4428   HBitwise(HValue* context, Token::Value op, HValue* left, HValue* right)
4429       : HBitwiseBinaryOperation(context, left, right), op_(op) {
4430     DCHECK(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
4431     // BIT_AND with a smi-range positive value will always unset the
4432     // entire sign-extension of the smi-sign.
4433     if (op == Token::BIT_AND &&
4434         ((left->IsConstant() &&
4435           left->representation().IsSmi() &&
4436           HConstant::cast(left)->Integer32Value() >= 0) ||
4437          (right->IsConstant() &&
4438           right->representation().IsSmi() &&
4439           HConstant::cast(right)->Integer32Value() >= 0))) {
4440       SetFlag(kTruncatingToSmi);
4441       SetFlag(kTruncatingToInt32);
4442     // BIT_OR with a smi-range negative value will always set the entire
4443     // sign-extension of the smi-sign.
4444     } else if (op == Token::BIT_OR &&
4445         ((left->IsConstant() &&
4446           left->representation().IsSmi() &&
4447           HConstant::cast(left)->Integer32Value() < 0) ||
4448          (right->IsConstant() &&
4449           right->representation().IsSmi() &&
4450           HConstant::cast(right)->Integer32Value() < 0))) {
4451       SetFlag(kTruncatingToSmi);
4452       SetFlag(kTruncatingToInt32);
4453     }
4454   }
4455 
4456   Token::Value op_;
4457 };
4458 
4459 
4460 class HShl final : public HBitwiseBinaryOperation {
4461  public:
4462   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4463                            HValue* left, HValue* right);
4464 
4465   Range* InferRange(Zone* zone) override;
4466 
UpdateRepresentation(Representation new_rep,HInferRepresentationPhase * h_infer,const char * reason)4467   void UpdateRepresentation(Representation new_rep,
4468                             HInferRepresentationPhase* h_infer,
4469                             const char* reason) override {
4470     if (new_rep.IsSmi() &&
4471         !(right()->IsInteger32Constant() &&
4472           right()->GetInteger32Constant() >= 0)) {
4473       new_rep = Representation::Integer32();
4474     }
4475     HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4476   }
4477 
DECLARE_CONCRETE_INSTRUCTION(Shl)4478   DECLARE_CONCRETE_INSTRUCTION(Shl)
4479 
4480  protected:
4481   bool DataEquals(HValue* other) override { return true; }
4482 
4483  private:
HShl(HValue * context,HValue * left,HValue * right)4484   HShl(HValue* context, HValue* left, HValue* right)
4485       : HBitwiseBinaryOperation(context, left, right) {}
4486 };
4487 
4488 
4489 class HShr final : public HBitwiseBinaryOperation {
4490  public:
4491   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4492                            HValue* left, HValue* right);
4493 
4494   Range* InferRange(Zone* zone) override;
4495 
UpdateRepresentation(Representation new_rep,HInferRepresentationPhase * h_infer,const char * reason)4496   void UpdateRepresentation(Representation new_rep,
4497                             HInferRepresentationPhase* h_infer,
4498                             const char* reason) override {
4499     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4500     HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4501   }
4502 
DECLARE_CONCRETE_INSTRUCTION(Shr)4503   DECLARE_CONCRETE_INSTRUCTION(Shr)
4504 
4505  protected:
4506   bool DataEquals(HValue* other) override { return true; }
4507 
4508  private:
HShr(HValue * context,HValue * left,HValue * right)4509   HShr(HValue* context, HValue* left, HValue* right)
4510       : HBitwiseBinaryOperation(context, left, right) {}
4511 };
4512 
4513 
4514 class HSar final : public HBitwiseBinaryOperation {
4515  public:
4516   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4517                            HValue* left, HValue* right);
4518 
4519   Range* InferRange(Zone* zone) override;
4520 
UpdateRepresentation(Representation new_rep,HInferRepresentationPhase * h_infer,const char * reason)4521   void UpdateRepresentation(Representation new_rep,
4522                             HInferRepresentationPhase* h_infer,
4523                             const char* reason) override {
4524     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4525     HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4526   }
4527 
DECLARE_CONCRETE_INSTRUCTION(Sar)4528   DECLARE_CONCRETE_INSTRUCTION(Sar)
4529 
4530  protected:
4531   bool DataEquals(HValue* other) override { return true; }
4532 
4533  private:
HSar(HValue * context,HValue * left,HValue * right)4534   HSar(HValue* context, HValue* left, HValue* right)
4535       : HBitwiseBinaryOperation(context, left, right) {}
4536 };
4537 
4538 
4539 class HRor final : public HBitwiseBinaryOperation {
4540  public:
New(Isolate * isolate,Zone * zone,HValue * context,HValue * left,HValue * right)4541   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4542                            HValue* left, HValue* right) {
4543     return new (zone) HRor(context, left, right);
4544   }
4545 
UpdateRepresentation(Representation new_rep,HInferRepresentationPhase * h_infer,const char * reason)4546   void UpdateRepresentation(Representation new_rep,
4547                             HInferRepresentationPhase* h_infer,
4548                             const char* reason) override {
4549     if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4550     HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4551   }
4552 
DECLARE_CONCRETE_INSTRUCTION(Ror)4553   DECLARE_CONCRETE_INSTRUCTION(Ror)
4554 
4555  protected:
4556   bool DataEquals(HValue* other) override { return true; }
4557 
4558  private:
HRor(HValue * context,HValue * left,HValue * right)4559   HRor(HValue* context, HValue* left, HValue* right)
4560       : HBitwiseBinaryOperation(context, left, right) {
4561     ChangeRepresentation(Representation::Integer32());
4562   }
4563 };
4564 
4565 
4566 class HOsrEntry final : public HTemplateInstruction<0> {
4567  public:
4568   DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId);
4569 
ast_id()4570   BailoutId ast_id() const { return ast_id_; }
4571 
RequiredInputRepresentation(int index)4572   Representation RequiredInputRepresentation(int index) override {
4573     return Representation::None();
4574   }
4575 
DECLARE_CONCRETE_INSTRUCTION(OsrEntry)4576   DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
4577 
4578  private:
4579   explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
4580     SetChangesFlag(kOsrEntries);
4581     SetChangesFlag(kNewSpacePromotion);
4582   }
4583 
4584   BailoutId ast_id_;
4585 };
4586 
4587 
4588 class HParameter final : public HTemplateInstruction<0> {
4589  public:
4590   enum ParameterKind {
4591     STACK_PARAMETER,
4592     REGISTER_PARAMETER
4593   };
4594 
4595   DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned);
4596   DECLARE_INSTRUCTION_FACTORY_P2(HParameter, unsigned, ParameterKind);
4597   DECLARE_INSTRUCTION_FACTORY_P3(HParameter, unsigned, ParameterKind,
4598                                  Representation);
4599 
index()4600   unsigned index() const { return index_; }
kind()4601   ParameterKind kind() const { return kind_; }
4602 
4603   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
4604 
RequiredInputRepresentation(int index)4605   Representation RequiredInputRepresentation(int index) override {
4606     return Representation::None();
4607   }
4608 
KnownOptimalRepresentation()4609   Representation KnownOptimalRepresentation() override {
4610     // If a parameter is an input to a phi, that phi should not
4611     // choose any more optimistic representation than Tagged.
4612     return Representation::Tagged();
4613   }
4614 
DECLARE_CONCRETE_INSTRUCTION(Parameter)4615   DECLARE_CONCRETE_INSTRUCTION(Parameter)
4616 
4617  private:
4618   explicit HParameter(unsigned index,
4619                       ParameterKind kind = STACK_PARAMETER)
4620       : index_(index),
4621         kind_(kind) {
4622     set_representation(Representation::Tagged());
4623   }
4624 
HParameter(unsigned index,ParameterKind kind,Representation r)4625   explicit HParameter(unsigned index,
4626                       ParameterKind kind,
4627                       Representation r)
4628       : index_(index),
4629         kind_(kind) {
4630     set_representation(r);
4631   }
4632 
4633   unsigned index_;
4634   ParameterKind kind_;
4635 };
4636 
4637 
4638 class HUnknownOSRValue final : public HTemplateInstruction<0> {
4639  public:
4640   DECLARE_INSTRUCTION_FACTORY_P2(HUnknownOSRValue, HEnvironment*, int);
4641 
4642   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
4643 
RequiredInputRepresentation(int index)4644   Representation RequiredInputRepresentation(int index) override {
4645     return Representation::None();
4646   }
4647 
set_incoming_value(HPhi * value)4648   void set_incoming_value(HPhi* value) { incoming_value_ = value; }
incoming_value()4649   HPhi* incoming_value() { return incoming_value_; }
environment()4650   HEnvironment *environment() { return environment_; }
index()4651   int index() { return index_; }
4652 
KnownOptimalRepresentation()4653   Representation KnownOptimalRepresentation() override {
4654     if (incoming_value_ == NULL) return Representation::None();
4655     return incoming_value_->KnownOptimalRepresentation();
4656   }
4657 
DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)4658   DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
4659 
4660  private:
4661   HUnknownOSRValue(HEnvironment* environment, int index)
4662       : environment_(environment),
4663         index_(index),
4664         incoming_value_(NULL) {
4665     set_representation(Representation::Tagged());
4666   }
4667 
4668   HEnvironment* environment_;
4669   int index_;
4670   HPhi* incoming_value_;
4671 };
4672 
4673 class HAllocate final : public HTemplateInstruction<3> {
4674  public:
CompatibleInstanceTypes(InstanceType type1,InstanceType type2)4675   static bool CompatibleInstanceTypes(InstanceType type1,
4676                                       InstanceType type2) {
4677     return ComputeFlags(TENURED, type1) == ComputeFlags(TENURED, type2) &&
4678         ComputeFlags(NOT_TENURED, type1) == ComputeFlags(NOT_TENURED, type2);
4679   }
4680 
4681   static HAllocate* New(
4682       Isolate* isolate, Zone* zone, HValue* context, HValue* size, HType type,
4683       PretenureFlag pretenure_flag, InstanceType instance_type,
4684       HValue* dominator,
4685       Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null()) {
4686     return new (zone) HAllocate(context, size, type, pretenure_flag,
4687                                 instance_type, dominator, allocation_site);
4688   }
4689 
4690   // Maximum instance size for which allocations will be inlined.
4691   static const int kMaxInlineSize = 64 * kPointerSize;
4692 
context()4693   HValue* context() const { return OperandAt(0); }
size()4694   HValue* size() const { return OperandAt(1); }
allocation_folding_dominator()4695   HValue* allocation_folding_dominator() const { return OperandAt(2); }
4696 
RequiredInputRepresentation(int index)4697   Representation RequiredInputRepresentation(int index) override {
4698     if (index == 0) {
4699       return Representation::Tagged();
4700     } else {
4701       return Representation::Integer32();
4702     }
4703   }
4704 
GetMonomorphicJSObjectMap()4705   Handle<Map> GetMonomorphicJSObjectMap() override {
4706     return known_initial_map_;
4707   }
4708 
set_known_initial_map(Handle<Map> known_initial_map)4709   void set_known_initial_map(Handle<Map> known_initial_map) {
4710     known_initial_map_ = known_initial_map;
4711   }
4712 
IsNewSpaceAllocation()4713   bool IsNewSpaceAllocation() const {
4714     return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
4715   }
4716 
IsOldSpaceAllocation()4717   bool IsOldSpaceAllocation() const {
4718     return (flags_ & ALLOCATE_IN_OLD_SPACE) != 0;
4719   }
4720 
MustAllocateDoubleAligned()4721   bool MustAllocateDoubleAligned() const {
4722     return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
4723   }
4724 
MustPrefillWithFiller()4725   bool MustPrefillWithFiller() const {
4726     return (flags_ & PREFILL_WITH_FILLER) != 0;
4727   }
4728 
MakePrefillWithFiller()4729   void MakePrefillWithFiller() {
4730     flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
4731   }
4732 
MakeDoubleAligned()4733   void MakeDoubleAligned() {
4734     flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
4735   }
4736 
MakeAllocationFoldingDominator()4737   void MakeAllocationFoldingDominator() {
4738     flags_ =
4739         static_cast<HAllocate::Flags>(flags_ | ALLOCATION_FOLDING_DOMINATOR);
4740   }
4741 
IsAllocationFoldingDominator()4742   bool IsAllocationFoldingDominator() const {
4743     return (flags_ & ALLOCATION_FOLDING_DOMINATOR) != 0;
4744   }
4745 
MakeFoldedAllocation(HAllocate * dominator)4746   void MakeFoldedAllocation(HAllocate* dominator) {
4747     flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATION_FOLDED);
4748     ClearFlag(kTrackSideEffectDominators);
4749     ClearChangesFlag(kNewSpacePromotion);
4750     SetOperandAt(2, dominator);
4751   }
4752 
IsAllocationFolded()4753   bool IsAllocationFolded() const { return (flags_ & ALLOCATION_FOLDED) != 0; }
4754 
4755   bool HandleSideEffectDominator(GVNFlag side_effect,
4756                                  HValue* dominator) override;
4757 
4758   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
4759 
4760   DECLARE_CONCRETE_INSTRUCTION(Allocate)
4761 
4762  private:
4763   enum Flags {
4764     ALLOCATE_IN_NEW_SPACE = 1 << 0,
4765     ALLOCATE_IN_OLD_SPACE = 1 << 2,
4766     ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
4767     PREFILL_WITH_FILLER = 1 << 4,
4768     ALLOCATION_FOLDING_DOMINATOR = 1 << 5,
4769     ALLOCATION_FOLDED = 1 << 6
4770   };
4771 
4772   HAllocate(
4773       HValue* context, HValue* size, HType type, PretenureFlag pretenure_flag,
4774       InstanceType instance_type, HValue* dominator,
4775       Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null())
4776       : HTemplateInstruction<3>(type),
4777         flags_(ComputeFlags(pretenure_flag, instance_type)) {
4778     SetOperandAt(0, context);
4779     UpdateSize(size);
4780     SetOperandAt(2, dominator);
4781     set_representation(Representation::Tagged());
4782     SetFlag(kTrackSideEffectDominators);
4783     SetChangesFlag(kNewSpacePromotion);
4784     SetDependsOnFlag(kNewSpacePromotion);
4785 
4786     if (FLAG_trace_pretenuring) {
4787       PrintF("HAllocate with AllocationSite %p %s\n",
4788              allocation_site.is_null()
4789                  ? static_cast<void*>(NULL)
4790                  : static_cast<void*>(*allocation_site),
4791              pretenure_flag == TENURED ? "tenured" : "not tenured");
4792     }
4793   }
4794 
ComputeFlags(PretenureFlag pretenure_flag,InstanceType instance_type)4795   static Flags ComputeFlags(PretenureFlag pretenure_flag,
4796                             InstanceType instance_type) {
4797     Flags flags = pretenure_flag == TENURED ? ALLOCATE_IN_OLD_SPACE
4798                                             : ALLOCATE_IN_NEW_SPACE;
4799     if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
4800       flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED);
4801     }
4802     // We have to fill the allocated object with one word fillers if we do
4803     // not use allocation folding since some allocations may depend on each
4804     // other, i.e., have a pointer to each other. A GC in between these
4805     // allocations may leave such objects behind in a not completely initialized
4806     // state.
4807     if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
4808       flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER);
4809     }
4810     return flags;
4811   }
4812 
UpdateSize(HValue * size)4813   void UpdateSize(HValue* size) {
4814     SetOperandAt(1, size);
4815   }
4816 
IsFoldable(HAllocate * allocate)4817   bool IsFoldable(HAllocate* allocate) {
4818     return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) ||
4819            (IsOldSpaceAllocation() && allocate->IsOldSpaceAllocation());
4820   }
4821 
4822   Flags flags_;
4823   Handle<Map> known_initial_map_;
4824 };
4825 
4826 
4827 class HStoreCodeEntry final : public HTemplateInstruction<2> {
4828  public:
New(Isolate * isolate,Zone * zone,HValue * context,HValue * function,HValue * code)4829   static HStoreCodeEntry* New(Isolate* isolate, Zone* zone, HValue* context,
4830                               HValue* function, HValue* code) {
4831     return new(zone) HStoreCodeEntry(function, code);
4832   }
4833 
RequiredInputRepresentation(int index)4834   Representation RequiredInputRepresentation(int index) override {
4835     return Representation::Tagged();
4836   }
4837 
function()4838   HValue* function() { return OperandAt(0); }
code_object()4839   HValue* code_object() { return OperandAt(1); }
4840 
DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry)4841   DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry)
4842 
4843  private:
4844   HStoreCodeEntry(HValue* function, HValue* code) {
4845     SetOperandAt(0, function);
4846     SetOperandAt(1, code);
4847   }
4848 };
4849 
4850 
4851 class HInnerAllocatedObject final : public HTemplateInstruction<2> {
4852  public:
New(Isolate * isolate,Zone * zone,HValue * context,HValue * value,HValue * offset,HType type)4853   static HInnerAllocatedObject* New(Isolate* isolate, Zone* zone,
4854                                     HValue* context, HValue* value,
4855                                     HValue* offset, HType type) {
4856     return new(zone) HInnerAllocatedObject(value, offset, type);
4857   }
4858 
base_object()4859   HValue* base_object() const { return OperandAt(0); }
offset()4860   HValue* offset() const { return OperandAt(1); }
4861 
RequiredInputRepresentation(int index)4862   Representation RequiredInputRepresentation(int index) override {
4863     return index == 0 ? Representation::Tagged() : Representation::Integer32();
4864   }
4865 
4866   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
4867 
DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)4868   DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
4869 
4870  private:
4871   HInnerAllocatedObject(HValue* value,
4872                         HValue* offset,
4873                         HType type) : HTemplateInstruction<2>(type) {
4874     DCHECK(value->IsAllocate());
4875     DCHECK(type.IsHeapObject());
4876     SetOperandAt(0, value);
4877     SetOperandAt(1, offset);
4878     set_representation(Representation::Tagged());
4879   }
4880 };
4881 
4882 
StoringValueNeedsWriteBarrier(HValue * value)4883 inline bool StoringValueNeedsWriteBarrier(HValue* value) {
4884   return !value->type().IsSmi()
4885       && !value->type().IsNull()
4886       && !value->type().IsBoolean()
4887       && !value->type().IsUndefined()
4888       && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
4889 }
4890 
4891 
ReceiverObjectNeedsWriteBarrier(HValue * object,HValue * value,HValue * dominator)4892 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
4893                                             HValue* value,
4894                                             HValue* dominator) {
4895   // There may be multiple inner allocates dominated by one allocate.
4896   while (object->IsInnerAllocatedObject()) {
4897     object = HInnerAllocatedObject::cast(object)->base_object();
4898   }
4899 
4900   if (object->IsAllocate()) {
4901     HAllocate* allocate = HAllocate::cast(object);
4902     if (allocate->IsAllocationFolded()) {
4903       HValue* dominator = allocate->allocation_folding_dominator();
4904       // There is no guarantee that all allocations are folded together because
4905       // GVN performs a fixpoint.
4906       if (HAllocate::cast(dominator)->IsAllocationFoldingDominator()) {
4907         object = dominator;
4908       }
4909     }
4910   }
4911 
4912   if (object->IsConstant() &&
4913       HConstant::cast(object)->HasExternalReferenceValue()) {
4914     // Stores to external references require no write barriers
4915     return false;
4916   }
4917   // We definitely need a write barrier unless the object is the allocation
4918   // dominator.
4919   if (object == dominator && object->IsAllocate()) {
4920     // Stores to new space allocations require no write barriers.
4921     if (HAllocate::cast(object)->IsNewSpaceAllocation()) {
4922       return false;
4923     }
4924   }
4925   return true;
4926 }
4927 
4928 
PointersToHereCheckForObject(HValue * object,HValue * dominator)4929 inline PointersToHereCheck PointersToHereCheckForObject(HValue* object,
4930                                                         HValue* dominator) {
4931   while (object->IsInnerAllocatedObject()) {
4932     object = HInnerAllocatedObject::cast(object)->base_object();
4933   }
4934   if (object == dominator &&
4935       object->IsAllocate() &&
4936       HAllocate::cast(object)->IsNewSpaceAllocation()) {
4937     return kPointersToHereAreAlwaysInteresting;
4938   }
4939   return kPointersToHereMaybeInteresting;
4940 }
4941 
4942 
4943 class HLoadContextSlot final : public HUnaryOperation {
4944  public:
4945   enum Mode {
4946     // Perform a normal load of the context slot without checking its value.
4947     kNoCheck,
4948     // Load and check the value of the context slot. Deoptimize if it's the
4949     // hole value. This is used for checking for loading of uninitialized
4950     // harmony bindings where we deoptimize into full-codegen generated code
4951     // which will subsequently throw a reference error.
4952     kCheckDeoptimize
4953   };
4954 
HLoadContextSlot(HValue * context,int slot_index,Mode mode)4955   HLoadContextSlot(HValue* context, int slot_index, Mode mode)
4956       : HUnaryOperation(context), slot_index_(slot_index), mode_(mode) {
4957     set_representation(Representation::Tagged());
4958     SetFlag(kUseGVN);
4959     SetDependsOnFlag(kContextSlots);
4960   }
4961 
slot_index()4962   int slot_index() const { return slot_index_; }
mode()4963   Mode mode() const { return mode_; }
4964 
DeoptimizesOnHole()4965   bool DeoptimizesOnHole() {
4966     return mode_ == kCheckDeoptimize;
4967   }
4968 
RequiresHoleCheck()4969   bool RequiresHoleCheck() const {
4970     return mode_ != kNoCheck;
4971   }
4972 
RequiredInputRepresentation(int index)4973   Representation RequiredInputRepresentation(int index) override {
4974     return Representation::Tagged();
4975   }
4976 
4977   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
4978 
DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)4979   DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
4980 
4981  protected:
4982   bool DataEquals(HValue* other) override {
4983     HLoadContextSlot* b = HLoadContextSlot::cast(other);
4984     return (slot_index() == b->slot_index());
4985   }
4986 
4987  private:
IsDeletable()4988   bool IsDeletable() const override { return !RequiresHoleCheck(); }
4989 
4990   int slot_index_;
4991   Mode mode_;
4992 };
4993 
4994 
4995 class HStoreContextSlot final : public HTemplateInstruction<2> {
4996  public:
4997   enum Mode {
4998     // Perform a normal store to the context slot without checking its previous
4999     // value.
5000     kNoCheck,
5001     // Check the previous value of the context slot and deoptimize if it's the
5002     // hole value. This is used for checking for assignments to uninitialized
5003     // harmony bindings where we deoptimize into full-codegen generated code
5004     // which will subsequently throw a reference error.
5005     kCheckDeoptimize
5006   };
5007 
5008   DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
5009                                  Mode, HValue*);
5010 
context()5011   HValue* context() const { return OperandAt(0); }
value()5012   HValue* value() const { return OperandAt(1); }
slot_index()5013   int slot_index() const { return slot_index_; }
mode()5014   Mode mode() const { return mode_; }
5015 
NeedsWriteBarrier()5016   bool NeedsWriteBarrier() {
5017     return StoringValueNeedsWriteBarrier(value());
5018   }
5019 
DeoptimizesOnHole()5020   bool DeoptimizesOnHole() {
5021     return mode_ == kCheckDeoptimize;
5022   }
5023 
RequiresHoleCheck()5024   bool RequiresHoleCheck() {
5025     return mode_ != kNoCheck;
5026   }
5027 
RequiredInputRepresentation(int index)5028   Representation RequiredInputRepresentation(int index) override {
5029     return Representation::Tagged();
5030   }
5031 
5032   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
5033 
DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)5034   DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
5035 
5036  private:
5037   HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
5038       : slot_index_(slot_index), mode_(mode) {
5039     SetOperandAt(0, context);
5040     SetOperandAt(1, value);
5041     SetChangesFlag(kContextSlots);
5042   }
5043 
5044   int slot_index_;
5045   Mode mode_;
5046 };
5047 
5048 
5049 // Represents an access to a portion of an object, such as the map pointer,
5050 // array elements pointer, etc, but not accesses to array elements themselves.
5051 class HObjectAccess final {
5052  public:
IsInobject()5053   inline bool IsInobject() const {
5054     return portion() != kBackingStore && portion() != kExternalMemory;
5055   }
5056 
IsExternalMemory()5057   inline bool IsExternalMemory() const {
5058     return portion() == kExternalMemory;
5059   }
5060 
IsStringLength()5061   inline bool IsStringLength() const {
5062     return portion() == kStringLengths;
5063   }
5064 
IsMap()5065   inline bool IsMap() const {
5066     return portion() == kMaps;
5067   }
5068 
offset()5069   inline int offset() const {
5070     return OffsetField::decode(value_);
5071   }
5072 
representation()5073   inline Representation representation() const {
5074     return Representation::FromKind(RepresentationField::decode(value_));
5075   }
5076 
name()5077   inline Handle<Name> name() const { return name_; }
5078 
immutable()5079   inline bool immutable() const {
5080     return ImmutableField::decode(value_);
5081   }
5082 
5083   // Returns true if access is being made to an in-object property that
5084   // was already added to the object.
existing_inobject_property()5085   inline bool existing_inobject_property() const {
5086     return ExistingInobjectPropertyField::decode(value_);
5087   }
5088 
WithRepresentation(Representation representation)5089   inline HObjectAccess WithRepresentation(Representation representation) {
5090     return HObjectAccess(portion(), offset(), representation, name(),
5091                          immutable(), existing_inobject_property());
5092   }
5093 
ForHeapNumberValue()5094   static HObjectAccess ForHeapNumberValue() {
5095     return HObjectAccess(
5096         kDouble, HeapNumber::kValueOffset, Representation::Double());
5097   }
5098 
ForHeapNumberValueLowestBits()5099   static HObjectAccess ForHeapNumberValueLowestBits() {
5100     return HObjectAccess(kDouble,
5101                          HeapNumber::kValueOffset,
5102                          Representation::Integer32());
5103   }
5104 
ForHeapNumberValueHighestBits()5105   static HObjectAccess ForHeapNumberValueHighestBits() {
5106     return HObjectAccess(kDouble,
5107                          HeapNumber::kValueOffset + kIntSize,
5108                          Representation::Integer32());
5109   }
5110 
5111   static HObjectAccess ForOddballToNumber(
5112       Representation representation = Representation::Tagged()) {
5113     return HObjectAccess(kInobject, Oddball::kToNumberOffset, representation);
5114   }
5115 
ForOddballTypeOf()5116   static HObjectAccess ForOddballTypeOf() {
5117     return HObjectAccess(kInobject, Oddball::kTypeOfOffset,
5118                          Representation::HeapObject());
5119   }
5120 
ForElementsPointer()5121   static HObjectAccess ForElementsPointer() {
5122     return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
5123   }
5124 
ForNextFunctionLinkPointer()5125   static HObjectAccess ForNextFunctionLinkPointer() {
5126     return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
5127   }
5128 
ForArrayLength(ElementsKind elements_kind)5129   static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
5130     return HObjectAccess(
5131         kArrayLengths,
5132         JSArray::kLengthOffset,
5133         IsFastElementsKind(elements_kind)
5134             ? Representation::Smi() : Representation::Tagged());
5135   }
5136 
5137   static HObjectAccess ForAllocationSiteOffset(int offset);
5138 
ForAllocationSiteList()5139   static HObjectAccess ForAllocationSiteList() {
5140     return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
5141                          Handle<Name>::null(), false, false);
5142   }
5143 
ForFixedArrayLength()5144   static HObjectAccess ForFixedArrayLength() {
5145     return HObjectAccess(
5146         kArrayLengths,
5147         FixedArray::kLengthOffset,
5148         Representation::Smi());
5149   }
5150 
ForFixedTypedArrayBaseBasePointer()5151   static HObjectAccess ForFixedTypedArrayBaseBasePointer() {
5152     return HObjectAccess(kInobject, FixedTypedArrayBase::kBasePointerOffset,
5153                          Representation::Tagged());
5154   }
5155 
ForFixedTypedArrayBaseExternalPointer()5156   static HObjectAccess ForFixedTypedArrayBaseExternalPointer() {
5157     return HObjectAccess::ForObservableJSObjectOffset(
5158         FixedTypedArrayBase::kExternalPointerOffset,
5159         Representation::External());
5160   }
5161 
ForStringHashField()5162   static HObjectAccess ForStringHashField() {
5163     return HObjectAccess(kInobject,
5164                          String::kHashFieldOffset,
5165                          Representation::Integer32());
5166   }
5167 
ForStringLength()5168   static HObjectAccess ForStringLength() {
5169     STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
5170     return HObjectAccess(
5171         kStringLengths,
5172         String::kLengthOffset,
5173         Representation::Smi());
5174   }
5175 
ForConsStringFirst()5176   static HObjectAccess ForConsStringFirst() {
5177     return HObjectAccess(kInobject, ConsString::kFirstOffset);
5178   }
5179 
ForConsStringSecond()5180   static HObjectAccess ForConsStringSecond() {
5181     return HObjectAccess(kInobject, ConsString::kSecondOffset);
5182   }
5183 
ForPropertiesPointer()5184   static HObjectAccess ForPropertiesPointer() {
5185     return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
5186   }
5187 
ForPrototypeOrInitialMap()5188   static HObjectAccess ForPrototypeOrInitialMap() {
5189     return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
5190   }
5191 
ForSharedFunctionInfoPointer()5192   static HObjectAccess ForSharedFunctionInfoPointer() {
5193     return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
5194   }
5195 
ForCodeEntryPointer()5196   static HObjectAccess ForCodeEntryPointer() {
5197     return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
5198   }
5199 
ForCodeOffset()5200   static HObjectAccess ForCodeOffset() {
5201     return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
5202   }
5203 
ForOptimizedCodeMap()5204   static HObjectAccess ForOptimizedCodeMap() {
5205     return HObjectAccess(kInobject,
5206                          SharedFunctionInfo::kOptimizedCodeMapOffset);
5207   }
5208 
ForFunctionContextPointer()5209   static HObjectAccess ForFunctionContextPointer() {
5210     return HObjectAccess(kInobject, JSFunction::kContextOffset);
5211   }
5212 
ForMap()5213   static HObjectAccess ForMap() {
5214     return HObjectAccess(kMaps, JSObject::kMapOffset);
5215   }
5216 
ForPrototype()5217   static HObjectAccess ForPrototype() {
5218     return HObjectAccess(kMaps, Map::kPrototypeOffset);
5219   }
5220 
ForMapAsInteger32()5221   static HObjectAccess ForMapAsInteger32() {
5222     return HObjectAccess(kMaps, JSObject::kMapOffset,
5223                          Representation::Integer32());
5224   }
5225 
ForMapInObjectPropertiesOrConstructorFunctionIndex()5226   static HObjectAccess ForMapInObjectPropertiesOrConstructorFunctionIndex() {
5227     return HObjectAccess(
5228         kInobject, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset,
5229         Representation::UInteger8());
5230   }
5231 
ForMapInstanceType()5232   static HObjectAccess ForMapInstanceType() {
5233     return HObjectAccess(kInobject,
5234                          Map::kInstanceTypeOffset,
5235                          Representation::UInteger8());
5236   }
5237 
ForMapInstanceSize()5238   static HObjectAccess ForMapInstanceSize() {
5239     return HObjectAccess(kInobject,
5240                          Map::kInstanceSizeOffset,
5241                          Representation::UInteger8());
5242   }
5243 
ForMapBitField()5244   static HObjectAccess ForMapBitField() {
5245     return HObjectAccess(kInobject,
5246                          Map::kBitFieldOffset,
5247                          Representation::UInteger8());
5248   }
5249 
ForMapBitField2()5250   static HObjectAccess ForMapBitField2() {
5251     return HObjectAccess(kInobject,
5252                          Map::kBitField2Offset,
5253                          Representation::UInteger8());
5254   }
5255 
ForMapBitField3()5256   static HObjectAccess ForMapBitField3() {
5257     return HObjectAccess(kInobject, Map::kBitField3Offset,
5258                          Representation::Integer32());
5259   }
5260 
ForMapDescriptors()5261   static HObjectAccess ForMapDescriptors() {
5262     return HObjectAccess(kInobject, Map::kDescriptorsOffset);
5263   }
5264 
ForNameHashField()5265   static HObjectAccess ForNameHashField() {
5266     return HObjectAccess(kInobject,
5267                          Name::kHashFieldOffset,
5268                          Representation::Integer32());
5269   }
5270 
ForMapInstanceTypeAndBitField()5271   static HObjectAccess ForMapInstanceTypeAndBitField() {
5272     STATIC_ASSERT((Map::kInstanceTypeAndBitFieldOffset & 1) == 0);
5273     // Ensure the two fields share one 16-bit word, endian-independent.
5274     STATIC_ASSERT((Map::kBitFieldOffset & ~1) ==
5275                   (Map::kInstanceTypeOffset & ~1));
5276     return HObjectAccess(kInobject,
5277                          Map::kInstanceTypeAndBitFieldOffset,
5278                          Representation::UInteger16());
5279   }
5280 
ForPropertyCellValue()5281   static HObjectAccess ForPropertyCellValue() {
5282     return HObjectAccess(kInobject, PropertyCell::kValueOffset);
5283   }
5284 
ForPropertyCellDetails()5285   static HObjectAccess ForPropertyCellDetails() {
5286     return HObjectAccess(kInobject, PropertyCell::kDetailsOffset,
5287                          Representation::Smi());
5288   }
5289 
ForCellValue()5290   static HObjectAccess ForCellValue() {
5291     return HObjectAccess(kInobject, Cell::kValueOffset);
5292   }
5293 
ForWeakCellValue()5294   static HObjectAccess ForWeakCellValue() {
5295     return HObjectAccess(kInobject, WeakCell::kValueOffset);
5296   }
5297 
ForWeakCellNext()5298   static HObjectAccess ForWeakCellNext() {
5299     return HObjectAccess(kInobject, WeakCell::kNextOffset);
5300   }
5301 
ForAllocationMementoSite()5302   static HObjectAccess ForAllocationMementoSite() {
5303     return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
5304   }
5305 
ForCounter()5306   static HObjectAccess ForCounter() {
5307     return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
5308                          Handle<Name>::null(), false, false);
5309   }
5310 
ForExternalUInteger8()5311   static HObjectAccess ForExternalUInteger8() {
5312     return HObjectAccess(kExternalMemory, 0, Representation::UInteger8(),
5313                          Handle<Name>::null(), false, false);
5314   }
5315 
ForBoundTargetFunction()5316   static HObjectAccess ForBoundTargetFunction() {
5317     return HObjectAccess(kInobject,
5318                          JSBoundFunction::kBoundTargetFunctionOffset);
5319   }
5320 
ForBoundThis()5321   static HObjectAccess ForBoundThis() {
5322     return HObjectAccess(kInobject, JSBoundFunction::kBoundThisOffset);
5323   }
5324 
ForBoundArguments()5325   static HObjectAccess ForBoundArguments() {
5326     return HObjectAccess(kInobject, JSBoundFunction::kBoundArgumentsOffset);
5327   }
5328 
5329   // Create an access to an offset in a fixed array header.
5330   static HObjectAccess ForFixedArrayHeader(int offset);
5331 
5332   // Create an access to an in-object property in a JSObject.
5333   // This kind of access must be used when the object |map| is known and
5334   // in-object properties are being accessed. Accesses of the in-object
5335   // properties can have different semantics depending on whether corresponding
5336   // property was added to the map or not.
5337   static HObjectAccess ForMapAndOffset(Handle<Map> map, int offset,
5338       Representation representation = Representation::Tagged());
5339 
5340   // Create an access to an in-object property in a JSObject.
5341   // This kind of access can be used for accessing object header fields or
5342   // in-object properties if the map of the object is not known.
5343   static HObjectAccess ForObservableJSObjectOffset(int offset,
5344       Representation representation = Representation::Tagged()) {
5345     return ForMapAndOffset(Handle<Map>::null(), offset, representation);
5346   }
5347 
5348   // Create an access to an in-object property in a JSArray.
5349   static HObjectAccess ForJSArrayOffset(int offset);
5350 
5351   static HObjectAccess ForContextSlot(int index);
5352 
5353   static HObjectAccess ForScriptContext(int index);
5354 
5355   // Create an access to the backing store of an object.
5356   static HObjectAccess ForBackingStoreOffset(int offset,
5357       Representation representation = Representation::Tagged());
5358 
5359   // Create an access to a resolved field (in-object or backing store).
5360   static HObjectAccess ForField(Handle<Map> map, int index,
5361                                 Representation representation,
5362                                 Handle<Name> name);
5363 
ForJSTypedArrayLength()5364   static HObjectAccess ForJSTypedArrayLength() {
5365     return HObjectAccess::ForObservableJSObjectOffset(
5366         JSTypedArray::kLengthOffset);
5367   }
5368 
ForJSArrayBufferBackingStore()5369   static HObjectAccess ForJSArrayBufferBackingStore() {
5370     return HObjectAccess::ForObservableJSObjectOffset(
5371         JSArrayBuffer::kBackingStoreOffset, Representation::External());
5372   }
5373 
ForJSArrayBufferByteLength()5374   static HObjectAccess ForJSArrayBufferByteLength() {
5375     return HObjectAccess::ForObservableJSObjectOffset(
5376         JSArrayBuffer::kByteLengthOffset, Representation::Tagged());
5377   }
5378 
ForJSArrayBufferBitField()5379   static HObjectAccess ForJSArrayBufferBitField() {
5380     return HObjectAccess::ForObservableJSObjectOffset(
5381         JSArrayBuffer::kBitFieldOffset, Representation::Integer32());
5382   }
5383 
ForJSArrayBufferBitFieldSlot()5384   static HObjectAccess ForJSArrayBufferBitFieldSlot() {
5385     return HObjectAccess::ForObservableJSObjectOffset(
5386         JSArrayBuffer::kBitFieldSlot, Representation::Smi());
5387   }
5388 
ForJSArrayBufferViewBuffer()5389   static HObjectAccess ForJSArrayBufferViewBuffer() {
5390     return HObjectAccess::ForObservableJSObjectOffset(
5391         JSArrayBufferView::kBufferOffset);
5392   }
5393 
ForJSArrayBufferViewByteOffset()5394   static HObjectAccess ForJSArrayBufferViewByteOffset() {
5395     return HObjectAccess::ForObservableJSObjectOffset(
5396         JSArrayBufferView::kByteOffsetOffset);
5397   }
5398 
ForJSArrayBufferViewByteLength()5399   static HObjectAccess ForJSArrayBufferViewByteLength() {
5400     return HObjectAccess::ForObservableJSObjectOffset(
5401         JSArrayBufferView::kByteLengthOffset);
5402   }
5403 
ForJSGlobalObjectNativeContext()5404   static HObjectAccess ForJSGlobalObjectNativeContext() {
5405     return HObjectAccess(kInobject, JSGlobalObject::kNativeContextOffset);
5406   }
5407 
ForJSRegExpFlags()5408   static HObjectAccess ForJSRegExpFlags() {
5409     return HObjectAccess(kInobject, JSRegExp::kFlagsOffset);
5410   }
5411 
ForJSRegExpSource()5412   static HObjectAccess ForJSRegExpSource() {
5413     return HObjectAccess(kInobject, JSRegExp::kSourceOffset);
5414   }
5415 
ForJSCollectionTable()5416   static HObjectAccess ForJSCollectionTable() {
5417     return HObjectAccess::ForObservableJSObjectOffset(
5418         JSCollection::kTableOffset);
5419   }
5420 
5421   template <typename CollectionType>
ForOrderedHashTableNumberOfBuckets()5422   static HObjectAccess ForOrderedHashTableNumberOfBuckets() {
5423     return HObjectAccess(kInobject, CollectionType::kNumberOfBucketsOffset,
5424                          Representation::Smi());
5425   }
5426 
5427   template <typename CollectionType>
ForOrderedHashTableNumberOfElements()5428   static HObjectAccess ForOrderedHashTableNumberOfElements() {
5429     return HObjectAccess(kInobject, CollectionType::kNumberOfElementsOffset,
5430                          Representation::Smi());
5431   }
5432 
5433   template <typename CollectionType>
ForOrderedHashTableNumberOfDeletedElements()5434   static HObjectAccess ForOrderedHashTableNumberOfDeletedElements() {
5435     return HObjectAccess(kInobject,
5436                          CollectionType::kNumberOfDeletedElementsOffset,
5437                          Representation::Smi());
5438   }
5439 
5440   template <typename CollectionType>
ForOrderedHashTableNextTable()5441   static HObjectAccess ForOrderedHashTableNextTable() {
5442     return HObjectAccess(kInobject, CollectionType::kNextTableOffset);
5443   }
5444 
5445   template <typename CollectionType>
ForOrderedHashTableBucket(int bucket)5446   static HObjectAccess ForOrderedHashTableBucket(int bucket) {
5447     return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
5448                                         (bucket * kPointerSize),
5449                          Representation::Smi());
5450   }
5451 
5452   // Access into the data table of an OrderedHashTable with a
5453   // known-at-compile-time bucket count.
5454   template <typename CollectionType, int kBucketCount>
ForOrderedHashTableDataTableIndex(int index)5455   static HObjectAccess ForOrderedHashTableDataTableIndex(int index) {
5456     return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
5457                                         (kBucketCount * kPointerSize) +
5458                                         (index * kPointerSize));
5459   }
5460 
Equals(HObjectAccess that)5461   inline bool Equals(HObjectAccess that) const {
5462     return value_ == that.value_;  // portion and offset must match
5463   }
5464 
5465  protected:
5466   void SetGVNFlags(HValue *instr, PropertyAccessType access_type);
5467 
5468  private:
5469   // internal use only; different parts of an object or array
5470   enum Portion {
5471     kMaps,             // map of an object
5472     kArrayLengths,     // the length of an array
5473     kStringLengths,    // the length of a string
5474     kElementsPointer,  // elements pointer
5475     kBackingStore,     // some field in the backing store
5476     kDouble,           // some double field
5477     kInobject,         // some other in-object field
5478     kExternalMemory    // some field in external memory
5479   };
5480 
HObjectAccess()5481   HObjectAccess() : value_(0) {}
5482 
5483   HObjectAccess(Portion portion, int offset,
5484                 Representation representation = Representation::Tagged(),
5485                 Handle<Name> name = Handle<Name>::null(),
5486                 bool immutable = false, bool existing_inobject_property = true)
5487       : value_(PortionField::encode(portion) |
5488                RepresentationField::encode(representation.kind()) |
5489                ImmutableField::encode(immutable ? 1 : 0) |
5490                ExistingInobjectPropertyField::encode(
5491                    existing_inobject_property ? 1 : 0) |
5492                OffsetField::encode(offset)),
5493         name_(name) {
5494     // assert that the fields decode correctly
5495     DCHECK(this->offset() == offset);
5496     DCHECK(this->portion() == portion);
5497     DCHECK(this->immutable() == immutable);
5498     DCHECK(this->existing_inobject_property() == existing_inobject_property);
5499     DCHECK(RepresentationField::decode(value_) == representation.kind());
5500     DCHECK(!this->existing_inobject_property() || IsInobject());
5501   }
5502 
5503   class PortionField : public BitField<Portion, 0, 3> {};
5504   class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
5505   class ImmutableField : public BitField<bool, 7, 1> {};
5506   class ExistingInobjectPropertyField : public BitField<bool, 8, 1> {};
5507   class OffsetField : public BitField<int, 9, 23> {};
5508 
5509   uint32_t value_;  // encodes portion, representation, immutable, and offset
5510   Handle<Name> name_;
5511 
5512   friend class HLoadNamedField;
5513   friend class HStoreNamedField;
5514   friend class SideEffectsTracker;
5515   friend std::ostream& operator<<(std::ostream& os,
5516                                   const HObjectAccess& access);
5517 
portion()5518   inline Portion portion() const {
5519     return PortionField::decode(value_);
5520   }
5521 };
5522 
5523 
5524 std::ostream& operator<<(std::ostream& os, const HObjectAccess& access);
5525 
5526 
5527 class HLoadNamedField final : public HTemplateInstruction<2> {
5528  public:
5529   DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*,
5530                                  HValue*, HObjectAccess);
5531   DECLARE_INSTRUCTION_FACTORY_P5(HLoadNamedField, HValue*, HValue*,
5532                                  HObjectAccess, const UniqueSet<Map>*, HType);
5533 
object()5534   HValue* object() const { return OperandAt(0); }
dependency()5535   HValue* dependency() const {
5536     DCHECK(HasDependency());
5537     return OperandAt(1);
5538   }
HasDependency()5539   bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
access()5540   HObjectAccess access() const { return access_; }
field_representation()5541   Representation field_representation() const {
5542       return access_.representation();
5543   }
5544 
maps()5545   const UniqueSet<Map>* maps() const { return maps_; }
5546 
HasEscapingOperandAt(int index)5547   bool HasEscapingOperandAt(int index) override { return false; }
HasOutOfBoundsAccess(int size)5548   bool HasOutOfBoundsAccess(int size) override {
5549     return !access().IsInobject() || access().offset() >= size;
5550   }
RequiredInputRepresentation(int index)5551   Representation RequiredInputRepresentation(int index) override {
5552     if (index == 0) {
5553       // object must be external in case of external memory access
5554       return access().IsExternalMemory() ? Representation::External()
5555                                          : Representation::Tagged();
5556     }
5557     DCHECK(index == 1);
5558     return Representation::None();
5559   }
5560   Range* InferRange(Zone* zone) override;
5561   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
5562 
CanBeReplacedWith(HValue * other)5563   bool CanBeReplacedWith(HValue* other) const {
5564     if (!CheckFlag(HValue::kCantBeReplaced)) return false;
5565     if (!type().Equals(other->type())) return false;
5566     if (!representation().Equals(other->representation())) return false;
5567     if (!other->IsLoadNamedField()) return true;
5568     HLoadNamedField* that = HLoadNamedField::cast(other);
5569     if (this->maps_ == that->maps_) return true;
5570     if (this->maps_ == NULL || that->maps_ == NULL) return false;
5571     return this->maps_->IsSubset(that->maps_);
5572   }
5573 
DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)5574   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
5575 
5576  protected:
5577   bool DataEquals(HValue* other) override {
5578     HLoadNamedField* that = HLoadNamedField::cast(other);
5579     if (!this->access_.Equals(that->access_)) return false;
5580     if (this->maps_ == that->maps_) return true;
5581     return (this->maps_ != NULL &&
5582             that->maps_ != NULL &&
5583             this->maps_->Equals(that->maps_));
5584   }
5585 
5586  private:
HLoadNamedField(HValue * object,HValue * dependency,HObjectAccess access)5587   HLoadNamedField(HValue* object,
5588                   HValue* dependency,
5589                   HObjectAccess access)
5590       : access_(access), maps_(NULL) {
5591     DCHECK_NOT_NULL(object);
5592     SetOperandAt(0, object);
5593     SetOperandAt(1, dependency ? dependency : object);
5594 
5595     Representation representation = access.representation();
5596     if (representation.IsInteger8() ||
5597         representation.IsUInteger8() ||
5598         representation.IsInteger16() ||
5599         representation.IsUInteger16()) {
5600       set_representation(Representation::Integer32());
5601     } else if (representation.IsSmi()) {
5602       set_type(HType::Smi());
5603       if (SmiValuesAre32Bits()) {
5604         set_representation(Representation::Integer32());
5605       } else {
5606         set_representation(representation);
5607       }
5608     } else if (representation.IsDouble() ||
5609                representation.IsExternal() ||
5610                representation.IsInteger32()) {
5611       set_representation(representation);
5612     } else if (representation.IsHeapObject()) {
5613       set_type(HType::HeapObject());
5614       set_representation(Representation::Tagged());
5615     } else {
5616       set_representation(Representation::Tagged());
5617     }
5618     access.SetGVNFlags(this, LOAD);
5619   }
5620 
HLoadNamedField(HValue * object,HValue * dependency,HObjectAccess access,const UniqueSet<Map> * maps,HType type)5621   HLoadNamedField(HValue* object,
5622                   HValue* dependency,
5623                   HObjectAccess access,
5624                   const UniqueSet<Map>* maps,
5625                   HType type)
5626       : HTemplateInstruction<2>(type), access_(access), maps_(maps) {
5627     DCHECK_NOT_NULL(maps);
5628     DCHECK_NE(0, maps->size());
5629 
5630     DCHECK_NOT_NULL(object);
5631     SetOperandAt(0, object);
5632     SetOperandAt(1, dependency ? dependency : object);
5633 
5634     DCHECK(access.representation().IsHeapObject());
5635     DCHECK(type.IsHeapObject());
5636     set_representation(Representation::Tagged());
5637 
5638     access.SetGVNFlags(this, LOAD);
5639   }
5640 
IsDeletable()5641   bool IsDeletable() const override { return true; }
5642 
5643   HObjectAccess access_;
5644   const UniqueSet<Map>* maps_;
5645 };
5646 
5647 
5648 class HLoadFunctionPrototype final : public HUnaryOperation {
5649  public:
5650   DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);
5651 
function()5652   HValue* function() { return OperandAt(0); }
5653 
RequiredInputRepresentation(int index)5654   Representation RequiredInputRepresentation(int index) override {
5655     return Representation::Tagged();
5656   }
5657 
DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)5658   DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
5659 
5660  protected:
5661   bool DataEquals(HValue* other) override { return true; }
5662 
5663  private:
HLoadFunctionPrototype(HValue * function)5664   explicit HLoadFunctionPrototype(HValue* function)
5665       : HUnaryOperation(function) {
5666     set_representation(Representation::Tagged());
5667     SetFlag(kUseGVN);
5668     SetDependsOnFlag(kCalls);
5669   }
5670 };
5671 
5672 class ArrayInstructionInterface {
5673  public:
5674   virtual HValue* GetKey() = 0;
5675   virtual void SetKey(HValue* key) = 0;
5676   virtual ElementsKind elements_kind() const = 0;
5677   // TryIncreaseBaseOffset returns false if overflow would result.
5678   virtual bool TryIncreaseBaseOffset(uint32_t increase_by_value) = 0;
5679   virtual bool IsDehoisted() const = 0;
5680   virtual void SetDehoisted(bool is_dehoisted) = 0;
~ArrayInstructionInterface()5681   virtual ~ArrayInstructionInterface() { }
5682 
KeyedAccessIndexRequirement(Representation r)5683   static Representation KeyedAccessIndexRequirement(Representation r) {
5684     return r.IsInteger32() || SmiValuesAre32Bits()
5685         ? Representation::Integer32() : Representation::Smi();
5686   }
5687 };
5688 
5689 
5690 static const int kDefaultKeyedHeaderOffsetSentinel = -1;
5691 
5692 enum LoadKeyedHoleMode {
5693   NEVER_RETURN_HOLE,
5694   ALLOW_RETURN_HOLE,
5695   CONVERT_HOLE_TO_UNDEFINED
5696 };
5697 
5698 
5699 class HLoadKeyed final : public HTemplateInstruction<4>,
5700                          public ArrayInstructionInterface {
5701  public:
5702   DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
5703                                  ElementsKind);
5704   DECLARE_INSTRUCTION_FACTORY_P6(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
5705                                  ElementsKind, LoadKeyedHoleMode);
5706   DECLARE_INSTRUCTION_FACTORY_P7(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
5707                                  ElementsKind, LoadKeyedHoleMode, int);
5708 
is_fixed_typed_array()5709   bool is_fixed_typed_array() const {
5710     return IsFixedTypedArrayElementsKind(elements_kind());
5711   }
elements()5712   HValue* elements() const { return OperandAt(0); }
key()5713   HValue* key() const { return OperandAt(1); }
dependency()5714   HValue* dependency() const {
5715     DCHECK(HasDependency());
5716     return OperandAt(2);
5717   }
HasDependency()5718   bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
backing_store_owner()5719   HValue* backing_store_owner() const {
5720     DCHECK(HasBackingStoreOwner());
5721     return OperandAt(3);
5722   }
HasBackingStoreOwner()5723   bool HasBackingStoreOwner() const { return OperandAt(0) != OperandAt(3); }
base_offset()5724   uint32_t base_offset() const { return BaseOffsetField::decode(bit_field_); }
5725   bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
GetKey()5726   HValue* GetKey() override { return key(); }
SetKey(HValue * key)5727   void SetKey(HValue* key) override { SetOperandAt(1, key); }
IsDehoisted()5728   bool IsDehoisted() const override {
5729     return IsDehoistedField::decode(bit_field_);
5730   }
SetDehoisted(bool is_dehoisted)5731   void SetDehoisted(bool is_dehoisted) override {
5732     bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
5733   }
elements_kind()5734   ElementsKind elements_kind() const override {
5735     return ElementsKindField::decode(bit_field_);
5736   }
hole_mode()5737   LoadKeyedHoleMode hole_mode() const {
5738     return HoleModeField::decode(bit_field_);
5739   }
5740 
RequiredInputRepresentation(int index)5741   Representation RequiredInputRepresentation(int index) override {
5742     // kind_fast:                 tagged[int32] (none)
5743     // kind_double:               tagged[int32] (none)
5744     // kind_fixed_typed_array:    external[int32] (none)
5745     // kind_external:             external[int32] (none)
5746     if (index == 0) {
5747       return is_fixed_typed_array() ? Representation::External()
5748                                     : Representation::Tagged();
5749     }
5750     if (index == 1) {
5751       return ArrayInstructionInterface::KeyedAccessIndexRequirement(
5752           OperandAt(1)->representation());
5753     }
5754     if (index == 2) {
5755       return Representation::None();
5756     }
5757     DCHECK_EQ(3, index);
5758     return HasBackingStoreOwner() ? Representation::Tagged()
5759                                   : Representation::None();
5760   }
5761 
observed_input_representation(int index)5762   Representation observed_input_representation(int index) override {
5763     return RequiredInputRepresentation(index);
5764   }
5765 
5766   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
5767 
5768   bool UsesMustHandleHole() const;
5769   bool AllUsesCanTreatHoleAsNaN() const;
5770   bool RequiresHoleCheck() const;
5771 
5772   Range* InferRange(Zone* zone) override;
5773 
DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)5774   DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)
5775 
5776  protected:
5777   bool DataEquals(HValue* other) override {
5778     if (!other->IsLoadKeyed()) return false;
5779     HLoadKeyed* other_load = HLoadKeyed::cast(other);
5780 
5781     if (base_offset() != other_load->base_offset()) return false;
5782     return elements_kind() == other_load->elements_kind();
5783   }
5784 
5785  private:
5786   HLoadKeyed(HValue* obj, HValue* key, HValue* dependency,
5787              HValue* backing_store_owner, ElementsKind elements_kind,
5788              LoadKeyedHoleMode mode = NEVER_RETURN_HOLE,
5789              int offset = kDefaultKeyedHeaderOffsetSentinel)
5790       : bit_field_(0) {
5791     offset = offset == kDefaultKeyedHeaderOffsetSentinel
5792         ? GetDefaultHeaderSizeForElementsKind(elements_kind)
5793         : offset;
5794     bit_field_ = ElementsKindField::encode(elements_kind) |
5795         HoleModeField::encode(mode) |
5796         BaseOffsetField::encode(offset);
5797 
5798     SetOperandAt(0, obj);
5799     SetOperandAt(1, key);
5800     SetOperandAt(2, dependency != nullptr ? dependency : obj);
5801     SetOperandAt(3, backing_store_owner != nullptr ? backing_store_owner : obj);
5802     DCHECK_EQ(HasBackingStoreOwner(), is_fixed_typed_array());
5803 
5804     if (!is_fixed_typed_array()) {
5805       // I can detect the case between storing double (holey and fast) and
5806       // smi/object by looking at elements_kind_.
5807       DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
5808              IsFastDoubleElementsKind(elements_kind));
5809 
5810       if (IsFastSmiOrObjectElementsKind(elements_kind)) {
5811         if (IsFastSmiElementsKind(elements_kind) &&
5812             (!IsHoleyElementsKind(elements_kind) ||
5813              mode == NEVER_RETURN_HOLE)) {
5814           set_type(HType::Smi());
5815           if (SmiValuesAre32Bits() && !RequiresHoleCheck()) {
5816             set_representation(Representation::Integer32());
5817           } else {
5818             set_representation(Representation::Smi());
5819           }
5820         } else {
5821           set_representation(Representation::Tagged());
5822         }
5823 
5824         SetDependsOnFlag(kArrayElements);
5825       } else {
5826         set_representation(Representation::Double());
5827         SetDependsOnFlag(kDoubleArrayElements);
5828       }
5829     } else {
5830       if (elements_kind == FLOAT32_ELEMENTS ||
5831           elements_kind == FLOAT64_ELEMENTS) {
5832         set_representation(Representation::Double());
5833       } else {
5834         set_representation(Representation::Integer32());
5835       }
5836 
5837       if (is_fixed_typed_array()) {
5838         SetDependsOnFlag(kExternalMemory);
5839         SetDependsOnFlag(kTypedArrayElements);
5840       } else {
5841         UNREACHABLE();
5842       }
5843       // Native code could change the specialized array.
5844       SetDependsOnFlag(kCalls);
5845     }
5846 
5847     SetFlag(kUseGVN);
5848   }
5849 
IsDeletable()5850   bool IsDeletable() const override { return !RequiresHoleCheck(); }
5851 
5852   // Establish some checks around our packed fields
5853   enum LoadKeyedBits {
5854     kBitsForElementsKind = 5,
5855     kBitsForHoleMode = 2,
5856     kBitsForBaseOffset = 24,
5857     kBitsForIsDehoisted = 1,
5858 
5859     kStartElementsKind = 0,
5860     kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
5861     kStartBaseOffset = kStartHoleMode + kBitsForHoleMode,
5862     kStartIsDehoisted = kStartBaseOffset + kBitsForBaseOffset
5863   };
5864 
5865   STATIC_ASSERT((kBitsForElementsKind + kBitsForHoleMode + kBitsForBaseOffset +
5866                  kBitsForIsDehoisted) <= sizeof(uint32_t) * 8);
5867   STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
5868   class ElementsKindField:
5869     public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
5870     {};  // NOLINT
5871   class HoleModeField:
5872     public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
5873     {};  // NOLINT
5874   class BaseOffsetField:
5875     public BitField<uint32_t, kStartBaseOffset, kBitsForBaseOffset>
5876     {};  // NOLINT
5877   class IsDehoistedField:
5878     public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
5879     {};  // NOLINT
5880   uint32_t bit_field_;
5881 };
5882 
5883 
5884 // Indicates whether the store is a store to an entry that was previously
5885 // initialized or not.
5886 enum StoreFieldOrKeyedMode {
5887   // The entry could be either previously initialized or not.
5888   INITIALIZING_STORE,
5889   // At the time of this store it is guaranteed that the entry is already
5890   // initialized.
5891   STORE_TO_INITIALIZED_ENTRY
5892 };
5893 
5894 
5895 class HStoreNamedField final : public HTemplateInstruction<3> {
5896  public:
5897   DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
5898                                  HObjectAccess, HValue*);
5899   DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue*,
5900                                  HObjectAccess, HValue*, StoreFieldOrKeyedMode);
5901 
DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)5902   DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
5903 
5904   bool HasEscapingOperandAt(int index) override { return index == 1; }
HasOutOfBoundsAccess(int size)5905   bool HasOutOfBoundsAccess(int size) override {
5906     return !access().IsInobject() || access().offset() >= size;
5907   }
RequiredInputRepresentation(int index)5908   Representation RequiredInputRepresentation(int index) override {
5909     if (index == 0 && access().IsExternalMemory()) {
5910       // object must be external in case of external memory access
5911       return Representation::External();
5912     } else if (index == 1) {
5913       if (field_representation().IsInteger8() ||
5914           field_representation().IsUInteger8() ||
5915           field_representation().IsInteger16() ||
5916           field_representation().IsUInteger16() ||
5917           field_representation().IsInteger32()) {
5918         return Representation::Integer32();
5919       } else if (field_representation().IsDouble()) {
5920         return field_representation();
5921       } else if (field_representation().IsSmi()) {
5922         if (SmiValuesAre32Bits() &&
5923             store_mode() == STORE_TO_INITIALIZED_ENTRY) {
5924           return Representation::Integer32();
5925         }
5926         return field_representation();
5927       } else if (field_representation().IsExternal()) {
5928         return Representation::External();
5929       }
5930     }
5931     return Representation::Tagged();
5932   }
HandleSideEffectDominator(GVNFlag side_effect,HValue * dominator)5933   bool HandleSideEffectDominator(GVNFlag side_effect,
5934                                  HValue* dominator) override {
5935     DCHECK(side_effect == kNewSpacePromotion);
5936     if (!FLAG_use_write_barrier_elimination) return false;
5937     dominator_ = dominator;
5938     return false;
5939   }
5940   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
5941 
object()5942   HValue* object() const { return OperandAt(0); }
value()5943   HValue* value() const { return OperandAt(1); }
transition()5944   HValue* transition() const { return OperandAt(2); }
5945 
access()5946   HObjectAccess access() const { return access_; }
dominator()5947   HValue* dominator() const { return dominator_; }
has_transition()5948   bool has_transition() const { return HasTransitionField::decode(bit_field_); }
store_mode()5949   StoreFieldOrKeyedMode store_mode() const {
5950     return StoreModeField::decode(bit_field_);
5951   }
5952 
transition_map()5953   Handle<Map> transition_map() const {
5954     if (has_transition()) {
5955       return Handle<Map>::cast(
5956           HConstant::cast(transition())->handle(isolate()));
5957     } else {
5958       return Handle<Map>();
5959     }
5960   }
5961 
SetTransition(HConstant * transition)5962   void SetTransition(HConstant* transition) {
5963     DCHECK(!has_transition());  // Only set once.
5964     SetOperandAt(2, transition);
5965     bit_field_ = HasTransitionField::update(bit_field_, true);
5966     SetChangesFlag(kMaps);
5967   }
5968 
NeedsWriteBarrier()5969   bool NeedsWriteBarrier() const {
5970     DCHECK(!field_representation().IsDouble() ||
5971            (FLAG_unbox_double_fields && access_.IsInobject()) ||
5972            !has_transition());
5973     if (field_representation().IsDouble()) return false;
5974     if (field_representation().IsSmi()) return false;
5975     if (field_representation().IsInteger32()) return false;
5976     if (field_representation().IsExternal()) return false;
5977     return StoringValueNeedsWriteBarrier(value()) &&
5978         ReceiverObjectNeedsWriteBarrier(object(), value(), dominator());
5979   }
5980 
NeedsWriteBarrierForMap()5981   bool NeedsWriteBarrierForMap() {
5982     return ReceiverObjectNeedsWriteBarrier(object(), transition(),
5983                                            dominator());
5984   }
5985 
SmiCheckForWriteBarrier()5986   SmiCheck SmiCheckForWriteBarrier() const {
5987     if (field_representation().IsHeapObject()) return OMIT_SMI_CHECK;
5988     if (value()->type().IsHeapObject()) return OMIT_SMI_CHECK;
5989     return INLINE_SMI_CHECK;
5990   }
5991 
PointersToHereCheckForValue()5992   PointersToHereCheck PointersToHereCheckForValue() const {
5993     return PointersToHereCheckForObject(value(), dominator());
5994   }
5995 
field_representation()5996   Representation field_representation() const {
5997     return access_.representation();
5998   }
5999 
UpdateValue(HValue * value)6000   void UpdateValue(HValue* value) {
6001     SetOperandAt(1, value);
6002   }
6003 
CanBeReplacedWith(HStoreNamedField * that)6004   bool CanBeReplacedWith(HStoreNamedField* that) const {
6005     if (!this->access().Equals(that->access())) return false;
6006     if (SmiValuesAre32Bits() &&
6007         this->field_representation().IsSmi() &&
6008         this->store_mode() == INITIALIZING_STORE &&
6009         that->store_mode() == STORE_TO_INITIALIZED_ENTRY) {
6010       // We cannot replace an initializing store to a smi field with a store to
6011       // an initialized entry on 64-bit architectures (with 32-bit smis).
6012       return false;
6013     }
6014     return true;
6015   }
6016 
6017  private:
6018   HStoreNamedField(HValue* obj, HObjectAccess access, HValue* val,
6019                    StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
access_(access)6020       : access_(access),
6021         dominator_(NULL),
6022         bit_field_(HasTransitionField::encode(false) |
6023                    StoreModeField::encode(store_mode)) {
6024     // Stores to a non existing in-object property are allowed only to the
6025     // newly allocated objects (via HAllocate or HInnerAllocatedObject).
6026     DCHECK(!access.IsInobject() || access.existing_inobject_property() ||
6027            obj->IsAllocate() || obj->IsInnerAllocatedObject());
6028     SetOperandAt(0, obj);
6029     SetOperandAt(1, val);
6030     SetOperandAt(2, obj);
6031     access.SetGVNFlags(this, STORE);
6032   }
6033 
6034   class HasTransitionField : public BitField<bool, 0, 1> {};
6035   class StoreModeField : public BitField<StoreFieldOrKeyedMode, 1, 1> {};
6036 
6037   HObjectAccess access_;
6038   HValue* dominator_;
6039   uint32_t bit_field_;
6040 };
6041 
6042 class HStoreKeyed final : public HTemplateInstruction<4>,
6043                           public ArrayInstructionInterface {
6044  public:
6045   DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*,
6046                                  HValue*, ElementsKind);
6047   DECLARE_INSTRUCTION_FACTORY_P6(HStoreKeyed, HValue*, HValue*, HValue*,
6048                                  HValue*, ElementsKind, StoreFieldOrKeyedMode);
6049   DECLARE_INSTRUCTION_FACTORY_P7(HStoreKeyed, HValue*, HValue*, HValue*,
6050                                  HValue*, ElementsKind, StoreFieldOrKeyedMode,
6051                                  int);
6052 
RequiredInputRepresentation(int index)6053   Representation RequiredInputRepresentation(int index) override {
6054     // kind_fast:               tagged[int32] = tagged
6055     // kind_double:             tagged[int32] = double
6056     // kind_smi   :             tagged[int32] = smi
6057     // kind_fixed_typed_array:  tagged[int32] = (double | int32)
6058     // kind_external:           external[int32] = (double | int32)
6059     if (index == 0) {
6060       return is_fixed_typed_array() ? Representation::External()
6061                                     : Representation::Tagged();
6062     } else if (index == 1) {
6063       return ArrayInstructionInterface::KeyedAccessIndexRequirement(
6064           OperandAt(1)->representation());
6065     } else if (index == 2) {
6066       return RequiredValueRepresentation(elements_kind(), store_mode());
6067     }
6068 
6069     DCHECK_EQ(3, index);
6070     return HasBackingStoreOwner() ? Representation::Tagged()
6071                                   : Representation::None();
6072   }
6073 
RequiredValueRepresentation(ElementsKind kind,StoreFieldOrKeyedMode mode)6074   static Representation RequiredValueRepresentation(
6075       ElementsKind kind, StoreFieldOrKeyedMode mode) {
6076     if (IsDoubleOrFloatElementsKind(kind)) {
6077       return Representation::Double();
6078     }
6079 
6080     if (kind == FAST_SMI_ELEMENTS && SmiValuesAre32Bits() &&
6081         mode == STORE_TO_INITIALIZED_ENTRY) {
6082       return Representation::Integer32();
6083     }
6084 
6085     if (IsFastSmiElementsKind(kind)) {
6086       return Representation::Smi();
6087     }
6088 
6089     if (IsFixedTypedArrayElementsKind(kind)) {
6090       return Representation::Integer32();
6091     }
6092     return Representation::Tagged();
6093   }
6094 
is_fixed_typed_array()6095   bool is_fixed_typed_array() const {
6096     return IsFixedTypedArrayElementsKind(elements_kind());
6097   }
6098 
observed_input_representation(int index)6099   Representation observed_input_representation(int index) override {
6100     if (index != 2) return RequiredInputRepresentation(index);
6101     if (IsUninitialized()) {
6102       return Representation::None();
6103     }
6104     Representation r =
6105         RequiredValueRepresentation(elements_kind(), store_mode());
6106     // For fast object elements kinds, don't assume anything.
6107     if (r.IsTagged()) return Representation::None();
6108     return r;
6109   }
6110 
elements()6111   HValue* elements() const { return OperandAt(0); }
key()6112   HValue* key() const { return OperandAt(1); }
value()6113   HValue* value() const { return OperandAt(2); }
backing_store_owner()6114   HValue* backing_store_owner() const {
6115     DCHECK(HasBackingStoreOwner());
6116     return OperandAt(3);
6117   }
HasBackingStoreOwner()6118   bool HasBackingStoreOwner() const { return OperandAt(0) != OperandAt(3); }
value_is_smi()6119   bool value_is_smi() const { return IsFastSmiElementsKind(elements_kind()); }
store_mode()6120   StoreFieldOrKeyedMode store_mode() const {
6121     return StoreModeField::decode(bit_field_);
6122   }
elements_kind()6123   ElementsKind elements_kind() const override {
6124     return ElementsKindField::decode(bit_field_);
6125   }
base_offset()6126   uint32_t base_offset() const { return base_offset_; }
6127   bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
GetKey()6128   HValue* GetKey() override { return key(); }
SetKey(HValue * key)6129   void SetKey(HValue* key) override { SetOperandAt(1, key); }
IsDehoisted()6130   bool IsDehoisted() const override {
6131     return IsDehoistedField::decode(bit_field_);
6132   }
SetDehoisted(bool is_dehoisted)6133   void SetDehoisted(bool is_dehoisted) override {
6134     bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
6135   }
IsUninitialized()6136   bool IsUninitialized() { return IsUninitializedField::decode(bit_field_); }
SetUninitialized(bool is_uninitialized)6137   void SetUninitialized(bool is_uninitialized) {
6138     bit_field_ = IsUninitializedField::update(bit_field_, is_uninitialized);
6139   }
6140 
IsConstantHoleStore()6141   bool IsConstantHoleStore() {
6142     return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
6143   }
6144 
HandleSideEffectDominator(GVNFlag side_effect,HValue * dominator)6145   bool HandleSideEffectDominator(GVNFlag side_effect,
6146                                  HValue* dominator) override {
6147     DCHECK(side_effect == kNewSpacePromotion);
6148     dominator_ = dominator;
6149     return false;
6150   }
6151 
dominator()6152   HValue* dominator() const { return dominator_; }
6153 
NeedsWriteBarrier()6154   bool NeedsWriteBarrier() {
6155     if (value_is_smi()) {
6156       return false;
6157     } else {
6158       return StoringValueNeedsWriteBarrier(value()) &&
6159           ReceiverObjectNeedsWriteBarrier(elements(), value(), dominator());
6160     }
6161   }
6162 
PointersToHereCheckForValue()6163   PointersToHereCheck PointersToHereCheckForValue() const {
6164     return PointersToHereCheckForObject(value(), dominator());
6165   }
6166 
6167   bool NeedsCanonicalization();
6168 
6169   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6170 
DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)6171   DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
6172 
6173  private:
6174   HStoreKeyed(HValue* obj, HValue* key, HValue* val,
6175               HValue* backing_store_owner, ElementsKind elements_kind,
6176               StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE,
6177               int offset = kDefaultKeyedHeaderOffsetSentinel)
6178       : base_offset_(offset == kDefaultKeyedHeaderOffsetSentinel
6179                          ? GetDefaultHeaderSizeForElementsKind(elements_kind)
6180                          : offset),
6181         bit_field_(IsDehoistedField::encode(false) |
6182                    IsUninitializedField::encode(false) |
6183                    StoreModeField::encode(store_mode) |
6184                    ElementsKindField::encode(elements_kind)),
6185         dominator_(NULL) {
6186     SetOperandAt(0, obj);
6187     SetOperandAt(1, key);
6188     SetOperandAt(2, val);
6189     SetOperandAt(3, backing_store_owner != nullptr ? backing_store_owner : obj);
6190     DCHECK_EQ(HasBackingStoreOwner(), is_fixed_typed_array());
6191 
6192     if (IsFastObjectElementsKind(elements_kind)) {
6193       SetFlag(kTrackSideEffectDominators);
6194       SetDependsOnFlag(kNewSpacePromotion);
6195     }
6196     if (IsFastDoubleElementsKind(elements_kind)) {
6197       SetChangesFlag(kDoubleArrayElements);
6198     } else if (IsFastSmiElementsKind(elements_kind)) {
6199       SetChangesFlag(kArrayElements);
6200     } else if (is_fixed_typed_array()) {
6201       SetChangesFlag(kTypedArrayElements);
6202       SetChangesFlag(kExternalMemory);
6203       SetFlag(kTruncatingToNumber);
6204     } else {
6205       SetChangesFlag(kArrayElements);
6206     }
6207 
6208     // {UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
6209     if (elements_kind >= UINT8_ELEMENTS && elements_kind <= INT32_ELEMENTS) {
6210       SetFlag(kTruncatingToInt32);
6211     }
6212   }
6213 
6214   class IsDehoistedField : public BitField<bool, 0, 1> {};
6215   class IsUninitializedField : public BitField<bool, 1, 1> {};
6216   class StoreModeField : public BitField<StoreFieldOrKeyedMode, 2, 1> {};
6217   class ElementsKindField : public BitField<ElementsKind, 3, 5> {};
6218 
6219   uint32_t base_offset_;
6220   uint32_t bit_field_;
6221   HValue* dominator_;
6222 };
6223 
6224 class HTransitionElementsKind final : public HTemplateInstruction<2> {
6225  public:
New(Isolate * isolate,Zone * zone,HValue * context,HValue * object,Handle<Map> original_map,Handle<Map> transitioned_map)6226   inline static HTransitionElementsKind* New(Isolate* isolate, Zone* zone,
6227                                              HValue* context, HValue* object,
6228                                              Handle<Map> original_map,
6229                                              Handle<Map> transitioned_map) {
6230     return new(zone) HTransitionElementsKind(context, object,
6231                                              original_map, transitioned_map);
6232   }
6233 
RequiredInputRepresentation(int index)6234   Representation RequiredInputRepresentation(int index) override {
6235     return Representation::Tagged();
6236   }
6237 
object()6238   HValue* object() const { return OperandAt(0); }
context()6239   HValue* context() const { return OperandAt(1); }
original_map()6240   Unique<Map> original_map() const { return original_map_; }
transitioned_map()6241   Unique<Map> transitioned_map() const { return transitioned_map_; }
from_kind()6242   ElementsKind from_kind() const {
6243     return FromElementsKindField::decode(bit_field_);
6244   }
to_kind()6245   ElementsKind to_kind() const {
6246     return ToElementsKindField::decode(bit_field_);
6247   }
map_is_stable()6248   bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }
6249 
6250   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6251 
DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)6252   DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
6253 
6254  protected:
6255   bool DataEquals(HValue* other) override {
6256     HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
6257     return original_map_ == instr->original_map_ &&
6258            transitioned_map_ == instr->transitioned_map_;
6259   }
6260 
RedefinedOperandIndex()6261   int RedefinedOperandIndex() override { return 0; }
6262 
6263  private:
HTransitionElementsKind(HValue * context,HValue * object,Handle<Map> original_map,Handle<Map> transitioned_map)6264   HTransitionElementsKind(HValue* context, HValue* object,
6265                           Handle<Map> original_map,
6266                           Handle<Map> transitioned_map)
6267       : original_map_(Unique<Map>(original_map)),
6268         transitioned_map_(Unique<Map>(transitioned_map)),
6269         bit_field_(
6270             FromElementsKindField::encode(original_map->elements_kind()) |
6271             ToElementsKindField::encode(transitioned_map->elements_kind()) |
6272             MapIsStableField::encode(transitioned_map->is_stable())) {
6273     SetOperandAt(0, object);
6274     SetOperandAt(1, context);
6275     SetFlag(kUseGVN);
6276     SetChangesFlag(kElementsKind);
6277     if (!IsSimpleMapChangeTransition(from_kind(), to_kind())) {
6278       SetChangesFlag(kElementsPointer);
6279       SetChangesFlag(kNewSpacePromotion);
6280     }
6281     set_representation(Representation::Tagged());
6282   }
6283 
6284   class FromElementsKindField : public BitField<ElementsKind, 0, 5> {};
6285   class ToElementsKindField : public BitField<ElementsKind, 5, 5> {};
6286   class MapIsStableField : public BitField<bool, 10, 1> {};
6287 
6288   Unique<Map> original_map_;
6289   Unique<Map> transitioned_map_;
6290   uint32_t bit_field_;
6291 };
6292 
6293 
6294 class HStringAdd final : public HBinaryOperation {
6295  public:
6296   static HInstruction* New(
6297       Isolate* isolate, Zone* zone, HValue* context, HValue* left,
6298       HValue* right, PretenureFlag pretenure_flag = NOT_TENURED,
6299       StringAddFlags flags = STRING_ADD_CHECK_BOTH,
6300       Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null());
6301 
flags()6302   StringAddFlags flags() const { return flags_; }
pretenure_flag()6303   PretenureFlag pretenure_flag() const { return pretenure_flag_; }
6304 
RequiredInputRepresentation(int index)6305   Representation RequiredInputRepresentation(int index) override {
6306     return Representation::Tagged();
6307   }
6308 
6309   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6310 
DECLARE_CONCRETE_INSTRUCTION(StringAdd)6311   DECLARE_CONCRETE_INSTRUCTION(StringAdd)
6312 
6313  protected:
6314   bool DataEquals(HValue* other) override {
6315     return flags_ == HStringAdd::cast(other)->flags_ &&
6316         pretenure_flag_ == HStringAdd::cast(other)->pretenure_flag_;
6317   }
6318 
6319  private:
HStringAdd(HValue * context,HValue * left,HValue * right,PretenureFlag pretenure_flag,StringAddFlags flags,Handle<AllocationSite> allocation_site)6320   HStringAdd(HValue* context, HValue* left, HValue* right,
6321              PretenureFlag pretenure_flag, StringAddFlags flags,
6322              Handle<AllocationSite> allocation_site)
6323       : HBinaryOperation(context, left, right, HType::String()),
6324         flags_(flags),
6325         pretenure_flag_(pretenure_flag) {
6326     set_representation(Representation::Tagged());
6327     if ((flags & STRING_ADD_CONVERT) == STRING_ADD_CONVERT) {
6328       SetAllSideEffects();
6329       ClearFlag(kUseGVN);
6330     } else {
6331       SetChangesFlag(kNewSpacePromotion);
6332       SetFlag(kUseGVN);
6333     }
6334     SetDependsOnFlag(kMaps);
6335     if (FLAG_trace_pretenuring) {
6336       PrintF("HStringAdd with AllocationSite %p %s\n",
6337              allocation_site.is_null()
6338                  ? static_cast<void*>(NULL)
6339                  : static_cast<void*>(*allocation_site),
6340              pretenure_flag == TENURED ? "tenured" : "not tenured");
6341     }
6342   }
6343 
IsDeletable()6344   bool IsDeletable() const final {
6345     return (flags_ & STRING_ADD_CONVERT) != STRING_ADD_CONVERT;
6346   }
6347 
6348   const StringAddFlags flags_;
6349   const PretenureFlag pretenure_flag_;
6350 };
6351 
6352 
6353 class HStringCharCodeAt final : public HTemplateInstruction<3> {
6354  public:
6355   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HStringCharCodeAt,
6356                                               HValue*,
6357                                               HValue*);
6358 
RequiredInputRepresentation(int index)6359   Representation RequiredInputRepresentation(int index) override {
6360     // The index is supposed to be Integer32.
6361     return index == 2
6362         ? Representation::Integer32()
6363         : Representation::Tagged();
6364   }
6365 
context()6366   HValue* context() const { return OperandAt(0); }
string()6367   HValue* string() const { return OperandAt(1); }
index()6368   HValue* index() const { return OperandAt(2); }
6369 
DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)6370   DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
6371 
6372  protected:
6373   bool DataEquals(HValue* other) override { return true; }
6374 
InferRange(Zone * zone)6375   Range* InferRange(Zone* zone) override {
6376     return new(zone) Range(0, String::kMaxUtf16CodeUnit);
6377   }
6378 
6379  private:
HStringCharCodeAt(HValue * context,HValue * string,HValue * index)6380   HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
6381     SetOperandAt(0, context);
6382     SetOperandAt(1, string);
6383     SetOperandAt(2, index);
6384     set_representation(Representation::Integer32());
6385     SetFlag(kUseGVN);
6386     SetDependsOnFlag(kMaps);
6387     SetDependsOnFlag(kStringChars);
6388     SetChangesFlag(kNewSpacePromotion);
6389   }
6390 
6391   // No side effects: runtime function assumes string + number inputs.
IsDeletable()6392   bool IsDeletable() const override { return true; }
6393 };
6394 
6395 
6396 class HStringCharFromCode final : public HTemplateInstruction<2> {
6397  public:
6398   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
6399                            HValue* char_code);
6400 
RequiredInputRepresentation(int index)6401   Representation RequiredInputRepresentation(int index) override {
6402     return index == 0
6403         ? Representation::Tagged()
6404         : Representation::Integer32();
6405   }
6406 
context()6407   HValue* context() const { return OperandAt(0); }
value()6408   HValue* value() const { return OperandAt(1); }
6409 
DataEquals(HValue * other)6410   bool DataEquals(HValue* other) override { return true; }
6411 
DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)6412   DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
6413 
6414  private:
6415   HStringCharFromCode(HValue* context, HValue* char_code)
6416       : HTemplateInstruction<2>(HType::String()) {
6417     SetOperandAt(0, context);
6418     SetOperandAt(1, char_code);
6419     set_representation(Representation::Tagged());
6420     SetFlag(kUseGVN);
6421     SetChangesFlag(kNewSpacePromotion);
6422   }
6423 
IsDeletable()6424   bool IsDeletable() const override {
6425     return !value()->ToNumberCanBeObserved();
6426   }
6427 };
6428 
6429 
6430 class HTypeof final : public HTemplateInstruction<2> {
6431  public:
6432   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HTypeof, HValue*);
6433 
context()6434   HValue* context() const { return OperandAt(0); }
value()6435   HValue* value() const { return OperandAt(1); }
6436 
6437   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6438 
RequiredInputRepresentation(int index)6439   Representation RequiredInputRepresentation(int index) override {
6440     return Representation::Tagged();
6441   }
6442 
DECLARE_CONCRETE_INSTRUCTION(Typeof)6443   DECLARE_CONCRETE_INSTRUCTION(Typeof)
6444 
6445  private:
6446   explicit HTypeof(HValue* context, HValue* value) {
6447     SetOperandAt(0, context);
6448     SetOperandAt(1, value);
6449     set_representation(Representation::Tagged());
6450   }
6451 
IsDeletable()6452   bool IsDeletable() const override { return true; }
6453 };
6454 
6455 
6456 class HTrapAllocationMemento final : public HTemplateInstruction<1> {
6457  public:
6458   DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
6459 
RequiredInputRepresentation(int index)6460   Representation RequiredInputRepresentation(int index) override {
6461     return Representation::Tagged();
6462   }
6463 
object()6464   HValue* object() { return OperandAt(0); }
6465 
DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)6466   DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
6467 
6468  private:
6469   explicit HTrapAllocationMemento(HValue* obj) {
6470     SetOperandAt(0, obj);
6471   }
6472 };
6473 
6474 
6475 class HMaybeGrowElements final : public HTemplateInstruction<5> {
6476  public:
6477   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(HMaybeGrowElements, HValue*,
6478                                               HValue*, HValue*, HValue*, bool,
6479                                               ElementsKind);
6480 
RequiredInputRepresentation(int index)6481   Representation RequiredInputRepresentation(int index) override {
6482     if (index < 3) {
6483       return Representation::Tagged();
6484     }
6485     DCHECK(index == 3 || index == 4);
6486     return Representation::Integer32();
6487   }
6488 
context()6489   HValue* context() const { return OperandAt(0); }
object()6490   HValue* object() const { return OperandAt(1); }
elements()6491   HValue* elements() const { return OperandAt(2); }
key()6492   HValue* key() const { return OperandAt(3); }
current_capacity()6493   HValue* current_capacity() const { return OperandAt(4); }
6494 
is_js_array()6495   bool is_js_array() const { return is_js_array_; }
kind()6496   ElementsKind kind() const { return kind_; }
6497 
DECLARE_CONCRETE_INSTRUCTION(MaybeGrowElements)6498   DECLARE_CONCRETE_INSTRUCTION(MaybeGrowElements)
6499 
6500  protected:
6501   bool DataEquals(HValue* other) override { return true; }
6502 
6503  private:
HMaybeGrowElements(HValue * context,HValue * object,HValue * elements,HValue * key,HValue * current_capacity,bool is_js_array,ElementsKind kind)6504   explicit HMaybeGrowElements(HValue* context, HValue* object, HValue* elements,
6505                               HValue* key, HValue* current_capacity,
6506                               bool is_js_array, ElementsKind kind) {
6507     is_js_array_ = is_js_array;
6508     kind_ = kind;
6509 
6510     SetOperandAt(0, context);
6511     SetOperandAt(1, object);
6512     SetOperandAt(2, elements);
6513     SetOperandAt(3, key);
6514     SetOperandAt(4, current_capacity);
6515 
6516     SetFlag(kUseGVN);
6517     SetChangesFlag(kElementsPointer);
6518     SetChangesFlag(kNewSpacePromotion);
6519     set_representation(Representation::Tagged());
6520   }
6521 
6522   bool is_js_array_;
6523   ElementsKind kind_;
6524 };
6525 
6526 
6527 class HSeqStringGetChar final : public HTemplateInstruction<2> {
6528  public:
6529   static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
6530                            String::Encoding encoding, HValue* string,
6531                            HValue* index);
6532 
RequiredInputRepresentation(int index)6533   Representation RequiredInputRepresentation(int index) override {
6534     return (index == 0) ? Representation::Tagged()
6535                         : Representation::Integer32();
6536   }
6537 
encoding()6538   String::Encoding encoding() const { return encoding_; }
string()6539   HValue* string() const { return OperandAt(0); }
index()6540   HValue* index() const { return OperandAt(1); }
6541 
DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)6542   DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)
6543 
6544  protected:
6545   bool DataEquals(HValue* other) override {
6546     return encoding() == HSeqStringGetChar::cast(other)->encoding();
6547   }
6548 
InferRange(Zone * zone)6549   Range* InferRange(Zone* zone) override {
6550     if (encoding() == String::ONE_BYTE_ENCODING) {
6551       return new(zone) Range(0, String::kMaxOneByteCharCode);
6552     } else {
6553       DCHECK_EQ(String::TWO_BYTE_ENCODING, encoding());
6554       return  new(zone) Range(0, String::kMaxUtf16CodeUnit);
6555     }
6556   }
6557 
6558  private:
HSeqStringGetChar(String::Encoding encoding,HValue * string,HValue * index)6559   HSeqStringGetChar(String::Encoding encoding,
6560                     HValue* string,
6561                     HValue* index) : encoding_(encoding) {
6562     SetOperandAt(0, string);
6563     SetOperandAt(1, index);
6564     set_representation(Representation::Integer32());
6565     SetFlag(kUseGVN);
6566     SetDependsOnFlag(kStringChars);
6567   }
6568 
IsDeletable()6569   bool IsDeletable() const override { return true; }
6570 
6571   String::Encoding encoding_;
6572 };
6573 
6574 
6575 class HSeqStringSetChar final : public HTemplateInstruction<4> {
6576  public:
6577   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(
6578       HSeqStringSetChar, String::Encoding,
6579       HValue*, HValue*, HValue*);
6580 
encoding()6581   String::Encoding encoding() { return encoding_; }
context()6582   HValue* context() { return OperandAt(0); }
string()6583   HValue* string() { return OperandAt(1); }
index()6584   HValue* index() { return OperandAt(2); }
value()6585   HValue* value() { return OperandAt(3); }
6586 
RequiredInputRepresentation(int index)6587   Representation RequiredInputRepresentation(int index) override {
6588     return (index <= 1) ? Representation::Tagged()
6589                         : Representation::Integer32();
6590   }
6591 
DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)6592   DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
6593 
6594  private:
6595   HSeqStringSetChar(HValue* context,
6596                     String::Encoding encoding,
6597                     HValue* string,
6598                     HValue* index,
6599                     HValue* value) : encoding_(encoding) {
6600     SetOperandAt(0, context);
6601     SetOperandAt(1, string);
6602     SetOperandAt(2, index);
6603     SetOperandAt(3, value);
6604     set_representation(Representation::Tagged());
6605     SetChangesFlag(kStringChars);
6606   }
6607 
6608   String::Encoding encoding_;
6609 };
6610 
6611 
6612 class HCheckMapValue final : public HTemplateInstruction<2> {
6613  public:
6614   DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);
6615 
RequiredInputRepresentation(int index)6616   Representation RequiredInputRepresentation(int index) override {
6617     return Representation::Tagged();
6618   }
6619 
6620   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6621 
CalculateInferredType()6622   HType CalculateInferredType() override {
6623     if (value()->type().IsHeapObject()) return value()->type();
6624     return HType::HeapObject();
6625   }
6626 
value()6627   HValue* value() const { return OperandAt(0); }
map()6628   HValue* map() const { return OperandAt(1); }
6629 
6630   HValue* Canonicalize() override;
6631 
DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)6632   DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
6633 
6634  protected:
6635   int RedefinedOperandIndex() override { return 0; }
6636 
DataEquals(HValue * other)6637   bool DataEquals(HValue* other) override { return true; }
6638 
6639  private:
HCheckMapValue(HValue * value,HValue * map)6640   HCheckMapValue(HValue* value, HValue* map)
6641       : HTemplateInstruction<2>(HType::HeapObject()) {
6642     SetOperandAt(0, value);
6643     SetOperandAt(1, map);
6644     set_representation(Representation::Tagged());
6645     SetFlag(kUseGVN);
6646     SetDependsOnFlag(kMaps);
6647     SetDependsOnFlag(kElementsKind);
6648   }
6649 };
6650 
6651 
6652 class HForInPrepareMap final : public HTemplateInstruction<2> {
6653  public:
6654   DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HForInPrepareMap, HValue*);
6655 
RequiredInputRepresentation(int index)6656   Representation RequiredInputRepresentation(int index) override {
6657     return Representation::Tagged();
6658   }
6659 
context()6660   HValue* context() const { return OperandAt(0); }
enumerable()6661   HValue* enumerable() const { return OperandAt(1); }
6662 
6663   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6664 
CalculateInferredType()6665   HType CalculateInferredType() override { return HType::Tagged(); }
6666 
6667   DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
6668 
6669  private:
HForInPrepareMap(HValue * context,HValue * object)6670   HForInPrepareMap(HValue* context,
6671                    HValue* object) {
6672     SetOperandAt(0, context);
6673     SetOperandAt(1, object);
6674     set_representation(Representation::Tagged());
6675     SetAllSideEffects();
6676   }
6677 };
6678 
6679 
6680 class HForInCacheArray final : public HTemplateInstruction<2> {
6681  public:
6682   DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
6683 
RequiredInputRepresentation(int index)6684   Representation RequiredInputRepresentation(int index) override {
6685     return Representation::Tagged();
6686   }
6687 
enumerable()6688   HValue* enumerable() const { return OperandAt(0); }
map()6689   HValue* map() const { return OperandAt(1); }
idx()6690   int idx() const { return idx_; }
6691 
index_cache()6692   HForInCacheArray* index_cache() {
6693     return index_cache_;
6694   }
6695 
set_index_cache(HForInCacheArray * index_cache)6696   void set_index_cache(HForInCacheArray* index_cache) {
6697     index_cache_ = index_cache;
6698   }
6699 
6700   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6701 
CalculateInferredType()6702   HType CalculateInferredType() override { return HType::Tagged(); }
6703 
6704   DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
6705 
6706  private:
HForInCacheArray(HValue * enumerable,HValue * keys,int idx)6707   HForInCacheArray(HValue* enumerable,
6708                    HValue* keys,
6709                    int idx) : idx_(idx) {
6710     SetOperandAt(0, enumerable);
6711     SetOperandAt(1, keys);
6712     set_representation(Representation::Tagged());
6713   }
6714 
6715   int idx_;
6716   HForInCacheArray* index_cache_;
6717 };
6718 
6719 
6720 class HLoadFieldByIndex final : public HTemplateInstruction<2> {
6721  public:
6722   DECLARE_INSTRUCTION_FACTORY_P2(HLoadFieldByIndex, HValue*, HValue*);
6723 
HLoadFieldByIndex(HValue * object,HValue * index)6724   HLoadFieldByIndex(HValue* object,
6725                     HValue* index) {
6726     SetOperandAt(0, object);
6727     SetOperandAt(1, index);
6728     SetChangesFlag(kNewSpacePromotion);
6729     set_representation(Representation::Tagged());
6730   }
6731 
RequiredInputRepresentation(int index)6732   Representation RequiredInputRepresentation(int index) override {
6733     if (index == 1) {
6734       return Representation::Smi();
6735     } else {
6736       return Representation::Tagged();
6737     }
6738   }
6739 
object()6740   HValue* object() const { return OperandAt(0); }
index()6741   HValue* index() const { return OperandAt(1); }
6742 
6743   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6744 
CalculateInferredType()6745   HType CalculateInferredType() override { return HType::Tagged(); }
6746 
6747   DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
6748 
6749  private:
IsDeletable()6750   bool IsDeletable() const override { return true; }
6751 };
6752 
6753 #undef DECLARE_INSTRUCTION
6754 #undef DECLARE_CONCRETE_INSTRUCTION
6755 
6756 }  // namespace internal
6757 }  // namespace v8
6758 
6759 #endif  // V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_
6760