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