• 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 "small-pointer-list.h"
37 #include "string-stream.h"
38 #include "v8conversions.h"
39 #include "v8utils.h"
40 #include "zone.h"
41 
42 namespace v8 {
43 namespace internal {
44 
45 // Forward declarations.
46 class HBasicBlock;
47 class HEnvironment;
48 class HInstruction;
49 class HLoopInformation;
50 class HValue;
51 class LInstruction;
52 class LChunkBuilder;
53 
54 
55 #define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V)  \
56   V(BitwiseBinaryOperation)                    \
57   V(ControlInstruction)                        \
58   V(Instruction)                               \
59 
60 
61 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)  \
62   V(AbnormalExit)                              \
63   V(AccessArgumentsAt)                         \
64   V(Add)                                       \
65   V(AllocateObject)                            \
66   V(ApplyArguments)                            \
67   V(ArgumentsElements)                         \
68   V(ArgumentsLength)                           \
69   V(ArgumentsObject)                           \
70   V(ArrayLiteral)                              \
71   V(Bitwise)                                   \
72   V(BitNot)                                    \
73   V(BlockEntry)                                \
74   V(BoundsCheck)                               \
75   V(Branch)                                    \
76   V(CallConstantFunction)                      \
77   V(CallFunction)                              \
78   V(CallGlobal)                                \
79   V(CallKeyed)                                 \
80   V(CallKnownGlobal)                           \
81   V(CallNamed)                                 \
82   V(CallNew)                                   \
83   V(CallRuntime)                               \
84   V(CallStub)                                  \
85   V(Change)                                    \
86   V(CheckFunction)                             \
87   V(CheckInstanceType)                         \
88   V(CheckMap)                                  \
89   V(CheckNonSmi)                               \
90   V(CheckPrototypeMaps)                        \
91   V(CheckSmi)                                  \
92   V(ClampToUint8)                              \
93   V(ClassOfTestAndBranch)                      \
94   V(CompareIDAndBranch)                        \
95   V(CompareGeneric)                            \
96   V(CompareObjectEqAndBranch)                  \
97   V(CompareMap)                                \
98   V(CompareConstantEqAndBranch)                \
99   V(Constant)                                  \
100   V(Context)                                   \
101   V(DeclareGlobals)                            \
102   V(DeleteProperty)                            \
103   V(Deoptimize)                                \
104   V(Div)                                       \
105   V(ElementsKind)                              \
106   V(EnterInlined)                              \
107   V(FastLiteral)                               \
108   V(FixedArrayBaseLength)                      \
109   V(ForceRepresentation)                       \
110   V(FunctionLiteral)                           \
111   V(GetCachedArrayIndex)                       \
112   V(GlobalObject)                              \
113   V(GlobalReceiver)                            \
114   V(Goto)                                      \
115   V(HasCachedArrayIndexAndBranch)              \
116   V(HasInstanceTypeAndBranch)                  \
117   V(In)                                        \
118   V(InstanceOf)                                \
119   V(InstanceOfKnownGlobal)                     \
120   V(InvokeFunction)                            \
121   V(IsConstructCallAndBranch)                  \
122   V(IsNilAndBranch)                            \
123   V(IsObjectAndBranch)                         \
124   V(IsStringAndBranch)                         \
125   V(IsSmiAndBranch)                            \
126   V(IsUndetectableAndBranch)                   \
127   V(StringCompareAndBranch)                    \
128   V(JSArrayLength)                             \
129   V(LeaveInlined)                              \
130   V(LoadContextSlot)                           \
131   V(LoadElements)                              \
132   V(LoadExternalArrayPointer)                  \
133   V(LoadFunctionPrototype)                     \
134   V(LoadGlobalCell)                            \
135   V(LoadGlobalGeneric)                         \
136   V(LoadKeyedFastDoubleElement)                \
137   V(LoadKeyedFastElement)                      \
138   V(LoadKeyedGeneric)                          \
139   V(LoadKeyedSpecializedArrayElement)          \
140   V(LoadNamedField)                            \
141   V(LoadNamedFieldPolymorphic)                 \
142   V(LoadNamedGeneric)                          \
143   V(Mod)                                       \
144   V(Mul)                                       \
145   V(ObjectLiteral)                             \
146   V(OsrEntry)                                  \
147   V(OuterContext)                              \
148   V(Parameter)                                 \
149   V(Power)                                     \
150   V(PushArgument)                              \
151   V(Random)                                    \
152   V(RegExpLiteral)                             \
153   V(Return)                                    \
154   V(Sar)                                       \
155   V(Shl)                                       \
156   V(Shr)                                       \
157   V(Simulate)                                  \
158   V(SoftDeoptimize)                            \
159   V(StackCheck)                                \
160   V(StoreContextSlot)                          \
161   V(StoreGlobalCell)                           \
162   V(StoreGlobalGeneric)                        \
163   V(StoreKeyedFastDoubleElement)               \
164   V(StoreKeyedFastElement)                     \
165   V(StoreKeyedGeneric)                         \
166   V(StoreKeyedSpecializedArrayElement)         \
167   V(StoreNamedField)                           \
168   V(StoreNamedGeneric)                         \
169   V(StringAdd)                                 \
170   V(StringCharCodeAt)                          \
171   V(StringCharFromCode)                        \
172   V(StringLength)                              \
173   V(Sub)                                       \
174   V(ThisFunction)                              \
175   V(Throw)                                     \
176   V(ToFastProperties)                          \
177   V(TransitionElementsKind)                    \
178   V(Typeof)                                    \
179   V(TypeofIsAndBranch)                         \
180   V(UnaryMathOperation)                        \
181   V(UnknownOSRValue)                           \
182   V(UseConst)                                  \
183   V(ValueOf)                                   \
184   V(ForInPrepareMap)                           \
185   V(ForInCacheArray)                           \
186   V(CheckMapValue)                             \
187   V(LoadFieldByIndex)                          \
188   V(DateField)                                 \
189   V(WrapReceiver)
190 
191 #define GVN_FLAG_LIST(V)                       \
192   V(Calls)                                     \
193   V(InobjectFields)                            \
194   V(BackingStoreFields)                        \
195   V(ElementsKind)                              \
196   V(ElementsPointer)                           \
197   V(ArrayElements)                             \
198   V(DoubleArrayElements)                       \
199   V(SpecializedArrayElements)                  \
200   V(GlobalVars)                                \
201   V(Maps)                                      \
202   V(ArrayLengths)                              \
203   V(ContextSlots)                              \
204   V(OsrEntries)
205 
206 #define DECLARE_ABSTRACT_INSTRUCTION(type)          \
207   virtual bool Is##type() const { return true; }    \
208   static H##type* cast(HValue* value) {             \
209     ASSERT(value->Is##type());                      \
210     return reinterpret_cast<H##type*>(value);       \
211   }
212 
213 
214 #define DECLARE_CONCRETE_INSTRUCTION(type)                        \
215   virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
216   static H##type* cast(HValue* value) {                           \
217     ASSERT(value->Is##type());                                    \
218     return reinterpret_cast<H##type*>(value);                     \
219   }                                                               \
220   virtual Opcode opcode() const { return HValue::k##type; }
221 
222 
223 class Range: public ZoneObject {
224  public:
Range()225   Range()
226       : lower_(kMinInt),
227         upper_(kMaxInt),
228         next_(NULL),
229         can_be_minus_zero_(false) { }
230 
Range(int32_t lower,int32_t upper)231   Range(int32_t lower, int32_t upper)
232       : lower_(lower),
233         upper_(upper),
234         next_(NULL),
235         can_be_minus_zero_(false) { }
236 
upper()237   int32_t upper() const { return upper_; }
lower()238   int32_t lower() const { return lower_; }
next()239   Range* next() const { return next_; }
CopyClearLower(Zone * zone)240   Range* CopyClearLower(Zone* zone) const {
241     return new(zone) Range(kMinInt, upper_);
242   }
CopyClearUpper(Zone * zone)243   Range* CopyClearUpper(Zone* zone) const {
244     return new(zone) Range(lower_, kMaxInt);
245   }
Copy(Zone * zone)246   Range* Copy(Zone* zone) const {
247     Range* result = new(zone) Range(lower_, upper_);
248     result->set_can_be_minus_zero(CanBeMinusZero());
249     return result;
250   }
251   int32_t Mask() const;
set_can_be_minus_zero(bool b)252   void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
CanBeMinusZero()253   bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
CanBeZero()254   bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
CanBeNegative()255   bool CanBeNegative() const { return lower_ < 0; }
Includes(int value)256   bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
IsMostGeneric()257   bool IsMostGeneric() const {
258     return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
259   }
IsInSmiRange()260   bool IsInSmiRange() const {
261     return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
262   }
263   void KeepOrder();
264 #ifdef DEBUG
265   void Verify() const;
266 #endif
267 
StackUpon(Range * other)268   void StackUpon(Range* other) {
269     Intersect(other);
270     next_ = other;
271   }
272 
273   void Intersect(Range* other);
274   void Union(Range* other);
275 
276   void AddConstant(int32_t value);
277   void Sar(int32_t value);
278   void Shl(int32_t value);
279   bool AddAndCheckOverflow(Range* other);
280   bool SubAndCheckOverflow(Range* other);
281   bool MulAndCheckOverflow(Range* other);
282 
283  private:
284   int32_t lower_;
285   int32_t upper_;
286   Range* next_;
287   bool can_be_minus_zero_;
288 };
289 
290 
291 class Representation {
292  public:
293   enum Kind {
294     kNone,
295     kTagged,
296     kDouble,
297     kInteger32,
298     kExternal,
299     kNumRepresentations
300   };
301 
Representation()302   Representation() : kind_(kNone) { }
303 
None()304   static Representation None() { return Representation(kNone); }
Tagged()305   static Representation Tagged() { return Representation(kTagged); }
Integer32()306   static Representation Integer32() { return Representation(kInteger32); }
Double()307   static Representation Double() { return Representation(kDouble); }
External()308   static Representation External() { return Representation(kExternal); }
309 
Equals(const Representation & other)310   bool Equals(const Representation& other) {
311     return kind_ == other.kind_;
312   }
313 
kind()314   Kind kind() const { return static_cast<Kind>(kind_); }
IsNone()315   bool IsNone() const { return kind_ == kNone; }
IsTagged()316   bool IsTagged() const { return kind_ == kTagged; }
IsInteger32()317   bool IsInteger32() const { return kind_ == kInteger32; }
IsDouble()318   bool IsDouble() const { return kind_ == kDouble; }
IsExternal()319   bool IsExternal() const { return kind_ == kExternal; }
IsSpecialization()320   bool IsSpecialization() const {
321     return kind_ == kInteger32 || kind_ == kDouble;
322   }
323   const char* Mnemonic() const;
324 
325  private:
Representation(Kind k)326   explicit Representation(Kind k) : kind_(k) { }
327 
328   // Make sure kind fits in int8.
329   STATIC_ASSERT(kNumRepresentations <= (1 << kBitsPerByte));
330 
331   int8_t kind_;
332 };
333 
334 
335 class HType {
336  public:
HType()337   HType() : type_(kUninitialized) { }
338 
Tagged()339   static HType Tagged() { return HType(kTagged); }
TaggedPrimitive()340   static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
TaggedNumber()341   static HType TaggedNumber() { return HType(kTaggedNumber); }
Smi()342   static HType Smi() { return HType(kSmi); }
HeapNumber()343   static HType HeapNumber() { return HType(kHeapNumber); }
String()344   static HType String() { return HType(kString); }
Boolean()345   static HType Boolean() { return HType(kBoolean); }
NonPrimitive()346   static HType NonPrimitive() { return HType(kNonPrimitive); }
JSArray()347   static HType JSArray() { return HType(kJSArray); }
JSObject()348   static HType JSObject() { return HType(kJSObject); }
Uninitialized()349   static HType Uninitialized() { return HType(kUninitialized); }
350 
351   // Return the weakest (least precise) common type.
Combine(HType other)352   HType Combine(HType other) {
353     return HType(static_cast<Type>(type_ & other.type_));
354   }
355 
Equals(const HType & other)356   bool Equals(const HType& other) {
357     return type_ == other.type_;
358   }
359 
IsSubtypeOf(const HType & other)360   bool IsSubtypeOf(const HType& other) {
361     return Combine(other).Equals(other);
362   }
363 
IsTagged()364   bool IsTagged() {
365     ASSERT(type_ != kUninitialized);
366     return ((type_ & kTagged) == kTagged);
367   }
368 
IsTaggedPrimitive()369   bool IsTaggedPrimitive() {
370     ASSERT(type_ != kUninitialized);
371     return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
372   }
373 
IsTaggedNumber()374   bool IsTaggedNumber() {
375     ASSERT(type_ != kUninitialized);
376     return ((type_ & kTaggedNumber) == kTaggedNumber);
377   }
378 
IsSmi()379   bool IsSmi() {
380     ASSERT(type_ != kUninitialized);
381     return ((type_ & kSmi) == kSmi);
382   }
383 
IsHeapNumber()384   bool IsHeapNumber() {
385     ASSERT(type_ != kUninitialized);
386     return ((type_ & kHeapNumber) == kHeapNumber);
387   }
388 
IsString()389   bool IsString() {
390     ASSERT(type_ != kUninitialized);
391     return ((type_ & kString) == kString);
392   }
393 
IsBoolean()394   bool IsBoolean() {
395     ASSERT(type_ != kUninitialized);
396     return ((type_ & kBoolean) == kBoolean);
397   }
398 
IsNonPrimitive()399   bool IsNonPrimitive() {
400     ASSERT(type_ != kUninitialized);
401     return ((type_ & kNonPrimitive) == kNonPrimitive);
402   }
403 
IsJSArray()404   bool IsJSArray() {
405     ASSERT(type_ != kUninitialized);
406     return ((type_ & kJSArray) == kJSArray);
407   }
408 
IsJSObject()409   bool IsJSObject() {
410     ASSERT(type_ != kUninitialized);
411     return ((type_ & kJSObject) == kJSObject);
412   }
413 
IsUninitialized()414   bool IsUninitialized() {
415     return type_ == kUninitialized;
416   }
417 
IsHeapObject()418   bool IsHeapObject() {
419     ASSERT(type_ != kUninitialized);
420     return IsHeapNumber() || IsString() || IsNonPrimitive();
421   }
422 
423   static HType TypeFromValue(Handle<Object> value);
424 
425   const char* ToString();
426 
427  private:
428   enum Type {
429     kTagged = 0x1,           // 0000 0000 0000 0001
430     kTaggedPrimitive = 0x5,  // 0000 0000 0000 0101
431     kTaggedNumber = 0xd,     // 0000 0000 0000 1101
432     kSmi = 0x1d,             // 0000 0000 0001 1101
433     kHeapNumber = 0x2d,      // 0000 0000 0010 1101
434     kString = 0x45,          // 0000 0000 0100 0101
435     kBoolean = 0x85,         // 0000 0000 1000 0101
436     kNonPrimitive = 0x101,   // 0000 0001 0000 0001
437     kJSObject = 0x301,       // 0000 0011 0000 0001
438     kJSArray = 0x701,        // 0000 0111 0000 0001
439     kUninitialized = 0x1fff  // 0001 1111 1111 1111
440   };
441 
442   // Make sure type fits in int16.
443   STATIC_ASSERT(kUninitialized < (1 << (2 * kBitsPerByte)));
444 
HType(Type t)445   explicit HType(Type t) : type_(t) { }
446 
447   int16_t type_;
448 };
449 
450 
451 class HUseListNode: public ZoneObject {
452  public:
HUseListNode(HValue * value,int index,HUseListNode * tail)453   HUseListNode(HValue* value, int index, HUseListNode* tail)
454       : tail_(tail), value_(value), index_(index) {
455   }
456 
457   HUseListNode* tail();
value()458   HValue* value() const { return value_; }
index()459   int index() const { return index_; }
460 
set_tail(HUseListNode * list)461   void set_tail(HUseListNode* list) { tail_ = list; }
462 
463 #ifdef DEBUG
Zap()464   void Zap() {
465     tail_ = reinterpret_cast<HUseListNode*>(1);
466     value_ = NULL;
467     index_ = -1;
468   }
469 #endif
470 
471  private:
472   HUseListNode* tail_;
473   HValue* value_;
474   int index_;
475 };
476 
477 
478 // We reuse use list nodes behind the scenes as uses are added and deleted.
479 // This class is the safe way to iterate uses while deleting them.
480 class HUseIterator BASE_EMBEDDED {
481  public:
Done()482   bool Done() { return current_ == NULL; }
483   void Advance();
484 
value()485   HValue* value() {
486     ASSERT(!Done());
487     return value_;
488   }
489 
index()490   int index() {
491     ASSERT(!Done());
492     return index_;
493   }
494 
495  private:
496   explicit HUseIterator(HUseListNode* head);
497 
498   HUseListNode* current_;
499   HUseListNode* next_;
500   HValue* value_;
501   int index_;
502 
503   friend class HValue;
504 };
505 
506 
507 // There must be one corresponding kDepends flag for every kChanges flag and
508 // the order of the kChanges flags must be exactly the same as of the kDepends
509 // flags.
510 enum GVNFlag {
511   // Declare global value numbering flags.
512 #define DECLARE_FLAG(type) kChanges##type, kDependsOn##type,
513   GVN_FLAG_LIST(DECLARE_FLAG)
514 #undef DECLARE_FLAG
515   kAfterLastFlag,
516   kLastFlag = kAfterLastFlag - 1
517 };
518 
519 typedef EnumSet<GVNFlag> GVNFlagSet;
520 
521 
522 class HValue: public ZoneObject {
523  public:
524   static const int kNoNumber = -1;
525 
526   enum Flag {
527     kFlexibleRepresentation,
528     // Participate in Global Value Numbering, i.e. elimination of
529     // unnecessary recomputations. If an instruction sets this flag, it must
530     // implement DataEquals(), which will be used to determine if other
531     // occurrences of the instruction are indeed the same.
532     kUseGVN,
533     kCanOverflow,
534     kBailoutOnMinusZero,
535     kCanBeDivByZero,
536     kDeoptimizeOnUndefined,
537     kIsArguments,
538     kTruncatingToInt32,
539     kIsDead,
540     kLastFlag = kIsDead
541   };
542 
543   STATIC_ASSERT(kLastFlag < kBitsPerInt);
544 
545   static const int kChangesToDependsFlagsLeftShift = 1;
546 
ConvertChangesToDependsFlags(GVNFlagSet flags)547   static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags) {
548     return GVNFlagSet(flags.ToIntegral() << kChangesToDependsFlagsLeftShift);
549   }
550 
cast(HValue * value)551   static HValue* cast(HValue* value) { return value; }
552 
553   enum Opcode {
554     // Declare a unique enum value for each hydrogen instruction.
555   #define DECLARE_OPCODE(type) k##type,
556     HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
557     kPhi
558   #undef DECLARE_OPCODE
559   };
560   virtual Opcode opcode() const = 0;
561 
562   // Declare a non-virtual predicates for each concrete HInstruction or HValue.
563   #define DECLARE_PREDICATE(type) \
564     bool Is##type() const { return opcode() == k##type; }
HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)565     HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
566   #undef DECLARE_PREDICATE
567     bool IsPhi() const { return opcode() == kPhi; }
568 
569   // Declare virtual predicates for abstract HInstruction or HValue
570   #define DECLARE_PREDICATE(type) \
571     virtual bool Is##type() const { return false; }
572     HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
573   #undef DECLARE_PREDICATE
574 
HValue()575   HValue() : block_(NULL),
576              id_(kNoNumber),
577              type_(HType::Tagged()),
578              use_list_(NULL),
579              range_(NULL),
580              flags_(0) {}
~HValue()581   virtual ~HValue() {}
582 
block()583   HBasicBlock* block() const { return block_; }
584   void SetBlock(HBasicBlock* block);
585   int LoopWeight() const;
586 
id()587   int id() const { return id_; }
set_id(int id)588   void set_id(int id) { id_ = id; }
589 
uses()590   HUseIterator uses() const { return HUseIterator(use_list_); }
591 
EmitAtUses()592   virtual bool EmitAtUses() { return false; }
representation()593   Representation representation() const { return representation_; }
ChangeRepresentation(Representation r)594   void ChangeRepresentation(Representation r) {
595     // Representation was already set and is allowed to be changed.
596     ASSERT(!r.IsNone());
597     ASSERT(CheckFlag(kFlexibleRepresentation));
598     RepresentationChanged(r);
599     representation_ = r;
600   }
601   void AssumeRepresentation(Representation r);
602 
IsConvertibleToInteger()603   virtual bool IsConvertibleToInteger() const { return true; }
604 
type()605   HType type() const { return type_; }
set_type(HType new_type)606   void set_type(HType new_type) {
607     ASSERT(new_type.IsSubtypeOf(type_));
608     type_ = new_type;
609   }
610 
611   // An operation needs to override this function iff:
612   //   1) it can produce an int32 output.
613   //   2) the true value of its output can potentially be minus zero.
614   // The implementation must set a flag so that it bails out in the case where
615   // it would otherwise output what should be a minus zero as an int32 zero.
616   // If the operation also exists in a form that takes int32 and outputs int32
617   // then the operation should return its input value so that we can propagate
618   // back.  There are three operations that need to propagate back to more than
619   // one input.  They are phi and binary div and mul.  They always return NULL
620   // and expect the caller to take care of things.
EnsureAndPropagateNotMinusZero(BitVector * visited)621   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
622     visited->Add(id());
623     return NULL;
624   }
625 
626   bool IsDefinedAfter(HBasicBlock* other) const;
627 
628   // Operands.
629   virtual int OperandCount() = 0;
630   virtual HValue* OperandAt(int index) = 0;
631   void SetOperandAt(int index, HValue* value);
632 
633   void DeleteAndReplaceWith(HValue* other);
634   void ReplaceAllUsesWith(HValue* other);
HasNoUses()635   bool HasNoUses() const { return use_list_ == NULL; }
HasMultipleUses()636   bool HasMultipleUses() const {
637     return use_list_ != NULL && use_list_->tail() != NULL;
638   }
639   int UseCount() const;
640 
641   // Mark this HValue as dead and to be removed from other HValues' use lists.
642   void Kill();
643 
flags()644   int flags() const { return flags_; }
SetFlag(Flag f)645   void SetFlag(Flag f) { flags_ |= (1 << f); }
ClearFlag(Flag f)646   void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
CheckFlag(Flag f)647   bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
648 
649   // Returns true if the flag specified is set for all uses, false otherwise.
650   bool CheckUsesForFlag(Flag f);
651 
gvn_flags()652   GVNFlagSet gvn_flags() const { return gvn_flags_; }
SetGVNFlag(GVNFlag f)653   void SetGVNFlag(GVNFlag f) { gvn_flags_.Add(f); }
ClearGVNFlag(GVNFlag f)654   void ClearGVNFlag(GVNFlag f) { gvn_flags_.Remove(f); }
CheckGVNFlag(GVNFlag f)655   bool CheckGVNFlag(GVNFlag f) const { return gvn_flags_.Contains(f); }
SetAllSideEffects()656   void SetAllSideEffects() { gvn_flags_.Add(AllSideEffectsFlagSet()); }
ClearAllSideEffects()657   void ClearAllSideEffects() {
658     gvn_flags_.Remove(AllSideEffectsFlagSet());
659   }
HasSideEffects()660   bool HasSideEffects() const {
661     return gvn_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
662   }
HasObservableSideEffects()663   bool HasObservableSideEffects() const {
664     return gvn_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
665   }
666 
DependsOnFlags()667   GVNFlagSet DependsOnFlags() const {
668     GVNFlagSet result = gvn_flags_;
669     result.Intersect(AllDependsOnFlagSet());
670     return result;
671   }
672 
SideEffectFlags()673   GVNFlagSet SideEffectFlags() const {
674     GVNFlagSet result = gvn_flags_;
675     result.Intersect(AllSideEffectsFlagSet());
676     return result;
677   }
678 
ChangesFlags()679   GVNFlagSet ChangesFlags() const {
680     GVNFlagSet result = gvn_flags_;
681     result.Intersect(AllChangesFlagSet());
682     return result;
683   }
684 
ObservableChangesFlags()685   GVNFlagSet ObservableChangesFlags() const {
686     GVNFlagSet result = gvn_flags_;
687     result.Intersect(AllChangesFlagSet());
688     result.Intersect(AllObservableSideEffectsFlagSet());
689     return result;
690   }
691 
range()692   Range* range() const { return range_; }
HasRange()693   bool HasRange() const { return range_ != NULL; }
694   void AddNewRange(Range* r, Zone* zone);
695   void RemoveLastAddedRange();
696   void ComputeInitialRange(Zone* zone);
697 
698   // Representation helpers.
699   virtual Representation RequiredInputRepresentation(int index) = 0;
700 
InferredRepresentation()701   virtual Representation InferredRepresentation() {
702     return representation();
703   }
704 
705   // This gives the instruction an opportunity to replace itself with an
706   // instruction that does the same in some better way.  To replace an
707   // instruction with a new one, first add the new instruction to the graph,
708   // then return it.  Return NULL to have the instruction deleted.
Canonicalize()709   virtual HValue* Canonicalize() { return this; }
710 
711   bool Equals(HValue* other);
712   virtual intptr_t Hashcode();
713 
714   // Printing support.
715   virtual void PrintTo(StringStream* stream) = 0;
716   void PrintNameTo(StringStream* stream);
717   void PrintTypeTo(StringStream* stream);
718   void PrintRangeTo(StringStream* stream);
719   void PrintChangesTo(StringStream* stream);
720 
721   const char* Mnemonic() const;
722 
723   // Updated the inferred type of this instruction and returns true if
724   // it has changed.
725   bool UpdateInferredType();
726 
727   virtual HType CalculateInferredType();
728 
729 #ifdef DEBUG
730   virtual void Verify() = 0;
731 #endif
732 
733  protected:
734   // This function must be overridden for instructions with flag kUseGVN, to
735   // compare the non-Operand parts of the instruction.
DataEquals(HValue * other)736   virtual bool DataEquals(HValue* other) {
737     UNREACHABLE();
738     return false;
739   }
RepresentationChanged(Representation to)740   virtual void RepresentationChanged(Representation to) { }
741   virtual Range* InferRange(Zone* zone);
742   virtual void DeleteFromGraph() = 0;
743   virtual void InternalSetOperandAt(int index, HValue* value) = 0;
clear_block()744   void clear_block() {
745     ASSERT(block_ != NULL);
746     block_ = NULL;
747   }
748 
set_representation(Representation r)749   void set_representation(Representation r) {
750     // Representation is set-once.
751     ASSERT(representation_.IsNone() && !r.IsNone());
752     representation_ = r;
753   }
754 
AllDependsOnFlagSet()755   static GVNFlagSet AllDependsOnFlagSet() {
756     GVNFlagSet result;
757     // Create changes mask.
758 #define ADD_FLAG(type) result.Add(kDependsOn##type);
759   GVN_FLAG_LIST(ADD_FLAG)
760 #undef ADD_FLAG
761     return result;
762   }
763 
AllChangesFlagSet()764   static GVNFlagSet AllChangesFlagSet() {
765     GVNFlagSet result;
766     // Create changes mask.
767 #define ADD_FLAG(type) result.Add(kChanges##type);
768   GVN_FLAG_LIST(ADD_FLAG)
769 #undef ADD_FLAG
770     return result;
771   }
772 
773   // A flag mask to mark an instruction as having arbitrary side effects.
AllSideEffectsFlagSet()774   static GVNFlagSet AllSideEffectsFlagSet() {
775     GVNFlagSet result = AllChangesFlagSet();
776     result.Remove(kChangesOsrEntries);
777     return result;
778   }
779 
780   // A flag mask of all side effects that can make observable changes in
781   // an executing program (i.e. are not safe to repeat, move or remove);
AllObservableSideEffectsFlagSet()782   static GVNFlagSet AllObservableSideEffectsFlagSet() {
783     GVNFlagSet result = AllChangesFlagSet();
784     result.Remove(kChangesElementsKind);
785     result.Remove(kChangesElementsPointer);
786     result.Remove(kChangesMaps);
787     return result;
788   }
789 
790   // Remove the matching use from the use list if present.  Returns the
791   // removed list node or NULL.
792   HUseListNode* RemoveUse(HValue* value, int index);
793 
794   void RegisterUse(int index, HValue* new_value);
795 
796   HBasicBlock* block_;
797 
798   // The id of this instruction in the hydrogen graph, assigned when first
799   // added to the graph. Reflects creation order.
800   int id_;
801 
802   Representation representation_;
803   HType type_;
804   HUseListNode* use_list_;
805   Range* range_;
806   int flags_;
807   GVNFlagSet gvn_flags_;
808 
809  private:
810   DISALLOW_COPY_AND_ASSIGN(HValue);
811 };
812 
813 
814 class HInstruction: public HValue {
815  public:
next()816   HInstruction* next() const { return next_; }
previous()817   HInstruction* previous() const { return previous_; }
818 
819   virtual void PrintTo(StringStream* stream);
PrintDataTo(StringStream * stream)820   virtual void PrintDataTo(StringStream* stream) { }
821 
IsLinked()822   bool IsLinked() const { return block() != NULL; }
823   void Unlink();
824   void InsertBefore(HInstruction* next);
825   void InsertAfter(HInstruction* previous);
826 
position()827   int position() const { return position_; }
has_position()828   bool has_position() const { return position_ != RelocInfo::kNoPosition; }
set_position(int position)829   void set_position(int position) { position_ = position; }
830 
CanTruncateToInt32()831   bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
832 
833   virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
834 
835 #ifdef DEBUG
836   virtual void Verify();
837 #endif
838 
IsCall()839   virtual bool IsCall() { return false; }
840 
DECLARE_ABSTRACT_INSTRUCTION(Instruction)841   DECLARE_ABSTRACT_INSTRUCTION(Instruction)
842 
843  protected:
844   HInstruction()
845       : next_(NULL),
846         previous_(NULL),
847         position_(RelocInfo::kNoPosition) {
848     SetGVNFlag(kDependsOnOsrEntries);
849   }
850 
DeleteFromGraph()851   virtual void DeleteFromGraph() { Unlink(); }
852 
853  private:
InitializeAsFirst(HBasicBlock * block)854   void InitializeAsFirst(HBasicBlock* block) {
855     ASSERT(!IsLinked());
856     SetBlock(block);
857   }
858 
859   void PrintMnemonicTo(StringStream* stream);
860 
861   HInstruction* next_;
862   HInstruction* previous_;
863   int position_;
864 
865   friend class HBasicBlock;
866 };
867 
868 
869 template<int V>
870 class HTemplateInstruction : public HInstruction {
871  public:
OperandCount()872   int OperandCount() { return V; }
OperandAt(int i)873   HValue* OperandAt(int i) { return inputs_[i]; }
874 
875  protected:
InternalSetOperandAt(int i,HValue * value)876   void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
877 
878  private:
879   EmbeddedContainer<HValue*, V> inputs_;
880 };
881 
882 
883 class HControlInstruction: public HInstruction {
884  public:
885   virtual HBasicBlock* SuccessorAt(int i) = 0;
886   virtual int SuccessorCount() = 0;
887   virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
888 
889   virtual void PrintDataTo(StringStream* stream);
890 
FirstSuccessor()891   HBasicBlock* FirstSuccessor() {
892     return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
893   }
SecondSuccessor()894   HBasicBlock* SecondSuccessor() {
895     return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
896   }
897 
898   DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
899 };
900 
901 
902 class HSuccessorIterator BASE_EMBEDDED {
903  public:
HSuccessorIterator(HControlInstruction * instr)904   explicit HSuccessorIterator(HControlInstruction* instr)
905       : instr_(instr), current_(0) { }
906 
Done()907   bool Done() { return current_ >= instr_->SuccessorCount(); }
Current()908   HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
Advance()909   void Advance() { current_++; }
910 
911  private:
912   HControlInstruction* instr_;
913   int current_;
914 };
915 
916 
917 template<int S, int V>
918 class HTemplateControlInstruction: public HControlInstruction {
919  public:
SuccessorCount()920   int SuccessorCount() { return S; }
SuccessorAt(int i)921   HBasicBlock* SuccessorAt(int i) { return successors_[i]; }
SetSuccessorAt(int i,HBasicBlock * block)922   void SetSuccessorAt(int i, HBasicBlock* block) { successors_[i] = block; }
923 
OperandCount()924   int OperandCount() { return V; }
OperandAt(int i)925   HValue* OperandAt(int i) { return inputs_[i]; }
926 
927 
928  protected:
InternalSetOperandAt(int i,HValue * value)929   void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
930 
931  private:
932   EmbeddedContainer<HBasicBlock*, S> successors_;
933   EmbeddedContainer<HValue*, V> inputs_;
934 };
935 
936 
937 class HBlockEntry: public HTemplateInstruction<0> {
938  public:
RequiredInputRepresentation(int index)939   virtual Representation RequiredInputRepresentation(int index) {
940     return Representation::None();
941   }
942 
943   DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
944 };
945 
946 
947 // We insert soft-deoptimize when we hit code with unknown typefeedback,
948 // so that we get a chance of re-optimizing with useful typefeedback.
949 // HSoftDeoptimize does not end a basic block as opposed to HDeoptimize.
950 class HSoftDeoptimize: public HTemplateInstruction<0> {
951  public:
RequiredInputRepresentation(int index)952   virtual Representation RequiredInputRepresentation(int index) {
953     return Representation::None();
954   }
955 
956   DECLARE_CONCRETE_INSTRUCTION(SoftDeoptimize)
957 };
958 
959 
960 class HDeoptimize: public HControlInstruction {
961  public:
HDeoptimize(int environment_length)962   explicit HDeoptimize(int environment_length) : values_(environment_length) { }
963 
RequiredInputRepresentation(int index)964   virtual Representation RequiredInputRepresentation(int index) {
965     return Representation::None();
966   }
967 
OperandCount()968   virtual int OperandCount() { return values_.length(); }
OperandAt(int index)969   virtual HValue* OperandAt(int index) { return values_[index]; }
970   virtual void PrintDataTo(StringStream* stream);
971 
SuccessorCount()972   virtual int SuccessorCount() { return 0; }
SuccessorAt(int i)973   virtual HBasicBlock* SuccessorAt(int i) {
974     UNREACHABLE();
975     return NULL;
976   }
SetSuccessorAt(int i,HBasicBlock * block)977   virtual void SetSuccessorAt(int i, HBasicBlock* block) {
978     UNREACHABLE();
979   }
980 
AddEnvironmentValue(HValue * value)981   void AddEnvironmentValue(HValue* value) {
982     values_.Add(NULL);
983     SetOperandAt(values_.length() - 1, value);
984   }
985 
986   DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
987 
988   enum UseEnvironment {
989     kNoUses,
990     kUseAll
991   };
992 
993  protected:
InternalSetOperandAt(int index,HValue * value)994   virtual void InternalSetOperandAt(int index, HValue* value) {
995     values_[index] = value;
996   }
997 
998  private:
999   ZoneList<HValue*> values_;
1000 };
1001 
1002 
1003 class HGoto: public HTemplateControlInstruction<1, 0> {
1004  public:
HGoto(HBasicBlock * target)1005   explicit HGoto(HBasicBlock* target) {
1006     SetSuccessorAt(0, target);
1007   }
1008 
RequiredInputRepresentation(int index)1009   virtual Representation RequiredInputRepresentation(int index) {
1010     return Representation::None();
1011   }
1012 
1013   virtual void PrintDataTo(StringStream* stream);
1014 
1015   DECLARE_CONCRETE_INSTRUCTION(Goto)
1016 };
1017 
1018 
1019 class HUnaryControlInstruction: public HTemplateControlInstruction<2, 1> {
1020  public:
HUnaryControlInstruction(HValue * value,HBasicBlock * true_target,HBasicBlock * false_target)1021   HUnaryControlInstruction(HValue* value,
1022                            HBasicBlock* true_target,
1023                            HBasicBlock* false_target) {
1024     SetOperandAt(0, value);
1025     SetSuccessorAt(0, true_target);
1026     SetSuccessorAt(1, false_target);
1027   }
1028 
1029   virtual void PrintDataTo(StringStream* stream);
1030 
value()1031   HValue* value() { return OperandAt(0); }
1032 };
1033 
1034 
1035 class HBranch: public HUnaryControlInstruction {
1036  public:
1037   HBranch(HValue* value,
1038           HBasicBlock* true_target,
1039           HBasicBlock* false_target,
1040           ToBooleanStub::Types expected_input_types = ToBooleanStub::no_types())
HUnaryControlInstruction(value,true_target,false_target)1041       : HUnaryControlInstruction(value, true_target, false_target),
1042         expected_input_types_(expected_input_types) {
1043     ASSERT(true_target != NULL && false_target != NULL);
1044   }
HBranch(HValue * value)1045   explicit HBranch(HValue* value)
1046       : HUnaryControlInstruction(value, NULL, NULL) { }
1047 
1048 
RequiredInputRepresentation(int index)1049   virtual Representation RequiredInputRepresentation(int index) {
1050     return Representation::None();
1051   }
1052 
expected_input_types()1053   ToBooleanStub::Types expected_input_types() const {
1054     return expected_input_types_;
1055   }
1056 
1057   DECLARE_CONCRETE_INSTRUCTION(Branch)
1058 
1059  private:
1060   ToBooleanStub::Types expected_input_types_;
1061 };
1062 
1063 
1064 class HCompareMap: public HUnaryControlInstruction {
1065  public:
HCompareMap(HValue * value,Handle<Map> map,HBasicBlock * true_target,HBasicBlock * false_target)1066   HCompareMap(HValue* value,
1067               Handle<Map> map,
1068               HBasicBlock* true_target,
1069               HBasicBlock* false_target)
1070       : HUnaryControlInstruction(value, true_target, false_target),
1071         map_(map) {
1072     ASSERT(true_target != NULL);
1073     ASSERT(false_target != NULL);
1074     ASSERT(!map.is_null());
1075   }
1076 
1077   virtual void PrintDataTo(StringStream* stream);
1078 
map()1079   Handle<Map> map() const { return map_; }
1080 
RequiredInputRepresentation(int index)1081   virtual Representation RequiredInputRepresentation(int index) {
1082     return Representation::Tagged();
1083   }
1084 
1085   DECLARE_CONCRETE_INSTRUCTION(CompareMap)
1086 
1087  private:
1088   Handle<Map> map_;
1089 };
1090 
1091 
1092 class HReturn: public HTemplateControlInstruction<0, 1> {
1093  public:
HReturn(HValue * value)1094   explicit HReturn(HValue* value) {
1095     SetOperandAt(0, value);
1096   }
1097 
RequiredInputRepresentation(int index)1098   virtual Representation RequiredInputRepresentation(int index) {
1099     return Representation::Tagged();
1100   }
1101 
1102   virtual void PrintDataTo(StringStream* stream);
1103 
value()1104   HValue* value() { return OperandAt(0); }
1105 
1106   DECLARE_CONCRETE_INSTRUCTION(Return)
1107 };
1108 
1109 
1110 class HAbnormalExit: public HTemplateControlInstruction<0, 0> {
1111  public:
RequiredInputRepresentation(int index)1112   virtual Representation RequiredInputRepresentation(int index) {
1113     return Representation::None();
1114   }
1115 
1116   DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
1117 };
1118 
1119 
1120 class HUnaryOperation: public HTemplateInstruction<1> {
1121  public:
HUnaryOperation(HValue * value)1122   explicit HUnaryOperation(HValue* value) {
1123     SetOperandAt(0, value);
1124   }
1125 
cast(HValue * value)1126   static HUnaryOperation* cast(HValue* value) {
1127     return reinterpret_cast<HUnaryOperation*>(value);
1128   }
1129 
value()1130   HValue* value() { return OperandAt(0); }
1131   virtual void PrintDataTo(StringStream* stream);
1132 };
1133 
1134 
1135 class HThrow: public HTemplateInstruction<2> {
1136  public:
HThrow(HValue * context,HValue * value)1137   HThrow(HValue* context, HValue* value) {
1138     SetOperandAt(0, context);
1139     SetOperandAt(1, value);
1140     SetAllSideEffects();
1141   }
1142 
RequiredInputRepresentation(int index)1143   virtual Representation RequiredInputRepresentation(int index) {
1144     return Representation::Tagged();
1145   }
1146 
context()1147   HValue* context() { return OperandAt(0); }
value()1148   HValue* value() { return OperandAt(1); }
1149 
1150   DECLARE_CONCRETE_INSTRUCTION(Throw)
1151 };
1152 
1153 
1154 class HUseConst: public HUnaryOperation {
1155  public:
HUseConst(HValue * old_value)1156   explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
1157 
RequiredInputRepresentation(int index)1158   virtual Representation RequiredInputRepresentation(int index) {
1159     return Representation::None();
1160   }
1161 
1162   DECLARE_CONCRETE_INSTRUCTION(UseConst)
1163 };
1164 
1165 
1166 class HForceRepresentation: public HTemplateInstruction<1> {
1167  public:
HForceRepresentation(HValue * value,Representation required_representation)1168   HForceRepresentation(HValue* value, Representation required_representation) {
1169     SetOperandAt(0, value);
1170     set_representation(required_representation);
1171   }
1172 
value()1173   HValue* value() { return OperandAt(0); }
1174 
1175   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1176 
RequiredInputRepresentation(int index)1177   virtual Representation RequiredInputRepresentation(int index) {
1178     return representation();  // Same as the output representation.
1179   }
1180 
1181   DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
1182 };
1183 
1184 
1185 class HChange: public HUnaryOperation {
1186  public:
HChange(HValue * value,Representation to,bool is_truncating,bool deoptimize_on_undefined)1187   HChange(HValue* value,
1188           Representation to,
1189           bool is_truncating,
1190           bool deoptimize_on_undefined)
1191       : HUnaryOperation(value) {
1192     ASSERT(!value->representation().IsNone() && !to.IsNone());
1193     ASSERT(!value->representation().Equals(to));
1194     set_representation(to);
1195     set_type(HType::TaggedNumber());
1196     SetFlag(kUseGVN);
1197     if (deoptimize_on_undefined) SetFlag(kDeoptimizeOnUndefined);
1198     if (is_truncating) SetFlag(kTruncatingToInt32);
1199   }
1200 
1201   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1202   virtual HType CalculateInferredType();
1203   virtual HValue* Canonicalize();
1204 
from()1205   Representation from() { return value()->representation(); }
to()1206   Representation to() { return representation(); }
deoptimize_on_undefined()1207   bool deoptimize_on_undefined() const {
1208     return CheckFlag(kDeoptimizeOnUndefined);
1209   }
deoptimize_on_minus_zero()1210   bool deoptimize_on_minus_zero() const {
1211     return CheckFlag(kBailoutOnMinusZero);
1212   }
RequiredInputRepresentation(int index)1213   virtual Representation RequiredInputRepresentation(int index) {
1214     return from();
1215   }
1216 
1217   virtual Range* InferRange(Zone* zone);
1218 
1219   virtual void PrintDataTo(StringStream* stream);
1220 
DECLARE_CONCRETE_INSTRUCTION(Change)1221   DECLARE_CONCRETE_INSTRUCTION(Change)
1222 
1223  protected:
1224   virtual bool DataEquals(HValue* other) { return true; }
1225 };
1226 
1227 
1228 class HClampToUint8: public HUnaryOperation {
1229  public:
HClampToUint8(HValue * value)1230   explicit HClampToUint8(HValue* value)
1231       : HUnaryOperation(value) {
1232     set_representation(Representation::Integer32());
1233     SetFlag(kUseGVN);
1234   }
1235 
RequiredInputRepresentation(int index)1236   virtual Representation RequiredInputRepresentation(int index) {
1237     return Representation::None();
1238   }
1239 
DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)1240   DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
1241 
1242  protected:
1243   virtual bool DataEquals(HValue* other) { return true; }
1244 };
1245 
1246 
1247 class HSimulate: public HInstruction {
1248  public:
HSimulate(int ast_id,int pop_count)1249   HSimulate(int ast_id, int pop_count)
1250       : ast_id_(ast_id),
1251         pop_count_(pop_count),
1252         values_(2),
1253         assigned_indexes_(2) {}
~HSimulate()1254   virtual ~HSimulate() {}
1255 
1256   virtual void PrintDataTo(StringStream* stream);
1257 
HasAstId()1258   bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; }
ast_id()1259   int ast_id() const { return ast_id_; }
set_ast_id(int id)1260   void set_ast_id(int id) {
1261     ASSERT(!HasAstId());
1262     ast_id_ = id;
1263   }
1264 
pop_count()1265   int pop_count() const { return pop_count_; }
values()1266   const ZoneList<HValue*>* values() const { return &values_; }
GetAssignedIndexAt(int index)1267   int GetAssignedIndexAt(int index) const {
1268     ASSERT(HasAssignedIndexAt(index));
1269     return assigned_indexes_[index];
1270   }
HasAssignedIndexAt(int index)1271   bool HasAssignedIndexAt(int index) const {
1272     return assigned_indexes_[index] != kNoIndex;
1273   }
AddAssignedValue(int index,HValue * value)1274   void AddAssignedValue(int index, HValue* value) {
1275     AddValue(index, value);
1276   }
AddPushedValue(HValue * value)1277   void AddPushedValue(HValue* value) {
1278     AddValue(kNoIndex, value);
1279   }
OperandCount()1280   virtual int OperandCount() { return values_.length(); }
OperandAt(int index)1281   virtual HValue* OperandAt(int index) { return values_[index]; }
1282 
RequiredInputRepresentation(int index)1283   virtual Representation RequiredInputRepresentation(int index) {
1284     return Representation::None();
1285   }
1286 
1287   DECLARE_CONCRETE_INSTRUCTION(Simulate)
1288 
1289 #ifdef DEBUG
1290   virtual void Verify();
1291 #endif
1292 
1293  protected:
InternalSetOperandAt(int index,HValue * value)1294   virtual void InternalSetOperandAt(int index, HValue* value) {
1295     values_[index] = value;
1296   }
1297 
1298  private:
1299   static const int kNoIndex = -1;
AddValue(int index,HValue * value)1300   void AddValue(int index, HValue* value) {
1301     assigned_indexes_.Add(index);
1302     // Resize the list of pushed values.
1303     values_.Add(NULL);
1304     // Set the operand through the base method in HValue to make sure that the
1305     // use lists are correctly updated.
1306     SetOperandAt(values_.length() - 1, value);
1307   }
1308   int ast_id_;
1309   int pop_count_;
1310   ZoneList<HValue*> values_;
1311   ZoneList<int> assigned_indexes_;
1312 };
1313 
1314 
1315 class HStackCheck: public HTemplateInstruction<1> {
1316  public:
1317   enum Type {
1318     kFunctionEntry,
1319     kBackwardsBranch
1320   };
1321 
HStackCheck(HValue * context,Type type)1322   HStackCheck(HValue* context, Type type) : type_(type) {
1323     SetOperandAt(0, context);
1324   }
1325 
context()1326   HValue* context() { return OperandAt(0); }
1327 
RequiredInputRepresentation(int index)1328   virtual Representation RequiredInputRepresentation(int index) {
1329     return Representation::Tagged();
1330   }
1331 
Eliminate()1332   void Eliminate() {
1333     // The stack check eliminator might try to eliminate the same stack
1334     // check instruction multiple times.
1335     if (IsLinked()) {
1336       DeleteFromGraph();
1337     }
1338   }
1339 
is_function_entry()1340   bool is_function_entry() { return type_ == kFunctionEntry; }
is_backwards_branch()1341   bool is_backwards_branch() { return type_ == kBackwardsBranch; }
1342 
1343   DECLARE_CONCRETE_INSTRUCTION(StackCheck)
1344 
1345  private:
1346   Type type_;
1347 };
1348 
1349 
1350 class HEnterInlined: public HTemplateInstruction<0> {
1351  public:
1352   HEnterInlined(Handle<JSFunction> closure,
1353                 int arguments_count,
1354                 FunctionLiteral* function,
1355                 CallKind call_kind,
1356                 bool is_construct,
1357                 Variable* arguments)
1358       : closure_(closure),
1359         arguments_count_(arguments_count),
1360         function_(function),
1361         call_kind_(call_kind),
1362         is_construct_(is_construct),
1363         arguments_(arguments) {
1364   }
1365 
1366   virtual void PrintDataTo(StringStream* stream);
1367 
1368   Handle<JSFunction> closure() const { return closure_; }
1369   int arguments_count() const { return arguments_count_; }
1370   FunctionLiteral* function() const { return function_; }
1371   CallKind call_kind() const { return call_kind_; }
1372   bool is_construct() const { return is_construct_; }
1373 
1374   virtual Representation RequiredInputRepresentation(int index) {
1375     return Representation::None();
1376   }
1377 
1378   Variable* arguments() { return arguments_; }
1379 
1380   DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
1381 
1382  private:
1383   Handle<JSFunction> closure_;
1384   int arguments_count_;
1385   FunctionLiteral* function_;
1386   CallKind call_kind_;
1387   bool is_construct_;
1388   Variable* arguments_;
1389 };
1390 
1391 
1392 class HLeaveInlined: public HTemplateInstruction<0> {
1393  public:
1394   HLeaveInlined() {}
1395 
1396   virtual Representation RequiredInputRepresentation(int index) {
1397     return Representation::None();
1398   }
1399 
1400   DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
1401 };
1402 
1403 
1404 class HPushArgument: public HUnaryOperation {
1405  public:
1406   explicit HPushArgument(HValue* value) : HUnaryOperation(value) {
1407     set_representation(Representation::Tagged());
1408   }
1409 
1410   virtual Representation RequiredInputRepresentation(int index) {
1411     return Representation::Tagged();
1412   }
1413 
1414   HValue* argument() { return OperandAt(0); }
1415 
1416   DECLARE_CONCRETE_INSTRUCTION(PushArgument)
1417 };
1418 
1419 
1420 class HThisFunction: public HTemplateInstruction<0> {
1421  public:
1422   explicit HThisFunction(Handle<JSFunction> closure) : closure_(closure) {
1423     set_representation(Representation::Tagged());
1424     SetFlag(kUseGVN);
1425   }
1426 
1427   virtual Representation RequiredInputRepresentation(int index) {
1428     return Representation::None();
1429   }
1430 
1431   Handle<JSFunction> closure() const { return closure_; }
1432 
1433   DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
1434 
1435  protected:
1436   virtual bool DataEquals(HValue* other) {
1437     HThisFunction* b = HThisFunction::cast(other);
1438     return *closure() == *b->closure();
1439   }
1440 
1441  private:
1442   Handle<JSFunction> closure_;
1443 };
1444 
1445 
1446 class HContext: public HTemplateInstruction<0> {
1447  public:
1448   HContext() {
1449     set_representation(Representation::Tagged());
1450     SetFlag(kUseGVN);
1451   }
1452 
1453   virtual Representation RequiredInputRepresentation(int index) {
1454     return Representation::None();
1455   }
1456 
1457   DECLARE_CONCRETE_INSTRUCTION(Context)
1458 
1459  protected:
1460   virtual bool DataEquals(HValue* other) { return true; }
1461 };
1462 
1463 
1464 class HOuterContext: public HUnaryOperation {
1465  public:
1466   explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
1467     set_representation(Representation::Tagged());
1468     SetFlag(kUseGVN);
1469   }
1470 
1471   DECLARE_CONCRETE_INSTRUCTION(OuterContext);
1472 
1473   virtual Representation RequiredInputRepresentation(int index) {
1474     return Representation::Tagged();
1475   }
1476 
1477  protected:
1478   virtual bool DataEquals(HValue* other) { return true; }
1479 };
1480 
1481 
1482 class HDeclareGlobals: public HUnaryOperation {
1483  public:
1484   HDeclareGlobals(HValue* context,
1485                   Handle<FixedArray> pairs,
1486                   int flags)
1487       : HUnaryOperation(context),
1488         pairs_(pairs),
1489         flags_(flags) {
1490     set_representation(Representation::Tagged());
1491     SetAllSideEffects();
1492   }
1493 
1494   HValue* context() { return OperandAt(0); }
1495   Handle<FixedArray> pairs() const { return pairs_; }
1496   int flags() const { return flags_; }
1497 
1498   DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
1499 
1500   virtual Representation RequiredInputRepresentation(int index) {
1501     return Representation::Tagged();
1502   }
1503  private:
1504   Handle<FixedArray> pairs_;
1505   int flags_;
1506 };
1507 
1508 
1509 class HGlobalObject: public HUnaryOperation {
1510  public:
1511   explicit HGlobalObject(HValue* context) : HUnaryOperation(context) {
1512     set_representation(Representation::Tagged());
1513     SetFlag(kUseGVN);
1514   }
1515 
1516   DECLARE_CONCRETE_INSTRUCTION(GlobalObject)
1517 
1518   virtual Representation RequiredInputRepresentation(int index) {
1519     return Representation::Tagged();
1520   }
1521 
1522  protected:
1523   virtual bool DataEquals(HValue* other) { return true; }
1524 };
1525 
1526 
1527 class HGlobalReceiver: public HUnaryOperation {
1528  public:
1529   explicit HGlobalReceiver(HValue* global_object)
1530       : HUnaryOperation(global_object) {
1531     set_representation(Representation::Tagged());
1532     SetFlag(kUseGVN);
1533   }
1534 
1535   DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver)
1536 
1537   virtual Representation RequiredInputRepresentation(int index) {
1538     return Representation::Tagged();
1539   }
1540 
1541  protected:
1542   virtual bool DataEquals(HValue* other) { return true; }
1543 };
1544 
1545 
1546 template <int V>
1547 class HCall: public HTemplateInstruction<V> {
1548  public:
1549   // The argument count includes the receiver.
1550   explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
1551     this->set_representation(Representation::Tagged());
1552     this->SetAllSideEffects();
1553   }
1554 
1555   virtual HType CalculateInferredType() { return HType::Tagged(); }
1556 
1557   virtual int argument_count() const { return argument_count_; }
1558 
1559   virtual bool IsCall() { return true; }
1560 
1561  private:
1562   int argument_count_;
1563 };
1564 
1565 
1566 class HUnaryCall: public HCall<1> {
1567  public:
1568   HUnaryCall(HValue* value, int argument_count)
1569       : HCall<1>(argument_count) {
1570     SetOperandAt(0, value);
1571   }
1572 
1573   virtual Representation RequiredInputRepresentation(int index) {
1574     return Representation::Tagged();
1575   }
1576 
1577   virtual void PrintDataTo(StringStream* stream);
1578 
1579   HValue* value() { return OperandAt(0); }
1580 };
1581 
1582 
1583 class HBinaryCall: public HCall<2> {
1584  public:
1585   HBinaryCall(HValue* first, HValue* second, int argument_count)
1586       : HCall<2>(argument_count) {
1587     SetOperandAt(0, first);
1588     SetOperandAt(1, second);
1589   }
1590 
1591   virtual void PrintDataTo(StringStream* stream);
1592 
1593   virtual Representation RequiredInputRepresentation(int index) {
1594     return Representation::Tagged();
1595   }
1596 
1597   HValue* first() { return OperandAt(0); }
1598   HValue* second() { return OperandAt(1); }
1599 };
1600 
1601 
1602 class HInvokeFunction: public HBinaryCall {
1603  public:
1604   HInvokeFunction(HValue* context, HValue* function, int argument_count)
1605       : HBinaryCall(context, function, argument_count) {
1606   }
1607 
1608   virtual Representation RequiredInputRepresentation(int index) {
1609     return Representation::Tagged();
1610   }
1611 
1612   HValue* context() { return first(); }
1613   HValue* function() { return second(); }
1614 
1615   DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
1616 };
1617 
1618 
1619 class HCallConstantFunction: public HCall<0> {
1620  public:
1621   HCallConstantFunction(Handle<JSFunction> function, int argument_count)
1622       : HCall<0>(argument_count), function_(function) { }
1623 
1624   Handle<JSFunction> function() const { return function_; }
1625 
1626   bool IsApplyFunction() const {
1627     return function_->code() ==
1628         Isolate::Current()->builtins()->builtin(Builtins::kFunctionApply);
1629   }
1630 
1631   virtual void PrintDataTo(StringStream* stream);
1632 
1633   virtual Representation RequiredInputRepresentation(int index) {
1634     return Representation::None();
1635   }
1636 
1637   DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction)
1638 
1639  private:
1640   Handle<JSFunction> function_;
1641 };
1642 
1643 
1644 class HCallKeyed: public HBinaryCall {
1645  public:
1646   HCallKeyed(HValue* context, HValue* key, int argument_count)
1647       : HBinaryCall(context, key, argument_count) {
1648   }
1649 
1650   virtual Representation RequiredInputRepresentation(int index) {
1651     return Representation::Tagged();
1652   }
1653 
1654   HValue* context() { return first(); }
1655   HValue* key() { return second(); }
1656 
1657   DECLARE_CONCRETE_INSTRUCTION(CallKeyed)
1658 };
1659 
1660 
1661 class HCallNamed: public HUnaryCall {
1662  public:
1663   HCallNamed(HValue* context, Handle<String> name, int argument_count)
1664       : HUnaryCall(context, argument_count), name_(name) {
1665   }
1666 
1667   virtual void PrintDataTo(StringStream* stream);
1668 
1669   HValue* context() { return value(); }
1670   Handle<String> name() const { return name_; }
1671 
1672   DECLARE_CONCRETE_INSTRUCTION(CallNamed)
1673 
1674   virtual Representation RequiredInputRepresentation(int index) {
1675     return Representation::Tagged();
1676   }
1677 
1678  private:
1679   Handle<String> name_;
1680 };
1681 
1682 
1683 class HCallFunction: public HBinaryCall {
1684  public:
1685   HCallFunction(HValue* context, HValue* function, int argument_count)
1686       : HBinaryCall(context, function, argument_count) {
1687   }
1688 
1689   HValue* context() { return first(); }
1690   HValue* function() { return second(); }
1691 
1692   virtual Representation RequiredInputRepresentation(int index) {
1693     return Representation::Tagged();
1694   }
1695 
1696   DECLARE_CONCRETE_INSTRUCTION(CallFunction)
1697 };
1698 
1699 
1700 class HCallGlobal: public HUnaryCall {
1701  public:
1702   HCallGlobal(HValue* context, Handle<String> name, int argument_count)
1703       : HUnaryCall(context, argument_count), name_(name) {
1704   }
1705 
1706   virtual void PrintDataTo(StringStream* stream);
1707 
1708   HValue* context() { return value(); }
1709   Handle<String> name() const { return name_; }
1710 
1711   virtual Representation RequiredInputRepresentation(int index) {
1712     return Representation::Tagged();
1713   }
1714 
1715   DECLARE_CONCRETE_INSTRUCTION(CallGlobal)
1716 
1717  private:
1718   Handle<String> name_;
1719 };
1720 
1721 
1722 class HCallKnownGlobal: public HCall<0> {
1723  public:
1724   HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
1725       : HCall<0>(argument_count), target_(target) { }
1726 
1727   virtual void PrintDataTo(StringStream* stream);
1728 
1729   Handle<JSFunction> target() const { return target_; }
1730 
1731   virtual Representation RequiredInputRepresentation(int index) {
1732     return Representation::None();
1733   }
1734 
1735   DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal)
1736 
1737  private:
1738   Handle<JSFunction> target_;
1739 };
1740 
1741 
1742 class HCallNew: public HBinaryCall {
1743  public:
1744   HCallNew(HValue* context, HValue* constructor, int argument_count)
1745       : HBinaryCall(context, constructor, argument_count) {
1746   }
1747 
1748   virtual Representation RequiredInputRepresentation(int index) {
1749     return Representation::Tagged();
1750   }
1751 
1752   HValue* context() { return first(); }
1753   HValue* constructor() { return second(); }
1754 
1755   DECLARE_CONCRETE_INSTRUCTION(CallNew)
1756 };
1757 
1758 
1759 class HCallRuntime: public HCall<1> {
1760  public:
1761   HCallRuntime(HValue* context,
1762                Handle<String> name,
1763                const Runtime::Function* c_function,
1764                int argument_count)
1765       : HCall<1>(argument_count), c_function_(c_function), name_(name) {
1766     SetOperandAt(0, context);
1767   }
1768 
1769   virtual void PrintDataTo(StringStream* stream);
1770 
1771   HValue* context() { return OperandAt(0); }
1772   const Runtime::Function* function() const { return c_function_; }
1773   Handle<String> name() const { return name_; }
1774 
1775   virtual Representation RequiredInputRepresentation(int index) {
1776     return Representation::Tagged();
1777   }
1778 
1779   DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
1780 
1781  private:
1782   const Runtime::Function* c_function_;
1783   Handle<String> name_;
1784 };
1785 
1786 
1787 class HJSArrayLength: public HTemplateInstruction<2> {
1788  public:
1789   HJSArrayLength(HValue* value, HValue* typecheck) {
1790     // The length of an array is stored as a tagged value in the array
1791     // object. It is guaranteed to be 32 bit integer, but it can be
1792     // represented as either a smi or heap number.
1793     SetOperandAt(0, value);
1794     SetOperandAt(1, typecheck);
1795     set_representation(Representation::Tagged());
1796     SetFlag(kUseGVN);
1797     SetGVNFlag(kDependsOnArrayLengths);
1798     SetGVNFlag(kDependsOnMaps);
1799   }
1800 
1801   virtual Representation RequiredInputRepresentation(int index) {
1802     return Representation::Tagged();
1803   }
1804 
1805   virtual void PrintDataTo(StringStream* stream);
1806 
1807   HValue* value() { return OperandAt(0); }
1808   HValue* typecheck() { return OperandAt(1); }
1809 
1810   DECLARE_CONCRETE_INSTRUCTION(JSArrayLength)
1811 
1812  protected:
1813   virtual bool DataEquals(HValue* other) { return true; }
1814 };
1815 
1816 
1817 class HFixedArrayBaseLength: public HUnaryOperation {
1818  public:
1819   explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) {
1820     set_representation(Representation::Tagged());
1821     SetFlag(kUseGVN);
1822     SetGVNFlag(kDependsOnArrayLengths);
1823   }
1824 
1825   virtual Representation RequiredInputRepresentation(int index) {
1826     return Representation::Tagged();
1827   }
1828 
1829   DECLARE_CONCRETE_INSTRUCTION(FixedArrayBaseLength)
1830 
1831  protected:
1832   virtual bool DataEquals(HValue* other) { return true; }
1833 };
1834 
1835 
1836 class HElementsKind: public HUnaryOperation {
1837  public:
1838   explicit HElementsKind(HValue* value) : HUnaryOperation(value) {
1839     set_representation(Representation::Integer32());
1840     SetFlag(kUseGVN);
1841     SetGVNFlag(kDependsOnElementsKind);
1842   }
1843 
1844   virtual Representation RequiredInputRepresentation(int index) {
1845     return Representation::Tagged();
1846   }
1847 
1848   DECLARE_CONCRETE_INSTRUCTION(ElementsKind)
1849 
1850  protected:
1851   virtual bool DataEquals(HValue* other) { return true; }
1852 };
1853 
1854 
1855 class HBitNot: public HUnaryOperation {
1856  public:
1857   explicit HBitNot(HValue* value) : HUnaryOperation(value) {
1858     set_representation(Representation::Integer32());
1859     SetFlag(kUseGVN);
1860     SetFlag(kTruncatingToInt32);
1861   }
1862 
1863   virtual Representation RequiredInputRepresentation(int index) {
1864     return Representation::Integer32();
1865   }
1866   virtual HType CalculateInferredType();
1867 
1868   DECLARE_CONCRETE_INSTRUCTION(BitNot)
1869 
1870  protected:
1871   virtual bool DataEquals(HValue* other) { return true; }
1872 };
1873 
1874 
1875 class HUnaryMathOperation: public HTemplateInstruction<2> {
1876  public:
1877   HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
1878       : op_(op) {
1879     SetOperandAt(0, context);
1880     SetOperandAt(1, value);
1881     switch (op) {
1882       case kMathFloor:
1883       case kMathRound:
1884       case kMathCeil:
1885         set_representation(Representation::Integer32());
1886         break;
1887       case kMathAbs:
1888         set_representation(Representation::Tagged());
1889         SetFlag(kFlexibleRepresentation);
1890         break;
1891       case kMathSqrt:
1892       case kMathPowHalf:
1893       case kMathLog:
1894       case kMathSin:
1895       case kMathCos:
1896       case kMathTan:
1897         set_representation(Representation::Double());
1898         break;
1899       default:
1900         UNREACHABLE();
1901     }
1902     SetFlag(kUseGVN);
1903   }
1904 
1905   HValue* context() { return OperandAt(0); }
1906   HValue* value() { return OperandAt(1); }
1907 
1908   virtual void PrintDataTo(StringStream* stream);
1909 
1910   virtual HType CalculateInferredType();
1911 
1912   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1913 
1914   virtual Representation RequiredInputRepresentation(int index) {
1915     if (index == 0) {
1916       return Representation::Tagged();
1917     } else {
1918       switch (op_) {
1919         case kMathFloor:
1920         case kMathRound:
1921         case kMathCeil:
1922         case kMathSqrt:
1923         case kMathPowHalf:
1924         case kMathLog:
1925         case kMathSin:
1926         case kMathCos:
1927         case kMathTan:
1928           return Representation::Double();
1929         case kMathAbs:
1930           return representation();
1931         default:
1932           UNREACHABLE();
1933           return Representation::None();
1934       }
1935     }
1936   }
1937 
1938   virtual HValue* Canonicalize() {
1939     // If the input is integer32 then we replace the floor instruction
1940     // with its inputs.  This happens before the representation changes are
1941     // introduced.
1942     if (op() == kMathFloor) {
1943       if (value()->representation().IsInteger32()) return value();
1944     }
1945     return this;
1946   }
1947 
1948   BuiltinFunctionId op() const { return op_; }
1949   const char* OpName() const;
1950 
1951   DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
1952 
1953  protected:
1954   virtual bool DataEquals(HValue* other) {
1955     HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
1956     return op_ == b->op();
1957   }
1958 
1959  private:
1960   BuiltinFunctionId op_;
1961 };
1962 
1963 
1964 class HLoadElements: public HUnaryOperation {
1965  public:
1966   explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
1967     set_representation(Representation::Tagged());
1968     SetFlag(kUseGVN);
1969     SetGVNFlag(kDependsOnElementsPointer);
1970   }
1971 
1972   virtual Representation RequiredInputRepresentation(int index) {
1973     return Representation::Tagged();
1974   }
1975 
1976   DECLARE_CONCRETE_INSTRUCTION(LoadElements)
1977 
1978  protected:
1979   virtual bool DataEquals(HValue* other) { return true; }
1980 };
1981 
1982 
1983 class HLoadExternalArrayPointer: public HUnaryOperation {
1984  public:
1985   explicit HLoadExternalArrayPointer(HValue* value)
1986       : HUnaryOperation(value) {
1987     set_representation(Representation::External());
1988     // The result of this instruction is idempotent as long as its inputs don't
1989     // change.  The external array of a specialized array elements object cannot
1990     // change once set, so it's no necessary to introduce any additional
1991     // dependencies on top of the inputs.
1992     SetFlag(kUseGVN);
1993   }
1994 
1995   virtual Representation RequiredInputRepresentation(int index) {
1996     return Representation::Tagged();
1997   }
1998 
1999   DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer)
2000 
2001  protected:
2002   virtual bool DataEquals(HValue* other) { return true; }
2003 };
2004 
2005 
2006 class HCheckMap: public HTemplateInstruction<2> {
2007  public:
2008   HCheckMap(HValue* value,
2009             Handle<Map> map,
2010             HValue* typecheck = NULL,
2011             CompareMapMode mode = REQUIRE_EXACT_MAP)
2012       : map_(map),
2013         mode_(mode) {
2014     SetOperandAt(0, value);
2015     // If callers don't depend on a typecheck, they can pass in NULL. In that
2016     // case we use a copy of the |value| argument as a dummy value.
2017     SetOperandAt(1, typecheck != NULL ? typecheck : value);
2018     set_representation(Representation::Tagged());
2019     SetFlag(kUseGVN);
2020     SetGVNFlag(kDependsOnMaps);
2021     // If the map to check doesn't have the untransitioned elements, it must not
2022     // be hoisted above TransitionElements instructions.
2023     if (mode == REQUIRE_EXACT_MAP || !map->has_fast_smi_only_elements()) {
2024       SetGVNFlag(kDependsOnElementsKind);
2025     }
2026     has_element_transitions_ =
2027         map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL) != NULL ||
2028         map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL) != NULL;
2029   }
2030 
2031   virtual Representation RequiredInputRepresentation(int index) {
2032     return Representation::Tagged();
2033   }
2034   virtual void PrintDataTo(StringStream* stream);
2035   virtual HType CalculateInferredType();
2036 
2037   HValue* value() { return OperandAt(0); }
2038   Handle<Map> map() const { return map_; }
2039   CompareMapMode mode() const { return mode_; }
2040 
2041   DECLARE_CONCRETE_INSTRUCTION(CheckMap)
2042 
2043  protected:
2044   virtual bool DataEquals(HValue* other) {
2045     HCheckMap* b = HCheckMap::cast(other);
2046     // Two CheckMaps instructions are DataEqual if their maps are identical and
2047     // they have the same mode. The mode comparison can be ignored if the map
2048     // has no elements transitions.
2049     return map_.is_identical_to(b->map()) &&
2050         (b->mode() == mode() || !has_element_transitions_);
2051   }
2052 
2053  private:
2054   bool has_element_transitions_;
2055   Handle<Map> map_;
2056   CompareMapMode mode_;
2057 };
2058 
2059 
2060 class HCheckFunction: public HUnaryOperation {
2061  public:
2062   HCheckFunction(HValue* value, Handle<JSFunction> function)
2063       : HUnaryOperation(value), target_(function) {
2064     set_representation(Representation::Tagged());
2065     SetFlag(kUseGVN);
2066   }
2067 
2068   virtual Representation RequiredInputRepresentation(int index) {
2069     return Representation::Tagged();
2070   }
2071   virtual void PrintDataTo(StringStream* stream);
2072   virtual HType CalculateInferredType();
2073 
2074 #ifdef DEBUG
2075   virtual void Verify();
2076 #endif
2077 
2078   Handle<JSFunction> target() const { return target_; }
2079 
2080   DECLARE_CONCRETE_INSTRUCTION(CheckFunction)
2081 
2082  protected:
2083   virtual bool DataEquals(HValue* other) {
2084     HCheckFunction* b = HCheckFunction::cast(other);
2085     return target_.is_identical_to(b->target());
2086   }
2087 
2088  private:
2089   Handle<JSFunction> target_;
2090 };
2091 
2092 
2093 class HCheckInstanceType: public HUnaryOperation {
2094  public:
2095   static HCheckInstanceType* NewIsSpecObject(HValue* value) {
2096     return new HCheckInstanceType(value, IS_SPEC_OBJECT);
2097   }
2098   static HCheckInstanceType* NewIsJSArray(HValue* value) {
2099     return new HCheckInstanceType(value, IS_JS_ARRAY);
2100   }
2101   static HCheckInstanceType* NewIsString(HValue* value) {
2102     return new HCheckInstanceType(value, IS_STRING);
2103   }
2104   static HCheckInstanceType* NewIsSymbol(HValue* value) {
2105     return new HCheckInstanceType(value, IS_SYMBOL);
2106   }
2107 
2108   virtual void PrintDataTo(StringStream* stream);
2109 
2110   virtual Representation RequiredInputRepresentation(int index) {
2111     return Representation::Tagged();
2112   }
2113 
2114   virtual HValue* Canonicalize();
2115 
2116   bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
2117   void GetCheckInterval(InstanceType* first, InstanceType* last);
2118   void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
2119 
2120   DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
2121 
2122  protected:
2123   // TODO(ager): It could be nice to allow the ommision of instance
2124   // type checks if we have already performed an instance type check
2125   // with a larger range.
2126   virtual bool DataEquals(HValue* other) {
2127     HCheckInstanceType* b = HCheckInstanceType::cast(other);
2128     return check_ == b->check_;
2129   }
2130 
2131  private:
2132   enum Check {
2133     IS_SPEC_OBJECT,
2134     IS_JS_ARRAY,
2135     IS_STRING,
2136     IS_SYMBOL,
2137     LAST_INTERVAL_CHECK = IS_JS_ARRAY
2138   };
2139 
2140   const char* GetCheckName();
2141 
2142   HCheckInstanceType(HValue* value, Check check)
2143       : HUnaryOperation(value), check_(check) {
2144     set_representation(Representation::Tagged());
2145     SetFlag(kUseGVN);
2146   }
2147 
2148   const Check check_;
2149 };
2150 
2151 
2152 class HCheckNonSmi: public HUnaryOperation {
2153  public:
2154   explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
2155     set_representation(Representation::Tagged());
2156     SetFlag(kUseGVN);
2157   }
2158 
2159   virtual Representation RequiredInputRepresentation(int index) {
2160     return Representation::Tagged();
2161   }
2162 
2163   virtual HType CalculateInferredType();
2164 
2165 #ifdef DEBUG
2166   virtual void Verify();
2167 #endif
2168 
2169   virtual HValue* Canonicalize() {
2170     HType value_type = value()->type();
2171     if (!value_type.IsUninitialized() &&
2172         (value_type.IsHeapNumber() ||
2173          value_type.IsString() ||
2174          value_type.IsBoolean() ||
2175          value_type.IsNonPrimitive())) {
2176       return NULL;
2177     }
2178     return this;
2179   }
2180 
2181   DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi)
2182 
2183  protected:
2184   virtual bool DataEquals(HValue* other) { return true; }
2185 };
2186 
2187 
2188 class HCheckPrototypeMaps: public HTemplateInstruction<0> {
2189  public:
2190   HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
2191       : prototype_(prototype), holder_(holder) {
2192     SetFlag(kUseGVN);
2193     SetGVNFlag(kDependsOnMaps);
2194   }
2195 
2196 #ifdef DEBUG
2197   virtual void Verify();
2198 #endif
2199 
2200   Handle<JSObject> prototype() const { return prototype_; }
2201   Handle<JSObject> holder() const { return holder_; }
2202 
2203   DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps)
2204 
2205   virtual Representation RequiredInputRepresentation(int index) {
2206     return Representation::None();
2207   }
2208 
2209   virtual intptr_t Hashcode() {
2210     ASSERT(!HEAP->IsAllocationAllowed());
2211     intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
2212     hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
2213     return hash;
2214   }
2215 
2216  protected:
2217   virtual bool DataEquals(HValue* other) {
2218     HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
2219     return prototype_.is_identical_to(b->prototype()) &&
2220         holder_.is_identical_to(b->holder());
2221   }
2222 
2223  private:
2224   Handle<JSObject> prototype_;
2225   Handle<JSObject> holder_;
2226 };
2227 
2228 
2229 class HCheckSmi: public HUnaryOperation {
2230  public:
2231   explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
2232     set_representation(Representation::Tagged());
2233     SetFlag(kUseGVN);
2234   }
2235 
2236   virtual Representation RequiredInputRepresentation(int index) {
2237     return Representation::Tagged();
2238   }
2239   virtual HType CalculateInferredType();
2240 
2241 #ifdef DEBUG
2242   virtual void Verify();
2243 #endif
2244 
2245   DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
2246 
2247  protected:
2248   virtual bool DataEquals(HValue* other) { return true; }
2249 };
2250 
2251 
2252 class HPhi: public HValue {
2253  public:
2254   explicit HPhi(int merged_index)
2255       : inputs_(2),
2256         merged_index_(merged_index),
2257         phi_id_(-1),
2258         is_live_(false),
2259         is_convertible_to_integer_(true) {
2260     for (int i = 0; i < Representation::kNumRepresentations; i++) {
2261       non_phi_uses_[i] = 0;
2262       indirect_uses_[i] = 0;
2263     }
2264     ASSERT(merged_index >= 0);
2265     set_representation(Representation::Tagged());
2266     SetFlag(kFlexibleRepresentation);
2267   }
2268 
2269   virtual Representation InferredRepresentation();
2270 
2271   virtual Range* InferRange(Zone* zone);
2272   virtual Representation RequiredInputRepresentation(int index) {
2273     return representation();
2274   }
2275   virtual HType CalculateInferredType();
2276   virtual int OperandCount() { return inputs_.length(); }
2277   virtual HValue* OperandAt(int index) { return inputs_[index]; }
2278   HValue* GetRedundantReplacement();
2279   void AddInput(HValue* value);
2280   bool HasRealUses();
2281 
2282   bool IsReceiver() { return merged_index_ == 0; }
2283 
2284   int merged_index() const { return merged_index_; }
2285 
2286   virtual void PrintTo(StringStream* stream);
2287 
2288 #ifdef DEBUG
2289   virtual void Verify();
2290 #endif
2291 
2292   void InitRealUses(int id);
2293   void AddNonPhiUsesFrom(HPhi* other);
2294   void AddIndirectUsesTo(int* use_count);
2295 
2296   int tagged_non_phi_uses() const {
2297     return non_phi_uses_[Representation::kTagged];
2298   }
2299   int int32_non_phi_uses() const {
2300     return non_phi_uses_[Representation::kInteger32];
2301   }
2302   int double_non_phi_uses() const {
2303     return non_phi_uses_[Representation::kDouble];
2304   }
2305   int tagged_indirect_uses() const {
2306     return indirect_uses_[Representation::kTagged];
2307   }
2308   int int32_indirect_uses() const {
2309     return indirect_uses_[Representation::kInteger32];
2310   }
2311   int double_indirect_uses() const {
2312     return indirect_uses_[Representation::kDouble];
2313   }
2314   int phi_id() { return phi_id_; }
2315   bool is_live() { return is_live_; }
2316   void set_is_live(bool b) { is_live_ = b; }
2317 
2318   static HPhi* cast(HValue* value) {
2319     ASSERT(value->IsPhi());
2320     return reinterpret_cast<HPhi*>(value);
2321   }
2322   virtual Opcode opcode() const { return HValue::kPhi; }
2323 
2324   virtual bool IsConvertibleToInteger() const {
2325     return is_convertible_to_integer_;
2326   }
2327 
2328   void set_is_convertible_to_integer(bool b) {
2329     is_convertible_to_integer_ = b;
2330   }
2331 
2332   bool AllOperandsConvertibleToInteger() {
2333     for (int i = 0; i < OperandCount(); ++i) {
2334       if (!OperandAt(i)->IsConvertibleToInteger()) return false;
2335     }
2336     return true;
2337   }
2338 
2339  protected:
2340   virtual void DeleteFromGraph();
2341   virtual void InternalSetOperandAt(int index, HValue* value) {
2342     inputs_[index] = value;
2343   }
2344 
2345  private:
2346   ZoneList<HValue*> inputs_;
2347   int merged_index_;
2348 
2349   int non_phi_uses_[Representation::kNumRepresentations];
2350   int indirect_uses_[Representation::kNumRepresentations];
2351   int phi_id_;
2352   bool is_live_;
2353   bool is_convertible_to_integer_;
2354 };
2355 
2356 
2357 class HArgumentsObject: public HTemplateInstruction<0> {
2358  public:
2359   HArgumentsObject() {
2360     set_representation(Representation::Tagged());
2361     SetFlag(kIsArguments);
2362   }
2363 
2364   virtual Representation RequiredInputRepresentation(int index) {
2365     return Representation::None();
2366   }
2367 
2368   DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
2369 };
2370 
2371 
2372 class HConstant: public HTemplateInstruction<0> {
2373  public:
2374   HConstant(Handle<Object> handle, Representation r);
2375 
2376   Handle<Object> handle() const { return handle_; }
2377 
2378   bool InOldSpace() const { return !HEAP->InNewSpace(*handle_); }
2379 
2380   bool ImmortalImmovable() const {
2381     Heap* heap = HEAP;
2382     if (*handle_ == heap->undefined_value()) return true;
2383     if (*handle_ == heap->null_value()) return true;
2384     if (*handle_ == heap->true_value()) return true;
2385     if (*handle_ == heap->false_value()) return true;
2386     if (*handle_ == heap->the_hole_value()) return true;
2387     if (*handle_ == heap->minus_zero_value()) return true;
2388     if (*handle_ == heap->nan_value()) return true;
2389     if (*handle_ == heap->empty_string()) return true;
2390     return false;
2391   }
2392 
2393   virtual Representation RequiredInputRepresentation(int index) {
2394     return Representation::None();
2395   }
2396 
2397   virtual bool IsConvertibleToInteger() const {
2398     if (handle_->IsSmi()) return true;
2399     if (handle_->IsHeapNumber() &&
2400         (HeapNumber::cast(*handle_)->value() ==
2401          static_cast<double>(NumberToInt32(*handle_)))) return true;
2402     return false;
2403   }
2404 
2405   virtual bool EmitAtUses() { return !representation().IsDouble(); }
2406   virtual HValue* Canonicalize();
2407   virtual void PrintDataTo(StringStream* stream);
2408   virtual HType CalculateInferredType();
2409   bool IsInteger() const { return handle_->IsSmi(); }
2410   HConstant* CopyToRepresentation(Representation r) const;
2411   HConstant* CopyToTruncatedInt32() const;
2412   bool HasInteger32Value() const { return has_int32_value_; }
2413   int32_t Integer32Value() const {
2414     ASSERT(HasInteger32Value());
2415     return int32_value_;
2416   }
2417   bool HasDoubleValue() const { return has_double_value_; }
2418   double DoubleValue() const {
2419     ASSERT(HasDoubleValue());
2420     return double_value_;
2421   }
2422   bool HasNumberValue() const { return has_int32_value_ || has_double_value_; }
2423   int32_t NumberValueAsInteger32() const {
2424     ASSERT(HasNumberValue());
2425     if (has_int32_value_) return int32_value_;
2426     return DoubleToInt32(double_value_);
2427   }
2428   bool HasStringValue() const { return handle_->IsString(); }
2429 
2430   bool ToBoolean() const;
2431 
2432   virtual intptr_t Hashcode() {
2433     ASSERT(!HEAP->allow_allocation(false));
2434     intptr_t hash = reinterpret_cast<intptr_t>(*handle());
2435     // Prevent smis from having fewer hash values when truncated to
2436     // the least significant bits.
2437     const int kShiftSize = kSmiShiftSize + kSmiTagSize;
2438     STATIC_ASSERT(kShiftSize != 0);
2439     return hash ^ (hash >> kShiftSize);
2440   }
2441 
2442 #ifdef DEBUG
2443   virtual void Verify() { }
2444 #endif
2445 
2446   DECLARE_CONCRETE_INSTRUCTION(Constant)
2447 
2448  protected:
2449   virtual Range* InferRange(Zone* zone);
2450 
2451   virtual bool DataEquals(HValue* other) {
2452     HConstant* other_constant = HConstant::cast(other);
2453     return handle().is_identical_to(other_constant->handle());
2454   }
2455 
2456  private:
2457   Handle<Object> handle_;
2458 
2459   // The following two values represent the int32 and the double value of the
2460   // given constant if there is a lossless conversion between the constant
2461   // and the specific representation.
2462   bool has_int32_value_ : 1;
2463   bool has_double_value_ : 1;
2464   int32_t int32_value_;
2465   double double_value_;
2466 };
2467 
2468 
2469 class HBinaryOperation: public HTemplateInstruction<3> {
2470  public:
2471   HBinaryOperation(HValue* context, HValue* left, HValue* right) {
2472     ASSERT(left != NULL && right != NULL);
2473     SetOperandAt(0, context);
2474     SetOperandAt(1, left);
2475     SetOperandAt(2, right);
2476   }
2477 
2478   HValue* context() { return OperandAt(0); }
2479   HValue* left() { return OperandAt(1); }
2480   HValue* right() { return OperandAt(2); }
2481 
2482   // TODO(kasperl): Move these helpers to the IA-32 Lithium
2483   // instruction sequence builder.
2484   HValue* LeastConstantOperand() {
2485     if (IsCommutative() && left()->IsConstant()) return right();
2486     return left();
2487   }
2488   HValue* MostConstantOperand() {
2489     if (IsCommutative() && left()->IsConstant()) return left();
2490     return right();
2491   }
2492 
2493   virtual bool IsCommutative() const { return false; }
2494 
2495   virtual void PrintDataTo(StringStream* stream);
2496 };
2497 
2498 
2499 class HWrapReceiver: public HTemplateInstruction<2> {
2500  public:
2501   HWrapReceiver(HValue* receiver, HValue* function) {
2502     set_representation(Representation::Tagged());
2503     SetOperandAt(0, receiver);
2504     SetOperandAt(1, function);
2505   }
2506 
2507   virtual Representation RequiredInputRepresentation(int index) {
2508     return Representation::Tagged();
2509   }
2510 
2511   HValue* receiver() { return OperandAt(0); }
2512   HValue* function() { return OperandAt(1); }
2513 
2514   virtual HValue* Canonicalize();
2515 
2516   DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
2517 };
2518 
2519 
2520 class HApplyArguments: public HTemplateInstruction<4> {
2521  public:
2522   HApplyArguments(HValue* function,
2523                   HValue* receiver,
2524                   HValue* length,
2525                   HValue* elements) {
2526     set_representation(Representation::Tagged());
2527     SetOperandAt(0, function);
2528     SetOperandAt(1, receiver);
2529     SetOperandAt(2, length);
2530     SetOperandAt(3, elements);
2531     SetAllSideEffects();
2532   }
2533 
2534   virtual Representation RequiredInputRepresentation(int index) {
2535     // The length is untagged, all other inputs are tagged.
2536     return (index == 2)
2537         ? Representation::Integer32()
2538         : Representation::Tagged();
2539   }
2540 
2541   HValue* function() { return OperandAt(0); }
2542   HValue* receiver() { return OperandAt(1); }
2543   HValue* length() { return OperandAt(2); }
2544   HValue* elements() { return OperandAt(3); }
2545 
2546   DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
2547 };
2548 
2549 
2550 class HArgumentsElements: public HTemplateInstruction<0> {
2551  public:
2552   HArgumentsElements() {
2553     // The value produced by this instruction is a pointer into the stack
2554     // that looks as if it was a smi because of alignment.
2555     set_representation(Representation::Tagged());
2556     SetFlag(kUseGVN);
2557   }
2558 
2559   DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
2560 
2561   virtual Representation RequiredInputRepresentation(int index) {
2562     return Representation::None();
2563   }
2564 
2565  protected:
2566   virtual bool DataEquals(HValue* other) { return true; }
2567 };
2568 
2569 
2570 class HArgumentsLength: public HUnaryOperation {
2571  public:
2572   explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
2573     set_representation(Representation::Integer32());
2574     SetFlag(kUseGVN);
2575   }
2576 
2577   virtual Representation RequiredInputRepresentation(int index) {
2578     return Representation::Tagged();
2579   }
2580 
2581   DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
2582 
2583  protected:
2584   virtual bool DataEquals(HValue* other) { return true; }
2585 };
2586 
2587 
2588 class HAccessArgumentsAt: public HTemplateInstruction<3> {
2589  public:
2590   HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
2591     set_representation(Representation::Tagged());
2592     SetFlag(kUseGVN);
2593     SetOperandAt(0, arguments);
2594     SetOperandAt(1, length);
2595     SetOperandAt(2, index);
2596   }
2597 
2598   virtual void PrintDataTo(StringStream* stream);
2599 
2600   virtual Representation RequiredInputRepresentation(int index) {
2601     // The arguments elements is considered tagged.
2602     return index == 0
2603         ? Representation::Tagged()
2604         : Representation::Integer32();
2605   }
2606 
2607   HValue* arguments() { return OperandAt(0); }
2608   HValue* length() { return OperandAt(1); }
2609   HValue* index() { return OperandAt(2); }
2610 
2611   DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
2612 
2613   virtual bool DataEquals(HValue* other) { return true; }
2614 };
2615 
2616 
2617 class HBoundsCheck: public HTemplateInstruction<2> {
2618  public:
2619   HBoundsCheck(HValue* index, HValue* length) {
2620     SetOperandAt(0, index);
2621     SetOperandAt(1, length);
2622     set_representation(Representation::Integer32());
2623     SetFlag(kUseGVN);
2624   }
2625 
2626   virtual Representation RequiredInputRepresentation(int index) {
2627     return Representation::Integer32();
2628   }
2629 
2630   virtual void PrintDataTo(StringStream* stream);
2631 
2632   HValue* index() { return OperandAt(0); }
2633   HValue* length() { return OperandAt(1); }
2634 
2635   DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
2636 
2637  protected:
2638   virtual bool DataEquals(HValue* other) { return true; }
2639 };
2640 
2641 
2642 class HBitwiseBinaryOperation: public HBinaryOperation {
2643  public:
2644   HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right)
2645       : HBinaryOperation(context, left, right) {
2646     set_representation(Representation::Tagged());
2647     SetFlag(kFlexibleRepresentation);
2648     SetAllSideEffects();
2649   }
2650 
2651   virtual Representation RequiredInputRepresentation(int index) {
2652     return index == 0
2653         ? Representation::Tagged()
2654         : representation();
2655   }
2656 
2657   virtual void RepresentationChanged(Representation to) {
2658     if (!to.IsTagged()) {
2659       ASSERT(to.IsInteger32());
2660       ClearAllSideEffects();
2661       SetFlag(kTruncatingToInt32);
2662       SetFlag(kUseGVN);
2663     }
2664   }
2665 
2666   virtual HType CalculateInferredType();
2667 
2668   DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
2669 };
2670 
2671 
2672 class HArithmeticBinaryOperation: public HBinaryOperation {
2673  public:
2674   HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right)
2675       : HBinaryOperation(context, left, right) {
2676     set_representation(Representation::Tagged());
2677     SetFlag(kFlexibleRepresentation);
2678     SetAllSideEffects();
2679   }
2680 
2681   virtual void RepresentationChanged(Representation to) {
2682     if (!to.IsTagged()) {
2683       ClearAllSideEffects();
2684       SetFlag(kUseGVN);
2685     }
2686   }
2687 
2688   virtual HType CalculateInferredType();
2689   virtual Representation RequiredInputRepresentation(int index) {
2690     return index == 0
2691         ? Representation::Tagged()
2692         : representation();
2693   }
2694 
2695   virtual Representation InferredRepresentation() {
2696     if (left()->representation().Equals(right()->representation())) {
2697       return left()->representation();
2698     }
2699     return HValue::InferredRepresentation();
2700   }
2701 };
2702 
2703 
2704 class HCompareGeneric: public HBinaryOperation {
2705  public:
2706   HCompareGeneric(HValue* context,
2707                   HValue* left,
2708                   HValue* right,
2709                   Token::Value token)
2710       : HBinaryOperation(context, left, right), token_(token) {
2711     ASSERT(Token::IsCompareOp(token));
2712     set_representation(Representation::Tagged());
2713     SetAllSideEffects();
2714   }
2715 
2716   virtual Representation RequiredInputRepresentation(int index) {
2717     return Representation::Tagged();
2718   }
2719 
2720   Representation GetInputRepresentation() const {
2721     return Representation::Tagged();
2722   }
2723 
2724   Token::Value token() const { return token_; }
2725   virtual void PrintDataTo(StringStream* stream);
2726 
2727   virtual HType CalculateInferredType();
2728 
2729   DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
2730 
2731  private:
2732   Token::Value token_;
2733 };
2734 
2735 
2736 class HCompareIDAndBranch: public HTemplateControlInstruction<2, 2> {
2737  public:
2738   HCompareIDAndBranch(HValue* left, HValue* right, Token::Value token)
2739       : token_(token) {
2740     ASSERT(Token::IsCompareOp(token));
2741     SetOperandAt(0, left);
2742     SetOperandAt(1, right);
2743   }
2744 
2745   HValue* left() { return OperandAt(0); }
2746   HValue* right() { return OperandAt(1); }
2747   Token::Value token() const { return token_; }
2748 
2749   void SetInputRepresentation(Representation r);
2750   Representation GetInputRepresentation() const {
2751     return input_representation_;
2752   }
2753 
2754   virtual Representation RequiredInputRepresentation(int index) {
2755     return input_representation_;
2756   }
2757   virtual void PrintDataTo(StringStream* stream);
2758 
2759   DECLARE_CONCRETE_INSTRUCTION(CompareIDAndBranch)
2760 
2761  private:
2762   Representation input_representation_;
2763   Token::Value token_;
2764 };
2765 
2766 
2767 class HCompareObjectEqAndBranch: public HTemplateControlInstruction<2, 2> {
2768  public:
2769   HCompareObjectEqAndBranch(HValue* left, HValue* right) {
2770     SetOperandAt(0, left);
2771     SetOperandAt(1, right);
2772   }
2773 
2774   HValue* left() { return OperandAt(0); }
2775   HValue* right() { return OperandAt(1); }
2776 
2777   virtual void PrintDataTo(StringStream* stream);
2778 
2779   virtual Representation RequiredInputRepresentation(int index) {
2780     return Representation::Tagged();
2781   }
2782 
2783   DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
2784 };
2785 
2786 
2787 class HCompareConstantEqAndBranch: public HUnaryControlInstruction {
2788  public:
2789   HCompareConstantEqAndBranch(HValue* left, int right, Token::Value op)
2790       : HUnaryControlInstruction(left, NULL, NULL), op_(op), right_(right) {
2791     ASSERT(op == Token::EQ_STRICT);
2792   }
2793 
2794   Token::Value op() const { return op_; }
2795   HValue* left() { return value(); }
2796   int right() const { return right_; }
2797 
2798   virtual Representation RequiredInputRepresentation(int index) {
2799     return Representation::Integer32();
2800   }
2801 
2802   DECLARE_CONCRETE_INSTRUCTION(CompareConstantEqAndBranch);
2803 
2804  private:
2805   const Token::Value op_;
2806   const int right_;
2807 };
2808 
2809 
2810 class HIsNilAndBranch: public HUnaryControlInstruction {
2811  public:
2812   HIsNilAndBranch(HValue* value, EqualityKind kind, NilValue nil)
2813       : HUnaryControlInstruction(value, NULL, NULL), kind_(kind), nil_(nil) { }
2814 
2815   EqualityKind kind() const { return kind_; }
2816   NilValue nil() const { return nil_; }
2817 
2818   virtual void PrintDataTo(StringStream* stream);
2819 
2820   virtual Representation RequiredInputRepresentation(int index) {
2821     return Representation::Tagged();
2822   }
2823 
2824   DECLARE_CONCRETE_INSTRUCTION(IsNilAndBranch)
2825 
2826  private:
2827   EqualityKind kind_;
2828   NilValue nil_;
2829 };
2830 
2831 
2832 class HIsObjectAndBranch: public HUnaryControlInstruction {
2833  public:
2834   explicit HIsObjectAndBranch(HValue* value)
2835     : HUnaryControlInstruction(value, NULL, NULL) { }
2836 
2837   virtual Representation RequiredInputRepresentation(int index) {
2838     return Representation::Tagged();
2839   }
2840 
2841   DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch)
2842 };
2843 
2844 class HIsStringAndBranch: public HUnaryControlInstruction {
2845  public:
2846   explicit HIsStringAndBranch(HValue* value)
2847     : HUnaryControlInstruction(value, NULL, NULL) { }
2848 
2849   virtual Representation RequiredInputRepresentation(int index) {
2850     return Representation::Tagged();
2851   }
2852 
2853   DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
2854 };
2855 
2856 
2857 class HIsSmiAndBranch: public HUnaryControlInstruction {
2858  public:
2859   explicit HIsSmiAndBranch(HValue* value)
2860       : HUnaryControlInstruction(value, NULL, NULL) { }
2861 
2862   DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
2863 
2864   virtual Representation RequiredInputRepresentation(int index) {
2865     return Representation::Tagged();
2866   }
2867 
2868  protected:
2869   virtual bool DataEquals(HValue* other) { return true; }
2870 };
2871 
2872 
2873 class HIsUndetectableAndBranch: public HUnaryControlInstruction {
2874  public:
2875   explicit HIsUndetectableAndBranch(HValue* value)
2876       : HUnaryControlInstruction(value, NULL, NULL) { }
2877 
2878   virtual Representation RequiredInputRepresentation(int index) {
2879     return Representation::Tagged();
2880   }
2881 
2882   DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
2883 };
2884 
2885 
2886 class HStringCompareAndBranch: public HTemplateControlInstruction<2, 3> {
2887  public:
2888   HStringCompareAndBranch(HValue* context,
2889                            HValue* left,
2890                            HValue* right,
2891                            Token::Value token)
2892       : token_(token) {
2893     ASSERT(Token::IsCompareOp(token));
2894     SetOperandAt(0, context);
2895     SetOperandAt(1, left);
2896     SetOperandAt(2, right);
2897     set_representation(Representation::Tagged());
2898   }
2899 
2900   HValue* context() { return OperandAt(0); }
2901   HValue* left() { return OperandAt(1); }
2902   HValue* right() { return OperandAt(2); }
2903   Token::Value token() const { return token_; }
2904 
2905   virtual void PrintDataTo(StringStream* stream);
2906 
2907   virtual Representation RequiredInputRepresentation(int index) {
2908     return Representation::Tagged();
2909   }
2910 
2911   Representation GetInputRepresentation() const {
2912     return Representation::Tagged();
2913   }
2914 
2915   DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
2916 
2917  private:
2918   Token::Value token_;
2919 };
2920 
2921 
2922 class HIsConstructCallAndBranch: public HTemplateControlInstruction<2, 0> {
2923  public:
2924   virtual Representation RequiredInputRepresentation(int index) {
2925     return Representation::None();
2926   }
2927 
2928   DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch)
2929 };
2930 
2931 
2932 class HHasInstanceTypeAndBranch: public HUnaryControlInstruction {
2933  public:
2934   HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
2935       : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
2936   HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
2937       : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
2938     ASSERT(to == LAST_TYPE);  // Others not implemented yet in backend.
2939   }
2940 
2941   InstanceType from() { return from_; }
2942   InstanceType to() { return to_; }
2943 
2944   virtual void PrintDataTo(StringStream* stream);
2945 
2946   virtual Representation RequiredInputRepresentation(int index) {
2947     return Representation::Tagged();
2948   }
2949 
2950   DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
2951 
2952  private:
2953   InstanceType from_;
2954   InstanceType to_;  // Inclusive range, not all combinations work.
2955 };
2956 
2957 
2958 class HHasCachedArrayIndexAndBranch: public HUnaryControlInstruction {
2959  public:
2960   explicit HHasCachedArrayIndexAndBranch(HValue* value)
2961       : HUnaryControlInstruction(value, NULL, NULL) { }
2962 
2963   virtual Representation RequiredInputRepresentation(int index) {
2964     return Representation::Tagged();
2965   }
2966 
2967   DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
2968 };
2969 
2970 
2971 class HGetCachedArrayIndex: public HUnaryOperation {
2972  public:
2973   explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
2974     set_representation(Representation::Tagged());
2975     SetFlag(kUseGVN);
2976   }
2977 
2978   virtual Representation RequiredInputRepresentation(int index) {
2979     return Representation::Tagged();
2980   }
2981 
2982   DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
2983 
2984  protected:
2985   virtual bool DataEquals(HValue* other) { return true; }
2986 };
2987 
2988 
2989 class HClassOfTestAndBranch: public HUnaryControlInstruction {
2990  public:
2991   HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
2992       : HUnaryControlInstruction(value, NULL, NULL),
2993         class_name_(class_name) { }
2994 
2995   DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
2996 
2997   virtual Representation RequiredInputRepresentation(int index) {
2998     return Representation::Tagged();
2999   }
3000 
3001   virtual void PrintDataTo(StringStream* stream);
3002 
3003   Handle<String> class_name() const { return class_name_; }
3004 
3005  private:
3006   Handle<String> class_name_;
3007 };
3008 
3009 
3010 class HTypeofIsAndBranch: public HUnaryControlInstruction {
3011  public:
3012   HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
3013       : HUnaryControlInstruction(value, NULL, NULL),
3014         type_literal_(type_literal) { }
3015 
3016   Handle<String> type_literal() { return type_literal_; }
3017   virtual void PrintDataTo(StringStream* stream);
3018 
3019   DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
3020 
3021   virtual Representation RequiredInputRepresentation(int index) {
3022     return Representation::Tagged();
3023   }
3024 
3025  private:
3026   Handle<String> type_literal_;
3027 };
3028 
3029 
3030 class HInstanceOf: public HBinaryOperation {
3031  public:
3032   HInstanceOf(HValue* context, HValue* left, HValue* right)
3033       : HBinaryOperation(context, left, right) {
3034     set_representation(Representation::Tagged());
3035     SetAllSideEffects();
3036   }
3037 
3038   virtual Representation RequiredInputRepresentation(int index) {
3039     return Representation::Tagged();
3040   }
3041 
3042   virtual HType CalculateInferredType();
3043 
3044   virtual void PrintDataTo(StringStream* stream);
3045 
3046   DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
3047 };
3048 
3049 
3050 class HInstanceOfKnownGlobal: public HTemplateInstruction<2> {
3051  public:
3052   HInstanceOfKnownGlobal(HValue* context,
3053                          HValue* left,
3054                          Handle<JSFunction> right)
3055       : function_(right) {
3056     SetOperandAt(0, context);
3057     SetOperandAt(1, left);
3058     set_representation(Representation::Tagged());
3059     SetAllSideEffects();
3060   }
3061 
3062   HValue* context() { return OperandAt(0); }
3063   HValue* left() { return OperandAt(1); }
3064   Handle<JSFunction> function() { return function_; }
3065 
3066   virtual Representation RequiredInputRepresentation(int index) {
3067     return Representation::Tagged();
3068   }
3069 
3070   virtual HType CalculateInferredType();
3071 
3072   DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal)
3073 
3074  private:
3075   Handle<JSFunction> function_;
3076 };
3077 
3078 
3079 class HPower: public HTemplateInstruction<2> {
3080  public:
3081   HPower(HValue* left, HValue* right) {
3082     SetOperandAt(0, left);
3083     SetOperandAt(1, right);
3084     set_representation(Representation::Double());
3085     SetFlag(kUseGVN);
3086   }
3087 
3088   HValue* left() { return OperandAt(0); }
3089   HValue* right() { return OperandAt(1); }
3090 
3091   virtual Representation RequiredInputRepresentation(int index) {
3092     return index == 0
3093       ? Representation::Double()
3094       : Representation::None();
3095   }
3096 
3097   DECLARE_CONCRETE_INSTRUCTION(Power)
3098 
3099  protected:
3100   virtual bool DataEquals(HValue* other) { return true; }
3101 };
3102 
3103 
3104 class HRandom: public HTemplateInstruction<1> {
3105  public:
3106   explicit HRandom(HValue* global_object) {
3107     SetOperandAt(0, global_object);
3108     set_representation(Representation::Double());
3109   }
3110 
3111   HValue* global_object() { return OperandAt(0); }
3112 
3113   virtual Representation RequiredInputRepresentation(int index) {
3114     return Representation::Tagged();
3115   }
3116 
3117   DECLARE_CONCRETE_INSTRUCTION(Random)
3118 };
3119 
3120 
3121 class HAdd: public HArithmeticBinaryOperation {
3122  public:
3123   HAdd(HValue* context, HValue* left, HValue* right)
3124       : HArithmeticBinaryOperation(context, left, right) {
3125     SetFlag(kCanOverflow);
3126   }
3127 
3128   // Add is only commutative if two integer values are added and not if two
3129   // tagged values are added (because it might be a String concatenation).
3130   virtual bool IsCommutative() const {
3131     return !representation().IsTagged();
3132   }
3133 
3134   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3135 
3136   static HInstruction* NewHAdd(Zone* zone,
3137                                HValue* context,
3138                                HValue* left,
3139                                HValue* right);
3140 
3141   virtual HType CalculateInferredType();
3142 
3143   virtual HValue* Canonicalize();
3144 
3145   DECLARE_CONCRETE_INSTRUCTION(Add)
3146 
3147  protected:
3148   virtual bool DataEquals(HValue* other) { return true; }
3149 
3150   virtual Range* InferRange(Zone* zone);
3151 };
3152 
3153 
3154 class HSub: public HArithmeticBinaryOperation {
3155  public:
3156   HSub(HValue* context, HValue* left, HValue* right)
3157       : HArithmeticBinaryOperation(context, left, right) {
3158     SetFlag(kCanOverflow);
3159   }
3160 
3161   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3162 
3163   virtual HValue* Canonicalize();
3164 
3165   static HInstruction* NewHSub(Zone* zone,
3166                               HValue* context,
3167                               HValue* left,
3168                               HValue* right);
3169 
3170   DECLARE_CONCRETE_INSTRUCTION(Sub)
3171 
3172  protected:
3173   virtual bool DataEquals(HValue* other) { return true; }
3174 
3175   virtual Range* InferRange(Zone* zone);
3176 };
3177 
3178 
3179 class HMul: public HArithmeticBinaryOperation {
3180  public:
3181   HMul(HValue* context, HValue* left, HValue* right)
3182       : HArithmeticBinaryOperation(context, left, right) {
3183     SetFlag(kCanOverflow);
3184   }
3185 
3186   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3187 
3188   // Only commutative if it is certain that not two objects are multiplicated.
3189   virtual bool IsCommutative() const {
3190     return !representation().IsTagged();
3191   }
3192 
3193   static HInstruction* NewHMul(Zone* zone,
3194                                HValue* context,
3195                                HValue* left,
3196                                HValue* right);
3197 
3198   DECLARE_CONCRETE_INSTRUCTION(Mul)
3199 
3200  protected:
3201   virtual bool DataEquals(HValue* other) { return true; }
3202 
3203   virtual Range* InferRange(Zone* zone);
3204 };
3205 
3206 
3207 class HMod: public HArithmeticBinaryOperation {
3208  public:
3209   HMod(HValue* context, HValue* left, HValue* right)
3210       : HArithmeticBinaryOperation(context, left, right) {
3211     SetFlag(kCanBeDivByZero);
3212   }
3213 
3214   bool HasPowerOf2Divisor() {
3215     if (right()->IsConstant() &&
3216         HConstant::cast(right())->HasInteger32Value()) {
3217       int32_t value = HConstant::cast(right())->Integer32Value();
3218       return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
3219     }
3220 
3221     return false;
3222   }
3223 
3224   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3225 
3226   static HInstruction* NewHMod(Zone* zone,
3227                                HValue* context,
3228                                HValue* left,
3229                                HValue* right);
3230 
3231   DECLARE_CONCRETE_INSTRUCTION(Mod)
3232 
3233  protected:
3234   virtual bool DataEquals(HValue* other) { return true; }
3235 
3236   virtual Range* InferRange(Zone* zone);
3237 };
3238 
3239 
3240 class HDiv: public HArithmeticBinaryOperation {
3241  public:
3242   HDiv(HValue* context, HValue* left, HValue* right)
3243       : HArithmeticBinaryOperation(context, left, right) {
3244     SetFlag(kCanBeDivByZero);
3245     SetFlag(kCanOverflow);
3246   }
3247 
3248   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3249 
3250   static HInstruction* NewHDiv(Zone* zone,
3251                                HValue* context,
3252                                HValue* left,
3253                                HValue* right);
3254 
3255   DECLARE_CONCRETE_INSTRUCTION(Div)
3256 
3257  protected:
3258   virtual bool DataEquals(HValue* other) { return true; }
3259 
3260   virtual Range* InferRange(Zone* zone);
3261 };
3262 
3263 
3264 class HBitwise: public HBitwiseBinaryOperation {
3265  public:
3266   HBitwise(Token::Value op, HValue* context, HValue* left, HValue* right)
3267       : HBitwiseBinaryOperation(context, left, right), op_(op) {
3268         ASSERT(op == Token::BIT_AND ||
3269                op == Token::BIT_OR ||
3270                op == Token::BIT_XOR);
3271       }
3272 
3273   Token::Value op() const { return op_; }
3274 
3275   virtual bool IsCommutative() const { return true; }
3276 
3277   virtual HValue* Canonicalize();
3278 
3279   static HInstruction* NewHBitwise(Zone* zone,
3280                                    Token::Value op,
3281                                    HValue* context,
3282                                    HValue* left,
3283                                    HValue* right);
3284 
3285   DECLARE_CONCRETE_INSTRUCTION(Bitwise)
3286 
3287  protected:
3288   virtual bool DataEquals(HValue* other) {
3289     return op() == HBitwise::cast(other)->op();
3290   }
3291 
3292   virtual Range* InferRange(Zone* zone);
3293 
3294  private:
3295   Token::Value op_;
3296 };
3297 
3298 
3299 class HShl: public HBitwiseBinaryOperation {
3300  public:
3301   HShl(HValue* context, HValue* left, HValue* right)
3302       : HBitwiseBinaryOperation(context, left, right) { }
3303 
3304   virtual Range* InferRange(Zone* zone);
3305 
3306   static HInstruction* NewHShl(Zone* zone,
3307                                HValue* context,
3308                                HValue* left,
3309                                HValue* right);
3310 
3311   DECLARE_CONCRETE_INSTRUCTION(Shl)
3312 
3313  protected:
3314   virtual bool DataEquals(HValue* other) { return true; }
3315 };
3316 
3317 
3318 class HShr: public HBitwiseBinaryOperation {
3319  public:
3320   HShr(HValue* context, HValue* left, HValue* right)
3321       : HBitwiseBinaryOperation(context, left, right) { }
3322 
3323   virtual Range* InferRange(Zone* zone);
3324 
3325   static HInstruction* NewHShr(Zone* zone,
3326                                HValue* context,
3327                                HValue* left,
3328                                HValue* right);
3329 
3330   DECLARE_CONCRETE_INSTRUCTION(Shr)
3331 
3332  protected:
3333   virtual bool DataEquals(HValue* other) { return true; }
3334 };
3335 
3336 
3337 class HSar: public HBitwiseBinaryOperation {
3338  public:
3339   HSar(HValue* context, HValue* left, HValue* right)
3340       : HBitwiseBinaryOperation(context, left, right) { }
3341 
3342   virtual Range* InferRange(Zone* zone);
3343 
3344   static HInstruction* NewHSar(Zone* zone,
3345                                HValue* context,
3346                                HValue* left,
3347                                HValue* right);
3348 
3349   DECLARE_CONCRETE_INSTRUCTION(Sar)
3350 
3351  protected:
3352   virtual bool DataEquals(HValue* other) { return true; }
3353 };
3354 
3355 
3356 class HOsrEntry: public HTemplateInstruction<0> {
3357  public:
3358   explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
3359     SetGVNFlag(kChangesOsrEntries);
3360   }
3361 
3362   int ast_id() const { return ast_id_; }
3363 
3364   virtual Representation RequiredInputRepresentation(int index) {
3365     return Representation::None();
3366   }
3367 
3368   DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
3369 
3370  private:
3371   int ast_id_;
3372 };
3373 
3374 
3375 class HParameter: public HTemplateInstruction<0> {
3376  public:
3377   explicit HParameter(unsigned index) : index_(index) {
3378     set_representation(Representation::Tagged());
3379   }
3380 
3381   unsigned index() const { return index_; }
3382 
3383   virtual void PrintDataTo(StringStream* stream);
3384 
3385   virtual Representation RequiredInputRepresentation(int index) {
3386     return Representation::None();
3387   }
3388 
3389   DECLARE_CONCRETE_INSTRUCTION(Parameter)
3390 
3391  private:
3392   unsigned index_;
3393 };
3394 
3395 
3396 class HCallStub: public HUnaryCall {
3397  public:
3398   HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
3399       : HUnaryCall(context, argument_count),
3400         major_key_(major_key),
3401         transcendental_type_(TranscendentalCache::kNumberOfCaches) {
3402   }
3403 
3404   CodeStub::Major major_key() { return major_key_; }
3405 
3406   HValue* context() { return value(); }
3407 
3408   void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
3409     transcendental_type_ = transcendental_type;
3410   }
3411   TranscendentalCache::Type transcendental_type() {
3412     return transcendental_type_;
3413   }
3414 
3415   virtual void PrintDataTo(StringStream* stream);
3416 
3417   virtual Representation RequiredInputRepresentation(int index) {
3418     return Representation::Tagged();
3419   }
3420 
3421   DECLARE_CONCRETE_INSTRUCTION(CallStub)
3422 
3423  private:
3424   CodeStub::Major major_key_;
3425   TranscendentalCache::Type transcendental_type_;
3426 };
3427 
3428 
3429 class HUnknownOSRValue: public HTemplateInstruction<0> {
3430  public:
3431   HUnknownOSRValue()
3432       : incoming_value_(NULL) {
3433     set_representation(Representation::Tagged());
3434   }
3435 
3436   virtual Representation RequiredInputRepresentation(int index) {
3437     return Representation::None();
3438   }
3439 
3440   void set_incoming_value(HPhi* value) {
3441     incoming_value_ = value;
3442   }
3443 
3444   HPhi* incoming_value() {
3445     return incoming_value_;
3446   }
3447 
3448   DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
3449 
3450  private:
3451   HPhi* incoming_value_;
3452 };
3453 
3454 
3455 class HLoadGlobalCell: public HTemplateInstruction<0> {
3456  public:
3457   HLoadGlobalCell(Handle<JSGlobalPropertyCell> cell, PropertyDetails details)
3458       : cell_(cell), details_(details) {
3459     set_representation(Representation::Tagged());
3460     SetFlag(kUseGVN);
3461     SetGVNFlag(kDependsOnGlobalVars);
3462   }
3463 
3464   Handle<JSGlobalPropertyCell>  cell() const { return cell_; }
3465   bool RequiresHoleCheck();
3466 
3467   virtual void PrintDataTo(StringStream* stream);
3468 
3469   virtual intptr_t Hashcode() {
3470     ASSERT(!HEAP->allow_allocation(false));
3471     return reinterpret_cast<intptr_t>(*cell_);
3472   }
3473 
3474   virtual Representation RequiredInputRepresentation(int index) {
3475     return Representation::None();
3476   }
3477 
3478   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell)
3479 
3480  protected:
3481   virtual bool DataEquals(HValue* other) {
3482     HLoadGlobalCell* b = HLoadGlobalCell::cast(other);
3483     return cell_.is_identical_to(b->cell());
3484   }
3485 
3486  private:
3487   Handle<JSGlobalPropertyCell> cell_;
3488   PropertyDetails details_;
3489 };
3490 
3491 
3492 class HLoadGlobalGeneric: public HTemplateInstruction<2> {
3493  public:
3494   HLoadGlobalGeneric(HValue* context,
3495                      HValue* global_object,
3496                      Handle<Object> name,
3497                      bool for_typeof)
3498       : name_(name),
3499         for_typeof_(for_typeof) {
3500     SetOperandAt(0, context);
3501     SetOperandAt(1, global_object);
3502     set_representation(Representation::Tagged());
3503     SetAllSideEffects();
3504   }
3505 
3506   HValue* context() { return OperandAt(0); }
3507   HValue* global_object() { return OperandAt(1); }
3508   Handle<Object> name() const { return name_; }
3509   bool for_typeof() const { return for_typeof_; }
3510 
3511   virtual void PrintDataTo(StringStream* stream);
3512 
3513   virtual Representation RequiredInputRepresentation(int index) {
3514     return Representation::Tagged();
3515   }
3516 
3517   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
3518 
3519  private:
3520   Handle<Object> name_;
3521   bool for_typeof_;
3522 };
3523 
3524 
3525 inline bool StoringValueNeedsWriteBarrier(HValue* value) {
3526   return !value->type().IsBoolean()
3527       && !value->type().IsSmi()
3528       && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
3529 }
3530 
3531 
3532 class HStoreGlobalCell: public HUnaryOperation {
3533  public:
3534   HStoreGlobalCell(HValue* value,
3535                    Handle<JSGlobalPropertyCell> cell,
3536                    PropertyDetails details)
3537       : HUnaryOperation(value),
3538         cell_(cell),
3539         details_(details) {
3540     SetGVNFlag(kChangesGlobalVars);
3541   }
3542 
3543   Handle<JSGlobalPropertyCell> cell() const { return cell_; }
3544   bool RequiresHoleCheck() {
3545     return !details_.IsDontDelete() || details_.IsReadOnly();
3546   }
3547   bool NeedsWriteBarrier() {
3548     return StoringValueNeedsWriteBarrier(value());
3549   }
3550 
3551   virtual Representation RequiredInputRepresentation(int index) {
3552     return Representation::Tagged();
3553   }
3554   virtual void PrintDataTo(StringStream* stream);
3555 
3556   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell)
3557 
3558  private:
3559   Handle<JSGlobalPropertyCell> cell_;
3560   PropertyDetails details_;
3561 };
3562 
3563 
3564 class HStoreGlobalGeneric: public HTemplateInstruction<3> {
3565  public:
3566   HStoreGlobalGeneric(HValue* context,
3567                       HValue* global_object,
3568                       Handle<Object> name,
3569                       HValue* value,
3570                       StrictModeFlag strict_mode_flag)
3571       : name_(name),
3572         strict_mode_flag_(strict_mode_flag) {
3573     SetOperandAt(0, context);
3574     SetOperandAt(1, global_object);
3575     SetOperandAt(2, value);
3576     set_representation(Representation::Tagged());
3577     SetAllSideEffects();
3578   }
3579 
3580   HValue* context() { return OperandAt(0); }
3581   HValue* global_object() { return OperandAt(1); }
3582   Handle<Object> name() const { return name_; }
3583   HValue* value() { return OperandAt(2); }
3584   StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
3585 
3586   virtual void PrintDataTo(StringStream* stream);
3587 
3588   virtual Representation RequiredInputRepresentation(int index) {
3589     return Representation::Tagged();
3590   }
3591 
3592   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric)
3593 
3594  private:
3595   Handle<Object> name_;
3596   StrictModeFlag strict_mode_flag_;
3597 };
3598 
3599 
3600 class HLoadContextSlot: public HUnaryOperation {
3601  public:
3602   enum Mode {
3603     // Perform a normal load of the context slot without checking its value.
3604     kNoCheck,
3605     // Load and check the value of the context slot. Deoptimize if it's the
3606     // hole value. This is used for checking for loading of uninitialized
3607     // harmony bindings where we deoptimize into full-codegen generated code
3608     // which will subsequently throw a reference error.
3609     kCheckDeoptimize,
3610     // Load and check the value of the context slot. Return undefined if it's
3611     // the hole value. This is used for non-harmony const assignments
3612     kCheckReturnUndefined
3613   };
3614 
3615   HLoadContextSlot(HValue* context, Variable* var)
3616       : HUnaryOperation(context), slot_index_(var->index()) {
3617     ASSERT(var->IsContextSlot());
3618     switch (var->mode()) {
3619       case LET:
3620       case CONST_HARMONY:
3621         mode_ = kCheckDeoptimize;
3622         break;
3623       case CONST:
3624         mode_ = kCheckReturnUndefined;
3625         break;
3626       default:
3627         mode_ = kNoCheck;
3628     }
3629     set_representation(Representation::Tagged());
3630     SetFlag(kUseGVN);
3631     SetGVNFlag(kDependsOnContextSlots);
3632   }
3633 
3634   int slot_index() const { return slot_index_; }
3635   Mode mode() const { return mode_; }
3636 
3637   bool DeoptimizesOnHole() {
3638     return mode_ == kCheckDeoptimize;
3639   }
3640 
3641   bool RequiresHoleCheck() {
3642     return mode_ != kNoCheck;
3643   }
3644 
3645   virtual Representation RequiredInputRepresentation(int index) {
3646     return Representation::Tagged();
3647   }
3648 
3649   virtual void PrintDataTo(StringStream* stream);
3650 
3651   DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
3652 
3653  protected:
3654   virtual bool DataEquals(HValue* other) {
3655     HLoadContextSlot* b = HLoadContextSlot::cast(other);
3656     return (slot_index() == b->slot_index());
3657   }
3658 
3659  private:
3660   int slot_index_;
3661   Mode mode_;
3662 };
3663 
3664 
3665 class HStoreContextSlot: public HTemplateInstruction<2> {
3666  public:
3667   enum Mode {
3668     // Perform a normal store to the context slot without checking its previous
3669     // value.
3670     kNoCheck,
3671     // Check the previous value of the context slot and deoptimize if it's the
3672     // hole value. This is used for checking for assignments to uninitialized
3673     // harmony bindings where we deoptimize into full-codegen generated code
3674     // which will subsequently throw a reference error.
3675     kCheckDeoptimize,
3676     // Check the previous value and ignore assignment if it isn't a hole value
3677     kCheckIgnoreAssignment
3678   };
3679 
3680   HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
3681       : slot_index_(slot_index), mode_(mode) {
3682     SetOperandAt(0, context);
3683     SetOperandAt(1, value);
3684     SetGVNFlag(kChangesContextSlots);
3685   }
3686 
3687   HValue* context() { return OperandAt(0); }
3688   HValue* value() { return OperandAt(1); }
3689   int slot_index() const { return slot_index_; }
3690   Mode mode() const { return mode_; }
3691 
3692   bool NeedsWriteBarrier() {
3693     return StoringValueNeedsWriteBarrier(value());
3694   }
3695 
3696   bool DeoptimizesOnHole() {
3697     return mode_ == kCheckDeoptimize;
3698   }
3699 
3700   bool RequiresHoleCheck() {
3701     return mode_ != kNoCheck;
3702   }
3703 
3704   virtual Representation RequiredInputRepresentation(int index) {
3705     return Representation::Tagged();
3706   }
3707 
3708   virtual void PrintDataTo(StringStream* stream);
3709 
3710   DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
3711 
3712  private:
3713   int slot_index_;
3714   Mode mode_;
3715 };
3716 
3717 
3718 class HLoadNamedField: public HUnaryOperation {
3719  public:
3720   HLoadNamedField(HValue* object, bool is_in_object, int offset)
3721       : HUnaryOperation(object),
3722         is_in_object_(is_in_object),
3723         offset_(offset) {
3724     set_representation(Representation::Tagged());
3725     SetFlag(kUseGVN);
3726     SetGVNFlag(kDependsOnMaps);
3727     if (is_in_object) {
3728       SetGVNFlag(kDependsOnInobjectFields);
3729     } else {
3730       SetGVNFlag(kDependsOnBackingStoreFields);
3731     }
3732   }
3733 
3734   HValue* object() { return OperandAt(0); }
3735   bool is_in_object() const { return is_in_object_; }
3736   int offset() const { return offset_; }
3737 
3738   virtual Representation RequiredInputRepresentation(int index) {
3739     return Representation::Tagged();
3740   }
3741   virtual void PrintDataTo(StringStream* stream);
3742 
3743   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
3744 
3745  protected:
3746   virtual bool DataEquals(HValue* other) {
3747     HLoadNamedField* b = HLoadNamedField::cast(other);
3748     return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
3749   }
3750 
3751  private:
3752   bool is_in_object_;
3753   int offset_;
3754 };
3755 
3756 
3757 class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
3758  public:
3759   HLoadNamedFieldPolymorphic(HValue* context,
3760                              HValue* object,
3761                              SmallMapList* types,
3762                              Handle<String> name);
3763 
3764   HValue* context() { return OperandAt(0); }
3765   HValue* object() { return OperandAt(1); }
3766   SmallMapList* types() { return &types_; }
3767   Handle<String> name() { return name_; }
3768   bool need_generic() { return need_generic_; }
3769 
3770   virtual Representation RequiredInputRepresentation(int index) {
3771     return Representation::Tagged();
3772   }
3773 
3774   virtual void PrintDataTo(StringStream* stream);
3775 
3776   DECLARE_CONCRETE_INSTRUCTION(LoadNamedFieldPolymorphic)
3777 
3778   static const int kMaxLoadPolymorphism = 4;
3779 
3780  protected:
3781   virtual bool DataEquals(HValue* value);
3782 
3783  private:
3784   SmallMapList types_;
3785   Handle<String> name_;
3786   bool need_generic_;
3787 };
3788 
3789 
3790 
3791 class HLoadNamedGeneric: public HTemplateInstruction<2> {
3792  public:
3793   HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
3794       : name_(name) {
3795     SetOperandAt(0, context);
3796     SetOperandAt(1, object);
3797     set_representation(Representation::Tagged());
3798     SetAllSideEffects();
3799   }
3800 
3801   HValue* context() { return OperandAt(0); }
3802   HValue* object() { return OperandAt(1); }
3803   Handle<Object> name() const { return name_; }
3804 
3805   virtual Representation RequiredInputRepresentation(int index) {
3806     return Representation::Tagged();
3807   }
3808 
3809   virtual void PrintDataTo(StringStream* stream);
3810 
3811   DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
3812 
3813  private:
3814   Handle<Object> name_;
3815 };
3816 
3817 
3818 class HLoadFunctionPrototype: public HUnaryOperation {
3819  public:
3820   explicit HLoadFunctionPrototype(HValue* function)
3821       : HUnaryOperation(function) {
3822     set_representation(Representation::Tagged());
3823     SetFlag(kUseGVN);
3824     SetGVNFlag(kDependsOnCalls);
3825   }
3826 
3827   HValue* function() { return OperandAt(0); }
3828 
3829   virtual Representation RequiredInputRepresentation(int index) {
3830     return Representation::Tagged();
3831   }
3832 
3833   DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
3834 
3835  protected:
3836   virtual bool DataEquals(HValue* other) { return true; }
3837 };
3838 
3839 
3840 class HLoadKeyedFastElement: public HTemplateInstruction<2> {
3841  public:
3842   enum HoleCheckMode { PERFORM_HOLE_CHECK, OMIT_HOLE_CHECK };
3843 
3844   HLoadKeyedFastElement(HValue* obj,
3845                         HValue* key,
3846                         HoleCheckMode hole_check_mode = PERFORM_HOLE_CHECK)
3847       : hole_check_mode_(hole_check_mode) {
3848     SetOperandAt(0, obj);
3849     SetOperandAt(1, key);
3850     set_representation(Representation::Tagged());
3851     SetGVNFlag(kDependsOnArrayElements);
3852     SetFlag(kUseGVN);
3853   }
3854 
3855   HValue* object() { return OperandAt(0); }
3856   HValue* key() { return OperandAt(1); }
3857 
3858   virtual Representation RequiredInputRepresentation(int index) {
3859     // The key is supposed to be Integer32.
3860     return index == 0
3861       ? Representation::Tagged()
3862       : Representation::Integer32();
3863   }
3864 
3865   virtual void PrintDataTo(StringStream* stream);
3866 
3867   bool RequiresHoleCheck();
3868 
3869   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement)
3870 
3871  protected:
3872   virtual bool DataEquals(HValue* other) {
3873     if (!other->IsLoadKeyedFastElement()) return false;
3874     HLoadKeyedFastElement* other_load = HLoadKeyedFastElement::cast(other);
3875     return hole_check_mode_ == other_load->hole_check_mode_;
3876   }
3877 
3878  private:
3879   HoleCheckMode hole_check_mode_;
3880 };
3881 
3882 
3883 class HLoadKeyedFastDoubleElement: public HTemplateInstruction<2> {
3884  public:
3885   HLoadKeyedFastDoubleElement(HValue* elements, HValue* key) {
3886     SetOperandAt(0, elements);
3887     SetOperandAt(1, key);
3888     set_representation(Representation::Double());
3889     SetGVNFlag(kDependsOnDoubleArrayElements);
3890     SetFlag(kUseGVN);
3891   }
3892 
3893   HValue* elements() { return OperandAt(0); }
3894   HValue* key() { return OperandAt(1); }
3895 
3896   virtual Representation RequiredInputRepresentation(int index) {
3897     // The key is supposed to be Integer32.
3898     return index == 0
3899       ? Representation::Tagged()
3900       : Representation::Integer32();
3901   }
3902 
3903   virtual void PrintDataTo(StringStream* stream);
3904 
3905   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement)
3906 
3907  protected:
3908   virtual bool DataEquals(HValue* other) { return true; }
3909 };
3910 
3911 
3912 class HLoadKeyedSpecializedArrayElement: public HTemplateInstruction<2> {
3913  public:
3914   HLoadKeyedSpecializedArrayElement(HValue* external_elements,
3915                                     HValue* key,
3916                                     ElementsKind elements_kind)
3917       :  elements_kind_(elements_kind) {
3918     SetOperandAt(0, external_elements);
3919     SetOperandAt(1, key);
3920     if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
3921         elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3922       set_representation(Representation::Double());
3923     } else {
3924       set_representation(Representation::Integer32());
3925     }
3926     SetGVNFlag(kDependsOnSpecializedArrayElements);
3927     // Native code could change the specialized array.
3928     SetGVNFlag(kDependsOnCalls);
3929     SetFlag(kUseGVN);
3930   }
3931 
3932   virtual void PrintDataTo(StringStream* stream);
3933 
3934   virtual Representation RequiredInputRepresentation(int index) {
3935     // The key is supposed to be Integer32, but the base pointer
3936     // for the element load is a naked pointer.
3937     return index == 0
3938       ? Representation::External()
3939       : Representation::Integer32();
3940   }
3941 
3942   HValue* external_pointer() { return OperandAt(0); }
3943   HValue* key() { return OperandAt(1); }
3944   ElementsKind elements_kind() const { return elements_kind_; }
3945 
3946   virtual Range* InferRange(Zone* zone);
3947 
3948   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement)
3949 
3950  protected:
3951   virtual bool DataEquals(HValue* other) {
3952     if (!other->IsLoadKeyedSpecializedArrayElement()) return false;
3953     HLoadKeyedSpecializedArrayElement* cast_other =
3954         HLoadKeyedSpecializedArrayElement::cast(other);
3955     return elements_kind_ == cast_other->elements_kind();
3956   }
3957 
3958  private:
3959   ElementsKind elements_kind_;
3960 };
3961 
3962 
3963 class HLoadKeyedGeneric: public HTemplateInstruction<3> {
3964  public:
3965   HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key) {
3966     set_representation(Representation::Tagged());
3967     SetOperandAt(0, obj);
3968     SetOperandAt(1, key);
3969     SetOperandAt(2, context);
3970     SetAllSideEffects();
3971   }
3972 
3973   HValue* object() { return OperandAt(0); }
3974   HValue* key() { return OperandAt(1); }
3975   HValue* context() { return OperandAt(2); }
3976 
3977   virtual void PrintDataTo(StringStream* stream);
3978 
3979   virtual Representation RequiredInputRepresentation(int index) {
3980     return Representation::Tagged();
3981   }
3982 
3983   virtual HValue* Canonicalize();
3984 
3985   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
3986 };
3987 
3988 
3989 class HStoreNamedField: public HTemplateInstruction<2> {
3990  public:
3991   HStoreNamedField(HValue* obj,
3992                    Handle<String> name,
3993                    HValue* val,
3994                    bool in_object,
3995                    int offset)
3996       : name_(name),
3997         is_in_object_(in_object),
3998         offset_(offset) {
3999     SetOperandAt(0, obj);
4000     SetOperandAt(1, val);
4001     if (is_in_object_) {
4002       SetGVNFlag(kChangesInobjectFields);
4003     } else {
4004       SetGVNFlag(kChangesBackingStoreFields);
4005     }
4006   }
4007 
4008   DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
4009 
4010   virtual Representation RequiredInputRepresentation(int index) {
4011     return Representation::Tagged();
4012   }
4013   virtual void PrintDataTo(StringStream* stream);
4014 
4015   HValue* object() { return OperandAt(0); }
4016   HValue* value() { return OperandAt(1); }
4017 
4018   Handle<String> name() const { return name_; }
4019   bool is_in_object() const { return is_in_object_; }
4020   int offset() const { return offset_; }
4021   Handle<Map> transition() const { return transition_; }
4022   void set_transition(Handle<Map> map) { transition_ = map; }
4023 
4024   bool NeedsWriteBarrier() {
4025     return StoringValueNeedsWriteBarrier(value());
4026   }
4027 
4028  private:
4029   Handle<String> name_;
4030   bool is_in_object_;
4031   int offset_;
4032   Handle<Map> transition_;
4033 };
4034 
4035 
4036 class HStoreNamedGeneric: public HTemplateInstruction<3> {
4037  public:
4038   HStoreNamedGeneric(HValue* context,
4039                      HValue* object,
4040                      Handle<String> name,
4041                      HValue* value,
4042                      StrictModeFlag strict_mode_flag)
4043       : name_(name),
4044         strict_mode_flag_(strict_mode_flag) {
4045     SetOperandAt(0, object);
4046     SetOperandAt(1, value);
4047     SetOperandAt(2, context);
4048     SetAllSideEffects();
4049   }
4050 
4051   HValue* object() { return OperandAt(0); }
4052   HValue* value() { return OperandAt(1); }
4053   HValue* context() { return OperandAt(2); }
4054   Handle<String> name() { return name_; }
4055   StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
4056 
4057   virtual void PrintDataTo(StringStream* stream);
4058 
4059   virtual Representation RequiredInputRepresentation(int index) {
4060     return Representation::Tagged();
4061   }
4062 
4063   DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
4064 
4065  private:
4066   Handle<String> name_;
4067   StrictModeFlag strict_mode_flag_;
4068 };
4069 
4070 
4071 class HStoreKeyedFastElement: public HTemplateInstruction<3> {
4072  public:
4073   HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val,
4074                          ElementsKind elements_kind = FAST_ELEMENTS)
4075       : elements_kind_(elements_kind) {
4076     SetOperandAt(0, obj);
4077     SetOperandAt(1, key);
4078     SetOperandAt(2, val);
4079     SetGVNFlag(kChangesArrayElements);
4080   }
4081 
4082   virtual Representation RequiredInputRepresentation(int index) {
4083     // The key is supposed to be Integer32.
4084     return index == 1
4085         ? Representation::Integer32()
4086         : Representation::Tagged();
4087   }
4088 
4089   HValue* object() { return OperandAt(0); }
4090   HValue* key() { return OperandAt(1); }
4091   HValue* value() { return OperandAt(2); }
4092   bool value_is_smi() {
4093     return elements_kind_ == FAST_SMI_ONLY_ELEMENTS;
4094   }
4095 
4096   bool NeedsWriteBarrier() {
4097     if (value_is_smi()) {
4098       return false;
4099     } else {
4100       return StoringValueNeedsWriteBarrier(value());
4101     }
4102   }
4103 
4104   virtual void PrintDataTo(StringStream* stream);
4105 
4106   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement)
4107 
4108  private:
4109   ElementsKind elements_kind_;
4110 };
4111 
4112 
4113 class HStoreKeyedFastDoubleElement: public HTemplateInstruction<3> {
4114  public:
4115   HStoreKeyedFastDoubleElement(HValue* elements,
4116                                HValue* key,
4117                                HValue* val) {
4118     SetOperandAt(0, elements);
4119     SetOperandAt(1, key);
4120     SetOperandAt(2, val);
4121     SetGVNFlag(kChangesDoubleArrayElements);
4122   }
4123 
4124   virtual Representation RequiredInputRepresentation(int index) {
4125     if (index == 1) {
4126       return Representation::Integer32();
4127     } else if (index == 2) {
4128       return Representation::Double();
4129     } else {
4130       return Representation::Tagged();
4131     }
4132   }
4133 
4134   HValue* elements() { return OperandAt(0); }
4135   HValue* key() { return OperandAt(1); }
4136   HValue* value() { return OperandAt(2); }
4137 
4138   bool NeedsWriteBarrier() {
4139     return StoringValueNeedsWriteBarrier(value());
4140   }
4141 
4142   virtual void PrintDataTo(StringStream* stream);
4143 
4144   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement)
4145 };
4146 
4147 
4148 class HStoreKeyedSpecializedArrayElement: public HTemplateInstruction<3> {
4149  public:
4150   HStoreKeyedSpecializedArrayElement(HValue* external_elements,
4151                                      HValue* key,
4152                                      HValue* val,
4153                                      ElementsKind elements_kind)
4154       : elements_kind_(elements_kind) {
4155     SetGVNFlag(kChangesSpecializedArrayElements);
4156     SetOperandAt(0, external_elements);
4157     SetOperandAt(1, key);
4158     SetOperandAt(2, val);
4159   }
4160 
4161   virtual void PrintDataTo(StringStream* stream);
4162 
4163   virtual Representation RequiredInputRepresentation(int index) {
4164     if (index == 0) {
4165       return Representation::External();
4166     } else {
4167       bool float_or_double_elements =
4168           elements_kind() == EXTERNAL_FLOAT_ELEMENTS ||
4169           elements_kind() == EXTERNAL_DOUBLE_ELEMENTS;
4170       if (index == 2 && float_or_double_elements) {
4171         return Representation::Double();
4172       } else {
4173         return Representation::Integer32();
4174       }
4175     }
4176   }
4177 
4178   HValue* external_pointer() { return OperandAt(0); }
4179   HValue* key() { return OperandAt(1); }
4180   HValue* value() { return OperandAt(2); }
4181   ElementsKind elements_kind() const { return elements_kind_; }
4182 
4183   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement)
4184 
4185  private:
4186   ElementsKind elements_kind_;
4187 };
4188 
4189 
4190 class HStoreKeyedGeneric: public HTemplateInstruction<4> {
4191  public:
4192   HStoreKeyedGeneric(HValue* context,
4193                      HValue* object,
4194                      HValue* key,
4195                      HValue* value,
4196                      StrictModeFlag strict_mode_flag)
4197       : strict_mode_flag_(strict_mode_flag) {
4198     SetOperandAt(0, object);
4199     SetOperandAt(1, key);
4200     SetOperandAt(2, value);
4201     SetOperandAt(3, context);
4202     SetAllSideEffects();
4203   }
4204 
4205   HValue* object() { return OperandAt(0); }
4206   HValue* key() { return OperandAt(1); }
4207   HValue* value() { return OperandAt(2); }
4208   HValue* context() { return OperandAt(3); }
4209   StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
4210 
4211   virtual Representation RequiredInputRepresentation(int index) {
4212     return Representation::Tagged();
4213   }
4214 
4215   virtual void PrintDataTo(StringStream* stream);
4216 
4217   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
4218 
4219  private:
4220   StrictModeFlag strict_mode_flag_;
4221 };
4222 
4223 
4224 class HTransitionElementsKind: public HTemplateInstruction<1> {
4225  public:
4226   HTransitionElementsKind(HValue* object,
4227                           Handle<Map> original_map,
4228                           Handle<Map> transitioned_map)
4229       : original_map_(original_map),
4230         transitioned_map_(transitioned_map) {
4231     SetOperandAt(0, object);
4232     SetFlag(kUseGVN);
4233     SetGVNFlag(kChangesElementsKind);
4234     SetGVNFlag(kChangesElementsPointer);
4235     set_representation(Representation::Tagged());
4236   }
4237 
4238   virtual Representation RequiredInputRepresentation(int index) {
4239     return Representation::Tagged();
4240   }
4241 
4242   HValue* object() { return OperandAt(0); }
4243   Handle<Map> original_map() { return original_map_; }
4244   Handle<Map> transitioned_map() { return transitioned_map_; }
4245 
4246   virtual void PrintDataTo(StringStream* stream);
4247 
4248   DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
4249 
4250  protected:
4251   virtual bool DataEquals(HValue* other) {
4252     HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
4253     return original_map_.is_identical_to(instr->original_map()) &&
4254         transitioned_map_.is_identical_to(instr->transitioned_map());
4255   }
4256 
4257  private:
4258   Handle<Map> original_map_;
4259   Handle<Map> transitioned_map_;
4260 };
4261 
4262 
4263 class HStringAdd: public HBinaryOperation {
4264  public:
4265   HStringAdd(HValue* context, HValue* left, HValue* right)
4266       : HBinaryOperation(context, left, right) {
4267     set_representation(Representation::Tagged());
4268     SetFlag(kUseGVN);
4269     SetGVNFlag(kDependsOnMaps);
4270   }
4271 
4272   virtual Representation RequiredInputRepresentation(int index) {
4273     return Representation::Tagged();
4274   }
4275 
4276   virtual HType CalculateInferredType() {
4277     return HType::String();
4278   }
4279 
4280   DECLARE_CONCRETE_INSTRUCTION(StringAdd)
4281 
4282  protected:
4283   virtual bool DataEquals(HValue* other) { return true; }
4284 };
4285 
4286 
4287 class HStringCharCodeAt: public HTemplateInstruction<3> {
4288  public:
4289   HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
4290     SetOperandAt(0, context);
4291     SetOperandAt(1, string);
4292     SetOperandAt(2, index);
4293     set_representation(Representation::Integer32());
4294     SetFlag(kUseGVN);
4295     SetGVNFlag(kDependsOnMaps);
4296   }
4297 
4298   virtual Representation RequiredInputRepresentation(int index) {
4299     // The index is supposed to be Integer32.
4300     return index == 2
4301         ? Representation::Integer32()
4302         : Representation::Tagged();
4303   }
4304 
4305   HValue* context() { return OperandAt(0); }
4306   HValue* string() { return OperandAt(1); }
4307   HValue* index() { return OperandAt(2); }
4308 
4309   DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
4310 
4311  protected:
4312   virtual bool DataEquals(HValue* other) { return true; }
4313 
4314   virtual Range* InferRange(Zone* zone) {
4315     return new(zone) Range(0, String::kMaxUtf16CodeUnit);
4316   }
4317 };
4318 
4319 
4320 class HStringCharFromCode: public HTemplateInstruction<2> {
4321  public:
4322   HStringCharFromCode(HValue* context, HValue* char_code) {
4323     SetOperandAt(0, context);
4324     SetOperandAt(1, char_code);
4325     set_representation(Representation::Tagged());
4326     SetFlag(kUseGVN);
4327   }
4328 
4329   virtual Representation RequiredInputRepresentation(int index) {
4330     return index == 0
4331         ? Representation::Tagged()
4332         : Representation::Integer32();
4333   }
4334   virtual HType CalculateInferredType();
4335 
4336   HValue* context() { return OperandAt(0); }
4337   HValue* value() { return OperandAt(1); }
4338 
4339   virtual bool DataEquals(HValue* other) { return true; }
4340 
4341   DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
4342 };
4343 
4344 
4345 class HStringLength: public HUnaryOperation {
4346  public:
4347   explicit HStringLength(HValue* string) : HUnaryOperation(string) {
4348     set_representation(Representation::Tagged());
4349     SetFlag(kUseGVN);
4350     SetGVNFlag(kDependsOnMaps);
4351   }
4352 
4353   virtual Representation RequiredInputRepresentation(int index) {
4354     return Representation::Tagged();
4355   }
4356 
4357   virtual HType CalculateInferredType() {
4358     STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
4359     return HType::Smi();
4360   }
4361 
4362   DECLARE_CONCRETE_INSTRUCTION(StringLength)
4363 
4364  protected:
4365   virtual bool DataEquals(HValue* other) { return true; }
4366 
4367   virtual Range* InferRange(Zone* zone) {
4368     return new(zone) Range(0, String::kMaxLength);
4369   }
4370 };
4371 
4372 
4373 class HAllocateObject: public HTemplateInstruction<1> {
4374  public:
4375   HAllocateObject(HValue* context, Handle<JSFunction> constructor)
4376       : constructor_(constructor) {
4377     SetOperandAt(0, context);
4378     set_representation(Representation::Tagged());
4379   }
4380 
4381   HValue* context() { return OperandAt(0); }
4382   Handle<JSFunction> constructor() { return constructor_; }
4383 
4384   virtual Representation RequiredInputRepresentation(int index) {
4385     return Representation::Tagged();
4386   }
4387   virtual HType CalculateInferredType();
4388 
4389   DECLARE_CONCRETE_INSTRUCTION(AllocateObject)
4390 
4391  private:
4392   Handle<JSFunction> constructor_;
4393 };
4394 
4395 
4396 template <int V>
4397 class HMaterializedLiteral: public HTemplateInstruction<V> {
4398  public:
4399   HMaterializedLiteral<V>(int index, int depth)
4400       : literal_index_(index), depth_(depth) {
4401     this->set_representation(Representation::Tagged());
4402   }
4403 
4404   int literal_index() const { return literal_index_; }
4405   int depth() const { return depth_; }
4406 
4407  private:
4408   int literal_index_;
4409   int depth_;
4410 };
4411 
4412 
4413 class HFastLiteral: public HMaterializedLiteral<1> {
4414  public:
4415   HFastLiteral(HValue* context,
4416                Handle<JSObject> boilerplate,
4417                int total_size,
4418                int literal_index,
4419                int depth)
4420       : HMaterializedLiteral<1>(literal_index, depth),
4421         boilerplate_(boilerplate),
4422         total_size_(total_size) {
4423     SetOperandAt(0, context);
4424   }
4425 
4426   // Maximum depth and total number of elements and properties for literal
4427   // graphs to be considered for fast deep-copying.
4428   static const int kMaxLiteralDepth = 3;
4429   static const int kMaxLiteralProperties = 8;
4430 
4431   HValue* context() { return OperandAt(0); }
4432   Handle<JSObject> boilerplate() const { return boilerplate_; }
4433   int total_size() const { return total_size_; }
4434 
4435   virtual Representation RequiredInputRepresentation(int index) {
4436     return Representation::Tagged();
4437   }
4438   virtual HType CalculateInferredType();
4439 
4440   DECLARE_CONCRETE_INSTRUCTION(FastLiteral)
4441 
4442  private:
4443   Handle<JSObject> boilerplate_;
4444   int total_size_;
4445 };
4446 
4447 
4448 class HArrayLiteral: public HMaterializedLiteral<1> {
4449  public:
4450   HArrayLiteral(HValue* context,
4451                 Handle<HeapObject> boilerplate_object,
4452                 int length,
4453                 int literal_index,
4454                 int depth)
4455       : HMaterializedLiteral<1>(literal_index, depth),
4456         length_(length),
4457         boilerplate_object_(boilerplate_object) {
4458     SetOperandAt(0, context);
4459   }
4460 
4461   HValue* context() { return OperandAt(0); }
4462   ElementsKind boilerplate_elements_kind() const {
4463     if (!boilerplate_object_->IsJSObject()) {
4464       return FAST_ELEMENTS;
4465     }
4466     return Handle<JSObject>::cast(boilerplate_object_)->GetElementsKind();
4467   }
4468   Handle<HeapObject> boilerplate_object() const { return boilerplate_object_; }
4469   int length() const { return length_; }
4470 
4471   bool IsCopyOnWrite() const;
4472 
4473   virtual Representation RequiredInputRepresentation(int index) {
4474     return Representation::Tagged();
4475   }
4476   virtual HType CalculateInferredType();
4477 
4478   DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral)
4479 
4480  private:
4481   int length_;
4482   Handle<HeapObject> boilerplate_object_;
4483 };
4484 
4485 
4486 class HObjectLiteral: public HMaterializedLiteral<1> {
4487  public:
4488   HObjectLiteral(HValue* context,
4489                  Handle<FixedArray> constant_properties,
4490                  bool fast_elements,
4491                  int literal_index,
4492                  int depth,
4493                  bool has_function)
4494       : HMaterializedLiteral<1>(literal_index, depth),
4495         constant_properties_(constant_properties),
4496         fast_elements_(fast_elements),
4497         has_function_(has_function) {
4498     SetOperandAt(0, context);
4499   }
4500 
4501   HValue* context() { return OperandAt(0); }
4502   Handle<FixedArray> constant_properties() const {
4503     return constant_properties_;
4504   }
4505   bool fast_elements() const { return fast_elements_; }
4506   bool has_function() const { return has_function_; }
4507 
4508   virtual Representation RequiredInputRepresentation(int index) {
4509     return Representation::Tagged();
4510   }
4511   virtual HType CalculateInferredType();
4512 
4513   DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral)
4514 
4515  private:
4516   Handle<FixedArray> constant_properties_;
4517   bool fast_elements_;
4518   bool has_function_;
4519 };
4520 
4521 
4522 class HRegExpLiteral: public HMaterializedLiteral<1> {
4523  public:
4524   HRegExpLiteral(HValue* context,
4525                  Handle<String> pattern,
4526                  Handle<String> flags,
4527                  int literal_index)
4528       : HMaterializedLiteral<1>(literal_index, 0),
4529         pattern_(pattern),
4530         flags_(flags) {
4531     SetOperandAt(0, context);
4532     SetAllSideEffects();
4533   }
4534 
4535   HValue* context() { return OperandAt(0); }
4536   Handle<String> pattern() { return pattern_; }
4537   Handle<String> flags() { return flags_; }
4538 
4539   virtual Representation RequiredInputRepresentation(int index) {
4540     return Representation::Tagged();
4541   }
4542   virtual HType CalculateInferredType();
4543 
4544   DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
4545 
4546  private:
4547   Handle<String> pattern_;
4548   Handle<String> flags_;
4549 };
4550 
4551 
4552 class HFunctionLiteral: public HTemplateInstruction<1> {
4553  public:
4554   HFunctionLiteral(HValue* context,
4555                    Handle<SharedFunctionInfo> shared,
4556                    bool pretenure)
4557       : shared_info_(shared), pretenure_(pretenure) {
4558     SetOperandAt(0, context);
4559     set_representation(Representation::Tagged());
4560   }
4561 
4562   HValue* context() { return OperandAt(0); }
4563 
4564   virtual Representation RequiredInputRepresentation(int index) {
4565     return Representation::Tagged();
4566   }
4567   virtual HType CalculateInferredType();
4568 
4569   DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral)
4570 
4571   Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
4572   bool pretenure() const { return pretenure_; }
4573 
4574  private:
4575   Handle<SharedFunctionInfo> shared_info_;
4576   bool pretenure_;
4577 };
4578 
4579 
4580 class HTypeof: public HTemplateInstruction<2> {
4581  public:
4582   explicit HTypeof(HValue* context, HValue* value) {
4583     SetOperandAt(0, context);
4584     SetOperandAt(1, value);
4585     set_representation(Representation::Tagged());
4586   }
4587 
4588   HValue* context() { return OperandAt(0); }
4589   HValue* value() { return OperandAt(1); }
4590 
4591   virtual HValue* Canonicalize();
4592   virtual void PrintDataTo(StringStream* stream);
4593 
4594   virtual Representation RequiredInputRepresentation(int index) {
4595     return Representation::Tagged();
4596   }
4597 
4598   DECLARE_CONCRETE_INSTRUCTION(Typeof)
4599 };
4600 
4601 
4602 class HToFastProperties: public HUnaryOperation {
4603  public:
4604   explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
4605     // This instruction is not marked as having side effects, but
4606     // changes the map of the input operand. Use it only when creating
4607     // object literals.
4608     ASSERT(value->IsObjectLiteral() || value->IsFastLiteral());
4609     set_representation(Representation::Tagged());
4610   }
4611 
4612   virtual Representation RequiredInputRepresentation(int index) {
4613     return Representation::Tagged();
4614   }
4615 
4616   DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
4617 };
4618 
4619 
4620 class HValueOf: public HUnaryOperation {
4621  public:
4622   explicit HValueOf(HValue* value) : HUnaryOperation(value) {
4623     set_representation(Representation::Tagged());
4624   }
4625 
4626   virtual Representation RequiredInputRepresentation(int index) {
4627     return Representation::Tagged();
4628   }
4629 
4630   DECLARE_CONCRETE_INSTRUCTION(ValueOf)
4631 };
4632 
4633 
4634 class HDateField: public HUnaryOperation {
4635  public:
4636   HDateField(HValue* date, Smi* index)
4637       : HUnaryOperation(date), index_(index) {
4638     set_representation(Representation::Tagged());
4639   }
4640 
4641   Smi* index() const { return index_; }
4642 
4643   virtual Representation RequiredInputRepresentation(int index) {
4644     return Representation::Tagged();
4645   }
4646 
4647   DECLARE_CONCRETE_INSTRUCTION(DateField)
4648 
4649  private:
4650   Smi* index_;
4651 };
4652 
4653 
4654 class HDeleteProperty: public HBinaryOperation {
4655  public:
4656   HDeleteProperty(HValue* context, HValue* obj, HValue* key)
4657       : HBinaryOperation(context, obj, key) {
4658     set_representation(Representation::Tagged());
4659     SetAllSideEffects();
4660   }
4661 
4662   virtual Representation RequiredInputRepresentation(int index) {
4663     return Representation::Tagged();
4664   }
4665 
4666   virtual HType CalculateInferredType();
4667 
4668   DECLARE_CONCRETE_INSTRUCTION(DeleteProperty)
4669 
4670   HValue* object() { return left(); }
4671   HValue* key() { return right(); }
4672 };
4673 
4674 
4675 class HIn: public HTemplateInstruction<3> {
4676  public:
4677   HIn(HValue* context, HValue* key, HValue* object) {
4678     SetOperandAt(0, context);
4679     SetOperandAt(1, key);
4680     SetOperandAt(2, object);
4681     set_representation(Representation::Tagged());
4682     SetAllSideEffects();
4683   }
4684 
4685   HValue* context() { return OperandAt(0); }
4686   HValue* key() { return OperandAt(1); }
4687   HValue* object() { return OperandAt(2); }
4688 
4689   virtual Representation RequiredInputRepresentation(int index) {
4690     return Representation::Tagged();
4691   }
4692 
4693   virtual HType CalculateInferredType() {
4694     return HType::Boolean();
4695   }
4696 
4697   virtual void PrintDataTo(StringStream* stream);
4698 
4699   DECLARE_CONCRETE_INSTRUCTION(In)
4700 };
4701 
4702 
4703 class HCheckMapValue: public HTemplateInstruction<2> {
4704  public:
4705   HCheckMapValue(HValue* value,
4706                  HValue* map) {
4707     SetOperandAt(0, value);
4708     SetOperandAt(1, map);
4709     set_representation(Representation::Tagged());
4710     SetFlag(kUseGVN);
4711     SetGVNFlag(kDependsOnMaps);
4712     SetGVNFlag(kDependsOnElementsKind);
4713   }
4714 
4715   virtual Representation RequiredInputRepresentation(int index) {
4716     return Representation::Tagged();
4717   }
4718 
4719   virtual void PrintDataTo(StringStream* stream);
4720 
4721   virtual HType CalculateInferredType() {
4722     return HType::Tagged();
4723   }
4724 
4725   HValue* value() { return OperandAt(0); }
4726   HValue* map() { return OperandAt(1); }
4727 
4728   DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
4729 
4730  protected:
4731   virtual bool DataEquals(HValue* other) {
4732     return true;
4733   }
4734 };
4735 
4736 
4737 class HForInPrepareMap : public HTemplateInstruction<2> {
4738  public:
4739   HForInPrepareMap(HValue* context,
4740                    HValue* object) {
4741     SetOperandAt(0, context);
4742     SetOperandAt(1, object);
4743     set_representation(Representation::Tagged());
4744     SetAllSideEffects();
4745   }
4746 
4747   virtual Representation RequiredInputRepresentation(int index) {
4748     return Representation::Tagged();
4749   }
4750 
4751   HValue* context() { return OperandAt(0); }
4752   HValue* enumerable() { return OperandAt(1); }
4753 
4754   virtual void PrintDataTo(StringStream* stream);
4755 
4756   virtual HType CalculateInferredType() {
4757     return HType::Tagged();
4758   }
4759 
4760   DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
4761 };
4762 
4763 
4764 class HForInCacheArray : public HTemplateInstruction<2> {
4765  public:
4766   HForInCacheArray(HValue* enumerable,
4767                    HValue* keys,
4768                    int idx) : idx_(idx) {
4769     SetOperandAt(0, enumerable);
4770     SetOperandAt(1, keys);
4771     set_representation(Representation::Tagged());
4772   }
4773 
4774   virtual Representation RequiredInputRepresentation(int index) {
4775     return Representation::Tagged();
4776   }
4777 
4778   HValue* enumerable() { return OperandAt(0); }
4779   HValue* map() { return OperandAt(1); }
4780   int idx() { return idx_; }
4781 
4782   HForInCacheArray* index_cache() {
4783     return index_cache_;
4784   }
4785 
4786   void set_index_cache(HForInCacheArray* index_cache) {
4787     index_cache_ = index_cache;
4788   }
4789 
4790   virtual void PrintDataTo(StringStream* stream);
4791 
4792   virtual HType CalculateInferredType() {
4793     return HType::Tagged();
4794   }
4795 
4796   DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
4797 
4798  private:
4799   int idx_;
4800   HForInCacheArray* index_cache_;
4801 };
4802 
4803 
4804 class HLoadFieldByIndex : public HTemplateInstruction<2> {
4805  public:
4806   HLoadFieldByIndex(HValue* object,
4807                     HValue* index) {
4808     SetOperandAt(0, object);
4809     SetOperandAt(1, index);
4810     set_representation(Representation::Tagged());
4811   }
4812 
4813   virtual Representation RequiredInputRepresentation(int index) {
4814     return Representation::Tagged();
4815   }
4816 
4817   HValue* object() { return OperandAt(0); }
4818   HValue* index() { return OperandAt(1); }
4819 
4820   virtual void PrintDataTo(StringStream* stream);
4821 
4822   virtual HType CalculateInferredType() {
4823     return HType::Tagged();
4824   }
4825 
4826   DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
4827 };
4828 
4829 
4830 #undef DECLARE_INSTRUCTION
4831 #undef DECLARE_CONCRETE_INSTRUCTION
4832 
4833 } }  // namespace v8::internal
4834 
4835 #endif  // V8_HYDROGEN_INSTRUCTIONS_H_
4836