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
25namespace v8 {
26namespace internal {
27
28// Forward declarations.
29struct ChangesOf;
30class HBasicBlock;
31class HDiv;
32class HEnvironment;
33class HInferRepresentationPhase;
34class HInstruction;
35class HLoopInformation;
36class HStoreNamedField;
37class HValue;
38class LInstruction;
39class LChunkBuilder;
40class 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
187enum PropertyAccessType { LOAD, STORE };
188
189Representation RepresentationFromMachineType(MachineType type);
190
191class Range final : public ZoneObject {
192 public:
193  Range()
194      : lower_(kMinInt),
195        upper_(kMaxInt),
196        next_(NULL),
197        can_be_minus_zero_(false) { }
198
199  Range(int32_t lower, int32_t upper)
200      : lower_(lower),
201        upper_(upper),
202        next_(NULL),
203        can_be_minus_zero_(false) { }
204
205  int32_t upper() const { return upper_; }
206  int32_t lower() const { return lower_; }
207  Range* next() const { return next_; }
208  Range* CopyClearLower(Zone* zone) const {
209    return new(zone) Range(kMinInt, upper_);
210  }
211  Range* CopyClearUpper(Zone* zone) const {
212    return new(zone) Range(lower_, kMaxInt);
213  }
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;
220  void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
221  bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
222  bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
223  bool CanBeNegative() const { return lower_ < 0; }
224  bool CanBePositive() const { return upper_ > 0; }
225  bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
226  bool IsMostGeneric() const {
227    return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
228  }
229  bool IsInSmiRange() const {
230    return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
231  }
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
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
267class HUseListNode: public ZoneObject {
268 public:
269  HUseListNode(HValue* value, int index, HUseListNode* tail)
270      : tail_(tail), value_(value), index_(index) {
271  }
272
273  HUseListNode* tail();
274  HValue* value() const { return value_; }
275  int index() const { return index_; }
276
277  void set_tail(HUseListNode* list) { tail_ = list; }
278
279#ifdef DEBUG
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.
296class HUseIterator final BASE_EMBEDDED {
297 public:
298  bool Done() { return current_ == NULL; }
299  void Advance();
300
301  HValue* value() {
302    DCHECK(!Done());
303    return value_;
304  }
305
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.
324enum 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
338static inline GVNFlag GVNFlagFromInt(int i) {
339  DCHECK(i >= 0);
340  DCHECK(i < kNumberOfFlags);
341  return static_cast<GVNFlag>(i);
342}
343
344
345class DecompositionResult final BASE_EMBEDDED {
346 public:
347  DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
348
349  HValue* base() { return base_; }
350  int offset() { return offset_; }
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
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:
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
390typedef EnumSet<GVNFlag, int32_t> GVNFlagSet;
391
392
393class 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
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; }
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; }
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())
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) {}
486  virtual ~HValue() {}
487
488  virtual SourcePosition position() const { return SourcePosition::Unknown(); }
489
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
496  int id() const { return id_; }
497  void set_id(int id) { id_ = id; }
498
499  HUseIterator uses() const { return HUseIterator(use_list_); }
500
501  virtual bool EmitAtUses() { return false; }
502
503  Representation representation() const { return representation_; }
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
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
528  HType type() const { return 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;
543  virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
544  bool IsInformativeDefinition() {
545    return RedefinedOperandIndex() != kNoRedefinedOperand;
546  }
547  HValue* RedefinedOperand() {
548    int index = RedefinedOperandIndex();
549    return index == kNoRedefinedOperand ? NULL : OperandAt(index);
550  }
551
552  bool CanReplaceWithDummyUses();
553
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).
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.
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);
585  bool HasNoUses() const { return use_list_ == NULL; }
586  bool HasOneUse() const {
587    return use_list_ != NULL && use_list_->tail() == NULL;
588  }
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
597  int flags() const { return flags_; }
598  void SetFlag(Flag f) { flags_ |= (1 << f); }
599  void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
600  bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
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
613  GVNFlagSet ChangesFlags() const { return changes_flags_; }
614  GVNFlagSet DependsOnFlags() const { return depends_on_flags_; }
615  void SetChangesFlag(GVNFlag f) { changes_flags_.Add(f); }
616  void SetDependsOnFlag(GVNFlag f) { depends_on_flags_.Add(f); }
617  void ClearChangesFlag(GVNFlag f) { changes_flags_.Remove(f); }
618  void ClearDependsOnFlag(GVNFlag f) { depends_on_flags_.Remove(f); }
619  bool CheckChangesFlag(GVNFlag f) const {
620    return changes_flags_.Contains(f);
621  }
622  bool CheckDependsOnFlag(GVNFlag f) const {
623    return depends_on_flags_.Contains(f);
624  }
625  void SetAllSideEffects() { changes_flags_.Add(AllSideEffectsFlagSet()); }
626  void ClearAllSideEffects() {
627    changes_flags_.Remove(AllSideEffectsFlagSet());
628  }
629  bool HasSideEffects() const {
630    return changes_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
631  }
632  bool HasObservableSideEffects() const {
633    return !CheckFlag(kHasNoObservableSideEffects) &&
634        changes_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
635  }
636
637  GVNFlagSet SideEffectFlags() const {
638    GVNFlagSet result = ChangesFlags();
639    result.Intersect(AllSideEffectsFlagSet());
640    return result;
641  }
642
643  GVNFlagSet ObservableChangesFlags() const {
644    GVNFlagSet result = ChangesFlags();
645    result.Intersect(AllObservableSideEffectsFlagSet());
646    return result;
647  }
648
649  Range* range() const {
650    DCHECK(!range_poisoned_);
651    return range_;
652  }
653  bool HasRange() const {
654    DCHECK(!range_poisoned_);
655    return range_ != NULL;
656  }
657#ifdef DEBUG
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.
665  virtual bool HasEscapingOperandAt(int index) { return true; }
666  virtual bool HasOutOfBoundsAccess(int size) { return false; }
667
668  // Representation helpers.
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.
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.
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.
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.
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.
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.
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.
733  bool ToNumberCanBeObserved() const {
734    return ToStringOrToNumberCanBeObserved();
735  }
736
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.
745  virtual bool DataEquals(HValue* other) {
746    UNREACHABLE();
747    return false;
748  }
749
750  bool ToStringOrToNumberCanBeObserved() const {
751    if (type().IsTaggedPrimitive()) return false;
752    if (type().IsJSReceiver()) return true;
753    return !representation().IsSmiOrInteger32() && !representation().IsDouble();
754  }
755
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
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;
772  void clear_block() {
773    DCHECK(block_ != NULL);
774    block_ = NULL;
775  }
776
777  void set_representation(Representation r) {
778    DCHECK(representation_.IsNone() && !r.IsNone());
779    representation_ = r;
780  }
781
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.
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);
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:
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.
840struct NameOf {
841  explicit NameOf(const HValue* const v) : value(v) {}
842  const HValue* value;
843};
844
845
846struct TypeOf {
847  explicit TypeOf(const HValue* const v) : value(v) {}
848  const HValue* value;
849};
850
851
852struct ChangesOf {
853  explicit ChangesOf(const HValue* const v) : value(v) {}
854  const HValue* value;
855};
856
857
858std::ostream& operator<<(std::ostream& os, const HValue& v);
859std::ostream& operator<<(std::ostream& os, const NameOf& v);
860std::ostream& operator<<(std::ostream& os, const TypeOf& v);
861std::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
948class HInstruction : public HValue {
949 public:
950  HInstruction* next() const { return next_; }
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
956  bool IsLinked() const { return block() != NULL; }
957  void Unlink();
958
959  void InsertBefore(HInstruction* next);
960
961  template<class T> T* Prepend(T* instr) {
962    instr->InsertBefore(this);
963    return instr;
964  }
965
966  void InsertAfter(HInstruction* previous);
967
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.
974  SourcePosition position() const override { return position_; }
975  bool has_position() const { return position_.IsKnown(); }
976  void set_position(SourcePosition position) {
977    DCHECK(position.IsKnown());
978    position_ = position;
979  }
980
981  bool Dominates(HInstruction* other);
982  bool CanTruncateToSmi() const { return CheckFlag(kTruncatingToSmi); }
983  bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
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
994  virtual bool HasStackCheck() { return false; }
995
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
1007  void DeleteFromGraph() override { Unlink(); }
1008
1009 private:
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
1023template<int V>
1024class HTemplateInstruction : public HInstruction {
1025 public:
1026  int OperandCount() const final { return V; }
1027  HValue* OperandAt(int i) const final { return inputs_[i]; }
1028
1029 protected:
1030  explicit HTemplateInstruction(HType type = HType::Tagged())
1031      : HInstruction(type) {}
1032
1033  void InternalSetOperandAt(int i, HValue* value) final { inputs_[i] = value; }
1034
1035 private:
1036  EmbeddedContainer<HValue*, V> inputs_;
1037};
1038
1039
1040class 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
1048  virtual bool KnownSuccessorBlock(HBasicBlock** block) {
1049    *block = NULL;
1050    return false;
1051  }
1052
1053  HBasicBlock* FirstSuccessor() {
1054    return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
1055  }
1056  HBasicBlock* SecondSuccessor() {
1057    return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
1058  }
1059
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
1070class HSuccessorIterator final BASE_EMBEDDED {
1071 public:
1072  explicit HSuccessorIterator(const HControlInstruction* instr)
1073      : instr_(instr), current_(0) {}
1074
1075  bool Done() { return current_ >= instr_->SuccessorCount(); }
1076  HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
1077  void Advance() { current_++; }
1078
1079 private:
1080  const HControlInstruction* instr_;
1081  int current_;
1082};
1083
1084
1085template<int S, int V>
1086class HTemplateControlInstruction : public HControlInstruction {
1087 public:
1088  int SuccessorCount() const override { return S; }
1089  HBasicBlock* SuccessorAt(int i) const override { return successors_[i]; }
1090  void SetSuccessorAt(int i, HBasicBlock* block) override {
1091    successors_[i] = block;
1092  }
1093
1094  int OperandCount() const override { return V; }
1095  HValue* OperandAt(int i) const override { return inputs_[i]; }
1096
1097
1098 protected:
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
1109class HBlockEntry final : public HTemplateInstruction<0> {
1110 public:
1111  Representation RequiredInputRepresentation(int index) override {
1112    return Representation::None();
1113  }
1114
1115  DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
1116};
1117
1118
1119class HDummyUse final : public HTemplateInstruction<1> {
1120 public:
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
1129  HValue* value() const { return OperandAt(0); }
1130
1131  bool HasEscapingOperandAt(int index) override { return false; }
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.
1143class HDebugBreak final : public HTemplateInstruction<0> {
1144 public:
1145  DECLARE_INSTRUCTION_FACTORY_P0(HDebugBreak);
1146
1147  Representation RequiredInputRepresentation(int index) override {
1148    return Representation::None();
1149  }
1150
1151  DECLARE_CONCRETE_INSTRUCTION(DebugBreak)
1152};
1153
1154
1155class HPrologue final : public HTemplateInstruction<0> {
1156 public:
1157  static HPrologue* New(Zone* zone) { return new (zone) HPrologue(); }
1158
1159  Representation RequiredInputRepresentation(int index) override {
1160    return Representation::None();
1161  }
1162
1163  DECLARE_CONCRETE_INSTRUCTION(Prologue)
1164};
1165
1166
1167class HGoto final : public HTemplateControlInstruction<1, 0> {
1168 public:
1169  explicit HGoto(HBasicBlock* target) {
1170    SetSuccessorAt(0, target);
1171  }
1172
1173  bool KnownSuccessorBlock(HBasicBlock** block) override {
1174    *block = FirstSuccessor();
1175    return true;
1176  }
1177
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
1188class HDeoptimize final : public HTemplateControlInstruction<1, 0> {
1189 public:
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
1197  bool KnownSuccessorBlock(HBasicBlock** block) override {
1198    *block = NULL;
1199    return true;
1200  }
1201
1202  Representation RequiredInputRepresentation(int index) override {
1203    return Representation::None();
1204  }
1205
1206  DeoptimizeReason reason() const { return reason_; }
1207  Deoptimizer::BailoutType type() { return type_; }
1208
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
1223class HUnaryControlInstruction : public HTemplateControlInstruction<2, 1> {
1224 public:
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
1235  HValue* value() const { return OperandAt(0); }
1236};
1237
1238
1239class 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
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
1255  ToBooleanHints expected_input_types() const { return expected_input_types_; }
1256
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
1270class 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
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;
1288  int known_successor_index() const {
1289    return KnownSuccessorIndexField::decode(bit_field_) -
1290           kInternalKnownSuccessorOffset;
1291  }
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
1298  Unique<Map> map() const { return map_; }
1299  bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }
1300
1301  Representation RequiredInputRepresentation(int index) override {
1302    return Representation::Tagged();
1303  }
1304
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)
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
1334class HContext final : public HTemplateInstruction<0> {
1335 public:
1336  static HContext* New(Zone* zone) {
1337    return new(zone) HContext();
1338  }
1339
1340  Representation RequiredInputRepresentation(int index) override {
1341    return Representation::None();
1342  }
1343
1344  DECLARE_CONCRETE_INSTRUCTION(Context)
1345
1346 protected:
1347  bool DataEquals(HValue* other) override { return true; }
1348
1349 private:
1350  HContext() {
1351    set_representation(Representation::Tagged());
1352    SetFlag(kUseGVN);
1353  }
1354
1355  bool IsDeletable() const override { return true; }
1356};
1357
1358
1359class 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
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
1372  HValue* value() const { return OperandAt(0); }
1373  HValue* context() const { return OperandAt(1); }
1374  HValue* parameter_count() const { return OperandAt(2); }
1375
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
1387class HAbnormalExit final : public HTemplateControlInstruction<0, 0> {
1388 public:
1389  DECLARE_INSTRUCTION_FACTORY_P0(HAbnormalExit);
1390
1391  Representation RequiredInputRepresentation(int index) override {
1392    return Representation::None();
1393  }
1394
1395  DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
1396 private:
1397  HAbnormalExit() {}
1398};
1399
1400
1401class 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
1408  static HUnaryOperation* cast(HValue* value) {
1409    return reinterpret_cast<HUnaryOperation*>(value);
1410  }
1411
1412  HValue* value() const { return OperandAt(0); }
1413  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
1414};
1415
1416
1417class HUseConst final : public HUnaryOperation {
1418 public:
1419  DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue*);
1420
1421  Representation RequiredInputRepresentation(int index) override {
1422    return Representation::None();
1423  }
1424
1425  DECLARE_CONCRETE_INSTRUCTION(UseConst)
1426
1427 private:
1428    explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
1429};
1430
1431
1432class 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
1438  HValue* value() const { return OperandAt(0); }
1439
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  }
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
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
1460class HChange final : public HUnaryOperation {
1461 public:
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
1492  Representation from() const { return value()->representation(); }
1493  Representation to() const { return representation(); }
1494  bool deoptimize_on_minus_zero() const {
1495    return CheckFlag(kBailoutOnMinusZero);
1496  }
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
1505  DECLARE_CONCRETE_INSTRUCTION(Change)
1506
1507 protected:
1508  bool DataEquals(HValue* other) override { return true; }
1509
1510 private:
1511  bool IsDeletable() const override {
1512    return !from().IsTagged() || value()->type().IsSmi();
1513  }
1514};
1515
1516
1517class HClampToUint8 final : public HUnaryOperation {
1518 public:
1519  DECLARE_INSTRUCTION_FACTORY_P1(HClampToUint8, HValue*);
1520
1521  Representation RequiredInputRepresentation(int index) override {
1522    return Representation::None();
1523  }
1524
1525  DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
1526
1527 protected:
1528  bool DataEquals(HValue* other) override { return true; }
1529
1530 private:
1531  explicit HClampToUint8(HValue* value)
1532      : HUnaryOperation(value) {
1533    set_representation(Representation::Integer32());
1534    SetFlag(kTruncatingToNumber);
1535    SetFlag(kUseGVN);
1536  }
1537
1538  bool IsDeletable() const override { return true; }
1539};
1540
1541
1542enum RemovableSimulate {
1543  REMOVABLE_SIMULATE,
1544  FIXED_SIMULATE
1545};
1546
1547
1548class HSimulate final : public HInstruction {
1549 public:
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)) {}
1559  ~HSimulate() {}
1560
1561  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
1562
1563  bool HasAstId() const { return !ast_id_.IsNone(); }
1564  BailoutId ast_id() const { return ast_id_; }
1565  void set_ast_id(BailoutId id) {
1566    DCHECK(!HasAstId());
1567    ast_id_ = id;
1568  }
1569
1570  int pop_count() const { return pop_count_; }
1571  const ZoneList<HValue*>* values() const { return &values_; }
1572  int GetAssignedIndexAt(int index) const {
1573    DCHECK(HasAssignedIndexAt(index));
1574    return assigned_indexes_[index];
1575  }
1576  bool HasAssignedIndexAt(int index) const {
1577    return assigned_indexes_[index] != kNoIndex;
1578  }
1579  void AddAssignedValue(int index, HValue* value) {
1580    AddValue(index, value);
1581  }
1582  void AddPushedValue(HValue* value) {
1583    AddValue(kNoIndex, value);
1584  }
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  }
1591  int OperandCount() const override { return values_.length(); }
1592  HValue* OperandAt(int index) const override { return values_[index]; }
1593
1594  bool HasEscapingOperandAt(int index) override { return false; }
1595  Representation RequiredInputRepresentation(int index) override {
1596    return Representation::None();
1597  }
1598
1599  void MergeWith(ZoneList<HSimulate*>* list);
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;
1611  void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
1612  Handle<JSFunction> closure() const { return closure_; }
1613#endif
1614
1615 protected:
1616  void InternalSetOperandAt(int index, HValue* value) override {
1617    values_[index] = value;
1618  }
1619
1620 private:
1621  static const int kNoIndex = -1;
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  }
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  }
1636  bool is_done_with_replay() const {
1637    return DoneWithReplayField::decode(bit_field_);
1638  }
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
1659class HEnvironmentMarker final : public HTemplateInstruction<1> {
1660 public:
1661  enum Kind { BIND, LOOKUP };
1662
1663  DECLARE_INSTRUCTION_FACTORY_P2(HEnvironmentMarker, Kind, int);
1664
1665  Kind kind() const { return kind_; }
1666  int index() const { return index_; }
1667  HSimulate* next_simulate() { return next_simulate_; }
1668  void set_next_simulate(HSimulate* simulate) {
1669    next_simulate_ = simulate;
1670  }
1671
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
1679  void set_closure(Handle<JSFunction> closure) {
1680    DCHECK(closure_.is_null());
1681    DCHECK(!closure.is_null());
1682    closure_ = closure;
1683  }
1684  Handle<JSFunction> closure() const { return closure_; }
1685#endif
1686
1687  DECLARE_CONCRETE_INSTRUCTION(EnvironmentMarker);
1688
1689 private:
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
1703class 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
1712  HValue* context() { return OperandAt(0); }
1713
1714  Representation RequiredInputRepresentation(int index) override {
1715    return Representation::Tagged();
1716  }
1717
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
1726  bool is_function_entry() { return type_ == kFunctionEntry; }
1727  bool is_backwards_branch() { return type_ == kBackwardsBranch; }
1728
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
1741enum 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
1749class HArgumentsObject;
1750class HConstant;
1751
1752
1753class HEnterInlined final : public HTemplateInstruction<0> {
1754 public:
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);
1769  ZoneList<HBasicBlock*>* return_targets() { return &return_targets_; }
1770
1771  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
1772
1773  Handle<SharedFunctionInfo> shared() const { return shared_; }
1774  Handle<JSFunction> closure() const { return closure_; }
1775  HConstant* closure_context() const { return closure_context_; }
1776  int arguments_count() const { return arguments_count_; }
1777  bool arguments_pushed() const { return arguments_pushed_; }
1778  void set_arguments_pushed() { arguments_pushed_ = true; }
1779  FunctionLiteral* function() const { return function_; }
1780  InliningKind inlining_kind() const { return inlining_kind_; }
1781  TailCallMode syntactic_tail_call_mode() const {
1782    return syntactic_tail_call_mode_;
1783  }
1784  BailoutId ReturnId() const { return return_id_; }
1785  int inlining_id() const { return inlining_id_; }
1786  void set_inlining_id(int inlining_id) { inlining_id_ = inlining_id; }
1787
1788  Representation RequiredInputRepresentation(int index) override {
1789    return Representation::None();
1790  }
1791
1792  Variable* arguments_var() { return arguments_var_; }
1793  HArgumentsObject* arguments_object() { return arguments_object_; }
1794
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
1833class HLeaveInlined final : public HTemplateInstruction<0> {
1834 public:
1835  HLeaveInlined(HEnterInlined* entry,
1836                int drop_count)
1837      : entry_(entry),
1838        drop_count_(drop_count) { }
1839
1840  Representation RequiredInputRepresentation(int index) override {
1841    return Representation::None();
1842  }
1843
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
1856class HPushArguments final : public HInstruction {
1857 public:
1858  static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context) {
1859    return new(zone) HPushArguments(zone);
1860  }
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  }
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  }
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  }
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
1893  Representation RequiredInputRepresentation(int index) override {
1894    return Representation::Tagged();
1895  }
1896
1897  int argument_delta() const override { return inputs_.length(); }
1898  HValue* argument(int i) { return OperandAt(i); }
1899
1900  int OperandCount() const final { return inputs_.length(); }
1901  HValue* OperandAt(int i) const final { return inputs_[i]; }
1902
1903  void AddInput(HValue* value);
1904
1905  DECLARE_CONCRETE_INSTRUCTION(PushArguments)
1906
1907 protected:
1908  void InternalSetOperandAt(int i, HValue* value) final { inputs_[i] = value; }
1909
1910 private:
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
1920class HThisFunction final : public HTemplateInstruction<0> {
1921 public:
1922  DECLARE_INSTRUCTION_FACTORY_P0(HThisFunction);
1923
1924  Representation RequiredInputRepresentation(int index) override {
1925    return Representation::None();
1926  }
1927
1928  DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
1929
1930 protected:
1931  bool DataEquals(HValue* other) override { return true; }
1932
1933 private:
1934  HThisFunction() {
1935    set_representation(Representation::Tagged());
1936    SetFlag(kUseGVN);
1937  }
1938
1939  bool IsDeletable() const override { return true; }
1940};
1941
1942
1943class HDeclareGlobals final : public HUnaryOperation {
1944 public:
1945  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HDeclareGlobals,
1946                                              Handle<FixedArray>, int,
1947                                              Handle<FeedbackVector>);
1948
1949  HValue* context() { return OperandAt(0); }
1950  Handle<FixedArray> declarations() const { return declarations_; }
1951  int flags() const { return flags_; }
1952  Handle<FeedbackVector> feedback_vector() const { return feedback_vector_; }
1953
1954  DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
1955
1956  Representation RequiredInputRepresentation(int index) override {
1957    return Representation::Tagged();
1958  }
1959
1960 private:
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
1977template <int V>
1978class HCall : public HTemplateInstruction<V> {
1979 public:
1980  // The argument count includes the receiver.
1981  explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
1982    this->set_representation(Representation::Tagged());
1983    this->SetAllSideEffects();
1984  }
1985
1986  virtual int argument_count() const {
1987    return argument_count_;
1988  }
1989
1990  int argument_delta() const override { return -argument_count(); }
1991
1992 private:
1993  int argument_count_;
1994};
1995
1996
1997class HUnaryCall : public HCall<1> {
1998 public:
1999  HUnaryCall(HValue* value, int argument_count)
2000      : HCall<1>(argument_count) {
2001    SetOperandAt(0, value);
2002  }
2003
2004  Representation RequiredInputRepresentation(int index) final {
2005    return Representation::Tagged();
2006  }
2007
2008  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
2009
2010  HValue* value() const { return OperandAt(0); }
2011};
2012
2013
2014class HBinaryCall : public HCall<2> {
2015 public:
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
2024  Representation RequiredInputRepresentation(int index) final {
2025    return Representation::Tagged();
2026  }
2027
2028  HValue* first() const { return OperandAt(0); }
2029  HValue* second() const { return OperandAt(1); }
2030};
2031
2032
2033class 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
2059  int OperandCount() const final { return values_.length(); }
2060  HValue* OperandAt(int index) const final { return values_[index]; }
2061
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
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.
2082  TailCallMode tail_call_mode() const {
2083    return TailCallModeField::decode(bit_field_);
2084  }
2085  bool IsTailCall() const { return tail_call_mode() == TailCallMode::kAllow; }
2086
2087  Code::Kind kind() const { return KindField::decode(bit_field_); }
2088
2089  virtual int argument_count() const {
2090    return argument_count_;
2091  }
2092
2093  int argument_delta() const override { return -argument_count_; }
2094
2095  CallInterfaceDescriptor descriptor() const { return descriptor_; }
2096
2097  HValue* target() { return OperandAt(0); }
2098  HValue* context() { return OperandAt(1); }
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.
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
2134  void AddOperand(HValue* v, Zone* zone) {
2135    values_.Add(NULL, zone);
2136    SetOperandAt(values_.length() - 1, v);
2137  }
2138
2139  int GetParameterCount() const { return descriptor_.GetParameterCount(); }
2140
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
2157class HInvokeFunction final : public HBinaryCall {
2158 public:
2159  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HInvokeFunction, HValue*,
2160                                              Handle<JSFunction>, int,
2161                                              TailCallMode, TailCallMode);
2162
2163  HValue* context() { return first(); }
2164  HValue* function() { return second(); }
2165  Handle<JSFunction> known_function() { return known_function_; }
2166  int formal_parameter_count() const { return formal_parameter_count_; }
2167
2168  bool HasStackCheck() final { return HasStackCheckField::decode(bit_field_); }
2169
2170  // Defines whether this instruction corresponds to a JS call at tail position.
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.
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:
2186  void set_has_stack_check(bool has_stack_check) {
2187    bit_field_ = HasStackCheckField::update(bit_field_, has_stack_check);
2188  }
2189
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
2223class HCallNewArray final : public HBinaryCall {
2224 public:
2225  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HCallNewArray, HValue*, int,
2226                                              ElementsKind,
2227                                              Handle<AllocationSite>);
2228
2229  HValue* context() { return first(); }
2230  HValue* constructor() { return second(); }
2231
2232  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
2233
2234  ElementsKind elements_kind() const { return elements_kind_; }
2235  Handle<AllocationSite> site() const { return site_; }
2236
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
2251class 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
2258  HValue* context() { return OperandAt(0); }
2259  const Runtime::Function* function() const { return c_function_; }
2260  SaveFPRegsMode save_doubles() const { return save_doubles_; }
2261  void set_save_doubles(SaveFPRegsMode save_doubles) {
2262    save_doubles_ = save_doubles;
2263  }
2264
2265  Representation RequiredInputRepresentation(int index) override {
2266    return Representation::Tagged();
2267  }
2268
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
2285class HUnaryMathOperation final : public HTemplateInstruction<2> {
2286 public:
2287  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
2288                           HValue* value, BuiltinFunctionId op);
2289
2290  HValue* context() const { return OperandAt(0); }
2291  HValue* value() const { return OperandAt(1); }
2292
2293  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
2294
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
2327  BuiltinFunctionId op() const { return op_; }
2328  const char* OpName() const;
2329
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.
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  }
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
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
2403class 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
2408  Representation RequiredInputRepresentation(int index) override {
2409    return Representation::None();
2410  }
2411
2412  Heap::RootListIndex index() const { return index_; }
2413
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
2432  bool IsDeletable() const override { return true; }
2433
2434  const Heap::RootListIndex index_;
2435};
2436
2437
2438class 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
2456  bool IsStabilityCheck() const {
2457    return IsStabilityCheckField::decode(bit_field_);
2458  }
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
2468  bool HasEscapingOperandAt(int index) override { return false; }
2469  Representation RequiredInputRepresentation(int index) override {
2470    return Representation::Tagged();
2471  }
2472
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
2480  HValue* value() const { return OperandAt(0); }
2481  HValue* typecheck() const { return OperandAt(1); }
2482
2483  const UniqueSet<Map>* maps() const { return maps_; }
2484  void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; }
2485
2486  bool maps_are_stable() const {
2487    return MapsAreStableField::decode(bit_field_);
2488  }
2489
2490  bool HasMigrationTarget() const {
2491    return HasMigrationTargetField::decode(bit_field_);
2492  }
2493
2494  HValue* Canonicalize() override;
2495
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
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
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
2520  int RedefinedOperandIndex() override { return 0; }
2521
2522 private:
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
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
2574class HCheckValue final : public HUnaryOperation {
2575 public:
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  }
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
2591  void FinalizeUniqueness() override {
2592    object_ = Unique<HeapObject>(object_.handle());
2593  }
2594
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
2606  Unique<HeapObject> object() const { return object_; }
2607  bool object_in_new_space() const { return object_in_new_space_; }
2608
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:
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
2632class 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
2648  Representation RequiredInputRepresentation(int index) override {
2649    return Representation::Tagged();
2650  }
2651
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
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
2672  Check check() const { return check_; }
2673
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
2685  int RedefinedOperandIndex() override { return 0; }
2686
2687 private:
2688  const char* GetCheckName() const;
2689
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
2700class HCheckSmi final : public HUnaryOperation {
2701 public:
2702  DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue*);
2703
2704  Representation RequiredInputRepresentation(int index) override {
2705    return Representation::Tagged();
2706  }
2707
2708  HValue* Canonicalize() override {
2709    HType value_type = value()->type();
2710    if (value_type.IsSmi()) {
2711      return NULL;
2712    }
2713    return this;
2714  }
2715
2716  DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
2717
2718 protected:
2719  bool DataEquals(HValue* other) override { return true; }
2720
2721 private:
2722  explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
2723    set_representation(Representation::Smi());
2724    SetFlag(kUseGVN);
2725  }
2726};
2727
2728
2729class HCheckArrayBufferNotNeutered final : public HUnaryOperation {
2730 public:
2731  DECLARE_INSTRUCTION_FACTORY_P1(HCheckArrayBufferNotNeutered, HValue*);
2732
2733  bool HasEscapingOperandAt(int index) override { return false; }
2734  Representation RequiredInputRepresentation(int index) override {
2735    return Representation::Tagged();
2736  }
2737
2738  HType CalculateInferredType() override {
2739    if (value()->type().IsHeapObject()) return value()->type();
2740    return HType::HeapObject();
2741  }
2742
2743  DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered)
2744
2745 protected:
2746  bool DataEquals(HValue* other) override { return true; }
2747  int RedefinedOperandIndex() override { return 0; }
2748
2749 private:
2750  explicit HCheckArrayBufferNotNeutered(HValue* value)
2751      : HUnaryOperation(value) {
2752    set_representation(Representation::Tagged());
2753    SetFlag(kUseGVN);
2754    SetDependsOnFlag(kCalls);
2755  }
2756};
2757
2758
2759class HCheckHeapObject final : public HUnaryOperation {
2760 public:
2761  DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
2762
2763  bool HasEscapingOperandAt(int index) override { return false; }
2764  Representation RequiredInputRepresentation(int index) override {
2765    return Representation::Tagged();
2766  }
2767
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
2777  HValue* Canonicalize() override {
2778    return value()->type().IsHeapObject() ? NULL : this;
2779  }
2780
2781  DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
2782
2783 protected:
2784  bool DataEquals(HValue* other) override { return true; }
2785
2786 private:
2787  explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) {
2788    set_representation(Representation::Tagged());
2789    SetFlag(kUseGVN);
2790  }
2791};
2792
2793
2794class HPhi final : public HValue {
2795 public:
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;
2806  Representation RequiredInputRepresentation(int index) override {
2807    return representation();
2808  }
2809  Representation KnownOptimalRepresentation() override {
2810    return representation();
2811  }
2812  HType CalculateInferredType() override;
2813  int OperandCount() const override { return inputs_.length(); }
2814  HValue* OperandAt(int index) const override { return inputs_[index]; }
2815  HValue* GetRedundantReplacement();
2816  void AddInput(HValue* value);
2817  bool HasRealUses();
2818
2819  bool IsReceiver() const { return merged_index_ == 0; }
2820  bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
2821
2822  SourcePosition position() const override;
2823
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
2835  Representation representation_from_indirect_uses() const {
2836    return representation_from_indirect_uses_;
2837  }
2838
2839  bool has_type_feedback_from_uses() const {
2840    return has_type_feedback_from_uses_;
2841  }
2842
2843  int phi_id() { return phi_id_; }
2844
2845  static HPhi* cast(HValue* value) {
2846    DCHECK(value->IsPhi());
2847    return reinterpret_cast<HPhi*>(value);
2848  }
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;
2858  void InternalSetOperandAt(int index, HValue* value) override {
2859    inputs_[index] = value;
2860  }
2861
2862 private:
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
2876  bool IsDeletable() const override { return !IsReceiver(); }
2877};
2878
2879
2880// Common base class for HArgumentsObject and HCapturedObject.
2881class HDematerializedObject : public HInstruction {
2882 public:
2883  HDematerializedObject(int count, Zone* zone) : values_(count, zone) {}
2884
2885  int OperandCount() const final { return values_.length(); }
2886  HValue* OperandAt(int index) const final { return values_[index]; }
2887
2888  bool HasEscapingOperandAt(int index) final { return false; }
2889  Representation RequiredInputRepresentation(int index) final {
2890    return Representation::None();
2891  }
2892
2893 protected:
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
2903class HArgumentsObject final : public HDematerializedObject {
2904 public:
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.
2912  const ZoneList<HValue*>* arguments_values() const { return &values_; }
2913  int arguments_count() const { return values_.length(); }
2914
2915  void AddArgument(HValue* argument, Zone* zone) {
2916    values_.Add(NULL, zone);  // Resize list.
2917    SetOperandAt(values_.length() - 1, argument);
2918  }
2919
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
2931class HCapturedObject final : public HDematerializedObject {
2932 public:
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.
2942  const ZoneList<HValue*>* values() const { return &values_; }
2943  int length() const { return values_.length(); }
2944  int capture_id() const { return capture_id_; }
2945
2946  // Shortcut for the map value of this captured object.
2947  HValue* map_value() const { return values()->first(); }
2948
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
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
2972class 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
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
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
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
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
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
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
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
3045  bool NotInNewSpace() const {
3046    return IsNotInNewSpaceField::decode(bit_field_);
3047  }
3048
3049  bool ImmortalImmovable() const;
3050
3051  bool IsCell() const {
3052    InstanceType instance_type = GetInstanceType();
3053    return instance_type == CELL_TYPE;
3054  }
3055
3056  Representation RequiredInputRepresentation(int index) override {
3057    return Representation::None();
3058  }
3059
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);
3073  bool HasInteger32Value() const {
3074    return HasInt32ValueField::decode(bit_field_);
3075  }
3076  int32_t Integer32Value() const {
3077    DCHECK(HasInteger32Value());
3078    return int32_value_;
3079  }
3080  bool HasSmiValue() const { return HasSmiValueField::decode(bit_field_); }
3081  bool HasDoubleValue() const {
3082    return HasDoubleValueField::decode(bit_field_);
3083  }
3084  double DoubleValue() const {
3085    DCHECK(HasDoubleValue());
3086    return double_value_;
3087  }
3088  uint64_t DoubleValueAsBits() const {
3089    DCHECK(HasDoubleValue());
3090    return bit_cast<uint64_t>(double_value_);
3091  }
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  }
3099  bool HasNumberValue() const { return HasDoubleValue(); }
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  }
3107  bool HasStringValue() const {
3108    if (HasNumberValue()) return false;
3109    DCHECK(!object_.handle().is_null());
3110    return GetInstanceType() < FIRST_NONSTRING_TYPE;
3111  }
3112  Handle<String> StringValue() const {
3113    DCHECK(HasStringValue());
3114    return Handle<String>::cast(object_.handle());
3115  }
3116  bool HasInternalizedStringValue() const {
3117    return HasStringValue() && StringShape(GetInstanceType()).IsInternalized();
3118  }
3119
3120  bool HasExternalReferenceValue() const {
3121    return HasExternalReferenceValueField::decode(bit_field_);
3122  }
3123  ExternalReference ExternalReferenceValue() const {
3124    return external_reference_value_;
3125  }
3126
3127  bool HasBooleanValue() const { return type_.IsBoolean(); }
3128  bool BooleanValue() const { return BooleanValueField::decode(bit_field_); }
3129  bool IsCallable() const { return IsCallableField::decode(bit_field_); }
3130  bool IsUndetectable() const {
3131    return IsUndetectableField::decode(bit_field_);
3132  }
3133  InstanceType GetInstanceType() const {
3134    return InstanceTypeField::decode(bit_field_);
3135  }
3136
3137  bool HasMapValue() const { return GetInstanceType() == MAP_TYPE; }
3138  Unique<Map> MapValue() const {
3139    DCHECK(HasMapValue());
3140    return Unique<Map>::cast(GetUnique());
3141  }
3142  bool HasStableMapValue() const {
3143    DCHECK(HasMapValue() || !HasStableMapValueField::decode(bit_field_));
3144    return HasStableMapValueField::decode(bit_field_);
3145  }
3146
3147  bool HasObjectMap() const { return !object_map_.IsNull(); }
3148  Unique<Map> ObjectMap() const {
3149    DCHECK(HasObjectMap());
3150    return object_map_;
3151  }
3152
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
3170  void FinalizeUniqueness() override {
3171    if (!HasDoubleValue() && !HasExternalReferenceValue()) {
3172      DCHECK(!object_.handle().is_null());
3173      object_ = Unique<Object>(object_.handle());
3174    }
3175  }
3176
3177  Unique<Object> GetUnique() const {
3178    return object_;
3179  }
3180
3181  bool EqualsUnique(Unique<Object> other) const {
3182    return object_.IsInitialized() && object_ == other;
3183  }
3184
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
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
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
3284class 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
3298  HValue* context() const { return OperandAt(0); }
3299  HValue* left() const { return OperandAt(1); }
3300  HValue* right() const { return OperandAt(2); }
3301
3302  // True if switching left and right operands likely generates better code.
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
3317  HValue* BetterLeftOperand() {
3318    return AreOperandsBetterSwitched() ? right() : left();
3319  }
3320
3321  HValue* BetterRightOperand() {
3322    return AreOperandsBetterSwitched() ? left() : right();
3323  }
3324
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
3330  virtual void initialize_output_representation(Representation observed) {
3331    observed_output_representation_ = observed;
3332  }
3333
3334  Representation observed_input_representation(int index) override {
3335    if (index == 0) return Representation::Tagged();
3336    return observed_input_representation_[index - 1];
3337  }
3338
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
3352  virtual bool IsCommutative() const { return false; }
3353
3354  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
3355
3356  Representation RequiredInputRepresentation(int index) override {
3357    if (index == 0) return Representation::Tagged();
3358    return representation();
3359  }
3360
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
3380class HWrapReceiver final : public HTemplateInstruction<2> {
3381 public:
3382  DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
3383
3384  bool DataEquals(HValue* other) override { return true; }
3385
3386  Representation RequiredInputRepresentation(int index) override {
3387    return Representation::Tagged();
3388  }
3389
3390  HValue* receiver() const { return OperandAt(0); }
3391  HValue* function() const { return OperandAt(1); }
3392
3393  HValue* Canonicalize() override;
3394
3395  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
3396  bool known_function() const { return known_function_; }
3397
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
3414class HApplyArguments final : public HTemplateInstruction<4> {
3415 public:
3416  DECLARE_INSTRUCTION_FACTORY_P5(HApplyArguments, HValue*, HValue*, HValue*,
3417                                 HValue*, TailCallMode);
3418
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
3426  HValue* function() { return OperandAt(0); }
3427  HValue* receiver() { return OperandAt(1); }
3428  HValue* length() { return OperandAt(2); }
3429  HValue* elements() { return OperandAt(3); }
3430
3431  TailCallMode tail_call_mode() const {
3432    return TailCallModeField::decode(bit_field_);
3433  }
3434
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
3454class HArgumentsElements final : public HTemplateInstruction<0> {
3455 public:
3456  DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
3457  DECLARE_INSTRUCTION_FACTORY_P2(HArgumentsElements, bool, bool);
3458
3459  DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
3460
3461  Representation RequiredInputRepresentation(int index) override {
3462    return Representation::None();
3463  }
3464
3465  bool from_inlined() const { return from_inlined_; }
3466  bool arguments_adaptor() const { return arguments_adaptor_; }
3467
3468 protected:
3469  bool DataEquals(HValue* other) override { return true; }
3470
3471 private:
3472  explicit HArgumentsElements(bool from_inlined, bool arguments_adaptor = true)
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
3480  bool IsDeletable() const override { return true; }
3481
3482  bool from_inlined_;
3483  bool arguments_adaptor_;
3484};
3485
3486
3487class HArgumentsLength final : public HUnaryOperation {
3488 public:
3489  DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue*);
3490
3491  Representation RequiredInputRepresentation(int index) override {
3492    return Representation::Tagged();
3493  }
3494
3495  DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
3496
3497 protected:
3498  bool DataEquals(HValue* other) override { return true; }
3499
3500 private:
3501  explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
3502    set_representation(Representation::Integer32());
3503    SetFlag(kUseGVN);
3504  }
3505
3506  bool IsDeletable() const override { return true; }
3507};
3508
3509
3510class 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
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
3523  HValue* arguments() const { return OperandAt(0); }
3524  HValue* length() const { return OperandAt(1); }
3525  HValue* index() const { return OperandAt(2); }
3526
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
3538  bool DataEquals(HValue* other) override { return true; }
3539};
3540
3541
3542class HBoundsCheck final : public HTemplateInstruction<2> {
3543 public:
3544  DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
3545
3546  bool skip_check() const { return skip_check_; }
3547  void set_skip_check() { skip_check_ = true; }
3548
3549  HValue* base() const { return base_; }
3550  int offset() const { return offset_; }
3551  int scale() const { return scale_; }
3552
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
3560  HValue* index() const { return OperandAt(0); }
3561  HValue* length() const { return OperandAt(1); }
3562  bool allow_equality() const { return allow_equality_; }
3563  void set_allow_equality(bool v) { allow_equality_ = v; }
3564
3565  int RedefinedOperandIndex() override { return 0; }
3566  bool IsPurelyInformativeDefinition() override { return skip_check(); }
3567
3568  DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
3569
3570 protected:
3571  Range* InferRange(Zone* zone) override;
3572
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.
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
3595  bool IsDeletable() const override { return skip_check() && !FLAG_debug_code; }
3596};
3597
3598
3599class HBitwiseBinaryOperation : public HBinaryOperation {
3600 public:
3601  HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
3602                          HType type = HType::TaggedNumber())
3603      : HBinaryOperation(context, left, right, type) {
3604    SetFlag(kFlexibleRepresentation);
3605    SetFlag(kTruncatingToInt32);
3606    SetFlag(kTruncatingToNumber);
3607    SetAllSideEffects();
3608  }
3609
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
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
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
3636  void initialize_output_representation(Representation observed) override {
3637    if (observed.IsDouble()) observed = Representation::Integer32();
3638    HBinaryOperation::initialize_output_representation(observed);
3639  }
3640
3641  DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
3642
3643 private:
3644  bool IsDeletable() const override { return true; }
3645};
3646
3647
3648class HMathFloorOfDiv final : public HBinaryOperation {
3649 public:
3650  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HMathFloorOfDiv,
3651                                              HValue*,
3652                                              HValue*);
3653
3654  DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
3655
3656 protected:
3657  bool DataEquals(HValue* other) override { return true; }
3658
3659 private:
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
3674  bool IsDeletable() const override { return true; }
3675};
3676
3677
3678class HArithmeticBinaryOperation : public HBinaryOperation {
3679 public:
3680  HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right,
3681                             HType type = HType::TaggedNumber())
3682      : HBinaryOperation(context, left, right, type) {
3683    SetAllSideEffects();
3684    SetFlag(kFlexibleRepresentation);
3685    SetFlag(kTruncatingToNumber);
3686  }
3687
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
3700  DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
3701
3702 private:
3703  bool IsDeletable() const override { return true; }
3704};
3705
3706
3707class HCompareGeneric final : public HBinaryOperation {
3708 public:
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
3714  Representation RequiredInputRepresentation(int index) override {
3715    return index == 0
3716        ? Representation::Tagged()
3717        : representation();
3718  }
3719
3720  Token::Value token() const { return token_; }
3721  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
3722
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
3739class 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
3750  HValue* left() const { return OperandAt(0); }
3751  HValue* right() const { return OperandAt(1); }
3752  Token::Value token() const { return token_; }
3753
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
3762  Representation RequiredInputRepresentation(int index) override {
3763    return representation();
3764  }
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
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
3792class 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
3800  Representation RequiredInputRepresentation(int index) override {
3801    return representation();
3802  }
3803
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
3816class 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;
3825  int known_successor_index() const { return known_successor_index_; }
3826  void set_known_successor_index(int known_successor_index) {
3827    known_successor_index_ = known_successor_index;
3828  }
3829
3830  HValue* left() const { return OperandAt(0); }
3831  HValue* right() const { return OperandAt(1); }
3832
3833  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
3834
3835  Representation RequiredInputRepresentation(int index) override {
3836    return Representation::Tagged();
3837  }
3838
3839  Representation observed_input_representation(int index) override {
3840    return Representation::Tagged();
3841  }
3842
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
3861class HIsStringAndBranch final : public HUnaryControlInstruction {
3862 public:
3863  DECLARE_INSTRUCTION_FACTORY_P1(HIsStringAndBranch, HValue*);
3864  DECLARE_INSTRUCTION_FACTORY_P3(HIsStringAndBranch, HValue*,
3865                                 HBasicBlock*, HBasicBlock*);
3866
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;
3874  int known_successor_index() const { return known_successor_index_; }
3875  void set_known_successor_index(int known_successor_index) {
3876    known_successor_index_ = known_successor_index;
3877  }
3878
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)
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
3896class HIsSmiAndBranch final : public HUnaryControlInstruction {
3897 public:
3898  DECLARE_INSTRUCTION_FACTORY_P1(HIsSmiAndBranch, HValue*);
3899  DECLARE_INSTRUCTION_FACTORY_P3(HIsSmiAndBranch, HValue*,
3900                                 HBasicBlock*, HBasicBlock*);
3901
3902  DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
3903
3904  Representation RequiredInputRepresentation(int index) override {
3905    return Representation::Tagged();
3906  }
3907
3908 protected:
3909  bool DataEquals(HValue* other) override { return true; }
3910  int RedefinedOperandIndex() override { return 0; }
3911
3912 private:
3913  HIsSmiAndBranch(HValue* value,
3914                  HBasicBlock* true_target = NULL,
3915                  HBasicBlock* false_target = NULL)
3916      : HUnaryControlInstruction(value, true_target, false_target) {
3917    set_representation(Representation::Tagged());
3918  }
3919};
3920
3921
3922class HIsUndetectableAndBranch final : public HUnaryControlInstruction {
3923 public:
3924  DECLARE_INSTRUCTION_FACTORY_P1(HIsUndetectableAndBranch, HValue*);
3925  DECLARE_INSTRUCTION_FACTORY_P3(HIsUndetectableAndBranch, HValue*,
3926                                 HBasicBlock*, HBasicBlock*);
3927
3928  Representation RequiredInputRepresentation(int index) override {
3929    return Representation::Tagged();
3930  }
3931
3932  bool KnownSuccessorBlock(HBasicBlock** block) override;
3933
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
3944class HStringCompareAndBranch final : public HTemplateControlInstruction<2, 3> {
3945 public:
3946  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HStringCompareAndBranch,
3947                                              HValue*,
3948                                              HValue*,
3949                                              Token::Value);
3950
3951  HValue* context() const { return OperandAt(0); }
3952  HValue* left() const { return OperandAt(1); }
3953  HValue* right() const { return OperandAt(2); }
3954  Token::Value token() const { return token_; }
3955
3956  std::ostream& PrintDataTo(std::ostream& os) const final;  // NOLINT
3957
3958  Representation RequiredInputRepresentation(int index) final {
3959    return Representation::Tagged();
3960  }
3961
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
3982class 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
3989  InstanceType from() { return from_; }
3990  InstanceType to() { return to_; }
3991
3992  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
3993
3994  Representation RequiredInputRepresentation(int index) override {
3995    return Representation::Tagged();
3996  }
3997
3998  bool KnownSuccessorBlock(HBasicBlock** block) override;
3999
4000  DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
4001
4002 private:
4003  HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
4004      : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
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
4014class HClassOfTestAndBranch final : public HUnaryControlInstruction {
4015 public:
4016  DECLARE_INSTRUCTION_FACTORY_P2(HClassOfTestAndBranch, HValue*,
4017                                 Handle<String>);
4018
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
4027  Handle<String> class_name() const { return class_name_; }
4028
4029 private:
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
4038class HTypeofIsAndBranch final : public HUnaryControlInstruction {
4039 public:
4040  DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle<String>);
4041
4042  Handle<String> type_literal() const { return type_literal_.handle(); }
4043  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
4044
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
4053  void FinalizeUniqueness() override {
4054    type_literal_ = Unique<String>(type_literal_.handle());
4055  }
4056
4057 private:
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
4066class HHasInPrototypeChainAndBranch final
4067    : public HTemplateControlInstruction<2, 2> {
4068 public:
4069  DECLARE_INSTRUCTION_FACTORY_P2(HHasInPrototypeChainAndBranch, HValue*,
4070                                 HValue*);
4071
4072  HValue* object() const { return OperandAt(0); }
4073  HValue* prototype() const { return OperandAt(1); }
4074
4075  Representation RequiredInputRepresentation(int index) override {
4076    return Representation::Tagged();
4077  }
4078
4079  bool ObjectNeedsSmiCheck() const {
4080    return !object()->type().IsHeapObject() &&
4081           !object()->representation().IsHeapObject();
4082  }
4083
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
4095class HPower final : public HTemplateInstruction<2> {
4096 public:
4097  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4098                           HValue* left, HValue* right);
4099
4100  HValue* left() { return OperandAt(0); }
4101  HValue* right() const { return OperandAt(1); }
4102
4103  Representation RequiredInputRepresentation(int index) override {
4104    return index == 0
4105      ? Representation::Double()
4106      : Representation::None();
4107  }
4108  Representation observed_input_representation(int index) override {
4109    return RequiredInputRepresentation(index);
4110  }
4111
4112  DECLARE_CONCRETE_INSTRUCTION(Power)
4113
4114 protected:
4115  bool DataEquals(HValue* other) override { return true; }
4116
4117 private:
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
4126  bool IsDeletable() const override {
4127    return !right()->representation().IsTagged();
4128  }
4129};
4130
4131
4132enum ExternalAddType {
4133  AddOfExternalAndTagged,
4134  AddOfExternalAndInt32,
4135  NoExternalAdd
4136};
4137
4138
4139class 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).
4150  bool IsCommutative() const override {
4151    return !representation().IsTagged() && !representation().IsExternal();
4152  }
4153
4154  HValue* Canonicalize() override;
4155
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
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
4189  ExternalAddType external_add_type() const { return external_add_type_; }
4190
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)
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
4233class 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
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:
4248  HSub(HValue* context, HValue* left, HValue* right)
4249      : HArithmeticBinaryOperation(context, left, right) {
4250    SetFlag(kCanOverflow);
4251  }
4252};
4253
4254
4255class HMul final : public HArithmeticBinaryOperation {
4256 public:
4257  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4258                           HValue* left, HValue* right);
4259
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.
4274  bool IsCommutative() const override { return !representation().IsTagged(); }
4275
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
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:
4292  HMul(HValue* context, HValue* left, HValue* right)
4293      : HArithmeticBinaryOperation(context, left, right) {
4294    SetFlag(kCanOverflow);
4295  }
4296};
4297
4298
4299class 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
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
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:
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
4330class 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
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
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:
4352  HDiv(HValue* context, HValue* left, HValue* right)
4353      : HArithmeticBinaryOperation(context, left, right) {
4354    SetFlag(kCanBeDivByZero);
4355    SetFlag(kCanOverflow);
4356  }
4357};
4358
4359
4360class 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
4367  Representation observed_input_representation(int index) override {
4368    return RequiredInputRepresentation(index);
4369  }
4370
4371  void InferRepresentation(HInferRepresentationPhase* h_infer) override;
4372
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
4383  bool IsCommutative() const override { return true; }
4384
4385  Operation operation() { return operation_; }
4386
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:
4398  HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
4399      : HArithmeticBinaryOperation(context, left, right), operation_(op) {}
4400
4401  Operation operation_;
4402};
4403
4404
4405class 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
4410  Token::Value op() const { return op_; }
4411
4412  bool IsCommutative() const override { return true; }
4413
4414  HValue* Canonicalize() override;
4415
4416  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
4417
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:
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
4460class 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
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
4478  DECLARE_CONCRETE_INSTRUCTION(Shl)
4479
4480 protected:
4481  bool DataEquals(HValue* other) override { return true; }
4482
4483 private:
4484  HShl(HValue* context, HValue* left, HValue* right)
4485      : HBitwiseBinaryOperation(context, left, right) {}
4486};
4487
4488
4489class 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
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
4503  DECLARE_CONCRETE_INSTRUCTION(Shr)
4504
4505 protected:
4506  bool DataEquals(HValue* other) override { return true; }
4507
4508 private:
4509  HShr(HValue* context, HValue* left, HValue* right)
4510      : HBitwiseBinaryOperation(context, left, right) {}
4511};
4512
4513
4514class 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
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
4528  DECLARE_CONCRETE_INSTRUCTION(Sar)
4529
4530 protected:
4531  bool DataEquals(HValue* other) override { return true; }
4532
4533 private:
4534  HSar(HValue* context, HValue* left, HValue* right)
4535      : HBitwiseBinaryOperation(context, left, right) {}
4536};
4537
4538
4539class HRor final : public HBitwiseBinaryOperation {
4540 public:
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
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
4553  DECLARE_CONCRETE_INSTRUCTION(Ror)
4554
4555 protected:
4556  bool DataEquals(HValue* other) override { return true; }
4557
4558 private:
4559  HRor(HValue* context, HValue* left, HValue* right)
4560      : HBitwiseBinaryOperation(context, left, right) {
4561    ChangeRepresentation(Representation::Integer32());
4562  }
4563};
4564
4565
4566class HOsrEntry final : public HTemplateInstruction<0> {
4567 public:
4568  DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId);
4569
4570  BailoutId ast_id() const { return ast_id_; }
4571
4572  Representation RequiredInputRepresentation(int index) override {
4573    return Representation::None();
4574  }
4575
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
4588class 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
4600  unsigned index() const { return index_; }
4601  ParameterKind kind() const { return kind_; }
4602
4603  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
4604
4605  Representation RequiredInputRepresentation(int index) override {
4606    return Representation::None();
4607  }
4608
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
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
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
4638class 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
4644  Representation RequiredInputRepresentation(int index) override {
4645    return Representation::None();
4646  }
4647
4648  void set_incoming_value(HPhi* value) { incoming_value_ = value; }
4649  HPhi* incoming_value() { return incoming_value_; }
4650  HEnvironment *environment() { return environment_; }
4651  int index() { return index_; }
4652
4653  Representation KnownOptimalRepresentation() override {
4654    if (incoming_value_ == NULL) return Representation::None();
4655    return incoming_value_->KnownOptimalRepresentation();
4656  }
4657
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
4673class HAllocate final : public HTemplateInstruction<3> {
4674 public:
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
4693  HValue* context() const { return OperandAt(0); }
4694  HValue* size() const { return OperandAt(1); }
4695  HValue* allocation_folding_dominator() const { return OperandAt(2); }
4696
4697  Representation RequiredInputRepresentation(int index) override {
4698    if (index == 0) {
4699      return Representation::Tagged();
4700    } else {
4701      return Representation::Integer32();
4702    }
4703  }
4704
4705  Handle<Map> GetMonomorphicJSObjectMap() override {
4706    return known_initial_map_;
4707  }
4708
4709  void set_known_initial_map(Handle<Map> known_initial_map) {
4710    known_initial_map_ = known_initial_map;
4711  }
4712
4713  bool IsNewSpaceAllocation() const {
4714    return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
4715  }
4716
4717  bool IsOldSpaceAllocation() const {
4718    return (flags_ & ALLOCATE_IN_OLD_SPACE) != 0;
4719  }
4720
4721  bool MustAllocateDoubleAligned() const {
4722    return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
4723  }
4724
4725  bool MustPrefillWithFiller() const {
4726    return (flags_ & PREFILL_WITH_FILLER) != 0;
4727  }
4728
4729  void MakePrefillWithFiller() {
4730    flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
4731  }
4732
4733  void MakeDoubleAligned() {
4734    flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
4735  }
4736
4737  void MakeAllocationFoldingDominator() {
4738    flags_ =
4739        static_cast<HAllocate::Flags>(flags_ | ALLOCATION_FOLDING_DOMINATOR);
4740  }
4741
4742  bool IsAllocationFoldingDominator() const {
4743    return (flags_ & ALLOCATION_FOLDING_DOMINATOR) != 0;
4744  }
4745
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
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
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
4813  void UpdateSize(HValue* size) {
4814    SetOperandAt(1, size);
4815  }
4816
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
4827class HStoreCodeEntry final : public HTemplateInstruction<2> {
4828 public:
4829  static HStoreCodeEntry* New(Isolate* isolate, Zone* zone, HValue* context,
4830                              HValue* function, HValue* code) {
4831    return new(zone) HStoreCodeEntry(function, code);
4832  }
4833
4834  Representation RequiredInputRepresentation(int index) override {
4835    return Representation::Tagged();
4836  }
4837
4838  HValue* function() { return OperandAt(0); }
4839  HValue* code_object() { return OperandAt(1); }
4840
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
4851class HInnerAllocatedObject final : public HTemplateInstruction<2> {
4852 public:
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
4859  HValue* base_object() const { return OperandAt(0); }
4860  HValue* offset() const { return OperandAt(1); }
4861
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
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
4883inline 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
4892inline 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
4929inline 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
4943class 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
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
4962  int slot_index() const { return slot_index_; }
4963  Mode mode() const { return mode_; }
4964
4965  bool DeoptimizesOnHole() {
4966    return mode_ == kCheckDeoptimize;
4967  }
4968
4969  bool RequiresHoleCheck() const {
4970    return mode_ != kNoCheck;
4971  }
4972
4973  Representation RequiredInputRepresentation(int index) override {
4974    return Representation::Tagged();
4975  }
4976
4977  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
4978
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:
4988  bool IsDeletable() const override { return !RequiresHoleCheck(); }
4989
4990  int slot_index_;
4991  Mode mode_;
4992};
4993
4994
4995class 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
5011  HValue* context() const { return OperandAt(0); }
5012  HValue* value() const { return OperandAt(1); }
5013  int slot_index() const { return slot_index_; }
5014  Mode mode() const { return mode_; }
5015
5016  bool NeedsWriteBarrier() {
5017    return StoringValueNeedsWriteBarrier(value());
5018  }
5019
5020  bool DeoptimizesOnHole() {
5021    return mode_ == kCheckDeoptimize;
5022  }
5023
5024  bool RequiresHoleCheck() {
5025    return mode_ != kNoCheck;
5026  }
5027
5028  Representation RequiredInputRepresentation(int index) override {
5029    return Representation::Tagged();
5030  }
5031
5032  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
5033
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.
5051class HObjectAccess final {
5052 public:
5053  inline bool IsInobject() const {
5054    return portion() != kBackingStore && portion() != kExternalMemory;
5055  }
5056
5057  inline bool IsExternalMemory() const {
5058    return portion() == kExternalMemory;
5059  }
5060
5061  inline bool IsStringLength() const {
5062    return portion() == kStringLengths;
5063  }
5064
5065  inline bool IsMap() const {
5066    return portion() == kMaps;
5067  }
5068
5069  inline int offset() const {
5070    return OffsetField::decode(value_);
5071  }
5072
5073  inline Representation representation() const {
5074    return Representation::FromKind(RepresentationField::decode(value_));
5075  }
5076
5077  inline Handle<Name> name() const { return name_; }
5078
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.
5085  inline bool existing_inobject_property() const {
5086    return ExistingInobjectPropertyField::decode(value_);
5087  }
5088
5089  inline HObjectAccess WithRepresentation(Representation representation) {
5090    return HObjectAccess(portion(), offset(), representation, name(),
5091                         immutable(), existing_inobject_property());
5092  }
5093
5094  static HObjectAccess ForHeapNumberValue() {
5095    return HObjectAccess(
5096        kDouble, HeapNumber::kValueOffset, Representation::Double());
5097  }
5098
5099  static HObjectAccess ForHeapNumberValueLowestBits() {
5100    return HObjectAccess(kDouble,
5101                         HeapNumber::kValueOffset,
5102                         Representation::Integer32());
5103  }
5104
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
5116  static HObjectAccess ForOddballTypeOf() {
5117    return HObjectAccess(kInobject, Oddball::kTypeOfOffset,
5118                         Representation::HeapObject());
5119  }
5120
5121  static HObjectAccess ForElementsPointer() {
5122    return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
5123  }
5124
5125  static HObjectAccess ForNextFunctionLinkPointer() {
5126    return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
5127  }
5128
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
5139  static HObjectAccess ForAllocationSiteList() {
5140    return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
5141                         Handle<Name>::null(), false, false);
5142  }
5143
5144  static HObjectAccess ForFixedArrayLength() {
5145    return HObjectAccess(
5146        kArrayLengths,
5147        FixedArray::kLengthOffset,
5148        Representation::Smi());
5149  }
5150
5151  static HObjectAccess ForFixedTypedArrayBaseBasePointer() {
5152    return HObjectAccess(kInobject, FixedTypedArrayBase::kBasePointerOffset,
5153                         Representation::Tagged());
5154  }
5155
5156  static HObjectAccess ForFixedTypedArrayBaseExternalPointer() {
5157    return HObjectAccess::ForObservableJSObjectOffset(
5158        FixedTypedArrayBase::kExternalPointerOffset,
5159        Representation::External());
5160  }
5161
5162  static HObjectAccess ForStringHashField() {
5163    return HObjectAccess(kInobject,
5164                         String::kHashFieldOffset,
5165                         Representation::Integer32());
5166  }
5167
5168  static HObjectAccess ForStringLength() {
5169    STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
5170    return HObjectAccess(
5171        kStringLengths,
5172        String::kLengthOffset,
5173        Representation::Smi());
5174  }
5175
5176  static HObjectAccess ForConsStringFirst() {
5177    return HObjectAccess(kInobject, ConsString::kFirstOffset);
5178  }
5179
5180  static HObjectAccess ForConsStringSecond() {
5181    return HObjectAccess(kInobject, ConsString::kSecondOffset);
5182  }
5183
5184  static HObjectAccess ForPropertiesPointer() {
5185    return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
5186  }
5187
5188  static HObjectAccess ForPrototypeOrInitialMap() {
5189    return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
5190  }
5191
5192  static HObjectAccess ForSharedFunctionInfoPointer() {
5193    return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
5194  }
5195
5196  static HObjectAccess ForCodeEntryPointer() {
5197    return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
5198  }
5199
5200  static HObjectAccess ForCodeOffset() {
5201    return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
5202  }
5203
5204  static HObjectAccess ForOptimizedCodeMap() {
5205    return HObjectAccess(kInobject,
5206                         SharedFunctionInfo::kOptimizedCodeMapOffset);
5207  }
5208
5209  static HObjectAccess ForFunctionContextPointer() {
5210    return HObjectAccess(kInobject, JSFunction::kContextOffset);
5211  }
5212
5213  static HObjectAccess ForMap() {
5214    return HObjectAccess(kMaps, JSObject::kMapOffset);
5215  }
5216
5217  static HObjectAccess ForPrototype() {
5218    return HObjectAccess(kMaps, Map::kPrototypeOffset);
5219  }
5220
5221  static HObjectAccess ForMapAsInteger32() {
5222    return HObjectAccess(kMaps, JSObject::kMapOffset,
5223                         Representation::Integer32());
5224  }
5225
5226  static HObjectAccess ForMapInObjectPropertiesOrConstructorFunctionIndex() {
5227    return HObjectAccess(
5228        kInobject, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset,
5229        Representation::UInteger8());
5230  }
5231
5232  static HObjectAccess ForMapInstanceType() {
5233    return HObjectAccess(kInobject,
5234                         Map::kInstanceTypeOffset,
5235                         Representation::UInteger8());
5236  }
5237
5238  static HObjectAccess ForMapInstanceSize() {
5239    return HObjectAccess(kInobject,
5240                         Map::kInstanceSizeOffset,
5241                         Representation::UInteger8());
5242  }
5243
5244  static HObjectAccess ForMapBitField() {
5245    return HObjectAccess(kInobject,
5246                         Map::kBitFieldOffset,
5247                         Representation::UInteger8());
5248  }
5249
5250  static HObjectAccess ForMapBitField2() {
5251    return HObjectAccess(kInobject,
5252                         Map::kBitField2Offset,
5253                         Representation::UInteger8());
5254  }
5255
5256  static HObjectAccess ForMapBitField3() {
5257    return HObjectAccess(kInobject, Map::kBitField3Offset,
5258                         Representation::Integer32());
5259  }
5260
5261  static HObjectAccess ForMapDescriptors() {
5262    return HObjectAccess(kInobject, Map::kDescriptorsOffset);
5263  }
5264
5265  static HObjectAccess ForNameHashField() {
5266    return HObjectAccess(kInobject,
5267                         Name::kHashFieldOffset,
5268                         Representation::Integer32());
5269  }
5270
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
5281  static HObjectAccess ForPropertyCellValue() {
5282    return HObjectAccess(kInobject, PropertyCell::kValueOffset);
5283  }
5284
5285  static HObjectAccess ForPropertyCellDetails() {
5286    return HObjectAccess(kInobject, PropertyCell::kDetailsOffset,
5287                         Representation::Smi());
5288  }
5289
5290  static HObjectAccess ForCellValue() {
5291    return HObjectAccess(kInobject, Cell::kValueOffset);
5292  }
5293
5294  static HObjectAccess ForWeakCellValue() {
5295    return HObjectAccess(kInobject, WeakCell::kValueOffset);
5296  }
5297
5298  static HObjectAccess ForWeakCellNext() {
5299    return HObjectAccess(kInobject, WeakCell::kNextOffset);
5300  }
5301
5302  static HObjectAccess ForAllocationMementoSite() {
5303    return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
5304  }
5305
5306  static HObjectAccess ForCounter() {
5307    return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
5308                         Handle<Name>::null(), false, false);
5309  }
5310
5311  static HObjectAccess ForExternalUInteger8() {
5312    return HObjectAccess(kExternalMemory, 0, Representation::UInteger8(),
5313                         Handle<Name>::null(), false, false);
5314  }
5315
5316  static HObjectAccess ForBoundTargetFunction() {
5317    return HObjectAccess(kInobject,
5318                         JSBoundFunction::kBoundTargetFunctionOffset);
5319  }
5320
5321  static HObjectAccess ForBoundThis() {
5322    return HObjectAccess(kInobject, JSBoundFunction::kBoundThisOffset);
5323  }
5324
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
5364  static HObjectAccess ForJSTypedArrayLength() {
5365    return HObjectAccess::ForObservableJSObjectOffset(
5366        JSTypedArray::kLengthOffset);
5367  }
5368
5369  static HObjectAccess ForJSArrayBufferBackingStore() {
5370    return HObjectAccess::ForObservableJSObjectOffset(
5371        JSArrayBuffer::kBackingStoreOffset, Representation::External());
5372  }
5373
5374  static HObjectAccess ForJSArrayBufferByteLength() {
5375    return HObjectAccess::ForObservableJSObjectOffset(
5376        JSArrayBuffer::kByteLengthOffset, Representation::Tagged());
5377  }
5378
5379  static HObjectAccess ForJSArrayBufferBitField() {
5380    return HObjectAccess::ForObservableJSObjectOffset(
5381        JSArrayBuffer::kBitFieldOffset, Representation::Integer32());
5382  }
5383
5384  static HObjectAccess ForJSArrayBufferBitFieldSlot() {
5385    return HObjectAccess::ForObservableJSObjectOffset(
5386        JSArrayBuffer::kBitFieldSlot, Representation::Smi());
5387  }
5388
5389  static HObjectAccess ForJSArrayBufferViewBuffer() {
5390    return HObjectAccess::ForObservableJSObjectOffset(
5391        JSArrayBufferView::kBufferOffset);
5392  }
5393
5394  static HObjectAccess ForJSArrayBufferViewByteOffset() {
5395    return HObjectAccess::ForObservableJSObjectOffset(
5396        JSArrayBufferView::kByteOffsetOffset);
5397  }
5398
5399  static HObjectAccess ForJSArrayBufferViewByteLength() {
5400    return HObjectAccess::ForObservableJSObjectOffset(
5401        JSArrayBufferView::kByteLengthOffset);
5402  }
5403
5404  static HObjectAccess ForJSGlobalObjectNativeContext() {
5405    return HObjectAccess(kInobject, JSGlobalObject::kNativeContextOffset);
5406  }
5407
5408  static HObjectAccess ForJSRegExpFlags() {
5409    return HObjectAccess(kInobject, JSRegExp::kFlagsOffset);
5410  }
5411
5412  static HObjectAccess ForJSRegExpSource() {
5413    return HObjectAccess(kInobject, JSRegExp::kSourceOffset);
5414  }
5415
5416  static HObjectAccess ForJSCollectionTable() {
5417    return HObjectAccess::ForObservableJSObjectOffset(
5418        JSCollection::kTableOffset);
5419  }
5420
5421  template <typename CollectionType>
5422  static HObjectAccess ForOrderedHashTableNumberOfBuckets() {
5423    return HObjectAccess(kInobject, CollectionType::kNumberOfBucketsOffset,
5424                         Representation::Smi());
5425  }
5426
5427  template <typename CollectionType>
5428  static HObjectAccess ForOrderedHashTableNumberOfElements() {
5429    return HObjectAccess(kInobject, CollectionType::kNumberOfElementsOffset,
5430                         Representation::Smi());
5431  }
5432
5433  template <typename CollectionType>
5434  static HObjectAccess ForOrderedHashTableNumberOfDeletedElements() {
5435    return HObjectAccess(kInobject,
5436                         CollectionType::kNumberOfDeletedElementsOffset,
5437                         Representation::Smi());
5438  }
5439
5440  template <typename CollectionType>
5441  static HObjectAccess ForOrderedHashTableNextTable() {
5442    return HObjectAccess(kInobject, CollectionType::kNextTableOffset);
5443  }
5444
5445  template <typename CollectionType>
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>
5455  static HObjectAccess ForOrderedHashTableDataTableIndex(int index) {
5456    return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
5457                                        (kBucketCount * kPointerSize) +
5458                                        (index * kPointerSize));
5459  }
5460
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
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
5518  inline Portion portion() const {
5519    return PortionField::decode(value_);
5520  }
5521};
5522
5523
5524std::ostream& operator<<(std::ostream& os, const HObjectAccess& access);
5525
5526
5527class 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
5534  HValue* object() const { return OperandAt(0); }
5535  HValue* dependency() const {
5536    DCHECK(HasDependency());
5537    return OperandAt(1);
5538  }
5539  bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
5540  HObjectAccess access() const { return access_; }
5541  Representation field_representation() const {
5542      return access_.representation();
5543  }
5544
5545  const UniqueSet<Map>* maps() const { return maps_; }
5546
5547  bool HasEscapingOperandAt(int index) override { return false; }
5548  bool HasOutOfBoundsAccess(int size) override {
5549    return !access().IsInobject() || access().offset() >= size;
5550  }
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
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
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:
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
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
5641  bool IsDeletable() const override { return true; }
5642
5643  HObjectAccess access_;
5644  const UniqueSet<Map>* maps_;
5645};
5646
5647
5648class HLoadFunctionPrototype final : public HUnaryOperation {
5649 public:
5650  DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);
5651
5652  HValue* function() { return OperandAt(0); }
5653
5654  Representation RequiredInputRepresentation(int index) override {
5655    return Representation::Tagged();
5656  }
5657
5658  DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
5659
5660 protected:
5661  bool DataEquals(HValue* other) override { return true; }
5662
5663 private:
5664  explicit HLoadFunctionPrototype(HValue* function)
5665      : HUnaryOperation(function) {
5666    set_representation(Representation::Tagged());
5667    SetFlag(kUseGVN);
5668    SetDependsOnFlag(kCalls);
5669  }
5670};
5671
5672class 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;
5681  virtual ~ArrayInstructionInterface() { }
5682
5683  static Representation KeyedAccessIndexRequirement(Representation r) {
5684    return r.IsInteger32() || SmiValuesAre32Bits()
5685        ? Representation::Integer32() : Representation::Smi();
5686  }
5687};
5688
5689
5690static const int kDefaultKeyedHeaderOffsetSentinel = -1;
5691
5692enum LoadKeyedHoleMode {
5693  NEVER_RETURN_HOLE,
5694  ALLOW_RETURN_HOLE,
5695  CONVERT_HOLE_TO_UNDEFINED
5696};
5697
5698
5699class 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
5709  bool is_fixed_typed_array() const {
5710    return IsFixedTypedArrayElementsKind(elements_kind());
5711  }
5712  HValue* elements() const { return OperandAt(0); }
5713  HValue* key() const { return OperandAt(1); }
5714  HValue* dependency() const {
5715    DCHECK(HasDependency());
5716    return OperandAt(2);
5717  }
5718  bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
5719  HValue* backing_store_owner() const {
5720    DCHECK(HasBackingStoreOwner());
5721    return OperandAt(3);
5722  }
5723  bool HasBackingStoreOwner() const { return OperandAt(0) != OperandAt(3); }
5724  uint32_t base_offset() const { return BaseOffsetField::decode(bit_field_); }
5725  bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
5726  HValue* GetKey() override { return key(); }
5727  void SetKey(HValue* key) override { SetOperandAt(1, key); }
5728  bool IsDehoisted() const override {
5729    return IsDehoistedField::decode(bit_field_);
5730  }
5731  void SetDehoisted(bool is_dehoisted) override {
5732    bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
5733  }
5734  ElementsKind elements_kind() const override {
5735    return ElementsKindField::decode(bit_field_);
5736  }
5737  LoadKeyedHoleMode hole_mode() const {
5738    return HoleModeField::decode(bit_field_);
5739  }
5740
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
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
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
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.
5886enum 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
5895class 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
5902  DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
5903
5904  bool HasEscapingOperandAt(int index) override { return index == 1; }
5905  bool HasOutOfBoundsAccess(int size) override {
5906    return !access().IsInobject() || access().offset() >= size;
5907  }
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  }
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
5942  HValue* object() const { return OperandAt(0); }
5943  HValue* value() const { return OperandAt(1); }
5944  HValue* transition() const { return OperandAt(2); }
5945
5946  HObjectAccess access() const { return access_; }
5947  HValue* dominator() const { return dominator_; }
5948  bool has_transition() const { return HasTransitionField::decode(bit_field_); }
5949  StoreFieldOrKeyedMode store_mode() const {
5950    return StoreModeField::decode(bit_field_);
5951  }
5952
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
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
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
5981  bool NeedsWriteBarrierForMap() {
5982    return ReceiverObjectNeedsWriteBarrier(object(), transition(),
5983                                           dominator());
5984  }
5985
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
5992  PointersToHereCheck PointersToHereCheckForValue() const {
5993    return PointersToHereCheckForObject(value(), dominator());
5994  }
5995
5996  Representation field_representation() const {
5997    return access_.representation();
5998  }
5999
6000  void UpdateValue(HValue* value) {
6001    SetOperandAt(1, value);
6002  }
6003
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)
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
6042class 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
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
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
6095  bool is_fixed_typed_array() const {
6096    return IsFixedTypedArrayElementsKind(elements_kind());
6097  }
6098
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
6111  HValue* elements() const { return OperandAt(0); }
6112  HValue* key() const { return OperandAt(1); }
6113  HValue* value() const { return OperandAt(2); }
6114  HValue* backing_store_owner() const {
6115    DCHECK(HasBackingStoreOwner());
6116    return OperandAt(3);
6117  }
6118  bool HasBackingStoreOwner() const { return OperandAt(0) != OperandAt(3); }
6119  bool value_is_smi() const { return IsFastSmiElementsKind(elements_kind()); }
6120  StoreFieldOrKeyedMode store_mode() const {
6121    return StoreModeField::decode(bit_field_);
6122  }
6123  ElementsKind elements_kind() const override {
6124    return ElementsKindField::decode(bit_field_);
6125  }
6126  uint32_t base_offset() const { return base_offset_; }
6127  bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
6128  HValue* GetKey() override { return key(); }
6129  void SetKey(HValue* key) override { SetOperandAt(1, key); }
6130  bool IsDehoisted() const override {
6131    return IsDehoistedField::decode(bit_field_);
6132  }
6133  void SetDehoisted(bool is_dehoisted) override {
6134    bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
6135  }
6136  bool IsUninitialized() { return IsUninitializedField::decode(bit_field_); }
6137  void SetUninitialized(bool is_uninitialized) {
6138    bit_field_ = IsUninitializedField::update(bit_field_, is_uninitialized);
6139  }
6140
6141  bool IsConstantHoleStore() {
6142    return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
6143  }
6144
6145  bool HandleSideEffectDominator(GVNFlag side_effect,
6146                                 HValue* dominator) override {
6147    DCHECK(side_effect == kNewSpacePromotion);
6148    dominator_ = dominator;
6149    return false;
6150  }
6151
6152  HValue* dominator() const { return dominator_; }
6153
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
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
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
6224class HTransitionElementsKind final : public HTemplateInstruction<2> {
6225 public:
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
6234  Representation RequiredInputRepresentation(int index) override {
6235    return Representation::Tagged();
6236  }
6237
6238  HValue* object() const { return OperandAt(0); }
6239  HValue* context() const { return OperandAt(1); }
6240  Unique<Map> original_map() const { return original_map_; }
6241  Unique<Map> transitioned_map() const { return transitioned_map_; }
6242  ElementsKind from_kind() const {
6243    return FromElementsKindField::decode(bit_field_);
6244  }
6245  ElementsKind to_kind() const {
6246    return ToElementsKindField::decode(bit_field_);
6247  }
6248  bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }
6249
6250  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6251
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
6261  int RedefinedOperandIndex() override { return 0; }
6262
6263 private:
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
6294class 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
6302  StringAddFlags flags() const { return flags_; }
6303  PretenureFlag pretenure_flag() const { return pretenure_flag_; }
6304
6305  Representation RequiredInputRepresentation(int index) override {
6306    return Representation::Tagged();
6307  }
6308
6309  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6310
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:
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
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
6353class HStringCharCodeAt final : public HTemplateInstruction<3> {
6354 public:
6355  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HStringCharCodeAt,
6356                                              HValue*,
6357                                              HValue*);
6358
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
6366  HValue* context() const { return OperandAt(0); }
6367  HValue* string() const { return OperandAt(1); }
6368  HValue* index() const { return OperandAt(2); }
6369
6370  DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
6371
6372 protected:
6373  bool DataEquals(HValue* other) override { return true; }
6374
6375  Range* InferRange(Zone* zone) override {
6376    return new(zone) Range(0, String::kMaxUtf16CodeUnit);
6377  }
6378
6379 private:
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.
6392  bool IsDeletable() const override { return true; }
6393};
6394
6395
6396class HStringCharFromCode final : public HTemplateInstruction<2> {
6397 public:
6398  static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
6399                           HValue* char_code);
6400
6401  Representation RequiredInputRepresentation(int index) override {
6402    return index == 0
6403        ? Representation::Tagged()
6404        : Representation::Integer32();
6405  }
6406
6407  HValue* context() const { return OperandAt(0); }
6408  HValue* value() const { return OperandAt(1); }
6409
6410  bool DataEquals(HValue* other) override { return true; }
6411
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
6424  bool IsDeletable() const override {
6425    return !value()->ToNumberCanBeObserved();
6426  }
6427};
6428
6429
6430class HTypeof final : public HTemplateInstruction<2> {
6431 public:
6432  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HTypeof, HValue*);
6433
6434  HValue* context() const { return OperandAt(0); }
6435  HValue* value() const { return OperandAt(1); }
6436
6437  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6438
6439  Representation RequiredInputRepresentation(int index) override {
6440    return Representation::Tagged();
6441  }
6442
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
6452  bool IsDeletable() const override { return true; }
6453};
6454
6455
6456class HTrapAllocationMemento final : public HTemplateInstruction<1> {
6457 public:
6458  DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
6459
6460  Representation RequiredInputRepresentation(int index) override {
6461    return Representation::Tagged();
6462  }
6463
6464  HValue* object() { return OperandAt(0); }
6465
6466  DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
6467
6468 private:
6469  explicit HTrapAllocationMemento(HValue* obj) {
6470    SetOperandAt(0, obj);
6471  }
6472};
6473
6474
6475class HMaybeGrowElements final : public HTemplateInstruction<5> {
6476 public:
6477  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(HMaybeGrowElements, HValue*,
6478                                              HValue*, HValue*, HValue*, bool,
6479                                              ElementsKind);
6480
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
6489  HValue* context() const { return OperandAt(0); }
6490  HValue* object() const { return OperandAt(1); }
6491  HValue* elements() const { return OperandAt(2); }
6492  HValue* key() const { return OperandAt(3); }
6493  HValue* current_capacity() const { return OperandAt(4); }
6494
6495  bool is_js_array() const { return is_js_array_; }
6496  ElementsKind kind() const { return kind_; }
6497
6498  DECLARE_CONCRETE_INSTRUCTION(MaybeGrowElements)
6499
6500 protected:
6501  bool DataEquals(HValue* other) override { return true; }
6502
6503 private:
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
6527class 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
6533  Representation RequiredInputRepresentation(int index) override {
6534    return (index == 0) ? Representation::Tagged()
6535                        : Representation::Integer32();
6536  }
6537
6538  String::Encoding encoding() const { return encoding_; }
6539  HValue* string() const { return OperandAt(0); }
6540  HValue* index() const { return OperandAt(1); }
6541
6542  DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)
6543
6544 protected:
6545  bool DataEquals(HValue* other) override {
6546    return encoding() == HSeqStringGetChar::cast(other)->encoding();
6547  }
6548
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:
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
6569  bool IsDeletable() const override { return true; }
6570
6571  String::Encoding encoding_;
6572};
6573
6574
6575class HSeqStringSetChar final : public HTemplateInstruction<4> {
6576 public:
6577  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(
6578      HSeqStringSetChar, String::Encoding,
6579      HValue*, HValue*, HValue*);
6580
6581  String::Encoding encoding() { return encoding_; }
6582  HValue* context() { return OperandAt(0); }
6583  HValue* string() { return OperandAt(1); }
6584  HValue* index() { return OperandAt(2); }
6585  HValue* value() { return OperandAt(3); }
6586
6587  Representation RequiredInputRepresentation(int index) override {
6588    return (index <= 1) ? Representation::Tagged()
6589                        : Representation::Integer32();
6590  }
6591
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
6612class HCheckMapValue final : public HTemplateInstruction<2> {
6613 public:
6614  DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);
6615
6616  Representation RequiredInputRepresentation(int index) override {
6617    return Representation::Tagged();
6618  }
6619
6620  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6621
6622  HType CalculateInferredType() override {
6623    if (value()->type().IsHeapObject()) return value()->type();
6624    return HType::HeapObject();
6625  }
6626
6627  HValue* value() const { return OperandAt(0); }
6628  HValue* map() const { return OperandAt(1); }
6629
6630  HValue* Canonicalize() override;
6631
6632  DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
6633
6634 protected:
6635  int RedefinedOperandIndex() override { return 0; }
6636
6637  bool DataEquals(HValue* other) override { return true; }
6638
6639 private:
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
6652class HForInPrepareMap final : public HTemplateInstruction<2> {
6653 public:
6654  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HForInPrepareMap, HValue*);
6655
6656  Representation RequiredInputRepresentation(int index) override {
6657    return Representation::Tagged();
6658  }
6659
6660  HValue* context() const { return OperandAt(0); }
6661  HValue* enumerable() const { return OperandAt(1); }
6662
6663  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6664
6665  HType CalculateInferredType() override { return HType::Tagged(); }
6666
6667  DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
6668
6669 private:
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
6680class HForInCacheArray final : public HTemplateInstruction<2> {
6681 public:
6682  DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
6683
6684  Representation RequiredInputRepresentation(int index) override {
6685    return Representation::Tagged();
6686  }
6687
6688  HValue* enumerable() const { return OperandAt(0); }
6689  HValue* map() const { return OperandAt(1); }
6690  int idx() const { return idx_; }
6691
6692  HForInCacheArray* index_cache() {
6693    return index_cache_;
6694  }
6695
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
6702  HType CalculateInferredType() override { return HType::Tagged(); }
6703
6704  DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
6705
6706 private:
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
6720class HLoadFieldByIndex final : public HTemplateInstruction<2> {
6721 public:
6722  DECLARE_INSTRUCTION_FACTORY_P2(HLoadFieldByIndex, HValue*, HValue*);
6723
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
6732  Representation RequiredInputRepresentation(int index) override {
6733    if (index == 1) {
6734      return Representation::Smi();
6735    } else {
6736      return Representation::Tagged();
6737    }
6738  }
6739
6740  HValue* object() const { return OperandAt(0); }
6741  HValue* index() const { return OperandAt(1); }
6742
6743  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
6744
6745  HType CalculateInferredType() override { return HType::Tagged(); }
6746
6747  DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
6748
6749 private:
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