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