v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
hydrogen-instructions.h
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #ifndef V8_HYDROGEN_INSTRUCTIONS_H_
29 #define V8_HYDROGEN_INSTRUCTIONS_H_
30 
31 #include "v8.h"
32 
33 #include "allocation.h"
34 #include "code-stubs.h"
35 #include "data-flow.h"
36 #include "small-pointer-list.h"
37 #include "string-stream.h"
38 #include "v8conversions.h"
39 #include "v8utils.h"
40 #include "zone.h"
41 
42 namespace v8 {
43 namespace internal {
44 
45 // Forward declarations.
46 class HBasicBlock;
47 class HEnvironment;
48 class HInstruction;
49 class HLoopInformation;
50 class HValue;
51 class LInstruction;
52 class LChunkBuilder;
53 
54 
55 #define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V) \
56  V(BinaryOperation) \
57  V(BitwiseBinaryOperation) \
58  V(ControlInstruction) \
59  V(Instruction) \
60 
61 
62 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
63  V(AbnormalExit) \
64  V(AccessArgumentsAt) \
65  V(Add) \
66  V(AllocateObject) \
67  V(ApplyArguments) \
68  V(ArgumentsElements) \
69  V(ArgumentsLength) \
70  V(ArgumentsObject) \
71  V(ArrayLiteral) \
72  V(Bitwise) \
73  V(BitNot) \
74  V(BlockEntry) \
75  V(BoundsCheck) \
76  V(Branch) \
77  V(CallConstantFunction) \
78  V(CallFunction) \
79  V(CallGlobal) \
80  V(CallKeyed) \
81  V(CallKnownGlobal) \
82  V(CallNamed) \
83  V(CallNew) \
84  V(CallRuntime) \
85  V(CallStub) \
86  V(Change) \
87  V(CheckFunction) \
88  V(CheckInstanceType) \
89  V(CheckMaps) \
90  V(CheckNonSmi) \
91  V(CheckPrototypeMaps) \
92  V(CheckSmi) \
93  V(ClampToUint8) \
94  V(ClassOfTestAndBranch) \
95  V(CompareIDAndBranch) \
96  V(CompareGeneric) \
97  V(CompareObjectEqAndBranch) \
98  V(CompareMap) \
99  V(CompareConstantEqAndBranch) \
100  V(Constant) \
101  V(Context) \
102  V(DeclareGlobals) \
103  V(DeleteProperty) \
104  V(Deoptimize) \
105  V(Div) \
106  V(ElementsKind) \
107  V(EnterInlined) \
108  V(FastLiteral) \
109  V(FixedArrayBaseLength) \
110  V(ForceRepresentation) \
111  V(FunctionLiteral) \
112  V(GetCachedArrayIndex) \
113  V(GlobalObject) \
114  V(GlobalReceiver) \
115  V(Goto) \
116  V(HasCachedArrayIndexAndBranch) \
117  V(HasInstanceTypeAndBranch) \
118  V(In) \
119  V(InstanceOf) \
120  V(InstanceOfKnownGlobal) \
121  V(InvokeFunction) \
122  V(IsConstructCallAndBranch) \
123  V(IsNilAndBranch) \
124  V(IsObjectAndBranch) \
125  V(IsStringAndBranch) \
126  V(IsSmiAndBranch) \
127  V(IsUndetectableAndBranch) \
128  V(JSArrayLength) \
129  V(LeaveInlined) \
130  V(LoadContextSlot) \
131  V(LoadElements) \
132  V(LoadExternalArrayPointer) \
133  V(LoadFunctionPrototype) \
134  V(LoadGlobalCell) \
135  V(LoadGlobalGeneric) \
136  V(LoadKeyedFastDoubleElement) \
137  V(LoadKeyedFastElement) \
138  V(LoadKeyedGeneric) \
139  V(LoadKeyedSpecializedArrayElement) \
140  V(LoadNamedField) \
141  V(LoadNamedFieldPolymorphic) \
142  V(LoadNamedGeneric) \
143  V(MapEnumLength) \
144  V(MathFloorOfDiv) \
145  V(MathMinMax) \
146  V(Mod) \
147  V(Mul) \
148  V(ObjectLiteral) \
149  V(OsrEntry) \
150  V(OuterContext) \
151  V(Parameter) \
152  V(Power) \
153  V(PushArgument) \
154  V(Random) \
155  V(RegExpLiteral) \
156  V(Return) \
157  V(Sar) \
158  V(Shl) \
159  V(Shr) \
160  V(Simulate) \
161  V(SoftDeoptimize) \
162  V(StackCheck) \
163  V(StoreContextSlot) \
164  V(StoreGlobalCell) \
165  V(StoreGlobalGeneric) \
166  V(StoreKeyedFastDoubleElement) \
167  V(StoreKeyedFastElement) \
168  V(StoreKeyedGeneric) \
169  V(StoreKeyedSpecializedArrayElement) \
170  V(StoreNamedField) \
171  V(StoreNamedGeneric) \
172  V(StringAdd) \
173  V(StringCharCodeAt) \
174  V(StringCharFromCode) \
175  V(StringCompareAndBranch) \
176  V(StringLength) \
177  V(Sub) \
178  V(ThisFunction) \
179  V(Throw) \
180  V(ToFastProperties) \
181  V(TransitionElementsKind) \
182  V(Typeof) \
183  V(TypeofIsAndBranch) \
184  V(UnaryMathOperation) \
185  V(UnknownOSRValue) \
186  V(UseConst) \
187  V(ValueOf) \
188  V(ForInPrepareMap) \
189  V(ForInCacheArray) \
190  V(CheckMapValue) \
191  V(LoadFieldByIndex) \
192  V(DateField) \
193  V(WrapReceiver)
194 
195 #define GVN_TRACKED_FLAG_LIST(V) \
196  V(NewSpacePromotion)
197 
198 #define GVN_UNTRACKED_FLAG_LIST(V) \
199  V(Calls) \
200  V(InobjectFields) \
201  V(BackingStoreFields) \
202  V(ElementsKind) \
203  V(ElementsPointer) \
204  V(ArrayElements) \
205  V(DoubleArrayElements) \
206  V(SpecializedArrayElements) \
207  V(GlobalVars) \
208  V(Maps) \
209  V(ArrayLengths) \
210  V(ContextSlots) \
211  V(OsrEntries)
212 
213 #define DECLARE_ABSTRACT_INSTRUCTION(type) \
214  virtual bool Is##type() const { return true; } \
215  static H##type* cast(HValue* value) { \
216  ASSERT(value->Is##type()); \
217  return reinterpret_cast<H##type*>(value); \
218  }
219 
220 
221 #define DECLARE_CONCRETE_INSTRUCTION(type) \
222  virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
223  static H##type* cast(HValue* value) { \
224  ASSERT(value->Is##type()); \
225  return reinterpret_cast<H##type*>(value); \
226  } \
227  virtual Opcode opcode() const { return HValue::k##type; }
228 
229 
230 #ifdef DEBUG
231 #define ASSERT_ALLOCATION_DISABLED do { \
232  OptimizingCompilerThread* thread = \
233  ISOLATE->optimizing_compiler_thread(); \
234  ASSERT(thread->IsOptimizerThread() || !HEAP->IsAllocationAllowed()); \
235  } while (0)
236 #else
237 #define ASSERT_ALLOCATION_DISABLED do {} while (0)
238 #endif
239 
240 class Range: public ZoneObject {
241  public:
243  : lower_(kMinInt),
244  upper_(kMaxInt),
245  next_(NULL),
246  can_be_minus_zero_(false) { }
247 
249  : lower_(lower),
250  upper_(upper),
251  next_(NULL),
252  can_be_minus_zero_(false) { }
253 
254  int32_t upper() const { return upper_; }
255  int32_t lower() const { return lower_; }
256  Range* next() const { return next_; }
257  Range* CopyClearLower(Zone* zone) const {
258  return new(zone) Range(kMinInt, upper_);
259  }
260  Range* CopyClearUpper(Zone* zone) const {
261  return new(zone) Range(lower_, kMaxInt);
262  }
263  Range* Copy(Zone* zone) const {
264  Range* result = new(zone) Range(lower_, upper_);
266  return result;
267  }
268  int32_t Mask() const;
269  void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
270  bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
271  bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
272  bool CanBeNegative() const { return lower_ < 0; }
273  bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
274  bool IsMostGeneric() const {
275  return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
276  }
277  bool IsInSmiRange() const {
278  return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
279  }
280  void KeepOrder();
281 #ifdef DEBUG
282  void Verify() const;
283 #endif
284 
285  void StackUpon(Range* other) {
286  Intersect(other);
287  next_ = other;
288  }
289 
290  void Intersect(Range* other);
291  void Union(Range* other);
292  void CombinedMax(Range* other);
293  void CombinedMin(Range* other);
294 
295  void AddConstant(int32_t value);
296  void Sar(int32_t value);
297  void Shl(int32_t value);
298  bool AddAndCheckOverflow(Range* other);
299  bool SubAndCheckOverflow(Range* other);
300  bool MulAndCheckOverflow(Range* other);
301 
302  private:
303  int32_t lower_;
304  int32_t upper_;
305  Range* next_;
306  bool can_be_minus_zero_;
307 };
308 
309 
311  public:
312  enum Kind {
319  };
320 
321  Representation() : kind_(kNone) { }
322 
323  static Representation None() { return Representation(kNone); }
328 
329  bool Equals(const Representation& other) {
330  return kind_ == other.kind_;
331  }
332 
333  Kind kind() const { return static_cast<Kind>(kind_); }
334  bool IsNone() const { return kind_ == kNone; }
335  bool IsTagged() const { return kind_ == kTagged; }
336  bool IsInteger32() const { return kind_ == kInteger32; }
337  bool IsDouble() const { return kind_ == kDouble; }
338  bool IsExternal() const { return kind_ == kExternal; }
339  bool IsSpecialization() const {
340  return kind_ == kInteger32 || kind_ == kDouble;
341  }
342  const char* Mnemonic() const;
343 
344  private:
345  explicit Representation(Kind k) : kind_(k) { }
346 
347  // Make sure kind fits in int8.
348  STATIC_ASSERT(kNumRepresentations <= (1 << kBitsPerByte));
349 
350  int8_t kind_;
351 };
352 
353 
354 class HType {
355  public:
356  HType() : type_(kUninitialized) { }
357 
358  static HType Tagged() { return HType(kTagged); }
359  static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
360  static HType TaggedNumber() { return HType(kTaggedNumber); }
361  static HType Smi() { return HType(kSmi); }
362  static HType HeapNumber() { return HType(kHeapNumber); }
363  static HType String() { return HType(kString); }
364  static HType Boolean() { return HType(kBoolean); }
365  static HType NonPrimitive() { return HType(kNonPrimitive); }
366  static HType JSArray() { return HType(kJSArray); }
367  static HType JSObject() { return HType(kJSObject); }
368  static HType Uninitialized() { return HType(kUninitialized); }
369 
370  // Return the weakest (least precise) common type.
371  HType Combine(HType other) {
372  return HType(static_cast<Type>(type_ & other.type_));
373  }
374 
375  bool Equals(const HType& other) {
376  return type_ == other.type_;
377  }
378 
379  bool IsSubtypeOf(const HType& other) {
380  return Combine(other).Equals(other);
381  }
382 
383  bool IsTagged() {
384  ASSERT(type_ != kUninitialized);
385  return ((type_ & kTagged) == kTagged);
386  }
387 
389  ASSERT(type_ != kUninitialized);
390  return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
391  }
392 
393  bool IsTaggedNumber() {
394  ASSERT(type_ != kUninitialized);
395  return ((type_ & kTaggedNumber) == kTaggedNumber);
396  }
397 
398  bool IsSmi() {
399  ASSERT(type_ != kUninitialized);
400  return ((type_ & kSmi) == kSmi);
401  }
402 
403  bool IsHeapNumber() {
404  ASSERT(type_ != kUninitialized);
405  return ((type_ & kHeapNumber) == kHeapNumber);
406  }
407 
408  bool IsString() {
409  ASSERT(type_ != kUninitialized);
410  return ((type_ & kString) == kString);
411  }
412 
413  bool IsBoolean() {
414  ASSERT(type_ != kUninitialized);
415  return ((type_ & kBoolean) == kBoolean);
416  }
417 
418  bool IsNonPrimitive() {
419  ASSERT(type_ != kUninitialized);
420  return ((type_ & kNonPrimitive) == kNonPrimitive);
421  }
422 
423  bool IsJSArray() {
424  ASSERT(type_ != kUninitialized);
425  return ((type_ & kJSArray) == kJSArray);
426  }
427 
428  bool IsJSObject() {
429  ASSERT(type_ != kUninitialized);
430  return ((type_ & kJSObject) == kJSObject);
431  }
432 
434  return type_ == kUninitialized;
435  }
436 
437  bool IsHeapObject() {
438  ASSERT(type_ != kUninitialized);
439  return IsHeapNumber() || IsString() || IsNonPrimitive();
440  }
441 
442  static HType TypeFromValue(Handle<Object> value);
443 
444  const char* ToString();
445 
446  private:
447  enum Type {
448  kTagged = 0x1, // 0000 0000 0000 0001
449  kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
450  kTaggedNumber = 0xd, // 0000 0000 0000 1101
451  kSmi = 0x1d, // 0000 0000 0001 1101
452  kHeapNumber = 0x2d, // 0000 0000 0010 1101
453  kString = 0x45, // 0000 0000 0100 0101
454  kBoolean = 0x85, // 0000 0000 1000 0101
455  kNonPrimitive = 0x101, // 0000 0001 0000 0001
456  kJSObject = 0x301, // 0000 0011 0000 0001
457  kJSArray = 0x701, // 0000 0111 0000 0001
458  kUninitialized = 0x1fff // 0001 1111 1111 1111
459  };
460 
461  // Make sure type fits in int16.
462  STATIC_ASSERT(kUninitialized < (1 << (2 * kBitsPerByte)));
463 
464  explicit HType(Type t) : type_(t) { }
465 
466  int16_t type_;
467 };
468 
469 
470 class HUseListNode: public ZoneObject {
471  public:
473  : tail_(tail), value_(value), index_(index) {
474  }
475 
476  HUseListNode* tail();
477  HValue* value() const { return value_; }
478  int index() const { return index_; }
479 
480  void set_tail(HUseListNode* list) { tail_ = list; }
481 
482 #ifdef DEBUG
483  void Zap() {
484  tail_ = reinterpret_cast<HUseListNode*>(1);
485  value_ = NULL;
486  index_ = -1;
487  }
488 #endif
489 
490  private:
491  HUseListNode* tail_;
492  HValue* value_;
493  int index_;
494 };
495 
496 
497 // We reuse use list nodes behind the scenes as uses are added and deleted.
498 // This class is the safe way to iterate uses while deleting them.
499 class HUseIterator BASE_EMBEDDED {
500  public:
501  bool Done() { return current_ == NULL; }
502  void Advance();
503 
505  ASSERT(!Done());
506  return value_;
507  }
508 
509  int index() {
510  ASSERT(!Done());
511  return index_;
512  }
513 
514  private:
515  explicit HUseIterator(HUseListNode* head);
516 
518  HUseListNode* next_;
519  HValue* value_;
520  int index_;
521 
522  friend class HValue;
523 };
524 
525 
526 // There must be one corresponding kDepends flag for every kChanges flag and
527 // the order of the kChanges flags must be exactly the same as of the kDepends
528 // flags. All tracked flags should appear before untracked ones.
529 enum GVNFlag {
530  // Declare global value numbering flags.
531 #define DECLARE_FLAG(type) kChanges##type, kDependsOn##type,
534 #undef DECLARE_FLAG
537 #define COUNT_FLAG(type) + 1
539 #undef COUNT_FLAG
540 };
541 
543 
544 
545 class HValue: public ZoneObject {
546  public:
547  static const int kNoNumber = -1;
548 
549  enum Flag {
551  // Participate in Global Value Numbering, i.e. elimination of
552  // unnecessary recomputations. If an instruction sets this flag, it must
553  // implement DataEquals(), which will be used to determine if other
554  // occurrences of the instruction are indeed the same.
556  // Track instructions that are dominating side effects. If an instruction
557  // sets this flag, it must implement SetSideEffectDominator() and should
558  // indicate which side effects to track by setting GVN flags.
567  // Instructions that are allowed to produce full range unsigned integer
568  // values are marked with kUint32 flag. If arithmetic shift or a load from
569  // EXTERNAL_UNSIGNED_INT_ELEMENTS array is not marked with this flag
570  // it will deoptimize if result does not fit into signed integer range.
571  // HGraph::ComputeSafeUint32Operations is responsible for setting this
572  // flag.
575  };
576 
578 
579  static const int kChangesToDependsFlagsLeftShift = 1;
580 
581  static GVNFlag ChangesFlagFromInt(int x) {
582  return static_cast<GVNFlag>(x * 2);
583  }
585  return static_cast<GVNFlag>(x * 2 + 1);
586  }
589  }
590 
591  static HValue* cast(HValue* value) { return value; }
592 
593  enum Opcode {
594  // Declare a unique enum value for each hydrogen instruction.
595  #define DECLARE_OPCODE(type) k##type,
598  #undef DECLARE_OPCODE
599  };
600  virtual Opcode opcode() const = 0;
601 
602  // Declare a non-virtual predicates for each concrete HInstruction or HValue.
603  #define DECLARE_PREDICATE(type) \
604  bool Is##type() const { return opcode() == k##type; }
606  #undef DECLARE_PREDICATE
607  bool IsPhi() const { return opcode() == kPhi; }
608 
609  // Declare virtual predicates for abstract HInstruction or HValue
610  #define DECLARE_PREDICATE(type) \
611  virtual bool Is##type() const { return false; }
613  #undef DECLARE_PREDICATE
614 
616  id_(kNoNumber),
617  type_(HType::Tagged()),
618  use_list_(NULL),
619  range_(NULL),
620  flags_(0) {}
621  virtual ~HValue() {}
622 
623  HBasicBlock* block() const { return block_; }
624  void SetBlock(HBasicBlock* block);
625  int LoopWeight() const;
626 
627  int id() const { return id_; }
628  void set_id(int id) { id_ = id; }
629 
630  HUseIterator uses() const { return HUseIterator(use_list_); }
631 
632  virtual bool EmitAtUses() { return false; }
635  // Representation was already set and is allowed to be changed.
636  ASSERT(!r.IsNone());
639  representation_ = r;
640  }
642 
643  virtual bool IsConvertibleToInteger() const { return true; }
644 
645  HType type() const { return type_; }
646  void set_type(HType new_type) {
647  ASSERT(new_type.IsSubtypeOf(type_));
648  type_ = new_type;
649  }
650 
651  // An operation needs to override this function iff:
652  // 1) it can produce an int32 output.
653  // 2) the true value of its output can potentially be minus zero.
654  // The implementation must set a flag so that it bails out in the case where
655  // it would otherwise output what should be a minus zero as an int32 zero.
656  // If the operation also exists in a form that takes int32 and outputs int32
657  // then the operation should return its input value so that we can propagate
658  // back. There are three operations that need to propagate back to more than
659  // one input. They are phi and binary div and mul. They always return NULL
660  // and expect the caller to take care of things.
662  visited->Add(id());
663  return NULL;
664  }
665 
666  bool IsDefinedAfter(HBasicBlock* other) const;
667 
668  // Operands.
669  virtual int OperandCount() = 0;
670  virtual HValue* OperandAt(int index) const = 0;
671  void SetOperandAt(int index, HValue* value);
672 
673  void DeleteAndReplaceWith(HValue* other);
674  void ReplaceAllUsesWith(HValue* other);
675  bool HasNoUses() const { return use_list_ == NULL; }
676  bool HasMultipleUses() const {
677  return use_list_ != NULL && use_list_->tail() != NULL;
678  }
679  int UseCount() const;
680 
681  // Mark this HValue as dead and to be removed from other HValues' use lists.
682  void Kill();
683 
684  int flags() const { return flags_; }
685  void SetFlag(Flag f) { flags_ |= (1 << f); }
686  void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
687  bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
688 
689  // Returns true if the flag specified is set for all uses, false otherwise.
690  bool CheckUsesForFlag(Flag f);
691 
692  GVNFlagSet gvn_flags() const { return gvn_flags_; }
695  bool CheckGVNFlag(GVNFlag f) const { return gvn_flags_.Contains(f); }
699  }
700  bool HasSideEffects() const {
702  }
705  }
706 
708  GVNFlagSet result = gvn_flags_;
709  result.Intersect(AllDependsOnFlagSet());
710  return result;
711  }
712 
714  GVNFlagSet result = gvn_flags_;
716  return result;
717  }
718 
720  GVNFlagSet result = gvn_flags_;
721  result.Intersect(AllChangesFlagSet());
722  return result;
723  }
724 
726  GVNFlagSet result = gvn_flags_;
727  result.Intersect(AllChangesFlagSet());
729  return result;
730  }
731 
732  Range* range() const { return range_; }
733  bool HasRange() const { return range_ != NULL; }
734  void AddNewRange(Range* r, Zone* zone);
735  void RemoveLastAddedRange();
736  void ComputeInitialRange(Zone* zone);
737 
738  // Representation helpers.
739  virtual Representation RequiredInputRepresentation(int index) = 0;
740 
742  return representation();
743  }
744 
745  // Type feedback access.
747  return RequiredInputRepresentation(index);
748  }
749 
750  // This gives the instruction an opportunity to replace itself with an
751  // instruction that does the same in some better way. To replace an
752  // instruction with a new one, first add the new instruction to the graph,
753  // then return it. Return NULL to have the instruction deleted.
754  virtual HValue* Canonicalize() { return this; }
755 
756  bool Equals(HValue* other);
757  virtual intptr_t Hashcode();
758 
759  // Printing support.
760  virtual void PrintTo(StringStream* stream) = 0;
761  void PrintNameTo(StringStream* stream);
762  void PrintTypeTo(StringStream* stream);
763  void PrintRangeTo(StringStream* stream);
764  void PrintChangesTo(StringStream* stream);
765 
766  const char* Mnemonic() const;
767 
768  // Updated the inferred type of this instruction and returns true if
769  // it has changed.
770  bool UpdateInferredType();
771 
772  virtual HType CalculateInferredType();
773 
774  // This function must be overridden for instructions which have the
775  // kTrackSideEffectDominators flag set, to track instructions that are
776  // dominating side effects.
777  virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) {
778  UNREACHABLE();
779  }
780 
781  bool IsDead() const {
782  return HasNoUses() && !HasObservableSideEffects() && IsDeletable();
783  }
784 
785 #ifdef DEBUG
786  virtual void Verify() = 0;
787 #endif
788 
789  protected:
790  // This function must be overridden for instructions with flag kUseGVN, to
791  // compare the non-Operand parts of the instruction.
792  virtual bool DataEquals(HValue* other) {
793  UNREACHABLE();
794  return false;
795  }
797  virtual Range* InferRange(Zone* zone);
798  virtual void DeleteFromGraph() = 0;
799  virtual void InternalSetOperandAt(int index, HValue* value) = 0;
800  void clear_block() {
801  ASSERT(block_ != NULL);
802  block_ = NULL;
803  }
804 
806  // Representation is set-once.
807  ASSERT(representation_.IsNone() && !r.IsNone());
808  representation_ = r;
809  }
810 
812  GVNFlagSet result;
813  // Create changes mask.
814 #define ADD_FLAG(type) result.Add(kDependsOn##type);
817 #undef ADD_FLAG
818  return result;
819  }
820 
822  GVNFlagSet result;
823  // Create changes mask.
824 #define ADD_FLAG(type) result.Add(kChanges##type);
827 #undef ADD_FLAG
828  return result;
829  }
830 
831  // A flag mask to mark an instruction as having arbitrary side effects.
833  GVNFlagSet result = AllChangesFlagSet();
834  result.Remove(kChangesOsrEntries);
835  return result;
836  }
837 
838  // A flag mask of all side effects that can make observable changes in
839  // an executing program (i.e. are not safe to repeat, move or remove);
841  GVNFlagSet result = AllChangesFlagSet();
842  result.Remove(kChangesNewSpacePromotion);
843  result.Remove(kChangesElementsKind);
844  result.Remove(kChangesElementsPointer);
845  result.Remove(kChangesMaps);
846  return result;
847  }
848 
849  // Remove the matching use from the use list if present. Returns the
850  // removed list node or NULL.
851  HUseListNode* RemoveUse(HValue* value, int index);
852 
853  void RegisterUse(int index, HValue* new_value);
854 
856 
857  // The id of this instruction in the hydrogen graph, assigned when first
858  // added to the graph. Reflects creation order.
859  int id_;
860 
865  int flags_;
867 
868  private:
869  virtual bool IsDeletable() const { return false; }
870 
871  DISALLOW_COPY_AND_ASSIGN(HValue);
872 };
873 
874 
875 class HInstruction: public HValue {
876  public:
877  HInstruction* next() const { return next_; }
878  HInstruction* previous() const { return previous_; }
879 
880  virtual void PrintTo(StringStream* stream);
881  virtual void PrintDataTo(StringStream* stream) { }
882 
883  bool IsLinked() const { return block() != NULL; }
884  void Unlink();
887 
888  // The position is a write-once variable.
889  int position() const { return position_; }
890  bool has_position() const { return position_ != RelocInfo::kNoPosition; }
891  void set_position(int position) {
892  ASSERT(!has_position());
893  ASSERT(position != RelocInfo::kNoPosition);
894  position_ = position;
895  }
896 
898 
899  virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
900 
901 #ifdef DEBUG
902  virtual void Verify();
903 #endif
904 
905  virtual bool IsCall() { return false; }
906 
908 
909  protected:
911  : next_(NULL),
912  previous_(NULL),
913  position_(RelocInfo::kNoPosition) {
914  SetGVNFlag(kDependsOnOsrEntries);
915  }
916 
917  virtual void DeleteFromGraph() { Unlink(); }
918 
919  private:
920  void InitializeAsFirst(HBasicBlock* block) {
921  ASSERT(!IsLinked());
922  SetBlock(block);
923  }
924 
925  void PrintMnemonicTo(StringStream* stream);
926 
927  HInstruction* next_;
928  HInstruction* previous_;
929  int position_;
930 
931  friend class HBasicBlock;
932 };
933 
934 
935 template<int V>
937  public:
938  int OperandCount() { return V; }
939  HValue* OperandAt(int i) const { return inputs_[i]; }
940 
941  protected:
942  void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
943 
944  private:
946 };
947 
948 
950  public:
951  virtual HBasicBlock* SuccessorAt(int i) = 0;
952  virtual int SuccessorCount() = 0;
953  virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
954 
955  virtual void PrintDataTo(StringStream* stream);
956 
958  return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
959  }
961  return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
962  }
963 
964  DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
965 };
966 
967 
968 class HSuccessorIterator BASE_EMBEDDED {
969  public:
971  : instr_(instr), current_(0) { }
972 
973  bool Done() { return current_ >= instr_->SuccessorCount(); }
974  HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
975  void Advance() { current_++; }
976 
977  private:
978  HControlInstruction* instr_;
979  int current_;
980 };
981 
982 
983 template<int S, int V>
985  public:
986  int SuccessorCount() { return S; }
987  HBasicBlock* SuccessorAt(int i) { return successors_[i]; }
988  void SetSuccessorAt(int i, HBasicBlock* block) { successors_[i] = block; }
989 
990  int OperandCount() { return V; }
991  HValue* OperandAt(int i) const { return inputs_[i]; }
992 
993 
994  protected:
995  void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
996 
997  private:
1000 };
1001 
1002 
1004  public:
1006  return Representation::None();
1007  }
1008 
1009  DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
1010 };
1011 
1012 
1013 // We insert soft-deoptimize when we hit code with unknown typefeedback,
1014 // so that we get a chance of re-optimizing with useful typefeedback.
1015 // HSoftDeoptimize does not end a basic block as opposed to HDeoptimize.
1017  public:
1019  return Representation::None();
1020  }
1021 
1022  DECLARE_CONCRETE_INSTRUCTION(SoftDeoptimize)
1023 };
1024 
1025 
1027  public:
1028  HDeoptimize(int environment_length, Zone* zone)
1029  : values_(environment_length, zone) { }
1030 
1032  return Representation::None();
1033  }
1034 
1035  virtual int OperandCount() { return values_.length(); }
1036  virtual HValue* OperandAt(int index) const { return values_[index]; }
1037  virtual void PrintDataTo(StringStream* stream);
1038 
1039  virtual int SuccessorCount() { return 0; }
1040  virtual HBasicBlock* SuccessorAt(int i) {
1041  UNREACHABLE();
1042  return NULL;
1043  }
1044  virtual void SetSuccessorAt(int i, HBasicBlock* block) {
1045  UNREACHABLE();
1046  }
1047 
1048  void AddEnvironmentValue(HValue* value, Zone* zone) {
1049  values_.Add(NULL, zone);
1050  SetOperandAt(values_.length() - 1, value);
1051  }
1052 
1053  DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
1054 
1058  };
1059 
1060  protected:
1061  virtual void InternalSetOperandAt(int index, HValue* value) {
1062  values_[index] = value;
1063  }
1064 
1065  private:
1066  ZoneList<HValue*> values_;
1067 };
1068 
1069 
1070 class HGoto: public HTemplateControlInstruction<1, 0> {
1071  public:
1072  explicit HGoto(HBasicBlock* target) {
1073  SetSuccessorAt(0, target);
1074  }
1075 
1077  return Representation::None();
1078  }
1079 
1080  virtual void PrintDataTo(StringStream* stream);
1081 
1083 };
1084 
1085 
1087  public:
1089  HBasicBlock* true_target,
1090  HBasicBlock* false_target) {
1091  SetOperandAt(0, value);
1092  SetSuccessorAt(0, true_target);
1093  SetSuccessorAt(1, false_target);
1094  }
1095 
1096  virtual void PrintDataTo(StringStream* stream);
1097 
1098  HValue* value() { return OperandAt(0); }
1099 };
1100 
1101 
1103  public:
1105  HBasicBlock* true_target,
1106  HBasicBlock* false_target,
1108  : HUnaryControlInstruction(value, true_target, false_target),
1109  expected_input_types_(expected_input_types) {
1110  ASSERT(true_target != NULL && false_target != NULL);
1111  }
1112  explicit HBranch(HValue* value)
1113  : HUnaryControlInstruction(value, NULL, NULL) { }
1114 
1115 
1117  return Representation::None();
1118  }
1119 
1121  return expected_input_types_;
1122  }
1123 
1125 
1126  private:
1127  ToBooleanStub::Types expected_input_types_;
1128 };
1129 
1130 
1132  public:
1134  Handle<Map> map,
1135  HBasicBlock* true_target,
1136  HBasicBlock* false_target)
1137  : HUnaryControlInstruction(value, true_target, false_target),
1138  map_(map) {
1139  ASSERT(true_target != NULL);
1140  ASSERT(false_target != NULL);
1141  ASSERT(!map.is_null());
1142  }
1143 
1144  virtual void PrintDataTo(StringStream* stream);
1145 
1146  Handle<Map> map() const { return map_; }
1147 
1149  return Representation::Tagged();
1150  }
1151 
1152  DECLARE_CONCRETE_INSTRUCTION(CompareMap)
1153 
1154  private:
1155  Handle<Map> map_;
1156 };
1157 
1158 
1160  public:
1161  explicit HReturn(HValue* value) {
1162  SetOperandAt(0, value);
1163  }
1164 
1166  return Representation::Tagged();
1167  }
1168 
1169  virtual void PrintDataTo(StringStream* stream);
1170 
1171  HValue* value() { return OperandAt(0); }
1172 
1174 };
1175 
1176 
1178  public:
1180  return Representation::None();
1181  }
1182 
1183  DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
1184 };
1185 
1186 
1188  public:
1189  explicit HUnaryOperation(HValue* value) {
1190  SetOperandAt(0, value);
1191  }
1192 
1193  static HUnaryOperation* cast(HValue* value) {
1194  return reinterpret_cast<HUnaryOperation*>(value);
1195  }
1196 
1197  HValue* value() const { return OperandAt(0); }
1198  virtual void PrintDataTo(StringStream* stream);
1199 };
1200 
1201 
1202 class HThrow: public HTemplateInstruction<2> {
1203  public:
1204  HThrow(HValue* context, HValue* value) {
1205  SetOperandAt(0, context);
1206  SetOperandAt(1, value);
1208  }
1209 
1211  return Representation::Tagged();
1212  }
1213 
1214  HValue* context() { return OperandAt(0); }
1215  HValue* value() { return OperandAt(1); }
1216 
1218 };
1219 
1220 
1222  public:
1223  explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
1224 
1226  return Representation::None();
1227  }
1228 
1230 };
1231 
1232 
1234  public:
1235  HForceRepresentation(HValue* value, Representation required_representation) {
1236  SetOperandAt(0, value);
1237  set_representation(required_representation);
1238  }
1239 
1240  HValue* value() { return OperandAt(0); }
1241 
1242  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1243 
1245  return representation(); // Same as the output representation.
1246  }
1247 
1248  DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
1249 };
1250 
1251 
1252 class HChange: public HUnaryOperation {
1253  public:
1254  HChange(HValue* value,
1255  Representation to,
1256  bool is_truncating,
1257  bool deoptimize_on_undefined)
1258  : HUnaryOperation(value) {
1259  ASSERT(!value->representation().IsNone() && !to.IsNone());
1260  ASSERT(!value->representation().Equals(to));
1261  set_representation(to);
1263  SetFlag(kUseGVN);
1264  if (deoptimize_on_undefined) SetFlag(kDeoptimizeOnUndefined);
1265  if (is_truncating) SetFlag(kTruncatingToInt32);
1266  if (to.IsTagged()) SetGVNFlag(kChangesNewSpacePromotion);
1267  }
1268 
1269  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1270  virtual HType CalculateInferredType();
1271  virtual HValue* Canonicalize();
1272 
1273  Representation from() const { return value()->representation(); }
1274  Representation to() const { return representation(); }
1277  }
1280  }
1282  return from();
1283  }
1284 
1285  virtual Range* InferRange(Zone* zone);
1286 
1287  virtual void PrintDataTo(StringStream* stream);
1288 
1290 
1291  protected:
1292  virtual bool DataEquals(HValue* other) { return true; }
1293 
1294  private:
1295  virtual bool IsDeletable() const {
1296  return !from().IsTagged() || value()->type().IsSmi();
1297  }
1298 };
1299 
1300 
1302  public:
1303  explicit HClampToUint8(HValue* value)
1304  : HUnaryOperation(value) {
1306  SetFlag(kUseGVN);
1307  }
1308 
1310  return Representation::None();
1311  }
1312 
1313  DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
1314 
1315  protected:
1316  virtual bool DataEquals(HValue* other) { return true; }
1317 
1318  private:
1319  virtual bool IsDeletable() const { return true; }
1320 };
1321 
1322 
1323 class HSimulate: public HInstruction {
1324  public:
1325  HSimulate(BailoutId ast_id, int pop_count, Zone* zone)
1326  : ast_id_(ast_id),
1327  pop_count_(pop_count),
1328  values_(2, zone),
1329  assigned_indexes_(2, zone),
1330  zone_(zone) {}
1331  virtual ~HSimulate() {}
1332 
1333  virtual void PrintDataTo(StringStream* stream);
1334 
1335  bool HasAstId() const { return !ast_id_.IsNone(); }
1336  BailoutId ast_id() const { return ast_id_; }
1338  ASSERT(!HasAstId());
1339  ast_id_ = id;
1340  }
1341 
1342  int pop_count() const { return pop_count_; }
1343  const ZoneList<HValue*>* values() const { return &values_; }
1344  int GetAssignedIndexAt(int index) const {
1345  ASSERT(HasAssignedIndexAt(index));
1346  return assigned_indexes_[index];
1347  }
1348  bool HasAssignedIndexAt(int index) const {
1349  return assigned_indexes_[index] != kNoIndex;
1350  }
1351  void AddAssignedValue(int index, HValue* value) {
1352  AddValue(index, value);
1353  }
1354  void AddPushedValue(HValue* value) {
1355  AddValue(kNoIndex, value);
1356  }
1357  virtual int OperandCount() { return values_.length(); }
1358  virtual HValue* OperandAt(int index) const { return values_[index]; }
1359 
1361  return Representation::None();
1362  }
1363 
1365 
1366 #ifdef DEBUG
1367  virtual void Verify();
1368 #endif
1369 
1370  protected:
1371  virtual void InternalSetOperandAt(int index, HValue* value) {
1372  values_[index] = value;
1373  }
1374 
1375  private:
1376  static const int kNoIndex = -1;
1377  void AddValue(int index, HValue* value) {
1378  assigned_indexes_.Add(index, zone_);
1379  // Resize the list of pushed values.
1380  values_.Add(NULL, zone_);
1381  // Set the operand through the base method in HValue to make sure that the
1382  // use lists are correctly updated.
1383  SetOperandAt(values_.length() - 1, value);
1384  }
1385  BailoutId ast_id_;
1386  int pop_count_;
1387  ZoneList<HValue*> values_;
1388  ZoneList<int> assigned_indexes_;
1389  Zone* zone_;
1390 };
1391 
1392 
1394  public:
1395  enum Type {
1397  kBackwardsBranch
1398  };
1399 
1400  HStackCheck(HValue* context, Type type) : type_(type) {
1401  SetOperandAt(0, context);
1402  SetGVNFlag(kChangesNewSpacePromotion);
1403  }
1404 
1405  HValue* context() { return OperandAt(0); }
1406 
1408  return Representation::Tagged();
1409  }
1410 
1411  void Eliminate() {
1412  // The stack check eliminator might try to eliminate the same stack
1413  // check instruction multiple times.
1414  if (IsLinked()) {
1415  DeleteFromGraph();
1416  }
1417  }
1418 
1419  bool is_function_entry() { return type_ == kFunctionEntry; }
1420  bool is_backwards_branch() { return type_ == kBackwardsBranch; }
1421 
1422  DECLARE_CONCRETE_INSTRUCTION(StackCheck)
1423 
1424  private:
1425  Type type_;
1426 };
1427 
1428 
1430  NORMAL_RETURN, // Normal function/method call and return.
1431  DROP_EXTRA_ON_RETURN, // Drop an extra value from the environment on return.
1432  CONSTRUCT_CALL_RETURN, // Either use allocated receiver or return value.
1433  GETTER_CALL_RETURN, // Returning from a getter, need to restore context.
1434  SETTER_CALL_RETURN // Use the RHS of the assignment as the return value.
1435 };
1436 
1437 
1439  public:
1441  int arguments_count,
1442  FunctionLiteral* function,
1443  CallKind call_kind,
1444  InliningKind inlining_kind,
1445  Variable* arguments_var,
1446  ZoneList<HValue*>* arguments_values)
1447  : closure_(closure),
1448  arguments_count_(arguments_count),
1449  arguments_pushed_(false),
1450  function_(function),
1451  call_kind_(call_kind),
1452  inlining_kind_(inlining_kind),
1453  arguments_var_(arguments_var),
1454  arguments_values_(arguments_values) {
1455  }
1456 
1457  virtual void PrintDataTo(StringStream* stream);
1458 
1459  Handle<JSFunction> closure() const { return closure_; }
1460  int arguments_count() const { return arguments_count_; }
1461  bool arguments_pushed() const { return arguments_pushed_; }
1462  void set_arguments_pushed() { arguments_pushed_ = true; }
1463  FunctionLiteral* function() const { return function_; }
1464  CallKind call_kind() const { return call_kind_; }
1465  InliningKind inlining_kind() const { return inlining_kind_; }
1466 
1468  return Representation::None();
1469  }
1470 
1471  Variable* arguments_var() { return arguments_var_; }
1472  ZoneList<HValue*>* arguments_values() { return arguments_values_; }
1473 
1474  DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
1475 
1476  private:
1477  Handle<JSFunction> closure_;
1478  int arguments_count_;
1479  bool arguments_pushed_;
1480  FunctionLiteral* function_;
1481  CallKind call_kind_;
1482  InliningKind inlining_kind_;
1483  Variable* arguments_var_;
1484  ZoneList<HValue*>* arguments_values_;
1485 };
1486 
1487 
1489  public:
1491 
1493  return Representation::None();
1494  }
1495 
1496  DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
1497 };
1498 
1499 
1501  public:
1502  explicit HPushArgument(HValue* value) : HUnaryOperation(value) {
1504  }
1505 
1507  return Representation::Tagged();
1508  }
1509 
1510  HValue* argument() { return OperandAt(0); }
1511 
1512  DECLARE_CONCRETE_INSTRUCTION(PushArgument)
1513 };
1514 
1515 
1517  public:
1520  SetFlag(kUseGVN);
1521  }
1522 
1524  return Representation::None();
1525  }
1526 
1528 
1529  protected:
1530  virtual bool DataEquals(HValue* other) { return true; }
1531 
1532  private:
1533  virtual bool IsDeletable() const { return true; }
1534 };
1535 
1536 
1537 class HContext: public HTemplateInstruction<0> {
1538  public:
1541  SetFlag(kUseGVN);
1542  }
1543 
1545  return Representation::None();
1546  }
1547 
1549 
1550  protected:
1551  virtual bool DataEquals(HValue* other) { return true; }
1552 
1553  private:
1554  virtual bool IsDeletable() const { return true; }
1555 };
1556 
1557 
1559  public:
1560  explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
1562  SetFlag(kUseGVN);
1563  }
1564 
1565  DECLARE_CONCRETE_INSTRUCTION(OuterContext);
1566 
1568  return Representation::Tagged();
1569  }
1570 
1571  protected:
1572  virtual bool DataEquals(HValue* other) { return true; }
1573 
1574  private:
1575  virtual bool IsDeletable() const { return true; }
1576 };
1577 
1578 
1580  public:
1583  int flags)
1584  : HUnaryOperation(context),
1585  pairs_(pairs),
1586  flags_(flags) {
1589  }
1590 
1591  HValue* context() { return OperandAt(0); }
1592  Handle<FixedArray> pairs() const { return pairs_; }
1593  int flags() const { return flags_; }
1594 
1595  DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
1596 
1598  return Representation::Tagged();
1599  }
1600  private:
1601  Handle<FixedArray> pairs_;
1602  int flags_;
1603 };
1604 
1605 
1607  public:
1608  explicit HGlobalObject(HValue* context) : HUnaryOperation(context) {
1610  SetFlag(kUseGVN);
1611  }
1612 
1614 
1616  return Representation::Tagged();
1617  }
1618 
1619  protected:
1620  virtual bool DataEquals(HValue* other) { return true; }
1621 
1622  private:
1623  virtual bool IsDeletable() const { return true; }
1624 };
1625 
1626 
1628  public:
1629  explicit HGlobalReceiver(HValue* global_object)
1630  : HUnaryOperation(global_object) {
1632  SetFlag(kUseGVN);
1633  }
1634 
1635  DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver)
1636 
1638  return Representation::Tagged();
1639  }
1640 
1641  protected:
1642  virtual bool DataEquals(HValue* other) { return true; }
1643 
1644  private:
1645  virtual bool IsDeletable() const { return true; }
1646 };
1647 
1648 
1649 template <int V>
1650 class HCall: public HTemplateInstruction<V> {
1651  public:
1652  // The argument count includes the receiver.
1653  explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
1655  this->SetAllSideEffects();
1656  }
1657 
1659 
1660  virtual int argument_count() const { return argument_count_; }
1661 
1662  virtual bool IsCall() { return true; }
1663 
1664  private:
1665  int argument_count_;
1666 };
1667 
1668 
1669 class HUnaryCall: public HCall<1> {
1670  public:
1671  HUnaryCall(HValue* value, int argument_count)
1672  : HCall<1>(argument_count) {
1673  SetOperandAt(0, value);
1674  }
1675 
1677  return Representation::Tagged();
1678  }
1679 
1680  virtual void PrintDataTo(StringStream* stream);
1681 
1682  HValue* value() { return OperandAt(0); }
1683 };
1684 
1685 
1686 class HBinaryCall: public HCall<2> {
1687  public:
1688  HBinaryCall(HValue* first, HValue* second, int argument_count)
1689  : HCall<2>(argument_count) {
1690  SetOperandAt(0, first);
1691  SetOperandAt(1, second);
1692  }
1693 
1694  virtual void PrintDataTo(StringStream* stream);
1695 
1697  return Representation::Tagged();
1698  }
1699 
1700  HValue* first() { return OperandAt(0); }
1701  HValue* second() { return OperandAt(1); }
1702 };
1703 
1704 
1706  public:
1707  HInvokeFunction(HValue* context, HValue* function, int argument_count)
1708  : HBinaryCall(context, function, argument_count) {
1709  }
1710 
1712  HValue* function,
1713  Handle<JSFunction> known_function,
1714  int argument_count)
1715  : HBinaryCall(context, function, argument_count),
1716  known_function_(known_function) {
1717  }
1718 
1720  return Representation::Tagged();
1721  }
1722 
1723  HValue* context() { return first(); }
1724  HValue* function() { return second(); }
1725  Handle<JSFunction> known_function() { return known_function_; }
1726 
1727  DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
1728 
1729  private:
1730  Handle<JSFunction> known_function_;
1731 };
1732 
1733 
1734 class HCallConstantFunction: public HCall<0> {
1735  public:
1736  HCallConstantFunction(Handle<JSFunction> function, int argument_count)
1737  : HCall<0>(argument_count), function_(function) { }
1738 
1739  Handle<JSFunction> function() const { return function_; }
1740 
1741  bool IsApplyFunction() const {
1742  return function_->code() ==
1743  Isolate::Current()->builtins()->builtin(Builtins::kFunctionApply);
1744  }
1745 
1746  virtual void PrintDataTo(StringStream* stream);
1747 
1749  return Representation::None();
1750  }
1751 
1752  DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction)
1753 
1754  private:
1755  Handle<JSFunction> function_;
1756 };
1757 
1758 
1759 class HCallKeyed: public HBinaryCall {
1760  public:
1761  HCallKeyed(HValue* context, HValue* key, int argument_count)
1762  : HBinaryCall(context, key, argument_count) {
1763  }
1764 
1766  return Representation::Tagged();
1767  }
1768 
1769  HValue* context() { return first(); }
1770  HValue* key() { return second(); }
1771 
1772  DECLARE_CONCRETE_INSTRUCTION(CallKeyed)
1773 };
1774 
1775 
1776 class HCallNamed: public HUnaryCall {
1777  public:
1778  HCallNamed(HValue* context, Handle<String> name, int argument_count)
1779  : HUnaryCall(context, argument_count), name_(name) {
1780  }
1781 
1782  virtual void PrintDataTo(StringStream* stream);
1783 
1784  HValue* context() { return value(); }
1785  Handle<String> name() const { return name_; }
1786 
1787  DECLARE_CONCRETE_INSTRUCTION(CallNamed)
1788 
1790  return Representation::Tagged();
1791  }
1792 
1793  private:
1794  Handle<String> name_;
1795 };
1796 
1797 
1799  public:
1800  HCallFunction(HValue* context, HValue* function, int argument_count)
1801  : HBinaryCall(context, function, argument_count) {
1802  }
1803 
1804  HValue* context() { return first(); }
1805  HValue* function() { return second(); }
1806 
1808  return Representation::Tagged();
1809  }
1810 
1811  DECLARE_CONCRETE_INSTRUCTION(CallFunction)
1812 };
1813 
1814 
1815 class HCallGlobal: public HUnaryCall {
1816  public:
1817  HCallGlobal(HValue* context, Handle<String> name, int argument_count)
1818  : HUnaryCall(context, argument_count), name_(name) {
1819  }
1820 
1821  virtual void PrintDataTo(StringStream* stream);
1822 
1823  HValue* context() { return value(); }
1824  Handle<String> name() const { return name_; }
1825 
1827  return Representation::Tagged();
1828  }
1829 
1830  DECLARE_CONCRETE_INSTRUCTION(CallGlobal)
1831 
1832  private:
1833  Handle<String> name_;
1834 };
1835 
1836 
1837 class HCallKnownGlobal: public HCall<0> {
1838  public:
1839  HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
1840  : HCall<0>(argument_count), target_(target) { }
1841 
1842  virtual void PrintDataTo(StringStream* stream);
1843 
1844  Handle<JSFunction> target() const { return target_; }
1845 
1847  return Representation::None();
1848  }
1849 
1850  DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal)
1851 
1852  private:
1853  Handle<JSFunction> target_;
1854 };
1855 
1856 
1857 class HCallNew: public HBinaryCall {
1858  public:
1859  HCallNew(HValue* context, HValue* constructor, int argument_count)
1860  : HBinaryCall(context, constructor, argument_count) {
1861  }
1862 
1864  return Representation::Tagged();
1865  }
1866 
1867  HValue* context() { return first(); }
1868  HValue* constructor() { return second(); }
1869 
1871 };
1872 
1873 
1874 class HCallRuntime: public HCall<1> {
1875  public:
1877  Handle<String> name,
1878  const Runtime::Function* c_function,
1879  int argument_count)
1880  : HCall<1>(argument_count), c_function_(c_function), name_(name) {
1881  SetOperandAt(0, context);
1882  }
1883 
1884  virtual void PrintDataTo(StringStream* stream);
1885 
1886  HValue* context() { return OperandAt(0); }
1887  const Runtime::Function* function() const { return c_function_; }
1888  Handle<String> name() const { return name_; }
1889 
1891  return Representation::Tagged();
1892  }
1893 
1895 
1896  private:
1897  const Runtime::Function* c_function_;
1898  Handle<String> name_;
1899 };
1900 
1901 
1903  public:
1904  HJSArrayLength(HValue* value, HValue* typecheck,
1905  HType type = HType::Tagged()) {
1906  set_type(type);
1907  // The length of an array is stored as a tagged value in the array
1908  // object. It is guaranteed to be 32 bit integer, but it can be
1909  // represented as either a smi or heap number.
1910  SetOperandAt(0, value);
1911  SetOperandAt(1, typecheck);
1913  SetFlag(kUseGVN);
1914  SetGVNFlag(kDependsOnArrayLengths);
1915  SetGVNFlag(kDependsOnMaps);
1916  }
1917 
1919  return Representation::Tagged();
1920  }
1921 
1922  virtual void PrintDataTo(StringStream* stream);
1923 
1924  HValue* value() { return OperandAt(0); }
1925  HValue* typecheck() { return OperandAt(1); }
1926 
1927  DECLARE_CONCRETE_INSTRUCTION(JSArrayLength)
1928 
1929  protected:
1930  virtual bool DataEquals(HValue* other_raw) { return true; }
1931 
1932  private:
1933  virtual bool IsDeletable() const { return true; }
1934 };
1935 
1936 
1938  public:
1939  explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) {
1940  set_type(HType::Smi());
1942  SetFlag(kUseGVN);
1943  SetGVNFlag(kDependsOnArrayLengths);
1944  }
1945 
1947  return Representation::Tagged();
1948  }
1949 
1950  DECLARE_CONCRETE_INSTRUCTION(FixedArrayBaseLength)
1951 
1952  protected:
1953  virtual bool DataEquals(HValue* other) { return true; }
1954 
1955  private:
1956  virtual bool IsDeletable() const { return true; }
1957 };
1958 
1959 
1961  public:
1962  explicit HMapEnumLength(HValue* value) : HUnaryOperation(value) {
1963  set_type(HType::Smi());
1965  SetFlag(kUseGVN);
1966  SetGVNFlag(kDependsOnMaps);
1967  }
1968 
1970  return Representation::Tagged();
1971  }
1972 
1973  DECLARE_CONCRETE_INSTRUCTION(MapEnumLength)
1974 
1975  protected:
1976  virtual bool DataEquals(HValue* other) { return true; }
1977 
1978  private:
1979  virtual bool IsDeletable() const { return true; }
1980 };
1981 
1982 
1984  public:
1985  explicit HElementsKind(HValue* value) : HUnaryOperation(value) {
1987  SetFlag(kUseGVN);
1988  SetGVNFlag(kDependsOnElementsKind);
1989  }
1990 
1992  return Representation::Tagged();
1993  }
1994 
1996 
1997  protected:
1998  virtual bool DataEquals(HValue* other) { return true; }
1999 
2000  private:
2001  virtual bool IsDeletable() const { return true; }
2002 };
2003 
2004 
2005 class HBitNot: public HUnaryOperation {
2006  public:
2007  explicit HBitNot(HValue* value) : HUnaryOperation(value) {
2009  SetFlag(kUseGVN);
2011  }
2012 
2014  return Representation::Integer32();
2015  }
2016  virtual HType CalculateInferredType();
2017 
2018  virtual HValue* Canonicalize();
2019 
2021 
2022  protected:
2023  virtual bool DataEquals(HValue* other) { return true; }
2024 
2025  private:
2026  virtual bool IsDeletable() const { return true; }
2027 };
2028 
2029 
2030 class HUnaryMathOperation: public HTemplateInstruction<2> {
2031  public:
2033  : op_(op) {
2034  SetOperandAt(0, context);
2035  SetOperandAt(1, value);
2036  switch (op) {
2037  case kMathFloor:
2038  case kMathRound:
2039  case kMathCeil:
2041  break;
2042  case kMathAbs:
2045  SetGVNFlag(kChangesNewSpacePromotion);
2046  break;
2047  case kMathSqrt:
2048  case kMathPowHalf:
2049  case kMathLog:
2050  case kMathSin:
2051  case kMathCos:
2052  case kMathTan:
2054  SetGVNFlag(kChangesNewSpacePromotion);
2055  break;
2056  default:
2057  UNREACHABLE();
2058  }
2059  SetFlag(kUseGVN);
2060  }
2061 
2062  HValue* context() { return OperandAt(0); }
2063  HValue* value() { return OperandAt(1); }
2064 
2065  virtual void PrintDataTo(StringStream* stream);
2066 
2067  virtual HType CalculateInferredType();
2068 
2069  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2070 
2072  if (index == 0) {
2073  return Representation::Tagged();
2074  } else {
2075  switch (op_) {
2076  case kMathFloor:
2077  case kMathRound:
2078  case kMathCeil:
2079  case kMathSqrt:
2080  case kMathPowHalf:
2081  case kMathLog:
2082  case kMathSin:
2083  case kMathCos:
2084  case kMathTan:
2085  return Representation::Double();
2086  case kMathAbs:
2087  return representation();
2088  default:
2089  UNREACHABLE();
2090  return Representation::None();
2091  }
2092  }
2093  }
2094 
2095  virtual HValue* Canonicalize();
2096 
2097  BuiltinFunctionId op() const { return op_; }
2098  const char* OpName() const;
2099 
2100  DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
2101 
2102  protected:
2103  virtual bool DataEquals(HValue* other) {
2105  return op_ == b->op();
2106  }
2107 
2108  private:
2109  virtual bool IsDeletable() const { return true; }
2110 
2111  BuiltinFunctionId op_;
2112 };
2113 
2114 
2115 class HLoadElements: public HTemplateInstruction<2> {
2116  public:
2117  HLoadElements(HValue* value, HValue* typecheck) {
2118  SetOperandAt(0, value);
2119  SetOperandAt(1, typecheck);
2121  SetFlag(kUseGVN);
2122  SetGVNFlag(kDependsOnElementsPointer);
2123  }
2124 
2125  HValue* value() { return OperandAt(0); }
2126  HValue* typecheck() { return OperandAt(1); }
2127 
2128  virtual void PrintDataTo(StringStream* stream);
2129 
2131  return Representation::Tagged();
2132  }
2133 
2134  DECLARE_CONCRETE_INSTRUCTION(LoadElements)
2135 
2136  protected:
2137  virtual bool DataEquals(HValue* other) { return true; }
2138 
2139  private:
2140  virtual bool IsDeletable() const { return true; }
2141 };
2142 
2143 
2145  public:
2147  : HUnaryOperation(value) {
2149  // The result of this instruction is idempotent as long as its inputs don't
2150  // change. The external array of a specialized array elements object cannot
2151  // change once set, so it's no necessary to introduce any additional
2152  // dependencies on top of the inputs.
2153  SetFlag(kUseGVN);
2154  }
2155 
2157  return Representation::Tagged();
2158  }
2159 
2160  DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer)
2161 
2162  protected:
2163  virtual bool DataEquals(HValue* other) { return true; }
2164 
2165  private:
2166  virtual bool IsDeletable() const { return true; }
2167 };
2168 
2169 
2170 class HCheckMaps: public HTemplateInstruction<2> {
2171  public:
2172  HCheckMaps(HValue* value, Handle<Map> map, Zone* zone,
2173  HValue* typecheck = NULL) {
2174  SetOperandAt(0, value);
2175  // If callers don't depend on a typecheck, they can pass in NULL. In that
2176  // case we use a copy of the |value| argument as a dummy value.
2177  SetOperandAt(1, typecheck != NULL ? typecheck : value);
2179  SetFlag(kUseGVN);
2180  SetGVNFlag(kDependsOnMaps);
2181  SetGVNFlag(kDependsOnElementsKind);
2182  map_set()->Add(map, zone);
2183  }
2184  HCheckMaps(HValue* value, SmallMapList* maps, Zone* zone) {
2185  SetOperandAt(0, value);
2186  SetOperandAt(1, value);
2188  SetFlag(kUseGVN);
2189  SetGVNFlag(kDependsOnMaps);
2190  SetGVNFlag(kDependsOnElementsKind);
2191  for (int i = 0; i < maps->length(); i++) {
2192  map_set()->Add(maps->at(i), zone);
2193  }
2194  map_set()->Sort();
2195  }
2196 
2198  Zone* zone) {
2199  HCheckMaps* check_map = new(zone) HCheckMaps(object, map, zone);
2200  SmallMapList* map_set = check_map->map_set();
2201 
2202  // Since transitioned elements maps of the initial map don't fail the map
2203  // check, the CheckMaps instruction doesn't need to depend on ElementsKinds.
2204  check_map->ClearGVNFlag(kDependsOnElementsKind);
2205 
2206  ElementsKind kind = map->elements_kind();
2207  bool packed = IsFastPackedElementsKind(kind);
2208  while (CanTransitionToMoreGeneralFastElementsKind(kind, packed)) {
2209  kind = GetNextMoreGeneralFastElementsKind(kind, packed);
2210  Map* transitioned_map =
2211  map->LookupElementsTransitionMap(kind);
2212  if (transitioned_map) {
2213  map_set->Add(Handle<Map>(transitioned_map), zone);
2214  }
2215  };
2216  map_set->Sort();
2217  return check_map;
2218  }
2219 
2221  return Representation::Tagged();
2222  }
2223  virtual void PrintDataTo(StringStream* stream);
2224  virtual HType CalculateInferredType();
2225 
2226  HValue* value() { return OperandAt(0); }
2227  SmallMapList* map_set() { return &map_set_; }
2228 
2229  DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
2230 
2231  protected:
2232  virtual bool DataEquals(HValue* other) {
2233  HCheckMaps* b = HCheckMaps::cast(other);
2234  // Relies on the fact that map_set has been sorted before.
2235  if (map_set()->length() != b->map_set()->length()) return false;
2236  for (int i = 0; i < map_set()->length(); i++) {
2237  if (!map_set()->at(i).is_identical_to(b->map_set()->at(i))) return false;
2238  }
2239  return true;
2240  }
2241 
2242  private:
2243  SmallMapList map_set_;
2244 };
2245 
2246 
2248  public:
2250  : HUnaryOperation(value), target_(function) {
2252  SetFlag(kUseGVN);
2253  }
2254 
2256  return Representation::Tagged();
2257  }
2258  virtual void PrintDataTo(StringStream* stream);
2259  virtual HType CalculateInferredType();
2260 
2261 #ifdef DEBUG
2262  virtual void Verify();
2263 #endif
2264 
2265  Handle<JSFunction> target() const { return target_; }
2266 
2267  DECLARE_CONCRETE_INSTRUCTION(CheckFunction)
2268 
2269  protected:
2270  virtual bool DataEquals(HValue* other) {
2272  return target_.is_identical_to(b->target());
2273  }
2274 
2275  private:
2276  Handle<JSFunction> target_;
2277 };
2278 
2279 
2281  public:
2283  return new(zone) HCheckInstanceType(value, IS_SPEC_OBJECT);
2284  }
2285  static HCheckInstanceType* NewIsJSArray(HValue* value, Zone* zone) {
2286  return new(zone) HCheckInstanceType(value, IS_JS_ARRAY);
2287  }
2288  static HCheckInstanceType* NewIsString(HValue* value, Zone* zone) {
2289  return new(zone) HCheckInstanceType(value, IS_STRING);
2290  }
2291  static HCheckInstanceType* NewIsSymbol(HValue* value, Zone* zone) {
2292  return new(zone) HCheckInstanceType(value, IS_SYMBOL);
2293  }
2294 
2295  virtual void PrintDataTo(StringStream* stream);
2296 
2298  return Representation::Tagged();
2299  }
2300 
2301  virtual HValue* Canonicalize();
2302 
2303  bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
2304  void GetCheckInterval(InstanceType* first, InstanceType* last);
2305  void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
2306 
2307  DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
2308 
2309  protected:
2310  // TODO(ager): It could be nice to allow the ommision of instance
2311  // type checks if we have already performed an instance type check
2312  // with a larger range.
2313  virtual bool DataEquals(HValue* other) {
2315  return check_ == b->check_;
2316  }
2317 
2318  private:
2319  enum Check {
2320  IS_SPEC_OBJECT,
2321  IS_JS_ARRAY,
2322  IS_STRING,
2323  IS_SYMBOL,
2324  LAST_INTERVAL_CHECK = IS_JS_ARRAY
2325  };
2326 
2327  const char* GetCheckName();
2328 
2329  HCheckInstanceType(HValue* value, Check check)
2330  : HUnaryOperation(value), check_(check) {
2332  SetFlag(kUseGVN);
2333  }
2334 
2335  const Check check_;
2336 };
2337 
2338 
2340  public:
2341  explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
2343  SetFlag(kUseGVN);
2344  }
2345 
2347  return Representation::Tagged();
2348  }
2349 
2350  virtual HType CalculateInferredType();
2351 
2352 #ifdef DEBUG
2353  virtual void Verify();
2354 #endif
2355 
2356  virtual HValue* Canonicalize() {
2357  HType value_type = value()->type();
2358  if (!value_type.IsUninitialized() &&
2359  (value_type.IsHeapNumber() ||
2360  value_type.IsString() ||
2361  value_type.IsBoolean() ||
2362  value_type.IsNonPrimitive())) {
2363  return NULL;
2364  }
2365  return this;
2366  }
2367 
2368  DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi)
2369 
2370  protected:
2371  virtual bool DataEquals(HValue* other) { return true; }
2372 };
2373 
2374 
2375 class HCheckPrototypeMaps: public HTemplateInstruction<0> {
2376  public:
2378  : prototype_(prototype), holder_(holder) {
2379  SetFlag(kUseGVN);
2380  SetGVNFlag(kDependsOnMaps);
2381  }
2382 
2383 #ifdef DEBUG
2384  virtual void Verify();
2385 #endif
2386 
2387  Handle<JSObject> prototype() const { return prototype_; }
2388  Handle<JSObject> holder() const { return holder_; }
2389 
2390  DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps)
2391 
2393  return Representation::None();
2394  }
2395 
2396  virtual void PrintDataTo(StringStream* stream);
2397 
2398  virtual intptr_t Hashcode() {
2400  intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
2401  hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
2402  return hash;
2403  }
2404 
2405  protected:
2406  virtual bool DataEquals(HValue* other) {
2408  return prototype_.is_identical_to(b->prototype()) &&
2409  holder_.is_identical_to(b->holder());
2410  }
2411 
2412  private:
2413  Handle<JSObject> prototype_;
2414  Handle<JSObject> holder_;
2415 };
2416 
2417 
2419  public:
2420  explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
2422  SetFlag(kUseGVN);
2423  }
2424 
2426  return Representation::Tagged();
2427  }
2428  virtual HType CalculateInferredType();
2429 
2430 #ifdef DEBUG
2431  virtual void Verify();
2432 #endif
2433 
2435 
2436  protected:
2437  virtual bool DataEquals(HValue* other) { return true; }
2438 };
2439 
2440 
2441 class HPhi: public HValue {
2442  public:
2443  HPhi(int merged_index, Zone* zone)
2444  : inputs_(2, zone),
2445  merged_index_(merged_index),
2446  phi_id_(-1),
2447  is_live_(false),
2448  is_convertible_to_integer_(true) {
2449  for (int i = 0; i < Representation::kNumRepresentations; i++) {
2450  non_phi_uses_[i] = 0;
2451  indirect_uses_[i] = 0;
2452  }
2453  ASSERT(merged_index >= 0);
2456  }
2457 
2459 
2460  virtual Range* InferRange(Zone* zone);
2462  return representation();
2463  }
2464  virtual HType CalculateInferredType();
2465  virtual int OperandCount() { return inputs_.length(); }
2466  virtual HValue* OperandAt(int index) const { return inputs_[index]; }
2467  HValue* GetRedundantReplacement();
2468  void AddInput(HValue* value);
2469  bool HasRealUses();
2470 
2471  bool IsReceiver() { return merged_index_ == 0; }
2472 
2473  int merged_index() const { return merged_index_; }
2474 
2475  virtual void PrintTo(StringStream* stream);
2476 
2477 #ifdef DEBUG
2478  virtual void Verify();
2479 #endif
2480 
2481  void InitRealUses(int id);
2482  void AddNonPhiUsesFrom(HPhi* other);
2483  void AddIndirectUsesTo(int* use_count);
2484 
2485  int tagged_non_phi_uses() const {
2486  return non_phi_uses_[Representation::kTagged];
2487  }
2488  int int32_non_phi_uses() const {
2489  return non_phi_uses_[Representation::kInteger32];
2490  }
2491  int double_non_phi_uses() const {
2492  return non_phi_uses_[Representation::kDouble];
2493  }
2494  int tagged_indirect_uses() const {
2495  return indirect_uses_[Representation::kTagged];
2496  }
2497  int int32_indirect_uses() const {
2498  return indirect_uses_[Representation::kInteger32];
2499  }
2500  int double_indirect_uses() const {
2501  return indirect_uses_[Representation::kDouble];
2502  }
2503  int phi_id() { return phi_id_; }
2504  bool is_live() { return is_live_; }
2505  void set_is_live(bool b) { is_live_ = b; }
2506 
2507  static HPhi* cast(HValue* value) {
2508  ASSERT(value->IsPhi());
2509  return reinterpret_cast<HPhi*>(value);
2510  }
2511  virtual Opcode opcode() const { return HValue::kPhi; }
2512 
2513  virtual bool IsConvertibleToInteger() const {
2514  return is_convertible_to_integer_;
2515  }
2516 
2518  is_convertible_to_integer_ = b;
2519  }
2520 
2522  for (int i = 0; i < OperandCount(); ++i) {
2523  if (!OperandAt(i)->IsConvertibleToInteger()) {
2524  return false;
2525  }
2526  }
2527  return true;
2528  }
2529 
2530  void ResetInteger32Uses();
2531 
2532  protected:
2533  virtual void DeleteFromGraph();
2534  virtual void InternalSetOperandAt(int index, HValue* value) {
2535  inputs_[index] = value;
2536  }
2537 
2538  private:
2539  ZoneList<HValue*> inputs_;
2540  int merged_index_;
2541 
2542  int non_phi_uses_[Representation::kNumRepresentations];
2543  int indirect_uses_[Representation::kNumRepresentations];
2544  int phi_id_;
2545  bool is_live_;
2546  bool is_convertible_to_integer_;
2547 };
2548 
2549 
2550 class HArgumentsObject: public HTemplateInstruction<0> {
2551  public:
2555  }
2556 
2558  return Representation::None();
2559  }
2560 
2561  DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
2562 
2563  private:
2564  virtual bool IsDeletable() const { return true; }
2565 };
2566 
2567 
2568 class HConstant: public HTemplateInstruction<0> {
2569  public:
2571  HConstant(int32_t value, Representation r);
2572  HConstant(double value, Representation r);
2573 
2575  if (handle_.is_null()) {
2576  handle_ = FACTORY->NewNumber(double_value_, TENURED);
2577  }
2578  ASSERT(has_int32_value_ || !handle_->IsSmi());
2579  return handle_;
2580  }
2581 
2582  bool InOldSpace() const { return !HEAP->InNewSpace(*handle_); }
2583 
2584  bool ImmortalImmovable() const {
2585  if (has_int32_value_) {
2586  return false;
2587  }
2588  if (has_double_value_) {
2589  if (BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) ||
2590  isnan(double_value_)) {
2591  return true;
2592  }
2593  return false;
2594  }
2595 
2596  ASSERT(!handle_.is_null());
2597  Heap* heap = HEAP;
2598  // We should have handled minus_zero_value and nan_value in the
2599  // has_double_value_ clause above.
2600  ASSERT(*handle_ != heap->minus_zero_value());
2601  ASSERT(*handle_ != heap->nan_value());
2602  if (*handle_ == heap->undefined_value()) return true;
2603  if (*handle_ == heap->null_value()) return true;
2604  if (*handle_ == heap->true_value()) return true;
2605  if (*handle_ == heap->false_value()) return true;
2606  if (*handle_ == heap->the_hole_value()) return true;
2607  if (*handle_ == heap->empty_string()) return true;
2608  return false;
2609  }
2610 
2612  return Representation::None();
2613  }
2614 
2615  virtual bool IsConvertibleToInteger() const {
2616  return has_int32_value_;
2617  }
2618 
2619  virtual bool EmitAtUses() { return !representation().IsDouble(); }
2620  virtual HValue* Canonicalize();
2621  virtual void PrintDataTo(StringStream* stream);
2622  virtual HType CalculateInferredType();
2623  bool IsInteger() { return handle()->IsSmi(); }
2624  HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
2625  HConstant* CopyToTruncatedInt32(Zone* zone) const;
2626  bool HasInteger32Value() const { return has_int32_value_; }
2628  ASSERT(HasInteger32Value());
2629  return int32_value_;
2630  }
2631  bool HasDoubleValue() const { return has_double_value_; }
2632  double DoubleValue() const {
2633  ASSERT(HasDoubleValue());
2634  return double_value_;
2635  }
2636  bool HasNumberValue() const { return has_double_value_; }
2638  ASSERT(HasNumberValue());
2639  // Irrespective of whether a numeric HConstant can be safely
2640  // represented as an int32, we store the (in some cases lossy)
2641  // representation of the number in int32_value_.
2642  return int32_value_;
2643  }
2644 
2645  bool ToBoolean();
2646 
2647  bool IsUint32() {
2648  return HasInteger32Value() && (Integer32Value() >= 0);
2649  }
2650 
2651  virtual intptr_t Hashcode() {
2653  intptr_t hash;
2654 
2655  if (has_int32_value_) {
2656  hash = static_cast<intptr_t>(int32_value_);
2657  } else if (has_double_value_) {
2658  hash = static_cast<intptr_t>(BitCast<int64_t>(double_value_));
2659  } else {
2660  ASSERT(!handle_.is_null());
2661  hash = reinterpret_cast<intptr_t>(*handle_);
2662  }
2663 
2664  return hash;
2665  }
2666 
2667 #ifdef DEBUG
2668  virtual void Verify() { }
2669 #endif
2670 
2672 
2673  protected:
2674  virtual Range* InferRange(Zone* zone);
2675 
2676  virtual bool DataEquals(HValue* other) {
2677  HConstant* other_constant = HConstant::cast(other);
2678  if (has_int32_value_) {
2679  return other_constant->has_int32_value_ &&
2680  int32_value_ == other_constant->int32_value_;
2681  } else if (has_double_value_) {
2682  return other_constant->has_double_value_ &&
2683  BitCast<int64_t>(double_value_) ==
2684  BitCast<int64_t>(other_constant->double_value_);
2685  } else {
2686  ASSERT(!handle_.is_null());
2687  return !other_constant->handle_.is_null() &&
2688  *handle_ == *other_constant->handle_;
2689  }
2690  }
2691 
2692  private:
2693  virtual bool IsDeletable() const { return true; }
2694 
2695  // If this is a numerical constant, handle_ either points to to the
2696  // HeapObject the constant originated from or is null. If the
2697  // constant is non-numeric, handle_ always points to a valid
2698  // constant HeapObject.
2699  Handle<Object> handle_;
2700 
2701  // We store the HConstant in the most specific form safely possible.
2702  // The two flags, has_int32_value_ and has_double_value_ tell us if
2703  // int32_value_ and double_value_ hold valid, safe representations
2704  // of the constant. has_int32_value_ implies has_double_value_ but
2705  // not the converse.
2706  bool has_int32_value_ : 1;
2707  bool has_double_value_ : 1;
2708  int32_t int32_value_;
2709  double double_value_;
2710 };
2711 
2712 
2713 class HBinaryOperation: public HTemplateInstruction<3> {
2714  public:
2715  HBinaryOperation(HValue* context, HValue* left, HValue* right) {
2716  ASSERT(left != NULL && right != NULL);
2717  SetOperandAt(0, context);
2718  SetOperandAt(1, left);
2719  SetOperandAt(2, right);
2720  }
2721 
2722  HValue* context() { return OperandAt(0); }
2723  HValue* left() { return OperandAt(1); }
2724  HValue* right() { return OperandAt(2); }
2725 
2726  // TODO(kasperl): Move these helpers to the IA-32 Lithium
2727  // instruction sequence builder.
2729  if (IsCommutative() && left()->IsConstant()) return right();
2730  return left();
2731  }
2732 
2734  if (IsCommutative() && left()->IsConstant()) return left();
2735  return right();
2736  }
2737 
2738  virtual bool IsCommutative() const { return false; }
2739 
2740  virtual void PrintDataTo(StringStream* stream);
2741 
2743 };
2744 
2745 
2746 class HWrapReceiver: public HTemplateInstruction<2> {
2747  public:
2748  HWrapReceiver(HValue* receiver, HValue* function) {
2750  SetOperandAt(0, receiver);
2751  SetOperandAt(1, function);
2752  }
2753 
2755  return Representation::Tagged();
2756  }
2757 
2758  HValue* receiver() { return OperandAt(0); }
2759  HValue* function() { return OperandAt(1); }
2760 
2761  virtual HValue* Canonicalize();
2762 
2763  DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
2764 };
2765 
2766 
2767 class HApplyArguments: public HTemplateInstruction<4> {
2768  public:
2770  HValue* receiver,
2771  HValue* length,
2772  HValue* elements) {
2774  SetOperandAt(0, function);
2775  SetOperandAt(1, receiver);
2776  SetOperandAt(2, length);
2777  SetOperandAt(3, elements);
2779  }
2780 
2782  // The length is untagged, all other inputs are tagged.
2783  return (index == 2)
2786  }
2787 
2788  HValue* function() { return OperandAt(0); }
2789  HValue* receiver() { return OperandAt(1); }
2790  HValue* length() { return OperandAt(2); }
2791  HValue* elements() { return OperandAt(3); }
2792 
2793  DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
2794 };
2795 
2796 
2797 class HArgumentsElements: public HTemplateInstruction<0> {
2798  public:
2799  explicit HArgumentsElements(bool from_inlined) : from_inlined_(from_inlined) {
2800  // The value produced by this instruction is a pointer into the stack
2801  // that looks as if it was a smi because of alignment.
2803  SetFlag(kUseGVN);
2804  }
2805 
2806  DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
2807 
2809  return Representation::None();
2810  }
2811 
2812  bool from_inlined() const { return from_inlined_; }
2813 
2814  protected:
2815  virtual bool DataEquals(HValue* other) { return true; }
2816 
2817  private:
2818  virtual bool IsDeletable() const { return true; }
2819 
2820  bool from_inlined_;
2821 };
2822 
2823 
2825  public:
2826  explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
2828  SetFlag(kUseGVN);
2829  }
2830 
2832  return Representation::Tagged();
2833  }
2834 
2835  DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
2836 
2837  protected:
2838  virtual bool DataEquals(HValue* other) { return true; }
2839 
2840  private:
2841  virtual bool IsDeletable() const { return true; }
2842 };
2843 
2844 
2845 class HAccessArgumentsAt: public HTemplateInstruction<3> {
2846  public:
2847  HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
2849  SetFlag(kUseGVN);
2850  SetOperandAt(0, arguments);
2851  SetOperandAt(1, length);
2852  SetOperandAt(2, index);
2853  }
2854 
2855  virtual void PrintDataTo(StringStream* stream);
2856 
2858  // The arguments elements is considered tagged.
2859  return index == 0
2862  }
2863 
2864  HValue* arguments() { return OperandAt(0); }
2865  HValue* length() { return OperandAt(1); }
2866  HValue* index() { return OperandAt(2); }
2867 
2868  DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
2869 
2870  virtual bool DataEquals(HValue* other) { return true; }
2871 };
2872 
2873 
2877 };
2878 
2879 
2880 class HBoundsCheck: public HTemplateInstruction<2> {
2881  public:
2882  HBoundsCheck(HValue* index, HValue* length,
2884  : key_mode_(key_mode) {
2885  SetOperandAt(0, index);
2886  SetOperandAt(1, length);
2888  SetFlag(kUseGVN);
2889  }
2890 
2892  if (key_mode_ == DONT_ALLOW_SMI_KEY ||
2893  !length()->representation().IsTagged()) {
2894  return Representation::Integer32();
2895  }
2896  // If the index is tagged and isn't constant, then allow the length
2897  // to be tagged, since it is usually already tagged from loading it out of
2898  // the length field of a JSArray. This allows for direct comparison without
2899  // untagging.
2900  if (index()->representation().IsTagged() && !index()->IsConstant()) {
2901  return Representation::Tagged();
2902  }
2903  // Also allow the length to be tagged if the index is constant, because
2904  // it can be tagged to allow direct comparison.
2905  if (index()->IsConstant() &&
2906  index()->representation().IsInteger32() &&
2907  arg_index == 1) {
2908  return Representation::Tagged();
2909  }
2910  return Representation::Integer32();
2911  }
2912 
2913  virtual void PrintDataTo(StringStream* stream);
2914 
2915  HValue* index() { return OperandAt(0); }
2916  HValue* length() { return OperandAt(1); }
2917 
2918  DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
2919 
2920  protected:
2921  virtual bool DataEquals(HValue* other) { return true; }
2923 };
2924 
2925 
2927  public:
2928  HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right)
2929  : HBinaryOperation(context, left, right) {
2933  observed_input_representation_[0] = Representation::Tagged();
2934  observed_input_representation_[1] = Representation::None();
2935  observed_input_representation_[2] = Representation::None();
2936  }
2937 
2939  return index == 0
2941  : representation();
2942  }
2943 
2945  if (!to.IsTagged()) {
2946  ASSERT(to.IsInteger32());
2949  SetFlag(kUseGVN);
2950  }
2951  }
2952 
2953  virtual HType CalculateInferredType();
2954 
2956  return observed_input_representation_[index];
2957  }
2958 
2960  observed_input_representation_[1] = r;
2961  observed_input_representation_[2] = r;
2962  }
2963 
2964  DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
2965 
2966  private:
2967  virtual bool IsDeletable() const { return true; }
2968 
2969  Representation observed_input_representation_[3];
2970 };
2971 
2972 
2974  public:
2975  HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
2976  : HBinaryOperation(context, left, right) {
2978  SetFlag(kUseGVN);
2980  }
2981 
2982  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
2983 
2985  return Representation::Integer32();
2986  }
2987 
2988  DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
2989 
2990  protected:
2991  virtual bool DataEquals(HValue* other) { return true; }
2992 
2993  private:
2994  virtual bool IsDeletable() const { return true; }
2995 };
2996 
2997 
2999  public:
3001  : HBinaryOperation(context, left, right) {
3005  }
3006 
3008  if (!to.IsTagged()) {
3010  SetFlag(kUseGVN);
3011  }
3012  }
3013 
3014  virtual HType CalculateInferredType();
3016  return index == 0
3018  : representation();
3019  }
3020 
3022  if (left()->representation().Equals(right()->representation())) {
3023  return left()->representation();
3024  }
3026  }
3027 
3028  private:
3029  virtual bool IsDeletable() const { return true; }
3030 };
3031 
3032 
3034  public:
3036  HValue* left,
3037  HValue* right,
3038  Token::Value token)
3039  : HBinaryOperation(context, left, right), token_(token) {
3040  ASSERT(Token::IsCompareOp(token));
3043  }
3044 
3046  return Representation::Tagged();
3047  }
3048 
3050  return Representation::Tagged();
3051  }
3052 
3053  Token::Value token() const { return token_; }
3054  virtual void PrintDataTo(StringStream* stream);
3055 
3056  virtual HType CalculateInferredType();
3057 
3058  DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
3059 
3060  private:
3061  Token::Value token_;
3062 };
3063 
3064 
3066  public:
3068  : token_(token) {
3069  ASSERT(Token::IsCompareOp(token));
3070  SetOperandAt(0, left);
3071  SetOperandAt(1, right);
3072  }
3073 
3074  HValue* left() { return OperandAt(0); }
3075  HValue* right() { return OperandAt(1); }
3076  Token::Value token() const { return token_; }
3077 
3078  void SetInputRepresentation(Representation r);
3080  return input_representation_;
3081  }
3082 
3084  return input_representation_;
3085  }
3086  virtual void PrintDataTo(StringStream* stream);
3087 
3088  DECLARE_CONCRETE_INSTRUCTION(CompareIDAndBranch)
3089 
3090  private:
3091  Representation input_representation_;
3092  Token::Value token_;
3093 };
3094 
3095 
3096 class HCompareObjectEqAndBranch: public HTemplateControlInstruction<2, 2> {
3097  public:
3099  SetOperandAt(0, left);
3100  SetOperandAt(1, right);
3101  }
3102 
3103  HValue* left() { return OperandAt(0); }
3104  HValue* right() { return OperandAt(1); }
3105 
3106  virtual void PrintDataTo(StringStream* stream);
3107 
3109  return Representation::Tagged();
3110  }
3111 
3112  DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
3113 };
3114 
3115 
3116 class HCompareConstantEqAndBranch: public HUnaryControlInstruction {
3117  public:
3119  : HUnaryControlInstruction(left, NULL, NULL), op_(op), right_(right) {
3120  ASSERT(op == Token::EQ_STRICT);
3121  }
3122 
3123  Token::Value op() const { return op_; }
3124  HValue* left() { return value(); }
3125  int right() const { return right_; }
3126 
3128  return Representation::Integer32();
3129  }
3130 
3131  DECLARE_CONCRETE_INSTRUCTION(CompareConstantEqAndBranch);
3132 
3133  private:
3134  const Token::Value op_;
3135  const int right_;
3136 };
3137 
3138 
3139 class HIsNilAndBranch: public HUnaryControlInstruction {
3140  public:
3142  : HUnaryControlInstruction(value, NULL, NULL), kind_(kind), nil_(nil) { }
3143 
3144  EqualityKind kind() const { return kind_; }
3145  NilValue nil() const { return nil_; }
3146 
3147  virtual void PrintDataTo(StringStream* stream);
3148 
3150  return Representation::Tagged();
3151  }
3152 
3153  DECLARE_CONCRETE_INSTRUCTION(IsNilAndBranch)
3154 
3155  private:
3156  EqualityKind kind_;
3157  NilValue nil_;
3158 };
3159 
3160 
3161 class HIsObjectAndBranch: public HUnaryControlInstruction {
3162  public:
3163  explicit HIsObjectAndBranch(HValue* value)
3164  : HUnaryControlInstruction(value, NULL, NULL) { }
3165 
3167  return Representation::Tagged();
3168  }
3169 
3170  DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch)
3171 };
3172 
3173 class HIsStringAndBranch: public HUnaryControlInstruction {
3174  public:
3175  explicit HIsStringAndBranch(HValue* value)
3176  : HUnaryControlInstruction(value, NULL, NULL) { }
3177 
3179  return Representation::Tagged();
3180  }
3181 
3182  DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
3183 };
3184 
3185 
3186 class HIsSmiAndBranch: public HUnaryControlInstruction {
3187  public:
3188  explicit HIsSmiAndBranch(HValue* value)
3189  : HUnaryControlInstruction(value, NULL, NULL) { }
3190 
3191  DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
3192 
3194  return Representation::Tagged();
3195  }
3196 
3197  protected:
3198  virtual bool DataEquals(HValue* other) { return true; }
3199 };
3200 
3201 
3202 class HIsUndetectableAndBranch: public HUnaryControlInstruction {
3203  public:
3205  : HUnaryControlInstruction(value, NULL, NULL) { }
3206 
3208  return Representation::Tagged();
3209  }
3210 
3211  DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
3212 };
3213 
3214 
3215 class HStringCompareAndBranch: public HTemplateControlInstruction<2, 3> {
3216  public:
3218  HValue* left,
3219  HValue* right,
3220  Token::Value token)
3221  : token_(token) {
3222  ASSERT(Token::IsCompareOp(token));
3223  SetOperandAt(0, context);
3224  SetOperandAt(1, left);
3225  SetOperandAt(2, right);
3227  }
3228 
3229  HValue* context() { return OperandAt(0); }
3230  HValue* left() { return OperandAt(1); }
3231  HValue* right() { return OperandAt(2); }
3232  Token::Value token() const { return token_; }
3233 
3234  virtual void PrintDataTo(StringStream* stream);
3235 
3237  return Representation::Tagged();
3238  }
3239 
3241  return Representation::Tagged();
3242  }
3243 
3244  DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
3245 
3246  private:
3247  Token::Value token_;
3248 };
3249 
3250 
3251 class HIsConstructCallAndBranch: public HTemplateControlInstruction<2, 0> {
3252  public:
3254  return Representation::None();
3255  }
3256 
3257  DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch)
3258 };
3259 
3260 
3261 class HHasInstanceTypeAndBranch: public HUnaryControlInstruction {
3262  public:
3264  : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
3266  : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
3267  ASSERT(to == LAST_TYPE); // Others not implemented yet in backend.
3268  }
3269 
3270  InstanceType from() { return from_; }
3271  InstanceType to() { return to_; }
3272 
3273  virtual void PrintDataTo(StringStream* stream);
3274 
3276  return Representation::Tagged();
3277  }
3278 
3279  DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
3280 
3281  private:
3282  InstanceType from_;
3283  InstanceType to_; // Inclusive range, not all combinations work.
3284 };
3285 
3286 
3287 class HHasCachedArrayIndexAndBranch: public HUnaryControlInstruction {
3288  public:
3290  : HUnaryControlInstruction(value, NULL, NULL) { }
3291 
3293  return Representation::Tagged();
3294  }
3295 
3296  DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
3297 };
3298 
3299 
3301  public:
3302  explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
3304  SetFlag(kUseGVN);
3305  }
3306 
3308  return Representation::Tagged();
3309  }
3310 
3311  DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
3312 
3313  protected:
3314  virtual bool DataEquals(HValue* other) { return true; }
3315 
3316  private:
3317  virtual bool IsDeletable() const { return true; }
3318 };
3319 
3320 
3321 class HClassOfTestAndBranch: public HUnaryControlInstruction {
3322  public:
3324  : HUnaryControlInstruction(value, NULL, NULL),
3325  class_name_(class_name) { }
3326 
3327  DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
3328 
3330  return Representation::Tagged();
3331  }
3332 
3333  virtual void PrintDataTo(StringStream* stream);
3334 
3335  Handle<String> class_name() const { return class_name_; }
3336 
3337  private:
3338  Handle<String> class_name_;
3339 };
3340 
3341 
3342 class HTypeofIsAndBranch: public HUnaryControlInstruction {
3343  public:
3345  : HUnaryControlInstruction(value, NULL, NULL),
3346  type_literal_(type_literal) { }
3347 
3348  Handle<String> type_literal() { return type_literal_; }
3349  virtual void PrintDataTo(StringStream* stream);
3350 
3351  DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
3352 
3354  return Representation::Tagged();
3355  }
3356 
3357  private:
3358  Handle<String> type_literal_;
3359 };
3360 
3361 
3363  public:
3364  HInstanceOf(HValue* context, HValue* left, HValue* right)
3365  : HBinaryOperation(context, left, right) {
3368  }
3369 
3371  return Representation::Tagged();
3372  }
3373 
3374  virtual HType CalculateInferredType();
3375 
3376  virtual void PrintDataTo(StringStream* stream);
3377 
3378  DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
3379 };
3380 
3381 
3382 class HInstanceOfKnownGlobal: public HTemplateInstruction<2> {
3383  public:
3385  HValue* left,
3386  Handle<JSFunction> right)
3387  : function_(right) {
3388  SetOperandAt(0, context);
3389  SetOperandAt(1, left);
3392  }
3393 
3394  HValue* context() { return OperandAt(0); }
3395  HValue* left() { return OperandAt(1); }
3396  Handle<JSFunction> function() { return function_; }
3397 
3399  return Representation::Tagged();
3400  }
3401 
3402  virtual HType CalculateInferredType();
3403 
3404  DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal)
3405 
3406  private:
3407  Handle<JSFunction> function_;
3408 };
3409 
3410 
3411 class HPower: public HTemplateInstruction<2> {
3412  public:
3413  HPower(HValue* left, HValue* right) {
3414  SetOperandAt(0, left);
3415  SetOperandAt(1, right);
3417  SetFlag(kUseGVN);
3418  SetGVNFlag(kChangesNewSpacePromotion);
3419  }
3420 
3421  HValue* left() { return OperandAt(0); }
3422  HValue* right() const { return OperandAt(1); }
3423 
3425  return index == 0
3428  }
3429 
3431 
3432  protected:
3433  virtual bool DataEquals(HValue* other) { return true; }
3434 
3435  private:
3436  virtual bool IsDeletable() const {
3437  return !right()->representation().IsTagged();
3438  }
3439 };
3440 
3441 
3442 class HRandom: public HTemplateInstruction<1> {
3443  public:
3444  explicit HRandom(HValue* global_object) {
3445  SetOperandAt(0, global_object);
3447  }
3448 
3449  HValue* global_object() { return OperandAt(0); }
3450 
3452  return Representation::Tagged();
3453  }
3454 
3456 
3457  private:
3458  virtual bool IsDeletable() const { return true; }
3459 };
3460 
3461 
3463  public:
3464  HAdd(HValue* context, HValue* left, HValue* right)
3465  : HArithmeticBinaryOperation(context, left, right) {
3467  }
3468 
3469  // Add is only commutative if two integer values are added and not if two
3470  // tagged values are added (because it might be a String concatenation).
3471  virtual bool IsCommutative() const {
3472  return !representation().IsTagged();
3473  }
3474 
3475  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3476 
3477  static HInstruction* NewHAdd(Zone* zone,
3478  HValue* context,
3479  HValue* left,
3480  HValue* right);
3481 
3482  virtual HType CalculateInferredType();
3483 
3484  virtual HValue* Canonicalize();
3485 
3487 
3488  protected:
3489  virtual bool DataEquals(HValue* other) { return true; }
3490 
3491  virtual Range* InferRange(Zone* zone);
3492 };
3493 
3494 
3496  public:
3497  HSub(HValue* context, HValue* left, HValue* right)
3498  : HArithmeticBinaryOperation(context, left, right) {
3500  }
3501 
3502  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3503 
3504  virtual HValue* Canonicalize();
3505 
3506  static HInstruction* NewHSub(Zone* zone,
3507  HValue* context,
3508  HValue* left,
3509  HValue* right);
3510 
3512 
3513  protected:
3514  virtual bool DataEquals(HValue* other) { return true; }
3515 
3516  virtual Range* InferRange(Zone* zone);
3517 };
3518 
3519 
3521  public:
3522  HMul(HValue* context, HValue* left, HValue* right)
3523  : HArithmeticBinaryOperation(context, left, right) {
3525  }
3526 
3527  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3528 
3529  // Only commutative if it is certain that not two objects are multiplicated.
3530  virtual bool IsCommutative() const {
3531  return !representation().IsTagged();
3532  }
3533 
3534  static HInstruction* NewHMul(Zone* zone,
3535  HValue* context,
3536  HValue* left,
3537  HValue* right);
3538 
3540 
3541  protected:
3542  virtual bool DataEquals(HValue* other) { return true; }
3543 
3544  virtual Range* InferRange(Zone* zone);
3545 };
3546 
3547 
3549  public:
3550  HMod(HValue* context, HValue* left, HValue* right)
3551  : HArithmeticBinaryOperation(context, left, right) {
3553  }
3554 
3556  if (right()->IsConstant() &&
3557  HConstant::cast(right())->HasInteger32Value()) {
3558  int32_t value = HConstant::cast(right())->Integer32Value();
3559  return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
3560  }
3561 
3562  return false;
3563  }
3564 
3565  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3566 
3567  static HInstruction* NewHMod(Zone* zone,
3568  HValue* context,
3569  HValue* left,
3570  HValue* right);
3571 
3573 
3574  protected:
3575  virtual bool DataEquals(HValue* other) { return true; }
3576 
3577  virtual Range* InferRange(Zone* zone);
3578 };
3579 
3580 
3582  public:
3583  HDiv(HValue* context, HValue* left, HValue* right)
3584  : HArithmeticBinaryOperation(context, left, right) {
3587  }
3588 
3589  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3590 
3591  static HInstruction* NewHDiv(Zone* zone,
3592  HValue* context,
3593  HValue* left,
3594  HValue* right);
3595 
3597 
3598  protected:
3599  virtual bool DataEquals(HValue* other) { return true; }
3600 
3601  virtual Range* InferRange(Zone* zone);
3602 };
3603 
3604 
3606  public:
3607  enum Operation { kMathMin, kMathMax };
3608 
3609  HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
3610  : HArithmeticBinaryOperation(context, left, right),
3611  operation_(op) { }
3612 
3614  return index == 0
3616  : representation();
3617  }
3618 
3620  if (left()->representation().IsInteger32() &&
3621  right()->representation().IsInteger32()) {
3622  return Representation::Integer32();
3623  }
3624  return Representation::Double();
3625  }
3626 
3627  virtual bool IsCommutative() const { return true; }
3628 
3629  Operation operation() { return operation_; }
3630 
3631  DECLARE_CONCRETE_INSTRUCTION(MathMinMax)
3632 
3633  protected:
3634  virtual bool DataEquals(HValue* other) {
3635  return other->IsMathMinMax() &&
3636  HMathMinMax::cast(other)->operation_ == operation_;
3637  }
3638 
3639  virtual Range* InferRange(Zone* zone);
3640 
3641  private:
3642  Operation operation_;
3643 };
3644 
3645 
3647  public:
3648  HBitwise(Token::Value op, HValue* context, HValue* left, HValue* right)
3649  : HBitwiseBinaryOperation(context, left, right), op_(op) {
3650  ASSERT(op == Token::BIT_AND ||
3651  op == Token::BIT_OR ||
3652  op == Token::BIT_XOR);
3653  }
3654 
3655  Token::Value op() const { return op_; }
3656 
3657  virtual bool IsCommutative() const { return true; }
3658 
3659  virtual HValue* Canonicalize();
3660 
3661  static HInstruction* NewHBitwise(Zone* zone,
3662  Token::Value op,
3663  HValue* context,
3664  HValue* left,
3665  HValue* right);
3666 
3667  virtual void PrintDataTo(StringStream* stream);
3668 
3670 
3671  protected:
3672  virtual bool DataEquals(HValue* other) {
3673  return op() == HBitwise::cast(other)->op();
3674  }
3675 
3676  virtual Range* InferRange(Zone* zone);
3677 
3678  private:
3679  Token::Value op_;
3680 };
3681 
3682 
3684  public:
3685  HShl(HValue* context, HValue* left, HValue* right)
3686  : HBitwiseBinaryOperation(context, left, right) { }
3687 
3688  virtual Range* InferRange(Zone* zone);
3689 
3690  static HInstruction* NewHShl(Zone* zone,
3691  HValue* context,
3692  HValue* left,
3693  HValue* right);
3694 
3696 
3697  protected:
3698  virtual bool DataEquals(HValue* other) { return true; }
3699 };
3700 
3701 
3703  public:
3704  HShr(HValue* context, HValue* left, HValue* right)
3705  : HBitwiseBinaryOperation(context, left, right) { }
3706 
3707  virtual Range* InferRange(Zone* zone);
3708 
3709  static HInstruction* NewHShr(Zone* zone,
3710  HValue* context,
3711  HValue* left,
3712  HValue* right);
3713 
3715 
3716  protected:
3717  virtual bool DataEquals(HValue* other) { return true; }
3718 };
3719 
3720 
3722  public:
3723  HSar(HValue* context, HValue* left, HValue* right)
3724  : HBitwiseBinaryOperation(context, left, right) { }
3725 
3726  virtual Range* InferRange(Zone* zone);
3727 
3728  static HInstruction* NewHSar(Zone* zone,
3729  HValue* context,
3730  HValue* left,
3731  HValue* right);
3732 
3734 
3735  protected:
3736  virtual bool DataEquals(HValue* other) { return true; }
3737 };
3738 
3739 
3740 class HOsrEntry: public HTemplateInstruction<0> {
3741  public:
3742  explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
3743  SetGVNFlag(kChangesOsrEntries);
3744  }
3745 
3746  BailoutId ast_id() const { return ast_id_; }
3747 
3749  return Representation::None();
3750  }
3751 
3753 
3754  private:
3755  BailoutId ast_id_;
3756 };
3757 
3758 
3759 class HParameter: public HTemplateInstruction<0> {
3760  public:
3761  explicit HParameter(unsigned index) : index_(index) {
3763  }
3764 
3765  unsigned index() const { return index_; }
3766 
3767  virtual void PrintDataTo(StringStream* stream);
3768 
3770  return Representation::None();
3771  }
3772 
3773  DECLARE_CONCRETE_INSTRUCTION(Parameter)
3774 
3775  private:
3776  unsigned index_;
3777 };
3778 
3779 
3780 class HCallStub: public HUnaryCall {
3781  public:
3782  HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
3783  : HUnaryCall(context, argument_count),
3784  major_key_(major_key),
3785  transcendental_type_(TranscendentalCache::kNumberOfCaches) {
3786  }
3787 
3788  CodeStub::Major major_key() { return major_key_; }
3789 
3790  HValue* context() { return value(); }
3791 
3793  transcendental_type_ = transcendental_type;
3794  }
3796  return transcendental_type_;
3797  }
3798 
3799  virtual void PrintDataTo(StringStream* stream);
3800 
3802  return Representation::Tagged();
3803  }
3804 
3806 
3807  private:
3808  CodeStub::Major major_key_;
3809  TranscendentalCache::Type transcendental_type_;
3810 };
3811 
3812 
3813 class HUnknownOSRValue: public HTemplateInstruction<0> {
3814  public:
3816  : incoming_value_(NULL) {
3818  }
3819 
3821  return Representation::None();
3822  }
3823 
3824  void set_incoming_value(HPhi* value) {
3825  incoming_value_ = value;
3826  }
3827 
3829  return incoming_value_;
3830  }
3831 
3832  DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
3833 
3834  private:
3835  HPhi* incoming_value_;
3836 };
3837 
3838 
3839 class HLoadGlobalCell: public HTemplateInstruction<0> {
3840  public:
3841  HLoadGlobalCell(Handle<JSGlobalPropertyCell> cell, PropertyDetails details)
3842  : cell_(cell), details_(details) {
3844  SetFlag(kUseGVN);
3845  SetGVNFlag(kDependsOnGlobalVars);
3846  }
3847 
3848  Handle<JSGlobalPropertyCell> cell() const { return cell_; }
3849  bool RequiresHoleCheck() const;
3850 
3851  virtual void PrintDataTo(StringStream* stream);
3852 
3853  virtual intptr_t Hashcode() {
3855  return reinterpret_cast<intptr_t>(*cell_);
3856  }
3857 
3859  return Representation::None();
3860  }
3861 
3862  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell)
3863 
3864  protected:
3865  virtual bool DataEquals(HValue* other) {
3867  return cell_.is_identical_to(b->cell());
3868  }
3869 
3870  private:
3871  virtual bool IsDeletable() const { return !RequiresHoleCheck(); }
3872 
3874  PropertyDetails details_;
3875 };
3876 
3877 
3878 class HLoadGlobalGeneric: public HTemplateInstruction<2> {
3879  public:
3881  HValue* global_object,
3882  Handle<Object> name,
3883  bool for_typeof)
3884  : name_(name),
3885  for_typeof_(for_typeof) {
3886  SetOperandAt(0, context);
3887  SetOperandAt(1, global_object);
3890  }
3891 
3892  HValue* context() { return OperandAt(0); }
3893  HValue* global_object() { return OperandAt(1); }
3894  Handle<Object> name() const { return name_; }
3895  bool for_typeof() const { return for_typeof_; }
3896 
3897  virtual void PrintDataTo(StringStream* stream);
3898 
3900  return Representation::Tagged();
3901  }
3902 
3903  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
3904 
3905  private:
3906  Handle<Object> name_;
3907  bool for_typeof_;
3908 };
3909 
3910 
3912  return !value->type().IsBoolean()
3913  && !value->type().IsSmi()
3914  && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
3915 }
3916 
3917 
3919  HValue* new_space_dominator) {
3920  return !object->IsAllocateObject() || (object != new_space_dominator);
3921 }
3922 
3923 
3925  public:
3928  PropertyDetails details)
3929  : HUnaryOperation(value),
3930  cell_(cell),
3931  details_(details) {
3932  SetGVNFlag(kChangesGlobalVars);
3933  }
3934 
3935  Handle<JSGlobalPropertyCell> cell() const { return cell_; }
3937  return !details_.IsDontDelete() || details_.IsReadOnly();
3938  }
3941  }
3942 
3944  return Representation::Tagged();
3945  }
3946  virtual void PrintDataTo(StringStream* stream);
3947 
3948  DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell)
3949 
3950  private:
3952  PropertyDetails details_;
3953 };
3954 
3955 
3956 class HStoreGlobalGeneric: public HTemplateInstruction<3> {
3957  public:
3959  HValue* global_object,
3960  Handle<Object> name,
3961  HValue* value,
3962  StrictModeFlag strict_mode_flag)
3963  : name_(name),
3964  strict_mode_flag_(strict_mode_flag) {
3965  SetOperandAt(0, context);
3966  SetOperandAt(1, global_object);
3967  SetOperandAt(2, value);
3970  }
3971 
3972  HValue* context() { return OperandAt(0); }
3973  HValue* global_object() { return OperandAt(1); }
3974  Handle<Object> name() const { return name_; }
3975  HValue* value() { return OperandAt(2); }
3976  StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
3977 
3978  virtual void PrintDataTo(StringStream* stream);
3979 
3981  return Representation::Tagged();
3982  }
3983 
3984  DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric)
3985 
3986  private:
3987  Handle<Object> name_;
3988  StrictModeFlag strict_mode_flag_;
3989 };
3990 
3991 
3993  public:
3994  enum Mode {
3995  // Perform a normal load of the context slot without checking its value.
3997  // Load and check the value of the context slot. Deoptimize if it's the
3998  // hole value. This is used for checking for loading of uninitialized
3999  // harmony bindings where we deoptimize into full-codegen generated code
4000  // which will subsequently throw a reference error.
4002  // Load and check the value of the context slot. Return undefined if it's
4003  // the hole value. This is used for non-harmony const assignments
4004  kCheckReturnUndefined
4005  };
4006 
4008  : HUnaryOperation(context), slot_index_(var->index()) {
4009  ASSERT(var->IsContextSlot());
4010  switch (var->mode()) {
4011  case LET:
4012  case CONST_HARMONY:
4013  mode_ = kCheckDeoptimize;
4014  break;
4015  case CONST:
4016  mode_ = kCheckReturnUndefined;
4017  break;
4018  default:
4019  mode_ = kNoCheck;
4020  }
4022  SetFlag(kUseGVN);
4023  SetGVNFlag(kDependsOnContextSlots);
4024  }
4025 
4026  int slot_index() const { return slot_index_; }
4027  Mode mode() const { return mode_; }
4028 
4030  return mode_ == kCheckDeoptimize;
4031  }
4032 
4033  bool RequiresHoleCheck() const {
4034  return mode_ != kNoCheck;
4035  }
4036 
4038  return Representation::Tagged();
4039  }
4040 
4041  virtual void PrintDataTo(StringStream* stream);
4042 
4043  DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
4044 
4045  protected:
4046  virtual bool DataEquals(HValue* other) {
4048  return (slot_index() == b->slot_index());
4049  }
4050 
4051  private:
4052  virtual bool IsDeletable() const { return !RequiresHoleCheck(); }
4053 
4054  int slot_index_;
4055  Mode mode_;
4056 };
4057 
4058 
4059 class HStoreContextSlot: public HTemplateInstruction<2> {
4060  public:
4061  enum Mode {
4062  // Perform a normal store to the context slot without checking its previous
4063  // value.
4065  // Check the previous value of the context slot and deoptimize if it's the
4066  // hole value. This is used for checking for assignments to uninitialized
4067  // harmony bindings where we deoptimize into full-codegen generated code
4068  // which will subsequently throw a reference error.
4070  // Check the previous value and ignore assignment if it isn't a hole value
4071  kCheckIgnoreAssignment
4072  };
4073 
4074  HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
4075  : slot_index_(slot_index), mode_(mode) {
4076  SetOperandAt(0, context);
4077  SetOperandAt(1, value);
4078  SetGVNFlag(kChangesContextSlots);
4079  }
4080 
4081  HValue* context() { return OperandAt(0); }
4082  HValue* value() { return OperandAt(1); }
4083  int slot_index() const { return slot_index_; }
4084  Mode mode() const { return mode_; }
4085 
4088  }
4089 
4091  return mode_ == kCheckDeoptimize;
4092  }
4093 
4095  return mode_ != kNoCheck;
4096  }
4097 
4099  return Representation::Tagged();
4100  }
4101 
4102  virtual void PrintDataTo(StringStream* stream);
4103 
4104  DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
4105 
4106  private:
4107  int slot_index_;
4108  Mode mode_;
4109 };
4110 
4111 
4113  public:
4114  HLoadNamedField(HValue* object, bool is_in_object, int offset)
4115  : HUnaryOperation(object),
4116  is_in_object_(is_in_object),
4117  offset_(offset) {
4119  SetFlag(kUseGVN);
4120  SetGVNFlag(kDependsOnMaps);
4121  if (is_in_object) {
4122  SetGVNFlag(kDependsOnInobjectFields);
4123  } else {
4124  SetGVNFlag(kDependsOnBackingStoreFields);
4125  }
4126  }
4127 
4128  HValue* object() { return OperandAt(0); }
4129  bool is_in_object() const { return is_in_object_; }
4130  int offset() const { return offset_; }
4131 
4133  return Representation::Tagged();
4134  }
4135  virtual void PrintDataTo(StringStream* stream);
4136 
4137  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
4138 
4139  protected:
4140  virtual bool DataEquals(HValue* other) {
4142  return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
4143  }
4144 
4145  private:
4146  virtual bool IsDeletable() const { return true; }
4147 
4148  bool is_in_object_;
4149  int offset_;
4150 };
4151 
4152 
4153 class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
4154  public:
4156  HValue* object,
4157  SmallMapList* types,
4158  Handle<String> name,
4159  Zone* zone);
4160 
4161  HValue* context() { return OperandAt(0); }
4162  HValue* object() { return OperandAt(1); }
4163  SmallMapList* types() { return &types_; }
4164  Handle<String> name() { return name_; }
4165  bool need_generic() { return need_generic_; }
4166 
4168  return Representation::Tagged();
4169  }
4170 
4171  virtual void PrintDataTo(StringStream* stream);
4172 
4173  DECLARE_CONCRETE_INSTRUCTION(LoadNamedFieldPolymorphic)
4174 
4175  static const int kMaxLoadPolymorphism = 4;
4176 
4177  protected:
4178  virtual bool DataEquals(HValue* value);
4179 
4180  private:
4181  SmallMapList types_;
4182  Handle<String> name_;
4183  bool need_generic_;
4184 };
4185 
4186 
4187 
4188 class HLoadNamedGeneric: public HTemplateInstruction<2> {
4189  public:
4191  : name_(name) {
4192  SetOperandAt(0, context);
4193  SetOperandAt(1, object);
4196  }
4197 
4198  HValue* context() { return OperandAt(0); }
4199  HValue* object() { return OperandAt(1); }
4200  Handle<Object> name() const { return name_; }
4201 
4203  return Representation::Tagged();
4204  }
4205 
4206  virtual void PrintDataTo(StringStream* stream);
4207 
4208  DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
4209 
4210  private:
4211  Handle<Object> name_;
4212 };
4213 
4214 
4216  public:
4217  explicit HLoadFunctionPrototype(HValue* function)
4218  : HUnaryOperation(function) {
4220  SetFlag(kUseGVN);
4221  SetGVNFlag(kDependsOnCalls);
4222  }
4223 
4224  HValue* function() { return OperandAt(0); }
4225 
4227  return Representation::Tagged();
4228  }
4229 
4230  DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
4231 
4232  protected:
4233  virtual bool DataEquals(HValue* other) { return true; }
4234 };
4235 
4237  public:
4238  virtual HValue* GetKey() = 0;
4239  virtual void SetKey(HValue* key) = 0;
4240  virtual void SetIndexOffset(uint32_t index_offset) = 0;
4241  virtual bool IsDehoisted() = 0;
4242  virtual void SetDehoisted(bool is_dehoisted) = 0;
4244 };
4245 
4247  : public HTemplateInstruction<3>, public ArrayInstructionInterface {
4248  public:
4250  HValue* key,
4251  HValue* dependency,
4252  ElementsKind elements_kind = FAST_ELEMENTS)
4253  : bit_field_(0) {
4254  ASSERT(IsFastSmiOrObjectElementsKind(elements_kind));
4255  bit_field_ = ElementsKindField::encode(elements_kind);
4256  if (IsFastSmiElementsKind(elements_kind) &&
4257  IsFastPackedElementsKind(elements_kind)) {
4258  set_type(HType::Smi());
4259  }
4260  SetOperandAt(0, obj);
4261  SetOperandAt(1, key);
4262  SetOperandAt(2, dependency);
4264  SetGVNFlag(kDependsOnArrayElements);
4265  SetFlag(kUseGVN);
4266  }
4267 
4268  HValue* object() { return OperandAt(0); }
4269  HValue* key() { return OperandAt(1); }
4270  HValue* dependency() { return OperandAt(2); }
4271  uint32_t index_offset() { return IndexOffsetField::decode(bit_field_); }
4272  void SetIndexOffset(uint32_t index_offset) {
4273  bit_field_ = IndexOffsetField::update(bit_field_, index_offset);
4274  }
4275  HValue* GetKey() { return key(); }
4276  void SetKey(HValue* key) { SetOperandAt(1, key); }
4277  bool IsDehoisted() { return IsDehoistedField::decode(bit_field_); }
4278  void SetDehoisted(bool is_dehoisted) {
4279  bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
4280  }
4282  return ElementsKindField::decode(bit_field_);
4283  }
4284 
4286  // The key is supposed to be Integer32.
4287  if (index == 0) return Representation::Tagged();
4288  if (index == 1) return Representation::Integer32();
4289  return Representation::None();
4290  }
4291 
4292  virtual void PrintDataTo(StringStream* stream);
4293 
4294  bool RequiresHoleCheck() const;
4295 
4296  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement)
4297 
4298  protected:
4299  virtual bool DataEquals(HValue* other) {
4300  if (!other->IsLoadKeyedFastElement()) return false;
4302  if (IsDehoisted() && index_offset() != other_load->index_offset())
4303  return false;
4304  return elements_kind() == other_load->elements_kind();
4305  }
4306 
4307  private:
4308  virtual bool IsDeletable() const { return !RequiresHoleCheck(); }
4309 
4310  class ElementsKindField: public BitField<ElementsKind, 0, 4> {};
4311  class IndexOffsetField: public BitField<uint32_t, 4, 27> {};
4312  class IsDehoistedField: public BitField<bool, 31, 1> {};
4313  uint32_t bit_field_;
4314 };
4315 
4316 
4318 
4319 
4321  : public HTemplateInstruction<3>, public ArrayInstructionInterface {
4322  public:
4324  HValue* elements,
4325  HValue* key,
4326  HValue* dependency,
4327  HoleCheckMode hole_check_mode = PERFORM_HOLE_CHECK)
4328  : index_offset_(0),
4329  is_dehoisted_(false),
4330  hole_check_mode_(hole_check_mode) {
4331  SetOperandAt(0, elements);
4332  SetOperandAt(1, key);
4333  SetOperandAt(2, dependency);
4335  SetGVNFlag(kDependsOnDoubleArrayElements);
4336  SetFlag(kUseGVN);
4337  }
4338 
4339  HValue* elements() { return OperandAt(0); }
4340  HValue* key() { return OperandAt(1); }
4341  HValue* dependency() { return OperandAt(2); }
4342  uint32_t index_offset() { return index_offset_; }
4343  void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
4344  HValue* GetKey() { return key(); }
4345  void SetKey(HValue* key) { SetOperandAt(1, key); }
4346  bool IsDehoisted() { return is_dehoisted_; }
4347  void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
4348 
4350  // The key is supposed to be Integer32.
4351  if (index == 0) return Representation::Tagged();
4352  if (index == 1) return Representation::Integer32();
4353  return Representation::None();
4354  }
4355 
4356  bool RequiresHoleCheck() const {
4357  return hole_check_mode_ == PERFORM_HOLE_CHECK;
4358  }
4359 
4360  virtual void PrintDataTo(StringStream* stream);
4361 
4362  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement)
4363 
4364  protected:
4365  virtual bool DataEquals(HValue* other) {
4366  if (!other->IsLoadKeyedFastDoubleElement()) return false;
4367  HLoadKeyedFastDoubleElement* other_load =
4369  return hole_check_mode_ == other_load->hole_check_mode_;
4370  }
4371 
4372  private:
4373  virtual bool IsDeletable() const { return !RequiresHoleCheck(); }
4374 
4375  uint32_t index_offset_;
4376  bool is_dehoisted_;
4377  HoleCheckMode hole_check_mode_;
4378 };
4379 
4380 
4382  : public HTemplateInstruction<3>, public ArrayInstructionInterface {
4383  public:
4385  HValue* key,
4386  HValue* dependency,
4387  ElementsKind elements_kind)
4388  : elements_kind_(elements_kind),
4389  index_offset_(0),
4390  is_dehoisted_(false) {
4391  SetOperandAt(0, external_elements);
4392  SetOperandAt(1, key);
4393  SetOperandAt(2, dependency);
4394  if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
4395  elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
4397  } else {
4399  }
4400  SetGVNFlag(kDependsOnSpecializedArrayElements);
4401  // Native code could change the specialized array.
4402  SetGVNFlag(kDependsOnCalls);
4403  SetFlag(kUseGVN);
4404  }
4405 
4406  virtual void PrintDataTo(StringStream* stream);
4407 
4409  // The key is supposed to be Integer32.
4410  if (index == 0) return Representation::External();
4411  if (index == 1) return Representation::Integer32();
4412  return Representation::None();
4413  }
4414 
4416  HValue* key() { return OperandAt(1); }
4417  HValue* dependency() { return OperandAt(2); }
4418  ElementsKind elements_kind() const { return elements_kind_; }
4419  uint32_t index_offset() { return index_offset_; }
4420  void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
4421  HValue* GetKey() { return key(); }
4422  void SetKey(HValue* key) { SetOperandAt(1, key); }
4423  bool IsDehoisted() { return is_dehoisted_; }
4424  void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
4425 
4426  virtual Range* InferRange(Zone* zone);
4427 
4428  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement)
4429 
4430  protected:
4431  virtual bool DataEquals(HValue* other) {
4432  if (!other->IsLoadKeyedSpecializedArrayElement()) return false;
4433  HLoadKeyedSpecializedArrayElement* cast_other =
4435  return elements_kind_ == cast_other->elements_kind();
4436  }
4437 
4438  private:
4439  virtual bool IsDeletable() const { return true; }
4440 
4441  ElementsKind elements_kind_;
4442  uint32_t index_offset_;
4443  bool is_dehoisted_;
4444 };
4445 
4446 
4447 class HLoadKeyedGeneric: public HTemplateInstruction<3> {
4448  public:
4449  HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key) {
4451  SetOperandAt(0, obj);
4452  SetOperandAt(1, key);
4453  SetOperandAt(2, context);
4455  }
4456 
4457  HValue* object() { return OperandAt(0); }
4458  HValue* key() { return OperandAt(1); }
4459  HValue* context() { return OperandAt(2); }
4460 
4461  virtual void PrintDataTo(StringStream* stream);
4462 
4464  return Representation::Tagged();
4465  }
4466 
4467  virtual HValue* Canonicalize();
4468 
4469  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
4470 };
4471 
4472 
4473 class HStoreNamedField: public HTemplateInstruction<2> {
4474  public:
4476  Handle<String> name,
4477  HValue* val,
4478  bool in_object,
4479  int offset)
4480  : name_(name),
4481  is_in_object_(in_object),
4482  offset_(offset),
4483  new_space_dominator_(NULL) {
4484  SetOperandAt(0, obj);
4485  SetOperandAt(1, val);
4487  SetGVNFlag(kDependsOnNewSpacePromotion);
4488  if (is_in_object_) {
4489  SetGVNFlag(kChangesInobjectFields);
4490  } else {
4491  SetGVNFlag(kChangesBackingStoreFields);
4492  }
4493  }
4494 
4495  DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
4496 
4498  return Representation::Tagged();
4499  }
4500  virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) {
4501  ASSERT(side_effect == kChangesNewSpacePromotion);
4502  new_space_dominator_ = dominator;
4503  }
4504  virtual void PrintDataTo(StringStream* stream);
4505 
4506  HValue* object() { return OperandAt(0); }
4507  HValue* value() { return OperandAt(1); }
4508 
4509  Handle<String> name() const { return name_; }
4510  bool is_in_object() const { return is_in_object_; }
4511  int offset() const { return offset_; }
4512  Handle<Map> transition() const { return transition_; }
4513  void set_transition(Handle<Map> map) { transition_ = map; }
4514  HValue* new_space_dominator() const { return new_space_dominator_; }
4515 
4518  ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
4519  }
4520 
4522  return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
4523  }
4524 
4525  private:
4526  Handle<String> name_;
4527  bool is_in_object_;
4528  int offset_;
4529  Handle<Map> transition_;
4530  HValue* new_space_dominator_;
4531 };
4532 
4533 
4534 class HStoreNamedGeneric: public HTemplateInstruction<3> {
4535  public:
4537  HValue* object,
4538  Handle<String> name,
4539  HValue* value,
4540  StrictModeFlag strict_mode_flag)
4541  : name_(name),
4542  strict_mode_flag_(strict_mode_flag) {
4543  SetOperandAt(0, object);
4544  SetOperandAt(1, value);
4545  SetOperandAt(2, context);
4547  }
4548 
4549  HValue* object() { return OperandAt(0); }
4550  HValue* value() { return OperandAt(1); }
4551  HValue* context() { return OperandAt(2); }
4552  Handle<String> name() { return name_; }
4553  StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
4554 
4555  virtual void PrintDataTo(StringStream* stream);
4556 
4558  return Representation::Tagged();
4559  }
4560 
4561  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
4562 
4563  private:
4564  Handle<String> name_;
4565  StrictModeFlag strict_mode_flag_;
4566 };
4567 
4568 
4570  : public HTemplateInstruction<3>, public ArrayInstructionInterface {
4571  public:
4573  ElementsKind elements_kind = FAST_ELEMENTS)
4574  : elements_kind_(elements_kind), index_offset_(0), is_dehoisted_(false) {
4575  SetOperandAt(0, obj);
4576  SetOperandAt(1, key);
4577  SetOperandAt(2, val);
4578  SetGVNFlag(kChangesArrayElements);
4579  }
4580 
4582  // The key is supposed to be Integer32.
4583  return index == 1
4586  }
4587 
4588  HValue* object() { return OperandAt(0); }
4589  HValue* key() { return OperandAt(1); }
4590  HValue* value() { return OperandAt(2); }
4591  bool value_is_smi() {
4592  return IsFastSmiElementsKind(elements_kind_);
4593  }
4594  uint32_t index_offset() { return index_offset_; }
4595  void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
4596  HValue* GetKey() { return key(); }
4597  void SetKey(HValue* key) { SetOperandAt(1, key); }
4598  bool IsDehoisted() { return is_dehoisted_; }
4599  void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
4600 
4602  if (value_is_smi()) {
4603  return false;
4604  } else {
4606  }
4607  }
4608 
4609  virtual void PrintDataTo(StringStream* stream);
4610 
4611  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement)
4612 
4613  private:
4614  ElementsKind elements_kind_;
4615  uint32_t index_offset_;
4616  bool is_dehoisted_;
4617 };
4618 
4619 
4621  : public HTemplateInstruction<3>, public ArrayInstructionInterface {
4622  public:
4624  HValue* key,
4625  HValue* val)
4626  : index_offset_(0), is_dehoisted_(false) {
4627  SetOperandAt(0, elements);
4628  SetOperandAt(1, key);
4629  SetOperandAt(2, val);
4631  SetGVNFlag(kChangesDoubleArrayElements);
4632  }
4633 
4635  if (index == 1) {
4636  return Representation::Integer32();
4637  } else if (index == 2) {
4638  return Representation::Double();
4639  } else {
4640  return Representation::Tagged();
4641  }
4642  }
4643 
4644  HValue* elements() { return OperandAt(0); }
4645  HValue* key() { return OperandAt(1); }
4646  HValue* value() { return OperandAt(2); }
4647  uint32_t index_offset() { return index_offset_; }
4648  void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
4649  HValue* GetKey() { return key(); }
4650  void SetKey(HValue* key) { SetOperandAt(1, key); }
4651  bool IsDehoisted() { return is_dehoisted_; }
4652  void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
4653 
4656  }
4657 
4658  bool NeedsCanonicalization();
4659 
4660  virtual void PrintDataTo(StringStream* stream);
4661 
4662  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement)
4663 
4664  private:
4665  uint32_t index_offset_;
4666  bool is_dehoisted_;
4667 };
4668 
4669 
4671  : public HTemplateInstruction<3>, public ArrayInstructionInterface {
4672  public:
4674  HValue* key,
4675  HValue* val,
4676  ElementsKind elements_kind)
4677  : elements_kind_(elements_kind), index_offset_(0), is_dehoisted_(false) {
4678  SetGVNFlag(kChangesSpecializedArrayElements);
4679  SetOperandAt(0, external_elements);
4680  SetOperandAt(1, key);
4681  SetOperandAt(2, val);
4682  }
4683 
4684  virtual void PrintDataTo(StringStream* stream);
4685 
4687  if (index == 0) {
4688  return Representation::External();
4689  } else {
4690  bool float_or_double_elements =
4691  elements_kind() == EXTERNAL_FLOAT_ELEMENTS ||
4692  elements_kind() == EXTERNAL_DOUBLE_ELEMENTS;
4693  if (index == 2 && float_or_double_elements) {
4694  return Representation::Double();
4695  } else {
4696  return Representation::Integer32();
4697  }
4698  }
4699  }
4700 
4702  HValue* key() { return OperandAt(1); }
4703  HValue* value() { return OperandAt(2); }
4704  ElementsKind elements_kind() const { return elements_kind_; }
4705  uint32_t index_offset() { return index_offset_; }
4706  void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
4707  HValue* GetKey() { return key(); }
4708  void SetKey(HValue* key) { SetOperandAt(1, key); }
4709  bool IsDehoisted() { return is_dehoisted_; }
4710  void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
4711 
4712  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement)
4713 
4714  private:
4715  ElementsKind elements_kind_;
4716  uint32_t index_offset_;
4717  bool is_dehoisted_;
4718 };
4719 
4720 
4721 class HStoreKeyedGeneric: public HTemplateInstruction<4> {
4722  public:
4724  HValue* object,
4725  HValue* key,
4726  HValue* value,
4727  StrictModeFlag strict_mode_flag)
4728  : strict_mode_flag_(strict_mode_flag) {
4729  SetOperandAt(0, object);
4730  SetOperandAt(1, key);
4731  SetOperandAt(2, value);
4732  SetOperandAt(3, context);
4734  }
4735 
4736  HValue* object() { return OperandAt(0); }
4737  HValue* key() { return OperandAt(1); }
4738  HValue* value() { return OperandAt(2); }
4739  HValue* context() { return OperandAt(3); }
4740  StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
4741 
4743  return Representation::Tagged();
4744  }
4745 
4746  virtual void PrintDataTo(StringStream* stream);
4747 
4748  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
4749 
4750  private:
4751  StrictModeFlag strict_mode_flag_;
4752 };
4753 
4754 
4755 class HTransitionElementsKind: public HTemplateInstruction<1> {
4756  public:
4758  Handle<Map> original_map,
4759  Handle<Map> transitioned_map)
4760  : original_map_(original_map),
4761  transitioned_map_(transitioned_map) {
4762  SetOperandAt(0, object);
4763  SetFlag(kUseGVN);
4764  SetGVNFlag(kChangesElementsKind);
4765  if (original_map->has_fast_double_elements()) {
4766  SetGVNFlag(kChangesElementsPointer);
4767  SetGVNFlag(kChangesNewSpacePromotion);
4768  }
4769  if (transitioned_map->has_fast_double_elements()) {
4770  SetGVNFlag(kChangesElementsPointer);
4771  SetGVNFlag(kChangesNewSpacePromotion);
4772  }
4774  }
4775 
4777  return Representation::Tagged();
4778  }
4779 
4780  HValue* object() { return OperandAt(0); }
4781  Handle<Map> original_map() { return original_map_; }
4782  Handle<Map> transitioned_map() { return transitioned_map_; }
4783 
4784  virtual void PrintDataTo(StringStream* stream);
4785 
4786  DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
4787 
4788  protected:
4789  virtual bool DataEquals(HValue* other) {
4791  return original_map_.is_identical_to(instr->original_map()) &&
4792  transitioned_map_.is_identical_to(instr->transitioned_map());
4793  }
4794 
4795  private:
4796  Handle<Map> original_map_;
4797  Handle<Map> transitioned_map_;
4798 };
4799 
4800 
4802  public:
4803  HStringAdd(HValue* context, HValue* left, HValue* right)
4804  : HBinaryOperation(context, left, right) {
4806  SetFlag(kUseGVN);
4807  SetGVNFlag(kDependsOnMaps);
4808  }
4809 
4811  return Representation::Tagged();
4812  }
4813 
4815  return HType::String();
4816  }
4817 
4818  DECLARE_CONCRETE_INSTRUCTION(StringAdd)
4819 
4820  protected:
4821  virtual bool DataEquals(HValue* other) { return true; }
4822 
4823  // TODO(svenpanne) Might be safe, but leave it out until we know for sure.
4824  // private:
4825  // virtual bool IsDeletable() const { return true; }
4826 };
4827 
4828 
4829 class HStringCharCodeAt: public HTemplateInstruction<3> {
4830  public:
4831  HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
4832  SetOperandAt(0, context);
4833  SetOperandAt(1, string);
4834  SetOperandAt(2, index);
4836  SetFlag(kUseGVN);
4837  SetGVNFlag(kDependsOnMaps);
4838  SetGVNFlag(kChangesNewSpacePromotion);
4839  }
4840 
4842  // The index is supposed to be Integer32.
4843  return index == 2
4846  }
4847 
4848  HValue* context() { return OperandAt(0); }
4849  HValue* string() { return OperandAt(1); }
4850  HValue* index() { return OperandAt(2); }
4851 
4852  DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
4853 
4854  protected:
4855  virtual bool DataEquals(HValue* other) { return true; }
4856 
4857  virtual Range* InferRange(Zone* zone) {
4858  return new(zone) Range(0, String::kMaxUtf16CodeUnit);
4859  }
4860 
4861  // TODO(svenpanne) Might be safe, but leave it out until we know for sure.
4862  // private:
4863  // virtual bool IsDeletable() const { return true; }
4864 };
4865 
4866 
4867 class HStringCharFromCode: public HTemplateInstruction<2> {
4868  public:
4869  HStringCharFromCode(HValue* context, HValue* char_code) {
4870  SetOperandAt(0, context);
4871  SetOperandAt(1, char_code);
4873  SetFlag(kUseGVN);
4874  SetGVNFlag(kChangesNewSpacePromotion);
4875  }
4876 
4878  return index == 0
4881  }
4882  virtual HType CalculateInferredType();
4883 
4884  HValue* context() { return OperandAt(0); }
4885  HValue* value() { return OperandAt(1); }
4886 
4887  virtual bool DataEquals(HValue* other) { return true; }
4888 
4889  DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
4890 
4891  // TODO(svenpanne) Might be safe, but leave it out until we know for sure.
4892  // private:
4893  // virtual bool IsDeletable() const { return true; }
4894 };
4895 
4896 
4898  public:
4899  explicit HStringLength(HValue* string) : HUnaryOperation(string) {
4901  SetFlag(kUseGVN);
4902  SetGVNFlag(kDependsOnMaps);
4903  }
4904 
4906  return Representation::Tagged();
4907  }
4908 
4911  return HType::Smi();
4912  }
4913 
4914  DECLARE_CONCRETE_INSTRUCTION(StringLength)
4915 
4916  protected:
4917  virtual bool DataEquals(HValue* other) { return true; }
4918 
4919  virtual Range* InferRange(Zone* zone) {
4920  return new(zone) Range(0, String::kMaxLength);
4921  }
4922 
4923  private:
4924  virtual bool IsDeletable() const { return true; }
4925 };
4926 
4927 
4928 class HAllocateObject: public HTemplateInstruction<1> {
4929  public:
4931  : constructor_(constructor) {
4932  SetOperandAt(0, context);
4934  SetGVNFlag(kChangesNewSpacePromotion);
4935  }
4936 
4937  // Maximum instance size for which allocations will be inlined.
4938  static const int kMaxSize = 64 * kPointerSize;
4939 
4940  HValue* context() { return OperandAt(0); }
4941  Handle<JSFunction> constructor() { return constructor_; }
4942 
4944  return Representation::Tagged();
4945  }
4946  virtual HType CalculateInferredType();
4947 
4948  DECLARE_CONCRETE_INSTRUCTION(AllocateObject)
4949 
4950  private:
4951  // TODO(svenpanne) Might be safe, but leave it out until we know for sure.
4952  // virtual bool IsDeletable() const { return true; }
4953 
4954  Handle<JSFunction> constructor_;
4955 };
4956 
4957 
4958 template <int V>
4959 class HMaterializedLiteral: public HTemplateInstruction<V> {
4960  public:
4961  HMaterializedLiteral<V>(int index, int depth)
4962  : literal_index_(index), depth_(depth) {
4964  }
4965 
4966  int literal_index() const { return literal_index_; }
4967  int depth() const { return depth_; }
4968 
4969  private:
4970  virtual bool IsDeletable() const { return true; }
4971 
4972  int literal_index_;
4973  int depth_;
4974 };
4975 
4976 
4978  public:
4980  Handle<JSObject> boilerplate,
4981  int total_size,
4982  int literal_index,
4983  int depth)
4984  : HMaterializedLiteral<1>(literal_index, depth),
4985  boilerplate_(boilerplate),
4986  total_size_(total_size) {
4987  SetOperandAt(0, context);
4988  SetGVNFlag(kChangesNewSpacePromotion);
4989  }
4990 
4991  // Maximum depth and total number of elements and properties for literal
4992  // graphs to be considered for fast deep-copying.
4993  static const int kMaxLiteralDepth = 3;
4994  static const int kMaxLiteralProperties = 8;
4995 
4996  HValue* context() { return OperandAt(0); }
4997  Handle<JSObject> boilerplate() const { return boilerplate_; }
4998  int total_size() const { return total_size_; }
4999 
5001  return Representation::Tagged();
5002  }
5003  virtual HType CalculateInferredType();
5004 
5005  DECLARE_CONCRETE_INSTRUCTION(FastLiteral)
5006 
5007  private:
5008  Handle<JSObject> boilerplate_;
5009  int total_size_;
5010 };
5011 
5012 
5014  public:
5016  Handle<HeapObject> boilerplate_object,
5017  int length,
5018  int literal_index,
5019  int depth)
5020  : HMaterializedLiteral<1>(literal_index, depth),
5021  length_(length),
5022  boilerplate_object_(boilerplate_object) {
5023  SetOperandAt(0, context);
5024  SetGVNFlag(kChangesNewSpacePromotion);
5025  }
5026 
5027  HValue* context() { return OperandAt(0); }
5029  if (!boilerplate_object_->IsJSObject()) {
5031  }
5032  return Handle<JSObject>::cast(boilerplate_object_)->GetElementsKind();
5033  }
5034  Handle<HeapObject> boilerplate_object() const { return boilerplate_object_; }
5035  int length() const { return length_; }
5036 
5037  bool IsCopyOnWrite() const;
5038 
5040  return Representation::Tagged();
5041  }
5042  virtual HType CalculateInferredType();
5043 
5045 
5046  private:
5047  int length_;
5048  Handle<HeapObject> boilerplate_object_;
5049 };
5050 
5051 
5052 class HObjectLiteral: public HMaterializedLiteral<1> {
5053  public:
5055  Handle<FixedArray> constant_properties,
5056  bool fast_elements,
5057  int literal_index,
5058  int depth,
5059  bool has_function)
5060  : HMaterializedLiteral<1>(literal_index, depth),
5061  constant_properties_(constant_properties),
5062  fast_elements_(fast_elements),
5063  has_function_(has_function) {
5064  SetOperandAt(0, context);
5065  SetGVNFlag(kChangesNewSpacePromotion);
5066  }
5067 
5068  HValue* context() { return OperandAt(0); }
5070  return constant_properties_;
5071  }
5072  bool fast_elements() const { return fast_elements_; }
5073  bool has_function() const { return has_function_; }
5074 
5076  return Representation::Tagged();
5077  }
5078  virtual HType CalculateInferredType();
5079 
5081 
5082  private:
5083  Handle<FixedArray> constant_properties_;
5084  bool fast_elements_;
5085  bool has_function_;
5086 };
5087 
5088 
5089 class HRegExpLiteral: public HMaterializedLiteral<1> {
5090  public:
5092  Handle<FixedArray> literals,
5093  Handle<String> pattern,
5095  int literal_index)
5096  : HMaterializedLiteral<1>(literal_index, 0),
5097  literals_(literals),
5098  pattern_(pattern),
5099  flags_(flags) {
5100  SetOperandAt(0, context);
5102  }
5103 
5104  HValue* context() { return OperandAt(0); }
5105  Handle<FixedArray> literals() { return literals_; }
5106  Handle<String> pattern() { return pattern_; }
5108 
5110  return Representation::Tagged();
5111  }
5112  virtual HType CalculateInferredType();
5113 
5115 
5116  private:
5117  Handle<FixedArray> literals_;
5118  Handle<String> pattern_;
5119  Handle<String> flags_;
5120 };
5121 
5122 
5123 class HFunctionLiteral: public HTemplateInstruction<1> {
5124  public:
5127  bool pretenure)
5128  : shared_info_(shared), pretenure_(pretenure) {
5129  SetOperandAt(0, context);
5131  SetGVNFlag(kChangesNewSpacePromotion);
5132  }
5133 
5134  HValue* context() { return OperandAt(0); }
5135 
5137  return Representation::Tagged();
5138  }
5139  virtual HType CalculateInferredType();
5140 
5142 
5143  Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
5144  bool pretenure() const { return pretenure_; }
5145 
5146  private:
5147  virtual bool IsDeletable() const { return true; }
5148 
5149  Handle<SharedFunctionInfo> shared_info_;
5150  bool pretenure_;
5151 };
5152 
5153 
5154 class HTypeof: public HTemplateInstruction<2> {
5155  public:
5156  explicit HTypeof(HValue* context, HValue* value) {
5157  SetOperandAt(0, context);
5158  SetOperandAt(1, value);
5160  }
5161 
5162  HValue* context() { return OperandAt(0); }
5163  HValue* value() { return OperandAt(1); }
5164 
5165  virtual HValue* Canonicalize();
5166  virtual void PrintDataTo(StringStream* stream);
5167 
5169  return Representation::Tagged();
5170  }
5171 
5173 
5174  private:
5175  virtual bool IsDeletable() const { return true; }
5176 };
5177 
5178 
5180  public:
5181  explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
5182  // This instruction is not marked as having side effects, but
5183  // changes the map of the input operand. Use it only when creating
5184  // object literals.
5185  ASSERT(value->IsObjectLiteral() || value->IsFastLiteral());
5187  }
5188 
5190  return Representation::Tagged();
5191  }
5192 
5193  DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
5194 
5195  private:
5196  virtual bool IsDeletable() const { return true; }
5197 };
5198 
5199 
5200 class HValueOf: public HUnaryOperation {
5201  public:
5202  explicit HValueOf(HValue* value) : HUnaryOperation(value) {
5204  }
5205 
5207  return Representation::Tagged();
5208  }
5209 
5211 
5212  private:
5213  virtual bool IsDeletable() const { return true; }
5214 };
5215 
5216 
5218  public:
5219  HDateField(HValue* date, Smi* index)
5220  : HUnaryOperation(date), index_(index) {
5222  }
5223 
5224  Smi* index() const { return index_; }
5225 
5227  return Representation::Tagged();
5228  }
5229 
5230  DECLARE_CONCRETE_INSTRUCTION(DateField)
5231 
5232  private:
5233  Smi* index_;
5234 };
5235 
5236 
5238  public:
5239  HDeleteProperty(HValue* context, HValue* obj, HValue* key)
5240  : HBinaryOperation(context, obj, key) {
5243  }
5244 
5246  return Representation::Tagged();
5247  }
5248 
5249  virtual HType CalculateInferredType();
5250 
5251  DECLARE_CONCRETE_INSTRUCTION(DeleteProperty)
5252 
5253  HValue* object() { return left(); }
5254  HValue* key() { return right(); }
5255 };
5256 
5257 
5258 class HIn: public HTemplateInstruction<3> {
5259  public:
5260  HIn(HValue* context, HValue* key, HValue* object) {
5261  SetOperandAt(0, context);
5262  SetOperandAt(1, key);
5263  SetOperandAt(2, object);
5266  }
5267 
5268  HValue* context() { return OperandAt(0); }
5269  HValue* key() { return OperandAt(1); }
5270  HValue* object() { return OperandAt(2); }
5271 
5273  return Representation::Tagged();
5274  }
5275 
5277  return HType::Boolean();
5278  }
5279 
5280  virtual void PrintDataTo(StringStream* stream);
5281 
5283 };
5284 
5285 
5286 class HCheckMapValue: public HTemplateInstruction<2> {
5287  public:
5289  HValue* map) {
5290  SetOperandAt(0, value);
5291  SetOperandAt(1, map);
5293  SetFlag(kUseGVN);
5294  SetGVNFlag(kDependsOnMaps);
5295  SetGVNFlag(kDependsOnElementsKind);
5296  }
5297 
5299  return Representation::Tagged();
5300  }
5301 
5302  virtual void PrintDataTo(StringStream* stream);
5303 
5305  return HType::Tagged();
5306  }
5307 
5308  HValue* value() { return OperandAt(0); }
5309  HValue* map() { return OperandAt(1); }
5310 
5311  DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
5312 
5313  protected:
5314  virtual bool DataEquals(HValue* other) {
5315  return true;
5316  }
5317 };
5318 
5319 
5320 class HForInPrepareMap : public HTemplateInstruction<2> {
5321  public:
5323  HValue* object) {
5324  SetOperandAt(0, context);
5325  SetOperandAt(1, object);
5328  }
5329 
5331  return Representation::Tagged();
5332  }
5333 
5334  HValue* context() { return OperandAt(0); }
5335  HValue* enumerable() { return OperandAt(1); }
5336 
5337  virtual void PrintDataTo(StringStream* stream);
5338 
5340  return HType::Tagged();
5341  }
5342 
5343  DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
5344 };
5345 
5346 
5347 class HForInCacheArray : public HTemplateInstruction<2> {
5348  public:
5350  HValue* keys,
5351  int idx) : idx_(idx) {
5352  SetOperandAt(0, enumerable);
5353  SetOperandAt(1, keys);
5355  }
5356 
5358  return Representation::Tagged();
5359  }
5360 
5361  HValue* enumerable() { return OperandAt(0); }
5362  HValue* map() { return OperandAt(1); }
5363  int idx() { return idx_; }
5364 
5366  return index_cache_;
5367  }
5368 
5369  void set_index_cache(HForInCacheArray* index_cache) {
5370  index_cache_ = index_cache;
5371  }
5372 
5373  virtual void PrintDataTo(StringStream* stream);
5374 
5376  return HType::Tagged();
5377  }
5378 
5379  DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
5380 
5381  private:
5382  int idx_;
5383  HForInCacheArray* index_cache_;
5384 };
5385 
5386 
5387 class HLoadFieldByIndex : public HTemplateInstruction<2> {
5388  public:
5390  HValue* index) {
5391  SetOperandAt(0, object);
5392  SetOperandAt(1, index);
5394  }
5395 
5397  return Representation::Tagged();
5398  }
5399 
5400  HValue* object() { return OperandAt(0); }
5401  HValue* index() { return OperandAt(1); }
5402 
5403  virtual void PrintDataTo(StringStream* stream);
5404 
5406  return HType::Tagged();
5407  }
5408 
5409  DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
5410 
5411  private:
5412  virtual bool IsDeletable() const { return true; }
5413 };
5414 
5415 
5416 #undef DECLARE_INSTRUCTION
5417 #undef DECLARE_CONCRETE_INSTRUCTION
5418 
5419 } } // namespace v8::internal
5420 
5421 #endif // V8_HYDROGEN_INSTRUCTIONS_H_
static HPhi * cast(HValue *value)
void SetIndexOffset(uint32_t index_offset)
virtual Representation RequiredInputRepresentation(int index)
HChange(HValue *value, Representation to, bool is_truncating, bool deoptimize_on_undefined)
virtual bool DataEquals(HValue *other)
bool HasObservableSideEffects() const
void set_can_be_minus_zero(bool b)
void CombinedMin(Range *other)
bool deoptimize_on_minus_zero() const
const int kMinInt
Definition: globals.h:211
bool IsSubtypeOf(const HType &other)
virtual Representation RequiredInputRepresentation(int index)
virtual bool IsConvertibleToInteger() const
HMathMinMax(HValue *context, HValue *left, HValue *right, Operation op)
virtual Representation InferredRepresentation()
Handle< String > name() const
Representation GetInputRepresentation() const
HDateField(HValue *date, Smi *index)
Handle< Map > at(int i) const
Definition: ast.h:278
BailoutId ast_id() const
virtual Representation RequiredInputRepresentation(int index)
virtual Range * InferRange(Zone *zone)
Representation GetInputRepresentation() const
GVNFlagSet gvn_flags() const
virtual Representation RequiredInputRepresentation(int index)
HCallKeyed(HValue *context, HValue *key, int argument_count)
HOsrEntry(BailoutId ast_id)
HType Combine(HType other)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
HUnaryMathOperation(HValue *context, HValue *value, BuiltinFunctionId op)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
HCallFunction(HValue *context, HValue *function, int argument_count)
virtual Representation RequiredInputRepresentation(int index)
void InternalSetOperandAt(int i, HValue *value)
HDiv(HValue *context, HValue *left, HValue *right)
virtual bool DataEquals(HValue *other)
void InitializeObservedInputRepresentation(Representation r)
virtual bool IsCommutative() const
static const int kMaxUtf16CodeUnit
Definition: objects.h:7329
virtual Representation RequiredInputRepresentation(int index)
HLoadFieldByIndex(HValue *object, HValue *index)
bool Equals(const HType &other)
virtual HValue * Canonicalize()
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
virtual void SetSideEffectDominator(GVNFlag side_effect, HValue *dominator)
Definition: v8.h:869
HIsNilAndBranch(HValue *value, EqualityKind kind, NilValue nil)
virtual bool DataEquals(HValue *other)
HUseListNode * RemoveUse(HValue *value, int index)
Handle< FixedArray > pairs() const
virtual void SetSideEffectDominator(GVNFlag side_effect, HValue *dominator)
HInstruction * previous() const
virtual Representation RequiredInputRepresentation(int index)
HSuccessorIterator(HControlInstruction *instr)
virtual Representation RequiredInputRepresentation(int index)
Representation from() const
HMathFloorOfDiv(HValue *context, HValue *left, HValue *right)
HTypeofIsAndBranch(HValue *value, Handle< String > type_literal)
HBinaryOperation(HValue *context, HValue *left, HValue *right)
virtual Representation RequiredInputRepresentation(int index)
void CombinedMax(Range *other)
int current_
HInvokeFunction(HValue *context, HValue *function, int argument_count)
HSar(HValue *context, HValue *left, HValue *right)
void Intersect(Range *other)
virtual Representation RequiredInputRepresentation(int index)
HBitwise(Token::Value op, HValue *context, HValue *left, HValue *right)
virtual Representation RequiredInputRepresentation(int index)
InliningKind inlining_kind() const
HBasicBlock * block() const
static bool IsCompareOp(Value op)
Definition: token.h:214
static Handle< T > cast(Handle< S > that)
Definition: handles.h:81
virtual Representation RequiredInputRepresentation(int index)
#define ASSERT_ALLOCATION_DISABLED
HCompareMap(HValue *value, Handle< Map > map, HBasicBlock *true_target, HBasicBlock *false_target)
static Representation Integer32()
Handle< JSGlobalPropertyCell > cell() const
HForInPrepareMap(HValue *context, HValue *object)
virtual Representation RequiredInputRepresentation(int index)
HTransitionElementsKind(HValue *object, Handle< Map > original_map, Handle< Map > transitioned_map)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
Handle< String > name() const
ElementsKind boilerplate_elements_kind() const
virtual LInstruction * CompileToLithium(LChunkBuilder *builder)=0
static HCheckInstanceType * NewIsString(HValue *value, Zone *zone)
virtual Representation RequiredInputRepresentation(int index)
HHasInstanceTypeAndBranch(HValue *value, InstanceType type)
virtual Representation RequiredInputRepresentation(int index)
HUseListNode(HValue *value, int index, HUseListNode *tail)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
static GVNFlagSet AllChangesFlagSet()
HStringCharCodeAt(HValue *context, HValue *string, HValue *index)
bool ReceiverObjectNeedsWriteBarrier(HValue *object, HValue *new_space_dominator)
int int32_t
Definition: unicode.cc:47
#define DECLARE_FLAG(type)
Token::Value op() const
void AssumeRepresentation(Representation r)
virtual Representation RequiredInputRepresentation(int index)
const int kMaxInt
Definition: globals.h:210
HCallGlobal(HValue *context, Handle< String > name, int argument_count)
EqualityKind
Definition: v8.h:145
virtual bool IsCommutative() const
virtual Representation ObservedInputRepresentation(int index)
static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags)
virtual void PrintDataTo(StringStream *stream)
virtual HBasicBlock * SuccessorAt(int i)=0
HCallKnownGlobal(Handle< JSFunction > target, int argument_count)
virtual Representation RequiredInputRepresentation(int index)
static HCheckMaps * NewWithTransitions(HValue *object, Handle< Map > map, Zone *zone)
void AddConstant(int32_t value)
#define ASSERT(condition)
Definition: checks.h:270
Handle< JSObject > prototype() const
bool CanTransitionToMoreGeneralFastElementsKind(ElementsKind elements_kind, bool allow_only_packed)
ToBooleanStub::Types expected_input_types() const
static GVNFlagSet AllDependsOnFlagSet()
HTypeof(HValue *context, HValue *value)
HLoadKeyedFastDoubleElement(HValue *elements, HValue *key, HValue *dependency, HoleCheckMode hole_check_mode=PERFORM_HOLE_CHECK)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
bool Includes(int value) const
virtual void PrintDataTo(StringStream *stream)
HCheckFunction(HValue *value, Handle< JSFunction > function)
HFunctionLiteral(HValue *context, Handle< SharedFunctionInfo > shared, bool pretenure)
virtual HValue * OperandAt(int index) const
HRandom(HValue *global_object)
Range * CopyClearLower(Zone *zone) const
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
HInvokeFunction(HValue *context, HValue *function, Handle< JSFunction > known_function, int argument_count)
virtual bool DataEquals(HValue *other)
static Representation Double()
virtual Representation RequiredInputRepresentation(int index)
bool Equals(const Representation &other)
virtual Representation RequiredInputRepresentation(int index)
bool ContainsAnyOf(const EnumSet &set) const
Definition: utils.h:970
int isnan(double x)
HLoadNamedGeneric(HValue *context, HValue *object, Handle< Object > name)
HStoreKeyedFastElement(HValue *obj, HValue *key, HValue *val, ElementsKind elements_kind=FAST_ELEMENTS)
virtual Representation RequiredInputRepresentation(int index)
HStoreKeyedSpecializedArrayElement(HValue *external_elements, HValue *key, HValue *val, ElementsKind elements_kind)
virtual void SetSuccessorAt(int i, HBasicBlock *block)
Representation representation() const
GVNFlagSet DependsOnFlags() const
virtual Representation RequiredInputRepresentation(int index)
HFastLiteral(HValue *context, Handle< JSObject > boilerplate, int total_size, int literal_index, int depth)
virtual Opcode opcode() const
void set_representation(Representation r)
virtual int argument_count() const
#define DECLARE_OPCODE(type)
HEnterInlined(Handle< JSFunction > closure, int arguments_count, FunctionLiteral *function, CallKind call_kind, InliningKind inlining_kind, Variable *arguments_var, ZoneList< HValue * > *arguments_values)
virtual Representation RequiredInputRepresentation(int index)
void SetIndexOffset(uint32_t index_offset)
virtual Representation RequiredInputRepresentation(int index)
virtual HType CalculateInferredType()
virtual Representation RequiredInputRepresentation(int index)
static HCheckInstanceType * NewIsJSArray(HValue *value, Zone *zone)
HLoadContextSlot(HValue *context, Variable *var)
virtual Representation RequiredInputRepresentation(int index)
HBinaryCall(HValue *first, HValue *second, int argument_count)
GVNFlagSet ObservableChangesFlags() const
HStoreKeyedFastDoubleElement(HValue *elements, HValue *key, HValue *val)
Handle< JSFunction > target() const
#define DECLARE_ABSTRACT_INSTRUCTION(type)
virtual Representation RequiredInputRepresentation(int index)
HInstanceOfKnownGlobal(HValue *context, HValue *left, Handle< JSFunction > right)
HStringAdd(HValue *context, HValue *left, HValue *right)
HDeoptimize(int environment_length, Zone *zone)
static HCheckInstanceType * NewIsSpecObject(HValue *value, Zone *zone)
HAllocateObject(HValue *context, Handle< JSFunction > constructor)
Handle< JSFunction > target() const
#define ADD_FLAG(type)
#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
virtual HType CalculateInferredType()
virtual Representation RequiredInputRepresentation(int index)
HLoadElements(HValue *value, HValue *typecheck)
HStringCharFromCode(HValue *context, HValue *char_code)
void AddNewRange(Range *r, Zone *zone)
virtual int OperandCount()=0
#define UNREACHABLE()
Definition: checks.h:50
virtual Representation RequiredInputRepresentation(int index)
HLoadNamedField(HValue *object, bool is_in_object, int offset)
bool Equals(HValue *other)
virtual void InternalSetOperandAt(int index, HValue *value)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
void PrintRangeTo(StringStream *stream)
HAccessArgumentsAt(HValue *arguments, HValue *length, HValue *index)
EnumSet< GVNFlag > GVNFlagSet
static GVNFlagSet AllSideEffectsFlagSet()
HMod(HValue *context, HValue *left, HValue *right)
virtual Representation RequiredInputRepresentation(int index)
VariableMode mode() const
Definition: variables.h:97
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
bool IsFastPackedElementsKind(ElementsKind kind)
HInstanceOf(HValue *context, HValue *left, HValue *right)
virtual Representation RequiredInputRepresentation(int index)
void PrintChangesTo(StringStream *stream)
virtual Representation RequiredInputRepresentation(int index)
virtual void RepresentationChanged(Representation to)
virtual Representation RequiredInputRepresentation(int index)
static HUnaryOperation * cast(HValue *value)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
Handle< HeapObject > boilerplate_object() const
Handle< String > name() const
NilValue
Definition: v8.h:141
static const int kMinValue
Definition: objects.h:1048
virtual Representation RequiredInputRepresentation(int index)
Range * Copy(Zone *zone) const
HArithmeticBinaryOperation(HValue *context, HValue *left, HValue *right)
virtual Representation InferredRepresentation()
virtual Representation RequiredInputRepresentation(int index)
virtual bool IsConvertibleToInteger() const
const int kPointerSize
Definition: globals.h:220
int length() const
Definition: ast.h:272
bool StoringValueNeedsWriteBarrier(HValue *value)
virtual HValue * OperandAt(int index) const
HForceRepresentation(HValue *value, Representation required_representation)
#define DECLARE_PREDICATE(type)
bool IsDefinedAfter(HBasicBlock *other) const
int GetAssignedIndexAt(int index) const
void ComputeInitialRange(Zone *zone)
HClassOfTestAndBranch(HValue *value, Handle< String > class_name)
HSub(HValue *context, HValue *left, HValue *right)
HCallNamed(HValue *context, Handle< String > name, int argument_count)
HRegExpLiteral(HValue *context, Handle< FixedArray > literals, Handle< String > pattern, Handle< String > flags, int literal_index)
static GVNFlagSet AllObservableSideEffectsFlagSet()
#define GVN_TRACKED_FLAG_LIST(V)
Range * CopyClearUpper(Zone *zone) const
ZoneList< HValue * > * arguments_values()
virtual void PrintDataTo(StringStream *stream)
HArrayLiteral(HValue *context, Handle< HeapObject > boilerplate_object, int length, int literal_index, int depth)
GVNFlagSet ChangesFlags() const
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
virtual bool IsCommutative() const
Handle< JSObject > boilerplate() const
virtual Representation RequiredInputRepresentation(int index)
virtual bool DataEquals(HValue *other)
HInstruction * next() const
void Intersect(const EnumSet &set)
Definition: utils.h:978
virtual bool IsConvertibleToInteger() const
Handle< JSFunction > closure() const
HBranch(HValue *value, HBasicBlock *true_target, HBasicBlock *false_target, ToBooleanStub::Types expected_input_types=ToBooleanStub::no_types())
virtual Representation RequiredInputRepresentation(int index)
bool IsContextSlot() const
Definition: variables.h:119
virtual Representation RequiredInputRepresentation(int index)
HStackCheck(HValue *context, Type type)
static GVNFlag DependsOnFlagFromInt(int x)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
TranscendentalCache::Type transcendental_type()
bool IsFastSmiElementsKind(ElementsKind kind)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
void set_type(HType new_type)
virtual HType CalculateInferredType()
const int kBitsPerByte
Definition: globals.h:237
virtual Representation RequiredInputRepresentation(int index)
bool IsPowerOf2(T x)
Definition: utils.h:50
HCheckMaps(HValue *value, SmallMapList *maps, Zone *zone)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
static Representation External()
#define BASE_EMBEDDED
Definition: allocation.h:68
virtual Representation RequiredInputRepresentation(int index)
HJSArrayLength(HValue *value, HValue *typecheck, HType type=HType::Tagged())
virtual void PrintTo(StringStream *stream)
virtual Representation RequiredInputRepresentation(int index)
const int kBitsPerInt
Definition: globals.h:240
activate correct semantics for inheriting readonliness false
Definition: flags.cc:141
virtual Representation RequiredInputRepresentation(int index)
HStoreKeyedGeneric(HValue *context, HValue *object, HValue *key, HValue *value, StrictModeFlag strict_mode_flag)
void DeleteAndReplaceWith(HValue *other)
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
#define GVN_UNTRACKED_FLAG_LIST(V)
void AddEnvironmentValue(HValue *value, Zone *zone)
virtual Representation RequiredInputRepresentation(int index)
HGlobalReceiver(HValue *global_object)
virtual intptr_t Hashcode()
HLoadGlobalCell(Handle< JSGlobalPropertyCell > cell, PropertyDetails details)
HThrow(HValue *context, HValue *value)
bool SubAndCheckOverflow(Range *other)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
bool IsFastSmiOrObjectElementsKind(ElementsKind kind)
HStoreNamedField(HValue *obj, Handle< String > name, HValue *val, bool in_object, int offset)
virtual HValue * EnsureAndPropagateNotMinusZero(BitVector *visited)
virtual Representation ObservedInputRepresentation(int index)
void PrintNameTo(StringStream *stream)
void set_transcendental_type(TranscendentalCache::Type transcendental_type)
void InsertAfter(HInstruction *previous)
virtual Representation RequiredInputRepresentation(int index)
virtual Opcode opcode() const =0
virtual void DeleteFromGraph()=0
virtual Representation RequiredInputRepresentation(int index)
HDeleteProperty(HValue *context, HValue *obj, HValue *key)
HStringCompareAndBranch(HValue *context, HValue *left, HValue *right, Token::Value token)
virtual void SetSuccessorAt(int i, HBasicBlock *block)=0
Representation to() const
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)=0
void set_transition(Handle< Map > map)
virtual Representation RequiredInputRepresentation(int index)
HIn(HValue *context, HValue *key, HValue *object)
HApplyArguments(HValue *function, HValue *receiver, HValue *length, HValue *elements)
virtual HValue * OperandAt(int index) const
void ChangeRepresentation(Representation r)
void SetSuccessorAt(int i, HBasicBlock *block)
HCheckMapValue(HValue *value, HValue *map)
virtual Representation RequiredInputRepresentation(int index)
bool is_null() const
Definition: handles.h:87
virtual Representation RequiredInputRepresentation(int index)
HShr(HValue *context, HValue *left, HValue *right)
bool Contains(E element) const
Definition: utils.h:969
HMul(HValue *context, HValue *left, HValue *right)
HDeclareGlobals(HValue *context, Handle< FixedArray > pairs, int flags)
HCallConstantFunction(Handle< JSFunction > function, int argument_count)
HStoreNamedGeneric(HValue *context, HValue *object, Handle< String > name, HValue *value, StrictModeFlag strict_mode_flag)
void SetOperandAt(int index, HValue *value)
virtual Range * InferRange(Zone *zone)
bool CheckFlag(Flag f) const
HStoreContextSlot(HValue *context, int slot_index, Mode mode, HValue *value)
virtual Representation RequiredInputRepresentation(int index)
HUnaryCall(HValue *value, int argument_count)
Handle< JSFunction > known_function()
int32_t NumberValueAsInteger32() const
#define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V)
virtual void InternalSetOperandAt(int index, HValue *value)
T ToIntegral() const
Definition: utils.h:979
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction pairs(ARM only)") DEFINE_bool(enable_unaligned_accesses
void InsertBefore(HInstruction *next)
virtual bool DataEquals(HValue *other)
virtual Representation RequiredInputRepresentation(int index)
void set_index_cache(HForInCacheArray *index_cache)
virtual Representation RequiredInputRepresentation(int index)
ElementsKind GetNextMoreGeneralFastElementsKind(ElementsKind elements_kind, bool allow_only_packed)
static HType TypeFromValue(Handle< Object > value)
virtual Representation RequiredInputRepresentation(int index)
HObjectLiteral(HValue *context, Handle< FixedArray > constant_properties, bool fast_elements, int literal_index, int depth, bool has_function)
Range(int32_t lower, int32_t upper)
virtual bool DataEquals(HValue *other)
GVNFlagSet SideEffectFlags() const
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int arg_index)
#define HEAP
Definition: isolate.h:1433
virtual Representation RequiredInputRepresentation(int index)
void AddPushedValue(HValue *value)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property keys(0 means random)" "(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption
virtual Representation RequiredInputRepresentation(int index)
void SetBlock(HBasicBlock *block)
static const int kChangesToDependsFlagsLeftShift
HPhi(int merged_index, Zone *zone)
HStoreGlobalGeneric(HValue *context, HValue *global_object, Handle< Object > name, HValue *value, StrictModeFlag strict_mode_flag)
HCompareIDAndBranch(HValue *left, HValue *right, Token::Value token)
virtual Representation RequiredInputRepresentation(int index)
HCompareConstantEqAndBranch(HValue *left, int right, Token::Value op)
HLoadKeyedGeneric(HValue *context, HValue *obj, HValue *key)
HLoadGlobalGeneric(HValue *context, HValue *global_object, Handle< Object > name, bool for_typeof)
void Sar(int32_t value)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
#define DECLARE_CONCRETE_INSTRUCTION(type)
virtual HValue * OperandAt(int index) const =0
virtual Representation RequiredInputRepresentation(int index)
virtual void InternalSetOperandAt(int index, HValue *value)
virtual Representation RequiredInputRepresentation(int index)
#define COUNT_FLAG(type)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
#define FACTORY
Definition: isolate.h:1434
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
void set_is_convertible_to_integer(bool b)
HShl(HValue *context, HValue *left, HValue *right)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
void Shl(int32_t value)
virtual void RepresentationChanged(Representation to)
virtual Representation RequiredInputRepresentation(int index)
static GVNFlag ChangesFlagFromInt(int x)
bool CheckGVNFlag(GVNFlag f) const
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
const char * Mnemonic() const
HUnaryControlInstruction(HValue *value, HBasicBlock *true_target, HBasicBlock *false_target)
Handle< JSObject > holder() const
virtual bool IsCommutative() const
HGoto(HBasicBlock *target)
virtual HBasicBlock * SuccessorAt(int i)
HCheckPrototypeMaps(Handle< JSObject > prototype, Handle< JSObject > holder)
virtual void PrintTo(StringStream *stream)=0
virtual void InternalSetOperandAt(int index, HValue *value)=0
static const int kMaxLength
Definition: objects.h:7386
void set_tail(HUseListNode *list)
virtual void RepresentationChanged(Representation to)
HLoadKeyedSpecializedArrayElement(HValue *external_elements, HValue *key, HValue *dependency, ElementsKind elements_kind)
static Representation Tagged()
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
void PrintTypeTo(StringStream *stream)
Handle< JSGlobalPropertyCell > cell() const
void StackUpon(Range *other)
HBitwiseBinaryOperation(HValue *context, HValue *left, HValue *right)
Handle< FixedArray > constant_properties() const
HStoreGlobalCell(HValue *value, Handle< JSGlobalPropertyCell > cell, PropertyDetails details)
HCompareGeneric(HValue *context, HValue *left, HValue *right, Token::Value token)
static HCheckInstanceType * NewIsSymbol(HValue *value, Zone *zone)
virtual Range * InferRange(Zone *zone)
void Add(Handle< Map > handle, Zone *zone)
Definition: ast.h:274
signed short int16_t
Definition: unicode.cc:45
HLoadKeyedFastElement(HValue *obj, HValue *key, HValue *dependency, ElementsKind elements_kind=FAST_ELEMENTS)
void Remove(E element)
Definition: utils.h:975
STATIC_ASSERT(kLastFlag< kBitsPerInt)
void AddAssignedValue(int index, HValue *value)
HCheckMaps(HValue *value, Handle< Map > map, Zone *zone, HValue *typecheck=NULL)
HForInCacheArray(HValue *enumerable, HValue *keys, int idx)
void RegisterUse(int index, HValue *new_value)
bool HasAssignedIndexAt(int index) const
virtual Representation RequiredInputRepresentation(int index)
void Union(Range *other)
virtual Representation RequiredInputRepresentation(int index)
void Add(E element)
Definition: utils.h:973
static const int kMaxValue
Definition: objects.h:1050
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
HBoundsCheck(HValue *index, HValue *length, BoundsCheckKeyMode key_mode=DONT_ALLOW_SMI_KEY)
static HValue * cast(HValue *value)
void ReplaceAllUsesWith(HValue *other)
const ZoneList< HValue * > * values() const
void check(i::Vector< const char > string)
virtual Representation RequiredInputRepresentation(int index)
virtual Representation RequiredInputRepresentation(int index)
HHasInstanceTypeAndBranch(HValue *value, InstanceType from, InstanceType to)
virtual bool DataEquals(HValue *other)
bool AddAndCheckOverflow(Range *other)
HSimulate(BailoutId ast_id, int pop_count, Zone *zone)
HWrapReceiver(HValue *receiver, HValue *function)
HCallNew(HValue *context, HValue *constructor, int argument_count)
virtual Representation RequiredInputRepresentation(int index)
bool MulAndCheckOverflow(Range *other)
HAdd(HValue *context, HValue *left, HValue *right)
HCompareObjectEqAndBranch(HValue *left, HValue *right)
HCallStub(HValue *context, CodeStub::Major major_key, int argument_count)
HUseIterator uses() const
static HType TaggedPrimitive()
HCallRuntime(HValue *context, Handle< String > name, const Runtime::Function *c_function, int argument_count)
virtual Representation RequiredInputRepresentation(int index)
HPower(HValue *left, HValue *right)