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