hydrogen-instructions.h revision b8e0da25ee8efac3bb05cd6b2730aafbd96119f4
1// Copyright 2010 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#include "code-stubs.h"
33#include "string-stream.h"
34#include "zone.h"
35
36namespace v8 {
37namespace internal {
38
39// Forward declarations.
40class HBasicBlock;
41class HEnvironment;
42class HInstruction;
43class HLoopInformation;
44class HValue;
45class LInstruction;
46class LChunkBuilder;
47
48
49// Type hierarchy:
50//
51// HValue
52//   HInstruction
53//     HAccessArgumentsAt
54//     HApplyArguments
55//     HArgumentsElements
56//     HArgumentsLength
57//     HArgumentsObject
58//     HBinaryOperation
59//       HArithmeticBinaryOperation
60//         HAdd
61//         HDiv
62//         HMod
63//         HMul
64//         HSub
65//       HBitwiseBinaryOperation
66//         HBitAnd
67//         HBitOr
68//         HBitXor
69//         HSar
70//         HShl
71//         HShr
72//       HBoundsCheck
73//       HCompare
74//       HCompareJSObjectEq
75//       HInstanceOf
76//       HInstanceOfKnownGlobal
77//       HLoadKeyed
78//         HLoadKeyedFastElement
79//         HLoadKeyedGeneric
80//       HPower
81//       HStoreNamed
82//         HStoreNamedField
83//         HStoreNamedGeneric
84//     HBlockEntry
85//     HCall
86//       HCallConstantFunction
87//       HCallFunction
88//       HCallGlobal
89//       HCallKeyed
90//       HCallKnownGlobal
91//       HCallNamed
92//       HCallNew
93//       HCallRuntime
94//     HCallStub
95//     HCheckPrototypeMaps
96//     HConstant
97//     HControlInstruction
98//       HDeoptimize
99//       HGoto
100//       HUnaryControlInstruction
101//         HBranch
102//         HCompareMapAndBranch
103//         HReturn
104//         HThrow
105//     HEnterInlined
106//     HFunctionLiteral
107//     HGlobalObject
108//     HGlobalReceiver
109//     HLeaveInlined
110//     HLoadContextSlot
111//     HLoadGlobal
112//     HMaterializedLiteral
113//       HArrayLiteral
114//       HObjectLiteral
115//       HRegExpLiteral
116//     HOsrEntry
117//     HParameter
118//     HSimulate
119//     HStackCheck
120//     HStoreKeyed
121//       HStoreKeyedFastElement
122//       HStoreKeyedGeneric
123//     HUnaryOperation
124//       HBitNot
125//       HChange
126//       HCheckFunction
127//       HCheckInstanceType
128//       HCheckMap
129//       HCheckNonSmi
130//       HCheckSmi
131//       HDeleteProperty
132//       HFixedArrayLength
133//       HJSArrayLength
134//       HLoadElements
135//         HTypeofIs
136//       HLoadNamedField
137//       HLoadNamedGeneric
138//       HLoadFunctionPrototype
139//       HPushArgument
140//       HTypeof
141//       HUnaryMathOperation
142//       HUnaryPredicate
143//         HClassOfTest
144//         HHasCachedArrayIndex
145//         HHasInstanceType
146//         HIsNull
147//         HIsObject
148//         HIsSmi
149//       HValueOf
150//     HUnknownOSRValue
151//   HPhi
152
153#define HYDROGEN_ALL_INSTRUCTION_LIST(V)       \
154  V(ArithmeticBinaryOperation)                 \
155  V(BinaryOperation)                           \
156  V(BitwiseBinaryOperation)                    \
157  V(Call)                                      \
158  V(ControlInstruction)                        \
159  V(Instruction)                               \
160  V(LoadKeyed)                                 \
161  V(MaterializedLiteral)                       \
162  V(Phi)                                       \
163  V(StoreKeyed)                                \
164  V(StoreNamed)                                \
165  V(UnaryControlInstruction)                   \
166  V(UnaryOperation)                            \
167  HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
168
169
170#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)  \
171  V(AccessArgumentsAt)                         \
172  V(Add)                                       \
173  V(ApplyArguments)                            \
174  V(ArgumentsElements)                         \
175  V(ArgumentsLength)                           \
176  V(ArgumentsObject)                           \
177  V(ArrayLiteral)                              \
178  V(BitAnd)                                    \
179  V(BitNot)                                    \
180  V(BitOr)                                     \
181  V(BitXor)                                    \
182  V(BlockEntry)                                \
183  V(BoundsCheck)                               \
184  V(Branch)                                    \
185  V(CallConstantFunction)                      \
186  V(CallFunction)                              \
187  V(CallGlobal)                                \
188  V(CallKeyed)                                 \
189  V(CallKnownGlobal)                           \
190  V(CallNamed)                                 \
191  V(CallNew)                                   \
192  V(CallRuntime)                               \
193  V(CallStub)                                  \
194  V(Change)                                    \
195  V(CheckFunction)                             \
196  V(CheckInstanceType)                         \
197  V(CheckMap)                                  \
198  V(CheckNonSmi)                               \
199  V(CheckPrototypeMaps)                        \
200  V(CheckSmi)                                  \
201  V(Compare)                                   \
202  V(CompareJSObjectEq)                         \
203  V(CompareMapAndBranch)                       \
204  V(Constant)                                  \
205  V(DeleteProperty)                            \
206  V(Deoptimize)                                \
207  V(Div)                                       \
208  V(EnterInlined)                              \
209  V(FixedArrayLength)                          \
210  V(FunctionLiteral)                           \
211  V(GlobalObject)                              \
212  V(GlobalReceiver)                            \
213  V(Goto)                                      \
214  V(InstanceOf)                                \
215  V(InstanceOfKnownGlobal)                     \
216  V(IsNull)                                    \
217  V(IsObject)                                  \
218  V(IsSmi)                                     \
219  V(HasInstanceType)                           \
220  V(HasCachedArrayIndex)                       \
221  V(JSArrayLength)                             \
222  V(ClassOfTest)                               \
223  V(LeaveInlined)                              \
224  V(LoadContextSlot)                           \
225  V(LoadElements)                              \
226  V(LoadGlobal)                                \
227  V(LoadKeyedFastElement)                      \
228  V(LoadKeyedGeneric)                          \
229  V(LoadNamedField)                            \
230  V(LoadNamedGeneric)                          \
231  V(LoadFunctionPrototype)                     \
232  V(Mod)                                       \
233  V(Mul)                                       \
234  V(ObjectLiteral)                             \
235  V(OsrEntry)                                  \
236  V(Parameter)                                 \
237  V(Power)                                     \
238  V(PushArgument)                              \
239  V(RegExpLiteral)                             \
240  V(Return)                                    \
241  V(Sar)                                       \
242  V(Shl)                                       \
243  V(Shr)                                       \
244  V(Simulate)                                  \
245  V(StackCheck)                                \
246  V(StoreGlobal)                               \
247  V(StoreKeyedFastElement)                     \
248  V(StoreKeyedGeneric)                         \
249  V(StoreNamedField)                           \
250  V(StoreNamedGeneric)                         \
251  V(Sub)                                       \
252  V(Throw)                                     \
253  V(Typeof)                                    \
254  V(TypeofIs)                                  \
255  V(UnaryMathOperation)                        \
256  V(UnknownOSRValue)                           \
257  V(ValueOf)
258
259#define GVN_FLAG_LIST(V)                       \
260  V(Calls)                                     \
261  V(InobjectFields)                            \
262  V(BackingStoreFields)                        \
263  V(ArrayElements)                             \
264  V(GlobalVars)                                \
265  V(Maps)                                      \
266  V(ArrayLengths)                              \
267  V(FunctionPrototypes)                        \
268  V(OsrEntries)
269
270#define DECLARE_INSTRUCTION(type)                   \
271  virtual bool Is##type() const { return true; }    \
272  static H##type* cast(HValue* value) {             \
273    ASSERT(value->Is##type());                      \
274    return reinterpret_cast<H##type*>(value);       \
275  }                                                 \
276  Opcode opcode() const { return HValue::k##type; }
277
278
279#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic)              \
280  virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
281  virtual const char* Mnemonic() const { return mnemonic; }       \
282  DECLARE_INSTRUCTION(type)
283
284
285
286template<int kSize>
287class HOperandVector : public EmbeddedVector<HValue*, kSize> {
288 public:
289  HOperandVector() : EmbeddedVector<HValue*, kSize>(NULL) { }
290};
291
292
293class Range: public ZoneObject {
294 public:
295  Range() : lower_(kMinInt),
296            upper_(kMaxInt),
297            next_(NULL),
298            can_be_minus_zero_(false) { }
299
300  Range(int32_t lower, int32_t upper)
301      : lower_(lower), upper_(upper), next_(NULL), can_be_minus_zero_(false) { }
302
303  bool IsInSmiRange() const {
304    return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
305  }
306  void KeepOrder();
307  void Verify() const;
308  int32_t upper() const { return upper_; }
309  int32_t lower() const { return lower_; }
310  Range* next() const { return next_; }
311  Range* CopyClearLower() const { return new Range(kMinInt, upper_); }
312  Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); }
313  void ClearLower() { lower_ = kMinInt; }
314  void ClearUpper() { upper_ = kMaxInt; }
315  Range* Copy() const { return new Range(lower_, upper_); }
316  bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; }
317  int32_t Mask() const;
318  void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
319  bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
320  bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
321  bool CanBeNegative() const { return lower_ < 0; }
322  bool Includes(int value) const {
323    return lower_ <= value && upper_ >= value;
324  }
325
326  void Sar(int32_t value) {
327    int32_t bits = value & 0x1F;
328    lower_ = lower_ >> bits;
329    upper_ = upper_ >> bits;
330    set_can_be_minus_zero(false);
331  }
332
333  void Shl(int32_t value) {
334    int32_t bits = value & 0x1F;
335    int old_lower = lower_;
336    int old_upper = upper_;
337    lower_ = lower_ << bits;
338    upper_ = upper_ << bits;
339    if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
340      upper_ = kMaxInt;
341      lower_ = kMinInt;
342    }
343    set_can_be_minus_zero(false);
344  }
345
346  // Adds a constant to the lower and upper bound of the range.
347  void AddConstant(int32_t value);
348
349  void StackUpon(Range* other) {
350    Intersect(other);
351    next_ = other;
352  }
353
354  void Intersect(Range* other) {
355    upper_ = Min(upper_, other->upper_);
356    lower_ = Max(lower_, other->lower_);
357    bool b = CanBeMinusZero() && other->CanBeMinusZero();
358    set_can_be_minus_zero(b);
359  }
360
361  void Union(Range* other) {
362    upper_ = Max(upper_, other->upper_);
363    lower_ = Min(lower_, other->lower_);
364    bool b = CanBeMinusZero() || other->CanBeMinusZero();
365    set_can_be_minus_zero(b);
366  }
367
368  // Compute a new result range and return true, if the operation
369  // can overflow.
370  bool AddAndCheckOverflow(Range* other);
371  bool SubAndCheckOverflow(Range* other);
372  bool MulAndCheckOverflow(Range* other);
373
374 private:
375  int32_t lower_;
376  int32_t upper_;
377  Range* next_;
378  bool can_be_minus_zero_;
379};
380
381
382class Representation {
383 public:
384  enum Kind {
385    kNone,
386    kTagged,
387    kDouble,
388    kInteger32,
389    kNumRepresentations
390  };
391
392  Representation() : kind_(kNone) { }
393
394  static Representation None() { return Representation(kNone); }
395  static Representation Tagged() { return Representation(kTagged); }
396  static Representation Integer32() { return Representation(kInteger32); }
397  static Representation Double() { return Representation(kDouble); }
398
399  bool Equals(const Representation& other) const {
400    return kind_ == other.kind_;
401  }
402
403  Kind kind() const { return kind_; }
404  bool IsNone() const { return kind_ == kNone; }
405  bool IsTagged() const { return kind_ == kTagged; }
406  bool IsInteger32() const { return kind_ == kInteger32; }
407  bool IsDouble() const { return kind_ == kDouble; }
408  bool IsSpecialization() const {
409    return kind_ == kInteger32 || kind_ == kDouble;
410  }
411  const char* Mnemonic() const;
412
413 private:
414  explicit Representation(Kind k) : kind_(k) { }
415
416  Kind kind_;
417};
418
419
420class HType {
421 public:
422  HType() : type_(kUninitialized) { }
423
424  static HType Tagged() { return HType(kTagged); }
425  static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
426  static HType TaggedNumber() { return HType(kTaggedNumber); }
427  static HType Smi() { return HType(kSmi); }
428  static HType HeapNumber() { return HType(kHeapNumber); }
429  static HType String() { return HType(kString); }
430  static HType Boolean() { return HType(kBoolean); }
431  static HType NonPrimitive() { return HType(kNonPrimitive); }
432  static HType JSArray() { return HType(kJSArray); }
433  static HType JSObject() { return HType(kJSObject); }
434  static HType Uninitialized() { return HType(kUninitialized); }
435
436  // Return the weakest (least precise) common type.
437  HType Combine(HType other) {
438    return HType(static_cast<Type>(type_ & other.type_));
439  }
440
441  bool Equals(const HType& other) {
442    return type_ == other.type_;
443  }
444
445  bool IsSubtypeOf(const HType& other) {
446    return Combine(other).Equals(other);
447  }
448
449  bool IsTagged() {
450    ASSERT(type_ != kUninitialized);
451    return ((type_ & kTagged) == kTagged);
452  }
453
454  bool IsTaggedPrimitive() {
455    ASSERT(type_ != kUninitialized);
456    return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
457  }
458
459  bool IsTaggedNumber() {
460    ASSERT(type_ != kUninitialized);
461    return ((type_ & kTaggedNumber) == kTaggedNumber);
462  }
463
464  bool IsSmi() {
465    ASSERT(type_ != kUninitialized);
466    return ((type_ & kSmi) == kSmi);
467  }
468
469  bool IsHeapNumber() {
470    ASSERT(type_ != kUninitialized);
471    return ((type_ & kHeapNumber) == kHeapNumber);
472  }
473
474  bool IsString() {
475    ASSERT(type_ != kUninitialized);
476    return ((type_ & kString) == kString);
477  }
478
479  bool IsBoolean() {
480    ASSERT(type_ != kUninitialized);
481    return ((type_ & kBoolean) == kBoolean);
482  }
483
484  bool IsNonPrimitive() {
485    ASSERT(type_ != kUninitialized);
486    return ((type_ & kNonPrimitive) == kNonPrimitive);
487  }
488
489  bool IsJSArray() {
490    ASSERT(type_ != kUninitialized);
491    return ((type_ & kJSArray) == kJSArray);
492  }
493
494  bool IsJSObject() {
495    ASSERT(type_ != kUninitialized);
496    return ((type_ & kJSObject) == kJSObject);
497  }
498
499  bool IsUninitialized() {
500    return type_ == kUninitialized;
501  }
502
503  static HType TypeFromValue(Handle<Object> value);
504
505  const char* ToString();
506  const char* ToShortString();
507
508 private:
509  enum Type {
510    kTagged = 0x1,           // 0000 0000 0000 0001
511    kTaggedPrimitive = 0x5,  // 0000 0000 0000 0101
512    kTaggedNumber = 0xd,     // 0000 0000 0000 1101
513    kSmi = 0x1d,             // 0000 0000 0001 1101
514    kHeapNumber = 0x2d,      // 0000 0000 0010 1101
515    kString = 0x45,          // 0000 0000 0100 0101
516    kBoolean = 0x85,         // 0000 0000 1000 0101
517    kNonPrimitive = 0x101,   // 0000 0001 0000 0001
518    kJSObject = 0x301,       // 0000 0011 0000 0001
519    kJSArray = 0x701,        // 0000 0111 1000 0001
520    kUninitialized = 0x1fff  // 0001 1111 1111 1111
521  };
522
523  explicit HType(Type t) : type_(t) { }
524
525  Type type_;
526};
527
528
529class HValue: public ZoneObject {
530 public:
531  static const int kNoNumber = -1;
532
533  // There must be one corresponding kDepends flag for every kChanges flag and
534  // the order of the kChanges flags must be exactly the same as of the kDepends
535  // flags.
536  enum Flag {
537    // Declare global value numbering flags.
538  #define DECLARE_DO(type) kChanges##type, kDependsOn##type,
539    GVN_FLAG_LIST(DECLARE_DO)
540  #undef DECLARE_DO
541    kFlexibleRepresentation,
542    kUseGVN,
543    kCanOverflow,
544    kBailoutOnMinusZero,
545    kCanBeDivByZero,
546    kIsArguments,
547    kTruncatingToInt32,
548    kLastFlag = kTruncatingToInt32
549  };
550
551  STATIC_ASSERT(kLastFlag < kBitsPerInt);
552
553  static const int kChangesToDependsFlagsLeftShift = 1;
554
555  static int ChangesFlagsMask() {
556    int result = 0;
557    // Create changes mask.
558#define DECLARE_DO(type) result |= (1 << kChanges##type);
559  GVN_FLAG_LIST(DECLARE_DO)
560#undef DECLARE_DO
561    return result;
562  }
563
564  static int DependsFlagsMask() {
565    return ConvertChangesToDependsFlags(ChangesFlagsMask());
566  }
567
568  static int ConvertChangesToDependsFlags(int flags) {
569    return flags << kChangesToDependsFlagsLeftShift;
570  }
571
572  // A flag mask to mark an instruction as having arbitrary side effects.
573  static int AllSideEffects() {
574    return ChangesFlagsMask() & ~(1 << kChangesOsrEntries);
575  }
576
577  static HValue* cast(HValue* value) { return value; }
578
579  enum Opcode {
580    // Declare a unique enum value for each hydrogen instruction.
581  #define DECLARE_DO(type) k##type,
582    HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
583  #undef DECLARE_DO
584    kMaxInstructionClass
585  };
586
587  HValue() : block_(NULL),
588             id_(kNoNumber),
589             uses_(2),
590             type_(HType::Tagged()),
591             range_(NULL),
592             flags_(0) {}
593  virtual ~HValue() {}
594
595  HBasicBlock* block() const { return block_; }
596  void SetBlock(HBasicBlock* block);
597
598  int id() const { return id_; }
599  void set_id(int id) { id_ = id; }
600
601  const ZoneList<HValue*>* uses() const { return &uses_; }
602
603  virtual bool EmitAtUses() const { return false; }
604  Representation representation() const { return representation_; }
605  void ChangeRepresentation(Representation r) {
606    // Representation was already set and is allowed to be changed.
607    ASSERT(!representation_.IsNone());
608    ASSERT(!r.IsNone());
609    ASSERT(CheckFlag(kFlexibleRepresentation));
610    RepresentationChanged(r);
611    representation_ = r;
612  }
613
614  HType type() const { return type_; }
615  void set_type(HType type) {
616    ASSERT(uses_.length() == 0);
617    type_ = type;
618  }
619
620  // An operation needs to override this function iff:
621  //   1) it can produce an int32 output.
622  //   2) the true value of its output can potentially be minus zero.
623  // The implementation must set a flag so that it bails out in the case where
624  // it would otherwise output what should be a minus zero as an int32 zero.
625  // If the operation also exists in a form that takes int32 and outputs int32
626  // then the operation should return its input value so that we can propagate
627  // back.  There are two operations that need to propagate back to more than
628  // one input.  They are phi and binary add.  They always return NULL and
629  // expect the caller to take care of things.
630  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
631    visited->Add(id());
632    return NULL;
633  }
634
635  bool HasSideEffects() const {
636    return (flags_ & AllSideEffects()) != 0;
637  }
638  bool IsDefinedAfter(HBasicBlock* other) const;
639
640  // Operands.
641  virtual int OperandCount() const { return 0; }
642  virtual HValue* OperandAt(int index) const {
643    UNREACHABLE();
644    return NULL;
645  }
646  void SetOperandAt(int index, HValue* value);
647
648  int LookupOperandIndex(int occurrence_index, HValue* op) const;
649  bool UsesMultipleTimes(HValue* op) const;
650
651  void ReplaceAndDelete(HValue* other);
652  void ReplaceValue(HValue* other);
653  void ReplaceAtUse(HValue* use, HValue* other);
654  void ReplaceFirstAtUse(HValue* use, HValue* other, Representation r);
655  bool HasNoUses() const { return uses_.is_empty(); }
656  void ClearOperands();
657  void Delete();
658
659  int flags() const { return flags_; }
660  void SetFlagMask(int mask) { flags_ |= mask; }
661  void SetFlag(Flag f) { SetFlagMask(1 << f); }
662  void ClearFlagMask(int mask) { flags_ &= ~mask; }
663  void ClearFlag(Flag f) { ClearFlagMask(1 << f); }
664  bool CheckFlag(Flag f) const { return CheckFlagMask(1 << f); }
665  bool CheckFlagMask(int mask) const { return (flags_ & mask) != 0; }
666
667  Range* range() const { return range_; }
668  bool HasRange() const { return range_ != NULL; }
669  void AddNewRange(Range* r);
670  void RemoveLastAddedRange();
671  void ComputeInitialRange();
672
673  // Representation helpers.
674  virtual Representation RequiredInputRepresentation(int index) const {
675    return Representation::None();
676  }
677  virtual Representation InferredRepresentation() const {
678    return representation();
679  }
680
681  // This gives the instruction an opportunity to replace itself with an
682  // instruction that does the same in some better way.  To replace an
683  // instruction with a new one, first add the new instruction to the graph,
684  // then return it.  Return NULL to have the instruction deleted.
685  virtual HValue* Canonicalize() { return this; }
686
687  // Declare virtual type testers.
688#define DECLARE_DO(type) virtual bool Is##type() const { return false; }
689  HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO)
690#undef DECLARE_DO
691
692  bool Equals(HValue* other) const;
693  virtual intptr_t Hashcode() const;
694
695  // Printing support.
696  virtual void PrintTo(StringStream* stream) const = 0;
697  void PrintNameTo(StringStream* stream);
698  static void PrintTypeTo(HType type, StringStream* stream);
699
700  virtual const char* Mnemonic() const = 0;
701  virtual Opcode opcode() const = 0;
702
703  // Updated the inferred type of this instruction and returns true if
704  // it has changed.
705  bool UpdateInferredType();
706
707  virtual HType CalculateInferredType() const;
708
709  // Helper for type conversions used by normal and phi instructions.
710  void InsertInputConversion(HInstruction* previous, int index, HType type);
711
712#ifdef DEBUG
713  virtual void Verify() const = 0;
714#endif
715
716 protected:
717  virtual bool DataEquals(HValue* other) const { return true; }
718  virtual void RepresentationChanged(Representation to) { }
719  virtual Range* InferRange();
720  virtual void DeleteFromGraph() = 0;
721  virtual void InternalSetOperandAt(int index, HValue* value) { UNREACHABLE(); }
722  void clear_block() {
723    ASSERT(block_ != NULL);
724    block_ = NULL;
725  }
726
727  void set_representation(Representation r) {
728    // Representation is set-once.
729    ASSERT(representation_.IsNone() && !r.IsNone());
730    representation_ = r;
731  }
732
733 private:
734  void InternalReplaceAtUse(HValue* use, HValue* other);
735  void RegisterUse(int index, HValue* new_value);
736
737  HBasicBlock* block_;
738
739  // The id of this instruction in the hydrogen graph, assigned when first
740  // added to the graph. Reflects creation order.
741  int id_;
742
743  Representation representation_;
744  ZoneList<HValue*> uses_;
745  HType type_;
746  Range* range_;
747  int flags_;
748
749  DISALLOW_COPY_AND_ASSIGN(HValue);
750};
751
752
753class HInstruction: public HValue {
754 public:
755  HInstruction* next() const { return next_; }
756  HInstruction* previous() const { return previous_; }
757
758  void PrintTo(StringStream* stream) const;
759  virtual void PrintDataTo(StringStream* stream) const {}
760
761  bool IsLinked() const { return block() != NULL; }
762  void Unlink();
763  void InsertBefore(HInstruction* next);
764  void InsertAfter(HInstruction* previous);
765
766  int position() const { return position_; }
767  bool has_position() const { return position_ != RelocInfo::kNoPosition; }
768  void set_position(int position) { position_ = position; }
769
770  virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
771
772#ifdef DEBUG
773  virtual void Verify() const;
774#endif
775
776  // Returns whether this is some kind of deoptimizing check
777  // instruction.
778  virtual bool IsCheckInstruction() const { return false; }
779
780  DECLARE_INSTRUCTION(Instruction)
781
782 protected:
783  HInstruction()
784      : next_(NULL),
785        previous_(NULL),
786        position_(RelocInfo::kNoPosition) {
787    SetFlag(kDependsOnOsrEntries);
788  }
789
790  virtual void DeleteFromGraph() { Unlink(); }
791
792 private:
793  void InitializeAsFirst(HBasicBlock* block) {
794    ASSERT(!IsLinked());
795    SetBlock(block);
796  }
797
798  HInstruction* next_;
799  HInstruction* previous_;
800  int position_;
801
802  friend class HBasicBlock;
803};
804
805
806class HBlockEntry: public HInstruction {
807 public:
808  DECLARE_CONCRETE_INSTRUCTION(BlockEntry, "block_entry")
809};
810
811
812class HControlInstruction: public HInstruction {
813 public:
814  virtual HBasicBlock* FirstSuccessor() const { return NULL; }
815  virtual HBasicBlock* SecondSuccessor() const { return NULL; }
816
817  DECLARE_INSTRUCTION(ControlInstruction)
818};
819
820
821class HDeoptimize: public HControlInstruction {
822 public:
823  DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
824};
825
826
827class HGoto: public HControlInstruction {
828 public:
829  explicit HGoto(HBasicBlock* destination)
830      : destination_(destination),
831        include_stack_check_(false) {}
832
833  virtual HBasicBlock* FirstSuccessor() const { return destination_; }
834  void set_include_stack_check(bool include_stack_check) {
835    include_stack_check_ = include_stack_check;
836  }
837  bool include_stack_check() const { return include_stack_check_; }
838
839  virtual void PrintDataTo(StringStream* stream) const;
840
841  DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
842
843 private:
844  HBasicBlock* destination_;
845  bool include_stack_check_;
846};
847
848
849class HUnaryControlInstruction: public HControlInstruction {
850 public:
851  explicit HUnaryControlInstruction(HValue* value) {
852    SetOperandAt(0, value);
853  }
854
855  virtual Representation RequiredInputRepresentation(int index) const {
856    return Representation::Tagged();
857  }
858
859  HValue* value() const { return OperandAt(0); }
860  virtual int OperandCount() const { return 1; }
861  virtual HValue* OperandAt(int index) const { return operands_[index]; }
862
863  DECLARE_INSTRUCTION(UnaryControlInstruction)
864
865 protected:
866  virtual void InternalSetOperandAt(int index, HValue* value) {
867    operands_[index] = value;
868  }
869
870 private:
871  HOperandVector<1> operands_;
872};
873
874
875class HBranch: public HUnaryControlInstruction {
876 public:
877  HBranch(HBasicBlock* true_destination,
878          HBasicBlock* false_destination,
879          HValue* boolean_value)
880      : HUnaryControlInstruction(boolean_value),
881        true_destination_(true_destination),
882        false_destination_(false_destination) {
883    ASSERT(true_destination != NULL && false_destination != NULL);
884  }
885
886  virtual Representation RequiredInputRepresentation(int index) const {
887    return Representation::None();
888  }
889
890  virtual HBasicBlock* FirstSuccessor() const { return true_destination_; }
891  virtual HBasicBlock* SecondSuccessor() const { return false_destination_; }
892
893  virtual void PrintDataTo(StringStream* stream) const;
894
895  DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
896
897 private:
898  HBasicBlock* true_destination_;
899  HBasicBlock* false_destination_;
900};
901
902
903class HCompareMapAndBranch: public HUnaryControlInstruction {
904 public:
905  HCompareMapAndBranch(HValue* result,
906                       Handle<Map> map,
907                       HBasicBlock* true_destination,
908                       HBasicBlock* false_destination)
909      : HUnaryControlInstruction(result),
910        map_(map),
911        true_destination_(true_destination),
912        false_destination_(false_destination) {
913    ASSERT(true_destination != NULL);
914    ASSERT(false_destination != NULL);
915    ASSERT(!map.is_null());
916  }
917
918  virtual HBasicBlock* FirstSuccessor() const { return true_destination_; }
919  virtual HBasicBlock* SecondSuccessor() const { return false_destination_; }
920
921  HBasicBlock* true_destination() const { return true_destination_; }
922  HBasicBlock* false_destination() const { return false_destination_; }
923
924  virtual void PrintDataTo(StringStream* stream) const;
925
926  Handle<Map> map() const { return map_; }
927
928  DECLARE_CONCRETE_INSTRUCTION(CompareMapAndBranch, "compare_map_and_branch")
929
930 private:
931  Handle<Map> map_;
932  HBasicBlock* true_destination_;
933  HBasicBlock* false_destination_;
934};
935
936
937class HReturn: public HUnaryControlInstruction {
938 public:
939  explicit HReturn(HValue* result) : HUnaryControlInstruction(result) { }
940
941  virtual void PrintDataTo(StringStream* stream) const;
942
943  DECLARE_CONCRETE_INSTRUCTION(Return, "return")
944};
945
946
947class HThrow: public HUnaryControlInstruction {
948 public:
949  explicit HThrow(HValue* value) : HUnaryControlInstruction(value) { }
950
951  virtual void PrintDataTo(StringStream* stream) const;
952
953  DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
954};
955
956
957class HUnaryOperation: public HInstruction {
958 public:
959  explicit HUnaryOperation(HValue* value) {
960    SetOperandAt(0, value);
961  }
962
963  HValue* value() const { return OperandAt(0); }
964  virtual void PrintDataTo(StringStream* stream) const;
965  virtual int OperandCount() const { return 1; }
966  virtual HValue* OperandAt(int index) const { return operands_[index]; }
967
968  DECLARE_INSTRUCTION(UnaryOperation)
969
970 protected:
971  virtual void InternalSetOperandAt(int index, HValue* value) {
972    operands_[index] = value;
973  }
974
975 private:
976  HOperandVector<1> operands_;
977};
978
979
980class HChange: public HUnaryOperation {
981 public:
982  HChange(HValue* value,
983          Representation from,
984          Representation to)
985      : HUnaryOperation(value), from_(from), to_(to) {
986    ASSERT(!from.IsNone() && !to.IsNone());
987    ASSERT(!from.Equals(to));
988    set_representation(to);
989    SetFlag(kUseGVN);
990
991    if (from.IsInteger32() && to.IsTagged() && value->range() != NULL &&
992        value->range()->IsInSmiRange()) {
993      set_type(HType::Smi());
994    }
995  }
996
997  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
998
999  Representation from() const { return from_; }
1000  Representation to() const { return to_; }
1001  virtual Representation RequiredInputRepresentation(int index) const {
1002    return from_;
1003  }
1004
1005  bool CanTruncateToInt32() const {
1006    for (int i = 0; i < uses()->length(); ++i) {
1007      if (!uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) return false;
1008    }
1009    return true;
1010  }
1011
1012  virtual void PrintDataTo(StringStream* stream) const;
1013
1014  DECLARE_CONCRETE_INSTRUCTION(Change,
1015                               CanTruncateToInt32() ? "truncate" : "change")
1016
1017 protected:
1018  virtual bool DataEquals(HValue* other) const {
1019    if (!other->IsChange()) return false;
1020    HChange* change = HChange::cast(other);
1021    return value() == change->value()
1022        && to().Equals(change->to())
1023        && CanTruncateToInt32() == change->CanTruncateToInt32();
1024  }
1025
1026 private:
1027  Representation from_;
1028  Representation to_;
1029};
1030
1031
1032class HSimulate: public HInstruction {
1033 public:
1034  HSimulate(int ast_id, int pop_count, int environment_length)
1035      : ast_id_(ast_id),
1036        pop_count_(pop_count),
1037        environment_length_(environment_length),
1038        values_(2),
1039        assigned_indexes_(2) {}
1040  virtual ~HSimulate() {}
1041
1042  virtual void PrintDataTo(StringStream* stream) const;
1043
1044  bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; }
1045  int ast_id() const { return ast_id_; }
1046  void set_ast_id(int id) {
1047    ASSERT(!HasAstId());
1048    ast_id_ = id;
1049  }
1050
1051  int environment_length() const { return environment_length_; }
1052  int pop_count() const { return pop_count_; }
1053  const ZoneList<HValue*>* values() const { return &values_; }
1054  int GetAssignedIndexAt(int index) const {
1055    ASSERT(HasAssignedIndexAt(index));
1056    return assigned_indexes_[index];
1057  }
1058  bool HasAssignedIndexAt(int index) const {
1059    return assigned_indexes_[index] != kNoIndex;
1060  }
1061  void AddAssignedValue(int index, HValue* value) {
1062    AddValue(index, value);
1063  }
1064  void AddPushedValue(HValue* value) {
1065    AddValue(kNoIndex, value);
1066  }
1067  virtual int OperandCount() const { return values_.length(); }
1068  virtual HValue* OperandAt(int index) const { return values_[index]; }
1069
1070  DECLARE_CONCRETE_INSTRUCTION(Simulate, "simulate")
1071
1072#ifdef DEBUG
1073  virtual void Verify() const;
1074#endif
1075
1076 protected:
1077  virtual void InternalSetOperandAt(int index, HValue* value) {
1078    values_[index] = value;
1079  }
1080
1081 private:
1082  static const int kNoIndex = -1;
1083  void AddValue(int index, HValue* value) {
1084    assigned_indexes_.Add(index);
1085    // Resize the list of pushed values.
1086    values_.Add(NULL);
1087    // Set the operand through the base method in HValue to make sure that the
1088    // use lists are correctly updated.
1089    SetOperandAt(values_.length() - 1, value);
1090  }
1091  int ast_id_;
1092  int pop_count_;
1093  int environment_length_;
1094  ZoneList<HValue*> values_;
1095  ZoneList<int> assigned_indexes_;
1096};
1097
1098
1099class HStackCheck: public HInstruction {
1100 public:
1101  HStackCheck() { }
1102
1103  DECLARE_CONCRETE_INSTRUCTION(Throw, "stack_check")
1104};
1105
1106
1107class HEnterInlined: public HInstruction {
1108 public:
1109  HEnterInlined(Handle<JSFunction> closure, FunctionLiteral* function)
1110      : closure_(closure), function_(function) {
1111  }
1112
1113  virtual void PrintDataTo(StringStream* stream) const;
1114
1115  Handle<JSFunction> closure() const { return closure_; }
1116  FunctionLiteral* function() const { return function_; }
1117
1118  DECLARE_CONCRETE_INSTRUCTION(EnterInlined, "enter_inlined")
1119
1120 private:
1121  Handle<JSFunction> closure_;
1122  FunctionLiteral* function_;
1123};
1124
1125
1126class HLeaveInlined: public HInstruction {
1127 public:
1128  HLeaveInlined() {}
1129
1130  DECLARE_CONCRETE_INSTRUCTION(LeaveInlined, "leave_inlined")
1131};
1132
1133
1134class HPushArgument: public HUnaryOperation {
1135 public:
1136  explicit HPushArgument(HValue* value)
1137      : HUnaryOperation(value), argument_index_(-1) {
1138    set_representation(Representation::Tagged());
1139  }
1140
1141  virtual Representation RequiredInputRepresentation(int index) const {
1142    return Representation::Tagged();
1143  }
1144
1145  virtual void PrintDataTo(StringStream* stream) const;
1146  HValue* argument() const { return OperandAt(0); }
1147  int argument_index() const { return argument_index_; }
1148  void set_argument_index(int index) {
1149    ASSERT(argument_index_ == -1 || index == argument_index_);
1150    argument_index_ = index;
1151  }
1152
1153  DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push_argument")
1154
1155 private:
1156  int argument_index_;
1157};
1158
1159
1160class HGlobalObject: public HInstruction {
1161 public:
1162  HGlobalObject() {
1163    set_representation(Representation::Tagged());
1164    SetFlag(kUseGVN);
1165    SetFlag(kDependsOnCalls);
1166  }
1167
1168  DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global_object")
1169};
1170
1171
1172class HGlobalReceiver: public HInstruction {
1173 public:
1174  HGlobalReceiver() {
1175    set_representation(Representation::Tagged());
1176    SetFlag(kUseGVN);
1177    SetFlag(kDependsOnCalls);
1178  }
1179
1180  DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global_receiver")
1181};
1182
1183
1184class HCall: public HInstruction {
1185 public:
1186  // Construct a call with uninitialized arguments. The argument count
1187  // includes the receiver.
1188  explicit HCall(int count);
1189
1190  virtual HType CalculateInferredType() const { return HType::Tagged(); }
1191
1192  // TODO(3190496): This needs a cleanup. We don't want the arguments
1193  // be operands of the call instruction. This results in bad code quality.
1194  virtual int argument_count() const { return arguments_.length(); }
1195  virtual int OperandCount() const { return argument_count(); }
1196  virtual HValue* OperandAt(int index) const { return arguments_[index]; }
1197  virtual HPushArgument* PushArgumentAt(int index) const {
1198    return HPushArgument::cast(OperandAt(index));
1199  }
1200  virtual HValue* ArgumentAt(int index) const {
1201    return PushArgumentAt(index)->argument();
1202  }
1203  virtual void SetArgumentAt(int index, HPushArgument* push_argument);
1204
1205  virtual void PrintDataTo(StringStream* stream) const;
1206
1207  DECLARE_INSTRUCTION(Call)
1208
1209 protected:
1210  virtual void InternalSetOperandAt(int index, HValue* value) {
1211    arguments_[index] = value;
1212  }
1213
1214  int argument_count_;
1215  Vector<HValue*> arguments_;
1216};
1217
1218
1219class HCallConstantFunction: public HCall {
1220 public:
1221  HCallConstantFunction(Handle<JSFunction> function, int argument_count)
1222      : HCall(argument_count), function_(function) { }
1223
1224  Handle<JSFunction> function() const { return function_; }
1225  bool IsApplyFunction() const {
1226    return function_->code() == Builtins::builtin(Builtins::FunctionApply);
1227  }
1228
1229  virtual void PrintDataTo(StringStream* stream) const;
1230
1231  DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call_constant_function")
1232
1233 private:
1234  Handle<JSFunction> function_;
1235};
1236
1237
1238class HCallKeyed: public HCall {
1239 public:
1240  HCallKeyed(HValue* key, int argument_count)
1241      : HCall(argument_count + 1) {
1242    SetOperandAt(0, key);
1243  }
1244
1245  virtual Representation RequiredInputRepresentation(int index) const {
1246    return Representation::Tagged();
1247  }
1248
1249  // TODO(3190496): This is a hack to get an additional operand that
1250  // is not an argument to work with the current setup. This _needs_ a cleanup.
1251  // (see HCall)
1252  virtual void PrintDataTo(StringStream* stream) const;
1253  HValue* key() const { return OperandAt(0); }
1254  virtual int argument_count() const { return arguments_.length() - 1; }
1255  virtual int OperandCount() const { return arguments_.length(); }
1256  virtual HValue* OperandAt(int index) const { return arguments_[index]; }
1257  virtual HPushArgument* PushArgumentAt(int index) const {
1258    return HPushArgument::cast(OperandAt(index + 1));
1259  }
1260  virtual void SetArgumentAt(int index, HPushArgument* push_argument) {
1261    HCall::SetArgumentAt(index + 1, push_argument);
1262  }
1263
1264  DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed")
1265};
1266
1267
1268class HCallNamed: public HCall {
1269 public:
1270  HCallNamed(Handle<String> name, int argument_count)
1271      : HCall(argument_count), name_(name) { }
1272  virtual void PrintDataTo(StringStream* stream) const;
1273
1274  Handle<String> name() const { return name_; }
1275
1276  DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named")
1277
1278 private:
1279  Handle<String> name_;
1280};
1281
1282
1283class HCallFunction: public HCall {
1284 public:
1285  explicit HCallFunction(int argument_count) : HCall(argument_count) { }
1286
1287  DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function")
1288};
1289
1290
1291class HCallGlobal: public HCall {
1292 public:
1293  HCallGlobal(Handle<String> name, int argument_count)
1294      : HCall(argument_count), name_(name) { }
1295
1296  virtual void PrintDataTo(StringStream* stream) const;
1297
1298  Handle<String> name() const { return name_; }
1299
1300  DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global")
1301
1302 private:
1303  Handle<String> name_;
1304};
1305
1306
1307class HCallKnownGlobal: public HCall {
1308 public:
1309  HCallKnownGlobal(Handle<JSFunction> target,
1310                   int argument_count)
1311      : HCall(argument_count), target_(target) { }
1312
1313  Handle<JSFunction> target() const { return target_; }
1314
1315  DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global")
1316
1317 private:
1318  Handle<JSFunction> target_;
1319};
1320
1321
1322class HCallNew: public HCall {
1323 public:
1324  explicit HCallNew(int argument_count) : HCall(argument_count) { }
1325
1326  virtual Representation RequiredInputRepresentation(int index) const {
1327    return Representation::Tagged();
1328  }
1329
1330  HValue* constructor() const { return ArgumentAt(0); }
1331
1332  DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new")
1333};
1334
1335
1336class HCallRuntime: public HCall {
1337 public:
1338  HCallRuntime(Handle<String> name,
1339               Runtime::Function* c_function,
1340               int argument_count)
1341      : HCall(argument_count), c_function_(c_function), name_(name) { }
1342  virtual void PrintDataTo(StringStream* stream) const;
1343
1344  Runtime::Function* function() const { return c_function_; }
1345  Handle<String> name() const { return name_; }
1346
1347  DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call_runtime")
1348
1349 private:
1350  Runtime::Function* c_function_;
1351  Handle<String> name_;
1352};
1353
1354
1355class HJSArrayLength: public HUnaryOperation {
1356 public:
1357  explicit HJSArrayLength(HValue* value) : HUnaryOperation(value) {
1358    // The length of an array is stored as a tagged value in the array
1359    // object. It is guaranteed to be 32 bit integer, but it can be
1360    // represented as either a smi or heap number.
1361    set_representation(Representation::Tagged());
1362    SetFlag(kDependsOnArrayLengths);
1363    SetFlag(kUseGVN);
1364  }
1365
1366  virtual Representation RequiredInputRepresentation(int index) const {
1367    return Representation::Tagged();
1368  }
1369
1370  DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js_array_length")
1371};
1372
1373
1374class HFixedArrayLength: public HUnaryOperation {
1375 public:
1376  explicit HFixedArrayLength(HValue* value) : HUnaryOperation(value) {
1377    set_representation(Representation::Tagged());
1378    SetFlag(kDependsOnArrayLengths);
1379    SetFlag(kUseGVN);
1380  }
1381
1382  virtual Representation RequiredInputRepresentation(int index) const {
1383    return Representation::Tagged();
1384  }
1385
1386  DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed_array_length")
1387};
1388
1389
1390class HBitNot: public HUnaryOperation {
1391 public:
1392  explicit HBitNot(HValue* value) : HUnaryOperation(value) {
1393    set_representation(Representation::Integer32());
1394    SetFlag(kUseGVN);
1395    SetFlag(kTruncatingToInt32);
1396  }
1397
1398  virtual Representation RequiredInputRepresentation(int index) const {
1399    return Representation::Integer32();
1400  }
1401  virtual HType CalculateInferredType() const;
1402
1403  DECLARE_CONCRETE_INSTRUCTION(BitNot, "bit_not")
1404};
1405
1406
1407class HUnaryMathOperation: public HUnaryOperation {
1408 public:
1409  HUnaryMathOperation(HValue* value, BuiltinFunctionId op)
1410      : HUnaryOperation(value), op_(op) {
1411    switch (op) {
1412      case kMathFloor:
1413      case kMathRound:
1414      case kMathCeil:
1415        set_representation(Representation::Integer32());
1416        break;
1417      case kMathAbs:
1418        set_representation(Representation::Tagged());
1419        SetFlag(kFlexibleRepresentation);
1420        break;
1421      case kMathSqrt:
1422      case kMathPowHalf:
1423      case kMathLog:
1424      case kMathSin:
1425      case kMathCos:
1426        set_representation(Representation::Double());
1427        break;
1428      default:
1429        UNREACHABLE();
1430    }
1431    SetFlag(kUseGVN);
1432  }
1433
1434  virtual void PrintDataTo(StringStream* stream) const;
1435
1436  virtual HType CalculateInferredType() const;
1437
1438  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1439
1440  virtual Representation RequiredInputRepresentation(int index) const {
1441    switch (op_) {
1442      case kMathFloor:
1443      case kMathRound:
1444      case kMathCeil:
1445      case kMathSqrt:
1446      case kMathPowHalf:
1447      case kMathLog:
1448      case kMathSin:
1449      case kMathCos:
1450        return Representation::Double();
1451        break;
1452      case kMathAbs:
1453        return representation();
1454        break;
1455      default:
1456        return Representation::None();
1457    }
1458  }
1459
1460  virtual HValue* Canonicalize() {
1461    // If the input is integer32 then we replace the floor instruction
1462    // with its inputs.  This happens before the representation changes are
1463    // introduced.
1464    if (op() == kMathFloor) {
1465      if (value()->representation().IsInteger32()) return value();
1466    }
1467    return this;
1468  }
1469
1470  BuiltinFunctionId op() const { return op_; }
1471  const char* OpName() const;
1472
1473  DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary_math_operation")
1474
1475 protected:
1476  virtual bool DataEquals(HValue* other) const {
1477    HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
1478    return op_ == b->op();
1479  }
1480
1481 private:
1482  BuiltinFunctionId op_;
1483};
1484
1485
1486class HLoadElements: public HUnaryOperation {
1487 public:
1488  explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
1489    set_representation(Representation::Tagged());
1490    SetFlag(kUseGVN);
1491    SetFlag(kDependsOnMaps);
1492  }
1493
1494  virtual Representation RequiredInputRepresentation(int index) const {
1495    return Representation::Tagged();
1496  }
1497
1498  DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements")
1499};
1500
1501
1502class HCheckMap: public HUnaryOperation {
1503 public:
1504  HCheckMap(HValue* value, Handle<Map> map)
1505      : HUnaryOperation(value), map_(map) {
1506    set_representation(Representation::Tagged());
1507    SetFlag(kUseGVN);
1508    SetFlag(kDependsOnMaps);
1509  }
1510
1511  virtual bool IsCheckInstruction() const { return true; }
1512
1513  virtual Representation RequiredInputRepresentation(int index) const {
1514    return Representation::Tagged();
1515  }
1516  virtual void PrintDataTo(StringStream* stream) const;
1517  virtual HType CalculateInferredType() const;
1518
1519#ifdef DEBUG
1520  virtual void Verify() const;
1521#endif
1522
1523  Handle<Map> map() const { return map_; }
1524
1525  DECLARE_CONCRETE_INSTRUCTION(CheckMap, "check_map")
1526
1527 protected:
1528  virtual bool DataEquals(HValue* other) const {
1529    HCheckMap* b = HCheckMap::cast(other);
1530    return map_.is_identical_to(b->map());
1531  }
1532
1533 private:
1534  Handle<Map> map_;
1535};
1536
1537
1538class HCheckFunction: public HUnaryOperation {
1539 public:
1540  HCheckFunction(HValue* value, Handle<JSFunction> function)
1541      : HUnaryOperation(value), target_(function) {
1542    set_representation(Representation::Tagged());
1543    SetFlag(kUseGVN);
1544  }
1545
1546  virtual bool IsCheckInstruction() const { return true; }
1547
1548  virtual Representation RequiredInputRepresentation(int index) const {
1549    return Representation::Tagged();
1550  }
1551  virtual void PrintDataTo(StringStream* stream) const;
1552  virtual HType CalculateInferredType() const;
1553
1554#ifdef DEBUG
1555  virtual void Verify() const;
1556#endif
1557
1558  Handle<JSFunction> target() const { return target_; }
1559
1560  DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check_function")
1561
1562 protected:
1563  virtual bool DataEquals(HValue* other) const {
1564    HCheckFunction* b = HCheckFunction::cast(other);
1565    return target_.is_identical_to(b->target());
1566  }
1567
1568 private:
1569  Handle<JSFunction> target_;
1570};
1571
1572
1573class HCheckInstanceType: public HUnaryOperation {
1574 public:
1575  // Check that the instance type is in the range [first, last] where
1576  // both first and last are included.
1577  HCheckInstanceType(HValue* value, InstanceType first, InstanceType last)
1578      : HUnaryOperation(value), first_(first), last_(last) {
1579    ASSERT(first <= last);
1580    set_representation(Representation::Tagged());
1581    SetFlag(kUseGVN);
1582  }
1583
1584  virtual bool IsCheckInstruction() const { return true; }
1585
1586  virtual Representation RequiredInputRepresentation(int index) const {
1587    return Representation::Tagged();
1588  }
1589
1590#ifdef DEBUG
1591  virtual void Verify() const;
1592#endif
1593
1594  static HCheckInstanceType* NewIsJSObjectOrJSFunction(HValue* value);
1595
1596  InstanceType first() const { return first_; }
1597  InstanceType last() const { return last_; }
1598
1599  DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check_instance_type")
1600
1601 protected:
1602  // TODO(ager): It could be nice to allow the ommision of instance
1603  // type checks if we have already performed an instance type check
1604  // with a larger range.
1605  virtual bool DataEquals(HValue* other) const {
1606    HCheckInstanceType* b = HCheckInstanceType::cast(other);
1607    return (first_ == b->first()) && (last_ == b->last());
1608  }
1609
1610 private:
1611  InstanceType first_;
1612  InstanceType last_;
1613};
1614
1615
1616class HCheckNonSmi: public HUnaryOperation {
1617 public:
1618  explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
1619    set_representation(Representation::Tagged());
1620    SetFlag(kUseGVN);
1621  }
1622
1623  virtual bool IsCheckInstruction() const { return true; }
1624
1625  virtual Representation RequiredInputRepresentation(int index) const {
1626    return Representation::Tagged();
1627  }
1628
1629  virtual HType CalculateInferredType() const;
1630
1631#ifdef DEBUG
1632  virtual void Verify() const;
1633#endif
1634
1635  DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check_non_smi")
1636};
1637
1638
1639class HCheckPrototypeMaps: public HInstruction {
1640 public:
1641  HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
1642      : prototype_(prototype), holder_(holder) {
1643    SetFlag(kUseGVN);
1644    SetFlag(kDependsOnMaps);
1645  }
1646
1647  virtual bool IsCheckInstruction() const { return true; }
1648
1649#ifdef DEBUG
1650  virtual void Verify() const;
1651#endif
1652
1653  Handle<JSObject> prototype() const { return prototype_; }
1654  Handle<JSObject> holder() const { return holder_; }
1655
1656  DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check_prototype_maps")
1657
1658  virtual intptr_t Hashcode() const {
1659    ASSERT(!Heap::IsAllocationAllowed());
1660    intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
1661    hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
1662    return hash;
1663  }
1664
1665 protected:
1666  virtual bool DataEquals(HValue* other) const {
1667    HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
1668    return prototype_.is_identical_to(b->prototype()) &&
1669        holder_.is_identical_to(b->holder());
1670  }
1671
1672 private:
1673  Handle<JSObject> prototype_;
1674  Handle<JSObject> holder_;
1675};
1676
1677
1678class HCheckSmi: public HUnaryOperation {
1679 public:
1680  explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
1681    set_representation(Representation::Tagged());
1682    SetFlag(kUseGVN);
1683  }
1684
1685  virtual bool IsCheckInstruction() const { return true; }
1686
1687  virtual Representation RequiredInputRepresentation(int index) const {
1688    return Representation::Tagged();
1689  }
1690  virtual HType CalculateInferredType() const;
1691
1692#ifdef DEBUG
1693  virtual void Verify() const;
1694#endif
1695
1696  DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check_smi")
1697};
1698
1699
1700class HPhi: public HValue {
1701 public:
1702  explicit HPhi(int merged_index)
1703      : inputs_(2),
1704        merged_index_(merged_index),
1705        phi_id_(-1) {
1706    for (int i = 0; i < Representation::kNumRepresentations; i++) {
1707      non_phi_uses_[i] = 0;
1708      indirect_uses_[i] = 0;
1709    }
1710    ASSERT(merged_index >= 0);
1711    set_representation(Representation::Tagged());
1712    SetFlag(kFlexibleRepresentation);
1713  }
1714
1715  virtual Representation InferredRepresentation() const {
1716    bool double_occurred = false;
1717    bool int32_occurred = false;
1718    for (int i = 0; i < OperandCount(); ++i) {
1719      HValue* value = OperandAt(i);
1720      if (value->representation().IsDouble()) double_occurred = true;
1721      if (value->representation().IsInteger32()) int32_occurred = true;
1722      if (value->representation().IsTagged()) return Representation::Tagged();
1723    }
1724
1725    if (double_occurred) return Representation::Double();
1726    if (int32_occurred) return Representation::Integer32();
1727    return Representation::None();
1728  }
1729
1730  virtual Range* InferRange();
1731  virtual Representation RequiredInputRepresentation(int index) const {
1732    return representation();
1733  }
1734  virtual HType CalculateInferredType() const;
1735  virtual int OperandCount() const { return inputs_.length(); }
1736  virtual HValue* OperandAt(int index) const { return inputs_[index]; }
1737  HValue* GetRedundantReplacement() const;
1738  void AddInput(HValue* value);
1739
1740  bool HasReceiverOperand();
1741
1742  int merged_index() const { return merged_index_; }
1743
1744  virtual const char* Mnemonic() const { return "phi"; }
1745
1746  virtual void PrintTo(StringStream* stream) const;
1747
1748#ifdef DEBUG
1749  virtual void Verify() const;
1750#endif
1751
1752  DECLARE_INSTRUCTION(Phi)
1753
1754  void InitRealUses(int id);
1755  void AddNonPhiUsesFrom(HPhi* other);
1756  void AddIndirectUsesTo(int* use_count);
1757
1758  int tagged_non_phi_uses() const {
1759    return non_phi_uses_[Representation::kTagged];
1760  }
1761  int int32_non_phi_uses() const {
1762    return non_phi_uses_[Representation::kInteger32];
1763  }
1764  int double_non_phi_uses() const {
1765    return non_phi_uses_[Representation::kDouble];
1766  }
1767  int tagged_indirect_uses() const {
1768    return indirect_uses_[Representation::kTagged];
1769  }
1770  int int32_indirect_uses() const {
1771    return indirect_uses_[Representation::kInteger32];
1772  }
1773  int double_indirect_uses() const {
1774    return indirect_uses_[Representation::kDouble];
1775  }
1776  int phi_id() { return phi_id_; }
1777
1778 protected:
1779  virtual void DeleteFromGraph();
1780  virtual void InternalSetOperandAt(int index, HValue* value) {
1781    inputs_[index] = value;
1782  }
1783
1784 private:
1785  ZoneList<HValue*> inputs_;
1786  int merged_index_;
1787
1788  int non_phi_uses_[Representation::kNumRepresentations];
1789  int indirect_uses_[Representation::kNumRepresentations];
1790  int phi_id_;
1791};
1792
1793
1794class HArgumentsObject: public HInstruction {
1795 public:
1796  HArgumentsObject() {
1797    set_representation(Representation::Tagged());
1798    SetFlag(kIsArguments);
1799  }
1800
1801  DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject, "arguments-object")
1802};
1803
1804
1805class HConstant: public HInstruction {
1806 public:
1807  HConstant(Handle<Object> handle, Representation r);
1808
1809  Handle<Object> handle() const { return handle_; }
1810
1811  bool InOldSpace() const { return !Heap::InNewSpace(*handle_); }
1812
1813  virtual bool EmitAtUses() const { return !representation().IsDouble(); }
1814  virtual void PrintDataTo(StringStream* stream) const;
1815  virtual HType CalculateInferredType() const;
1816  bool IsInteger() const { return handle_->IsSmi(); }
1817  HConstant* CopyToRepresentation(Representation r) const;
1818  HConstant* CopyToTruncatedInt32() const;
1819  bool HasInteger32Value() const { return has_int32_value_; }
1820  int32_t Integer32Value() const {
1821    ASSERT(HasInteger32Value());
1822    return int32_value_;
1823  }
1824  bool HasDoubleValue() const { return has_double_value_; }
1825  double DoubleValue() const {
1826    ASSERT(HasDoubleValue());
1827    return double_value_;
1828  }
1829  bool HasStringValue() const { return handle_->IsString(); }
1830
1831  virtual intptr_t Hashcode() const {
1832    ASSERT(!Heap::allow_allocation(false));
1833    return reinterpret_cast<intptr_t>(*handle());
1834  }
1835
1836#ifdef DEBUG
1837  virtual void Verify() const { }
1838#endif
1839
1840  DECLARE_CONCRETE_INSTRUCTION(Constant, "constant")
1841
1842 protected:
1843  virtual Range* InferRange();
1844
1845  virtual bool DataEquals(HValue* other) const {
1846    HConstant* other_constant = HConstant::cast(other);
1847    return handle().is_identical_to(other_constant->handle());
1848  }
1849
1850 private:
1851  Handle<Object> handle_;
1852  HType constant_type_;
1853
1854  // The following two values represent the int32 and the double value of the
1855  // given constant if there is a lossless conversion between the constant
1856  // and the specific representation.
1857  bool has_int32_value_;
1858  int32_t int32_value_;
1859  bool has_double_value_;
1860  double double_value_;
1861};
1862
1863
1864class HBinaryOperation: public HInstruction {
1865 public:
1866  HBinaryOperation(HValue* left, HValue* right) {
1867    ASSERT(left != NULL && right != NULL);
1868    SetOperandAt(0, left);
1869    SetOperandAt(1, right);
1870  }
1871
1872  HValue* left() const { return OperandAt(0); }
1873  HValue* right() const { return OperandAt(1); }
1874
1875  // TODO(kasperl): Move these helpers to the IA-32 Lithium
1876  // instruction sequence builder.
1877  HValue* LeastConstantOperand() const {
1878    if (IsCommutative() && left()->IsConstant()) return right();
1879    return left();
1880  }
1881  HValue* MostConstantOperand() const {
1882    if (IsCommutative() && left()->IsConstant()) return left();
1883    return right();
1884  }
1885
1886  virtual bool IsCommutative() const { return false; }
1887
1888  virtual void PrintDataTo(StringStream* stream) const;
1889  virtual int OperandCount() const { return operands_.length(); }
1890  virtual HValue* OperandAt(int index) const { return operands_[index]; }
1891
1892  DECLARE_INSTRUCTION(BinaryOperation)
1893
1894 protected:
1895  virtual void InternalSetOperandAt(int index, HValue* value) {
1896    operands_[index] = value;
1897  }
1898
1899 private:
1900  HOperandVector<2> operands_;
1901};
1902
1903
1904class HApplyArguments: public HInstruction {
1905 public:
1906  HApplyArguments(HValue* function,
1907                  HValue* receiver,
1908                  HValue* length,
1909                  HValue* elements) {
1910    set_representation(Representation::Tagged());
1911    SetOperandAt(0, function);
1912    SetOperandAt(1, receiver);
1913    SetOperandAt(2, length);
1914    SetOperandAt(3, elements);
1915  }
1916
1917  virtual Representation RequiredInputRepresentation(int index) const {
1918    // The length is untagged, all other inputs are tagged.
1919    return (index == 2)
1920        ? Representation::Integer32()
1921        : Representation::Tagged();
1922  }
1923
1924  HValue* function() const { return OperandAt(0); }
1925  HValue* receiver() const { return OperandAt(1); }
1926  HValue* length() const { return OperandAt(2); }
1927  HValue* elements() const { return OperandAt(3); }
1928
1929  virtual int OperandCount() const { return operands_.length(); }
1930  virtual HValue* OperandAt(int index) const { return operands_[index]; }
1931
1932  DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply_arguments")
1933
1934
1935
1936 protected:
1937  virtual void InternalSetOperandAt(int index, HValue* value) {
1938    operands_[index] = value;
1939  }
1940
1941 private:
1942  HOperandVector<4> operands_;
1943};
1944
1945
1946class HArgumentsElements: public HInstruction {
1947 public:
1948  HArgumentsElements() {
1949    // The value produced by this instruction is a pointer into the stack
1950    // that looks as if it was a smi because of alignment.
1951    set_representation(Representation::Tagged());
1952    SetFlag(kUseGVN);
1953  }
1954
1955  DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments_elements")
1956};
1957
1958
1959class HArgumentsLength: public HUnaryOperation {
1960 public:
1961  explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
1962    set_representation(Representation::Integer32());
1963    SetFlag(kUseGVN);
1964  }
1965
1966  DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments_length")
1967};
1968
1969
1970class HAccessArgumentsAt: public HInstruction {
1971 public:
1972  HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
1973    set_representation(Representation::Tagged());
1974    SetFlag(kUseGVN);
1975    SetOperandAt(0, arguments);
1976    SetOperandAt(1, length);
1977    SetOperandAt(2, index);
1978  }
1979
1980  virtual void PrintDataTo(StringStream* stream) const;
1981
1982  virtual Representation RequiredInputRepresentation(int index) const {
1983    // The arguments elements is considered tagged.
1984    return index == 0
1985        ? Representation::Tagged()
1986        : Representation::Integer32();
1987  }
1988
1989  HValue* arguments() const { return operands_[0]; }
1990  HValue* length() const { return operands_[1]; }
1991  HValue* index() const { return operands_[2]; }
1992
1993  virtual int OperandCount() const { return operands_.length(); }
1994  virtual HValue* OperandAt(int index) const { return operands_[index]; }
1995
1996  DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access_arguments_at")
1997
1998 protected:
1999  virtual void InternalSetOperandAt(int index, HValue* value) {
2000    operands_[index] = value;
2001  }
2002
2003 private:
2004  HOperandVector<3> operands_;
2005};
2006
2007
2008class HBoundsCheck: public HBinaryOperation {
2009 public:
2010  HBoundsCheck(HValue* index, HValue* length)
2011      : HBinaryOperation(index, length) {
2012    SetFlag(kUseGVN);
2013  }
2014
2015  virtual bool IsCheckInstruction() const { return true; }
2016
2017  virtual Representation RequiredInputRepresentation(int index) const {
2018    return Representation::Integer32();
2019  }
2020
2021#ifdef DEBUG
2022  virtual void Verify() const;
2023#endif
2024
2025  HValue* index() const { return left(); }
2026  HValue* length() const { return right(); }
2027
2028  DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds_check")
2029};
2030
2031
2032class HBitwiseBinaryOperation: public HBinaryOperation {
2033 public:
2034  HBitwiseBinaryOperation(HValue* left, HValue* right)
2035      : HBinaryOperation(left, right) {
2036    // Default to truncating, Integer32, UseGVN.
2037    set_representation(Representation::Integer32());
2038    SetFlag(kTruncatingToInt32);
2039    SetFlag(kUseGVN);
2040  }
2041
2042  virtual Representation RequiredInputRepresentation(int index) const {
2043    return Representation::Integer32();
2044  }
2045
2046  DECLARE_INSTRUCTION(BitwiseBinaryOperation)
2047};
2048
2049
2050class HArithmeticBinaryOperation: public HBinaryOperation {
2051 public:
2052  HArithmeticBinaryOperation(HValue* left, HValue* right)
2053      : HBinaryOperation(left, right) {
2054    set_representation(Representation::Tagged());
2055    SetFlag(kFlexibleRepresentation);
2056    SetFlagMask(AllSideEffects());
2057  }
2058
2059  virtual void RepresentationChanged(Representation to) {
2060    if (!to.IsTagged()) {
2061      ClearFlagMask(AllSideEffects());
2062      SetFlag(kUseGVN);
2063    }
2064  }
2065
2066  virtual HType CalculateInferredType() const;
2067  virtual Representation RequiredInputRepresentation(int index) const {
2068    return representation();
2069  }
2070  virtual Representation InferredRepresentation() const {
2071    if (left()->representation().Equals(right()->representation())) {
2072      return left()->representation();
2073    }
2074    return HValue::InferredRepresentation();
2075  }
2076
2077  DECLARE_INSTRUCTION(ArithmeticBinaryOperation)
2078};
2079
2080
2081class HCompare: public HBinaryOperation {
2082 public:
2083  HCompare(HValue* left, HValue* right, Token::Value token)
2084      : HBinaryOperation(left, right), token_(token) {
2085    ASSERT(Token::IsCompareOp(token));
2086    set_representation(Representation::Tagged());
2087    SetFlagMask(AllSideEffects());
2088  }
2089
2090  void SetInputRepresentation(Representation r);
2091  virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2092  virtual Representation RequiredInputRepresentation(int index) const {
2093    return input_representation_;
2094  }
2095  Representation GetInputRepresentation() const {
2096    return input_representation_;
2097  }
2098  Token::Value token() const { return token_; }
2099  virtual void PrintDataTo(StringStream* stream) const;
2100
2101  virtual HType CalculateInferredType() const;
2102
2103  virtual intptr_t Hashcode() const {
2104    return HValue::Hashcode() * 7 + token_;
2105  }
2106
2107  DECLARE_CONCRETE_INSTRUCTION(Compare, "compare")
2108
2109 protected:
2110  virtual bool DataEquals(HValue* other) const {
2111    HCompare* comp = HCompare::cast(other);
2112    return token_ == comp->token();
2113  }
2114
2115 private:
2116  Representation input_representation_;
2117  Token::Value token_;
2118};
2119
2120
2121class HCompareJSObjectEq: public HBinaryOperation {
2122 public:
2123  HCompareJSObjectEq(HValue* left, HValue* right)
2124      : HBinaryOperation(left, right) {
2125    set_representation(Representation::Tagged());
2126    SetFlag(kUseGVN);
2127  }
2128
2129  virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2130  virtual Representation RequiredInputRepresentation(int index) const {
2131    return Representation::Tagged();
2132  }
2133  virtual HType CalculateInferredType() const;
2134
2135  DECLARE_CONCRETE_INSTRUCTION(CompareJSObjectEq, "compare-js-object-eq")
2136};
2137
2138
2139class HUnaryPredicate: public HUnaryOperation {
2140 public:
2141  explicit HUnaryPredicate(HValue* value) : HUnaryOperation(value) {
2142    set_representation(Representation::Tagged());
2143    SetFlag(kUseGVN);
2144  }
2145  virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2146  virtual Representation RequiredInputRepresentation(int index) const {
2147    return Representation::Tagged();
2148  }
2149  virtual HType CalculateInferredType() const;
2150};
2151
2152
2153class HIsNull: public HUnaryPredicate {
2154 public:
2155  HIsNull(HValue* value, bool is_strict)
2156      : HUnaryPredicate(value), is_strict_(is_strict) { }
2157
2158  bool is_strict() const { return is_strict_; }
2159
2160  DECLARE_CONCRETE_INSTRUCTION(IsNull, "is_null")
2161
2162 protected:
2163  virtual bool DataEquals(HValue* other) const {
2164    HIsNull* b = HIsNull::cast(other);
2165    return is_strict_ == b->is_strict();
2166  }
2167
2168 private:
2169  bool is_strict_;
2170};
2171
2172
2173class HIsObject: public HUnaryPredicate {
2174 public:
2175  explicit HIsObject(HValue* value) : HUnaryPredicate(value) { }
2176
2177  DECLARE_CONCRETE_INSTRUCTION(IsObject, "is_object")
2178};
2179
2180
2181class HIsSmi: public HUnaryPredicate {
2182 public:
2183  explicit HIsSmi(HValue* value) : HUnaryPredicate(value) { }
2184
2185  DECLARE_CONCRETE_INSTRUCTION(IsSmi, "is_smi")
2186};
2187
2188
2189class HHasInstanceType: public HUnaryPredicate {
2190 public:
2191  HHasInstanceType(HValue* value, InstanceType type)
2192      : HUnaryPredicate(value), from_(type), to_(type) { }
2193  HHasInstanceType(HValue* value, InstanceType from, InstanceType to)
2194      : HUnaryPredicate(value), from_(from), to_(to) {
2195    ASSERT(to == LAST_TYPE);  // Others not implemented yet in backend.
2196  }
2197
2198  InstanceType from() { return from_; }
2199  InstanceType to() { return to_; }
2200
2201  virtual void PrintDataTo(StringStream* stream) const;
2202
2203  DECLARE_CONCRETE_INSTRUCTION(HasInstanceType, "has_instance_type")
2204
2205 protected:
2206  virtual bool DataEquals(HValue* other) const {
2207    HHasInstanceType* b = HHasInstanceType::cast(other);
2208    return (from_ == b->from()) && (to_ == b->to());
2209  }
2210
2211 private:
2212  InstanceType from_;
2213  InstanceType to_;  // Inclusive range, not all combinations work.
2214};
2215
2216
2217class HHasCachedArrayIndex: public HUnaryPredicate {
2218 public:
2219  explicit HHasCachedArrayIndex(HValue* value) : HUnaryPredicate(value) { }
2220
2221  DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndex, "has_cached_array_index")
2222};
2223
2224
2225class HClassOfTest: public HUnaryPredicate {
2226 public:
2227  HClassOfTest(HValue* value, Handle<String> class_name)
2228      : HUnaryPredicate(value), class_name_(class_name) { }
2229
2230  DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class_of_test")
2231
2232  virtual void PrintDataTo(StringStream* stream) const;
2233
2234  Handle<String> class_name() const { return class_name_; }
2235
2236 protected:
2237  virtual bool DataEquals(HValue* other) const {
2238    HClassOfTest* b = HClassOfTest::cast(other);
2239    return class_name_.is_identical_to(b->class_name_);
2240  }
2241
2242 private:
2243  Handle<String> class_name_;
2244};
2245
2246
2247class HTypeofIs: public HUnaryPredicate {
2248 public:
2249  HTypeofIs(HValue* value, Handle<String> type_literal)
2250      : HUnaryPredicate(value), type_literal_(type_literal) { }
2251
2252  Handle<String> type_literal() { return type_literal_; }
2253  virtual void PrintDataTo(StringStream* stream) const;
2254
2255  DECLARE_CONCRETE_INSTRUCTION(TypeofIs, "typeof_is")
2256
2257 protected:
2258  virtual bool DataEquals(HValue* other) const {
2259    HTypeofIs* b = HTypeofIs::cast(other);
2260    return type_literal_.is_identical_to(b->type_literal_);
2261  }
2262
2263 private:
2264  Handle<String> type_literal_;
2265};
2266
2267
2268class HInstanceOf: public HBinaryOperation {
2269 public:
2270  HInstanceOf(HValue* left, HValue* right) : HBinaryOperation(left, right) {
2271    set_representation(Representation::Tagged());
2272    SetFlagMask(AllSideEffects());
2273  }
2274
2275  virtual bool EmitAtUses() const { return uses()->length() <= 1; }
2276
2277  virtual Representation RequiredInputRepresentation(int index) const {
2278    return Representation::Tagged();
2279  }
2280
2281  DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance_of")
2282};
2283
2284
2285class HInstanceOfKnownGlobal: public HUnaryOperation {
2286 public:
2287  HInstanceOfKnownGlobal(HValue* left, Handle<JSFunction> right)
2288      : HUnaryOperation(left), function_(right) {
2289    set_representation(Representation::Tagged());
2290    SetFlagMask(AllSideEffects());
2291  }
2292
2293  Handle<JSFunction> function() { return function_; }
2294
2295  virtual Representation RequiredInputRepresentation(int index) const {
2296    return Representation::Tagged();
2297  }
2298
2299  DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
2300                               "instance_of_known_global")
2301
2302 private:
2303  Handle<JSFunction> function_;
2304};
2305
2306
2307class HPower: public HBinaryOperation {
2308 public:
2309  HPower(HValue* left, HValue* right)
2310      : HBinaryOperation(left, right) {
2311    set_representation(Representation::Double());
2312    SetFlag(kUseGVN);
2313  }
2314
2315  virtual Representation RequiredInputRepresentation(int index) const {
2316    return (index == 1) ? Representation::None() : Representation::Double();
2317  }
2318
2319  DECLARE_CONCRETE_INSTRUCTION(Power, "power")
2320};
2321
2322
2323class HAdd: public HArithmeticBinaryOperation {
2324 public:
2325  HAdd(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2326    SetFlag(kCanOverflow);
2327  }
2328
2329  // Add is only commutative if two integer values are added and not if two
2330  // tagged values are added (because it might be a String concatenation).
2331  virtual bool IsCommutative() const {
2332    return !representation().IsTagged();
2333  }
2334
2335  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2336
2337  virtual HType CalculateInferredType() const;
2338
2339  DECLARE_CONCRETE_INSTRUCTION(Add, "add")
2340
2341 protected:
2342  virtual Range* InferRange();
2343};
2344
2345
2346class HSub: public HArithmeticBinaryOperation {
2347 public:
2348  HSub(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2349    SetFlag(kCanOverflow);
2350  }
2351
2352  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2353
2354  DECLARE_CONCRETE_INSTRUCTION(Sub, "sub")
2355
2356 protected:
2357  virtual Range* InferRange();
2358};
2359
2360
2361class HMul: public HArithmeticBinaryOperation {
2362 public:
2363  HMul(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2364    SetFlag(kCanOverflow);
2365  }
2366
2367  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2368
2369  // Only commutative if it is certain that not two objects are multiplicated.
2370  virtual bool IsCommutative() const {
2371    return !representation().IsTagged();
2372  }
2373
2374  DECLARE_CONCRETE_INSTRUCTION(Mul, "mul")
2375
2376 protected:
2377  virtual Range* InferRange();
2378};
2379
2380
2381class HMod: public HArithmeticBinaryOperation {
2382 public:
2383  HMod(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2384    SetFlag(kCanBeDivByZero);
2385  }
2386
2387  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2388
2389  DECLARE_CONCRETE_INSTRUCTION(Mod, "mod")
2390
2391 protected:
2392  virtual Range* InferRange();
2393};
2394
2395
2396class HDiv: public HArithmeticBinaryOperation {
2397 public:
2398  HDiv(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) {
2399    SetFlag(kCanBeDivByZero);
2400    SetFlag(kCanOverflow);
2401  }
2402
2403  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2404
2405  DECLARE_CONCRETE_INSTRUCTION(Div, "div")
2406
2407 protected:
2408  virtual Range* InferRange();
2409};
2410
2411
2412class HBitAnd: public HBitwiseBinaryOperation {
2413 public:
2414  HBitAnd(HValue* left, HValue* right)
2415      : HBitwiseBinaryOperation(left, right) { }
2416
2417  virtual bool IsCommutative() const { return true; }
2418  virtual HType CalculateInferredType() const;
2419
2420  DECLARE_CONCRETE_INSTRUCTION(BitAnd, "bit_and")
2421
2422 protected:
2423  virtual Range* InferRange();
2424};
2425
2426
2427class HBitXor: public HBitwiseBinaryOperation {
2428 public:
2429  HBitXor(HValue* left, HValue* right)
2430      : HBitwiseBinaryOperation(left, right) { }
2431
2432  virtual bool IsCommutative() const { return true; }
2433  virtual HType CalculateInferredType() const;
2434
2435  DECLARE_CONCRETE_INSTRUCTION(BitXor, "bit_xor")
2436};
2437
2438
2439class HBitOr: public HBitwiseBinaryOperation {
2440 public:
2441  HBitOr(HValue* left, HValue* right)
2442      : HBitwiseBinaryOperation(left, right) { }
2443
2444  virtual bool IsCommutative() const { return true; }
2445  virtual HType CalculateInferredType() const;
2446
2447  DECLARE_CONCRETE_INSTRUCTION(BitOr, "bit_or")
2448
2449 protected:
2450  virtual Range* InferRange();
2451};
2452
2453
2454class HShl: public HBitwiseBinaryOperation {
2455 public:
2456  HShl(HValue* left, HValue* right)
2457      : HBitwiseBinaryOperation(left, right) { }
2458
2459  virtual Range* InferRange();
2460  virtual HType CalculateInferredType() const;
2461
2462  DECLARE_CONCRETE_INSTRUCTION(Shl, "shl")
2463};
2464
2465
2466class HShr: public HBitwiseBinaryOperation {
2467 public:
2468  HShr(HValue* left, HValue* right)
2469      : HBitwiseBinaryOperation(left, right) { }
2470
2471  virtual HType CalculateInferredType() const;
2472
2473  DECLARE_CONCRETE_INSTRUCTION(Shr, "shr")
2474};
2475
2476
2477class HSar: public HBitwiseBinaryOperation {
2478 public:
2479  HSar(HValue* left, HValue* right)
2480      : HBitwiseBinaryOperation(left, right) { }
2481
2482  virtual Range* InferRange();
2483  virtual HType CalculateInferredType() const;
2484
2485  DECLARE_CONCRETE_INSTRUCTION(Sar, "sar")
2486};
2487
2488
2489class HOsrEntry: public HInstruction {
2490 public:
2491  explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
2492    SetFlag(kChangesOsrEntries);
2493  }
2494
2495  int ast_id() const { return ast_id_; }
2496
2497  DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr_entry")
2498
2499 private:
2500  int ast_id_;
2501};
2502
2503
2504class HParameter: public HInstruction {
2505 public:
2506  explicit HParameter(unsigned index) : index_(index) {
2507    set_representation(Representation::Tagged());
2508  }
2509
2510  unsigned index() const { return index_; }
2511
2512  virtual void PrintDataTo(StringStream* stream) const;
2513
2514  DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
2515
2516 private:
2517  unsigned index_;
2518};
2519
2520
2521class HCallStub: public HInstruction {
2522 public:
2523  HCallStub(CodeStub::Major major_key, int argument_count)
2524      : major_key_(major_key),
2525        argument_count_(argument_count),
2526        transcendental_type_(TranscendentalCache::kNumberOfCaches) {
2527    set_representation(Representation::Tagged());
2528    SetFlagMask(AllSideEffects());
2529  }
2530
2531  CodeStub::Major major_key() { return major_key_; }
2532  int argument_count() { return argument_count_; }
2533
2534  void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
2535    transcendental_type_ = transcendental_type;
2536  }
2537  TranscendentalCache::Type transcendental_type() {
2538    return transcendental_type_;
2539  }
2540  virtual void PrintDataTo(StringStream* stream) const;
2541
2542  DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub")
2543
2544 private:
2545  CodeStub::Major major_key_;
2546  int argument_count_;
2547  TranscendentalCache::Type transcendental_type_;
2548};
2549
2550
2551class HUnknownOSRValue: public HInstruction {
2552 public:
2553  HUnknownOSRValue() { set_representation(Representation::Tagged()); }
2554
2555  DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown_osr_value")
2556};
2557
2558
2559class HLoadGlobal: public HInstruction {
2560 public:
2561  HLoadGlobal(Handle<JSGlobalPropertyCell> cell, bool check_hole_value)
2562      : cell_(cell), check_hole_value_(check_hole_value) {
2563    set_representation(Representation::Tagged());
2564    SetFlag(kUseGVN);
2565    SetFlag(kDependsOnGlobalVars);
2566  }
2567
2568  Handle<JSGlobalPropertyCell>  cell() const { return cell_; }
2569  bool check_hole_value() const { return check_hole_value_; }
2570
2571  virtual Representation RequiredInputRepresentation(int index) const {
2572    return Representation::Tagged();
2573  }
2574  virtual void PrintDataTo(StringStream* stream) const;
2575
2576  virtual intptr_t Hashcode() const {
2577    ASSERT(!Heap::allow_allocation(false));
2578    return reinterpret_cast<intptr_t>(*cell_);
2579  }
2580
2581  DECLARE_CONCRETE_INSTRUCTION(LoadGlobal, "load_global")
2582
2583 protected:
2584  virtual bool DataEquals(HValue* other) const {
2585    HLoadGlobal* b = HLoadGlobal::cast(other);
2586    return cell_.is_identical_to(b->cell());
2587  }
2588
2589 private:
2590  Handle<JSGlobalPropertyCell> cell_;
2591  bool check_hole_value_;
2592};
2593
2594
2595class HStoreGlobal: public HUnaryOperation {
2596 public:
2597  HStoreGlobal(HValue* value, Handle<JSGlobalPropertyCell> cell)
2598      : HUnaryOperation(value), cell_(cell) {
2599    SetFlag(kChangesGlobalVars);
2600  }
2601
2602  Handle<JSGlobalPropertyCell> cell() const { return cell_; }
2603
2604  virtual Representation RequiredInputRepresentation(int index) const {
2605    return Representation::Tagged();
2606  }
2607  virtual void PrintDataTo(StringStream* stream) const;
2608
2609  DECLARE_CONCRETE_INSTRUCTION(StoreGlobal, "store_global")
2610
2611 protected:
2612  virtual bool DataEquals(HValue* other) const {
2613    HStoreGlobal* b = HStoreGlobal::cast(other);
2614    return cell_.is_identical_to(b->cell());
2615  }
2616
2617 private:
2618  Handle<JSGlobalPropertyCell> cell_;
2619};
2620
2621
2622class HLoadContextSlot: public HInstruction {
2623 public:
2624  HLoadContextSlot(int context_chain_length , int slot_index)
2625      : context_chain_length_(context_chain_length), slot_index_(slot_index) {
2626    set_representation(Representation::Tagged());
2627    SetFlag(kUseGVN);
2628    SetFlag(kDependsOnCalls);
2629  }
2630
2631  int context_chain_length() const { return context_chain_length_; }
2632  int slot_index() const { return slot_index_; }
2633
2634  virtual void PrintDataTo(StringStream* stream) const;
2635
2636  virtual intptr_t Hashcode() const {
2637    return context_chain_length() * 29 + slot_index();
2638  }
2639
2640  DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load_context_slot")
2641
2642 protected:
2643  virtual bool DataEquals(HValue* other) const {
2644    HLoadContextSlot* b = HLoadContextSlot::cast(other);
2645    return (context_chain_length() == b->context_chain_length())
2646        && (slot_index() == b->slot_index());
2647  }
2648
2649 private:
2650  int context_chain_length_;
2651  int slot_index_;
2652};
2653
2654
2655class HLoadNamedField: public HUnaryOperation {
2656 public:
2657  HLoadNamedField(HValue* object, bool is_in_object, int offset)
2658      : HUnaryOperation(object),
2659        is_in_object_(is_in_object),
2660        offset_(offset) {
2661    set_representation(Representation::Tagged());
2662    SetFlag(kUseGVN);
2663    if (is_in_object) {
2664      SetFlag(kDependsOnInobjectFields);
2665    } else {
2666      SetFlag(kDependsOnBackingStoreFields);
2667    }
2668  }
2669
2670  HValue* object() const { return OperandAt(0); }
2671  bool is_in_object() const { return is_in_object_; }
2672  int offset() const { return offset_; }
2673
2674  virtual Representation RequiredInputRepresentation(int index) const {
2675    return Representation::Tagged();
2676  }
2677  virtual void PrintDataTo(StringStream* stream) const;
2678
2679  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load_named_field")
2680
2681 protected:
2682  virtual bool DataEquals(HValue* other) const {
2683    HLoadNamedField* b = HLoadNamedField::cast(other);
2684    return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
2685  }
2686
2687 private:
2688  bool is_in_object_;
2689  int offset_;
2690};
2691
2692
2693class HLoadNamedGeneric: public HUnaryOperation {
2694 public:
2695  HLoadNamedGeneric(HValue* object, Handle<Object> name)
2696      : HUnaryOperation(object), name_(name) {
2697    set_representation(Representation::Tagged());
2698    SetFlagMask(AllSideEffects());
2699  }
2700
2701  HValue* object() const { return OperandAt(0); }
2702  Handle<Object> name() const { return name_; }
2703
2704  virtual Representation RequiredInputRepresentation(int index) const {
2705    return Representation::Tagged();
2706  }
2707
2708  DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load_named_generic")
2709
2710 protected:
2711  virtual bool DataEquals(HValue* other) const {
2712    HLoadNamedGeneric* b = HLoadNamedGeneric::cast(other);
2713    return name_.is_identical_to(b->name_);
2714  }
2715
2716 private:
2717  Handle<Object> name_;
2718};
2719
2720
2721class HLoadFunctionPrototype: public HUnaryOperation {
2722 public:
2723  explicit HLoadFunctionPrototype(HValue* function)
2724      : HUnaryOperation(function) {
2725    set_representation(Representation::Tagged());
2726    SetFlagMask(kDependsOnFunctionPrototypes);
2727  }
2728
2729  HValue* function() const { return OperandAt(0); }
2730
2731  virtual Representation RequiredInputRepresentation(int index) const {
2732    return Representation::Tagged();
2733  }
2734
2735  DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load_function_prototype")
2736
2737 protected:
2738  virtual bool DataEquals(HValue* other) const { return true; }
2739};
2740
2741
2742class HLoadKeyed: public HBinaryOperation {
2743 public:
2744  HLoadKeyed(HValue* obj, HValue* key) : HBinaryOperation(obj, key) {
2745    set_representation(Representation::Tagged());
2746  }
2747
2748  virtual void PrintDataTo(StringStream* stream) const;
2749
2750  virtual Representation RequiredInputRepresentation(int index) const {
2751    return Representation::Tagged();
2752  }
2753  HValue* object() const { return OperandAt(0); }
2754  HValue* key() const { return OperandAt(1); }
2755
2756  DECLARE_INSTRUCTION(LoadKeyed)
2757};
2758
2759
2760class HLoadKeyedFastElement: public HLoadKeyed {
2761 public:
2762  HLoadKeyedFastElement(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
2763    SetFlag(kDependsOnArrayElements);
2764    SetFlag(kUseGVN);
2765  }
2766
2767  virtual Representation RequiredInputRepresentation(int index) const {
2768    // The key is supposed to be Integer32.
2769    return (index == 1) ? Representation::Integer32()
2770        : Representation::Tagged();
2771  }
2772
2773  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement,
2774                               "load_keyed_fast_element")
2775};
2776
2777
2778class HLoadKeyedGeneric: public HLoadKeyed {
2779 public:
2780  HLoadKeyedGeneric(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
2781    SetFlagMask(AllSideEffects());
2782  }
2783
2784  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load_keyed_generic")
2785};
2786
2787
2788static inline bool StoringValueNeedsWriteBarrier(HValue* value) {
2789  return !value->type().IsSmi() &&
2790      !(value->IsConstant() && HConstant::cast(value)->InOldSpace());
2791}
2792
2793
2794class HStoreNamed: public HBinaryOperation {
2795 public:
2796  HStoreNamed(HValue* obj, Handle<Object> name, HValue* val)
2797      : HBinaryOperation(obj, val), name_(name) {
2798  }
2799
2800  virtual Representation RequiredInputRepresentation(int index) const {
2801    return Representation::Tagged();
2802  }
2803
2804  virtual void PrintDataTo(StringStream* stream) const;
2805
2806  HValue* object() const { return OperandAt(0); }
2807  Handle<Object> name() const { return name_; }
2808  HValue* value() const { return OperandAt(1); }
2809  void set_value(HValue* value) { SetOperandAt(1, value); }
2810
2811  bool NeedsWriteBarrier() const {
2812    return StoringValueNeedsWriteBarrier(value());
2813  }
2814
2815  DECLARE_INSTRUCTION(StoreNamed)
2816
2817 protected:
2818  virtual bool DataEquals(HValue* other) const {
2819    HStoreNamed* b = HStoreNamed::cast(other);
2820    return name_.is_identical_to(b->name_);
2821  }
2822
2823 private:
2824  Handle<Object> name_;
2825};
2826
2827
2828class HStoreNamedField: public HStoreNamed {
2829 public:
2830  HStoreNamedField(HValue* obj,
2831                   Handle<Object> name,
2832                   HValue* val,
2833                   bool in_object,
2834                   int offset)
2835      : HStoreNamed(obj, name, val),
2836        is_in_object_(in_object),
2837        offset_(offset) {
2838    if (is_in_object_) {
2839      SetFlag(kChangesInobjectFields);
2840    } else {
2841      SetFlag(kChangesBackingStoreFields);
2842    }
2843  }
2844
2845  DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store_named_field")
2846
2847  virtual Representation RequiredInputRepresentation(int index) const {
2848    return  Representation::Tagged();
2849  }
2850  virtual void PrintDataTo(StringStream* stream) const;
2851
2852  bool is_in_object() const { return is_in_object_; }
2853  int offset() const { return offset_; }
2854  Handle<Map> transition() const { return transition_; }
2855  void set_transition(Handle<Map> map) { transition_ = map; }
2856
2857 private:
2858  bool is_in_object_;
2859  int offset_;
2860  Handle<Map> transition_;
2861};
2862
2863
2864class HStoreNamedGeneric: public HStoreNamed {
2865 public:
2866  HStoreNamedGeneric(HValue* obj, Handle<Object> name, HValue* val)
2867      : HStoreNamed(obj, name, val) {
2868    SetFlagMask(AllSideEffects());
2869  }
2870
2871  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store_named_generic")
2872};
2873
2874
2875class HStoreKeyed: public HInstruction {
2876 public:
2877  HStoreKeyed(HValue* obj, HValue* key, HValue* val) {
2878    SetOperandAt(0, obj);
2879    SetOperandAt(1, key);
2880    SetOperandAt(2, val);
2881  }
2882
2883  virtual void PrintDataTo(StringStream* stream) const;
2884  virtual int OperandCount() const { return operands_.length(); }
2885  virtual HValue* OperandAt(int index) const { return operands_[index]; }
2886
2887  virtual Representation RequiredInputRepresentation(int index) const {
2888    return Representation::Tagged();
2889  }
2890
2891  HValue* object() const { return OperandAt(0); }
2892  HValue* key() const { return OperandAt(1); }
2893  HValue* value() const { return OperandAt(2); }
2894
2895  bool NeedsWriteBarrier() const {
2896    return StoringValueNeedsWriteBarrier(value());
2897  }
2898
2899  DECLARE_INSTRUCTION(StoreKeyed)
2900
2901 protected:
2902  virtual void InternalSetOperandAt(int index, HValue* value) {
2903    operands_[index] = value;
2904  }
2905
2906 private:
2907  HOperandVector<3> operands_;
2908};
2909
2910
2911class HStoreKeyedFastElement: public HStoreKeyed {
2912 public:
2913  HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val)
2914      : HStoreKeyed(obj, key, val) {
2915    SetFlag(kChangesArrayElements);
2916  }
2917
2918  virtual Representation RequiredInputRepresentation(int index) const {
2919    // The key is supposed to be Integer32.
2920    return (index == 1) ? Representation::Integer32()
2921        : Representation::Tagged();
2922  }
2923
2924  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
2925                               "store_keyed_fast_element")
2926};
2927
2928
2929class HStoreKeyedGeneric: public HStoreKeyed {
2930 public:
2931  HStoreKeyedGeneric(HValue* obj, HValue* key, HValue* val)
2932      : HStoreKeyed(obj, key, val) {
2933    SetFlagMask(AllSideEffects());
2934  }
2935
2936  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store_keyed_generic")
2937};
2938
2939
2940class HMaterializedLiteral: public HInstruction {
2941 public:
2942  HMaterializedLiteral(int index, int depth)
2943      : literal_index_(index), depth_(depth) {
2944    set_representation(Representation::Tagged());
2945  }
2946
2947  int literal_index() const { return literal_index_; }
2948  int depth() const { return depth_; }
2949
2950  DECLARE_INSTRUCTION(MaterializedLiteral)
2951
2952 private:
2953  int literal_index_;
2954  int depth_;
2955};
2956
2957
2958class HArrayLiteral: public HMaterializedLiteral {
2959 public:
2960  HArrayLiteral(Handle<FixedArray> constant_elements,
2961                int length,
2962                int literal_index,
2963                int depth)
2964      : HMaterializedLiteral(literal_index, depth),
2965        length_(length),
2966        constant_elements_(constant_elements) {}
2967
2968  Handle<FixedArray> constant_elements() const { return constant_elements_; }
2969  int length() const { return length_; }
2970
2971  bool IsCopyOnWrite() const;
2972
2973  DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral, "array_literal")
2974
2975 private:
2976  int length_;
2977  Handle<FixedArray> constant_elements_;
2978};
2979
2980
2981class HObjectLiteral: public HMaterializedLiteral {
2982 public:
2983  HObjectLiteral(Handle<FixedArray> constant_properties,
2984                 bool fast_elements,
2985                 int literal_index,
2986                 int depth)
2987      : HMaterializedLiteral(literal_index, depth),
2988        constant_properties_(constant_properties),
2989        fast_elements_(fast_elements) {}
2990
2991  Handle<FixedArray> constant_properties() const {
2992    return constant_properties_;
2993  }
2994  bool fast_elements() const { return fast_elements_; }
2995
2996  DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object_literal")
2997
2998 private:
2999  Handle<FixedArray> constant_properties_;
3000  bool fast_elements_;
3001};
3002
3003
3004class HRegExpLiteral: public HMaterializedLiteral {
3005 public:
3006  HRegExpLiteral(Handle<String> pattern,
3007                 Handle<String> flags,
3008                 int literal_index)
3009      : HMaterializedLiteral(literal_index, 0),
3010        pattern_(pattern),
3011        flags_(flags) { }
3012
3013  Handle<String> pattern() { return pattern_; }
3014  Handle<String> flags() { return flags_; }
3015
3016  DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp_literal")
3017
3018 private:
3019  Handle<String> pattern_;
3020  Handle<String> flags_;
3021};
3022
3023
3024class HFunctionLiteral: public HInstruction {
3025 public:
3026  HFunctionLiteral(Handle<SharedFunctionInfo> shared, bool pretenure)
3027      : shared_info_(shared), pretenure_(pretenure) {
3028    set_representation(Representation::Tagged());
3029  }
3030
3031  DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function_literal")
3032
3033  Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
3034  bool pretenure() const { return pretenure_; }
3035
3036 private:
3037  Handle<SharedFunctionInfo> shared_info_;
3038  bool pretenure_;
3039};
3040
3041
3042class HTypeof: public HUnaryOperation {
3043 public:
3044  explicit HTypeof(HValue* value) : HUnaryOperation(value) {
3045    set_representation(Representation::Tagged());
3046  }
3047
3048  DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
3049};
3050
3051
3052class HValueOf: public HUnaryOperation {
3053 public:
3054  explicit HValueOf(HValue* value) : HUnaryOperation(value) {
3055    set_representation(Representation::Tagged());
3056  }
3057
3058  DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value_of")
3059};
3060
3061
3062class HDeleteProperty: public HBinaryOperation {
3063 public:
3064  HDeleteProperty(HValue* obj, HValue* key)
3065      : HBinaryOperation(obj, key) {
3066    set_representation(Representation::Tagged());
3067    SetFlagMask(AllSideEffects());
3068  }
3069
3070  virtual Representation RequiredInputRepresentation(int index) const {
3071    return Representation::Tagged();
3072  }
3073
3074  DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete_property")
3075
3076  HValue* object() const { return left(); }
3077  HValue* key() const { return right(); }
3078};
3079
3080#undef DECLARE_INSTRUCTION
3081#undef DECLARE_CONCRETE_INSTRUCTION
3082
3083} }  // namespace v8::internal
3084
3085#endif  // V8_HYDROGEN_INSTRUCTIONS_H_
3086