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