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