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