[V8] Introduce a QML compilation mode
[profile/ivi/qtjsbackend.git] / src / 3rdparty / v8 / src / hydrogen-instructions.h
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(CheckMaps)                                 \
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:
225   Range()
226       : lower_(kMinInt),
227         upper_(kMaxInt),
228         next_(NULL),
229         can_be_minus_zero_(false) { }
230
231   Range(int32_t lower, int32_t upper)
232       : lower_(lower),
233         upper_(upper),
234         next_(NULL),
235         can_be_minus_zero_(false) { }
236
237   int32_t upper() const { return upper_; }
238   int32_t lower() const { return lower_; }
239   Range* next() const { return next_; }
240   Range* CopyClearLower(Zone* zone) const {
241     return new(zone) Range(kMinInt, upper_);
242   }
243   Range* CopyClearUpper(Zone* zone) const {
244     return new(zone) Range(lower_, kMaxInt);
245   }
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;
252   void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
253   bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
254   bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
255   bool CanBeNegative() const { return lower_ < 0; }
256   bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
257   bool IsMostGeneric() const {
258     return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
259   }
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
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
302   Representation() : kind_(kNone) { }
303
304   static Representation None() { return Representation(kNone); }
305   static Representation Tagged() { return Representation(kTagged); }
306   static Representation Integer32() { return Representation(kInteger32); }
307   static Representation Double() { return Representation(kDouble); }
308   static Representation External() { return Representation(kExternal); }
309
310   bool Equals(const Representation& other) {
311     return kind_ == other.kind_;
312   }
313
314   Kind kind() const { return static_cast<Kind>(kind_); }
315   bool IsNone() const { return kind_ == kNone; }
316   bool IsTagged() const { return kind_ == kTagged; }
317   bool IsInteger32() const { return kind_ == kInteger32; }
318   bool IsDouble() const { return kind_ == kDouble; }
319   bool IsExternal() const { return kind_ == kExternal; }
320   bool IsSpecialization() const {
321     return kind_ == kInteger32 || kind_ == kDouble;
322   }
323   const char* Mnemonic() const;
324
325  private:
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:
337   HType() : type_(kUninitialized) { }
338
339   static HType Tagged() { return HType(kTagged); }
340   static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
341   static HType TaggedNumber() { return HType(kTaggedNumber); }
342   static HType Smi() { return HType(kSmi); }
343   static HType HeapNumber() { return HType(kHeapNumber); }
344   static HType String() { return HType(kString); }
345   static HType Boolean() { return HType(kBoolean); }
346   static HType NonPrimitive() { return HType(kNonPrimitive); }
347   static HType JSArray() { return HType(kJSArray); }
348   static HType JSObject() { return HType(kJSObject); }
349   static HType Uninitialized() { return HType(kUninitialized); }
350
351   // Return the weakest (least precise) common type.
352   HType Combine(HType other) {
353     return HType(static_cast<Type>(type_ & other.type_));
354   }
355
356   bool Equals(const HType& other) {
357     return type_ == other.type_;
358   }
359
360   bool IsSubtypeOf(const HType& other) {
361     return Combine(other).Equals(other);
362   }
363
364   bool IsTagged() {
365     ASSERT(type_ != kUninitialized);
366     return ((type_ & kTagged) == kTagged);
367   }
368
369   bool IsTaggedPrimitive() {
370     ASSERT(type_ != kUninitialized);
371     return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
372   }
373
374   bool IsTaggedNumber() {
375     ASSERT(type_ != kUninitialized);
376     return ((type_ & kTaggedNumber) == kTaggedNumber);
377   }
378
379   bool IsSmi() {
380     ASSERT(type_ != kUninitialized);
381     return ((type_ & kSmi) == kSmi);
382   }
383
384   bool IsHeapNumber() {
385     ASSERT(type_ != kUninitialized);
386     return ((type_ & kHeapNumber) == kHeapNumber);
387   }
388
389   bool IsString() {
390     ASSERT(type_ != kUninitialized);
391     return ((type_ & kString) == kString);
392   }
393
394   bool IsBoolean() {
395     ASSERT(type_ != kUninitialized);
396     return ((type_ & kBoolean) == kBoolean);
397   }
398
399   bool IsNonPrimitive() {
400     ASSERT(type_ != kUninitialized);
401     return ((type_ & kNonPrimitive) == kNonPrimitive);
402   }
403
404   bool IsJSArray() {
405     ASSERT(type_ != kUninitialized);
406     return ((type_ & kJSArray) == kJSArray);
407   }
408
409   bool IsJSObject() {
410     ASSERT(type_ != kUninitialized);
411     return ((type_ & kJSObject) == kJSObject);
412   }
413
414   bool IsUninitialized() {
415     return type_ == kUninitialized;
416   }
417
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
445   explicit HType(Type t) : type_(t) { }
446
447   int16_t type_;
448 };
449
450
451 class HUseListNode: public ZoneObject {
452  public:
453   HUseListNode(HValue* value, int index, HUseListNode* tail)
454       : tail_(tail), value_(value), index_(index) {
455   }
456
457   HUseListNode* tail();
458   HValue* value() const { return value_; }
459   int index() const { return index_; }
460
461   void set_tail(HUseListNode* list) { tail_ = list; }
462
463 #ifdef DEBUG
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:
482   bool Done() { return current_ == NULL; }
483   void Advance();
484
485   HValue* value() {
486     ASSERT(!Done());
487     return value_;
488   }
489
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
547   static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags) {
548     return GVNFlagSet(flags.ToIntegral() << kChangesToDependsFlagsLeftShift);
549   }
550
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; }
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
575   HValue() : block_(NULL),
576              id_(kNoNumber),
577              type_(HType::Tagged()),
578              use_list_(NULL),
579              range_(NULL),
580              flags_(0) {}
581   virtual ~HValue() {}
582
583   HBasicBlock* block() const { return block_; }
584   void SetBlock(HBasicBlock* block);
585   int LoopWeight() const;
586
587   int id() const { return id_; }
588   void set_id(int id) { id_ = id; }
589
590   HUseIterator uses() const { return HUseIterator(use_list_); }
591
592   virtual bool EmitAtUses() { return false; }
593   Representation representation() const { return representation_; }
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
603   virtual bool IsConvertibleToInteger() const { return true; }
604
605   HType type() const { return 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.
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);
635   bool HasNoUses() const { return use_list_ == NULL; }
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
644   int flags() const { return flags_; }
645   void SetFlag(Flag f) { flags_ |= (1 << f); }
646   void ClearFlag(Flag f) { flags_ &= ~(1 << 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
652   GVNFlagSet gvn_flags() const { return gvn_flags_; }
653   void SetGVNFlag(GVNFlag f) { gvn_flags_.Add(f); }
654   void ClearGVNFlag(GVNFlag f) { gvn_flags_.Remove(f); }
655   bool CheckGVNFlag(GVNFlag f) const { return gvn_flags_.Contains(f); }
656   void SetAllSideEffects() { gvn_flags_.Add(AllSideEffectsFlagSet()); }
657   void ClearAllSideEffects() {
658     gvn_flags_.Remove(AllSideEffectsFlagSet());
659   }
660   bool HasSideEffects() const {
661     return gvn_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
662   }
663   bool HasObservableSideEffects() const {
664     return gvn_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
665   }
666
667   GVNFlagSet DependsOnFlags() const {
668     GVNFlagSet result = gvn_flags_;
669     result.Intersect(AllDependsOnFlagSet());
670     return result;
671   }
672
673   GVNFlagSet SideEffectFlags() const {
674     GVNFlagSet result = gvn_flags_;
675     result.Intersect(AllSideEffectsFlagSet());
676     return result;
677   }
678
679   GVNFlagSet ChangesFlags() const {
680     GVNFlagSet result = gvn_flags_;
681     result.Intersect(AllChangesFlagSet());
682     return result;
683   }
684
685   GVNFlagSet ObservableChangesFlags() const {
686     GVNFlagSet result = gvn_flags_;
687     result.Intersect(AllChangesFlagSet());
688     result.Intersect(AllObservableSideEffectsFlagSet());
689     return result;
690   }
691
692   Range* range() const { return range_; }
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
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.
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.
736   virtual bool DataEquals(HValue* other) {
737     UNREACHABLE();
738     return false;
739   }
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;
744   void clear_block() {
745     ASSERT(block_ != NULL);
746     block_ = NULL;
747   }
748
749   void set_representation(Representation r) {
750     // Representation is set-once.
751     ASSERT(representation_.IsNone() && !r.IsNone());
752     representation_ = r;
753   }
754
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
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.
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);
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:
816   HInstruction* next() const { return next_; }
817   HInstruction* previous() const { return previous_; }
818
819   virtual void PrintTo(StringStream* stream);
820   virtual void PrintDataTo(StringStream* stream) { }
821
822   bool IsLinked() const { return block() != NULL; }
823   void Unlink();
824   void InsertBefore(HInstruction* next);
825   void InsertAfter(HInstruction* previous);
826
827   int position() const { return position_; }
828   bool has_position() const { return position_ != RelocInfo::kNoPosition; }
829   void set_position(int position) { position_ = position; }
830
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
839   virtual bool IsCall() { return false; }
840
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
851   virtual void DeleteFromGraph() { Unlink(); }
852
853  private:
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:
872   int OperandCount() { return V; }
873   HValue* OperandAt(int i) { return inputs_[i]; }
874
875  protected:
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
891   HBasicBlock* FirstSuccessor() {
892     return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
893   }
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:
904   explicit HSuccessorIterator(HControlInstruction* instr)
905       : instr_(instr), current_(0) { }
906
907   bool Done() { return current_ >= instr_->SuccessorCount(); }
908   HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
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:
920   int SuccessorCount() { return S; }
921   HBasicBlock* SuccessorAt(int i) { return successors_[i]; }
922   void SetSuccessorAt(int i, HBasicBlock* block) { successors_[i] = block; }
923
924   int OperandCount() { return V; }
925   HValue* OperandAt(int i) { return inputs_[i]; }
926
927
928  protected:
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:
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:
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:
962   explicit HDeoptimize(int environment_length) : values_(environment_length) { }
963
964   virtual Representation RequiredInputRepresentation(int index) {
965     return Representation::None();
966   }
967
968   virtual int OperandCount() { return values_.length(); }
969   virtual HValue* OperandAt(int index) { return values_[index]; }
970   virtual void PrintDataTo(StringStream* stream);
971
972   virtual int SuccessorCount() { return 0; }
973   virtual HBasicBlock* SuccessorAt(int i) {
974     UNREACHABLE();
975     return NULL;
976   }
977   virtual void SetSuccessorAt(int i, HBasicBlock* block) {
978     UNREACHABLE();
979   }
980
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:
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:
1005   explicit HGoto(HBasicBlock* target) {
1006     SetSuccessorAt(0, target);
1007   }
1008
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:
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
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())
1041       : HUnaryControlInstruction(value, true_target, false_target),
1042         expected_input_types_(expected_input_types) {
1043     ASSERT(true_target != NULL && false_target != NULL);
1044   }
1045   explicit HBranch(HValue* value)
1046       : HUnaryControlInstruction(value, NULL, NULL) { }
1047
1048
1049   virtual Representation RequiredInputRepresentation(int index) {
1050     return Representation::None();
1051   }
1052
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:
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
1079   Handle<Map> map() const { return map_; }
1080
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:
1094   explicit HReturn(HValue* value) {
1095     SetOperandAt(0, value);
1096   }
1097
1098   virtual Representation RequiredInputRepresentation(int index) {
1099     return Representation::Tagged();
1100   }
1101
1102   virtual void PrintDataTo(StringStream* stream);
1103
1104   HValue* value() { return OperandAt(0); }
1105
1106   DECLARE_CONCRETE_INSTRUCTION(Return)
1107 };
1108
1109
1110 class HAbnormalExit: public HTemplateControlInstruction<0, 0> {
1111  public:
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:
1122   explicit HUnaryOperation(HValue* value) {
1123     SetOperandAt(0, value);
1124   }
1125
1126   static HUnaryOperation* cast(HValue* value) {
1127     return reinterpret_cast<HUnaryOperation*>(value);
1128   }
1129
1130   HValue* value() { return OperandAt(0); }
1131   virtual void PrintDataTo(StringStream* stream);
1132 };
1133
1134
1135 class HThrow: public HTemplateInstruction<2> {
1136  public:
1137   HThrow(HValue* context, HValue* value) {
1138     SetOperandAt(0, context);
1139     SetOperandAt(1, value);
1140     SetAllSideEffects();
1141   }
1142
1143   virtual Representation RequiredInputRepresentation(int index) {
1144     return Representation::Tagged();
1145   }
1146
1147   HValue* context() { return OperandAt(0); }
1148   HValue* value() { return OperandAt(1); }
1149
1150   DECLARE_CONCRETE_INSTRUCTION(Throw)
1151 };
1152
1153
1154 class HUseConst: public HUnaryOperation {
1155  public:
1156   explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
1157
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:
1168   HForceRepresentation(HValue* value, Representation required_representation) {
1169     SetOperandAt(0, value);
1170     set_representation(required_representation);
1171   }
1172
1173   HValue* value() { return OperandAt(0); }
1174
1175   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1176
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:
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
1205   Representation from() { return value()->representation(); }
1206   Representation to() { return representation(); }
1207   bool deoptimize_on_undefined() const {
1208     return CheckFlag(kDeoptimizeOnUndefined);
1209   }
1210   bool deoptimize_on_minus_zero() const {
1211     return CheckFlag(kBailoutOnMinusZero);
1212   }
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
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:
1230   explicit HClampToUint8(HValue* value)
1231       : HUnaryOperation(value) {
1232     set_representation(Representation::Integer32());
1233     SetFlag(kUseGVN);
1234   }
1235
1236   virtual Representation RequiredInputRepresentation(int index) {
1237     return Representation::None();
1238   }
1239
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:
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) {}
1254   virtual ~HSimulate() {}
1255
1256   virtual void PrintDataTo(StringStream* stream);
1257
1258   bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; }
1259   int ast_id() const { return ast_id_; }
1260   void set_ast_id(int id) {
1261     ASSERT(!HasAstId());
1262     ast_id_ = id;
1263   }
1264
1265   int pop_count() const { return pop_count_; }
1266   const ZoneList<HValue*>* values() const { return &values_; }
1267   int GetAssignedIndexAt(int index) const {
1268     ASSERT(HasAssignedIndexAt(index));
1269     return assigned_indexes_[index];
1270   }
1271   bool HasAssignedIndexAt(int index) const {
1272     return assigned_indexes_[index] != kNoIndex;
1273   }
1274   void AddAssignedValue(int index, HValue* value) {
1275     AddValue(index, value);
1276   }
1277   void AddPushedValue(HValue* value) {
1278     AddValue(kNoIndex, value);
1279   }
1280   virtual int OperandCount() { return values_.length(); }
1281   virtual HValue* OperandAt(int index) { return values_[index]; }
1282
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:
1294   virtual void InternalSetOperandAt(int index, HValue* value) {
1295     values_[index] = value;
1296   }
1297
1298  private:
1299   static const int kNoIndex = -1;
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
1322   HStackCheck(HValue* context, Type type) : type_(type) {
1323     SetOperandAt(0, context);
1324   }
1325
1326   HValue* context() { return OperandAt(0); }
1327
1328   virtual Representation RequiredInputRepresentation(int index) {
1329     return Representation::Tagged();
1330   }
1331
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
1340   bool is_function_entry() { return type_ == kFunctionEntry; }
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), qml_global_(false) {
1512     set_representation(Representation::Tagged());
1513     SetFlag(kUseGVN);
1514   }
1515
1516   virtual void PrintDataTo(StringStream* stream);
1517
1518   DECLARE_CONCRETE_INSTRUCTION(GlobalObject)
1519
1520   virtual Representation RequiredInputRepresentation(int index) {
1521     return Representation::Tagged();
1522   }
1523
1524   bool qml_global() { return qml_global_; }
1525   void set_qml_global(bool v) { qml_global_ = v; }
1526
1527  protected:
1528   virtual bool DataEquals(HValue* other) {
1529       HGlobalObject* o = HGlobalObject::cast(other);
1530       return o->qml_global_ == qml_global_;
1531   }
1532
1533  private:
1534   bool qml_global_;
1535 };
1536
1537
1538 class HGlobalReceiver: public HUnaryOperation {
1539  public:
1540   explicit HGlobalReceiver(HValue* global_object)
1541       : HUnaryOperation(global_object) {
1542     set_representation(Representation::Tagged());
1543     SetFlag(kUseGVN);
1544   }
1545
1546   DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver)
1547
1548   virtual Representation RequiredInputRepresentation(int index) {
1549     return Representation::Tagged();
1550   }
1551
1552  protected:
1553   virtual bool DataEquals(HValue* other) { return true; }
1554 };
1555
1556
1557 template <int V>
1558 class HCall: public HTemplateInstruction<V> {
1559  public:
1560   // The argument count includes the receiver.
1561   explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
1562     this->set_representation(Representation::Tagged());
1563     this->SetAllSideEffects();
1564   }
1565
1566   virtual HType CalculateInferredType() { return HType::Tagged(); }
1567
1568   virtual int argument_count() const { return argument_count_; }
1569
1570   virtual bool IsCall() { return true; }
1571
1572  private:
1573   int argument_count_;
1574 };
1575
1576
1577 class HUnaryCall: public HCall<1> {
1578  public:
1579   HUnaryCall(HValue* value, int argument_count)
1580       : HCall<1>(argument_count) {
1581     SetOperandAt(0, value);
1582   }
1583
1584   virtual Representation RequiredInputRepresentation(int index) {
1585     return Representation::Tagged();
1586   }
1587
1588   virtual void PrintDataTo(StringStream* stream);
1589
1590   HValue* value() { return OperandAt(0); }
1591 };
1592
1593
1594 class HBinaryCall: public HCall<2> {
1595  public:
1596   HBinaryCall(HValue* first, HValue* second, int argument_count)
1597       : HCall<2>(argument_count) {
1598     SetOperandAt(0, first);
1599     SetOperandAt(1, second);
1600   }
1601
1602   virtual void PrintDataTo(StringStream* stream);
1603
1604   virtual Representation RequiredInputRepresentation(int index) {
1605     return Representation::Tagged();
1606   }
1607
1608   HValue* first() { return OperandAt(0); }
1609   HValue* second() { return OperandAt(1); }
1610 };
1611
1612
1613 class HInvokeFunction: public HBinaryCall {
1614  public:
1615   HInvokeFunction(HValue* context, HValue* function, int argument_count)
1616       : HBinaryCall(context, function, argument_count) {
1617   }
1618
1619   virtual Representation RequiredInputRepresentation(int index) {
1620     return Representation::Tagged();
1621   }
1622
1623   HValue* context() { return first(); }
1624   HValue* function() { return second(); }
1625
1626   DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
1627 };
1628
1629
1630 class HCallConstantFunction: public HCall<0> {
1631  public:
1632   HCallConstantFunction(Handle<JSFunction> function, int argument_count)
1633       : HCall<0>(argument_count), function_(function) { }
1634
1635   Handle<JSFunction> function() const { return function_; }
1636
1637   bool IsApplyFunction() const {
1638     return function_->code() ==
1639         Isolate::Current()->builtins()->builtin(Builtins::kFunctionApply);
1640   }
1641
1642   virtual void PrintDataTo(StringStream* stream);
1643
1644   virtual Representation RequiredInputRepresentation(int index) {
1645     return Representation::None();
1646   }
1647
1648   DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction)
1649
1650  private:
1651   Handle<JSFunction> function_;
1652 };
1653
1654
1655 class HCallKeyed: public HBinaryCall {
1656  public:
1657   HCallKeyed(HValue* context, HValue* key, int argument_count)
1658       : HBinaryCall(context, key, argument_count) {
1659   }
1660
1661   virtual Representation RequiredInputRepresentation(int index) {
1662     return Representation::Tagged();
1663   }
1664
1665   HValue* context() { return first(); }
1666   HValue* key() { return second(); }
1667
1668   DECLARE_CONCRETE_INSTRUCTION(CallKeyed)
1669 };
1670
1671
1672 class HCallNamed: public HUnaryCall {
1673  public:
1674   HCallNamed(HValue* context, Handle<String> name, int argument_count)
1675       : HUnaryCall(context, argument_count), name_(name) {
1676   }
1677
1678   virtual void PrintDataTo(StringStream* stream);
1679
1680   HValue* context() { return value(); }
1681   Handle<String> name() const { return name_; }
1682
1683   DECLARE_CONCRETE_INSTRUCTION(CallNamed)
1684
1685   virtual Representation RequiredInputRepresentation(int index) {
1686     return Representation::Tagged();
1687   }
1688
1689  private:
1690   Handle<String> name_;
1691 };
1692
1693
1694 class HCallFunction: public HBinaryCall {
1695  public:
1696   HCallFunction(HValue* context, HValue* function, int argument_count)
1697       : HBinaryCall(context, function, argument_count) {
1698   }
1699
1700   HValue* context() { return first(); }
1701   HValue* function() { return second(); }
1702
1703   virtual Representation RequiredInputRepresentation(int index) {
1704     return Representation::Tagged();
1705   }
1706
1707   DECLARE_CONCRETE_INSTRUCTION(CallFunction)
1708 };
1709
1710
1711 class HCallGlobal: public HUnaryCall {
1712  public:
1713   HCallGlobal(HValue* context, Handle<String> name, int argument_count)
1714       : HUnaryCall(context, argument_count), name_(name), qml_global_(false) {
1715   }
1716
1717   virtual void PrintDataTo(StringStream* stream);
1718
1719   HValue* context() { return value(); }
1720   Handle<String> name() const { return name_; }
1721
1722   virtual Representation RequiredInputRepresentation(int index) {
1723     return Representation::Tagged();
1724   }
1725
1726   bool qml_global() { return qml_global_; }
1727   void set_qml_global(bool v) { qml_global_ = v; }
1728
1729   DECLARE_CONCRETE_INSTRUCTION(CallGlobal)
1730
1731  private:
1732   Handle<String> name_;
1733   bool qml_global_;
1734 };
1735
1736
1737 class HCallKnownGlobal: public HCall<0> {
1738  public:
1739   HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
1740       : HCall<0>(argument_count), target_(target) { }
1741
1742   virtual void PrintDataTo(StringStream* stream);
1743
1744   Handle<JSFunction> target() const { return target_; }
1745
1746   virtual Representation RequiredInputRepresentation(int index) {
1747     return Representation::None();
1748   }
1749
1750   DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal)
1751
1752  private:
1753   Handle<JSFunction> target_;
1754 };
1755
1756
1757 class HCallNew: public HBinaryCall {
1758  public:
1759   HCallNew(HValue* context, HValue* constructor, int argument_count)
1760       : HBinaryCall(context, constructor, argument_count) {
1761   }
1762
1763   virtual Representation RequiredInputRepresentation(int index) {
1764     return Representation::Tagged();
1765   }
1766
1767   HValue* context() { return first(); }
1768   HValue* constructor() { return second(); }
1769
1770   DECLARE_CONCRETE_INSTRUCTION(CallNew)
1771 };
1772
1773
1774 class HCallRuntime: public HCall<1> {
1775  public:
1776   HCallRuntime(HValue* context,
1777                Handle<String> name,
1778                const Runtime::Function* c_function,
1779                int argument_count)
1780       : HCall<1>(argument_count), c_function_(c_function), name_(name) {
1781     SetOperandAt(0, context);
1782   }
1783
1784   virtual void PrintDataTo(StringStream* stream);
1785
1786   HValue* context() { return OperandAt(0); }
1787   const Runtime::Function* function() const { return c_function_; }
1788   Handle<String> name() const { return name_; }
1789
1790   virtual Representation RequiredInputRepresentation(int index) {
1791     return Representation::Tagged();
1792   }
1793
1794   DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
1795
1796  private:
1797   const Runtime::Function* c_function_;
1798   Handle<String> name_;
1799 };
1800
1801
1802 class HJSArrayLength: public HTemplateInstruction<2> {
1803  public:
1804   HJSArrayLength(HValue* value, HValue* typecheck) {
1805     // The length of an array is stored as a tagged value in the array
1806     // object. It is guaranteed to be 32 bit integer, but it can be
1807     // represented as either a smi or heap number.
1808     SetOperandAt(0, value);
1809     SetOperandAt(1, typecheck);
1810     set_representation(Representation::Tagged());
1811     SetFlag(kUseGVN);
1812     SetGVNFlag(kDependsOnArrayLengths);
1813     SetGVNFlag(kDependsOnMaps);
1814   }
1815
1816   virtual Representation RequiredInputRepresentation(int index) {
1817     return Representation::Tagged();
1818   }
1819
1820   virtual void PrintDataTo(StringStream* stream);
1821
1822   HValue* value() { return OperandAt(0); }
1823   HValue* typecheck() { return OperandAt(1); }
1824
1825   DECLARE_CONCRETE_INSTRUCTION(JSArrayLength)
1826
1827  protected:
1828   virtual bool DataEquals(HValue* other) { return true; }
1829 };
1830
1831
1832 class HFixedArrayBaseLength: public HUnaryOperation {
1833  public:
1834   explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) {
1835     set_representation(Representation::Tagged());
1836     SetFlag(kUseGVN);
1837     SetGVNFlag(kDependsOnArrayLengths);
1838   }
1839
1840   virtual Representation RequiredInputRepresentation(int index) {
1841     return Representation::Tagged();
1842   }
1843
1844   DECLARE_CONCRETE_INSTRUCTION(FixedArrayBaseLength)
1845
1846  protected:
1847   virtual bool DataEquals(HValue* other) { return true; }
1848 };
1849
1850
1851 class HElementsKind: public HUnaryOperation {
1852  public:
1853   explicit HElementsKind(HValue* value) : HUnaryOperation(value) {
1854     set_representation(Representation::Integer32());
1855     SetFlag(kUseGVN);
1856     SetGVNFlag(kDependsOnElementsKind);
1857   }
1858
1859   virtual Representation RequiredInputRepresentation(int index) {
1860     return Representation::Tagged();
1861   }
1862
1863   DECLARE_CONCRETE_INSTRUCTION(ElementsKind)
1864
1865  protected:
1866   virtual bool DataEquals(HValue* other) { return true; }
1867 };
1868
1869
1870 class HBitNot: public HUnaryOperation {
1871  public:
1872   explicit HBitNot(HValue* value) : HUnaryOperation(value) {
1873     set_representation(Representation::Integer32());
1874     SetFlag(kUseGVN);
1875     SetFlag(kTruncatingToInt32);
1876   }
1877
1878   virtual Representation RequiredInputRepresentation(int index) {
1879     return Representation::Integer32();
1880   }
1881   virtual HType CalculateInferredType();
1882
1883   DECLARE_CONCRETE_INSTRUCTION(BitNot)
1884
1885  protected:
1886   virtual bool DataEquals(HValue* other) { return true; }
1887 };
1888
1889
1890 class HUnaryMathOperation: public HTemplateInstruction<2> {
1891  public:
1892   HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
1893       : op_(op) {
1894     SetOperandAt(0, context);
1895     SetOperandAt(1, value);
1896     switch (op) {
1897       case kMathFloor:
1898       case kMathRound:
1899       case kMathCeil:
1900         set_representation(Representation::Integer32());
1901         break;
1902       case kMathAbs:
1903         set_representation(Representation::Tagged());
1904         SetFlag(kFlexibleRepresentation);
1905         break;
1906       case kMathSqrt:
1907       case kMathPowHalf:
1908       case kMathLog:
1909       case kMathSin:
1910       case kMathCos:
1911       case kMathTan:
1912         set_representation(Representation::Double());
1913         break;
1914       default:
1915         UNREACHABLE();
1916     }
1917     SetFlag(kUseGVN);
1918   }
1919
1920   HValue* context() { return OperandAt(0); }
1921   HValue* value() { return OperandAt(1); }
1922
1923   virtual void PrintDataTo(StringStream* stream);
1924
1925   virtual HType CalculateInferredType();
1926
1927   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1928
1929   virtual Representation RequiredInputRepresentation(int index) {
1930     if (index == 0) {
1931       return Representation::Tagged();
1932     } else {
1933       switch (op_) {
1934         case kMathFloor:
1935         case kMathRound:
1936         case kMathCeil:
1937         case kMathSqrt:
1938         case kMathPowHalf:
1939         case kMathLog:
1940         case kMathSin:
1941         case kMathCos:
1942         case kMathTan:
1943           return Representation::Double();
1944         case kMathAbs:
1945           return representation();
1946         default:
1947           UNREACHABLE();
1948           return Representation::None();
1949       }
1950     }
1951   }
1952
1953   virtual HValue* Canonicalize() {
1954     // If the input is integer32 then we replace the floor instruction
1955     // with its inputs.  This happens before the representation changes are
1956     // introduced.
1957     if (op() == kMathFloor) {
1958       if (value()->representation().IsInteger32()) return value();
1959     }
1960     return this;
1961   }
1962
1963   BuiltinFunctionId op() const { return op_; }
1964   const char* OpName() const;
1965
1966   DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
1967
1968  protected:
1969   virtual bool DataEquals(HValue* other) {
1970     HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
1971     return op_ == b->op();
1972   }
1973
1974  private:
1975   BuiltinFunctionId op_;
1976 };
1977
1978
1979 class HLoadElements: public HUnaryOperation {
1980  public:
1981   explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
1982     set_representation(Representation::Tagged());
1983     SetFlag(kUseGVN);
1984     SetGVNFlag(kDependsOnElementsPointer);
1985   }
1986
1987   virtual Representation RequiredInputRepresentation(int index) {
1988     return Representation::Tagged();
1989   }
1990
1991   DECLARE_CONCRETE_INSTRUCTION(LoadElements)
1992
1993  protected:
1994   virtual bool DataEquals(HValue* other) { return true; }
1995 };
1996
1997
1998 class HLoadExternalArrayPointer: public HUnaryOperation {
1999  public:
2000   explicit HLoadExternalArrayPointer(HValue* value)
2001       : HUnaryOperation(value) {
2002     set_representation(Representation::External());
2003     // The result of this instruction is idempotent as long as its inputs don't
2004     // change.  The external array of a specialized array elements object cannot
2005     // change once set, so it's no necessary to introduce any additional
2006     // dependencies on top of the inputs.
2007     SetFlag(kUseGVN);
2008   }
2009
2010   virtual Representation RequiredInputRepresentation(int index) {
2011     return Representation::Tagged();
2012   }
2013
2014   DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer)
2015
2016  protected:
2017   virtual bool DataEquals(HValue* other) { return true; }
2018 };
2019
2020
2021 class HCheckMaps: public HTemplateInstruction<2> {
2022  public:
2023   HCheckMaps(HValue* value, Handle<Map> map, HValue* typecheck = NULL) {
2024     SetOperandAt(0, value);
2025     // If callers don't depend on a typecheck, they can pass in NULL. In that
2026     // case we use a copy of the |value| argument as a dummy value.
2027     SetOperandAt(1, typecheck != NULL ? typecheck : value);
2028     set_representation(Representation::Tagged());
2029     SetFlag(kUseGVN);
2030     SetGVNFlag(kDependsOnMaps);
2031     SetGVNFlag(kDependsOnElementsKind);
2032     map_set()->Add(map);
2033   }
2034   HCheckMaps(HValue* value, SmallMapList* maps) {
2035     SetOperandAt(0, value);
2036     SetOperandAt(1, value);
2037     set_representation(Representation::Tagged());
2038     SetFlag(kUseGVN);
2039     SetGVNFlag(kDependsOnMaps);
2040     SetGVNFlag(kDependsOnElementsKind);
2041     for (int i = 0; i < maps->length(); i++) {
2042       map_set()->Add(maps->at(i));
2043     }
2044     map_set()->Sort();
2045   }
2046
2047   static HCheckMaps* NewWithTransitions(HValue* object, Handle<Map> map) {
2048     HCheckMaps* check_map = new HCheckMaps(object, map);
2049     SmallMapList* map_set = check_map->map_set();
2050
2051     // If the map to check has the untransitioned elements, it can be hoisted
2052     // above TransitionElements instructions.
2053     if (map->has_fast_smi_only_elements()) {
2054       check_map->ClearGVNFlag(kDependsOnElementsKind);
2055     }
2056
2057     Map* transitioned_fast_element_map =
2058         map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL);
2059     ASSERT(transitioned_fast_element_map == NULL ||
2060            map->elements_kind() != FAST_ELEMENTS);
2061     if (transitioned_fast_element_map != NULL) {
2062       map_set->Add(Handle<Map>(transitioned_fast_element_map));
2063     }
2064     Map* transitioned_double_map =
2065         map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL);
2066     ASSERT(transitioned_double_map == NULL ||
2067            map->elements_kind() == FAST_SMI_ONLY_ELEMENTS);
2068     if (transitioned_double_map != NULL) {
2069       map_set->Add(Handle<Map>(transitioned_double_map));
2070     }
2071     map_set->Sort();
2072
2073     return check_map;
2074   }
2075
2076   virtual Representation RequiredInputRepresentation(int index) {
2077     return Representation::Tagged();
2078   }
2079   virtual void PrintDataTo(StringStream* stream);
2080   virtual HType CalculateInferredType();
2081
2082   HValue* value() { return OperandAt(0); }
2083   SmallMapList* map_set() { return &map_set_; }
2084
2085   DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
2086
2087  protected:
2088   virtual bool DataEquals(HValue* other) {
2089     HCheckMaps* b = HCheckMaps::cast(other);
2090     // Relies on the fact that map_set has been sorted before.
2091     if (map_set()->length() != b->map_set()->length()) return false;
2092     for (int i = 0; i < map_set()->length(); i++) {
2093       if (!map_set()->at(i).is_identical_to(b->map_set()->at(i))) return false;
2094     }
2095     return true;
2096   }
2097
2098  private:
2099   SmallMapList map_set_;
2100 };
2101
2102
2103 class HCheckFunction: public HUnaryOperation {
2104  public:
2105   HCheckFunction(HValue* value, Handle<JSFunction> function)
2106       : HUnaryOperation(value), target_(function) {
2107     set_representation(Representation::Tagged());
2108     SetFlag(kUseGVN);
2109   }
2110
2111   virtual Representation RequiredInputRepresentation(int index) {
2112     return Representation::Tagged();
2113   }
2114   virtual void PrintDataTo(StringStream* stream);
2115   virtual HType CalculateInferredType();
2116
2117 #ifdef DEBUG
2118   virtual void Verify();
2119 #endif
2120
2121   Handle<JSFunction> target() const { return target_; }
2122
2123   DECLARE_CONCRETE_INSTRUCTION(CheckFunction)
2124
2125  protected:
2126   virtual bool DataEquals(HValue* other) {
2127     HCheckFunction* b = HCheckFunction::cast(other);
2128     return target_.is_identical_to(b->target());
2129   }
2130
2131  private:
2132   Handle<JSFunction> target_;
2133 };
2134
2135
2136 class HCheckInstanceType: public HUnaryOperation {
2137  public:
2138   static HCheckInstanceType* NewIsSpecObject(HValue* value) {
2139     return new HCheckInstanceType(value, IS_SPEC_OBJECT);
2140   }
2141   static HCheckInstanceType* NewIsJSArray(HValue* value) {
2142     return new HCheckInstanceType(value, IS_JS_ARRAY);
2143   }
2144   static HCheckInstanceType* NewIsString(HValue* value) {
2145     return new HCheckInstanceType(value, IS_STRING);
2146   }
2147   static HCheckInstanceType* NewIsSymbol(HValue* value) {
2148     return new HCheckInstanceType(value, IS_SYMBOL);
2149   }
2150
2151   virtual void PrintDataTo(StringStream* stream);
2152
2153   virtual Representation RequiredInputRepresentation(int index) {
2154     return Representation::Tagged();
2155   }
2156
2157   virtual HValue* Canonicalize();
2158
2159   bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
2160   void GetCheckInterval(InstanceType* first, InstanceType* last);
2161   void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
2162
2163   DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
2164
2165  protected:
2166   // TODO(ager): It could be nice to allow the ommision of instance
2167   // type checks if we have already performed an instance type check
2168   // with a larger range.
2169   virtual bool DataEquals(HValue* other) {
2170     HCheckInstanceType* b = HCheckInstanceType::cast(other);
2171     return check_ == b->check_;
2172   }
2173
2174  private:
2175   enum Check {
2176     IS_SPEC_OBJECT,
2177     IS_JS_ARRAY,
2178     IS_STRING,
2179     IS_SYMBOL,
2180     LAST_INTERVAL_CHECK = IS_JS_ARRAY
2181   };
2182
2183   const char* GetCheckName();
2184
2185   HCheckInstanceType(HValue* value, Check check)
2186       : HUnaryOperation(value), check_(check) {
2187     set_representation(Representation::Tagged());
2188     SetFlag(kUseGVN);
2189   }
2190
2191   const Check check_;
2192 };
2193
2194
2195 class HCheckNonSmi: public HUnaryOperation {
2196  public:
2197   explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
2198     set_representation(Representation::Tagged());
2199     SetFlag(kUseGVN);
2200   }
2201
2202   virtual Representation RequiredInputRepresentation(int index) {
2203     return Representation::Tagged();
2204   }
2205
2206   virtual HType CalculateInferredType();
2207
2208 #ifdef DEBUG
2209   virtual void Verify();
2210 #endif
2211
2212   virtual HValue* Canonicalize() {
2213     HType value_type = value()->type();
2214     if (!value_type.IsUninitialized() &&
2215         (value_type.IsHeapNumber() ||
2216          value_type.IsString() ||
2217          value_type.IsBoolean() ||
2218          value_type.IsNonPrimitive())) {
2219       return NULL;
2220     }
2221     return this;
2222   }
2223
2224   DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi)
2225
2226  protected:
2227   virtual bool DataEquals(HValue* other) { return true; }
2228 };
2229
2230
2231 class HCheckPrototypeMaps: public HTemplateInstruction<0> {
2232  public:
2233   HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
2234       : prototype_(prototype), holder_(holder) {
2235     SetFlag(kUseGVN);
2236     SetGVNFlag(kDependsOnMaps);
2237   }
2238
2239 #ifdef DEBUG
2240   virtual void Verify();
2241 #endif
2242
2243   Handle<JSObject> prototype() const { return prototype_; }
2244   Handle<JSObject> holder() const { return holder_; }
2245
2246   DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps)
2247
2248   virtual Representation RequiredInputRepresentation(int index) {
2249     return Representation::None();
2250   }
2251
2252   virtual intptr_t Hashcode() {
2253     ASSERT(!HEAP->IsAllocationAllowed());
2254     intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
2255     hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
2256     return hash;
2257   }
2258
2259  protected:
2260   virtual bool DataEquals(HValue* other) {
2261     HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
2262     return prototype_.is_identical_to(b->prototype()) &&
2263         holder_.is_identical_to(b->holder());
2264   }
2265
2266  private:
2267   Handle<JSObject> prototype_;
2268   Handle<JSObject> holder_;
2269 };
2270
2271
2272 class HCheckSmi: public HUnaryOperation {
2273  public:
2274   explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
2275     set_representation(Representation::Tagged());
2276     SetFlag(kUseGVN);
2277   }
2278
2279   virtual Representation RequiredInputRepresentation(int index) {
2280     return Representation::Tagged();
2281   }
2282   virtual HType CalculateInferredType();
2283
2284 #ifdef DEBUG
2285   virtual void Verify();
2286 #endif
2287
2288   DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
2289
2290  protected:
2291   virtual bool DataEquals(HValue* other) { return true; }
2292 };
2293
2294
2295 class HPhi: public HValue {
2296  public:
2297   explicit HPhi(int merged_index)
2298       : inputs_(2),
2299         merged_index_(merged_index),
2300         phi_id_(-1),
2301         is_live_(false),
2302         is_convertible_to_integer_(true) {
2303     for (int i = 0; i < Representation::kNumRepresentations; i++) {
2304       non_phi_uses_[i] = 0;
2305       indirect_uses_[i] = 0;
2306     }
2307     ASSERT(merged_index >= 0);
2308     set_representation(Representation::Tagged());
2309     SetFlag(kFlexibleRepresentation);
2310   }
2311
2312   virtual Representation InferredRepresentation();
2313
2314   virtual Range* InferRange(Zone* zone);
2315   virtual Representation RequiredInputRepresentation(int index) {
2316     return representation();
2317   }
2318   virtual HType CalculateInferredType();
2319   virtual int OperandCount() { return inputs_.length(); }
2320   virtual HValue* OperandAt(int index) { return inputs_[index]; }
2321   HValue* GetRedundantReplacement();
2322   void AddInput(HValue* value);
2323   bool HasRealUses();
2324
2325   bool IsReceiver() { return merged_index_ == 0; }
2326
2327   int merged_index() const { return merged_index_; }
2328
2329   virtual void PrintTo(StringStream* stream);
2330
2331 #ifdef DEBUG
2332   virtual void Verify();
2333 #endif
2334
2335   void InitRealUses(int id);
2336   void AddNonPhiUsesFrom(HPhi* other);
2337   void AddIndirectUsesTo(int* use_count);
2338
2339   int tagged_non_phi_uses() const {
2340     return non_phi_uses_[Representation::kTagged];
2341   }
2342   int int32_non_phi_uses() const {
2343     return non_phi_uses_[Representation::kInteger32];
2344   }
2345   int double_non_phi_uses() const {
2346     return non_phi_uses_[Representation::kDouble];
2347   }
2348   int tagged_indirect_uses() const {
2349     return indirect_uses_[Representation::kTagged];
2350   }
2351   int int32_indirect_uses() const {
2352     return indirect_uses_[Representation::kInteger32];
2353   }
2354   int double_indirect_uses() const {
2355     return indirect_uses_[Representation::kDouble];
2356   }
2357   int phi_id() { return phi_id_; }
2358   bool is_live() { return is_live_; }
2359   void set_is_live(bool b) { is_live_ = b; }
2360
2361   static HPhi* cast(HValue* value) {
2362     ASSERT(value->IsPhi());
2363     return reinterpret_cast<HPhi*>(value);
2364   }
2365   virtual Opcode opcode() const { return HValue::kPhi; }
2366
2367   virtual bool IsConvertibleToInteger() const {
2368     return is_convertible_to_integer_;
2369   }
2370
2371   void set_is_convertible_to_integer(bool b) {
2372     is_convertible_to_integer_ = b;
2373   }
2374
2375   bool AllOperandsConvertibleToInteger() {
2376     for (int i = 0; i < OperandCount(); ++i) {
2377       if (!OperandAt(i)->IsConvertibleToInteger()) return false;
2378     }
2379     return true;
2380   }
2381
2382  protected:
2383   virtual void DeleteFromGraph();
2384   virtual void InternalSetOperandAt(int index, HValue* value) {
2385     inputs_[index] = value;
2386   }
2387
2388  private:
2389   ZoneList<HValue*> inputs_;
2390   int merged_index_;
2391
2392   int non_phi_uses_[Representation::kNumRepresentations];
2393   int indirect_uses_[Representation::kNumRepresentations];
2394   int phi_id_;
2395   bool is_live_;
2396   bool is_convertible_to_integer_;
2397 };
2398
2399
2400 class HArgumentsObject: public HTemplateInstruction<0> {
2401  public:
2402   HArgumentsObject() {
2403     set_representation(Representation::Tagged());
2404     SetFlag(kIsArguments);
2405   }
2406
2407   virtual Representation RequiredInputRepresentation(int index) {
2408     return Representation::None();
2409   }
2410
2411   DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
2412 };
2413
2414
2415 class HConstant: public HTemplateInstruction<0> {
2416  public:
2417   HConstant(Handle<Object> handle, Representation r);
2418
2419   Handle<Object> handle() const { return handle_; }
2420
2421   bool InOldSpace() const { return !HEAP->InNewSpace(*handle_); }
2422
2423   bool ImmortalImmovable() const {
2424     Heap* heap = HEAP;
2425     if (*handle_ == heap->undefined_value()) return true;
2426     if (*handle_ == heap->null_value()) return true;
2427     if (*handle_ == heap->true_value()) return true;
2428     if (*handle_ == heap->false_value()) return true;
2429     if (*handle_ == heap->the_hole_value()) return true;
2430     if (*handle_ == heap->minus_zero_value()) return true;
2431     if (*handle_ == heap->nan_value()) return true;
2432     if (*handle_ == heap->empty_string()) return true;
2433     return false;
2434   }
2435
2436   virtual Representation RequiredInputRepresentation(int index) {
2437     return Representation::None();
2438   }
2439
2440   virtual bool IsConvertibleToInteger() const {
2441     if (handle_->IsSmi()) return true;
2442     if (handle_->IsHeapNumber() &&
2443         (HeapNumber::cast(*handle_)->value() ==
2444          static_cast<double>(NumberToInt32(*handle_)))) return true;
2445     return false;
2446   }
2447
2448   virtual bool EmitAtUses() { return !representation().IsDouble(); }
2449   virtual HValue* Canonicalize();
2450   virtual void PrintDataTo(StringStream* stream);
2451   virtual HType CalculateInferredType();
2452   bool IsInteger() const { return handle_->IsSmi(); }
2453   HConstant* CopyToRepresentation(Representation r) const;
2454   HConstant* CopyToTruncatedInt32() const;
2455   bool HasInteger32Value() const { return has_int32_value_; }
2456   int32_t Integer32Value() const {
2457     ASSERT(HasInteger32Value());
2458     return int32_value_;
2459   }
2460   bool HasDoubleValue() const { return has_double_value_; }
2461   double DoubleValue() const {
2462     ASSERT(HasDoubleValue());
2463     return double_value_;
2464   }
2465   bool HasNumberValue() const { return has_int32_value_ || has_double_value_; }
2466   int32_t NumberValueAsInteger32() const {
2467     ASSERT(HasNumberValue());
2468     if (has_int32_value_) return int32_value_;
2469     return DoubleToInt32(double_value_);
2470   }
2471   bool HasStringValue() const { return handle_->IsString(); }
2472
2473   bool ToBoolean() const;
2474
2475   virtual intptr_t Hashcode() {
2476     ASSERT(!HEAP->allow_allocation(false));
2477     intptr_t hash = reinterpret_cast<intptr_t>(*handle());
2478     // Prevent smis from having fewer hash values when truncated to
2479     // the least significant bits.
2480     const int kShiftSize = kSmiShiftSize + kSmiTagSize;
2481     STATIC_ASSERT(kShiftSize != 0);
2482     return hash ^ (hash >> kShiftSize);
2483   }
2484
2485 #ifdef DEBUG
2486   virtual void Verify() { }
2487 #endif
2488
2489   DECLARE_CONCRETE_INSTRUCTION(Constant)
2490
2491  protected:
2492   virtual Range* InferRange(Zone* zone);
2493
2494   virtual bool DataEquals(HValue* other) {
2495     HConstant* other_constant = HConstant::cast(other);
2496     return handle().is_identical_to(other_constant->handle());
2497   }
2498
2499  private:
2500   Handle<Object> handle_;
2501
2502   // The following two values represent the int32 and the double value of the
2503   // given constant if there is a lossless conversion between the constant
2504   // and the specific representation.
2505   bool has_int32_value_ : 1;
2506   bool has_double_value_ : 1;
2507   int32_t int32_value_;
2508   double double_value_;
2509 };
2510
2511
2512 class HBinaryOperation: public HTemplateInstruction<3> {
2513  public:
2514   HBinaryOperation(HValue* context, HValue* left, HValue* right) {
2515     ASSERT(left != NULL && right != NULL);
2516     SetOperandAt(0, context);
2517     SetOperandAt(1, left);
2518     SetOperandAt(2, right);
2519   }
2520
2521   HValue* context() { return OperandAt(0); }
2522   HValue* left() { return OperandAt(1); }
2523   HValue* right() { return OperandAt(2); }
2524
2525   // TODO(kasperl): Move these helpers to the IA-32 Lithium
2526   // instruction sequence builder.
2527   HValue* LeastConstantOperand() {
2528     if (IsCommutative() && left()->IsConstant()) return right();
2529     return left();
2530   }
2531   HValue* MostConstantOperand() {
2532     if (IsCommutative() && left()->IsConstant()) return left();
2533     return right();
2534   }
2535
2536   virtual bool IsCommutative() const { return false; }
2537
2538   virtual void PrintDataTo(StringStream* stream);
2539 };
2540
2541
2542 class HWrapReceiver: public HTemplateInstruction<2> {
2543  public:
2544   HWrapReceiver(HValue* receiver, HValue* function) {
2545     set_representation(Representation::Tagged());
2546     SetOperandAt(0, receiver);
2547     SetOperandAt(1, function);
2548   }
2549
2550   virtual Representation RequiredInputRepresentation(int index) {
2551     return Representation::Tagged();
2552   }
2553
2554   HValue* receiver() { return OperandAt(0); }
2555   HValue* function() { return OperandAt(1); }
2556
2557   virtual HValue* Canonicalize();
2558
2559   DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
2560 };
2561
2562
2563 class HApplyArguments: public HTemplateInstruction<4> {
2564  public:
2565   HApplyArguments(HValue* function,
2566                   HValue* receiver,
2567                   HValue* length,
2568                   HValue* elements) {
2569     set_representation(Representation::Tagged());
2570     SetOperandAt(0, function);
2571     SetOperandAt(1, receiver);
2572     SetOperandAt(2, length);
2573     SetOperandAt(3, elements);
2574     SetAllSideEffects();
2575   }
2576
2577   virtual Representation RequiredInputRepresentation(int index) {
2578     // The length is untagged, all other inputs are tagged.
2579     return (index == 2)
2580         ? Representation::Integer32()
2581         : Representation::Tagged();
2582   }
2583
2584   HValue* function() { return OperandAt(0); }
2585   HValue* receiver() { return OperandAt(1); }
2586   HValue* length() { return OperandAt(2); }
2587   HValue* elements() { return OperandAt(3); }
2588
2589   DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
2590 };
2591
2592
2593 class HArgumentsElements: public HTemplateInstruction<0> {
2594  public:
2595   HArgumentsElements() {
2596     // The value produced by this instruction is a pointer into the stack
2597     // that looks as if it was a smi because of alignment.
2598     set_representation(Representation::Tagged());
2599     SetFlag(kUseGVN);
2600   }
2601
2602   DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
2603
2604   virtual Representation RequiredInputRepresentation(int index) {
2605     return Representation::None();
2606   }
2607
2608  protected:
2609   virtual bool DataEquals(HValue* other) { return true; }
2610 };
2611
2612
2613 class HArgumentsLength: public HUnaryOperation {
2614  public:
2615   explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
2616     set_representation(Representation::Integer32());
2617     SetFlag(kUseGVN);
2618   }
2619
2620   virtual Representation RequiredInputRepresentation(int index) {
2621     return Representation::Tagged();
2622   }
2623
2624   DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
2625
2626  protected:
2627   virtual bool DataEquals(HValue* other) { return true; }
2628 };
2629
2630
2631 class HAccessArgumentsAt: public HTemplateInstruction<3> {
2632  public:
2633   HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
2634     set_representation(Representation::Tagged());
2635     SetFlag(kUseGVN);
2636     SetOperandAt(0, arguments);
2637     SetOperandAt(1, length);
2638     SetOperandAt(2, index);
2639   }
2640
2641   virtual void PrintDataTo(StringStream* stream);
2642
2643   virtual Representation RequiredInputRepresentation(int index) {
2644     // The arguments elements is considered tagged.
2645     return index == 0
2646         ? Representation::Tagged()
2647         : Representation::Integer32();
2648   }
2649
2650   HValue* arguments() { return OperandAt(0); }
2651   HValue* length() { return OperandAt(1); }
2652   HValue* index() { return OperandAt(2); }
2653
2654   DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
2655
2656   virtual bool DataEquals(HValue* other) { return true; }
2657 };
2658
2659
2660 class HBoundsCheck: public HTemplateInstruction<2> {
2661  public:
2662   HBoundsCheck(HValue* index, HValue* length) {
2663     SetOperandAt(0, index);
2664     SetOperandAt(1, length);
2665     set_representation(Representation::Integer32());
2666     SetFlag(kUseGVN);
2667   }
2668
2669   virtual Representation RequiredInputRepresentation(int index) {
2670     return Representation::Integer32();
2671   }
2672
2673   virtual void PrintDataTo(StringStream* stream);
2674
2675   HValue* index() { return OperandAt(0); }
2676   HValue* length() { return OperandAt(1); }
2677
2678   DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
2679
2680  protected:
2681   virtual bool DataEquals(HValue* other) { return true; }
2682 };
2683
2684
2685 class HBitwiseBinaryOperation: public HBinaryOperation {
2686  public:
2687   HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right)
2688       : HBinaryOperation(context, left, right) {
2689     set_representation(Representation::Tagged());
2690     SetFlag(kFlexibleRepresentation);
2691     SetAllSideEffects();
2692   }
2693
2694   virtual Representation RequiredInputRepresentation(int index) {
2695     return index == 0
2696         ? Representation::Tagged()
2697         : representation();
2698   }
2699
2700   virtual void RepresentationChanged(Representation to) {
2701     if (!to.IsTagged()) {
2702       ASSERT(to.IsInteger32());
2703       ClearAllSideEffects();
2704       SetFlag(kTruncatingToInt32);
2705       SetFlag(kUseGVN);
2706     }
2707   }
2708
2709   virtual HType CalculateInferredType();
2710
2711   DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
2712 };
2713
2714
2715 class HArithmeticBinaryOperation: public HBinaryOperation {
2716  public:
2717   HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right)
2718       : HBinaryOperation(context, left, right) {
2719     set_representation(Representation::Tagged());
2720     SetFlag(kFlexibleRepresentation);
2721     SetAllSideEffects();
2722   }
2723
2724   virtual void RepresentationChanged(Representation to) {
2725     if (!to.IsTagged()) {
2726       ClearAllSideEffects();
2727       SetFlag(kUseGVN);
2728     }
2729   }
2730
2731   virtual HType CalculateInferredType();
2732   virtual Representation RequiredInputRepresentation(int index) {
2733     return index == 0
2734         ? Representation::Tagged()
2735         : representation();
2736   }
2737
2738   virtual Representation InferredRepresentation() {
2739     if (left()->representation().Equals(right()->representation())) {
2740       return left()->representation();
2741     }
2742     return HValue::InferredRepresentation();
2743   }
2744 };
2745
2746
2747 class HCompareGeneric: public HBinaryOperation {
2748  public:
2749   HCompareGeneric(HValue* context,
2750                   HValue* left,
2751                   HValue* right,
2752                   Token::Value token)
2753       : HBinaryOperation(context, left, right), token_(token) {
2754     ASSERT(Token::IsCompareOp(token));
2755     set_representation(Representation::Tagged());
2756     SetAllSideEffects();
2757   }
2758
2759   virtual Representation RequiredInputRepresentation(int index) {
2760     return Representation::Tagged();
2761   }
2762
2763   Representation GetInputRepresentation() const {
2764     return Representation::Tagged();
2765   }
2766
2767   Token::Value token() const { return token_; }
2768   virtual void PrintDataTo(StringStream* stream);
2769
2770   virtual HType CalculateInferredType();
2771
2772   DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
2773
2774  private:
2775   Token::Value token_;
2776 };
2777
2778
2779 class HCompareIDAndBranch: public HTemplateControlInstruction<2, 2> {
2780  public:
2781   HCompareIDAndBranch(HValue* left, HValue* right, Token::Value token)
2782       : token_(token) {
2783     ASSERT(Token::IsCompareOp(token));
2784     SetOperandAt(0, left);
2785     SetOperandAt(1, right);
2786   }
2787
2788   HValue* left() { return OperandAt(0); }
2789   HValue* right() { return OperandAt(1); }
2790   Token::Value token() const { return token_; }
2791
2792   void SetInputRepresentation(Representation r);
2793   Representation GetInputRepresentation() const {
2794     return input_representation_;
2795   }
2796
2797   virtual Representation RequiredInputRepresentation(int index) {
2798     return input_representation_;
2799   }
2800   virtual void PrintDataTo(StringStream* stream);
2801
2802   DECLARE_CONCRETE_INSTRUCTION(CompareIDAndBranch)
2803
2804  private:
2805   Representation input_representation_;
2806   Token::Value token_;
2807 };
2808
2809
2810 class HCompareObjectEqAndBranch: public HTemplateControlInstruction<2, 2> {
2811  public:
2812   HCompareObjectEqAndBranch(HValue* left, HValue* right) {
2813     SetOperandAt(0, left);
2814     SetOperandAt(1, right);
2815   }
2816
2817   HValue* left() { return OperandAt(0); }
2818   HValue* right() { return OperandAt(1); }
2819
2820   virtual void PrintDataTo(StringStream* stream);
2821
2822   virtual Representation RequiredInputRepresentation(int index) {
2823     return Representation::Tagged();
2824   }
2825
2826   DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
2827 };
2828
2829
2830 class HCompareConstantEqAndBranch: public HUnaryControlInstruction {
2831  public:
2832   HCompareConstantEqAndBranch(HValue* left, int right, Token::Value op)
2833       : HUnaryControlInstruction(left, NULL, NULL), op_(op), right_(right) {
2834     ASSERT(op == Token::EQ_STRICT);
2835   }
2836
2837   Token::Value op() const { return op_; }
2838   HValue* left() { return value(); }
2839   int right() const { return right_; }
2840
2841   virtual Representation RequiredInputRepresentation(int index) {
2842     return Representation::Integer32();
2843   }
2844
2845   DECLARE_CONCRETE_INSTRUCTION(CompareConstantEqAndBranch);
2846
2847  private:
2848   const Token::Value op_;
2849   const int right_;
2850 };
2851
2852
2853 class HIsNilAndBranch: public HUnaryControlInstruction {
2854  public:
2855   HIsNilAndBranch(HValue* value, EqualityKind kind, NilValue nil)
2856       : HUnaryControlInstruction(value, NULL, NULL), kind_(kind), nil_(nil) { }
2857
2858   EqualityKind kind() const { return kind_; }
2859   NilValue nil() const { return nil_; }
2860
2861   virtual void PrintDataTo(StringStream* stream);
2862
2863   virtual Representation RequiredInputRepresentation(int index) {
2864     return Representation::Tagged();
2865   }
2866
2867   DECLARE_CONCRETE_INSTRUCTION(IsNilAndBranch)
2868
2869  private:
2870   EqualityKind kind_;
2871   NilValue nil_;
2872 };
2873
2874
2875 class HIsObjectAndBranch: public HUnaryControlInstruction {
2876  public:
2877   explicit HIsObjectAndBranch(HValue* value)
2878     : HUnaryControlInstruction(value, NULL, NULL) { }
2879
2880   virtual Representation RequiredInputRepresentation(int index) {
2881     return Representation::Tagged();
2882   }
2883
2884   DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch)
2885 };
2886
2887 class HIsStringAndBranch: public HUnaryControlInstruction {
2888  public:
2889   explicit HIsStringAndBranch(HValue* value)
2890     : HUnaryControlInstruction(value, NULL, NULL) { }
2891
2892   virtual Representation RequiredInputRepresentation(int index) {
2893     return Representation::Tagged();
2894   }
2895
2896   DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
2897 };
2898
2899
2900 class HIsSmiAndBranch: public HUnaryControlInstruction {
2901  public:
2902   explicit HIsSmiAndBranch(HValue* value)
2903       : HUnaryControlInstruction(value, NULL, NULL) { }
2904
2905   DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
2906
2907   virtual Representation RequiredInputRepresentation(int index) {
2908     return Representation::Tagged();
2909   }
2910
2911  protected:
2912   virtual bool DataEquals(HValue* other) { return true; }
2913 };
2914
2915
2916 class HIsUndetectableAndBranch: public HUnaryControlInstruction {
2917  public:
2918   explicit HIsUndetectableAndBranch(HValue* value)
2919       : HUnaryControlInstruction(value, NULL, NULL) { }
2920
2921   virtual Representation RequiredInputRepresentation(int index) {
2922     return Representation::Tagged();
2923   }
2924
2925   DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
2926 };
2927
2928
2929 class HStringCompareAndBranch: public HTemplateControlInstruction<2, 3> {
2930  public:
2931   HStringCompareAndBranch(HValue* context,
2932                            HValue* left,
2933                            HValue* right,
2934                            Token::Value token)
2935       : token_(token) {
2936     ASSERT(Token::IsCompareOp(token));
2937     SetOperandAt(0, context);
2938     SetOperandAt(1, left);
2939     SetOperandAt(2, right);
2940     set_representation(Representation::Tagged());
2941   }
2942
2943   HValue* context() { return OperandAt(0); }
2944   HValue* left() { return OperandAt(1); }
2945   HValue* right() { return OperandAt(2); }
2946   Token::Value token() const { return token_; }
2947
2948   virtual void PrintDataTo(StringStream* stream);
2949
2950   virtual Representation RequiredInputRepresentation(int index) {
2951     return Representation::Tagged();
2952   }
2953
2954   Representation GetInputRepresentation() const {
2955     return Representation::Tagged();
2956   }
2957
2958   DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
2959
2960  private:
2961   Token::Value token_;
2962 };
2963
2964
2965 class HIsConstructCallAndBranch: public HTemplateControlInstruction<2, 0> {
2966  public:
2967   virtual Representation RequiredInputRepresentation(int index) {
2968     return Representation::None();
2969   }
2970
2971   DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch)
2972 };
2973
2974
2975 class HHasInstanceTypeAndBranch: public HUnaryControlInstruction {
2976  public:
2977   HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
2978       : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
2979   HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
2980       : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
2981     ASSERT(to == LAST_TYPE);  // Others not implemented yet in backend.
2982   }
2983
2984   InstanceType from() { return from_; }
2985   InstanceType to() { return to_; }
2986
2987   virtual void PrintDataTo(StringStream* stream);
2988
2989   virtual Representation RequiredInputRepresentation(int index) {
2990     return Representation::Tagged();
2991   }
2992
2993   DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
2994
2995  private:
2996   InstanceType from_;
2997   InstanceType to_;  // Inclusive range, not all combinations work.
2998 };
2999
3000
3001 class HHasCachedArrayIndexAndBranch: public HUnaryControlInstruction {
3002  public:
3003   explicit HHasCachedArrayIndexAndBranch(HValue* value)
3004       : HUnaryControlInstruction(value, NULL, NULL) { }
3005
3006   virtual Representation RequiredInputRepresentation(int index) {
3007     return Representation::Tagged();
3008   }
3009
3010   DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
3011 };
3012
3013
3014 class HGetCachedArrayIndex: public HUnaryOperation {
3015  public:
3016   explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
3017     set_representation(Representation::Tagged());
3018     SetFlag(kUseGVN);
3019   }
3020
3021   virtual Representation RequiredInputRepresentation(int index) {
3022     return Representation::Tagged();
3023   }
3024
3025   DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
3026
3027  protected:
3028   virtual bool DataEquals(HValue* other) { return true; }
3029 };
3030
3031
3032 class HClassOfTestAndBranch: public HUnaryControlInstruction {
3033  public:
3034   HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
3035       : HUnaryControlInstruction(value, NULL, NULL),
3036         class_name_(class_name) { }
3037
3038   DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
3039
3040   virtual Representation RequiredInputRepresentation(int index) {
3041     return Representation::Tagged();
3042   }
3043
3044   virtual void PrintDataTo(StringStream* stream);
3045
3046   Handle<String> class_name() const { return class_name_; }
3047
3048  private:
3049   Handle<String> class_name_;
3050 };
3051
3052
3053 class HTypeofIsAndBranch: public HUnaryControlInstruction {
3054  public:
3055   HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
3056       : HUnaryControlInstruction(value, NULL, NULL),
3057         type_literal_(type_literal) { }
3058
3059   Handle<String> type_literal() { return type_literal_; }
3060   virtual void PrintDataTo(StringStream* stream);
3061
3062   DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
3063
3064   virtual Representation RequiredInputRepresentation(int index) {
3065     return Representation::Tagged();
3066   }
3067
3068  private:
3069   Handle<String> type_literal_;
3070 };
3071
3072
3073 class HInstanceOf: public HBinaryOperation {
3074  public:
3075   HInstanceOf(HValue* context, HValue* left, HValue* right)
3076       : HBinaryOperation(context, left, right) {
3077     set_representation(Representation::Tagged());
3078     SetAllSideEffects();
3079   }
3080
3081   virtual Representation RequiredInputRepresentation(int index) {
3082     return Representation::Tagged();
3083   }
3084
3085   virtual HType CalculateInferredType();
3086
3087   virtual void PrintDataTo(StringStream* stream);
3088
3089   DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
3090 };
3091
3092
3093 class HInstanceOfKnownGlobal: public HTemplateInstruction<2> {
3094  public:
3095   HInstanceOfKnownGlobal(HValue* context,
3096                          HValue* left,
3097                          Handle<JSFunction> right)
3098       : function_(right) {
3099     SetOperandAt(0, context);
3100     SetOperandAt(1, left);
3101     set_representation(Representation::Tagged());
3102     SetAllSideEffects();
3103   }
3104
3105   HValue* context() { return OperandAt(0); }
3106   HValue* left() { return OperandAt(1); }
3107   Handle<JSFunction> function() { return function_; }
3108
3109   virtual Representation RequiredInputRepresentation(int index) {
3110     return Representation::Tagged();
3111   }
3112
3113   virtual HType CalculateInferredType();
3114
3115   DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal)
3116
3117  private:
3118   Handle<JSFunction> function_;
3119 };
3120
3121
3122 class HPower: public HTemplateInstruction<2> {
3123  public:
3124   HPower(HValue* left, HValue* right) {
3125     SetOperandAt(0, left);
3126     SetOperandAt(1, right);
3127     set_representation(Representation::Double());
3128     SetFlag(kUseGVN);
3129   }
3130
3131   HValue* left() { return OperandAt(0); }
3132   HValue* right() { return OperandAt(1); }
3133
3134   virtual Representation RequiredInputRepresentation(int index) {
3135     return index == 0
3136       ? Representation::Double()
3137       : Representation::None();
3138   }
3139
3140   DECLARE_CONCRETE_INSTRUCTION(Power)
3141
3142  protected:
3143   virtual bool DataEquals(HValue* other) { return true; }
3144 };
3145
3146
3147 class HRandom: public HTemplateInstruction<1> {
3148  public:
3149   explicit HRandom(HValue* global_object) {
3150     SetOperandAt(0, global_object);
3151     set_representation(Representation::Double());
3152   }
3153
3154   HValue* global_object() { return OperandAt(0); }
3155
3156   virtual Representation RequiredInputRepresentation(int index) {
3157     return Representation::Tagged();
3158   }
3159
3160   DECLARE_CONCRETE_INSTRUCTION(Random)
3161 };
3162
3163
3164 class HAdd: public HArithmeticBinaryOperation {
3165  public:
3166   HAdd(HValue* context, HValue* left, HValue* right)
3167       : HArithmeticBinaryOperation(context, left, right) {
3168     SetFlag(kCanOverflow);
3169   }
3170
3171   // Add is only commutative if two integer values are added and not if two
3172   // tagged values are added (because it might be a String concatenation).
3173   virtual bool IsCommutative() const {
3174     return !representation().IsTagged();
3175   }
3176
3177   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3178
3179   static HInstruction* NewHAdd(Zone* zone,
3180                                HValue* context,
3181                                HValue* left,
3182                                HValue* right);
3183
3184   virtual HType CalculateInferredType();
3185
3186   virtual HValue* Canonicalize();
3187
3188   DECLARE_CONCRETE_INSTRUCTION(Add)
3189
3190  protected:
3191   virtual bool DataEquals(HValue* other) { return true; }
3192
3193   virtual Range* InferRange(Zone* zone);
3194 };
3195
3196
3197 class HSub: public HArithmeticBinaryOperation {
3198  public:
3199   HSub(HValue* context, HValue* left, HValue* right)
3200       : HArithmeticBinaryOperation(context, left, right) {
3201     SetFlag(kCanOverflow);
3202   }
3203
3204   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3205
3206   virtual HValue* Canonicalize();
3207
3208   static HInstruction* NewHSub(Zone* zone,
3209                               HValue* context,
3210                               HValue* left,
3211                               HValue* right);
3212
3213   DECLARE_CONCRETE_INSTRUCTION(Sub)
3214
3215  protected:
3216   virtual bool DataEquals(HValue* other) { return true; }
3217
3218   virtual Range* InferRange(Zone* zone);
3219 };
3220
3221
3222 class HMul: public HArithmeticBinaryOperation {
3223  public:
3224   HMul(HValue* context, HValue* left, HValue* right)
3225       : HArithmeticBinaryOperation(context, left, right) {
3226     SetFlag(kCanOverflow);
3227   }
3228
3229   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3230
3231   // Only commutative if it is certain that not two objects are multiplicated.
3232   virtual bool IsCommutative() const {
3233     return !representation().IsTagged();
3234   }
3235
3236   static HInstruction* NewHMul(Zone* zone,
3237                                HValue* context,
3238                                HValue* left,
3239                                HValue* right);
3240
3241   DECLARE_CONCRETE_INSTRUCTION(Mul)
3242
3243  protected:
3244   virtual bool DataEquals(HValue* other) { return true; }
3245
3246   virtual Range* InferRange(Zone* zone);
3247 };
3248
3249
3250 class HMod: public HArithmeticBinaryOperation {
3251  public:
3252   HMod(HValue* context, HValue* left, HValue* right)
3253       : HArithmeticBinaryOperation(context, left, right) {
3254     SetFlag(kCanBeDivByZero);
3255   }
3256
3257   bool HasPowerOf2Divisor() {
3258     if (right()->IsConstant() &&
3259         HConstant::cast(right())->HasInteger32Value()) {
3260       int32_t value = HConstant::cast(right())->Integer32Value();
3261       return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
3262     }
3263
3264     return false;
3265   }
3266
3267   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3268
3269   static HInstruction* NewHMod(Zone* zone,
3270                                HValue* context,
3271                                HValue* left,
3272                                HValue* right);
3273
3274   DECLARE_CONCRETE_INSTRUCTION(Mod)
3275
3276  protected:
3277   virtual bool DataEquals(HValue* other) { return true; }
3278
3279   virtual Range* InferRange(Zone* zone);
3280 };
3281
3282
3283 class HDiv: public HArithmeticBinaryOperation {
3284  public:
3285   HDiv(HValue* context, HValue* left, HValue* right)
3286       : HArithmeticBinaryOperation(context, left, right) {
3287     SetFlag(kCanBeDivByZero);
3288     SetFlag(kCanOverflow);
3289   }
3290
3291   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3292
3293   static HInstruction* NewHDiv(Zone* zone,
3294                                HValue* context,
3295                                HValue* left,
3296                                HValue* right);
3297
3298   DECLARE_CONCRETE_INSTRUCTION(Div)
3299
3300  protected:
3301   virtual bool DataEquals(HValue* other) { return true; }
3302
3303   virtual Range* InferRange(Zone* zone);
3304 };
3305
3306
3307 class HBitwise: public HBitwiseBinaryOperation {
3308  public:
3309   HBitwise(Token::Value op, HValue* context, HValue* left, HValue* right)
3310       : HBitwiseBinaryOperation(context, left, right), op_(op) {
3311         ASSERT(op == Token::BIT_AND ||
3312                op == Token::BIT_OR ||
3313                op == Token::BIT_XOR);
3314       }
3315
3316   Token::Value op() const { return op_; }
3317
3318   virtual bool IsCommutative() const { return true; }
3319
3320   virtual HValue* Canonicalize();
3321
3322   static HInstruction* NewHBitwise(Zone* zone,
3323                                    Token::Value op,
3324                                    HValue* context,
3325                                    HValue* left,
3326                                    HValue* right);
3327
3328   DECLARE_CONCRETE_INSTRUCTION(Bitwise)
3329
3330  protected:
3331   virtual bool DataEquals(HValue* other) {
3332     return op() == HBitwise::cast(other)->op();
3333   }
3334
3335   virtual Range* InferRange(Zone* zone);
3336
3337  private:
3338   Token::Value op_;
3339 };
3340
3341
3342 class HShl: public HBitwiseBinaryOperation {
3343  public:
3344   HShl(HValue* context, HValue* left, HValue* right)
3345       : HBitwiseBinaryOperation(context, left, right) { }
3346
3347   virtual Range* InferRange(Zone* zone);
3348
3349   static HInstruction* NewHShl(Zone* zone,
3350                                HValue* context,
3351                                HValue* left,
3352                                HValue* right);
3353
3354   DECLARE_CONCRETE_INSTRUCTION(Shl)
3355
3356  protected:
3357   virtual bool DataEquals(HValue* other) { return true; }
3358 };
3359
3360
3361 class HShr: public HBitwiseBinaryOperation {
3362  public:
3363   HShr(HValue* context, HValue* left, HValue* right)
3364       : HBitwiseBinaryOperation(context, left, right) { }
3365
3366   virtual Range* InferRange(Zone* zone);
3367
3368   static HInstruction* NewHShr(Zone* zone,
3369                                HValue* context,
3370                                HValue* left,
3371                                HValue* right);
3372
3373   DECLARE_CONCRETE_INSTRUCTION(Shr)
3374
3375  protected:
3376   virtual bool DataEquals(HValue* other) { return true; }
3377 };
3378
3379
3380 class HSar: public HBitwiseBinaryOperation {
3381  public:
3382   HSar(HValue* context, HValue* left, HValue* right)
3383       : HBitwiseBinaryOperation(context, left, right) { }
3384
3385   virtual Range* InferRange(Zone* zone);
3386
3387   static HInstruction* NewHSar(Zone* zone,
3388                                HValue* context,
3389                                HValue* left,
3390                                HValue* right);
3391
3392   DECLARE_CONCRETE_INSTRUCTION(Sar)
3393
3394  protected:
3395   virtual bool DataEquals(HValue* other) { return true; }
3396 };
3397
3398
3399 class HOsrEntry: public HTemplateInstruction<0> {
3400  public:
3401   explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
3402     SetGVNFlag(kChangesOsrEntries);
3403   }
3404
3405   int ast_id() const { return ast_id_; }
3406
3407   virtual Representation RequiredInputRepresentation(int index) {
3408     return Representation::None();
3409   }
3410
3411   DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
3412
3413  private:
3414   int ast_id_;
3415 };
3416
3417
3418 class HParameter: public HTemplateInstruction<0> {
3419  public:
3420   explicit HParameter(unsigned index) : index_(index) {
3421     set_representation(Representation::Tagged());
3422   }
3423
3424   unsigned index() const { return index_; }
3425
3426   virtual void PrintDataTo(StringStream* stream);
3427
3428   virtual Representation RequiredInputRepresentation(int index) {
3429     return Representation::None();
3430   }
3431
3432   DECLARE_CONCRETE_INSTRUCTION(Parameter)
3433
3434  private:
3435   unsigned index_;
3436 };
3437
3438
3439 class HCallStub: public HUnaryCall {
3440  public:
3441   HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
3442       : HUnaryCall(context, argument_count),
3443         major_key_(major_key),
3444         transcendental_type_(TranscendentalCache::kNumberOfCaches) {
3445   }
3446
3447   CodeStub::Major major_key() { return major_key_; }
3448
3449   HValue* context() { return value(); }
3450
3451   void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
3452     transcendental_type_ = transcendental_type;
3453   }
3454   TranscendentalCache::Type transcendental_type() {
3455     return transcendental_type_;
3456   }
3457
3458   virtual void PrintDataTo(StringStream* stream);
3459
3460   virtual Representation RequiredInputRepresentation(int index) {
3461     return Representation::Tagged();
3462   }
3463
3464   DECLARE_CONCRETE_INSTRUCTION(CallStub)
3465
3466  private:
3467   CodeStub::Major major_key_;
3468   TranscendentalCache::Type transcendental_type_;
3469 };
3470
3471
3472 class HUnknownOSRValue: public HTemplateInstruction<0> {
3473  public:
3474   HUnknownOSRValue()
3475       : incoming_value_(NULL) {
3476     set_representation(Representation::Tagged());
3477   }
3478
3479   virtual Representation RequiredInputRepresentation(int index) {
3480     return Representation::None();
3481   }
3482
3483   void set_incoming_value(HPhi* value) {
3484     incoming_value_ = value;
3485   }
3486
3487   HPhi* incoming_value() {
3488     return incoming_value_;
3489   }
3490
3491   DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
3492
3493  private:
3494   HPhi* incoming_value_;
3495 };
3496
3497
3498 class HLoadGlobalCell: public HTemplateInstruction<0> {
3499  public:
3500   HLoadGlobalCell(Handle<JSGlobalPropertyCell> cell, PropertyDetails details)
3501       : cell_(cell), details_(details) {
3502     set_representation(Representation::Tagged());
3503     SetFlag(kUseGVN);
3504     SetGVNFlag(kDependsOnGlobalVars);
3505   }
3506
3507   Handle<JSGlobalPropertyCell>  cell() const { return cell_; }
3508   bool RequiresHoleCheck();
3509
3510   virtual void PrintDataTo(StringStream* stream);
3511
3512   virtual intptr_t Hashcode() {
3513     ASSERT(!HEAP->allow_allocation(false));
3514     return reinterpret_cast<intptr_t>(*cell_);
3515   }
3516
3517   virtual Representation RequiredInputRepresentation(int index) {
3518     return Representation::None();
3519   }
3520
3521   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell)
3522
3523  protected:
3524   virtual bool DataEquals(HValue* other) {
3525     HLoadGlobalCell* b = HLoadGlobalCell::cast(other);
3526     return cell_.is_identical_to(b->cell());
3527   }
3528
3529  private:
3530   Handle<JSGlobalPropertyCell> cell_;
3531   PropertyDetails details_;
3532 };
3533
3534
3535 class HLoadGlobalGeneric: public HTemplateInstruction<2> {
3536  public:
3537   HLoadGlobalGeneric(HValue* context,
3538                      HValue* global_object,
3539                      Handle<Object> name,
3540                      bool for_typeof)
3541       : name_(name),
3542         for_typeof_(for_typeof) {
3543     SetOperandAt(0, context);
3544     SetOperandAt(1, global_object);
3545     set_representation(Representation::Tagged());
3546     SetAllSideEffects();
3547   }
3548
3549   HValue* context() { return OperandAt(0); }
3550   HValue* global_object() { return OperandAt(1); }
3551   Handle<Object> name() const { return name_; }
3552   bool for_typeof() const { return for_typeof_; }
3553
3554   virtual void PrintDataTo(StringStream* stream);
3555
3556   virtual Representation RequiredInputRepresentation(int index) {
3557     return Representation::Tagged();
3558   }
3559
3560   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
3561
3562  private:
3563   Handle<Object> name_;
3564   bool for_typeof_;
3565 };
3566
3567
3568 inline bool StoringValueNeedsWriteBarrier(HValue* value) {
3569   return !value->type().IsBoolean()
3570       && !value->type().IsSmi()
3571       && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
3572 }
3573
3574
3575 class HStoreGlobalCell: public HUnaryOperation {
3576  public:
3577   HStoreGlobalCell(HValue* value,
3578                    Handle<JSGlobalPropertyCell> cell,
3579                    PropertyDetails details)
3580       : HUnaryOperation(value),
3581         cell_(cell),
3582         details_(details) {
3583     SetGVNFlag(kChangesGlobalVars);
3584   }
3585
3586   Handle<JSGlobalPropertyCell> cell() const { return cell_; }
3587   bool RequiresHoleCheck() {
3588     return !details_.IsDontDelete() || details_.IsReadOnly();
3589   }
3590   bool NeedsWriteBarrier() {
3591     return StoringValueNeedsWriteBarrier(value());
3592   }
3593
3594   virtual Representation RequiredInputRepresentation(int index) {
3595     return Representation::Tagged();
3596   }
3597   virtual void PrintDataTo(StringStream* stream);
3598
3599   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell)
3600
3601  private:
3602   Handle<JSGlobalPropertyCell> cell_;
3603   PropertyDetails details_;
3604 };
3605
3606
3607 class HStoreGlobalGeneric: public HTemplateInstruction<3> {
3608  public:
3609   HStoreGlobalGeneric(HValue* context,
3610                       HValue* global_object,
3611                       Handle<Object> name,
3612                       HValue* value,
3613                       StrictModeFlag strict_mode_flag)
3614       : name_(name),
3615         strict_mode_flag_(strict_mode_flag) {
3616     SetOperandAt(0, context);
3617     SetOperandAt(1, global_object);
3618     SetOperandAt(2, value);
3619     set_representation(Representation::Tagged());
3620     SetAllSideEffects();
3621   }
3622
3623   HValue* context() { return OperandAt(0); }
3624   HValue* global_object() { return OperandAt(1); }
3625   Handle<Object> name() const { return name_; }
3626   HValue* value() { return OperandAt(2); }
3627   StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
3628
3629   virtual void PrintDataTo(StringStream* stream);
3630
3631   virtual Representation RequiredInputRepresentation(int index) {
3632     return Representation::Tagged();
3633   }
3634
3635   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric)
3636
3637  private:
3638   Handle<Object> name_;
3639   StrictModeFlag strict_mode_flag_;
3640 };
3641
3642
3643 class HLoadContextSlot: public HUnaryOperation {
3644  public:
3645   enum Mode {
3646     // Perform a normal load of the context slot without checking its value.
3647     kNoCheck,
3648     // Load and check the value of the context slot. Deoptimize if it's the
3649     // hole value. This is used for checking for loading of uninitialized
3650     // harmony bindings where we deoptimize into full-codegen generated code
3651     // which will subsequently throw a reference error.
3652     kCheckDeoptimize,
3653     // Load and check the value of the context slot. Return undefined if it's
3654     // the hole value. This is used for non-harmony const assignments
3655     kCheckReturnUndefined
3656   };
3657
3658   HLoadContextSlot(HValue* context, Variable* var)
3659       : HUnaryOperation(context), slot_index_(var->index()) {
3660     ASSERT(var->IsContextSlot());
3661     switch (var->mode()) {
3662       case LET:
3663       case CONST_HARMONY:
3664         mode_ = kCheckDeoptimize;
3665         break;
3666       case CONST:
3667         mode_ = kCheckReturnUndefined;
3668         break;
3669       default:
3670         mode_ = kNoCheck;
3671     }
3672     set_representation(Representation::Tagged());
3673     SetFlag(kUseGVN);
3674     SetGVNFlag(kDependsOnContextSlots);
3675   }
3676
3677   int slot_index() const { return slot_index_; }
3678   Mode mode() const { return mode_; }
3679
3680   bool DeoptimizesOnHole() {
3681     return mode_ == kCheckDeoptimize;
3682   }
3683
3684   bool RequiresHoleCheck() {
3685     return mode_ != kNoCheck;
3686   }
3687
3688   virtual Representation RequiredInputRepresentation(int index) {
3689     return Representation::Tagged();
3690   }
3691
3692   virtual void PrintDataTo(StringStream* stream);
3693
3694   DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
3695
3696  protected:
3697   virtual bool DataEquals(HValue* other) {
3698     HLoadContextSlot* b = HLoadContextSlot::cast(other);
3699     return (slot_index() == b->slot_index());
3700   }
3701
3702  private:
3703   int slot_index_;
3704   Mode mode_;
3705 };
3706
3707
3708 class HStoreContextSlot: public HTemplateInstruction<2> {
3709  public:
3710   enum Mode {
3711     // Perform a normal store to the context slot without checking its previous
3712     // value.
3713     kNoCheck,
3714     // Check the previous value of the context slot and deoptimize if it's the
3715     // hole value. This is used for checking for assignments to uninitialized
3716     // harmony bindings where we deoptimize into full-codegen generated code
3717     // which will subsequently throw a reference error.
3718     kCheckDeoptimize,
3719     // Check the previous value and ignore assignment if it isn't a hole value
3720     kCheckIgnoreAssignment
3721   };
3722
3723   HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
3724       : slot_index_(slot_index), mode_(mode) {
3725     SetOperandAt(0, context);
3726     SetOperandAt(1, value);
3727     SetGVNFlag(kChangesContextSlots);
3728   }
3729
3730   HValue* context() { return OperandAt(0); }
3731   HValue* value() { return OperandAt(1); }
3732   int slot_index() const { return slot_index_; }
3733   Mode mode() const { return mode_; }
3734
3735   bool NeedsWriteBarrier() {
3736     return StoringValueNeedsWriteBarrier(value());
3737   }
3738
3739   bool DeoptimizesOnHole() {
3740     return mode_ == kCheckDeoptimize;
3741   }
3742
3743   bool RequiresHoleCheck() {
3744     return mode_ != kNoCheck;
3745   }
3746
3747   virtual Representation RequiredInputRepresentation(int index) {
3748     return Representation::Tagged();
3749   }
3750
3751   virtual void PrintDataTo(StringStream* stream);
3752
3753   DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
3754
3755  private:
3756   int slot_index_;
3757   Mode mode_;
3758 };
3759
3760
3761 class HLoadNamedField: public HUnaryOperation {
3762  public:
3763   HLoadNamedField(HValue* object, bool is_in_object, int offset)
3764       : HUnaryOperation(object),
3765         is_in_object_(is_in_object),
3766         offset_(offset) {
3767     set_representation(Representation::Tagged());
3768     SetFlag(kUseGVN);
3769     SetGVNFlag(kDependsOnMaps);
3770     if (is_in_object) {
3771       SetGVNFlag(kDependsOnInobjectFields);
3772     } else {
3773       SetGVNFlag(kDependsOnBackingStoreFields);
3774     }
3775   }
3776
3777   HValue* object() { return OperandAt(0); }
3778   bool is_in_object() const { return is_in_object_; }
3779   int offset() const { return offset_; }
3780
3781   virtual Representation RequiredInputRepresentation(int index) {
3782     return Representation::Tagged();
3783   }
3784   virtual void PrintDataTo(StringStream* stream);
3785
3786   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
3787
3788  protected:
3789   virtual bool DataEquals(HValue* other) {
3790     HLoadNamedField* b = HLoadNamedField::cast(other);
3791     return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
3792   }
3793
3794  private:
3795   bool is_in_object_;
3796   int offset_;
3797 };
3798
3799
3800 class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
3801  public:
3802   HLoadNamedFieldPolymorphic(HValue* context,
3803                              HValue* object,
3804                              SmallMapList* types,
3805                              Handle<String> name);
3806
3807   HValue* context() { return OperandAt(0); }
3808   HValue* object() { return OperandAt(1); }
3809   SmallMapList* types() { return &types_; }
3810   Handle<String> name() { return name_; }
3811   bool need_generic() { return need_generic_; }
3812
3813   virtual Representation RequiredInputRepresentation(int index) {
3814     return Representation::Tagged();
3815   }
3816
3817   virtual void PrintDataTo(StringStream* stream);
3818
3819   DECLARE_CONCRETE_INSTRUCTION(LoadNamedFieldPolymorphic)
3820
3821   static const int kMaxLoadPolymorphism = 4;
3822
3823  protected:
3824   virtual bool DataEquals(HValue* value);
3825
3826  private:
3827   SmallMapList types_;
3828   Handle<String> name_;
3829   bool need_generic_;
3830 };
3831
3832
3833
3834 class HLoadNamedGeneric: public HTemplateInstruction<2> {
3835  public:
3836   HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
3837       : name_(name) {
3838     SetOperandAt(0, context);
3839     SetOperandAt(1, object);
3840     set_representation(Representation::Tagged());
3841     SetAllSideEffects();
3842   }
3843
3844   HValue* context() { return OperandAt(0); }
3845   HValue* object() { return OperandAt(1); }
3846   Handle<Object> name() const { return name_; }
3847
3848   virtual Representation RequiredInputRepresentation(int index) {
3849     return Representation::Tagged();
3850   }
3851
3852   virtual void PrintDataTo(StringStream* stream);
3853
3854   DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
3855
3856  private:
3857   Handle<Object> name_;
3858 };
3859
3860
3861 class HLoadFunctionPrototype: public HUnaryOperation {
3862  public:
3863   explicit HLoadFunctionPrototype(HValue* function)
3864       : HUnaryOperation(function) {
3865     set_representation(Representation::Tagged());
3866     SetFlag(kUseGVN);
3867     SetGVNFlag(kDependsOnCalls);
3868   }
3869
3870   HValue* function() { return OperandAt(0); }
3871
3872   virtual Representation RequiredInputRepresentation(int index) {
3873     return Representation::Tagged();
3874   }
3875
3876   DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
3877
3878  protected:
3879   virtual bool DataEquals(HValue* other) { return true; }
3880 };
3881
3882
3883 class HLoadKeyedFastElement: public HTemplateInstruction<2> {
3884  public:
3885   enum HoleCheckMode { PERFORM_HOLE_CHECK, OMIT_HOLE_CHECK };
3886
3887   HLoadKeyedFastElement(HValue* obj,
3888                         HValue* key,
3889                         HoleCheckMode hole_check_mode = PERFORM_HOLE_CHECK)
3890       : hole_check_mode_(hole_check_mode) {
3891     SetOperandAt(0, obj);
3892     SetOperandAt(1, key);
3893     set_representation(Representation::Tagged());
3894     SetGVNFlag(kDependsOnArrayElements);
3895     SetFlag(kUseGVN);
3896   }
3897
3898   HValue* object() { return OperandAt(0); }
3899   HValue* key() { return OperandAt(1); }
3900
3901   virtual Representation RequiredInputRepresentation(int index) {
3902     // The key is supposed to be Integer32.
3903     return index == 0
3904       ? Representation::Tagged()
3905       : Representation::Integer32();
3906   }
3907
3908   virtual void PrintDataTo(StringStream* stream);
3909
3910   bool RequiresHoleCheck();
3911
3912   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement)
3913
3914  protected:
3915   virtual bool DataEquals(HValue* other) {
3916     if (!other->IsLoadKeyedFastElement()) return false;
3917     HLoadKeyedFastElement* other_load = HLoadKeyedFastElement::cast(other);
3918     return hole_check_mode_ == other_load->hole_check_mode_;
3919   }
3920
3921  private:
3922   HoleCheckMode hole_check_mode_;
3923 };
3924
3925
3926 class HLoadKeyedFastDoubleElement: public HTemplateInstruction<2> {
3927  public:
3928   HLoadKeyedFastDoubleElement(HValue* elements, HValue* key) {
3929     SetOperandAt(0, elements);
3930     SetOperandAt(1, key);
3931     set_representation(Representation::Double());
3932     SetGVNFlag(kDependsOnDoubleArrayElements);
3933     SetFlag(kUseGVN);
3934   }
3935
3936   HValue* elements() { return OperandAt(0); }
3937   HValue* key() { return OperandAt(1); }
3938
3939   virtual Representation RequiredInputRepresentation(int index) {
3940     // The key is supposed to be Integer32.
3941     return index == 0
3942       ? Representation::Tagged()
3943       : Representation::Integer32();
3944   }
3945
3946   virtual void PrintDataTo(StringStream* stream);
3947
3948   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement)
3949
3950  protected:
3951   virtual bool DataEquals(HValue* other) { return true; }
3952 };
3953
3954
3955 class HLoadKeyedSpecializedArrayElement: public HTemplateInstruction<2> {
3956  public:
3957   HLoadKeyedSpecializedArrayElement(HValue* external_elements,
3958                                     HValue* key,
3959                                     ElementsKind elements_kind)
3960       :  elements_kind_(elements_kind) {
3961     SetOperandAt(0, external_elements);
3962     SetOperandAt(1, key);
3963     if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
3964         elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3965       set_representation(Representation::Double());
3966     } else {
3967       set_representation(Representation::Integer32());
3968     }
3969     SetGVNFlag(kDependsOnSpecializedArrayElements);
3970     // Native code could change the specialized array.
3971     SetGVNFlag(kDependsOnCalls);
3972     SetFlag(kUseGVN);
3973   }
3974
3975   virtual void PrintDataTo(StringStream* stream);
3976
3977   virtual Representation RequiredInputRepresentation(int index) {
3978     // The key is supposed to be Integer32, but the base pointer
3979     // for the element load is a naked pointer.
3980     return index == 0
3981       ? Representation::External()
3982       : Representation::Integer32();
3983   }
3984
3985   HValue* external_pointer() { return OperandAt(0); }
3986   HValue* key() { return OperandAt(1); }
3987   ElementsKind elements_kind() const { return elements_kind_; }
3988
3989   virtual Range* InferRange(Zone* zone);
3990
3991   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement)
3992
3993  protected:
3994   virtual bool DataEquals(HValue* other) {
3995     if (!other->IsLoadKeyedSpecializedArrayElement()) return false;
3996     HLoadKeyedSpecializedArrayElement* cast_other =
3997         HLoadKeyedSpecializedArrayElement::cast(other);
3998     return elements_kind_ == cast_other->elements_kind();
3999   }
4000
4001  private:
4002   ElementsKind elements_kind_;
4003 };
4004
4005
4006 class HLoadKeyedGeneric: public HTemplateInstruction<3> {
4007  public:
4008   HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key) {
4009     set_representation(Representation::Tagged());
4010     SetOperandAt(0, obj);
4011     SetOperandAt(1, key);
4012     SetOperandAt(2, context);
4013     SetAllSideEffects();
4014   }
4015
4016   HValue* object() { return OperandAt(0); }
4017   HValue* key() { return OperandAt(1); }
4018   HValue* context() { return OperandAt(2); }
4019
4020   virtual void PrintDataTo(StringStream* stream);
4021
4022   virtual Representation RequiredInputRepresentation(int index) {
4023     return Representation::Tagged();
4024   }
4025
4026   virtual HValue* Canonicalize();
4027
4028   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
4029 };
4030
4031
4032 class HStoreNamedField: public HTemplateInstruction<2> {
4033  public:
4034   HStoreNamedField(HValue* obj,
4035                    Handle<String> name,
4036                    HValue* val,
4037                    bool in_object,
4038                    int offset)
4039       : name_(name),
4040         is_in_object_(in_object),
4041         offset_(offset) {
4042     SetOperandAt(0, obj);
4043     SetOperandAt(1, val);
4044     if (is_in_object_) {
4045       SetGVNFlag(kChangesInobjectFields);
4046     } else {
4047       SetGVNFlag(kChangesBackingStoreFields);
4048     }
4049   }
4050
4051   DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
4052
4053   virtual Representation RequiredInputRepresentation(int index) {
4054     return Representation::Tagged();
4055   }
4056   virtual void PrintDataTo(StringStream* stream);
4057
4058   HValue* object() { return OperandAt(0); }
4059   HValue* value() { return OperandAt(1); }
4060
4061   Handle<String> name() const { return name_; }
4062   bool is_in_object() const { return is_in_object_; }
4063   int offset() const { return offset_; }
4064   Handle<Map> transition() const { return transition_; }
4065   void set_transition(Handle<Map> map) { transition_ = map; }
4066
4067   bool NeedsWriteBarrier() {
4068     return StoringValueNeedsWriteBarrier(value());
4069   }
4070
4071  private:
4072   Handle<String> name_;
4073   bool is_in_object_;
4074   int offset_;
4075   Handle<Map> transition_;
4076 };
4077
4078
4079 class HStoreNamedGeneric: public HTemplateInstruction<3> {
4080  public:
4081   HStoreNamedGeneric(HValue* context,
4082                      HValue* object,
4083                      Handle<String> name,
4084                      HValue* value,
4085                      StrictModeFlag strict_mode_flag)
4086       : name_(name),
4087         strict_mode_flag_(strict_mode_flag) {
4088     SetOperandAt(0, object);
4089     SetOperandAt(1, value);
4090     SetOperandAt(2, context);
4091     SetAllSideEffects();
4092   }
4093
4094   HValue* object() { return OperandAt(0); }
4095   HValue* value() { return OperandAt(1); }
4096   HValue* context() { return OperandAt(2); }
4097   Handle<String> name() { return name_; }
4098   StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
4099
4100   virtual void PrintDataTo(StringStream* stream);
4101
4102   virtual Representation RequiredInputRepresentation(int index) {
4103     return Representation::Tagged();
4104   }
4105
4106   DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
4107
4108  private:
4109   Handle<String> name_;
4110   StrictModeFlag strict_mode_flag_;
4111 };
4112
4113
4114 class HStoreKeyedFastElement: public HTemplateInstruction<3> {
4115  public:
4116   HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val,
4117                          ElementsKind elements_kind = FAST_ELEMENTS)
4118       : elements_kind_(elements_kind) {
4119     SetOperandAt(0, obj);
4120     SetOperandAt(1, key);
4121     SetOperandAt(2, val);
4122     SetGVNFlag(kChangesArrayElements);
4123   }
4124
4125   virtual Representation RequiredInputRepresentation(int index) {
4126     // The key is supposed to be Integer32.
4127     return index == 1
4128         ? Representation::Integer32()
4129         : Representation::Tagged();
4130   }
4131
4132   HValue* object() { return OperandAt(0); }
4133   HValue* key() { return OperandAt(1); }
4134   HValue* value() { return OperandAt(2); }
4135   bool value_is_smi() {
4136     return elements_kind_ == FAST_SMI_ONLY_ELEMENTS;
4137   }
4138
4139   bool NeedsWriteBarrier() {
4140     if (value_is_smi()) {
4141       return false;
4142     } else {
4143       return StoringValueNeedsWriteBarrier(value());
4144     }
4145   }
4146
4147   virtual void PrintDataTo(StringStream* stream);
4148
4149   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement)
4150
4151  private:
4152   ElementsKind elements_kind_;
4153 };
4154
4155
4156 class HStoreKeyedFastDoubleElement: public HTemplateInstruction<3> {
4157  public:
4158   HStoreKeyedFastDoubleElement(HValue* elements,
4159                                HValue* key,
4160                                HValue* val) {
4161     SetOperandAt(0, elements);
4162     SetOperandAt(1, key);
4163     SetOperandAt(2, val);
4164     SetGVNFlag(kChangesDoubleArrayElements);
4165   }
4166
4167   virtual Representation RequiredInputRepresentation(int index) {
4168     if (index == 1) {
4169       return Representation::Integer32();
4170     } else if (index == 2) {
4171       return Representation::Double();
4172     } else {
4173       return Representation::Tagged();
4174     }
4175   }
4176
4177   HValue* elements() { return OperandAt(0); }
4178   HValue* key() { return OperandAt(1); }
4179   HValue* value() { return OperandAt(2); }
4180
4181   bool NeedsWriteBarrier() {
4182     return StoringValueNeedsWriteBarrier(value());
4183   }
4184
4185   virtual void PrintDataTo(StringStream* stream);
4186
4187   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement)
4188 };
4189
4190
4191 class HStoreKeyedSpecializedArrayElement: public HTemplateInstruction<3> {
4192  public:
4193   HStoreKeyedSpecializedArrayElement(HValue* external_elements,
4194                                      HValue* key,
4195                                      HValue* val,
4196                                      ElementsKind elements_kind)
4197       : elements_kind_(elements_kind) {
4198     SetGVNFlag(kChangesSpecializedArrayElements);
4199     SetOperandAt(0, external_elements);
4200     SetOperandAt(1, key);
4201     SetOperandAt(2, val);
4202   }
4203
4204   virtual void PrintDataTo(StringStream* stream);
4205
4206   virtual Representation RequiredInputRepresentation(int index) {
4207     if (index == 0) {
4208       return Representation::External();
4209     } else {
4210       bool float_or_double_elements =
4211           elements_kind() == EXTERNAL_FLOAT_ELEMENTS ||
4212           elements_kind() == EXTERNAL_DOUBLE_ELEMENTS;
4213       if (index == 2 && float_or_double_elements) {
4214         return Representation::Double();
4215       } else {
4216         return Representation::Integer32();
4217       }
4218     }
4219   }
4220
4221   HValue* external_pointer() { return OperandAt(0); }
4222   HValue* key() { return OperandAt(1); }
4223   HValue* value() { return OperandAt(2); }
4224   ElementsKind elements_kind() const { return elements_kind_; }
4225
4226   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement)
4227
4228  private:
4229   ElementsKind elements_kind_;
4230 };
4231
4232
4233 class HStoreKeyedGeneric: public HTemplateInstruction<4> {
4234  public:
4235   HStoreKeyedGeneric(HValue* context,
4236                      HValue* object,
4237                      HValue* key,
4238                      HValue* value,
4239                      StrictModeFlag strict_mode_flag)
4240       : strict_mode_flag_(strict_mode_flag) {
4241     SetOperandAt(0, object);
4242     SetOperandAt(1, key);
4243     SetOperandAt(2, value);
4244     SetOperandAt(3, context);
4245     SetAllSideEffects();
4246   }
4247
4248   HValue* object() { return OperandAt(0); }
4249   HValue* key() { return OperandAt(1); }
4250   HValue* value() { return OperandAt(2); }
4251   HValue* context() { return OperandAt(3); }
4252   StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
4253
4254   virtual Representation RequiredInputRepresentation(int index) {
4255     return Representation::Tagged();
4256   }
4257
4258   virtual void PrintDataTo(StringStream* stream);
4259
4260   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
4261
4262  private:
4263   StrictModeFlag strict_mode_flag_;
4264 };
4265
4266
4267 class HTransitionElementsKind: public HTemplateInstruction<1> {
4268  public:
4269   HTransitionElementsKind(HValue* object,
4270                           Handle<Map> original_map,
4271                           Handle<Map> transitioned_map)
4272       : original_map_(original_map),
4273         transitioned_map_(transitioned_map) {
4274     SetOperandAt(0, object);
4275     SetFlag(kUseGVN);
4276     SetGVNFlag(kChangesElementsKind);
4277     SetGVNFlag(kChangesElementsPointer);
4278     set_representation(Representation::Tagged());
4279   }
4280
4281   virtual Representation RequiredInputRepresentation(int index) {
4282     return Representation::Tagged();
4283   }
4284
4285   HValue* object() { return OperandAt(0); }
4286   Handle<Map> original_map() { return original_map_; }
4287   Handle<Map> transitioned_map() { return transitioned_map_; }
4288
4289   virtual void PrintDataTo(StringStream* stream);
4290
4291   DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
4292
4293  protected:
4294   virtual bool DataEquals(HValue* other) {
4295     HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
4296     return original_map_.is_identical_to(instr->original_map()) &&
4297         transitioned_map_.is_identical_to(instr->transitioned_map());
4298   }
4299
4300  private:
4301   Handle<Map> original_map_;
4302   Handle<Map> transitioned_map_;
4303 };
4304
4305
4306 class HStringAdd: public HBinaryOperation {
4307  public:
4308   HStringAdd(HValue* context, HValue* left, HValue* right)
4309       : HBinaryOperation(context, left, right) {
4310     set_representation(Representation::Tagged());
4311     SetFlag(kUseGVN);
4312     SetGVNFlag(kDependsOnMaps);
4313   }
4314
4315   virtual Representation RequiredInputRepresentation(int index) {
4316     return Representation::Tagged();
4317   }
4318
4319   virtual HType CalculateInferredType() {
4320     return HType::String();
4321   }
4322
4323   DECLARE_CONCRETE_INSTRUCTION(StringAdd)
4324
4325  protected:
4326   virtual bool DataEquals(HValue* other) { return true; }
4327 };
4328
4329
4330 class HStringCharCodeAt: public HTemplateInstruction<3> {
4331  public:
4332   HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
4333     SetOperandAt(0, context);
4334     SetOperandAt(1, string);
4335     SetOperandAt(2, index);
4336     set_representation(Representation::Integer32());
4337     SetFlag(kUseGVN);
4338     SetGVNFlag(kDependsOnMaps);
4339   }
4340
4341   virtual Representation RequiredInputRepresentation(int index) {
4342     // The index is supposed to be Integer32.
4343     return index == 2
4344         ? Representation::Integer32()
4345         : Representation::Tagged();
4346   }
4347
4348   HValue* context() { return OperandAt(0); }
4349   HValue* string() { return OperandAt(1); }
4350   HValue* index() { return OperandAt(2); }
4351
4352   DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
4353
4354  protected:
4355   virtual bool DataEquals(HValue* other) { return true; }
4356
4357   virtual Range* InferRange(Zone* zone) {
4358     return new(zone) Range(0, String::kMaxUtf16CodeUnit);
4359   }
4360 };
4361
4362
4363 class HStringCharFromCode: public HTemplateInstruction<2> {
4364  public:
4365   HStringCharFromCode(HValue* context, HValue* char_code) {
4366     SetOperandAt(0, context);
4367     SetOperandAt(1, char_code);
4368     set_representation(Representation::Tagged());
4369     SetFlag(kUseGVN);
4370   }
4371
4372   virtual Representation RequiredInputRepresentation(int index) {
4373     return index == 0
4374         ? Representation::Tagged()
4375         : Representation::Integer32();
4376   }
4377   virtual HType CalculateInferredType();
4378
4379   HValue* context() { return OperandAt(0); }
4380   HValue* value() { return OperandAt(1); }
4381
4382   virtual bool DataEquals(HValue* other) { return true; }
4383
4384   DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
4385 };
4386
4387
4388 class HStringLength: public HUnaryOperation {
4389  public:
4390   explicit HStringLength(HValue* string) : HUnaryOperation(string) {
4391     set_representation(Representation::Tagged());
4392     SetFlag(kUseGVN);
4393     SetGVNFlag(kDependsOnMaps);
4394   }
4395
4396   virtual Representation RequiredInputRepresentation(int index) {
4397     return Representation::Tagged();
4398   }
4399
4400   virtual HType CalculateInferredType() {
4401     STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
4402     return HType::Smi();
4403   }
4404
4405   DECLARE_CONCRETE_INSTRUCTION(StringLength)
4406
4407  protected:
4408   virtual bool DataEquals(HValue* other) { return true; }
4409
4410   virtual Range* InferRange(Zone* zone) {
4411     return new(zone) Range(0, String::kMaxLength);
4412   }
4413 };
4414
4415
4416 class HAllocateObject: public HTemplateInstruction<1> {
4417  public:
4418   HAllocateObject(HValue* context, Handle<JSFunction> constructor)
4419       : constructor_(constructor) {
4420     SetOperandAt(0, context);
4421     set_representation(Representation::Tagged());
4422   }
4423
4424   // Maximum instance size for which allocations will be inlined.
4425   static const int kMaxSize = 64 * kPointerSize;
4426
4427   HValue* context() { return OperandAt(0); }
4428   Handle<JSFunction> constructor() { return constructor_; }
4429
4430   virtual Representation RequiredInputRepresentation(int index) {
4431     return Representation::Tagged();
4432   }
4433   virtual HType CalculateInferredType();
4434
4435   DECLARE_CONCRETE_INSTRUCTION(AllocateObject)
4436
4437  private:
4438   Handle<JSFunction> constructor_;
4439 };
4440
4441
4442 template <int V>
4443 class HMaterializedLiteral: public HTemplateInstruction<V> {
4444  public:
4445   HMaterializedLiteral<V>(int index, int depth)
4446       : literal_index_(index), depth_(depth) {
4447     this->set_representation(Representation::Tagged());
4448   }
4449
4450   int literal_index() const { return literal_index_; }
4451   int depth() const { return depth_; }
4452
4453  private:
4454   int literal_index_;
4455   int depth_;
4456 };
4457
4458
4459 class HFastLiteral: public HMaterializedLiteral<1> {
4460  public:
4461   HFastLiteral(HValue* context,
4462                Handle<JSObject> boilerplate,
4463                int total_size,
4464                int literal_index,
4465                int depth)
4466       : HMaterializedLiteral<1>(literal_index, depth),
4467         boilerplate_(boilerplate),
4468         total_size_(total_size) {
4469     SetOperandAt(0, context);
4470   }
4471
4472   // Maximum depth and total number of elements and properties for literal
4473   // graphs to be considered for fast deep-copying.
4474   static const int kMaxLiteralDepth = 3;
4475   static const int kMaxLiteralProperties = 8;
4476
4477   HValue* context() { return OperandAt(0); }
4478   Handle<JSObject> boilerplate() const { return boilerplate_; }
4479   int total_size() const { return total_size_; }
4480
4481   virtual Representation RequiredInputRepresentation(int index) {
4482     return Representation::Tagged();
4483   }
4484   virtual HType CalculateInferredType();
4485
4486   DECLARE_CONCRETE_INSTRUCTION(FastLiteral)
4487
4488  private:
4489   Handle<JSObject> boilerplate_;
4490   int total_size_;
4491 };
4492
4493
4494 class HArrayLiteral: public HMaterializedLiteral<1> {
4495  public:
4496   HArrayLiteral(HValue* context,
4497                 Handle<HeapObject> boilerplate_object,
4498                 int length,
4499                 int literal_index,
4500                 int depth)
4501       : HMaterializedLiteral<1>(literal_index, depth),
4502         length_(length),
4503         boilerplate_object_(boilerplate_object) {
4504     SetOperandAt(0, context);
4505   }
4506
4507   HValue* context() { return OperandAt(0); }
4508   ElementsKind boilerplate_elements_kind() const {
4509     if (!boilerplate_object_->IsJSObject()) {
4510       return FAST_ELEMENTS;
4511     }
4512     return Handle<JSObject>::cast(boilerplate_object_)->GetElementsKind();
4513   }
4514   Handle<HeapObject> boilerplate_object() const { return boilerplate_object_; }
4515   int length() const { return length_; }
4516
4517   bool IsCopyOnWrite() const;
4518
4519   virtual Representation RequiredInputRepresentation(int index) {
4520     return Representation::Tagged();
4521   }
4522   virtual HType CalculateInferredType();
4523
4524   DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral)
4525
4526  private:
4527   int length_;
4528   Handle<HeapObject> boilerplate_object_;
4529 };
4530
4531
4532 class HObjectLiteral: public HMaterializedLiteral<1> {
4533  public:
4534   HObjectLiteral(HValue* context,
4535                  Handle<FixedArray> constant_properties,
4536                  bool fast_elements,
4537                  int literal_index,
4538                  int depth,
4539                  bool has_function)
4540       : HMaterializedLiteral<1>(literal_index, depth),
4541         constant_properties_(constant_properties),
4542         fast_elements_(fast_elements),
4543         has_function_(has_function) {
4544     SetOperandAt(0, context);
4545   }
4546
4547   HValue* context() { return OperandAt(0); }
4548   Handle<FixedArray> constant_properties() const {
4549     return constant_properties_;
4550   }
4551   bool fast_elements() const { return fast_elements_; }
4552   bool has_function() const { return has_function_; }
4553
4554   virtual Representation RequiredInputRepresentation(int index) {
4555     return Representation::Tagged();
4556   }
4557   virtual HType CalculateInferredType();
4558
4559   DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral)
4560
4561  private:
4562   Handle<FixedArray> constant_properties_;
4563   bool fast_elements_;
4564   bool has_function_;
4565 };
4566
4567
4568 class HRegExpLiteral: public HMaterializedLiteral<1> {
4569  public:
4570   HRegExpLiteral(HValue* context,
4571                  Handle<String> pattern,
4572                  Handle<String> flags,
4573                  int literal_index)
4574       : HMaterializedLiteral<1>(literal_index, 0),
4575         pattern_(pattern),
4576         flags_(flags) {
4577     SetOperandAt(0, context);
4578     SetAllSideEffects();
4579   }
4580
4581   HValue* context() { return OperandAt(0); }
4582   Handle<String> pattern() { return pattern_; }
4583   Handle<String> flags() { return flags_; }
4584
4585   virtual Representation RequiredInputRepresentation(int index) {
4586     return Representation::Tagged();
4587   }
4588   virtual HType CalculateInferredType();
4589
4590   DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
4591
4592  private:
4593   Handle<String> pattern_;
4594   Handle<String> flags_;
4595 };
4596
4597
4598 class HFunctionLiteral: public HTemplateInstruction<1> {
4599  public:
4600   HFunctionLiteral(HValue* context,
4601                    Handle<SharedFunctionInfo> shared,
4602                    bool pretenure)
4603       : shared_info_(shared), pretenure_(pretenure) {
4604     SetOperandAt(0, context);
4605     set_representation(Representation::Tagged());
4606   }
4607
4608   HValue* context() { return OperandAt(0); }
4609
4610   virtual Representation RequiredInputRepresentation(int index) {
4611     return Representation::Tagged();
4612   }
4613   virtual HType CalculateInferredType();
4614
4615   DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral)
4616
4617   Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
4618   bool pretenure() const { return pretenure_; }
4619
4620  private:
4621   Handle<SharedFunctionInfo> shared_info_;
4622   bool pretenure_;
4623 };
4624
4625
4626 class HTypeof: public HTemplateInstruction<2> {
4627  public:
4628   explicit HTypeof(HValue* context, HValue* value) {
4629     SetOperandAt(0, context);
4630     SetOperandAt(1, value);
4631     set_representation(Representation::Tagged());
4632   }
4633
4634   HValue* context() { return OperandAt(0); }
4635   HValue* value() { return OperandAt(1); }
4636
4637   virtual HValue* Canonicalize();
4638   virtual void PrintDataTo(StringStream* stream);
4639
4640   virtual Representation RequiredInputRepresentation(int index) {
4641     return Representation::Tagged();
4642   }
4643
4644   DECLARE_CONCRETE_INSTRUCTION(Typeof)
4645 };
4646
4647
4648 class HToFastProperties: public HUnaryOperation {
4649  public:
4650   explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
4651     // This instruction is not marked as having side effects, but
4652     // changes the map of the input operand. Use it only when creating
4653     // object literals.
4654     ASSERT(value->IsObjectLiteral() || value->IsFastLiteral());
4655     set_representation(Representation::Tagged());
4656   }
4657
4658   virtual Representation RequiredInputRepresentation(int index) {
4659     return Representation::Tagged();
4660   }
4661
4662   DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
4663 };
4664
4665
4666 class HValueOf: public HUnaryOperation {
4667  public:
4668   explicit HValueOf(HValue* value) : HUnaryOperation(value) {
4669     set_representation(Representation::Tagged());
4670   }
4671
4672   virtual Representation RequiredInputRepresentation(int index) {
4673     return Representation::Tagged();
4674   }
4675
4676   DECLARE_CONCRETE_INSTRUCTION(ValueOf)
4677 };
4678
4679
4680 class HDateField: public HUnaryOperation {
4681  public:
4682   HDateField(HValue* date, Smi* index)
4683       : HUnaryOperation(date), index_(index) {
4684     set_representation(Representation::Tagged());
4685   }
4686
4687   Smi* index() const { return index_; }
4688
4689   virtual Representation RequiredInputRepresentation(int index) {
4690     return Representation::Tagged();
4691   }
4692
4693   DECLARE_CONCRETE_INSTRUCTION(DateField)
4694
4695  private:
4696   Smi* index_;
4697 };
4698
4699
4700 class HDeleteProperty: public HBinaryOperation {
4701  public:
4702   HDeleteProperty(HValue* context, HValue* obj, HValue* key)
4703       : HBinaryOperation(context, obj, key) {
4704     set_representation(Representation::Tagged());
4705     SetAllSideEffects();
4706   }
4707
4708   virtual Representation RequiredInputRepresentation(int index) {
4709     return Representation::Tagged();
4710   }
4711
4712   virtual HType CalculateInferredType();
4713
4714   DECLARE_CONCRETE_INSTRUCTION(DeleteProperty)
4715
4716   HValue* object() { return left(); }
4717   HValue* key() { return right(); }
4718 };
4719
4720
4721 class HIn: public HTemplateInstruction<3> {
4722  public:
4723   HIn(HValue* context, HValue* key, HValue* object) {
4724     SetOperandAt(0, context);
4725     SetOperandAt(1, key);
4726     SetOperandAt(2, object);
4727     set_representation(Representation::Tagged());
4728     SetAllSideEffects();
4729   }
4730
4731   HValue* context() { return OperandAt(0); }
4732   HValue* key() { return OperandAt(1); }
4733   HValue* object() { return OperandAt(2); }
4734
4735   virtual Representation RequiredInputRepresentation(int index) {
4736     return Representation::Tagged();
4737   }
4738
4739   virtual HType CalculateInferredType() {
4740     return HType::Boolean();
4741   }
4742
4743   virtual void PrintDataTo(StringStream* stream);
4744
4745   DECLARE_CONCRETE_INSTRUCTION(In)
4746 };
4747
4748
4749 class HCheckMapValue: public HTemplateInstruction<2> {
4750  public:
4751   HCheckMapValue(HValue* value,
4752                  HValue* map) {
4753     SetOperandAt(0, value);
4754     SetOperandAt(1, map);
4755     set_representation(Representation::Tagged());
4756     SetFlag(kUseGVN);
4757     SetGVNFlag(kDependsOnMaps);
4758     SetGVNFlag(kDependsOnElementsKind);
4759   }
4760
4761   virtual Representation RequiredInputRepresentation(int index) {
4762     return Representation::Tagged();
4763   }
4764
4765   virtual void PrintDataTo(StringStream* stream);
4766
4767   virtual HType CalculateInferredType() {
4768     return HType::Tagged();
4769   }
4770
4771   HValue* value() { return OperandAt(0); }
4772   HValue* map() { return OperandAt(1); }
4773
4774   DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
4775
4776  protected:
4777   virtual bool DataEquals(HValue* other) {
4778     return true;
4779   }
4780 };
4781
4782
4783 class HForInPrepareMap : public HTemplateInstruction<2> {
4784  public:
4785   HForInPrepareMap(HValue* context,
4786                    HValue* object) {
4787     SetOperandAt(0, context);
4788     SetOperandAt(1, object);
4789     set_representation(Representation::Tagged());
4790     SetAllSideEffects();
4791   }
4792
4793   virtual Representation RequiredInputRepresentation(int index) {
4794     return Representation::Tagged();
4795   }
4796
4797   HValue* context() { return OperandAt(0); }
4798   HValue* enumerable() { return OperandAt(1); }
4799
4800   virtual void PrintDataTo(StringStream* stream);
4801
4802   virtual HType CalculateInferredType() {
4803     return HType::Tagged();
4804   }
4805
4806   DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
4807 };
4808
4809
4810 class HForInCacheArray : public HTemplateInstruction<2> {
4811  public:
4812   HForInCacheArray(HValue* enumerable,
4813                    HValue* keys,
4814                    int idx) : idx_(idx) {
4815     SetOperandAt(0, enumerable);
4816     SetOperandAt(1, keys);
4817     set_representation(Representation::Tagged());
4818   }
4819
4820   virtual Representation RequiredInputRepresentation(int index) {
4821     return Representation::Tagged();
4822   }
4823
4824   HValue* enumerable() { return OperandAt(0); }
4825   HValue* map() { return OperandAt(1); }
4826   int idx() { return idx_; }
4827
4828   HForInCacheArray* index_cache() {
4829     return index_cache_;
4830   }
4831
4832   void set_index_cache(HForInCacheArray* index_cache) {
4833     index_cache_ = index_cache;
4834   }
4835
4836   virtual void PrintDataTo(StringStream* stream);
4837
4838   virtual HType CalculateInferredType() {
4839     return HType::Tagged();
4840   }
4841
4842   DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
4843
4844  private:
4845   int idx_;
4846   HForInCacheArray* index_cache_;
4847 };
4848
4849
4850 class HLoadFieldByIndex : public HTemplateInstruction<2> {
4851  public:
4852   HLoadFieldByIndex(HValue* object,
4853                     HValue* index) {
4854     SetOperandAt(0, object);
4855     SetOperandAt(1, index);
4856     set_representation(Representation::Tagged());
4857   }
4858
4859   virtual Representation RequiredInputRepresentation(int index) {
4860     return Representation::Tagged();
4861   }
4862
4863   HValue* object() { return OperandAt(0); }
4864   HValue* index() { return OperandAt(1); }
4865
4866   virtual void PrintDataTo(StringStream* stream);
4867
4868   virtual HType CalculateInferredType() {
4869     return HType::Tagged();
4870   }
4871
4872   DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
4873 };
4874
4875
4876 #undef DECLARE_INSTRUCTION
4877 #undef DECLARE_CONCRETE_INSTRUCTION
4878
4879 } }  // namespace v8::internal
4880
4881 #endif  // V8_HYDROGEN_INSTRUCTIONS_H_