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