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