V8 Project
hydrogen-instructions.h
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_HYDROGEN_INSTRUCTIONS_H_
6 #define V8_HYDROGEN_INSTRUCTIONS_H_
7 
8 #include "src/v8.h"
9 
10 #include "src/allocation.h"
11 #include "src/base/bits.h"
12 #include "src/code-stubs.h"
13 #include "src/conversions.h"
14 #include "src/data-flow.h"
15 #include "src/deoptimizer.h"
16 #include "src/feedback-slots.h"
17 #include "src/hydrogen-types.h"
18 #include "src/small-pointer-list.h"
19 #include "src/unique.h"
20 #include "src/utils.h"
21 #include "src/zone.h"
22 
23 namespace v8 {
24 namespace internal {
25 
26 // Forward declarations.
27 struct ChangesOf;
28 class HBasicBlock;
29 class HDiv;
30 class HEnvironment;
31 class HInferRepresentationPhase;
32 class HInstruction;
33 class HLoopInformation;
34 class HStoreNamedField;
35 class HValue;
36 class LInstruction;
37 class LChunkBuilder;
38 class OStream;
39 
40 #define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V) \
41  V(ArithmeticBinaryOperation) \
42  V(BinaryOperation) \
43  V(BitwiseBinaryOperation) \
44  V(ControlInstruction) \
45  V(Instruction)
46 
47 
48 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
49  V(AbnormalExit) \
50  V(AccessArgumentsAt) \
51  V(Add) \
52  V(AllocateBlockContext) \
53  V(Allocate) \
54  V(ApplyArguments) \
55  V(ArgumentsElements) \
56  V(ArgumentsLength) \
57  V(ArgumentsObject) \
58  V(Bitwise) \
59  V(BlockEntry) \
60  V(BoundsCheck) \
61  V(BoundsCheckBaseIndexInformation) \
62  V(Branch) \
63  V(CallWithDescriptor) \
64  V(CallJSFunction) \
65  V(CallFunction) \
66  V(CallNew) \
67  V(CallNewArray) \
68  V(CallRuntime) \
69  V(CallStub) \
70  V(CapturedObject) \
71  V(Change) \
72  V(CheckHeapObject) \
73  V(CheckInstanceType) \
74  V(CheckMaps) \
75  V(CheckMapValue) \
76  V(CheckSmi) \
77  V(CheckValue) \
78  V(ClampToUint8) \
79  V(ClassOfTestAndBranch) \
80  V(CompareNumericAndBranch) \
81  V(CompareHoleAndBranch) \
82  V(CompareGeneric) \
83  V(CompareMinusZeroAndBranch) \
84  V(CompareObjectEqAndBranch) \
85  V(CompareMap) \
86  V(Constant) \
87  V(ConstructDouble) \
88  V(Context) \
89  V(DateField) \
90  V(DebugBreak) \
91  V(DeclareGlobals) \
92  V(Deoptimize) \
93  V(Div) \
94  V(DoubleBits) \
95  V(DummyUse) \
96  V(EnterInlined) \
97  V(EnvironmentMarker) \
98  V(ForceRepresentation) \
99  V(ForInCacheArray) \
100  V(ForInPrepareMap) \
101  V(FunctionLiteral) \
102  V(GetCachedArrayIndex) \
103  V(Goto) \
104  V(HasCachedArrayIndexAndBranch) \
105  V(HasInstanceTypeAndBranch) \
106  V(InnerAllocatedObject) \
107  V(InstanceOf) \
108  V(InstanceOfKnownGlobal) \
109  V(InvokeFunction) \
110  V(IsConstructCallAndBranch) \
111  V(IsObjectAndBranch) \
112  V(IsStringAndBranch) \
113  V(IsSmiAndBranch) \
114  V(IsUndetectableAndBranch) \
115  V(LeaveInlined) \
116  V(LoadContextSlot) \
117  V(LoadFieldByIndex) \
118  V(LoadFunctionPrototype) \
119  V(LoadGlobalCell) \
120  V(LoadGlobalGeneric) \
121  V(LoadKeyed) \
122  V(LoadKeyedGeneric) \
123  V(LoadNamedField) \
124  V(LoadNamedGeneric) \
125  V(LoadRoot) \
126  V(MapEnumLength) \
127  V(MathFloorOfDiv) \
128  V(MathMinMax) \
129  V(Mod) \
130  V(Mul) \
131  V(OsrEntry) \
132  V(Parameter) \
133  V(Power) \
134  V(PushArguments) \
135  V(RegExpLiteral) \
136  V(Return) \
137  V(Ror) \
138  V(Sar) \
139  V(SeqStringGetChar) \
140  V(SeqStringSetChar) \
141  V(Shl) \
142  V(Shr) \
143  V(Simulate) \
144  V(StackCheck) \
145  V(StoreCodeEntry) \
146  V(StoreContextSlot) \
147  V(StoreFrameContext) \
148  V(StoreGlobalCell) \
149  V(StoreKeyed) \
150  V(StoreKeyedGeneric) \
151  V(StoreNamedField) \
152  V(StoreNamedGeneric) \
153  V(StringAdd) \
154  V(StringCharCodeAt) \
155  V(StringCharFromCode) \
156  V(StringCompareAndBranch) \
157  V(Sub) \
158  V(TailCallThroughMegamorphicCache) \
159  V(ThisFunction) \
160  V(ToFastProperties) \
161  V(TransitionElementsKind) \
162  V(TrapAllocationMemento) \
163  V(Typeof) \
164  V(TypeofIsAndBranch) \
165  V(UnaryMathOperation) \
166  V(UnknownOSRValue) \
167  V(UseConst) \
168  V(WrapReceiver)
169 
170 #define GVN_TRACKED_FLAG_LIST(V) \
171  V(NewSpacePromotion)
172 
173 #define GVN_UNTRACKED_FLAG_LIST(V) \
174  V(ArrayElements) \
175  V(ArrayLengths) \
176  V(StringLengths) \
177  V(BackingStoreFields) \
178  V(Calls) \
179  V(ContextSlots) \
180  V(DoubleArrayElements) \
181  V(DoubleFields) \
182  V(ElementsKind) \
183  V(ElementsPointer) \
184  V(GlobalVars) \
185  V(InobjectFields) \
186  V(Maps) \
187  V(OsrEntries) \
188  V(ExternalMemory) \
189  V(StringChars) \
190  V(TypedArrayElements)
191 
192 
193 #define DECLARE_ABSTRACT_INSTRUCTION(type) \
194  virtual bool Is##type() const FINAL OVERRIDE { return true; } \
195  static H##type* cast(HValue* value) { \
196  DCHECK(value->Is##type()); \
197  return reinterpret_cast<H##type*>(value); \
198  }
199 
200 
201 #define DECLARE_CONCRETE_INSTRUCTION(type) \
202  virtual LInstruction* CompileToLithium( \
203  LChunkBuilder* builder) FINAL OVERRIDE; \
204  static H##type* cast(HValue* value) { \
205  DCHECK(value->Is##type()); \
206  return reinterpret_cast<H##type*>(value); \
207  } \
208  virtual Opcode opcode() const FINAL OVERRIDE { \
209  return HValue::k##type; \
210  }
211 
212 
214 
215 
216 class Range FINAL : public ZoneObject {
217  public:
219  : lower_(kMinInt),
220  upper_(kMaxInt),
221  next_(NULL),
222  can_be_minus_zero_(false) { }
223 
224  Range(int32_t lower, int32_t upper)
225  : lower_(lower),
226  upper_(upper),
227  next_(NULL),
228  can_be_minus_zero_(false) { }
229 
230  int32_t upper() const { return upper_; }
231  int32_t lower() const { return lower_; }
232  Range* next() const { return next_; }
233  Range* CopyClearLower(Zone* zone) const {
234  return new(zone) Range(kMinInt, upper_);
235  }
236  Range* CopyClearUpper(Zone* zone) const {
237  return new(zone) Range(lower_, kMaxInt);
238  }
239  Range* Copy(Zone* zone) const {
240  Range* result = new(zone) Range(lower_, upper_);
241  result->set_can_be_minus_zero(CanBeMinusZero());
242  return result;
243  }
244  int32_t Mask() const;
245  void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
246  bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
247  bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
248  bool CanBeNegative() const { return lower_ < 0; }
249  bool CanBePositive() const { return upper_ > 0; }
250  bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
251  bool IsMostGeneric() const {
252  return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
253  }
254  bool IsInSmiRange() const {
255  return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
256  }
257  void ClampToSmi() {
258  lower_ = Max(lower_, Smi::kMinValue);
259  upper_ = Min(upper_, Smi::kMaxValue);
260  }
261  void KeepOrder();
262 #ifdef DEBUG
263  void Verify() const;
264 #endif
265 
266  void StackUpon(Range* other) {
267  Intersect(other);
268  next_ = other;
269  }
270 
271  void Intersect(Range* other);
272  void Union(Range* other);
273  void CombinedMax(Range* other);
274  void CombinedMin(Range* other);
275 
276  void AddConstant(int32_t value);
277  void Sar(int32_t value);
278  void Shl(int32_t value);
279  bool AddAndCheckOverflow(const Representation& r, Range* other);
280  bool SubAndCheckOverflow(const Representation& r, Range* other);
281  bool MulAndCheckOverflow(const Representation& r, Range* other);
282 
283  private:
286  Range* next_;
288 };
289 
290 
291 class HUseListNode: public ZoneObject {
292  public:
294  : tail_(tail), value_(value), index_(index) {
295  }
296 
297  HUseListNode* tail();
298  HValue* value() const { return value_; }
299  int index() const { return index_; }
300 
301  void set_tail(HUseListNode* list) { tail_ = list; }
302 
303 #ifdef DEBUG
304  void Zap() {
305  tail_ = reinterpret_cast<HUseListNode*>(1);
306  value_ = NULL;
307  index_ = -1;
308  }
309 #endif
310 
311  private:
314  int index_;
315 };
316 
317 
318 // We reuse use list nodes behind the scenes as uses are added and deleted.
319 // This class is the safe way to iterate uses while deleting them.
320 class HUseIterator FINAL BASE_EMBEDDED {
321  public:
322  bool Done() { return current_ == NULL; }
323  void Advance();
324 
326  DCHECK(!Done());
327  return value_;
328  }
329 
330  int index() {
331  DCHECK(!Done());
332  return index_;
333  }
334 
335  private:
336  explicit HUseIterator(HUseListNode* head);
337 
341  int index_;
342 
343  friend class HValue;
344 };
345 
346 
347 // All tracked flags should appear before untracked ones.
348 enum GVNFlag {
349  // Declare global value numbering flags.
350 #define DECLARE_FLAG(Type) k##Type,
353 #undef DECLARE_FLAG
354 #define COUNT_FLAG(Type) + 1
357 #undef COUNT_FLAG
359 };
360 
361 
362 static inline GVNFlag GVNFlagFromInt(int i) {
363  DCHECK(i >= 0);
365  return static_cast<GVNFlag>(i);
366 }
367 
368 
369 class DecompositionResult FINAL BASE_EMBEDDED {
370  public:
371  DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
372 
373  HValue* base() { return base_; }
374  int offset() { return offset_; }
375  int scale() { return scale_; }
376 
377  bool Apply(HValue* other_base, int other_offset, int other_scale = 0) {
378  if (base_ == NULL) {
379  base_ = other_base;
380  offset_ = other_offset;
381  scale_ = other_scale;
382  return true;
383  } else {
384  if (scale_ == 0) {
385  base_ = other_base;
386  offset_ += other_offset;
387  scale_ = other_scale;
388  return true;
389  } else {
390  return false;
391  }
392  }
393  }
394 
395  void SwapValues(HValue** other_base, int* other_offset, int* other_scale) {
396  swap(&base_, other_base);
397  swap(&offset_, other_offset);
398  swap(&scale_, other_scale);
399  }
400 
401  private:
402  template <class T> void swap(T* a, T* b) {
403  T c(*a);
404  *a = *b;
405  *b = c;
406  }
407 
409  int offset_;
410  int scale_;
411 };
412 
413 
415 
416 
417 // This class encapsulates encoding and decoding of sources positions from
418 // which hydrogen values originated.
419 // When FLAG_track_hydrogen_positions is set this object encodes the
420 // identifier of the inlining and absolute offset from the start of the
421 // inlined function.
422 // When the flag is not set we simply track absolute offset from the
423 // script start.
425  public:
426  HSourcePosition(const HSourcePosition& other) : value_(other.value_) { }
427 
430  }
431 
432  bool IsUnknown() const { return value_ == RelocInfo::kNoPosition; }
433 
434  int position() const { return PositionField::decode(value_); }
435  void set_position(int position) {
436  if (FLAG_hydrogen_track_positions) {
437  value_ = static_cast<int>(PositionField::update(value_, position));
438  } else {
439  value_ = position;
440  }
441  }
442 
443  int inlining_id() const { return InliningIdField::decode(value_); }
445  if (FLAG_hydrogen_track_positions) {
446  value_ = static_cast<int>(InliningIdField::update(value_, inlining_id));
447  }
448  }
449 
450  int raw() const { return value_; }
451 
452  private:
454 
455  // Offset from the start of the inlined function.
457 
458  explicit HSourcePosition(int value) : value_(value) { }
459 
460  friend class HPositionInfo;
461  friend class LCodeGenBase;
462 
463  // If FLAG_hydrogen_track_positions is set contains bitfields InliningIdField
464  // and PositionField.
465  // Otherwise contains absolute offset from the script start.
466  int value_;
467 };
468 
469 
470 OStream& operator<<(OStream& os, const HSourcePosition& p);
471 
472 
473 class HValue : public ZoneObject {
474  public:
475  static const int kNoNumber = -1;
476 
477  enum Flag {
480  // Participate in Global Value Numbering, i.e. elimination of
481  // unnecessary recomputations. If an instruction sets this flag, it must
482  // implement DataEquals(), which will be used to determine if other
483  // occurrences of the instruction are indeed the same.
485  // Track instructions that are dominating side effects. If an instruction
486  // sets this flag, it must implement HandleSideEffectDominator() and should
487  // indicate which side effects to track by setting GVN flags.
501  // Set after an instruction is killed.
503  // Instructions that are allowed to produce full range unsigned integer
504  // values are marked with kUint32 flag. If arithmetic shift or a load from
505  // EXTERNAL_UINT32_ELEMENTS array is not marked with this flag
506  // it will deoptimize if result does not fit into signed integer range.
507  // HGraph::ComputeSafeUint32Operations is responsible for setting this
508  // flag.
511  // Indicates an instruction shouldn't be replaced by optimization, this flag
512  // is useful to set in cases where recomputing a value is cheaper than
513  // extending the value's live range and spilling it.
515  // Indicates the instruction is live during dead code elimination.
517 
518  // HEnvironmentMarkers are deleted before dead code
519  // elimination takes place, so they can repurpose the kIsLive flag:
521 
522  // TODO(everyone): Don't forget to update this!
524  };
525 
527 
528  static HValue* cast(HValue* value) { return value; }
529 
530  enum Opcode {
531  // Declare a unique enum value for each hydrogen instruction.
532  #define DECLARE_OPCODE(type) k##type,
534  kPhi
535  #undef DECLARE_OPCODE
536  };
537  virtual Opcode opcode() const = 0;
538 
539  // Declare a non-virtual predicates for each concrete HInstruction or HValue.
540  #define DECLARE_PREDICATE(type) \
541  bool Is##type() const { return opcode() == k##type; }
543  #undef DECLARE_PREDICATE
544  bool IsPhi() const { return opcode() == kPhi; }
545 
546  // Declare virtual predicates for abstract HInstruction or HValue
547  #define DECLARE_PREDICATE(type) \
548  virtual bool Is##type() const { return false; }
550  #undef DECLARE_PREDICATE
551 
553  return IsShl() || IsShr() || IsSar();
554  }
555 
556  explicit HValue(HType type = HType::Tagged())
557  : block_(NULL),
558  id_(kNoNumber),
559  type_(type),
560  use_list_(NULL),
561  range_(NULL),
562 #ifdef DEBUG
563  range_poisoned_(false),
564 #endif
565  flags_(0) {}
566  virtual ~HValue() {}
567 
568  virtual HSourcePosition position() const {
569  return HSourcePosition::Unknown();
570  }
571  virtual HSourcePosition operand_position(int index) const {
572  return position();
573  }
574 
575  HBasicBlock* block() const { return block_; }
576  void SetBlock(HBasicBlock* block);
577 
578  // Note: Never call this method for an unlinked value.
579  Isolate* isolate() const;
580 
581  int id() const { return id_; }
582  void set_id(int id) { id_ = id; }
583 
584  HUseIterator uses() const { return HUseIterator(use_list_); }
585 
586  virtual bool EmitAtUses() { return false; }
587 
593  representation_ = r;
594  if (r.IsTagged()) {
595  // Tagged is the bottom of the lattice, don't go any further.
597  }
598  }
599  virtual void AssumeRepresentation(Representation r);
600 
603  if (r.IsTagged()) {
604  HType t = type();
605  if (t.IsSmi()) return Representation::Smi();
606  if (t.IsHeapNumber()) return Representation::Double();
607  if (t.IsHeapObject()) return r;
608  return Representation::None();
609  }
610  return r;
611  }
612 
613  HType type() const { return type_; }
614  void set_type(HType new_type) {
615  DCHECK(new_type.IsSubtypeOf(type_));
616  type_ = new_type;
617  }
618 
619  // There are HInstructions that do not really change a value, they
620  // only add pieces of information to it (like bounds checks, map checks,
621  // smi checks...).
622  // We call these instructions "informative definitions", or "iDef".
623  // One of the iDef operands is special because it is the value that is
624  // "transferred" to the output, we call it the "redefined operand".
625  // If an HValue is an iDef it must override RedefinedOperandIndex() so that
626  // it does not return kNoRedefinedOperand;
627  static const int kNoRedefinedOperand = -1;
628  virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
631  }
633  int index = RedefinedOperandIndex();
634  return index == kNoRedefinedOperand ? NULL : OperandAt(index);
635  }
636 
638 
639  virtual int argument_delta() const { return 0; }
640 
641  // A purely informative definition is an idef that will not emit code and
642  // should therefore be removed from the graph in the RestoreActualValues
643  // phase (so that live ranges will be shorter).
644  virtual bool IsPurelyInformativeDefinition() { return false; }
645 
646  // This method must always return the original HValue SSA definition,
647  // regardless of any chain of iDefs of this value.
649  HValue* value = this;
650  int index;
651  while ((index = value->RedefinedOperandIndex()) != kNoRedefinedOperand) {
652  value = value->OperandAt(index);
653  }
654  return value;
655  }
656 
657  bool IsInteger32Constant();
659  bool EqualsInteger32Constant(int32_t value);
660 
661  bool IsDefinedAfter(HBasicBlock* other) const;
662 
663  // Operands.
664  virtual int OperandCount() const = 0;
665  virtual HValue* OperandAt(int index) const = 0;
666  void SetOperandAt(int index, HValue* value);
667 
668  void DeleteAndReplaceWith(HValue* other);
669  void ReplaceAllUsesWith(HValue* other);
670  bool HasNoUses() const { return use_list_ == NULL; }
671  bool HasOneUse() const {
672  return use_list_ != NULL && use_list_->tail() == NULL;
673  }
674  bool HasMultipleUses() const {
675  return use_list_ != NULL && use_list_->tail() != NULL;
676  }
677  int UseCount() const;
678 
679  // Mark this HValue as dead and to be removed from other HValues' use lists.
680  void Kill();
681 
682  int flags() const { return flags_; }
683  void SetFlag(Flag f) { flags_ |= (1 << f); }
684  void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
685  bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
686  void CopyFlag(Flag f, HValue* other) {
687  if (other->CheckFlag(f)) SetFlag(f);
688  }
689 
690  // Returns true if the flag specified is set for all uses, false otherwise.
691  bool CheckUsesForFlag(Flag f) const;
692  // Same as before and the first one without the flag is returned in value.
693  bool CheckUsesForFlag(Flag f, HValue** value) const;
694  // Returns true if the flag specified is set for all uses, and this set
695  // of uses is non-empty.
697 
704  bool CheckChangesFlag(GVNFlag f) const {
705  return changes_flags_.Contains(f);
706  }
707  bool CheckDependsOnFlag(GVNFlag f) const {
708  return depends_on_flags_.Contains(f);
709  }
713  }
714  bool HasSideEffects() const {
716  }
720  }
721 
723  GVNFlagSet result = ChangesFlags();
725  return result;
726  }
727 
729  GVNFlagSet result = ChangesFlags();
731  return result;
732  }
733 
734  Range* range() const {
735  DCHECK(!range_poisoned_);
736  return range_;
737  }
738  bool HasRange() const {
739  DCHECK(!range_poisoned_);
740  return range_ != NULL;
741  }
742 #ifdef DEBUG
743  void PoisonRange() { range_poisoned_ = true; }
744 #endif
745  void AddNewRange(Range* r, Zone* zone);
746  void RemoveLastAddedRange();
747  void ComputeInitialRange(Zone* zone);
748 
749  // Escape analysis helpers.
750  virtual bool HasEscapingOperandAt(int index) { return true; }
751  virtual bool HasOutOfBoundsAccess(int size) { return false; }
752 
753  // Representation helpers.
755  return Representation::None();
756  }
758  virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
759 
760  // This gives the instruction an opportunity to replace itself with an
761  // instruction that does the same in some better way. To replace an
762  // instruction with a new one, first add the new instruction to the graph,
763  // then return it. Return NULL to have the instruction deleted.
764  virtual HValue* Canonicalize() { return this; }
765 
766  bool Equals(HValue* other);
767  virtual intptr_t Hashcode();
768 
769  // Compute unique ids upfront that is safe wrt GC and concurrent compilation.
770  virtual void FinalizeUniqueness() { }
771 
772  // Printing support.
773  virtual OStream& PrintTo(OStream& os) const = 0; // NOLINT
774 
775  const char* Mnemonic() const;
776 
777  // Type information helpers.
779 
780  // TODO(mstarzinger): For now instructions can override this function to
781  // specify statically known types, once HType can convey more information
782  // it should be based on the HType.
784 
785  // Updated the inferred type of this instruction and returns true if
786  // it has changed.
787  bool UpdateInferredType();
788 
789  virtual HType CalculateInferredType();
790 
791  // This function must be overridden for instructions which have the
792  // kTrackSideEffectDominators flag set, to track instructions that are
793  // dominating side effects.
794  // It returns true if it removed an instruction which had side effects.
795  virtual bool HandleSideEffectDominator(GVNFlag side_effect,
796  HValue* dominator) {
797  UNREACHABLE();
798  return false;
799  }
800 
801  // Check if this instruction has some reason that prevents elimination.
802  bool CannotBeEliminated() const {
803  return HasObservableSideEffects() || !IsDeletable();
804  }
805 
806 #ifdef DEBUG
807  virtual void Verify() = 0;
808 #endif
809 
810  virtual bool TryDecompose(DecompositionResult* decomposition) {
811  if (RedefinedOperand() != NULL) {
812  return RedefinedOperand()->TryDecompose(decomposition);
813  } else {
814  return false;
815  }
816  }
817 
818  // Returns true conservatively if the program might be able to observe a
819  // ToString() operation on this value.
820  bool ToStringCanBeObserved() const {
822  }
823 
824  // Returns true conservatively if the program might be able to observe a
825  // ToNumber() operation on this value.
826  bool ToNumberCanBeObserved() const {
828  }
829 
833  }
834 
835  protected:
836  // This function must be overridden for instructions with flag kUseGVN, to
837  // compare the non-Operand parts of the instruction.
838  virtual bool DataEquals(HValue* other) {
839  UNREACHABLE();
840  return false;
841  }
842 
844  if (type().IsTaggedPrimitive()) return false;
845  if (type().IsJSObject()) return true;
847  }
848 
850  return representation();
851  }
854  bool HasNonSmiUse();
855  virtual void UpdateRepresentation(Representation new_rep,
856  HInferRepresentationPhase* h_infer,
857  const char* reason);
859 
861 
862  virtual Range* InferRange(Zone* zone);
863  virtual void DeleteFromGraph() = 0;
864  virtual void InternalSetOperandAt(int index, HValue* value) = 0;
865  void clear_block() {
866  DCHECK(block_ != NULL);
867  block_ = NULL;
868  }
869 
871  DCHECK(representation_.IsNone() && !r.IsNone());
872  representation_ = r;
873  }
874 
876  GVNFlagSet result;
877 #define ADD_FLAG(Type) result.Add(k##Type);
880 #undef ADD_FLAG
881  return result;
882  }
883 
884  // A flag mask to mark an instruction as having arbitrary side effects.
886  GVNFlagSet result = AllFlagSet();
887  result.Remove(kOsrEntries);
888  return result;
889  }
890  friend OStream& operator<<(OStream& os, const ChangesOf& v);
891 
892  // A flag mask of all side effects that can make observable changes in
893  // an executing program (i.e. are not safe to repeat, move or remove);
895  GVNFlagSet result = AllFlagSet();
896  result.Remove(kNewSpacePromotion);
897  result.Remove(kElementsKind);
898  result.Remove(kElementsPointer);
899  result.Remove(kMaps);
900  return result;
901  }
902 
903  // Remove the matching use from the use list if present. Returns the
904  // removed list node or NULL.
905  HUseListNode* RemoveUse(HValue* value, int index);
906 
907  void RegisterUse(int index, HValue* new_value);
908 
909  HBasicBlock* block_;
910 
911  // The id of this instruction in the hydrogen graph, assigned when first
912  // added to the graph. Reflects creation order.
913  int id_;
914 
916  HType type_;
918  Range* range_;
919 #ifdef DEBUG
920  bool range_poisoned_;
921 #endif
922  int flags_;
925 
926  private:
927  virtual bool IsDeletable() const { return false; }
928 
930 };
931 
932 // Support for printing various aspects of an HValue.
933 struct NameOf {
934  explicit NameOf(const HValue* const v) : value(v) {}
935  const HValue* value;
936 };
937 
938 
939 struct TypeOf {
940  explicit TypeOf(const HValue* const v) : value(v) {}
941  const HValue* value;
942 };
943 
944 
945 struct ChangesOf {
946  explicit ChangesOf(const HValue* const v) : value(v) {}
947  const HValue* value;
948 };
949 
950 
951 OStream& operator<<(OStream& os, const HValue& v);
952 OStream& operator<<(OStream& os, const NameOf& v);
953 OStream& operator<<(OStream& os, const TypeOf& v);
954 OStream& operator<<(OStream& os, const ChangesOf& v);
955 
956 
957 #define DECLARE_INSTRUCTION_FACTORY_P0(I) \
958  static I* New(Zone* zone, HValue* context) { \
959  return new(zone) I(); \
960 }
961 
962 #define DECLARE_INSTRUCTION_FACTORY_P1(I, P1) \
963  static I* New(Zone* zone, HValue* context, P1 p1) { \
964  return new(zone) I(p1); \
965  }
966 
967 #define DECLARE_INSTRUCTION_FACTORY_P2(I, P1, P2) \
968  static I* New(Zone* zone, HValue* context, P1 p1, P2 p2) { \
969  return new(zone) I(p1, p2); \
970  }
971 
972 #define DECLARE_INSTRUCTION_FACTORY_P3(I, P1, P2, P3) \
973  static I* New(Zone* zone, HValue* context, P1 p1, P2 p2, P3 p3) { \
974  return new(zone) I(p1, p2, p3); \
975  }
976 
977 #define DECLARE_INSTRUCTION_FACTORY_P4(I, P1, P2, P3, P4) \
978  static I* New(Zone* zone, \
979  HValue* context, \
980  P1 p1, \
981  P2 p2, \
982  P3 p3, \
983  P4 p4) { \
984  return new(zone) I(p1, p2, p3, p4); \
985  }
986 
987 #define DECLARE_INSTRUCTION_FACTORY_P5(I, P1, P2, P3, P4, P5) \
988  static I* New(Zone* zone, \
989  HValue* context, \
990  P1 p1, \
991  P2 p2, \
992  P3 p3, \
993  P4 p4, \
994  P5 p5) { \
995  return new(zone) I(p1, p2, p3, p4, p5); \
996  }
997 
998 #define DECLARE_INSTRUCTION_FACTORY_P6(I, P1, P2, P3, P4, P5, P6) \
999  static I* New(Zone* zone, \
1000  HValue* context, \
1001  P1 p1, \
1002  P2 p2, \
1003  P3 p3, \
1004  P4 p4, \
1005  P5 p5, \
1006  P6 p6) { \
1007  return new(zone) I(p1, p2, p3, p4, p5, p6); \
1008  }
1009 
1010 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(I) \
1011  static I* New(Zone* zone, HValue* context) { \
1012  return new(zone) I(context); \
1013  }
1014 
1015 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(I, P1) \
1016  static I* New(Zone* zone, HValue* context, P1 p1) { \
1017  return new(zone) I(context, p1); \
1018  }
1019 
1020 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(I, P1, P2) \
1021  static I* New(Zone* zone, HValue* context, P1 p1, P2 p2) { \
1022  return new(zone) I(context, p1, p2); \
1023  }
1024 
1025 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(I, P1, P2, P3) \
1026  static I* New(Zone* zone, HValue* context, P1 p1, P2 p2, P3 p3) { \
1027  return new(zone) I(context, p1, p2, p3); \
1028  }
1029 
1030 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(I, P1, P2, P3, P4) \
1031  static I* New(Zone* zone, \
1032  HValue* context, \
1033  P1 p1, \
1034  P2 p2, \
1035  P3 p3, \
1036  P4 p4) { \
1037  return new(zone) I(context, p1, p2, p3, p4); \
1038  }
1039 
1040 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(I, P1, P2, P3, P4, P5) \
1041  static I* New(Zone* zone, \
1042  HValue* context, \
1043  P1 p1, \
1044  P2 p2, \
1045  P3 p3, \
1046  P4 p4, \
1047  P5 p5) { \
1048  return new(zone) I(context, p1, p2, p3, p4, p5); \
1049  }
1050 
1051 
1052 // A helper class to represent per-operand position information attached to
1053 // the HInstruction in the compact form. Uses tagging to distinguish between
1054 // case when only instruction's position is available and case when operands'
1055 // positions are also available.
1056 // In the first case it contains intruction's position as a tagged value.
1057 // In the second case it points to an array which contains instruction's
1058 // position and operands' positions.
1060  public:
1061  explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { }
1062 
1064  if (has_operand_positions()) {
1066  }
1067  return HSourcePosition(static_cast<int>(UntagPosition(data_)));
1068  }
1069 
1071  if (has_operand_positions()) {
1073  } else {
1074  data_ = TagPosition(pos.raw());
1075  }
1076  }
1077 
1078  void ensure_storage_for_operand_positions(Zone* zone, int operand_count) {
1079  if (has_operand_positions()) {
1080  return;
1081  }
1082 
1083  const int length = kFirstOperandPosIndex + operand_count;
1084  HSourcePosition* positions =
1085  zone->NewArray<HSourcePosition>(length);
1086  for (int i = 0; i < length; i++) {
1087  positions[i] = HSourcePosition::Unknown();
1088  }
1089 
1090  const HSourcePosition pos = position();
1091  data_ = reinterpret_cast<intptr_t>(positions);
1092  set_position(pos);
1093 
1095  }
1096 
1098  if (!has_operand_positions()) {
1099  return position();
1100  }
1101  return *operand_position_slot(idx);
1102  }
1103 
1105  *operand_position_slot(idx) = pos;
1106  }
1107 
1108  private:
1109  static const intptr_t kInstructionPosIndex = 0;
1110  static const intptr_t kFirstOperandPosIndex = 1;
1111 
1114  return &(operand_positions()[kFirstOperandPosIndex + idx]);
1115  }
1116 
1117  bool has_operand_positions() const {
1118  return !IsTaggedPosition(data_);
1119  }
1120 
1123  return reinterpret_cast<HSourcePosition*>(data_);
1124  }
1125 
1126  static const intptr_t kPositionTag = 1;
1127  static const intptr_t kPositionShift = 1;
1128  static bool IsTaggedPosition(intptr_t val) {
1129  return (val & kPositionTag) != 0;
1130  }
1131  static intptr_t UntagPosition(intptr_t val) {
1132  DCHECK(IsTaggedPosition(val));
1133  return val >> kPositionShift;
1134  }
1135  static intptr_t TagPosition(intptr_t val) {
1136  const intptr_t result = (val << kPositionShift) | kPositionTag;
1137  DCHECK(UntagPosition(result) == val);
1138  return result;
1139  }
1140 
1141  intptr_t data_;
1142 };
1143 
1144 
1145 class HInstruction : public HValue {
1146  public:
1147  HInstruction* next() const { return next_; }
1148  HInstruction* previous() const { return previous_; }
1149 
1150  virtual OStream& PrintTo(OStream& os) const OVERRIDE; // NOLINT
1151  virtual OStream& PrintDataTo(OStream& os) const; // NOLINT
1152 
1153  bool IsLinked() const { return block() != NULL; }
1154  void Unlink();
1155 
1157 
1158  template<class T> T* Prepend(T* instr) {
1159  instr->InsertBefore(this);
1160  return instr;
1161  }
1162 
1164 
1165  template<class T> T* Append(T* instr) {
1166  instr->InsertAfter(this);
1167  return instr;
1168  }
1169 
1170  // The position is a write-once variable.
1173  }
1174  bool has_position() const {
1175  return !position().IsUnknown();
1176  }
1178  DCHECK(!has_position());
1181  }
1182 
1183  virtual HSourcePosition operand_position(int index) const OVERRIDE {
1184  const HSourcePosition pos = position_.operand_position(index);
1185  return pos.IsUnknown() ? position() : pos;
1186  }
1187  void set_operand_position(Zone* zone, int index, HSourcePosition pos) {
1188  DCHECK(0 <= index && index < OperandCount());
1190  position_.set_operand_position(index, pos);
1191  }
1192 
1193  bool Dominates(HInstruction* other);
1194  bool CanTruncateToSmi() const { return CheckFlag(kTruncatingToSmi); }
1196 
1197  virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
1198 
1199 #ifdef DEBUG
1200  virtual void Verify() OVERRIDE;
1201 #endif
1202 
1203  bool CanDeoptimize();
1204 
1205  virtual bool HasStackCheck() { return false; }
1206 
1208 
1209  protected:
1210  explicit HInstruction(HType type = HType::Tagged())
1211  : HValue(type),
1212  next_(NULL),
1213  previous_(NULL),
1214  position_(RelocInfo::kNoPosition) {
1215  SetDependsOnFlag(kOsrEntries);
1216  }
1217 
1218  virtual void DeleteFromGraph() OVERRIDE { Unlink(); }
1219 
1220  private:
1222  DCHECK(!IsLinked());
1223  SetBlock(block);
1224  }
1225 
1229 
1230  friend class HBasicBlock;
1231 };
1232 
1233 
1234 template<int V>
1236  public:
1237  virtual int OperandCount() const FINAL OVERRIDE { return V; }
1238  virtual HValue* OperandAt(int i) const FINAL OVERRIDE {
1239  return inputs_[i];
1240  }
1241 
1242  protected:
1243  explicit HTemplateInstruction(HType type = HType::Tagged())
1244  : HInstruction(type) {}
1245 
1246  virtual void InternalSetOperandAt(int i, HValue* value) FINAL OVERRIDE {
1247  inputs_[i] = value;
1248  }
1249 
1250  private:
1252 };
1253 
1254 
1256  public:
1257  virtual HBasicBlock* SuccessorAt(int i) const = 0;
1258  virtual int SuccessorCount() const = 0;
1259  virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
1260 
1261  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1262 
1264  *block = NULL;
1265  return false;
1266  }
1267 
1269  return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
1270  }
1272  return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
1273  }
1274 
1275  void Not() {
1276  HBasicBlock* swap = SuccessorAt(0);
1277  SetSuccessorAt(0, SuccessorAt(1));
1278  SetSuccessorAt(1, swap);
1279  }
1280 
1281  DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
1282 };
1283 
1284 
1285 class HSuccessorIterator FINAL BASE_EMBEDDED {
1286  public:
1288  : instr_(instr), current_(0) {}
1289 
1290  bool Done() { return current_ >= instr_->SuccessorCount(); }
1291  HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
1292  void Advance() { current_++; }
1293 
1294  private:
1297 };
1298 
1299 
1300 template<int S, int V>
1302  public:
1303  int SuccessorCount() const OVERRIDE { return S; }
1304  HBasicBlock* SuccessorAt(int i) const OVERRIDE { return successors_[i]; }
1306  successors_[i] = block;
1307  }
1308 
1309  int OperandCount() const OVERRIDE { return V; }
1310  HValue* OperandAt(int i) const OVERRIDE { return inputs_[i]; }
1311 
1312 
1313  protected:
1315  inputs_[i] = value;
1316  }
1317 
1318  private:
1321 };
1322 
1323 
1324 class HBlockEntry FINAL : public HTemplateInstruction<0> {
1325  public:
1327  return Representation::None();
1328  }
1329 
1330  DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
1331 };
1332 
1333 
1334 class HDummyUse FINAL : public HTemplateInstruction<1> {
1335  public:
1336  explicit HDummyUse(HValue* value)
1337  : HTemplateInstruction<1>(HType::Smi()) {
1338  SetOperandAt(0, value);
1339  // Pretend to be a Smi so that the HChange instructions inserted
1340  // before any use generate as little code as possible.
1341  set_representation(Representation::Tagged());
1342  }
1343 
1344  HValue* value() const { return OperandAt(0); }
1345 
1346  virtual bool HasEscapingOperandAt(int index) OVERRIDE { return false; }
1348  return Representation::None();
1349  }
1350 
1351  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1352 
1354 };
1355 
1356 
1357 // Inserts an int3/stop break instruction for debugging purposes.
1358 class HDebugBreak FINAL : public HTemplateInstruction<0> {
1359  public:
1361 
1363  return Representation::None();
1364  }
1365 
1366  DECLARE_CONCRETE_INSTRUCTION(DebugBreak)
1367 };
1368 
1369 
1370 class HGoto FINAL : public HTemplateControlInstruction<1, 0> {
1371  public:
1372  explicit HGoto(HBasicBlock* target) {
1373  SetSuccessorAt(0, target);
1374  }
1375 
1376  virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE {
1377  *block = FirstSuccessor();
1378  return true;
1379  }
1380 
1382  return Representation::None();
1383  }
1384 
1385  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1386 
1388 };
1389 
1390 
1391 class HDeoptimize FINAL : public HTemplateControlInstruction<1, 0> {
1392  public:
1393  static HDeoptimize* New(Zone* zone,
1394  HValue* context,
1395  const char* reason,
1397  HBasicBlock* unreachable_continuation) {
1398  return new(zone) HDeoptimize(reason, type, unreachable_continuation);
1399  }
1400 
1401  virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE {
1402  *block = NULL;
1403  return true;
1404  }
1405 
1407  return Representation::None();
1408  }
1409 
1410  const char* reason() const { return reason_; }
1411  Deoptimizer::BailoutType type() { return type_; }
1412 
1413  DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
1414 
1415  private:
1416  explicit HDeoptimize(const char* reason,
1418  HBasicBlock* unreachable_continuation)
1419  : reason_(reason), type_(type) {
1420  SetSuccessorAt(0, unreachable_continuation);
1421  }
1422 
1423  const char* reason_;
1425 };
1426 
1427 
1429  public:
1431  HBasicBlock* true_target,
1432  HBasicBlock* false_target) {
1433  SetOperandAt(0, value);
1434  SetSuccessorAt(0, true_target);
1435  SetSuccessorAt(1, false_target);
1436  }
1437 
1438  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1439 
1440  HValue* value() const { return OperandAt(0); }
1441 };
1442 
1443 
1444 class HBranch FINAL : public HUnaryControlInstruction {
1445  public:
1451  HBasicBlock*, HBasicBlock*);
1452 
1454  return Representation::None();
1455  }
1457 
1458  virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE;
1459 
1460  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1461 
1463  return expected_input_types_;
1464  }
1465 
1467 
1468  private:
1469  HBranch(HValue* value,
1470  ToBooleanStub::Types expected_input_types = ToBooleanStub::Types(),
1471  HBasicBlock* true_target = NULL,
1472  HBasicBlock* false_target = NULL)
1473  : HUnaryControlInstruction(value, true_target, false_target),
1474  expected_input_types_(expected_input_types) {
1475  SetFlag(kAllowUndefinedAsNaN);
1476  }
1477 
1479 };
1480 
1481 
1482 class HCompareMap FINAL : public HUnaryControlInstruction {
1483  public:
1486  HBasicBlock*, HBasicBlock*);
1487 
1488  virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE {
1489  if (known_successor_index() != kNoKnownSuccessorIndex) {
1490  *block = SuccessorAt(known_successor_index());
1491  return true;
1492  }
1493  *block = NULL;
1494  return false;
1495  }
1496 
1497  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1498 
1499  static const int kNoKnownSuccessorIndex = -1;
1500  int known_successor_index() const { return known_successor_index_; }
1501  void set_known_successor_index(int known_successor_index) {
1502  known_successor_index_ = known_successor_index;
1503  }
1504 
1505  Unique<Map> map() const { return map_; }
1506  bool map_is_stable() const { return map_is_stable_; }
1507 
1509  return Representation::Tagged();
1510  }
1511 
1512  DECLARE_CONCRETE_INSTRUCTION(CompareMap)
1513 
1514  protected:
1515  virtual int RedefinedOperandIndex() { return 0; }
1516 
1517  private:
1519  Handle<Map> map,
1520  HBasicBlock* true_target = NULL,
1521  HBasicBlock* false_target = NULL)
1522  : HUnaryControlInstruction(value, true_target, false_target),
1523  known_successor_index_(kNoKnownSuccessorIndex),
1524  map_is_stable_(map->is_stable()),
1525  map_(Unique<Map>::CreateImmovable(map)) {
1526  set_representation(Representation::Tagged());
1527  }
1528 
1530  bool map_is_stable_ : 1;
1532 };
1533 
1534 
1535 class HContext FINAL : public HTemplateInstruction<0> {
1536  public:
1537  static HContext* New(Zone* zone) {
1538  return new(zone) HContext();
1539  }
1540 
1542  return Representation::None();
1543  }
1544 
1546 
1547  protected:
1548  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
1549 
1550  private:
1552  set_representation(Representation::Tagged());
1553  SetFlag(kUseGVN);
1554  }
1555 
1556  virtual bool IsDeletable() const OVERRIDE { return true; }
1557 };
1558 
1559 
1560 class HReturn FINAL : public HTemplateControlInstruction<0, 3> {
1561  public:
1564 
1566  // TODO(titzer): require an Int32 input for faster returns.
1567  if (index == 2) return Representation::Smi();
1568  return Representation::Tagged();
1569  }
1570 
1571  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1572 
1573  HValue* value() const { return OperandAt(0); }
1574  HValue* context() const { return OperandAt(1); }
1575  HValue* parameter_count() const { return OperandAt(2); }
1576 
1578 
1579  private:
1580  HReturn(HValue* context, HValue* value, HValue* parameter_count = 0) {
1581  SetOperandAt(0, value);
1582  SetOperandAt(1, context);
1583  SetOperandAt(2, parameter_count);
1584  }
1585 };
1586 
1587 
1588 class HAbnormalExit FINAL : public HTemplateControlInstruction<0, 0> {
1589  public:
1591 
1593  return Representation::None();
1594  }
1595 
1596  DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
1597  private:
1599 };
1600 
1601 
1603  public:
1604  explicit HUnaryOperation(HValue* value, HType type = HType::Tagged())
1605  : HTemplateInstruction<1>(type) {
1606  SetOperandAt(0, value);
1607  }
1608 
1610  return reinterpret_cast<HUnaryOperation*>(value);
1611  }
1612 
1613  HValue* value() const { return OperandAt(0); }
1614  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1615 };
1616 
1617 
1618 class HUseConst FINAL : public HUnaryOperation {
1619  public:
1621 
1623  return Representation::None();
1624  }
1625 
1627 
1628  private:
1629  explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
1630 };
1631 
1632 
1633 class HForceRepresentation FINAL : public HTemplateInstruction<1> {
1634  public:
1635  static HInstruction* New(Zone* zone, HValue* context, HValue* value,
1636  Representation required_representation);
1637 
1638  HValue* value() const { return OperandAt(0); }
1639 
1641  return representation(); // Same as the output representation.
1642  }
1643 
1644  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1645 
1646  DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
1647 
1648  private:
1649  HForceRepresentation(HValue* value, Representation required_representation) {
1650  SetOperandAt(0, value);
1651  set_representation(required_representation);
1652  }
1653 };
1654 
1655 
1656 class HChange FINAL : public HUnaryOperation {
1657  public:
1658  HChange(HValue* value,
1660  bool is_truncating_to_smi,
1661  bool is_truncating_to_int32)
1662  : HUnaryOperation(value) {
1663  DCHECK(!value->representation().IsNone());
1664  DCHECK(!to.IsNone());
1665  DCHECK(!value->representation().Equals(to));
1666  set_representation(to);
1667  SetFlag(kUseGVN);
1668  SetFlag(kCanOverflow);
1669  if (is_truncating_to_smi && to.IsSmi()) {
1670  SetFlag(kTruncatingToSmi);
1671  SetFlag(kTruncatingToInt32);
1672  }
1673  if (is_truncating_to_int32) SetFlag(kTruncatingToInt32);
1674  if (value->representation().IsSmi() || value->type().IsSmi()) {
1675  set_type(HType::Smi());
1676  } else {
1677  set_type(HType::TaggedNumber());
1678  if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
1679  }
1680  }
1681 
1683  return CheckUsesForFlag(kAllowUndefinedAsNaN);
1684  }
1685 
1688 
1689  Representation from() const { return value()->representation(); }
1690  Representation to() const { return representation(); }
1692  return CheckFlag(kBailoutOnMinusZero);
1693  }
1695  return from();
1696  }
1697 
1698  virtual Range* InferRange(Zone* zone) OVERRIDE;
1699 
1700  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1701 
1703 
1704  protected:
1705  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
1706 
1707  private:
1708  virtual bool IsDeletable() const OVERRIDE {
1709  return !from().IsTagged() || value()->type().IsSmi();
1710  }
1711 };
1712 
1713 
1714 class HClampToUint8 FINAL : public HUnaryOperation {
1715  public:
1717 
1719  return Representation::None();
1720  }
1721 
1722  DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
1723 
1724  protected:
1725  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
1726 
1727  private:
1728  explicit HClampToUint8(HValue* value)
1729  : HUnaryOperation(value) {
1730  set_representation(Representation::Integer32());
1731  SetFlag(kAllowUndefinedAsNaN);
1732  SetFlag(kUseGVN);
1733  }
1734 
1735  virtual bool IsDeletable() const OVERRIDE { return true; }
1736 };
1737 
1738 
1739 class HDoubleBits FINAL : public HUnaryOperation {
1740  public:
1741  enum Bits { HIGH, LOW };
1743 
1745  return Representation::Double();
1746  }
1747 
1748  DECLARE_CONCRETE_INSTRUCTION(DoubleBits)
1749 
1750  Bits bits() { return bits_; }
1751 
1752  protected:
1753  virtual bool DataEquals(HValue* other) OVERRIDE {
1754  return other->IsDoubleBits() && HDoubleBits::cast(other)->bits() == bits();
1755  }
1756 
1757  private:
1758  HDoubleBits(HValue* value, Bits bits)
1759  : HUnaryOperation(value), bits_(bits) {
1760  set_representation(Representation::Integer32());
1761  SetFlag(kUseGVN);
1762  }
1763 
1764  virtual bool IsDeletable() const OVERRIDE { return true; }
1765 
1767 };
1768 
1769 
1770 class HConstructDouble FINAL : public HTemplateInstruction<2> {
1771  public:
1773 
1775  return Representation::Integer32();
1776  }
1777 
1778  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble)
1779 
1780  HValue* hi() { return OperandAt(0); }
1781  HValue* lo() { return OperandAt(1); }
1782 
1783  protected:
1784  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
1785 
1786  private:
1788  set_representation(Representation::Double());
1789  SetFlag(kUseGVN);
1790  SetOperandAt(0, hi);
1791  SetOperandAt(1, lo);
1792  }
1793 
1794  virtual bool IsDeletable() const OVERRIDE { return true; }
1795 };
1796 
1797 
1801 };
1802 
1803 
1804 class HSimulate FINAL : public HInstruction {
1805  public:
1807  int pop_count,
1808  Zone* zone,
1809  RemovableSimulate removable)
1810  : ast_id_(ast_id),
1811  pop_count_(pop_count),
1812  values_(2, zone),
1813  assigned_indexes_(2, zone),
1814  zone_(zone),
1815  removable_(removable),
1816  done_with_replay_(false) {}
1818 
1819  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1820 
1821  bool HasAstId() const { return !ast_id_.IsNone(); }
1822  BailoutId ast_id() const { return ast_id_; }
1824  DCHECK(!HasAstId());
1825  ast_id_ = id;
1826  }
1827 
1828  int pop_count() const { return pop_count_; }
1829  const ZoneList<HValue*>* values() const { return &values_; }
1830  int GetAssignedIndexAt(int index) const {
1831  DCHECK(HasAssignedIndexAt(index));
1832  return assigned_indexes_[index];
1833  }
1834  bool HasAssignedIndexAt(int index) const {
1835  return assigned_indexes_[index] != kNoIndex;
1836  }
1837  void AddAssignedValue(int index, HValue* value) {
1838  AddValue(index, value);
1839  }
1840  void AddPushedValue(HValue* value) {
1841  AddValue(kNoIndex, value);
1842  }
1843  int ToOperandIndex(int environment_index) {
1844  for (int i = 0; i < assigned_indexes_.length(); ++i) {
1845  if (assigned_indexes_[i] == environment_index) return i;
1846  }
1847  return -1;
1848  }
1849  virtual int OperandCount() const OVERRIDE { return values_.length(); }
1850  virtual HValue* OperandAt(int index) const OVERRIDE {
1851  return values_[index];
1852  }
1853 
1854  virtual bool HasEscapingOperandAt(int index) OVERRIDE { return false; }
1856  return Representation::None();
1857  }
1858 
1860  bool is_candidate_for_removal() { return removable_ == REMOVABLE_SIMULATE; }
1861 
1862  // Replay effects of this instruction on the given environment.
1863  void ReplayEnvironment(HEnvironment* env);
1864 
1866 
1867 #ifdef DEBUG
1868  virtual void Verify() OVERRIDE;
1869  void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
1870  Handle<JSFunction> closure() const { return closure_; }
1871 #endif
1872 
1873  protected:
1874  virtual void InternalSetOperandAt(int index, HValue* value) OVERRIDE {
1875  values_[index] = value;
1876  }
1877 
1878  private:
1879  static const int kNoIndex = -1;
1880  void AddValue(int index, HValue* value) {
1881  assigned_indexes_.Add(index, zone_);
1882  // Resize the list of pushed values.
1883  values_.Add(NULL, zone_);
1884  // Set the operand through the base method in HValue to make sure that the
1885  // use lists are correctly updated.
1886  SetOperandAt(values_.length() - 1, value);
1887  }
1888  bool HasValueForIndex(int index) {
1889  for (int i = 0; i < assigned_indexes_.length(); ++i) {
1890  if (assigned_indexes_[i] == index) return true;
1891  }
1892  return false;
1893  }
1898  Zone* zone_;
1901 
1902 #ifdef DEBUG
1903  Handle<JSFunction> closure_;
1904 #endif
1905 };
1906 
1907 
1908 class HEnvironmentMarker FINAL : public HTemplateInstruction<1> {
1909  public:
1910  enum Kind { BIND, LOOKUP };
1911 
1912  DECLARE_INSTRUCTION_FACTORY_P2(HEnvironmentMarker, Kind, int);
1913 
1914  Kind kind() const { return kind_; }
1915  int index() const { return index_; }
1916  HSimulate* next_simulate() { return next_simulate_; }
1917  void set_next_simulate(HSimulate* simulate) {
1918  next_simulate_ = simulate;
1919  }
1920 
1922  return Representation::None();
1923  }
1924 
1925  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1926 
1927 #ifdef DEBUG
1928  void set_closure(Handle<JSFunction> closure) {
1929  DCHECK(closure_.is_null());
1930  DCHECK(!closure.is_null());
1931  closure_ = closure;
1932  }
1933  Handle<JSFunction> closure() const { return closure_; }
1934 #endif
1935 
1936  DECLARE_CONCRETE_INSTRUCTION(EnvironmentMarker);
1937 
1938  private:
1939  HEnvironmentMarker(Kind kind, int index)
1940  : kind_(kind), index_(index), next_simulate_(NULL) { }
1941 
1942  Kind kind_;
1943  int index_;
1944  HSimulate* next_simulate_;
1945 
1946 #ifdef DEBUG
1947  Handle<JSFunction> closure_;
1948 #endif
1949 };
1950 
1951 
1952 class HStackCheck FINAL : public HTemplateInstruction<1> {
1953  public:
1954  enum Type {
1956  kBackwardsBranch
1957  };
1958 
1960 
1961  HValue* context() { return OperandAt(0); }
1962 
1964  return Representation::Tagged();
1965  }
1966 
1967  void Eliminate() {
1968  // The stack check eliminator might try to eliminate the same stack
1969  // check instruction multiple times.
1970  if (IsLinked()) {
1971  DeleteAndReplaceWith(NULL);
1972  }
1973  }
1974 
1975  bool is_function_entry() { return type_ == kFunctionEntry; }
1976  bool is_backwards_branch() { return type_ == kBackwardsBranch; }
1977 
1978  DECLARE_CONCRETE_INSTRUCTION(StackCheck)
1979 
1980  private:
1981  HStackCheck(HValue* context, Type type) : type_(type) {
1982  SetOperandAt(0, context);
1983  SetChangesFlag(kNewSpacePromotion);
1984  }
1985 
1987 };
1988 
1989 
1991  NORMAL_RETURN, // Drop the function from the environment on return.
1992  CONSTRUCT_CALL_RETURN, // Either use allocated receiver or return value.
1993  GETTER_CALL_RETURN, // Returning from a getter, need to restore context.
1994  SETTER_CALL_RETURN // Use the RHS of the assignment as the return value.
1995 };
1996 
1997 
1998 class HArgumentsObject;
1999 class HConstant;
2000 
2001 
2002 class HEnterInlined FINAL : public HTemplateInstruction<0> {
2003  public:
2004  static HEnterInlined* New(Zone* zone, HValue* context, BailoutId return_id,
2005  Handle<JSFunction> closure,
2006  HConstant* closure_context, int arguments_count,
2007  FunctionLiteral* function,
2008  InliningKind inlining_kind, Variable* arguments_var,
2009  HArgumentsObject* arguments_object) {
2010  return new (zone) HEnterInlined(return_id, closure, closure_context,
2011  arguments_count, function, inlining_kind,
2012  arguments_var, arguments_object, zone);
2013  }
2014 
2015  void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
2016  ZoneList<HBasicBlock*>* return_targets() { return &return_targets_; }
2017 
2018  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2019 
2020  Handle<JSFunction> closure() const { return closure_; }
2021  HConstant* closure_context() const { return closure_context_; }
2022  int arguments_count() const { return arguments_count_; }
2023  bool arguments_pushed() const { return arguments_pushed_; }
2024  void set_arguments_pushed() { arguments_pushed_ = true; }
2025  FunctionLiteral* function() const { return function_; }
2026  InliningKind inlining_kind() const { return inlining_kind_; }
2027  BailoutId ReturnId() const { return return_id_; }
2028 
2030  return Representation::None();
2031  }
2032 
2033  Variable* arguments_var() { return arguments_var_; }
2034  HArgumentsObject* arguments_object() { return arguments_object_; }
2035 
2036  DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
2037 
2038  private:
2040  HConstant* closure_context, int arguments_count,
2041  FunctionLiteral* function, InliningKind inlining_kind,
2042  Variable* arguments_var, HArgumentsObject* arguments_object,
2043  Zone* zone)
2044  : return_id_(return_id),
2045  closure_(closure),
2046  closure_context_(closure_context),
2047  arguments_count_(arguments_count),
2048  arguments_pushed_(false),
2049  function_(function),
2050  inlining_kind_(inlining_kind),
2051  arguments_var_(arguments_var),
2052  arguments_object_(arguments_object),
2053  return_targets_(2, zone) {}
2054 
2057  HConstant* closure_context_;
2060  FunctionLiteral* function_;
2063  HArgumentsObject* arguments_object_;
2065 };
2066 
2067 
2068 class HLeaveInlined FINAL : public HTemplateInstruction<0> {
2069  public:
2070  HLeaveInlined(HEnterInlined* entry,
2071  int drop_count)
2072  : entry_(entry),
2073  drop_count_(drop_count) { }
2074 
2076  return Representation::None();
2077  }
2078 
2079  virtual int argument_delta() const OVERRIDE {
2080  return entry_->arguments_pushed() ? -drop_count_ : 0;
2081  }
2082 
2083  DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
2084 
2085  private:
2086  HEnterInlined* entry_;
2088 };
2089 
2090 
2091 class HPushArguments FINAL : public HInstruction {
2092  public:
2093  static HPushArguments* New(Zone* zone, HValue* context) {
2094  return new(zone) HPushArguments(zone);
2095  }
2096  static HPushArguments* New(Zone* zone, HValue* context, HValue* arg1) {
2097  HPushArguments* instr = new(zone) HPushArguments(zone);
2098  instr->AddInput(arg1);
2099  return instr;
2100  }
2101  static HPushArguments* New(Zone* zone, HValue* context, HValue* arg1,
2102  HValue* arg2) {
2103  HPushArguments* instr = new(zone) HPushArguments(zone);
2104  instr->AddInput(arg1);
2105  instr->AddInput(arg2);
2106  return instr;
2107  }
2108  static HPushArguments* New(Zone* zone, HValue* context, HValue* arg1,
2109  HValue* arg2, HValue* arg3) {
2110  HPushArguments* instr = new(zone) HPushArguments(zone);
2111  instr->AddInput(arg1);
2112  instr->AddInput(arg2);
2113  instr->AddInput(arg3);
2114  return instr;
2115  }
2116  static HPushArguments* New(Zone* zone, HValue* context, HValue* arg1,
2117  HValue* arg2, HValue* arg3, HValue* arg4) {
2118  HPushArguments* instr = new(zone) HPushArguments(zone);
2119  instr->AddInput(arg1);
2120  instr->AddInput(arg2);
2121  instr->AddInput(arg3);
2122  instr->AddInput(arg4);
2123  return instr;
2124  }
2125 
2127  return Representation::Tagged();
2128  }
2129 
2130  virtual int argument_delta() const OVERRIDE { return inputs_.length(); }
2131  HValue* argument(int i) { return OperandAt(i); }
2132 
2133  virtual int OperandCount() const FINAL OVERRIDE {
2134  return inputs_.length();
2135  }
2136  virtual HValue* OperandAt(int i) const FINAL OVERRIDE {
2137  return inputs_[i];
2138  }
2139 
2140  void AddInput(HValue* value);
2141 
2142  DECLARE_CONCRETE_INSTRUCTION(PushArguments)
2143 
2144  protected:
2145  virtual void InternalSetOperandAt(int i, HValue* value) FINAL OVERRIDE {
2146  inputs_[i] = value;
2147  }
2148 
2149  private:
2150  explicit HPushArguments(Zone* zone)
2151  : HInstruction(HType::Tagged()), inputs_(4, zone) {
2152  set_representation(Representation::Tagged());
2153  }
2154 
2156 };
2157 
2158 
2159 class HThisFunction FINAL : public HTemplateInstruction<0> {
2160  public:
2162 
2164  return Representation::None();
2165  }
2166 
2167  DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
2168 
2169  protected:
2170  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
2171 
2172  private:
2174  set_representation(Representation::Tagged());
2175  SetFlag(kUseGVN);
2176  }
2177 
2178  virtual bool IsDeletable() const OVERRIDE { return true; }
2179 };
2180 
2181 
2182 class HDeclareGlobals FINAL : public HUnaryOperation {
2183  public:
2186  int);
2187 
2188  HValue* context() { return OperandAt(0); }
2189  Handle<FixedArray> pairs() const { return pairs_; }
2190  int flags() const { return flags_; }
2191 
2193 
2194  virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
2195  return Representation::Tagged();
2196  }
2197 
2198  private:
2201  int flags)
2202  : HUnaryOperation(context),
2203  pairs_(pairs),
2204  flags_(flags) {
2205  set_representation(Representation::Tagged());
2206  SetAllSideEffects();
2207  }
2208 
2210  int flags_;
2211 };
2212 
2213 
2214 template <int V>
2215 class HCall : public HTemplateInstruction<V> {
2216  public:
2217  // The argument count includes the receiver.
2220  this->SetAllSideEffects();
2221  }
2222 
2224  return HType::Tagged();
2225  }
2226 
2227  virtual int argument_count() const {
2228  return argument_count_;
2229  }
2230 
2231  virtual int argument_delta() const OVERRIDE {
2232  return -argument_count();
2233  }
2234 
2235  private:
2237 };
2238 
2239 
2240 class HUnaryCall : public HCall<1> {
2241  public:
2243  : HCall<1>(argument_count) {
2244  SetOperandAt(0, value);
2245  }
2246 
2248  int index) FINAL OVERRIDE {
2249  return Representation::Tagged();
2250  }
2251 
2252  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2253 
2254  HValue* value() const { return OperandAt(0); }
2255 };
2256 
2257 
2258 class HBinaryCall : public HCall<2> {
2259  public:
2261  : HCall<2>(argument_count) {
2262  SetOperandAt(0, first);
2263  SetOperandAt(1, second);
2264  }
2265 
2266  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2267 
2269  int index) FINAL OVERRIDE {
2270  return Representation::Tagged();
2271  }
2272 
2273  HValue* first() const { return OperandAt(0); }
2274  HValue* second() const { return OperandAt(1); }
2275 };
2276 
2277 
2278 class HCallJSFunction FINAL : public HCall<1> {
2279  public:
2280  static HCallJSFunction* New(Zone* zone,
2281  HValue* context,
2282  HValue* function,
2283  int argument_count,
2284  bool pass_argument_count);
2285 
2286  HValue* function() const { return OperandAt(0); }
2287 
2288  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2289 
2291  int index) FINAL OVERRIDE {
2292  DCHECK(index == 0);
2293  return Representation::Tagged();
2294  }
2295 
2296  bool pass_argument_count() const { return pass_argument_count_; }
2297 
2298  virtual bool HasStackCheck() FINAL OVERRIDE {
2299  return has_stack_check_;
2300  }
2301 
2302  DECLARE_CONCRETE_INSTRUCTION(CallJSFunction)
2303 
2304  private:
2305  // The argument count includes the receiver.
2307  int argument_count,
2308  bool pass_argument_count,
2309  bool has_stack_check)
2310  : HCall<1>(argument_count),
2311  pass_argument_count_(pass_argument_count),
2312  has_stack_check_(has_stack_check) {
2313  SetOperandAt(0, function);
2314  }
2315 
2318 };
2319 
2320 
2321 class HCallWithDescriptor FINAL : public HInstruction {
2322  public:
2323  static HCallWithDescriptor* New(Zone* zone, HValue* context, HValue* target,
2324  int argument_count,
2325  CallInterfaceDescriptor descriptor,
2326  const Vector<HValue*>& operands) {
2327  DCHECK(operands.length() == descriptor.GetEnvironmentLength());
2328  HCallWithDescriptor* res = new (zone)
2329  HCallWithDescriptor(target, argument_count, descriptor, operands, zone);
2330  return res;
2331  }
2332 
2333  virtual int OperandCount() const FINAL OVERRIDE {
2334  return values_.length();
2335  }
2336  virtual HValue* OperandAt(int index) const FINAL OVERRIDE {
2337  return values_[index];
2338  }
2339 
2341  int index) FINAL OVERRIDE {
2342  if (index == 0) {
2343  return Representation::Tagged();
2344  } else {
2345  int par_index = index - 1;
2346  DCHECK(par_index < descriptor_.GetEnvironmentLength());
2347  return descriptor_.GetParameterRepresentation(par_index);
2348  }
2349  }
2350 
2351  DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor)
2352 
2353  virtual HType CalculateInferredType() FINAL OVERRIDE {
2354  return HType::Tagged();
2355  }
2356 
2357  virtual int argument_count() const {
2358  return argument_count_;
2359  }
2360 
2361  virtual int argument_delta() const OVERRIDE {
2362  return -argument_count_;
2363  }
2364 
2365  CallInterfaceDescriptor descriptor() const { return descriptor_; }
2366 
2368  return OperandAt(0);
2369  }
2370 
2371  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2372 
2373  private:
2374  // The argument count includes the receiver.
2375  HCallWithDescriptor(HValue* target, int argument_count,
2376  CallInterfaceDescriptor descriptor,
2377  const Vector<HValue*>& operands, Zone* zone)
2378  : descriptor_(descriptor),
2379  values_(descriptor.GetEnvironmentLength() + 1, zone) {
2380  argument_count_ = argument_count;
2381  AddOperand(target, zone);
2382  for (int i = 0; i < operands.length(); i++) {
2383  AddOperand(operands[i], zone);
2384  }
2385  this->set_representation(Representation::Tagged());
2386  this->SetAllSideEffects();
2387  }
2388 
2389  void AddOperand(HValue* v, Zone* zone) {
2390  values_.Add(NULL, zone);
2391  SetOperandAt(values_.length() - 1, v);
2392  }
2393 
2394  void InternalSetOperandAt(int index,
2395  HValue* value) FINAL OVERRIDE {
2396  values_[index] = value;
2397  }
2398 
2399  CallInterfaceDescriptor descriptor_;
2400  ZoneList<HValue*> values_;
2402 };
2403 
2404 
2405 class HInvokeFunction FINAL : public HBinaryCall {
2406  public:
2408 
2410  HValue* function,
2411  Handle<JSFunction> known_function,
2412  int argument_count)
2413  : HBinaryCall(context, function, argument_count),
2414  known_function_(known_function) {
2415  formal_parameter_count_ = known_function.is_null()
2416  ? 0 : known_function->shared()->formal_parameter_count();
2417  has_stack_check_ = !known_function.is_null() &&
2418  (known_function->code()->kind() == Code::FUNCTION ||
2419  known_function->code()->kind() == Code::OPTIMIZED_FUNCTION);
2420  }
2421 
2422  static HInvokeFunction* New(Zone* zone,
2423  HValue* context,
2424  HValue* function,
2425  Handle<JSFunction> known_function,
2426  int argument_count) {
2427  return new(zone) HInvokeFunction(context, function,
2428  known_function, argument_count);
2429  }
2430 
2431  HValue* context() { return first(); }
2432  HValue* function() { return second(); }
2433  Handle<JSFunction> known_function() { return known_function_; }
2434  int formal_parameter_count() const { return formal_parameter_count_; }
2435 
2436  virtual bool HasStackCheck() FINAL OVERRIDE {
2437  return has_stack_check_;
2438  }
2439 
2440  DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
2441 
2442  private:
2443  HInvokeFunction(HValue* context, HValue* function, int argument_count)
2444  : HBinaryCall(context, function, argument_count),
2445  has_stack_check_(false) {
2446  }
2447 
2450  bool has_stack_check_;
2451 };
2452 
2453 
2454 class HCallFunction FINAL : public HBinaryCall {
2455  public:
2458  HCallFunction, HValue*, int, CallFunctionFlags);
2459 
2460  HValue* context() { return first(); }
2461  HValue* function() { return second(); }
2462  CallFunctionFlags function_flags() const { return function_flags_; }
2463 
2464  DECLARE_CONCRETE_INSTRUCTION(CallFunction)
2465 
2466  virtual int argument_delta() const OVERRIDE { return -argument_count(); }
2467 
2468  private:
2470  HValue* function,
2471  int argument_count,
2473  : HBinaryCall(context, function, argument_count), function_flags_(flags) {
2474  }
2476 };
2477 
2478 
2479 class HCallNew FINAL : public HBinaryCall {
2480  public:
2482 
2483  HValue* context() { return first(); }
2484  HValue* constructor() { return second(); }
2485 
2487 
2488  private:
2489  HCallNew(HValue* context, HValue* constructor, int argument_count)
2490  : HBinaryCall(context, constructor, argument_count) {}
2491 };
2492 
2493 
2494 class HCallNewArray FINAL : public HBinaryCall {
2495  public:
2497  HValue*,
2498  int,
2499  ElementsKind);
2500 
2501  HValue* context() { return first(); }
2502  HValue* constructor() { return second(); }
2503 
2504  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2505 
2506  ElementsKind elements_kind() const { return elements_kind_; }
2507 
2508  DECLARE_CONCRETE_INSTRUCTION(CallNewArray)
2509 
2510  private:
2511  HCallNewArray(HValue* context, HValue* constructor, int argument_count,
2512  ElementsKind elements_kind)
2513  : HBinaryCall(context, constructor, argument_count),
2514  elements_kind_(elements_kind) {}
2515 
2517 };
2518 
2519 
2520 class HCallRuntime FINAL : public HCall<1> {
2521  public:
2524  const Runtime::Function*,
2525  int);
2526 
2527  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2528 
2529  HValue* context() { return OperandAt(0); }
2530  const Runtime::Function* function() const { return c_function_; }
2531  Handle<String> name() const { return name_; }
2532  SaveFPRegsMode save_doubles() const { return save_doubles_; }
2533  void set_save_doubles(SaveFPRegsMode save_doubles) {
2534  save_doubles_ = save_doubles;
2535  }
2536 
2538  return Representation::Tagged();
2539  }
2540 
2541  DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
2542 
2543  private:
2546  const Runtime::Function* c_function,
2547  int argument_count)
2548  : HCall<1>(argument_count), c_function_(c_function), name_(name),
2549  save_doubles_(kDontSaveFPRegs) {
2550  SetOperandAt(0, context);
2551  }
2552 
2554  Handle<String> name_;
2556 };
2557 
2558 
2559 class HMapEnumLength FINAL : public HUnaryOperation {
2560  public:
2562 
2564  return Representation::Tagged();
2565  }
2566 
2567  DECLARE_CONCRETE_INSTRUCTION(MapEnumLength)
2568 
2569  protected:
2570  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
2571 
2572  private:
2573  explicit HMapEnumLength(HValue* value)
2574  : HUnaryOperation(value, HType::Smi()) {
2575  set_representation(Representation::Smi());
2576  SetFlag(kUseGVN);
2577  SetDependsOnFlag(kMaps);
2578  }
2579 
2580  virtual bool IsDeletable() const OVERRIDE { return true; }
2581 };
2582 
2583 
2584 class HUnaryMathOperation FINAL : public HTemplateInstruction<2> {
2585  public:
2586  static HInstruction* New(Zone* zone,
2587  HValue* context,
2588  HValue* value,
2589  BuiltinFunctionId op);
2590 
2591  HValue* context() const { return OperandAt(0); }
2592  HValue* value() const { return OperandAt(1); }
2593 
2594  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2595 
2597  if (index == 0) {
2598  return Representation::Tagged();
2599  } else {
2600  switch (op_) {
2601  case kMathFloor:
2602  case kMathRound:
2603  case kMathFround:
2604  case kMathSqrt:
2605  case kMathPowHalf:
2606  case kMathLog:
2607  case kMathExp:
2608  return Representation::Double();
2609  case kMathAbs:
2610  return representation();
2611  case kMathClz32:
2612  return Representation::Integer32();
2613  default:
2614  UNREACHABLE();
2615  return Representation::None();
2616  }
2617  }
2618  }
2619 
2620  virtual Range* InferRange(Zone* zone) OVERRIDE;
2621 
2623  virtual Representation RepresentationFromUses() OVERRIDE;
2624  virtual Representation RepresentationFromInputs() OVERRIDE;
2625 
2626  BuiltinFunctionId op() const { return op_; }
2627  const char* OpName() const;
2628 
2629  DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
2630 
2631  protected:
2632  virtual bool DataEquals(HValue* other) OVERRIDE {
2633  HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
2634  return op_ == b->op();
2635  }
2636 
2637  private:
2638  // Indicates if we support a double (and int32) output for Math.floor and
2639  // Math.round.
2641 #ifdef V8_TARGET_ARCH_ARM64
2642  return true;
2643 #else
2644  return false;
2645 #endif
2646  }
2648  : HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
2649  SetOperandAt(0, context);
2650  SetOperandAt(1, value);
2651  switch (op) {
2652  case kMathFloor:
2653  case kMathRound:
2654  if (SupportsFlexibleFloorAndRound()) {
2655  SetFlag(kFlexibleRepresentation);
2656  } else {
2657  set_representation(Representation::Integer32());
2658  }
2659  break;
2660  case kMathClz32:
2661  set_representation(Representation::Integer32());
2662  break;
2663  case kMathAbs:
2664  // Not setting representation here: it is None intentionally.
2665  SetFlag(kFlexibleRepresentation);
2666  // TODO(svenpanne) This flag is actually only needed if representation()
2667  // is tagged, and not when it is an unboxed double or unboxed integer.
2668  SetChangesFlag(kNewSpacePromotion);
2669  break;
2670  case kMathFround:
2671  case kMathLog:
2672  case kMathExp:
2673  case kMathSqrt:
2674  case kMathPowHalf:
2675  set_representation(Representation::Double());
2676  break;
2677  default:
2678  UNREACHABLE();
2679  }
2680  SetFlag(kUseGVN);
2681  SetFlag(kAllowUndefinedAsNaN);
2682  }
2683 
2684  virtual bool IsDeletable() const OVERRIDE { return true; }
2685 
2688 
2690 };
2691 
2692 
2693 class HLoadRoot FINAL : public HTemplateInstruction<0> {
2694  public:
2697 
2699  return Representation::None();
2700  }
2701 
2702  Heap::RootListIndex index() const { return index_; }
2703 
2705 
2706  protected:
2707  virtual bool DataEquals(HValue* other) OVERRIDE {
2708  HLoadRoot* b = HLoadRoot::cast(other);
2709  return index_ == b->index_;
2710  }
2711 
2712  private:
2713  explicit HLoadRoot(Heap::RootListIndex index, HType type = HType::Tagged())
2714  : HTemplateInstruction<0>(type), index_(index) {
2715  SetFlag(kUseGVN);
2716  // TODO(bmeurer): We'll need kDependsOnRoots once we add the
2717  // corresponding HStoreRoot instruction.
2718  SetDependsOnFlag(kCalls);
2719  }
2720 
2721  virtual bool IsDeletable() const OVERRIDE { return true; }
2722 
2724 };
2725 
2726 
2727 class HCheckMaps FINAL : public HTemplateInstruction<2> {
2728  public:
2729  static HCheckMaps* New(Zone* zone, HValue* context, HValue* value,
2730  Handle<Map> map, HValue* typecheck = NULL) {
2731  return new(zone) HCheckMaps(value, new(zone) UniqueSet<Map>(
2732  Unique<Map>::CreateImmovable(map), zone), typecheck);
2733  }
2734  static HCheckMaps* New(Zone* zone, HValue* context,
2735  HValue* value, SmallMapList* map_list,
2736  HValue* typecheck = NULL) {
2737  UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone);
2738  for (int i = 0; i < map_list->length(); ++i) {
2739  maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone);
2740  }
2741  return new(zone) HCheckMaps(value, maps, typecheck);
2742  }
2743 
2744  bool IsStabilityCheck() const { return is_stability_check_; }
2746  maps_are_stable_ = true;
2747  has_migration_target_ = false;
2748  is_stability_check_ = true;
2749  ClearChangesFlag(kNewSpacePromotion);
2750  ClearDependsOnFlag(kElementsKind);
2751  ClearDependsOnFlag(kMaps);
2752  }
2753 
2754  virtual bool HasEscapingOperandAt(int index) OVERRIDE { return false; }
2756  return Representation::Tagged();
2757  }
2758 
2760  if (value()->type().IsHeapObject()) return value()->type();
2761  return HType::HeapObject();
2762  }
2763 
2764  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2765 
2766  HValue* value() const { return OperandAt(0); }
2767  HValue* typecheck() const { return OperandAt(1); }
2768 
2769  const UniqueSet<Map>* maps() const { return maps_; }
2770  void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; }
2771 
2772  bool maps_are_stable() const { return maps_are_stable_; }
2773 
2774  bool HasMigrationTarget() const { return has_migration_target_; }
2775 
2777 
2778  static HCheckMaps* CreateAndInsertAfter(Zone* zone,
2779  HValue* value,
2780  Unique<Map> map,
2781  bool map_is_stable,
2782  HInstruction* instr) {
2783  return instr->Append(new(zone) HCheckMaps(
2784  value, new(zone) UniqueSet<Map>(map, zone), map_is_stable));
2785  }
2786 
2787  static HCheckMaps* CreateAndInsertBefore(Zone* zone,
2788  HValue* value,
2789  const UniqueSet<Map>* maps,
2790  bool maps_are_stable,
2791  HInstruction* instr) {
2792  return instr->Prepend(new(zone) HCheckMaps(value, maps, maps_are_stable));
2793  }
2794 
2795  DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
2796 
2797  protected:
2798  virtual bool DataEquals(HValue* other) OVERRIDE {
2799  return this->maps()->Equals(HCheckMaps::cast(other)->maps());
2800  }
2801 
2802  virtual int RedefinedOperandIndex() { return 0; }
2803 
2804  private:
2805  HCheckMaps(HValue* value, const UniqueSet<Map>* maps, bool maps_are_stable)
2806  : HTemplateInstruction<2>(HType::HeapObject()), maps_(maps),
2807  has_migration_target_(false), is_stability_check_(false),
2808  maps_are_stable_(maps_are_stable) {
2809  DCHECK_NE(0, maps->size());
2810  SetOperandAt(0, value);
2811  // Use the object value for the dependency.
2812  SetOperandAt(1, value);
2813  set_representation(Representation::Tagged());
2814  SetFlag(kUseGVN);
2815  SetDependsOnFlag(kMaps);
2816  SetDependsOnFlag(kElementsKind);
2817  }
2818 
2819  HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck)
2820  : HTemplateInstruction<2>(HType::HeapObject()), maps_(maps),
2821  has_migration_target_(false), is_stability_check_(false),
2822  maps_are_stable_(true) {
2823  DCHECK_NE(0, maps->size());
2824  SetOperandAt(0, value);
2825  // Use the object value for the dependency if NULL is passed.
2826  SetOperandAt(1, typecheck ? typecheck : value);
2827  set_representation(Representation::Tagged());
2828  SetFlag(kUseGVN);
2829  SetDependsOnFlag(kMaps);
2830  SetDependsOnFlag(kElementsKind);
2831  for (int i = 0; i < maps->size(); ++i) {
2832  Handle<Map> map = maps->at(i).handle();
2833  if (map->is_migration_target()) has_migration_target_ = true;
2834  if (!map->is_stable()) maps_are_stable_ = false;
2835  }
2836  if (has_migration_target_) SetChangesFlag(kNewSpacePromotion);
2837  }
2838 
2843 };
2844 
2845 
2846 class HCheckValue FINAL : public HUnaryOperation {
2847  public:
2848  static HCheckValue* New(Zone* zone, HValue* context,
2849  HValue* value, Handle<JSFunction> func) {
2850  bool in_new_space = zone->isolate()->heap()->InNewSpace(*func);
2851  // NOTE: We create an uninitialized Unique and initialize it later.
2852  // This is because a JSFunction can move due to GC during graph creation.
2853  // TODO(titzer): This is a migration crutch. Replace with some kind of
2854  // Uniqueness scope later.
2856  HCheckValue* check = new(zone) HCheckValue(value, target, in_new_space);
2857  return check;
2858  }
2859  static HCheckValue* New(Zone* zone, HValue* context,
2860  HValue* value, Unique<HeapObject> target,
2861  bool object_in_new_space) {
2862  return new(zone) HCheckValue(value, target, object_in_new_space);
2863  }
2864 
2865  virtual void FinalizeUniqueness() OVERRIDE {
2866  object_ = Unique<HeapObject>(object_.handle());
2867  }
2868 
2870  return Representation::Tagged();
2871  }
2872  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2873 
2875 
2876 #ifdef DEBUG
2877  virtual void Verify() OVERRIDE;
2878 #endif
2879 
2880  Unique<HeapObject> object() const { return object_; }
2881  bool object_in_new_space() const { return object_in_new_space_; }
2882 
2883  DECLARE_CONCRETE_INSTRUCTION(CheckValue)
2884 
2885  protected:
2886  virtual bool DataEquals(HValue* other) OVERRIDE {
2887  HCheckValue* b = HCheckValue::cast(other);
2888  return object_ == b->object_;
2889  }
2890 
2891  private:
2893  bool object_in_new_space)
2894  : HUnaryOperation(value, value->type()),
2895  object_(object),
2896  object_in_new_space_(object_in_new_space) {
2897  set_representation(Representation::Tagged());
2898  SetFlag(kUseGVN);
2899  }
2900 
2903 };
2904 
2905 
2906 class HCheckInstanceType FINAL : public HUnaryOperation {
2907  public:
2908  enum Check {
2913  LAST_INTERVAL_CHECK = IS_JS_ARRAY
2914  };
2915 
2917 
2918  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2919 
2921  return Representation::Tagged();
2922  }
2923 
2925  switch (check_) {
2926  case IS_SPEC_OBJECT: return HType::JSObject();
2927  case IS_JS_ARRAY: return HType::JSArray();
2928  case IS_STRING: return HType::String();
2929  case IS_INTERNALIZED_STRING: return HType::String();
2930  }
2931  UNREACHABLE();
2932  return HType::Tagged();
2933  }
2934 
2936 
2937  bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
2939  void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
2940 
2941  Check check() const { return check_; }
2942 
2943  DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
2944 
2945  protected:
2946  // TODO(ager): It could be nice to allow the ommision of instance
2947  // type checks if we have already performed an instance type check
2948  // with a larger range.
2949  virtual bool DataEquals(HValue* other) OVERRIDE {
2950  HCheckInstanceType* b = HCheckInstanceType::cast(other);
2951  return check_ == b->check_;
2952  }
2953 
2954  virtual int RedefinedOperandIndex() { return 0; }
2955 
2956  private:
2957  const char* GetCheckName() const;
2958 
2960  : HUnaryOperation(value, HType::HeapObject()), check_(check) {
2961  set_representation(Representation::Tagged());
2962  SetFlag(kUseGVN);
2963  }
2964 
2965  const Check check_;
2966 };
2967 
2968 
2969 class HCheckSmi FINAL : public HUnaryOperation {
2970  public:
2972 
2974  return Representation::Tagged();
2975  }
2976 
2978  HType value_type = value()->type();
2979  if (value_type.IsSmi()) {
2980  return NULL;
2981  }
2982  return this;
2983  }
2984 
2986 
2987  protected:
2988  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
2989 
2990  private:
2991  explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
2992  set_representation(Representation::Smi());
2993  SetFlag(kUseGVN);
2994  }
2995 };
2996 
2997 
2998 class HCheckHeapObject FINAL : public HUnaryOperation {
2999  public:
3001 
3002  virtual bool HasEscapingOperandAt(int index) OVERRIDE { return false; }
3004  return Representation::Tagged();
3005  }
3006 
3008  if (value()->type().IsHeapObject()) return value()->type();
3009  return HType::HeapObject();
3010  }
3011 
3012 #ifdef DEBUG
3013  virtual void Verify() OVERRIDE;
3014 #endif
3015 
3017  return value()->type().IsHeapObject() ? NULL : this;
3018  }
3019 
3020  DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
3021 
3022  protected:
3023  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
3024 
3025  private:
3026  explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) {
3027  set_representation(Representation::Tagged());
3028  SetFlag(kUseGVN);
3029  }
3030 };
3031 
3032 
3033 class InductionVariableData;
3034 
3035 
3037  InductionVariableData* updated_variable;
3041 
3045 };
3046 
3047 
3048 class HBoundsCheck;
3049 class HPhi;
3050 class HBitwise;
3051 
3052 
3053 class InductionVariableData FINAL : public ZoneObject {
3054  public:
3056  public:
3057  HBoundsCheck* check() { return check_; }
3058  InductionVariableCheck* next() { return next_; }
3059  bool HasUpperLimit() { return upper_limit_ >= 0; }
3061  DCHECK(HasUpperLimit());
3062  return upper_limit_;
3063  }
3064  void set_upper_limit(int32_t upper_limit) {
3065  upper_limit_ = upper_limit;
3066  }
3067 
3068  bool processed() { return processed_; }
3069  void set_processed() { processed_ = true; }
3070 
3071  InductionVariableCheck(HBoundsCheck* check,
3072  InductionVariableCheck* next,
3073  int32_t upper_limit = kNoLimit)
3074  : check_(check), next_(next), upper_limit_(upper_limit),
3075  processed_(false) {}
3076 
3077  private:
3078  HBoundsCheck* check_;
3082  };
3083 
3085  public:
3086  HValue* length() { return length_; }
3087  ChecksRelatedToLength* next() { return next_; }
3088  InductionVariableCheck* checks() { return checks_; }
3089 
3090  void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3092 
3094  : length_(length), next_(next), checks_(NULL),
3095  first_check_in_block_(NULL),
3096  added_index_(NULL),
3097  added_constant_(NULL),
3098  current_and_mask_in_block_(0),
3099  current_or_mask_in_block_(0) {}
3100 
3101  private:
3103  int32_t mask,
3104  HValue* index_base,
3105  HValue* context);
3106 
3107  HBoundsCheck* first_check_in_block() { return first_check_in_block_; }
3108  HBitwise* added_index() { return added_index_; }
3109  void set_added_index(HBitwise* index) { added_index_ = index; }
3110  HConstant* added_constant() { return added_constant_; }
3111  void set_added_constant(HConstant* constant) { added_constant_ = constant; }
3112  int32_t current_and_mask_in_block() { return current_and_mask_in_block_; }
3113  int32_t current_or_mask_in_block() { return current_or_mask_in_block_; }
3114  int32_t current_upper_limit() { return current_upper_limit_; }
3115 
3119 
3120  HBoundsCheck* first_check_in_block_;
3121  HBitwise* added_index_;
3122  HConstant* added_constant_;
3126  };
3127 
3129  InductionVariableData* variable;
3132  HBasicBlock* other_target;
3133 
3134  bool LimitIsValid() { return token != Token::ILLEGAL; }
3135 
3137  return Token::IsEqualityOp(token) ||
3138  token == Token::GTE || token == Token::LTE;
3139  }
3140  bool LimitIsUpper() {
3141  return token == Token::LTE || token == Token::LT || token == Token::NE;
3142  }
3143 
3145  : variable(NULL),
3146  token(Token::ILLEGAL),
3147  limit(NULL),
3148  other_target(NULL) {}
3149  };
3150 
3151  static const int32_t kNoLimit = -1;
3152 
3153  static InductionVariableData* ExaminePhi(HPhi* phi);
3155  HBasicBlock* block,
3156  LimitFromPredecessorBlock* result);
3158  HBasicBlock* block,
3159  InductionVariableLimitUpdate* additional_limit);
3160 
3166 
3168  : base(NULL), and_mask(0), or_mask(0), context(NULL) {}
3169  };
3170  static void DecomposeBitwise(HValue* value,
3171  BitwiseDecompositionResult* result);
3172 
3173  void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3174 
3176  HBasicBlock* current_branch,
3177  HBasicBlock* other_branch);
3178 
3180 
3181  HPhi* phi() { return phi_; }
3182  HValue* base() { return base_; }
3183  int32_t increment() { return increment_; }
3184  HValue* limit() { return limit_; }
3185  bool limit_included() { return limit_included_; }
3186  HBasicBlock* limit_validity() { return limit_validity_; }
3187  HBasicBlock* induction_exit_block() { return induction_exit_block_; }
3188  HBasicBlock* induction_exit_target() { return induction_exit_target_; }
3189  ChecksRelatedToLength* checks() { return checks_; }
3190  HValue* additional_upper_limit() { return additional_upper_limit_; }
3192  return additional_upper_limit_is_included_;
3193  }
3194  HValue* additional_lower_limit() { return additional_lower_limit_; }
3196  return additional_lower_limit_is_included_;
3197  }
3198 
3200  if (base()->IsInteger32Constant() && base()->GetInteger32Constant() >= 0) {
3201  return true;
3202  }
3203  if (additional_lower_limit() != NULL &&
3204  additional_lower_limit()->IsInteger32Constant() &&
3205  additional_lower_limit()->GetInteger32Constant() >= 0) {
3206  // Ignoring the corner case of !additional_lower_limit_is_included()
3207  // is safe, handling it adds unneeded complexity.
3208  return true;
3209  }
3210  return false;
3211  }
3212 
3214 
3215  private:
3216  template <class T> void swap(T* a, T* b) {
3217  T c(*a);
3218  *a = *b;
3219  *b = c;
3220  }
3221 
3222  InductionVariableData(HPhi* phi, HValue* base, int32_t increment)
3223  : phi_(phi), base_(IgnoreOsrValue(base)), increment_(increment),
3224  limit_(NULL), limit_included_(false), limit_validity_(NULL),
3225  induction_exit_block_(NULL), induction_exit_target_(NULL),
3226  checks_(NULL),
3227  additional_upper_limit_(NULL),
3228  additional_upper_limit_is_included_(false),
3229  additional_lower_limit_(NULL),
3230  additional_lower_limit_is_included_(false) {}
3231 
3232  static int32_t ComputeIncrement(HPhi* phi, HValue* phi_operand);
3233 
3235  static InductionVariableData* GetInductionVariableData(HValue* v);
3236 
3237  HPhi* phi_;
3242  HBasicBlock* limit_validity_;
3250 };
3251 
3252 
3253 class HPhi FINAL : public HValue {
3254  public:
3255  HPhi(int merged_index, Zone* zone)
3256  : inputs_(2, zone),
3257  merged_index_(merged_index),
3258  phi_id_(-1),
3259  induction_variable_data_(NULL) {
3260  for (int i = 0; i < Representation::kNumRepresentations; i++) {
3261  non_phi_uses_[i] = 0;
3262  indirect_uses_[i] = 0;
3263  }
3264  DCHECK(merged_index >= 0 || merged_index == kInvalidMergedIndex);
3265  SetFlag(kFlexibleRepresentation);
3266  SetFlag(kAllowUndefinedAsNaN);
3267  }
3268 
3270 
3271  virtual Range* InferRange(Zone* zone) OVERRIDE;
3272  virtual void InferRepresentation(
3274  virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
3275  return representation();
3276  }
3278  return representation();
3279  }
3281  virtual int OperandCount() const OVERRIDE { return inputs_.length(); }
3282  virtual HValue* OperandAt(int index) const OVERRIDE {
3283  return inputs_[index];
3284  }
3286  void AddInput(HValue* value);
3287  bool HasRealUses();
3288 
3289  bool IsReceiver() const { return merged_index_ == 0; }
3290  bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
3291 
3293 
3294  int merged_index() const { return merged_index_; }
3295 
3296  InductionVariableData* induction_variable_data() {
3297  return induction_variable_data_;
3298  }
3300  return induction_variable_data_ != NULL;
3301  }
3303  return IsInductionVariable() &&
3304  induction_variable_data_->limit() != NULL;
3305  }
3307  DCHECK(induction_variable_data_ == NULL);
3308  induction_variable_data_ = InductionVariableData::ExaminePhi(this);
3309  }
3310 
3311  virtual OStream& PrintTo(OStream& os) const OVERRIDE; // NOLINT
3312 
3313 #ifdef DEBUG
3314  virtual void Verify() OVERRIDE;
3315 #endif
3316 
3317  void InitRealUses(int id);
3318  void AddNonPhiUsesFrom(HPhi* other);
3319  void AddIndirectUsesTo(int* use_count);
3320 
3321  int tagged_non_phi_uses() const {
3322  return non_phi_uses_[Representation::kTagged];
3323  }
3324  int smi_non_phi_uses() const {
3325  return non_phi_uses_[Representation::kSmi];
3326  }
3327  int int32_non_phi_uses() const {
3328  return non_phi_uses_[Representation::kInteger32];
3329  }
3330  int double_non_phi_uses() const {
3331  return non_phi_uses_[Representation::kDouble];
3332  }
3333  int tagged_indirect_uses() const {
3334  return indirect_uses_[Representation::kTagged];
3335  }
3336  int smi_indirect_uses() const {
3337  return indirect_uses_[Representation::kSmi];
3338  }
3339  int int32_indirect_uses() const {
3340  return indirect_uses_[Representation::kInteger32];
3341  }
3342  int double_indirect_uses() const {
3343  return indirect_uses_[Representation::kDouble];
3344  }
3345  int phi_id() { return phi_id_; }
3346 
3347  static HPhi* cast(HValue* value) {
3348  DCHECK(value->IsPhi());
3349  return reinterpret_cast<HPhi*>(value);
3350  }
3351  virtual Opcode opcode() const OVERRIDE { return HValue::kPhi; }
3352 
3354 
3355  // Marker value representing an invalid merge index.
3356  static const int kInvalidMergedIndex = -1;
3357 
3358  protected:
3359  virtual void DeleteFromGraph() OVERRIDE;
3360  virtual void InternalSetOperandAt(int index, HValue* value) OVERRIDE {
3361  inputs_[index] = value;
3362  }
3363 
3364  private:
3365  ZoneList<HValue*> inputs_;
3367 
3370  int phi_id_;
3371  InductionVariableData* induction_variable_data_;
3372 
3373  // TODO(titzer): we can't eliminate the receiver for generating backtraces
3374  virtual bool IsDeletable() const OVERRIDE { return !IsReceiver(); }
3375 };
3376 
3377 
3378 // Common base class for HArgumentsObject and HCapturedObject.
3380  public:
3381  HDematerializedObject(int count, Zone* zone) : values_(count, zone) {}
3382 
3383  virtual int OperandCount() const FINAL OVERRIDE {
3384  return values_.length();
3385  }
3386  virtual HValue* OperandAt(int index) const FINAL OVERRIDE {
3387  return values_[index];
3388  }
3389 
3390  virtual bool HasEscapingOperandAt(int index) FINAL OVERRIDE {
3391  return false;
3392  }
3394  int index) FINAL OVERRIDE {
3395  return Representation::None();
3396  }
3397 
3398  protected:
3399  virtual void InternalSetOperandAt(int index,
3400  HValue* value) FINAL OVERRIDE {
3401  values_[index] = value;
3402  }
3403 
3404  // List of values tracked by this marker.
3406 };
3407 
3408 
3409 class HArgumentsObject FINAL : public HDematerializedObject {
3410  public:
3411  static HArgumentsObject* New(Zone* zone, HValue* context, int count) {
3412  return new(zone) HArgumentsObject(count, zone);
3413  }
3414 
3415  // The values contain a list of all elements in the arguments object
3416  // including the receiver object, which is skipped when materializing.
3417  const ZoneList<HValue*>* arguments_values() const { return &values_; }
3418  int arguments_count() const { return values_.length(); }
3419 
3420  void AddArgument(HValue* argument, Zone* zone) {
3421  values_.Add(NULL, zone); // Resize list.
3422  SetOperandAt(values_.length() - 1, argument);
3423  }
3424 
3425  DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
3426 
3427  private:
3428  HArgumentsObject(int count, Zone* zone)
3429  : HDematerializedObject(count, zone) {
3430  set_representation(Representation::Tagged());
3431  SetFlag(kIsArguments);
3432  }
3433 };
3434 
3435 
3436 class HCapturedObject FINAL : public HDematerializedObject {
3437  public:
3438  HCapturedObject(int length, int id, Zone* zone)
3439  : HDematerializedObject(length, zone), capture_id_(id) {
3440  set_representation(Representation::Tagged());
3441  values_.AddBlock(NULL, length, zone); // Resize list.
3442  }
3443 
3444  // The values contain a list of all in-object properties inside the
3445  // captured object and is index by field index. Properties in the
3446  // properties or elements backing store are not tracked here.
3447  const ZoneList<HValue*>* values() const { return &values_; }
3448  int length() const { return values_.length(); }
3449  int capture_id() const { return capture_id_; }
3450 
3451  // Shortcut for the map value of this captured object.
3452  HValue* map_value() const { return values()->first(); }
3453 
3455  DCHECK(store->HasObservableSideEffects());
3456  DCHECK(store->IsStoreNamedField());
3457  changes_flags_.Add(store->ChangesFlags());
3458  }
3459 
3460  // Replay effects of this instruction on the given environment.
3461  void ReplayEnvironment(HEnvironment* env);
3462 
3463  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
3464 
3465  DECLARE_CONCRETE_INSTRUCTION(CapturedObject)
3466 
3467  private:
3469 
3470  // Note that we cannot DCE captured objects as they are used to replay
3471  // the environment. This method is here as an explicit reminder.
3472  // TODO(mstarzinger): Turn HSimulates into full snapshots maybe?
3473  virtual bool IsDeletable() const FINAL OVERRIDE { return false; }
3474 };
3475 
3476 
3477 class HConstant FINAL : public HTemplateInstruction<0> {
3478  public:
3483  DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);
3484 
3485  static HConstant* CreateAndInsertAfter(Zone* zone,
3486  HValue* context,
3487  int32_t value,
3488  Representation representation,
3489  HInstruction* instruction) {
3490  return instruction->Append(HConstant::New(
3491  zone, context, value, representation));
3492  }
3493 
3495  Handle<Object> object = object_.handle();
3496  if (!object.is_null() && object->IsHeapObject()) {
3497  return v8::internal::handle(HeapObject::cast(*object)->map());
3498  }
3499  return Handle<Map>();
3500  }
3501 
3502  static HConstant* CreateAndInsertBefore(Zone* zone,
3503  HValue* context,
3504  int32_t value,
3505  Representation representation,
3506  HInstruction* instruction) {
3507  return instruction->Prepend(HConstant::New(
3508  zone, context, value, representation));
3509  }
3510 
3511  static HConstant* CreateAndInsertBefore(Zone* zone,
3512  Unique<Map> map,
3513  bool map_is_stable,
3514  HInstruction* instruction) {
3515  return instruction->Prepend(new(zone) HConstant(
3516  map, Unique<Map>(Handle<Map>::null()), map_is_stable,
3517  Representation::Tagged(), HType::HeapObject(), true,
3518  false, false, MAP_TYPE));
3519  }
3520 
3521  static HConstant* CreateAndInsertAfter(Zone* zone,
3522  Unique<Map> map,
3523  bool map_is_stable,
3524  HInstruction* instruction) {
3525  return instruction->Append(new(zone) HConstant(
3526  map, Unique<Map>(Handle<Map>::null()), map_is_stable,
3527  Representation::Tagged(), HType::HeapObject(), true,
3528  false, false, MAP_TYPE));
3529  }
3530 
3532  if (object_.handle().is_null()) {
3533  // Default arguments to is_not_in_new_space depend on this heap number
3534  // to be tenured so that it's guaranteed not to be located in new space.
3536  isolate->factory()->NewNumber(double_value_, TENURED));
3537  }
3539  DCHECK(has_int32_value_ || !object_.handle()->IsSmi());
3540  return object_.handle();
3541  }
3542 
3543  bool IsSpecialDouble() const {
3544  return has_double_value_ &&
3545  (bit_cast<int64_t>(double_value_) == bit_cast<int64_t>(-0.0) ||
3546  FixedDoubleArray::is_the_hole_nan(double_value_) ||
3547  std::isnan(double_value_));
3548  }
3549 
3550  bool NotInNewSpace() const {
3551  return is_not_in_new_space_;
3552  }
3553 
3554  bool ImmortalImmovable() const;
3555 
3556  bool IsCell() const {
3557  return instance_type_ == CELL_TYPE || instance_type_ == PROPERTY_CELL_TYPE;
3558  }
3559 
3560  bool IsMap() const {
3561  return instance_type_ == MAP_TYPE;
3562  }
3563 
3565  return Representation::None();
3566  }
3567 
3569  if (HasSmiValue() && SmiValuesAre31Bits()) return Representation::Smi();
3570  if (HasInteger32Value()) return Representation::Integer32();
3571  if (HasNumberValue()) return Representation::Double();
3572  if (HasExternalReferenceValue()) return Representation::External();
3573  return Representation::Tagged();
3574  }
3575 
3576  virtual bool EmitAtUses() OVERRIDE;
3577  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
3578  HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
3579  Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone);
3580  Maybe<HConstant*> CopyToTruncatedNumber(Zone* zone);
3581  bool HasInteger32Value() const { return has_int32_value_; }
3583  DCHECK(HasInteger32Value());
3584  return int32_value_;
3585  }
3586  bool HasSmiValue() const { return has_smi_value_; }
3587  bool HasDoubleValue() const { return has_double_value_; }
3588  double DoubleValue() const {
3589  DCHECK(HasDoubleValue());
3590  return double_value_;
3591  }
3592  bool IsTheHole() const {
3593  if (HasDoubleValue() && FixedDoubleArray::is_the_hole_nan(double_value_)) {
3594  return true;
3595  }
3596  return object_.IsInitialized() &&
3597  object_.IsKnownGlobal(isolate()->heap()->the_hole_value());
3598  }
3599  bool HasNumberValue() const { return has_double_value_; }
3601  DCHECK(HasNumberValue());
3602  // Irrespective of whether a numeric HConstant can be safely
3603  // represented as an int32, we store the (in some cases lossy)
3604  // representation of the number in int32_value_.
3605  return int32_value_;
3606  }
3607  bool HasStringValue() const {
3608  if (has_double_value_ || has_int32_value_) return false;
3609  DCHECK(!object_.handle().is_null());
3610  return instance_type_ < FIRST_NONSTRING_TYPE;
3611  }
3613  DCHECK(HasStringValue());
3614  return Handle<String>::cast(object_.handle());
3615  }
3617  return HasStringValue() && StringShape(instance_type_).IsInternalized();
3618  }
3619 
3621  return has_external_reference_value_;
3622  }
3623  ExternalReference ExternalReferenceValue() const {
3624  return external_reference_value_;
3625  }
3626 
3627  bool HasBooleanValue() const { return type_.IsBoolean(); }
3628  bool BooleanValue() const { return boolean_value_; }
3629  bool IsUndetectable() const { return is_undetectable_; }
3630  InstanceType GetInstanceType() const { return instance_type_; }
3631 
3632  bool HasMapValue() const { return instance_type_ == MAP_TYPE; }
3634  DCHECK(HasMapValue());
3635  return Unique<Map>::cast(GetUnique());
3636  }
3637  bool HasStableMapValue() const {
3638  DCHECK(HasMapValue() || !has_stable_map_value_);
3639  return has_stable_map_value_;
3640  }
3641 
3642  bool HasObjectMap() const { return !object_map_.IsNull(); }
3644  DCHECK(HasObjectMap());
3645  return object_map_;
3646  }
3647 
3648  virtual intptr_t Hashcode() OVERRIDE {
3649  if (has_int32_value_) {
3650  return static_cast<intptr_t>(int32_value_);
3651  } else if (has_double_value_) {
3652  return static_cast<intptr_t>(bit_cast<int64_t>(double_value_));
3653  } else if (has_external_reference_value_) {
3654  return reinterpret_cast<intptr_t>(external_reference_value_.address());
3655  } else {
3656  DCHECK(!object_.handle().is_null());
3657  return object_.Hashcode();
3658  }
3659  }
3660 
3661  virtual void FinalizeUniqueness() OVERRIDE {
3662  if (!has_double_value_ && !has_external_reference_value_) {
3663  DCHECK(!object_.handle().is_null());
3664  object_ = Unique<Object>(object_.handle());
3665  }
3666  }
3667 
3669  return object_;
3670  }
3671 
3672  bool EqualsUnique(Unique<Object> other) const {
3673  return object_.IsInitialized() && object_ == other;
3674  }
3675 
3676  virtual bool DataEquals(HValue* other) OVERRIDE {
3677  HConstant* other_constant = HConstant::cast(other);
3678  if (has_int32_value_) {
3679  return other_constant->has_int32_value_ &&
3680  int32_value_ == other_constant->int32_value_;
3681  } else if (has_double_value_) {
3682  return other_constant->has_double_value_ &&
3683  bit_cast<int64_t>(double_value_) ==
3684  bit_cast<int64_t>(other_constant->double_value_);
3685  } else if (has_external_reference_value_) {
3686  return other_constant->has_external_reference_value_ &&
3687  external_reference_value_ ==
3688  other_constant->external_reference_value_;
3689  } else {
3690  if (other_constant->has_int32_value_ ||
3691  other_constant->has_double_value_ ||
3692  other_constant->has_external_reference_value_) {
3693  return false;
3694  }
3695  DCHECK(!object_.handle().is_null());
3696  return other_constant->object_ == object_;
3697  }
3698  }
3699 
3700 #ifdef DEBUG
3701  virtual void Verify() OVERRIDE { }
3702 #endif
3703 
3705 
3706  protected:
3707  virtual Range* InferRange(Zone* zone) OVERRIDE;
3708 
3709  private:
3710  friend class HGraph;
3715  bool is_not_in_new_space = true,
3717  HConstant(double value,
3719  bool is_not_in_new_space = true,
3722  Unique<Map> object_map,
3723  bool has_stable_map_value,
3724  Representation r,
3725  HType type,
3726  bool is_not_in_new_space,
3727  bool boolean_value,
3728  bool is_undetectable,
3729  InstanceType instance_type);
3730 
3731  explicit HConstant(ExternalReference reference);
3732 
3734 
3735  virtual bool IsDeletable() const OVERRIDE { return true; }
3736 
3737  // If this is a numerical constant, object_ either points to the
3738  // HeapObject the constant originated from or is null. If the
3739  // constant is non-numeric, object_ always points to a valid
3740  // constant HeapObject.
3742 
3743  // If object_ is a heap object, this points to the stable map of the object.
3745 
3746  // If object_ is a map, this indicates whether the map is stable.
3748 
3749  // We store the HConstant in the most specific form safely possible.
3750  // The two flags, has_int32_value_ and has_double_value_ tell us if
3751  // int32_value_ and double_value_ hold valid, safe representations
3752  // of the constant. has_int32_value_ implies has_double_value_ but
3753  // not the converse.
3754  bool has_smi_value_ : 1;
3759  bool boolean_value_ : 1;
3763  ExternalReference external_reference_value_;
3764 
3765  static const InstanceType kUnknownInstanceType = FILLER_TYPE;
3767 };
3768 
3769 
3771  public:
3773  HType type = HType::Tagged())
3774  : HTemplateInstruction<3>(type),
3776  DCHECK(left != NULL && right != NULL);
3777  SetOperandAt(0, context);
3778  SetOperandAt(1, left);
3779  SetOperandAt(2, right);
3782  }
3783 
3784  HValue* context() const { return OperandAt(0); }
3785  HValue* left() const { return OperandAt(1); }
3786  HValue* right() const { return OperandAt(2); }
3787 
3788  // True if switching left and right operands likely generates better code.
3790  if (!IsCommutative()) return false;
3791 
3792  // Constant operands are better off on the right, they can be inlined in
3793  // many situations on most platforms.
3794  if (left()->IsConstant()) return true;
3795  if (right()->IsConstant()) return false;
3796 
3797  // Otherwise, if there is only one use of the right operand, it would be
3798  // better off on the left for platforms that only have 2-arg arithmetic
3799  // ops (e.g ia32, x64) that clobber the left operand.
3800  return right()->HasOneUse();
3801  }
3802 
3804  return AreOperandsBetterSwitched() ? right() : left();
3805  }
3806 
3808  return AreOperandsBetterSwitched() ? left() : right();
3809  }
3810 
3812  DCHECK(index >= 1 && index <= 2);
3813  observed_input_representation_[index - 1] = rep;
3814  }
3815 
3818  }
3819 
3821  if (index == 0) return Representation::Tagged();
3822  return observed_input_representation_[index - 1];
3823  }
3824 
3825  virtual void UpdateRepresentation(Representation new_rep,
3826  HInferRepresentationPhase* h_infer,
3827  const char* reason) OVERRIDE {
3828  Representation rep = !FLAG_smi_binop && new_rep.IsSmi()
3829  ? Representation::Integer32() : new_rep;
3830  HValue::UpdateRepresentation(rep, h_infer, reason);
3831  }
3832 
3833  virtual void InferRepresentation(
3838 
3839  virtual bool IsCommutative() const { return false; }
3840 
3841  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
3842 
3844  if (index == 0) return Representation::Tagged();
3845  return representation();
3846  }
3847 
3849  HSourcePosition left_pos,
3850  HSourcePosition right_pos) {
3851  set_operand_position(zone, 1, left_pos);
3852  set_operand_position(zone, 2, right_pos);
3853  }
3854 
3856  if (!right()->IsInteger32Constant()) return false;
3857  int32_t value = right()->GetInteger32Constant();
3858  if (value < 0) {
3859  return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(-value));
3860  }
3861  return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(value));
3862  }
3863 
3864  DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
3865 
3866  private:
3868 
3871 };
3872 
3873 
3874 class HWrapReceiver FINAL : public HTemplateInstruction<2> {
3875  public:
3877 
3878  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
3879 
3881  return Representation::Tagged();
3882  }
3883 
3884  HValue* receiver() const { return OperandAt(0); }
3885  HValue* function() const { return OperandAt(1); }
3886 
3888 
3889  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
3890  bool known_function() const { return known_function_; }
3891 
3892  DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
3893 
3894  private:
3895  HWrapReceiver(HValue* receiver, HValue* function) {
3896  known_function_ = function->IsConstant() &&
3897  HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
3898  set_representation(Representation::Tagged());
3899  SetOperandAt(0, receiver);
3900  SetOperandAt(1, function);
3901  SetFlag(kUseGVN);
3902  }
3903 
3905 };
3906 
3907 
3908 class HApplyArguments FINAL : public HTemplateInstruction<4> {
3909  public:
3911  HValue*);
3912 
3914  // The length is untagged, all other inputs are tagged.
3915  return (index == 2)
3918  }
3919 
3920  HValue* function() { return OperandAt(0); }
3921  HValue* receiver() { return OperandAt(1); }
3922  HValue* length() { return OperandAt(2); }
3923  HValue* elements() { return OperandAt(3); }
3924 
3925  DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
3926 
3927  private:
3929  HValue* receiver,
3930  HValue* length,
3931  HValue* elements) {
3932  set_representation(Representation::Tagged());
3933  SetOperandAt(0, function);
3934  SetOperandAt(1, receiver);
3935  SetOperandAt(2, length);
3936  SetOperandAt(3, elements);
3937  SetAllSideEffects();
3938  }
3939 };
3940 
3941 
3942 class HArgumentsElements FINAL : public HTemplateInstruction<0> {
3943  public:
3944  DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
3945 
3946  DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
3947 
3948  virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
3949  return Representation::None();
3950  }
3951 
3952  bool from_inlined() const { return from_inlined_; }
3953 
3954  protected:
3955  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
3956 
3957  private:
3958  explicit HArgumentsElements(bool from_inlined) : from_inlined_(from_inlined) {
3959  // The value produced by this instruction is a pointer into the stack
3960  // that looks as if it was a smi because of alignment.
3961  set_representation(Representation::Tagged());
3962  SetFlag(kUseGVN);
3963  }
3964 
3965  virtual bool IsDeletable() const OVERRIDE { return true; }
3966 
3968 };
3969 
3970 
3971 class HArgumentsLength FINAL : public HUnaryOperation {
3972  public:
3974 
3976  return Representation::Tagged();
3977  }
3978 
3979  DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
3980 
3981  protected:
3982  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
3983 
3984  private:
3985  explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
3986  set_representation(Representation::Integer32());
3987  SetFlag(kUseGVN);
3988  }
3989 
3990  virtual bool IsDeletable() const OVERRIDE { return true; }
3991 };
3992 
3993 
3994 class HAccessArgumentsAt FINAL : public HTemplateInstruction<3> {
3995  public:
3997 
3998  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
3999 
4001  // The arguments elements is considered tagged.
4002  return index == 0
4005  }
4006 
4007  HValue* arguments() const { return OperandAt(0); }
4008  HValue* length() const { return OperandAt(1); }
4009  HValue* index() const { return OperandAt(2); }
4010 
4011  DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
4012 
4013  private:
4014  HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
4015  set_representation(Representation::Tagged());
4016  SetFlag(kUseGVN);
4017  SetOperandAt(0, arguments);
4018  SetOperandAt(1, length);
4019  SetOperandAt(2, index);
4020  }
4021 
4022  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4023 };
4024 
4025 
4026 class HBoundsCheckBaseIndexInformation;
4027 
4028 
4029 class HBoundsCheck FINAL : public HTemplateInstruction<2> {
4030  public:
4032 
4033  bool skip_check() const { return skip_check_; }
4034  void set_skip_check() { skip_check_ = true; }
4035 
4036  HValue* base() const { return base_; }
4037  int offset() const { return offset_; }
4038  int scale() const { return scale_; }
4039 
4042  DCHECK(base() == NULL);
4043 
4044  DecompositionResult decomposition;
4045  if (index()->TryDecompose(&decomposition)) {
4046  base_ = decomposition.base();
4047  offset_ = decomposition.offset();
4048  scale_ = decomposition.scale();
4049  return true;
4050  } else {
4051  base_ = index();
4052  offset_ = 0;
4053  scale_ = 0;
4054  return false;
4055  }
4056  }
4057 
4059  return representation();
4060  }
4061 
4062  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4063  virtual void InferRepresentation(
4065 
4066  HValue* index() const { return OperandAt(0); }
4067  HValue* length() const { return OperandAt(1); }
4068  bool allow_equality() const { return allow_equality_; }
4069  void set_allow_equality(bool v) { allow_equality_ = v; }
4070 
4071  virtual int RedefinedOperandIndex() OVERRIDE { return 0; }
4073  return skip_check();
4074  }
4075 
4076  DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
4077 
4078  protected:
4079  friend class HBoundsCheckBaseIndexInformation;
4080 
4081  virtual Range* InferRange(Zone* zone) OVERRIDE;
4082 
4083  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4085  HValue* base_;
4086  int offset_;
4087  int scale_;
4089 
4090  private:
4091  // Normally HBoundsCheck should be created using the
4092  // HGraphBuilder::AddBoundsCheck() helper.
4093  // However when building stubs, where we know that the arguments are Int32,
4094  // it makes sense to invoke this constructor directly.
4095  HBoundsCheck(HValue* index, HValue* length)
4096  : skip_check_(false),
4097  base_(NULL), offset_(0), scale_(0),
4098  allow_equality_(false) {
4099  SetOperandAt(0, index);
4100  SetOperandAt(1, length);
4101  SetFlag(kFlexibleRepresentation);
4102  SetFlag(kUseGVN);
4103  }
4104 
4105  virtual bool IsDeletable() const OVERRIDE {
4106  return skip_check() && !FLAG_debug_code;
4107  }
4108 };
4109 
4110 
4111 class HBoundsCheckBaseIndexInformation FINAL
4112  : public HTemplateInstruction<2> {
4113  public:
4114  explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) {
4115  DecompositionResult decomposition;
4116  if (check->index()->TryDecompose(&decomposition)) {
4117  SetOperandAt(0, decomposition.base());
4118  SetOperandAt(1, check);
4119  } else {
4120  UNREACHABLE();
4121  }
4122  }
4123 
4124  HValue* base_index() const { return OperandAt(0); }
4125  HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); }
4126 
4127  DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation)
4128 
4129  virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4130  return representation();
4131  }
4132 
4133  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4134 
4135  virtual int RedefinedOperandIndex() OVERRIDE { return 0; }
4136  virtual bool IsPurelyInformativeDefinition() OVERRIDE { return true; }
4137 };
4138 
4139 
4141  public:
4143  HType type = HType::TaggedNumber())
4149  }
4150 
4152  if (to.IsTagged() &&
4155  ClearFlag(kUseGVN);
4156  } else {
4158  SetFlag(kUseGVN);
4159  }
4160  if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
4161  }
4162 
4163  virtual void UpdateRepresentation(Representation new_rep,
4164  HInferRepresentationPhase* h_infer,
4165  const char* reason) OVERRIDE {
4166  // We only generate either int32 or generic tagged bitwise operations.
4167  if (new_rep.IsDouble()) new_rep = Representation::Integer32();
4168  HBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4169  }
4170 
4173  if (r.IsDouble()) return Representation::Integer32();
4174  return r;
4175  }
4176 
4178  if (observed.IsDouble()) observed = Representation::Integer32();
4180  }
4181 
4182  DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
4183 
4184  private:
4185  virtual bool IsDeletable() const OVERRIDE { return true; }
4186 };
4187 
4188 
4189 class HMathFloorOfDiv FINAL : public HBinaryOperation {
4190  public:
4192  HValue*,
4193  HValue*);
4194 
4195  DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
4196 
4197  protected:
4198  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4199 
4200  private:
4201  HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
4202  : HBinaryOperation(context, left, right) {
4203  set_representation(Representation::Integer32());
4204  SetFlag(kUseGVN);
4205  SetFlag(kCanOverflow);
4206  SetFlag(kCanBeDivByZero);
4207  SetFlag(kLeftCanBeMinInt);
4208  SetFlag(kLeftCanBeNegative);
4209  SetFlag(kLeftCanBePositive);
4210  SetFlag(kAllowUndefinedAsNaN);
4211  }
4212 
4213  virtual Range* InferRange(Zone* zone) OVERRIDE;
4214 
4215  virtual bool IsDeletable() const OVERRIDE { return true; }
4216 };
4217 
4218 
4220  public:
4222  : HBinaryOperation(context, left, right, HType::TaggedNumber()) {
4226  }
4227 
4229  if (to.IsTagged() &&
4232  ClearFlag(kUseGVN);
4233  } else {
4235  SetFlag(kUseGVN);
4236  }
4237  if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
4238  }
4239 
4240  DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
4241 
4242  private:
4243  virtual bool IsDeletable() const OVERRIDE { return true; }
4244 };
4245 
4246 
4247 class HCompareGeneric FINAL : public HBinaryOperation {
4248  public:
4250  HValue*, Token::Value);
4251 
4253  return index == 0
4255  : representation();
4256  }
4257 
4258  Token::Value token() const { return token_; }
4259  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4260 
4261  DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
4262 
4263  private:
4265  HValue* left,
4266  HValue* right,
4267  Token::Value token)
4268  : HBinaryOperation(context, left, right, HType::Boolean()),
4269  token_(token) {
4270  DCHECK(Token::IsCompareOp(token));
4271  set_representation(Representation::Tagged());
4272  SetAllSideEffects();
4273  }
4274 
4276 };
4277 
4278 
4280  public:
4282  HValue*, HValue*, Token::Value);
4286 
4287  HValue* left() const { return OperandAt(0); }
4288  HValue* right() const { return OperandAt(1); }
4289  Token::Value token() const { return token_; }
4290 
4295  }
4296 
4297  virtual void InferRepresentation(
4299 
4301  return representation();
4302  }
4304  return observed_input_representation_[index];
4305  }
4306 
4308 
4309  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4310 
4312  HSourcePosition left_pos,
4313  HSourcePosition right_pos) {
4314  set_operand_position(zone, 0, left_pos);
4315  set_operand_position(zone, 1, right_pos);
4316  }
4317 
4318  DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
4319 
4320  private:
4322  HValue* right,
4324  HBasicBlock* true_target = NULL,
4325  HBasicBlock* false_target = NULL)
4326  : token_(token) {
4329  SetOperandAt(0, left);
4330  SetOperandAt(1, right);
4331  SetSuccessorAt(0, true_target);
4332  SetSuccessorAt(1, false_target);
4333  }
4334 
4337 };
4338 
4339 
4340 class HCompareHoleAndBranch FINAL : public HUnaryControlInstruction {
4341  public:
4342  DECLARE_INSTRUCTION_FACTORY_P1(HCompareHoleAndBranch, HValue*);
4343  DECLARE_INSTRUCTION_FACTORY_P3(HCompareHoleAndBranch, HValue*,
4344  HBasicBlock*, HBasicBlock*);
4345 
4346  virtual void InferRepresentation(
4348 
4350  return representation();
4351  }
4352 
4353  DECLARE_CONCRETE_INSTRUCTION(CompareHoleAndBranch)
4354 
4355  private:
4357  HBasicBlock* true_target = NULL,
4358  HBasicBlock* false_target = NULL)
4359  : HUnaryControlInstruction(value, true_target, false_target) {
4360  SetFlag(kFlexibleRepresentation);
4361  SetFlag(kAllowUndefinedAsNaN);
4362  }
4363 };
4364 
4365 
4366 class HCompareMinusZeroAndBranch FINAL : public HUnaryControlInstruction {
4367  public:
4368  DECLARE_INSTRUCTION_FACTORY_P1(HCompareMinusZeroAndBranch, HValue*);
4369 
4370  virtual void InferRepresentation(
4372 
4374  return representation();
4375  }
4376 
4377  virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE;
4378 
4379  DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch)
4380 
4381  private:
4383  : HUnaryControlInstruction(value, NULL, NULL) {
4384  }
4385 };
4386 
4387 
4389  public:
4393 
4395 
4396  static const int kNoKnownSuccessorIndex = -1;
4400  }
4401 
4402  HValue* left() const { return OperandAt(0); }
4403  HValue* right() const { return OperandAt(1); }
4404 
4405  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4406 
4408  return Representation::Tagged();
4409  }
4410 
4412  return Representation::Tagged();
4413  }
4414 
4415  DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
4416 
4417  private:
4419  HValue* right,
4420  HBasicBlock* true_target = NULL,
4421  HBasicBlock* false_target = NULL)
4423  SetOperandAt(0, left);
4424  SetOperandAt(1, right);
4425  SetSuccessorAt(0, true_target);
4426  SetSuccessorAt(1, false_target);
4427  }
4428 
4430 };
4431 
4432 
4433 class HIsObjectAndBranch FINAL : public HUnaryControlInstruction {
4434  public:
4437  HBasicBlock*, HBasicBlock*);
4438 
4440  return Representation::Tagged();
4441  }
4442 
4443  virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE;
4444 
4445  DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch)
4446 
4447  private:
4449  HBasicBlock* true_target = NULL,
4450  HBasicBlock* false_target = NULL)
4451  : HUnaryControlInstruction(value, true_target, false_target) {}
4452 };
4453 
4454 
4455 class HIsStringAndBranch FINAL : public HUnaryControlInstruction {
4456  public:
4459  HBasicBlock*, HBasicBlock*);
4460 
4462  return Representation::Tagged();
4463  }
4464 
4465  virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE;
4466 
4467  static const int kNoKnownSuccessorIndex = -1;
4468  int known_successor_index() const { return known_successor_index_; }
4469  void set_known_successor_index(int known_successor_index) {
4470  known_successor_index_ = known_successor_index;
4471  }
4472 
4473  DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
4474 
4475  protected:
4476  virtual int RedefinedOperandIndex() { return 0; }
4477 
4478  private:
4480  HBasicBlock* true_target = NULL,
4481  HBasicBlock* false_target = NULL)
4482  : HUnaryControlInstruction(value, true_target, false_target),
4483  known_successor_index_(kNoKnownSuccessorIndex) { }
4484 
4485  int known_successor_index_;
4486 };
4487 
4488 
4489 class HIsSmiAndBranch FINAL : public HUnaryControlInstruction {
4490  public:
4493  HBasicBlock*, HBasicBlock*);
4494 
4495  DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
4496 
4497  virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4498  return Representation::Tagged();
4499  }
4500 
4501  protected:
4502  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4503  virtual int RedefinedOperandIndex() { return 0; }
4504 
4505  private:
4507  HBasicBlock* true_target = NULL,
4508  HBasicBlock* false_target = NULL)
4509  : HUnaryControlInstruction(value, true_target, false_target) {
4510  set_representation(Representation::Tagged());
4511  }
4512 };
4513 
4514 
4515 class HIsUndetectableAndBranch FINAL : public HUnaryControlInstruction {
4516  public:
4517  DECLARE_INSTRUCTION_FACTORY_P1(HIsUndetectableAndBranch, HValue*);
4518  DECLARE_INSTRUCTION_FACTORY_P3(HIsUndetectableAndBranch, HValue*,
4519  HBasicBlock*, HBasicBlock*);
4520 
4522  return Representation::Tagged();
4523  }
4524 
4525  virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE;
4526 
4527  DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
4528 
4529  private:
4531  HBasicBlock* true_target = NULL,
4532  HBasicBlock* false_target = NULL)
4533  : HUnaryControlInstruction(value, true_target, false_target) {}
4534 };
4535 
4536 
4538  public:
4540  HValue*,
4541  HValue*,
4542  Token::Value);
4543 
4544  HValue* context() { return OperandAt(0); }
4545  HValue* left() { return OperandAt(1); }
4546  HValue* right() { return OperandAt(2); }
4547  Token::Value token() const { return token_; }
4548 
4549  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4550 
4552  return Representation::Tagged();
4553  }
4554 
4556  return Representation::Tagged();
4557  }
4558 
4559  DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
4560 
4561  private:
4563  HValue* left,
4564  HValue* right,
4566  : token_(token) {
4568  SetOperandAt(0, context);
4569  SetOperandAt(1, left);
4570  SetOperandAt(2, right);
4572  SetChangesFlag(kNewSpacePromotion);
4573  }
4574 
4576 };
4577 
4578 
4580  public:
4582 
4584  return Representation::None();
4585  }
4586 
4587  DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch)
4588  private:
4590 };
4591 
4592 
4593 class HHasInstanceTypeAndBranch FINAL : public HUnaryControlInstruction {
4594  public:
4596  HHasInstanceTypeAndBranch, HValue*, InstanceType);
4598  HHasInstanceTypeAndBranch, HValue*, InstanceType, InstanceType);
4599 
4600  InstanceType from() { return from_; }
4601  InstanceType to() { return to_; }
4602 
4603  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4604 
4606  return Representation::Tagged();
4607  }
4608 
4609  virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE;
4610 
4611  DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
4612 
4613  private:
4615  : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
4617  : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
4618  DCHECK(to == LAST_TYPE); // Others not implemented yet in backend.
4619  }
4620 
4622  InstanceType to_; // Inclusive range, not all combinations work.
4623 };
4624 
4625 
4626 class HHasCachedArrayIndexAndBranch FINAL : public HUnaryControlInstruction {
4627  public:
4628  DECLARE_INSTRUCTION_FACTORY_P1(HHasCachedArrayIndexAndBranch, HValue*);
4629 
4631  return Representation::Tagged();
4632  }
4633 
4634  DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
4635  private:
4637  : HUnaryControlInstruction(value, NULL, NULL) { }
4638 };
4639 
4640 
4641 class HGetCachedArrayIndex FINAL : public HUnaryOperation {
4642  public:
4643  DECLARE_INSTRUCTION_FACTORY_P1(HGetCachedArrayIndex, HValue*);
4644 
4646  return Representation::Tagged();
4647  }
4648 
4649  DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
4650 
4651  protected:
4652  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4653 
4654  private:
4655  explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
4656  set_representation(Representation::Tagged());
4657  SetFlag(kUseGVN);
4658  }
4659 
4660  virtual bool IsDeletable() const OVERRIDE { return true; }
4661 };
4662 
4663 
4664 class HClassOfTestAndBranch FINAL : public HUnaryControlInstruction {
4665  public:
4666  DECLARE_INSTRUCTION_FACTORY_P2(HClassOfTestAndBranch, HValue*,
4667  Handle<String>);
4668 
4669  DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
4670 
4671  virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4672  return Representation::Tagged();
4673  }
4674 
4675  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4676 
4677  Handle<String> class_name() const { return class_name_; }
4678 
4679  private:
4681  : HUnaryControlInstruction(value, NULL, NULL),
4682  class_name_(class_name) { }
4683 
4685 };
4686 
4687 
4688 class HTypeofIsAndBranch FINAL : public HUnaryControlInstruction {
4689  public:
4691 
4692  Handle<String> type_literal() const { return type_literal_.handle(); }
4693  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4694 
4695  DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
4696 
4697  virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4698  return Representation::None();
4699  }
4700 
4701  virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE;
4702 
4703  virtual void FinalizeUniqueness() OVERRIDE {
4704  type_literal_ = Unique<String>(type_literal_.handle());
4705  }
4706 
4707  private:
4709  : HUnaryControlInstruction(value, NULL, NULL),
4710  type_literal_(Unique<String>::CreateUninitialized(type_literal)) { }
4711 
4713 };
4714 
4715 
4716 class HInstanceOf FINAL : public HBinaryOperation {
4717  public:
4719 
4721  return Representation::Tagged();
4722  }
4723 
4724  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4725 
4726  DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
4727 
4728  private:
4729  HInstanceOf(HValue* context, HValue* left, HValue* right)
4730  : HBinaryOperation(context, left, right, HType::Boolean()) {
4731  set_representation(Representation::Tagged());
4732  SetAllSideEffects();
4733  }
4734 };
4735 
4736 
4737 class HInstanceOfKnownGlobal FINAL : public HTemplateInstruction<2> {
4738  public:
4740  HValue*,
4742 
4743  HValue* context() { return OperandAt(0); }
4744  HValue* left() { return OperandAt(1); }
4745  Handle<JSFunction> function() { return function_; }
4746 
4748  return Representation::Tagged();
4749  }
4750 
4751  DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal)
4752 
4753  private:
4755  HValue* left,
4756  Handle<JSFunction> right)
4757  : HTemplateInstruction<2>(HType::Boolean()), function_(right) {
4758  SetOperandAt(0, context);
4759  SetOperandAt(1, left);
4760  set_representation(Representation::Tagged());
4761  SetAllSideEffects();
4762  }
4763 
4765 };
4766 
4767 
4768 class HPower FINAL : public HTemplateInstruction<2> {
4769  public:
4770  static HInstruction* New(Zone* zone,
4771  HValue* context,
4772  HValue* left,
4773  HValue* right);
4774 
4775  HValue* left() { return OperandAt(0); }
4776  HValue* right() const { return OperandAt(1); }
4777 
4779  return index == 0
4782  }
4784  return RequiredInputRepresentation(index);
4785  }
4786 
4788 
4789  protected:
4790  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4791 
4792  private:
4793  HPower(HValue* left, HValue* right) {
4794  SetOperandAt(0, left);
4795  SetOperandAt(1, right);
4796  set_representation(Representation::Double());
4797  SetFlag(kUseGVN);
4798  SetChangesFlag(kNewSpacePromotion);
4799  }
4800 
4801  virtual bool IsDeletable() const OVERRIDE {
4802  return !right()->representation().IsTagged();
4803  }
4804 };
4805 
4806 
4807 class HAdd FINAL : public HArithmeticBinaryOperation {
4808  public:
4809  static HInstruction* New(Zone* zone,
4810  HValue* context,
4811  HValue* left,
4812  HValue* right);
4813 
4814  // Add is only commutative if two integer values are added and not if two
4815  // tagged values are added (because it might be a String concatenation).
4816  // We also do not commute (pointer + offset).
4817  virtual bool IsCommutative() const OVERRIDE {
4818  return !representation().IsTagged() && !representation().IsExternal();
4819  }
4820 
4822 
4823  virtual bool TryDecompose(DecompositionResult* decomposition) OVERRIDE {
4824  if (left()->IsInteger32Constant()) {
4825  decomposition->Apply(right(), left()->GetInteger32Constant());
4826  return true;
4827  } else if (right()->IsInteger32Constant()) {
4828  decomposition->Apply(left(), right()->GetInteger32Constant());
4829  return true;
4830  } else {
4831  return false;
4832  }
4833  }
4834 
4836  if (to.IsTagged() &&
4837  (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() ||
4838  left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) {
4839  SetAllSideEffects();
4840  ClearFlag(kUseGVN);
4841  } else {
4842  ClearAllSideEffects();
4843  SetFlag(kUseGVN);
4844  }
4845  if (to.IsTagged()) {
4846  SetChangesFlag(kNewSpacePromotion);
4847  ClearFlag(kAllowUndefinedAsNaN);
4848  }
4849  }
4850 
4852 
4853  virtual Representation RequiredInputRepresentation(int index) OVERRIDE;
4854 
4856 
4857  protected:
4858  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4859 
4860  virtual Range* InferRange(Zone* zone) OVERRIDE;
4861 
4862  private:
4863  HAdd(HValue* context, HValue* left, HValue* right)
4864  : HArithmeticBinaryOperation(context, left, right) {
4865  SetFlag(kCanOverflow);
4866  }
4867 };
4868 
4869 
4870 class HSub FINAL : public HArithmeticBinaryOperation {
4871  public:
4872  static HInstruction* New(Zone* zone,
4873  HValue* context,
4874  HValue* left,
4875  HValue* right);
4876 
4878 
4879  virtual bool TryDecompose(DecompositionResult* decomposition) OVERRIDE {
4880  if (right()->IsInteger32Constant()) {
4881  decomposition->Apply(left(), -right()->GetInteger32Constant());
4882  return true;
4883  } else {
4884  return false;
4885  }
4886  }
4887 
4889 
4890  protected:
4891  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4892 
4893  virtual Range* InferRange(Zone* zone) OVERRIDE;
4894 
4895  private:
4896  HSub(HValue* context, HValue* left, HValue* right)
4897  : HArithmeticBinaryOperation(context, left, right) {
4898  SetFlag(kCanOverflow);
4899  }
4900 };
4901 
4902 
4903 class HMul FINAL : public HArithmeticBinaryOperation {
4904  public:
4905  static HInstruction* New(Zone* zone,
4906  HValue* context,
4907  HValue* left,
4908  HValue* right);
4909 
4910  static HInstruction* NewImul(Zone* zone,
4911  HValue* context,
4912  HValue* left,
4913  HValue* right) {
4914  HInstruction* instr = HMul::New(zone, context, left, right);
4915  if (!instr->IsMul()) return instr;
4916  HMul* mul = HMul::cast(instr);
4917  // TODO(mstarzinger): Prevent bailout on minus zero for imul.
4918  mul->AssumeRepresentation(Representation::Integer32());
4919  mul->ClearFlag(HValue::kCanOverflow);
4920  return mul;
4921  }
4922 
4924 
4925  // Only commutative if it is certain that not two objects are multiplicated.
4926  virtual bool IsCommutative() const OVERRIDE {
4927  return !representation().IsTagged();
4928  }
4929 
4930  virtual void UpdateRepresentation(Representation new_rep,
4931  HInferRepresentationPhase* h_infer,
4932  const char* reason) OVERRIDE {
4933  HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4934  }
4935 
4936  bool MulMinusOne();
4937 
4939 
4940  protected:
4941  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4942 
4943  virtual Range* InferRange(Zone* zone) OVERRIDE;
4944 
4945  private:
4946  HMul(HValue* context, HValue* left, HValue* right)
4947  : HArithmeticBinaryOperation(context, left, right) {
4948  SetFlag(kCanOverflow);
4949  }
4950 };
4951 
4952 
4953 class HMod FINAL : public HArithmeticBinaryOperation {
4954  public:
4955  static HInstruction* New(Zone* zone,
4956  HValue* context,
4957  HValue* left,
4958  HValue* right);
4959 
4961 
4962  virtual void UpdateRepresentation(Representation new_rep,
4963  HInferRepresentationPhase* h_infer,
4964  const char* reason) OVERRIDE {
4965  if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4966  HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4967  }
4968 
4970 
4971  protected:
4972  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4973 
4974  virtual Range* InferRange(Zone* zone) OVERRIDE;
4975 
4976  private:
4977  HMod(HValue* context,
4978  HValue* left,
4979  HValue* right) : HArithmeticBinaryOperation(context, left, right) {
4980  SetFlag(kCanBeDivByZero);
4981  SetFlag(kCanOverflow);
4982  SetFlag(kLeftCanBeNegative);
4983  }
4984 };
4985 
4986 
4987 class HDiv FINAL : public HArithmeticBinaryOperation {
4988  public:
4989  static HInstruction* New(Zone* zone,
4990  HValue* context,
4991  HValue* left,
4992  HValue* right);
4993 
4995 
4996  virtual void UpdateRepresentation(Representation new_rep,
4997  HInferRepresentationPhase* h_infer,
4998  const char* reason) OVERRIDE {
4999  if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5000  HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5001  }
5002 
5004 
5005  protected:
5006  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
5007 
5008  virtual Range* InferRange(Zone* zone) OVERRIDE;
5009 
5010  private:
5011  HDiv(HValue* context, HValue* left, HValue* right)
5012  : HArithmeticBinaryOperation(context, left, right) {
5013  SetFlag(kCanBeDivByZero);
5014  SetFlag(kCanOverflow);
5015  }
5016 };
5017 
5018 
5019 class HMathMinMax FINAL : public HArithmeticBinaryOperation {
5020  public:
5021  enum Operation { kMathMin, kMathMax };
5022 
5023  static HInstruction* New(Zone* zone,
5024  HValue* context,
5025  HValue* left,
5026  HValue* right,
5027  Operation op);
5028 
5030  return RequiredInputRepresentation(index);
5031  }
5032 
5033  virtual void InferRepresentation(
5035 
5037  Representation left_rep = left()->representation();
5038  Representation right_rep = right()->representation();
5040  result = result.generalize(left_rep);
5041  result = result.generalize(right_rep);
5042  if (result.IsTagged()) return Representation::Double();
5043  return result;
5044  }
5045 
5046  virtual bool IsCommutative() const OVERRIDE { return true; }
5047 
5048  Operation operation() { return operation_; }
5049 
5050  DECLARE_CONCRETE_INSTRUCTION(MathMinMax)
5051 
5052  protected:
5053  virtual bool DataEquals(HValue* other) OVERRIDE {
5054  return other->IsMathMinMax() &&
5055  HMathMinMax::cast(other)->operation_ == operation_;
5056  }
5057 
5058  virtual Range* InferRange(Zone* zone) OVERRIDE;
5059 
5060  private:
5061  HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
5062  : HArithmeticBinaryOperation(context, left, right),
5063  operation_(op) { }
5064 
5066 };
5067 
5068 
5069 class HBitwise FINAL : public HBitwiseBinaryOperation {
5070  public:
5071  static HInstruction* New(Zone* zone,
5072  HValue* context,
5073  Token::Value op,
5074  HValue* left,
5075  HValue* right);
5076 
5077  Token::Value op() const { return op_; }
5078 
5079  virtual bool IsCommutative() const OVERRIDE { return true; }
5080 
5082 
5083  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5084 
5086 
5087  protected:
5088  virtual bool DataEquals(HValue* other) OVERRIDE {
5089  return op() == HBitwise::cast(other)->op();
5090  }
5091 
5092  virtual Range* InferRange(Zone* zone) OVERRIDE;
5093 
5094  private:
5095  HBitwise(HValue* context,
5096  Token::Value op,
5097  HValue* left,
5098  HValue* right)
5099  : HBitwiseBinaryOperation(context, left, right),
5100  op_(op) {
5101  DCHECK(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
5102  // BIT_AND with a smi-range positive value will always unset the
5103  // entire sign-extension of the smi-sign.
5104  if (op == Token::BIT_AND &&
5105  ((left->IsConstant() &&
5106  left->representation().IsSmi() &&
5107  HConstant::cast(left)->Integer32Value() >= 0) ||
5108  (right->IsConstant() &&
5109  right->representation().IsSmi() &&
5110  HConstant::cast(right)->Integer32Value() >= 0))) {
5111  SetFlag(kTruncatingToSmi);
5112  SetFlag(kTruncatingToInt32);
5113  // BIT_OR with a smi-range negative value will always set the entire
5114  // sign-extension of the smi-sign.
5115  } else if (op == Token::BIT_OR &&
5116  ((left->IsConstant() &&
5117  left->representation().IsSmi() &&
5118  HConstant::cast(left)->Integer32Value() < 0) ||
5119  (right->IsConstant() &&
5120  right->representation().IsSmi() &&
5121  HConstant::cast(right)->Integer32Value() < 0))) {
5122  SetFlag(kTruncatingToSmi);
5123  SetFlag(kTruncatingToInt32);
5124  }
5125  }
5126 
5127  Token::Value op_;
5128 };
5129 
5130 
5131 class HShl FINAL : public HBitwiseBinaryOperation {
5132  public:
5133  static HInstruction* New(Zone* zone,
5134  HValue* context,
5135  HValue* left,
5136  HValue* right);
5137 
5138  virtual Range* InferRange(Zone* zone) OVERRIDE;
5139 
5140  virtual void UpdateRepresentation(Representation new_rep,
5141  HInferRepresentationPhase* h_infer,
5142  const char* reason) OVERRIDE {
5143  if (new_rep.IsSmi() &&
5144  !(right()->IsInteger32Constant() &&
5145  right()->GetInteger32Constant() >= 0)) {
5146  new_rep = Representation::Integer32();
5147  }
5148  HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5149  }
5150 
5152 
5153  protected:
5154  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
5155 
5156  private:
5157  HShl(HValue* context, HValue* left, HValue* right)
5158  : HBitwiseBinaryOperation(context, left, right) { }
5159 };
5160 
5161 
5162 class HShr FINAL : public HBitwiseBinaryOperation {
5163  public:
5164  static HInstruction* New(Zone* zone,
5165  HValue* context,
5166  HValue* left,
5167  HValue* right);
5168 
5169  virtual bool TryDecompose(DecompositionResult* decomposition) OVERRIDE {
5170  if (right()->IsInteger32Constant()) {
5171  if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
5172  // This is intended to look for HAdd and HSub, to handle compounds
5173  // like ((base + offset) >> scale) with one single decomposition.
5174  left()->TryDecompose(decomposition);
5175  return true;
5176  }
5177  }
5178  return false;
5179  }
5180 
5181  virtual Range* InferRange(Zone* zone) OVERRIDE;
5182 
5183  virtual void UpdateRepresentation(Representation new_rep,
5184  HInferRepresentationPhase* h_infer,
5185  const char* reason) OVERRIDE {
5186  if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5187  HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5188  }
5189 
5191 
5192  protected:
5193  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
5194 
5195  private:
5196  HShr(HValue* context, HValue* left, HValue* right)
5197  : HBitwiseBinaryOperation(context, left, right) { }
5198 };
5199 
5200 
5201 class HSar FINAL : public HBitwiseBinaryOperation {
5202  public:
5203  static HInstruction* New(Zone* zone,
5204  HValue* context,
5205  HValue* left,
5206  HValue* right);
5207 
5208  virtual bool TryDecompose(DecompositionResult* decomposition) OVERRIDE {
5209  if (right()->IsInteger32Constant()) {
5210  if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
5211  // This is intended to look for HAdd and HSub, to handle compounds
5212  // like ((base + offset) >> scale) with one single decomposition.
5213  left()->TryDecompose(decomposition);
5214  return true;
5215  }
5216  }
5217  return false;
5218  }
5219 
5220  virtual Range* InferRange(Zone* zone) OVERRIDE;
5221 
5222  virtual void UpdateRepresentation(Representation new_rep,
5223  HInferRepresentationPhase* h_infer,
5224  const char* reason) OVERRIDE {
5225  if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5226  HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5227  }
5228 
5230 
5231  protected:
5232  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
5233 
5234  private:
5235  HSar(HValue* context, HValue* left, HValue* right)
5236  : HBitwiseBinaryOperation(context, left, right) { }
5237 };
5238 
5239 
5240 class HRor FINAL : public HBitwiseBinaryOperation {
5241  public:
5242  static HInstruction* New(Zone* zone,
5243  HValue* context,
5244  HValue* left,
5245  HValue* right) {
5246  return new(zone) HRor(context, left, right);
5247  }
5248 
5249  virtual void UpdateRepresentation(Representation new_rep,
5250  HInferRepresentationPhase* h_infer,
5251  const char* reason) OVERRIDE {
5252  if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5253  HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5254  }
5255 
5257 
5258  protected:
5259  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
5260 
5261  private:
5262  HRor(HValue* context, HValue* left, HValue* right)
5263  : HBitwiseBinaryOperation(context, left, right) {
5264  ChangeRepresentation(Representation::Integer32());
5265  }
5266 };
5267 
5268 
5269 class HOsrEntry FINAL : public HTemplateInstruction<0> {
5270  public:
5272 
5273  BailoutId ast_id() const { return ast_id_; }
5274 
5276  return Representation::None();
5277  }
5278 
5280 
5281  private:
5282  explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
5283  SetChangesFlag(kOsrEntries);
5284  SetChangesFlag(kNewSpacePromotion);
5285  }
5286 
5287  BailoutId ast_id_;
5288 };
5289 
5290 
5291 class HParameter FINAL : public HTemplateInstruction<0> {
5292  public:
5295  REGISTER_PARAMETER
5296  };
5297 
5298  DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned);
5301  Representation);
5302 
5303  unsigned index() const { return index_; }
5304  ParameterKind kind() const { return kind_; }
5305 
5306  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5307 
5309  return Representation::None();
5310  }
5311 
5312  DECLARE_CONCRETE_INSTRUCTION(Parameter)
5313 
5314  private:
5315  explicit HParameter(unsigned index,
5316  ParameterKind kind = STACK_PARAMETER)
5317  : index_(index),
5318  kind_(kind) {
5319  set_representation(Representation::Tagged());
5320  }
5321 
5322  explicit HParameter(unsigned index,
5323  ParameterKind kind,
5324  Representation r)
5325  : index_(index),
5326  kind_(kind) {
5327  set_representation(r);
5328  }
5329 
5330  unsigned index_;
5332 };
5333 
5334 
5335 class HCallStub FINAL : public HUnaryCall {
5336  public:
5337  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallStub, CodeStub::Major, int);
5338  CodeStub::Major major_key() { return major_key_; }
5339 
5340  HValue* context() { return value(); }
5341 
5342  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5343 
5345 
5346  private:
5347  HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
5348  : HUnaryCall(context, argument_count),
5349  major_key_(major_key) {
5350  }
5351 
5352  CodeStub::Major major_key_;
5353 };
5354 
5355 
5356 class HTailCallThroughMegamorphicCache FINAL : public HTemplateInstruction<3> {
5357  public:
5358  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HTailCallThroughMegamorphicCache,
5359  HValue*, HValue*, Code::Flags);
5360 
5362  return Representation::Tagged();
5363  }
5364 
5365  HValue* context() const { return OperandAt(0); }
5366  HValue* receiver() const { return OperandAt(1); }
5367  HValue* name() const { return OperandAt(2); }
5368  Code::Flags flags() const { return flags_; }
5369 
5370  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5371 
5372  DECLARE_CONCRETE_INSTRUCTION(TailCallThroughMegamorphicCache)
5373 
5374  private:
5377  : flags_(flags) {
5378  SetOperandAt(0, context);
5379  SetOperandAt(1, receiver);
5380  SetOperandAt(2, name);
5381  }
5382 
5384 };
5385 
5386 
5387 class HUnknownOSRValue FINAL : public HTemplateInstruction<0> {
5388  public:
5389  DECLARE_INSTRUCTION_FACTORY_P2(HUnknownOSRValue, HEnvironment*, int);
5390 
5391  virtual OStream& PrintDataTo(OStream& os) const; // NOLINT
5392 
5394  return Representation::None();
5395  }
5396 
5397  void set_incoming_value(HPhi* value) { incoming_value_ = value; }
5398  HPhi* incoming_value() { return incoming_value_; }
5399  HEnvironment *environment() { return environment_; }
5400  int index() { return index_; }
5401 
5403  if (incoming_value_ == NULL) return Representation::None();
5404  return incoming_value_->KnownOptimalRepresentation();
5405  }
5406 
5407  DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
5408 
5409  private:
5410  HUnknownOSRValue(HEnvironment* environment, int index)
5411  : environment_(environment),
5412  index_(index),
5413  incoming_value_(NULL) {
5414  set_representation(Representation::Tagged());
5415  }
5416 
5417  HEnvironment* environment_;
5418  int index_;
5420 };
5421 
5422 
5423 class HLoadGlobalCell FINAL : public HTemplateInstruction<0> {
5424  public:
5426  PropertyDetails);
5427 
5428  Unique<Cell> cell() const { return cell_; }
5429  bool RequiresHoleCheck() const;
5430 
5431  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5432 
5433  virtual intptr_t Hashcode() OVERRIDE {
5434  return cell_.Hashcode();
5435  }
5436 
5437  virtual void FinalizeUniqueness() OVERRIDE {
5438  cell_ = Unique<Cell>(cell_.handle());
5439  }
5440 
5442  return Representation::None();
5443  }
5444 
5445  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell)
5446 
5447  protected:
5448  virtual bool DataEquals(HValue* other) OVERRIDE {
5449  return cell_ == HLoadGlobalCell::cast(other)->cell_;
5450  }
5451 
5452  private:
5453  HLoadGlobalCell(Handle<Cell> cell, PropertyDetails details)
5454  : cell_(Unique<Cell>::CreateUninitialized(cell)), details_(details) {
5455  set_representation(Representation::Tagged());
5456  SetFlag(kUseGVN);
5457  SetDependsOnFlag(kGlobalVars);
5458  }
5459 
5460  virtual bool IsDeletable() const OVERRIDE { return !RequiresHoleCheck(); }
5461 
5463  PropertyDetails details_;
5464 };
5465 
5466 
5467 class HLoadGlobalGeneric FINAL : public HTemplateInstruction<2> {
5468  public:
5470  Handle<String>, bool);
5471 
5472  HValue* context() { return OperandAt(0); }
5473  HValue* global_object() { return OperandAt(1); }
5474  Handle<String> name() const { return name_; }
5475  bool for_typeof() const { return for_typeof_; }
5476  int slot() const {
5477  DCHECK(FLAG_vector_ics &&
5479  return slot_;
5480  }
5481  Handle<FixedArray> feedback_vector() const { return feedback_vector_; }
5482  void SetVectorAndSlot(Handle<FixedArray> vector, int slot) {
5483  DCHECK(FLAG_vector_ics);
5484  feedback_vector_ = vector;
5485  slot_ = slot;
5486  }
5487 
5488  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5489 
5491  return Representation::Tagged();
5492  }
5493 
5494  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
5495 
5496  private:
5497  HLoadGlobalGeneric(HValue* context, HValue* global_object,
5498  Handle<String> name, bool for_typeof)
5499  : name_(name), for_typeof_(for_typeof),
5500  slot_(FeedbackSlotInterface::kInvalidFeedbackSlot) {
5501  SetOperandAt(0, context);
5502  SetOperandAt(1, global_object);
5503  set_representation(Representation::Tagged());
5504  SetAllSideEffects();
5505  }
5506 
5507  Handle<String> name_;
5510  int slot_;
5511 };
5512 
5513 
5514 class HAllocate FINAL : public HTemplateInstruction<2> {
5515  public:
5517  InstanceType type2) {
5518  return ComputeFlags(TENURED, type1) == ComputeFlags(TENURED, type2) &&
5519  ComputeFlags(NOT_TENURED, type1) == ComputeFlags(NOT_TENURED, type2);
5520  }
5521 
5522  static HAllocate* New(Zone* zone,
5523  HValue* context,
5524  HValue* size,
5525  HType type,
5526  PretenureFlag pretenure_flag,
5527  InstanceType instance_type,
5528  Handle<AllocationSite> allocation_site =
5530  return new(zone) HAllocate(context, size, type, pretenure_flag,
5531  instance_type, allocation_site);
5532  }
5533 
5534  // Maximum instance size for which allocations will be inlined.
5535  static const int kMaxInlineSize = 64 * kPointerSize;
5536 
5537  HValue* context() const { return OperandAt(0); }
5538  HValue* size() const { return OperandAt(1); }
5539 
5540  bool has_size_upper_bound() { return size_upper_bound_ != NULL; }
5541  HConstant* size_upper_bound() { return size_upper_bound_; }
5542  void set_size_upper_bound(HConstant* value) {
5543  DCHECK(size_upper_bound_ == NULL);
5544  size_upper_bound_ = value;
5545  }
5546 
5548  if (index == 0) {
5549  return Representation::Tagged();
5550  } else {
5551  return Representation::Integer32();
5552  }
5553  }
5554 
5556  return known_initial_map_;
5557  }
5558 
5559  void set_known_initial_map(Handle<Map> known_initial_map) {
5560  known_initial_map_ = known_initial_map;
5561  }
5562 
5563  bool IsNewSpaceAllocation() const {
5564  return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
5565  }
5566 
5568  return (flags_ & ALLOCATE_IN_OLD_DATA_SPACE) != 0;
5569  }
5570 
5572  return (flags_ & ALLOCATE_IN_OLD_POINTER_SPACE) != 0;
5573  }
5574 
5576  return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
5577  }
5578 
5579  bool MustPrefillWithFiller() const {
5580  return (flags_ & PREFILL_WITH_FILLER) != 0;
5581  }
5582 
5584  flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
5585  }
5586 
5587  bool MustClearNextMapWord() const {
5588  return (flags_ & CLEAR_NEXT_MAP_WORD) != 0;
5589  }
5590 
5592  flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
5593  }
5594 
5595  virtual bool HandleSideEffectDominator(GVNFlag side_effect,
5596  HValue* dominator) OVERRIDE;
5597 
5598  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5599 
5601 
5602  private:
5603  enum Flags {
5604  ALLOCATE_IN_NEW_SPACE = 1 << 0,
5605  ALLOCATE_IN_OLD_DATA_SPACE = 1 << 1,
5606  ALLOCATE_IN_OLD_POINTER_SPACE = 1 << 2,
5607  ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
5608  PREFILL_WITH_FILLER = 1 << 4,
5609  CLEAR_NEXT_MAP_WORD = 1 << 5
5610  };
5611 
5612  HAllocate(HValue* context,
5613  HValue* size,
5614  HType type,
5615  PretenureFlag pretenure_flag,
5616  InstanceType instance_type,
5617  Handle<AllocationSite> allocation_site =
5619  : HTemplateInstruction<2>(type),
5620  flags_(ComputeFlags(pretenure_flag, instance_type)),
5621  dominating_allocate_(NULL),
5622  filler_free_space_size_(NULL),
5623  size_upper_bound_(NULL) {
5624  SetOperandAt(0, context);
5625  UpdateSize(size);
5626  set_representation(Representation::Tagged());
5627  SetFlag(kTrackSideEffectDominators);
5628  SetChangesFlag(kNewSpacePromotion);
5629  SetDependsOnFlag(kNewSpacePromotion);
5630 
5631  if (FLAG_trace_pretenuring) {
5632  PrintF("HAllocate with AllocationSite %p %s\n",
5633  allocation_site.is_null()
5634  ? static_cast<void*>(NULL)
5635  : static_cast<void*>(*allocation_site),
5636  pretenure_flag == TENURED ? "tenured" : "not tenured");
5637  }
5638  }
5639 
5640  static Flags ComputeFlags(PretenureFlag pretenure_flag,
5641  InstanceType instance_type) {
5642  Flags flags = pretenure_flag == TENURED
5643  ? (Heap::TargetSpaceId(instance_type) == OLD_POINTER_SPACE
5644  ? ALLOCATE_IN_OLD_POINTER_SPACE : ALLOCATE_IN_OLD_DATA_SPACE)
5645  : ALLOCATE_IN_NEW_SPACE;
5646  if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
5647  flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED);
5648  }
5649  // We have to fill the allocated object with one word fillers if we do
5650  // not use allocation folding since some allocations may depend on each
5651  // other, i.e., have a pointer to each other. A GC in between these
5652  // allocations may leave such objects behind in a not completely initialized
5653  // state.
5654  if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
5655  flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER);
5656  }
5657  if (pretenure_flag == NOT_TENURED &&
5658  AllocationSite::CanTrack(instance_type)) {
5659  flags = static_cast<Flags>(flags | CLEAR_NEXT_MAP_WORD);
5660  }
5661  return flags;
5662  }
5663 
5664  void UpdateClearNextMapWord(bool clear_next_map_word) {
5665  flags_ = static_cast<Flags>(clear_next_map_word
5666  ? flags_ | CLEAR_NEXT_MAP_WORD
5667  : flags_ & ~CLEAR_NEXT_MAP_WORD);
5668  }
5669 
5671  SetOperandAt(1, size);
5672  if (size->IsInteger32Constant()) {
5673  size_upper_bound_ = HConstant::cast(size);
5674  } else {
5675  size_upper_bound_ = NULL;
5676  }
5677  }
5678 
5679  HAllocate* GetFoldableDominator(HAllocate* dominator);
5680 
5681  void UpdateFreeSpaceFiller(int32_t filler_size);
5682 
5683  void CreateFreeSpaceFiller(int32_t filler_size);
5684 
5685  bool IsFoldable(HAllocate* allocate) {
5686  return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) ||
5687  (IsOldDataSpaceAllocation() && allocate->IsOldDataSpaceAllocation()) ||
5688  (IsOldPointerSpaceAllocation() &&
5689  allocate->IsOldPointerSpaceAllocation());
5690  }
5691 
5692  void ClearNextMapWord(int offset);
5693 
5697  HStoreNamedField* filler_free_space_size_;
5698  HConstant* size_upper_bound_;
5699 };
5700 
5701 
5702 class HStoreCodeEntry FINAL: public HTemplateInstruction<2> {
5703  public:
5704  static HStoreCodeEntry* New(Zone* zone,
5705  HValue* context,
5706  HValue* function,
5707  HValue* code) {
5708  return new(zone) HStoreCodeEntry(function, code);
5709  }
5710 
5712  return Representation::Tagged();
5713  }
5714 
5715  HValue* function() { return OperandAt(0); }
5716  HValue* code_object() { return OperandAt(1); }
5717 
5718  DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry)
5719 
5720  private:
5721  HStoreCodeEntry(HValue* function, HValue* code) {
5722  SetOperandAt(0, function);
5723  SetOperandAt(1, code);
5724  }
5725 };
5726 
5727 
5728 class HInnerAllocatedObject FINAL : public HTemplateInstruction<2> {
5729  public:
5730  static HInnerAllocatedObject* New(Zone* zone,
5731  HValue* context,
5732  HValue* value,
5733  HValue* offset,
5734  HType type) {
5735  return new(zone) HInnerAllocatedObject(value, offset, type);
5736  }
5737 
5738  HValue* base_object() const { return OperandAt(0); }
5739  HValue* offset() const { return OperandAt(1); }
5740 
5742  return index == 0 ? Representation::Tagged() : Representation::Integer32();
5743  }
5744 
5745  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5746 
5747  DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
5748 
5749  private:
5751  HValue* offset,
5752  HType type) : HTemplateInstruction<2>(type) {
5753  DCHECK(value->IsAllocate());
5754  DCHECK(type.IsHeapObject());
5755  SetOperandAt(0, value);
5756  SetOperandAt(1, offset);
5757  set_representation(Representation::Tagged());
5758  }
5759 };
5760 
5761 
5763  return !value->type().IsSmi()
5764  && !value->type().IsNull()
5765  && !value->type().IsBoolean()
5766  && !value->type().IsUndefined()
5767  && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
5768 }
5769 
5770 
5772  HValue* value,
5773  HValue* dominator) {
5774  while (object->IsInnerAllocatedObject()) {
5775  object = HInnerAllocatedObject::cast(object)->base_object();
5776  }
5777  if (object->IsConstant() && HConstant::cast(object)->IsCell()) {
5778  return false;
5779  }
5780  if (object->IsConstant() &&
5781  HConstant::cast(object)->HasExternalReferenceValue()) {
5782  // Stores to external references require no write barriers
5783  return false;
5784  }
5785  // We definitely need a write barrier unless the object is the allocation
5786  // dominator.
5787  if (object == dominator && object->IsAllocate()) {
5788  // Stores to new space allocations require no write barriers.
5789  if (HAllocate::cast(object)->IsNewSpaceAllocation()) {
5790  return false;
5791  }
5792  // Stores to old space allocations require no write barriers if the value is
5793  // a constant provably not in new space.
5794  if (value->IsConstant() && HConstant::cast(value)->NotInNewSpace()) {
5795  return false;
5796  }
5797  // Stores to old space allocations require no write barriers if the value is
5798  // an old space allocation.
5799  while (value->IsInnerAllocatedObject()) {
5800  value = HInnerAllocatedObject::cast(value)->base_object();
5801  }
5802  if (value->IsAllocate() &&
5803  !HAllocate::cast(value)->IsNewSpaceAllocation()) {
5804  return false;
5805  }
5806  }
5807  return true;
5808 }
5809 
5810 
5812  HValue* dominator) {
5813  while (object->IsInnerAllocatedObject()) {
5814  object = HInnerAllocatedObject::cast(object)->base_object();
5815  }
5816  if (object == dominator &&
5817  object->IsAllocate() &&
5818  HAllocate::cast(object)->IsNewSpaceAllocation()) {
5820  }
5822 }
5823 
5824 
5825 class HStoreGlobalCell FINAL : public HUnaryOperation {
5826  public:
5828  Handle<PropertyCell>, PropertyDetails);
5829 
5830  Unique<PropertyCell> cell() const { return cell_; }
5831  bool RequiresHoleCheck() { return details_.IsConfigurable(); }
5833  return StoringValueNeedsWriteBarrier(value());
5834  }
5835 
5836  virtual void FinalizeUniqueness() OVERRIDE {
5837  cell_ = Unique<PropertyCell>(cell_.handle());
5838  }
5839 
5841  return Representation::Tagged();
5842  }
5843  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5844 
5845  DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell)
5846 
5847  private:
5849  Handle<PropertyCell> cell,
5850  PropertyDetails details)
5851  : HUnaryOperation(value),
5852  cell_(Unique<PropertyCell>::CreateUninitialized(cell)),
5853  details_(details) {
5854  SetChangesFlag(kGlobalVars);
5855  }
5856 
5858  PropertyDetails details_;
5859 };
5860 
5861 
5862 class HLoadContextSlot FINAL : public HUnaryOperation {
5863  public:
5864  enum Mode {
5865  // Perform a normal load of the context slot without checking its value.
5867  // Load and check the value of the context slot. Deoptimize if it's the
5868  // hole value. This is used for checking for loading of uninitialized
5869  // harmony bindings where we deoptimize into full-codegen generated code
5870  // which will subsequently throw a reference error.
5872  // Load and check the value of the context slot. Return undefined if it's
5873  // the hole value. This is used for non-harmony const assignments
5874  kCheckReturnUndefined
5875  };
5876 
5877  HLoadContextSlot(HValue* context, int slot_index, Mode mode)
5878  : HUnaryOperation(context), slot_index_(slot_index), mode_(mode) {
5879  set_representation(Representation::Tagged());
5880  SetFlag(kUseGVN);
5881  SetDependsOnFlag(kContextSlots);
5882  }
5883 
5884  int slot_index() const { return slot_index_; }
5885  Mode mode() const { return mode_; }
5886 
5888  return mode_ == kCheckDeoptimize;
5889  }
5890 
5891  bool RequiresHoleCheck() const {
5892  return mode_ != kNoCheck;
5893  }
5894 
5896  return Representation::Tagged();
5897  }
5898 
5899  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5900 
5901  DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
5902 
5903  protected:
5904  virtual bool DataEquals(HValue* other) OVERRIDE {
5905  HLoadContextSlot* b = HLoadContextSlot::cast(other);
5906  return (slot_index() == b->slot_index());
5907  }
5908 
5909  private:
5910  virtual bool IsDeletable() const OVERRIDE { return !RequiresHoleCheck(); }
5911 
5914 };
5915 
5916 
5917 class HStoreContextSlot FINAL : public HTemplateInstruction<2> {
5918  public:
5919  enum Mode {
5920  // Perform a normal store to the context slot without checking its previous
5921  // value.
5922  kNoCheck,
5923  // Check the previous value of the context slot and deoptimize if it's the
5924  // hole value. This is used for checking for assignments to uninitialized
5925  // harmony bindings where we deoptimize into full-codegen generated code
5926  // which will subsequently throw a reference error.
5927  kCheckDeoptimize,
5928  // Check the previous value and ignore assignment if it isn't a hole value
5929  kCheckIgnoreAssignment
5930  };
5931 
5932  DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
5933  Mode, HValue*);
5934 
5935  HValue* context() const { return OperandAt(0); }
5936  HValue* value() const { return OperandAt(1); }
5937  int slot_index() const { return slot_index_; }
5938  Mode mode() const { return mode_; }
5939 
5941  return StoringValueNeedsWriteBarrier(value());
5942  }
5943 
5945  return mode_ == kCheckDeoptimize;
5946  }
5947 
5949  return mode_ != kNoCheck;
5950  }
5951 
5953  return Representation::Tagged();
5954  }
5955 
5956  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5957 
5958  DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
5959 
5960  private:
5961  HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
5962  : slot_index_(slot_index), mode_(mode) {
5963  SetOperandAt(0, context);
5964  SetOperandAt(1, value);
5965  SetChangesFlag(kContextSlots);
5966  }
5967 
5968  int slot_index_;
5969  Mode mode_;
5970 };
5971 
5972 
5973 // Represents an access to a portion of an object, such as the map pointer,
5974 // array elements pointer, etc, but not accesses to array elements themselves.
5975 class HObjectAccess FINAL {
5976  public:
5977  inline bool IsInobject() const {
5978  return portion() != kBackingStore && portion() != kExternalMemory;
5979  }
5980 
5981  inline bool IsExternalMemory() const {
5982  return portion() == kExternalMemory;
5983  }
5984 
5985  inline bool IsStringLength() const {
5986  return portion() == kStringLengths;
5987  }
5988 
5989  inline bool IsMap() const {
5990  return portion() == kMaps;
5991  }
5992 
5993  inline int offset() const {
5994  return OffsetField::decode(value_);
5995  }
5996 
5998  return Representation::FromKind(RepresentationField::decode(value_));
5999  }
6000 
6001  inline Handle<String> name() const {
6002  return name_;
6003  }
6004 
6005  inline bool immutable() const {
6006  return ImmutableField::decode(value_);
6007  }
6008 
6009  // Returns true if access is being made to an in-object property that
6010  // was already added to the object.
6011  inline bool existing_inobject_property() const {
6012  return ExistingInobjectPropertyField::decode(value_);
6013  }
6014 
6015  inline HObjectAccess WithRepresentation(Representation representation) {
6016  return HObjectAccess(portion(), offset(), representation, name(),
6017  immutable(), existing_inobject_property());
6018  }
6019 
6020  static HObjectAccess ForHeapNumberValue() {
6021  return HObjectAccess(
6023  }
6024 
6025  static HObjectAccess ForHeapNumberValueLowestBits() {
6026  return HObjectAccess(kDouble,
6029  }
6030 
6031  static HObjectAccess ForHeapNumberValueHighestBits() {
6032  return HObjectAccess(kDouble,
6035  }
6036 
6037  static HObjectAccess ForElementsPointer() {
6038  return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
6039  }
6040 
6041  static HObjectAccess ForLiteralsPointer() {
6042  return HObjectAccess(kInobject, JSFunction::kLiteralsOffset);
6043  }
6044 
6045  static HObjectAccess ForNextFunctionLinkPointer() {
6046  return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
6047  }
6048 
6049  static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
6050  return HObjectAccess(
6051  kArrayLengths,
6053  IsFastElementsKind(elements_kind)
6055  }
6056 
6057  static HObjectAccess ForAllocationSiteOffset(int offset);
6058 
6059  static HObjectAccess ForAllocationSiteList() {
6060  return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
6061  Handle<String>::null(), false, false);
6062  }
6063 
6064  static HObjectAccess ForFixedArrayLength() {
6065  return HObjectAccess(
6066  kArrayLengths,
6069  }
6070 
6071  static HObjectAccess ForStringHashField() {
6072  return HObjectAccess(kInobject,
6075  }
6076 
6077  static HObjectAccess ForStringLength() {
6079  return HObjectAccess(
6080  kStringLengths,
6083  }
6084 
6085  static HObjectAccess ForConsStringFirst() {
6086  return HObjectAccess(kInobject, ConsString::kFirstOffset);
6087  }
6088 
6089  static HObjectAccess ForConsStringSecond() {
6090  return HObjectAccess(kInobject, ConsString::kSecondOffset);
6091  }
6092 
6093  static HObjectAccess ForPropertiesPointer() {
6094  return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
6095  }
6096 
6097  static HObjectAccess ForPrototypeOrInitialMap() {
6098  return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
6099  }
6100 
6101  static HObjectAccess ForSharedFunctionInfoPointer() {
6102  return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
6103  }
6104 
6105  static HObjectAccess ForCodeEntryPointer() {
6106  return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
6107  }
6108 
6109  static HObjectAccess ForCodeOffset() {
6110  return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
6111  }
6112 
6113  static HObjectAccess ForOptimizedCodeMap() {
6114  return HObjectAccess(kInobject,
6116  }
6117 
6118  static HObjectAccess ForFunctionContextPointer() {
6119  return HObjectAccess(kInobject, JSFunction::kContextOffset);
6120  }
6121 
6122  static HObjectAccess ForMap() {
6123  return HObjectAccess(kMaps, JSObject::kMapOffset);
6124  }
6125 
6126  static HObjectAccess ForMapAsInteger32() {
6127  return HObjectAccess(kMaps, JSObject::kMapOffset,
6129  }
6130 
6131  static HObjectAccess ForMapInObjectProperties() {
6132  return HObjectAccess(kInobject,
6135  }
6136 
6137  static HObjectAccess ForMapInstanceType() {
6138  return HObjectAccess(kInobject,
6141  }
6142 
6143  static HObjectAccess ForMapInstanceSize() {
6144  return HObjectAccess(kInobject,
6147  }
6148 
6149  static HObjectAccess ForMapBitField() {
6150  return HObjectAccess(kInobject,
6153  }
6154 
6155  static HObjectAccess ForMapBitField2() {
6156  return HObjectAccess(kInobject,
6159  }
6160 
6161  static HObjectAccess ForNameHashField() {
6162  return HObjectAccess(kInobject,
6165  }
6166 
6167  static HObjectAccess ForMapInstanceTypeAndBitField() {
6169  // Ensure the two fields share one 16-bit word, endian-independent.
6171  (Map::kInstanceTypeOffset & ~1));
6172  return HObjectAccess(kInobject,
6175  }
6176 
6177  static HObjectAccess ForPropertyCellValue() {
6178  return HObjectAccess(kInobject, PropertyCell::kValueOffset);
6179  }
6180 
6181  static HObjectAccess ForCellValue() {
6182  return HObjectAccess(kInobject, Cell::kValueOffset);
6183  }
6184 
6185  static HObjectAccess ForAllocationMementoSite() {
6186  return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
6187  }
6188 
6189  static HObjectAccess ForCounter() {
6190  return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
6191  Handle<String>::null(), false, false);
6192  }
6193 
6194  static HObjectAccess ForExternalUInteger8() {
6195  return HObjectAccess(kExternalMemory, 0, Representation::UInteger8(),
6196  Handle<String>::null(), false, false);
6197  }
6198 
6199  // Create an access to an offset in a fixed array header.
6200  static HObjectAccess ForFixedArrayHeader(int offset);
6201 
6202  // Create an access to an in-object property in a JSObject.
6203  // This kind of access must be used when the object |map| is known and
6204  // in-object properties are being accessed. Accesses of the in-object
6205  // properties can have different semantics depending on whether corresponding
6206  // property was added to the map or not.
6207  static HObjectAccess ForMapAndOffset(Handle<Map> map, int offset,
6208  Representation representation = Representation::Tagged());
6209 
6210  // Create an access to an in-object property in a JSObject.
6211  // This kind of access can be used for accessing object header fields or
6212  // in-object properties if the map of the object is not known.
6213  static HObjectAccess ForObservableJSObjectOffset(int offset,
6214  Representation representation = Representation::Tagged()) {
6215  return ForMapAndOffset(Handle<Map>::null(), offset, representation);
6216  }
6217 
6218  // Create an access to an in-object property in a JSArray.
6219  static HObjectAccess ForJSArrayOffset(int offset);
6220 
6221  static HObjectAccess ForContextSlot(int index);
6222 
6223  // Create an access to the backing store of an object.
6224  static HObjectAccess ForBackingStoreOffset(int offset,
6225  Representation representation = Representation::Tagged());
6226 
6227  // Create an access to a resolved field (in-object or backing store).
6228  static HObjectAccess ForField(Handle<Map> map, int index,
6229  Representation representation,
6231 
6232  // Create an access for the payload of a Cell or JSGlobalPropertyCell.
6233  static HObjectAccess ForCellPayload(Isolate* isolate);
6234 
6235  static HObjectAccess ForJSTypedArrayLength() {
6236  return HObjectAccess::ForObservableJSObjectOffset(
6238  }
6239 
6240  static HObjectAccess ForJSArrayBufferBackingStore() {
6241  return HObjectAccess::ForObservableJSObjectOffset(
6243  }
6244 
6245  static HObjectAccess ForJSArrayBufferByteLength() {
6246  return HObjectAccess::ForObservableJSObjectOffset(
6248  }
6249 
6250  static HObjectAccess ForExternalArrayExternalPointer() {
6251  return HObjectAccess::ForObservableJSObjectOffset(
6253  }
6254 
6255  static HObjectAccess ForJSArrayBufferViewWeakNext() {
6256  return HObjectAccess::ForObservableJSObjectOffset(
6258  }
6259 
6260  static HObjectAccess ForJSArrayBufferWeakFirstView() {
6261  return HObjectAccess::ForObservableJSObjectOffset(
6263  }
6264 
6265  static HObjectAccess ForJSArrayBufferViewBuffer() {
6266  return HObjectAccess::ForObservableJSObjectOffset(
6268  }
6269 
6270  static HObjectAccess ForJSArrayBufferViewByteOffset() {
6271  return HObjectAccess::ForObservableJSObjectOffset(
6273  }
6274 
6275  static HObjectAccess ForJSArrayBufferViewByteLength() {
6276  return HObjectAccess::ForObservableJSObjectOffset(
6278  }
6279 
6280  static HObjectAccess ForGlobalObjectNativeContext() {
6281  return HObjectAccess(kInobject, GlobalObject::kNativeContextOffset);
6282  }
6283 
6284  inline bool Equals(HObjectAccess that) const {
6285  return value_ == that.value_; // portion and offset must match
6286  }
6287 
6288  protected:
6289  void SetGVNFlags(HValue *instr, PropertyAccessType access_type);
6290 
6291  private:
6292  // internal use only; different parts of an object or array
6293  enum Portion {
6294  kMaps, // map of an object
6295  kArrayLengths, // the length of an array
6296  kStringLengths, // the length of a string
6297  kElementsPointer, // elements pointer
6298  kBackingStore, // some field in the backing store
6299  kDouble, // some double field
6300  kInobject, // some other in-object field
6301  kExternalMemory // some field in external memory
6302  };
6303 
6304  HObjectAccess() : value_(0) {}
6305 
6306  HObjectAccess(Portion portion, int offset,
6307  Representation representation = Representation::Tagged(),
6309  bool immutable = false,
6310  bool existing_inobject_property = true)
6311  : value_(PortionField::encode(portion) |
6312  RepresentationField::encode(representation.kind()) |
6313  ImmutableField::encode(immutable ? 1 : 0) |
6315  existing_inobject_property ? 1 : 0) |
6316  OffsetField::encode(offset)),
6317  name_(name) {
6318  // assert that the fields decode correctly
6319  DCHECK(this->offset() == offset);
6320  DCHECK(this->portion() == portion);
6321  DCHECK(this->immutable() == immutable);
6322  DCHECK(this->existing_inobject_property() == existing_inobject_property);
6323  DCHECK(RepresentationField::decode(value_) == representation.kind());
6324  DCHECK(!this->existing_inobject_property() || IsInobject());
6325  }
6326 
6327  class PortionField : public BitField<Portion, 0, 3> {};
6328  class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
6329  class ImmutableField : public BitField<bool, 7, 1> {};
6330  class ExistingInobjectPropertyField : public BitField<bool, 8, 1> {};
6331  class OffsetField : public BitField<int, 9, 23> {};
6332 
6333  uint32_t value_; // encodes portion, representation, immutable, and offset
6334  Handle<String> name_;
6335 
6336  friend class HLoadNamedField;
6337  friend class HStoreNamedField;
6338  friend class SideEffectsTracker;
6339  friend OStream& operator<<(OStream& os, const HObjectAccess& access);
6340 
6341  inline Portion portion() const {
6342  return PortionField::decode(value_);
6343  }
6344 };
6345 
6346 
6347 OStream& operator<<(OStream& os, const HObjectAccess& access);
6348 
6349 
6350 class HLoadNamedField FINAL : public HTemplateInstruction<2> {
6351  public:
6353  HValue*, HObjectAccess);
6355  HObjectAccess, const UniqueSet<Map>*, HType);
6356 
6357  HValue* object() const { return OperandAt(0); }
6358  HValue* dependency() const {
6359  DCHECK(HasDependency());
6360  return OperandAt(1);
6361  }
6362  bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
6363  HObjectAccess access() const { return access_; }
6365  return access_.representation();
6366  }
6367 
6368  const UniqueSet<Map>* maps() const { return maps_; }
6369 
6370  virtual bool HasEscapingOperandAt(int index) OVERRIDE { return false; }
6371  virtual bool HasOutOfBoundsAccess(int size) OVERRIDE {
6372  return !access().IsInobject() || access().offset() >= size;
6373  }
6375  if (index == 0 && access().IsExternalMemory()) {
6376  // object must be external in case of external memory access
6377  return Representation::External();
6378  }
6379  return Representation::Tagged();
6380  }
6381  virtual Range* InferRange(Zone* zone) OVERRIDE;
6382  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
6383 
6384  bool CanBeReplacedWith(HValue* other) const {
6385  if (!CheckFlag(HValue::kCantBeReplaced)) return false;
6386  if (!type().Equals(other->type())) return false;
6387  if (!representation().Equals(other->representation())) return false;
6388  if (!other->IsLoadNamedField()) return true;
6389  HLoadNamedField* that = HLoadNamedField::cast(other);
6390  if (this->maps_ == that->maps_) return true;
6391  if (this->maps_ == NULL || that->maps_ == NULL) return false;
6392  return this->maps_->IsSubset(that->maps_);
6393  }
6394 
6395  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
6396 
6397  protected:
6398  virtual bool DataEquals(HValue* other) OVERRIDE {
6399  HLoadNamedField* that = HLoadNamedField::cast(other);
6400  if (!this->access_.Equals(that->access_)) return false;
6401  if (this->maps_ == that->maps_) return true;
6402  return (this->maps_ != NULL &&
6403  that->maps_ != NULL &&
6404  this->maps_->Equals(that->maps_));
6405  }
6406 
6407  private:
6409  HValue* dependency,
6410  HObjectAccess access)
6411  : access_(access), maps_(NULL) {
6412  DCHECK_NOT_NULL(object);
6413  SetOperandAt(0, object);
6414  SetOperandAt(1, dependency ? dependency : object);
6415 
6416  Representation representation = access.representation();
6417  if (representation.IsInteger8() ||
6418  representation.IsUInteger8() ||
6419  representation.IsInteger16() ||
6420  representation.IsUInteger16()) {
6421  set_representation(Representation::Integer32());
6422  } else if (representation.IsSmi()) {
6423  set_type(HType::Smi());
6424  if (SmiValuesAre32Bits()) {
6425  set_representation(Representation::Integer32());
6426  } else {
6427  set_representation(representation);
6428  }
6429  } else if (representation.IsDouble() ||
6430  representation.IsExternal() ||
6431  representation.IsInteger32()) {
6432  set_representation(representation);
6433  } else if (representation.IsHeapObject()) {
6434  set_type(HType::HeapObject());
6435  set_representation(Representation::Tagged());
6436  } else {
6437  set_representation(Representation::Tagged());
6438  }
6439  access.SetGVNFlags(this, LOAD);
6440  }
6441 
6443  HValue* dependency,
6444  HObjectAccess access,
6445  const UniqueSet<Map>* maps,
6446  HType type)
6447  : HTemplateInstruction<2>(type), access_(access), maps_(maps) {
6448  DCHECK_NOT_NULL(maps);
6449  DCHECK_NE(0, maps->size());
6450 
6451  DCHECK_NOT_NULL(object);
6452  SetOperandAt(0, object);
6453  SetOperandAt(1, dependency ? dependency : object);
6454 
6455  DCHECK(access.representation().IsHeapObject());
6456  DCHECK(type.IsHeapObject());
6457  set_representation(Representation::Tagged());
6458 
6459  access.SetGVNFlags(this, LOAD);
6460  }
6461 
6462  virtual bool IsDeletable() const OVERRIDE { return true; }
6463 
6464  HObjectAccess access_;
6465  const UniqueSet<Map>* maps_;
6466 };
6467 
6468 
6469 class HLoadNamedGeneric FINAL : public HTemplateInstruction<2> {
6470  public:
6472  Handle<Object>);
6473 
6474  HValue* context() const { return OperandAt(0); }
6475  HValue* object() const { return OperandAt(1); }
6476  Handle<Object> name() const { return name_; }
6477 
6478  int slot() const {
6479  DCHECK(FLAG_vector_ics &&
6481  return slot_;
6482  }
6483  Handle<FixedArray> feedback_vector() const { return feedback_vector_; }
6484  void SetVectorAndSlot(Handle<FixedArray> vector, int slot) {
6485  DCHECK(FLAG_vector_ics);
6486  feedback_vector_ = vector;
6487  slot_ = slot;
6488  }
6489 
6491  return Representation::Tagged();
6492  }
6493 
6494  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
6495 
6496  DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
6497 
6498  private:
6500  : name_(name),
6501  slot_(FeedbackSlotInterface::kInvalidFeedbackSlot) {
6502  SetOperandAt(0, context);
6503  SetOperandAt(1, object);
6504  set_representation(Representation::Tagged());
6505  SetAllSideEffects();
6506  }
6507 
6509  Handle<FixedArray> feedback_vector_;
6510  int slot_;
6511 };
6512 
6513 
6514 class HLoadFunctionPrototype FINAL : public HUnaryOperation {
6515  public:
6516  DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);
6517 
6518  HValue* function() { return OperandAt(0); }
6519 
6521  return Representation::Tagged();
6522  }
6523 
6524  DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
6525 
6526  protected:
6527  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
6528 
6529  private:
6530  explicit HLoadFunctionPrototype(HValue* function)
6531  : HUnaryOperation(function) {
6532  set_representation(Representation::Tagged());
6533  SetFlag(kUseGVN);
6534  SetDependsOnFlag(kCalls);
6535  }
6536 };
6537 
6539  public:
6540  virtual HValue* GetKey() = 0;
6541  virtual void SetKey(HValue* key) = 0;
6542  virtual ElementsKind elements_kind() const = 0;
6543  // TryIncreaseBaseOffset returns false if overflow would result.
6544  virtual bool TryIncreaseBaseOffset(uint32_t increase_by_value) = 0;
6545  virtual bool IsDehoisted() const = 0;
6546  virtual void SetDehoisted(bool is_dehoisted) = 0;
6548 
6550  return r.IsInteger32() || SmiValuesAre32Bits()
6552  }
6553 };
6554 
6555 
6557 
6561 };
6562 
6563 
6564 class HLoadKeyed FINAL
6565  : public HTemplateInstruction<3>, public ArrayInstructionInterface {
6566  public:
6568  ElementsKind);
6573 
6574  bool is_external() const {
6575  return IsExternalArrayElementsKind(elements_kind());
6576  }
6577  bool is_fixed_typed_array() const {
6578  return IsFixedTypedArrayElementsKind(elements_kind());
6579  }
6580  bool is_typed_elements() const {
6581  return is_external() || is_fixed_typed_array();
6582  }
6583  HValue* elements() const { return OperandAt(0); }
6584  HValue* key() const { return OperandAt(1); }
6585  HValue* dependency() const {
6586  DCHECK(HasDependency());
6587  return OperandAt(2);
6588  }
6589  bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
6590  uint32_t base_offset() const { return BaseOffsetField::decode(bit_field_); }
6591  bool TryIncreaseBaseOffset(uint32_t increase_by_value);
6592  HValue* GetKey() { return key(); }
6593  void SetKey(HValue* key) { SetOperandAt(1, key); }
6594  bool IsDehoisted() const { return IsDehoistedField::decode(bit_field_); }
6595  void SetDehoisted(bool is_dehoisted) {
6596  bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
6597  }
6599  return ElementsKindField::decode(bit_field_);
6600  }
6602  return HoleModeField::decode(bit_field_);
6603  }
6604 
6606  // kind_fast: tagged[int32] (none)
6607  // kind_double: tagged[int32] (none)
6608  // kind_fixed_typed_array: tagged[int32] (none)
6609  // kind_external: external[int32] (none)
6610  if (index == 0) {
6611  return is_external() ? Representation::External()
6613  }
6614  if (index == 1) {
6616  OperandAt(1)->representation());
6617  }
6618  return Representation::None();
6619  }
6620 
6622  return RequiredInputRepresentation(index);
6623  }
6624 
6625  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
6626 
6627  bool UsesMustHandleHole() const;
6629  bool RequiresHoleCheck() const;
6630 
6631  virtual Range* InferRange(Zone* zone) OVERRIDE;
6632 
6633  DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)
6634 
6635  protected:
6636  virtual bool DataEquals(HValue* other) OVERRIDE {
6637  if (!other->IsLoadKeyed()) return false;
6638  HLoadKeyed* other_load = HLoadKeyed::cast(other);
6639 
6640  if (IsDehoisted() && base_offset() != other_load->base_offset())
6641  return false;
6642  return elements_kind() == other_load->elements_kind();
6643  }
6644 
6645  private:
6647  HValue* key,
6648  HValue* dependency,
6649  ElementsKind elements_kind,
6651  int offset = kDefaultKeyedHeaderOffsetSentinel)
6652  : bit_field_(0) {
6653  offset = offset == kDefaultKeyedHeaderOffsetSentinel
6654  ? GetDefaultHeaderSizeForElementsKind(elements_kind)
6655  : offset;
6656  bit_field_ = ElementsKindField::encode(elements_kind) |
6657  HoleModeField::encode(mode) |
6658  BaseOffsetField::encode(offset);
6659 
6660  SetOperandAt(0, obj);
6661  SetOperandAt(1, key);
6662  SetOperandAt(2, dependency != NULL ? dependency : obj);
6663 
6664  if (!is_typed_elements()) {
6665  // I can detect the case between storing double (holey and fast) and
6666  // smi/object by looking at elements_kind_.
6667  DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
6668  IsFastDoubleElementsKind(elements_kind));
6669 
6670  if (IsFastSmiOrObjectElementsKind(elements_kind)) {
6671  if (IsFastSmiElementsKind(elements_kind) &&
6672  (!IsHoleyElementsKind(elements_kind) ||
6673  mode == NEVER_RETURN_HOLE)) {
6674  set_type(HType::Smi());
6675  if (SmiValuesAre32Bits() && !RequiresHoleCheck()) {
6676  set_representation(Representation::Integer32());
6677  } else {
6678  set_representation(Representation::Smi());
6679  }
6680  } else {
6681  set_representation(Representation::Tagged());
6682  }
6683 
6684  SetDependsOnFlag(kArrayElements);
6685  } else {
6686  set_representation(Representation::Double());
6687  SetDependsOnFlag(kDoubleArrayElements);
6688  }
6689  } else {
6690  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
6691  elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
6692  elements_kind == FLOAT32_ELEMENTS ||
6693  elements_kind == FLOAT64_ELEMENTS) {
6694  set_representation(Representation::Double());
6695  } else {
6696  set_representation(Representation::Integer32());
6697  }
6698 
6699  if (is_external()) {
6700  SetDependsOnFlag(kExternalMemory);
6701  } else if (is_fixed_typed_array()) {
6702  SetDependsOnFlag(kTypedArrayElements);
6703  } else {
6704  UNREACHABLE();
6705  }
6706  // Native code could change the specialized array.
6707  SetDependsOnFlag(kCalls);
6708  }
6709 
6710  SetFlag(kUseGVN);
6711  }
6712 
6713  virtual bool IsDeletable() const OVERRIDE {
6714  return !RequiresHoleCheck();
6715  }
6716 
6717  // Establish some checks around our packed fields
6719  kBitsForElementsKind = 5,
6720  kBitsForHoleMode = 1,
6721  kBitsForBaseOffset = 25,
6722  kBitsForIsDehoisted = 1,
6723 
6724  kStartElementsKind = 0,
6725  kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
6726  kStartBaseOffset = kStartHoleMode + kBitsForHoleMode,
6727  kStartIsDehoisted = kStartBaseOffset + kBitsForBaseOffset
6728  };
6729 
6730  STATIC_ASSERT((kBitsForElementsKind + kBitsForBaseOffset +
6731  kBitsForIsDehoisted) <= sizeof(uint32_t)*8);
6732  STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
6734  public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
6735  {}; // NOLINT
6737  public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
6738  {}; // NOLINT
6740  public BitField<uint32_t, kStartBaseOffset, kBitsForBaseOffset>
6741  {}; // NOLINT
6743  public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
6744  {}; // NOLINT
6746 };
6747 
6748 
6749 class HLoadKeyedGeneric FINAL : public HTemplateInstruction<3> {
6750  public:
6752  HValue*);
6753  HValue* object() const { return OperandAt(0); }
6754  HValue* key() const { return OperandAt(1); }
6755  HValue* context() const { return OperandAt(2); }
6756  int slot() const {
6757  DCHECK(FLAG_vector_ics &&
6759  return slot_;
6760  }
6761  Handle<FixedArray> feedback_vector() const { return feedback_vector_; }
6762  void SetVectorAndSlot(Handle<FixedArray> vector, int slot) {
6763  DCHECK(FLAG_vector_ics);
6764  feedback_vector_ = vector;
6765  slot_ = slot;
6766  }
6767 
6768  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
6769 
6771  // tagged[tagged]
6772  return Representation::Tagged();
6773  }
6774 
6776 
6777  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
6778 
6779  private:
6780  HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key)
6781  : slot_(FeedbackSlotInterface::kInvalidFeedbackSlot) {
6782  set_representation(Representation::Tagged());
6783  SetOperandAt(0, obj);
6784  SetOperandAt(1, key);
6785  SetOperandAt(2, context);
6786  SetAllSideEffects();
6787  }
6788 
6789  Handle<FixedArray> feedback_vector_;
6790  int slot_;
6791 };
6792 
6793 
6794 // Indicates whether the store is a store to an entry that was previously
6795 // initialized or not.
6797  // The entry could be either previously initialized or not.
6799  // At the time of this store it is guaranteed that the entry is already
6800  // initialized.
6802 };
6803 
6804 
6805 class HStoreNamedField FINAL : public HTemplateInstruction<3> {
6806  public:
6808  HObjectAccess, HValue*);
6810  HObjectAccess, HValue*, StoreFieldOrKeyedMode);
6811 
6812  DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
6813 
6814  virtual bool HasEscapingOperandAt(int index) OVERRIDE {
6815  return index == 1;
6816  }
6817  virtual bool HasOutOfBoundsAccess(int size) OVERRIDE {
6818  return !access().IsInobject() || access().offset() >= size;
6819  }
6821  if (index == 0 && access().IsExternalMemory()) {
6822  // object must be external in case of external memory access
6823  return Representation::External();
6824  } else if (index == 1) {
6825  if (field_representation().IsInteger8() ||
6826  field_representation().IsUInteger8() ||
6827  field_representation().IsInteger16() ||
6828  field_representation().IsUInteger16() ||
6829  field_representation().IsInteger32()) {
6830  return Representation::Integer32();
6831  } else if (field_representation().IsDouble()) {
6832  return field_representation();
6833  } else if (field_representation().IsSmi()) {
6834  if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
6835  return Representation::Integer32();
6836  }
6837  return field_representation();
6838  } else if (field_representation().IsExternal()) {
6839  return Representation::External();
6840  }
6841  }
6842  return Representation::Tagged();
6843  }
6844  virtual bool HandleSideEffectDominator(GVNFlag side_effect,
6845  HValue* dominator) OVERRIDE {
6846  DCHECK(side_effect == kNewSpacePromotion);
6847  if (!FLAG_use_write_barrier_elimination) return false;
6848  dominator_ = dominator;
6849  return false;
6850  }
6851  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
6852 
6853  HValue* object() const { return OperandAt(0); }
6854  HValue* value() const { return OperandAt(1); }
6855  HValue* transition() const { return OperandAt(2); }
6856 
6857  HObjectAccess access() const { return access_; }
6858  HValue* dominator() const { return dominator_; }
6859  bool has_transition() const { return has_transition_; }
6860  StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
6861 
6863  if (has_transition()) {
6864  return Handle<Map>::cast(
6865  HConstant::cast(transition())->handle(Isolate::Current()));
6866  } else {
6867  return Handle<Map>();
6868  }
6869  }
6870 
6871  void SetTransition(HConstant* transition) {
6872  DCHECK(!has_transition()); // Only set once.
6873  SetOperandAt(2, transition);
6874  has_transition_ = true;
6875  SetChangesFlag(kMaps);
6876  }
6877 
6878  bool NeedsWriteBarrier() const {
6879  DCHECK(!field_representation().IsDouble() || !has_transition());
6880  if (field_representation().IsDouble()) return false;
6881  if (field_representation().IsSmi()) return false;
6882  if (field_representation().IsInteger32()) return false;
6883  if (field_representation().IsExternal()) return false;
6884  return StoringValueNeedsWriteBarrier(value()) &&
6885  ReceiverObjectNeedsWriteBarrier(object(), value(), dominator());
6886  }
6887 
6889  return ReceiverObjectNeedsWriteBarrier(object(), transition(),
6890  dominator());
6891  }
6892 
6894  if (field_representation().IsHeapObject()) return OMIT_SMI_CHECK;
6895  if (value()->type().IsHeapObject()) return OMIT_SMI_CHECK;
6896  return INLINE_SMI_CHECK;
6897  }
6898 
6900  return PointersToHereCheckForObject(value(), dominator());
6901  }
6902 
6904  return access_.representation();
6905  }
6906 
6907  void UpdateValue(HValue* value) {
6908  SetOperandAt(1, value);
6909  }
6910 
6911  bool CanBeReplacedWith(HStoreNamedField* that) const {
6912  if (!this->access().Equals(that->access())) return false;
6913  if (SmiValuesAre32Bits() &&
6914  this->field_representation().IsSmi() &&
6915  this->store_mode() == INITIALIZING_STORE &&
6916  that->store_mode() == STORE_TO_INITIALIZED_ENTRY) {
6917  // We cannot replace an initializing store to a smi field with a store to
6918  // an initialized entry on 64-bit architectures (with 32-bit smis).
6919  return false;
6920  }
6921  return true;
6922  }
6923 
6924  private:
6926  HObjectAccess access,
6927  HValue* val,
6929  : access_(access),
6930  dominator_(NULL),
6931  has_transition_(false),
6932  store_mode_(store_mode) {
6933  // Stores to a non existing in-object property are allowed only to the
6934  // newly allocated objects (via HAllocate or HInnerAllocatedObject).
6935  DCHECK(!access.IsInobject() || access.existing_inobject_property() ||
6936  obj->IsAllocate() || obj->IsInnerAllocatedObject());
6937  SetOperandAt(0, obj);
6938  SetOperandAt(1, val);
6939  SetOperandAt(2, obj);
6940  access.SetGVNFlags(this, STORE);
6941  }
6942 
6943  HObjectAccess access_;
6947 };
6948 
6949 
6950 class HStoreNamedGeneric FINAL : public HTemplateInstruction<3> {
6951  public:
6954  StrictMode);
6955  HValue* object() const { return OperandAt(0); }
6956  HValue* value() const { return OperandAt(1); }
6957  HValue* context() const { return OperandAt(2); }
6958  Handle<String> name() const { return name_; }
6959  StrictMode strict_mode() const { return strict_mode_; }
6960 
6961  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
6962 
6964  return Representation::Tagged();
6965  }
6966 
6967  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
6968 
6969  private:
6971  HValue* object,
6973  HValue* value,
6974  StrictMode strict_mode)
6975  : name_(name),
6976  strict_mode_(strict_mode) {
6977  SetOperandAt(0, object);
6978  SetOperandAt(1, value);
6979  SetOperandAt(2, context);
6980  SetAllSideEffects();
6981  }
6982 
6983  Handle<String> name_;
6985 };
6986 
6987 
6988 class HStoreKeyed FINAL
6989  : public HTemplateInstruction<3>, public ArrayInstructionInterface {
6990  public:
6992  ElementsKind);
6997 
6999  // kind_fast: tagged[int32] = tagged
7000  // kind_double: tagged[int32] = double
7001  // kind_smi : tagged[int32] = smi
7002  // kind_fixed_typed_array: tagged[int32] = (double | int32)
7003  // kind_external: external[int32] = (double | int32)
7004  if (index == 0) {
7005  return is_external() ? Representation::External()
7007  } else if (index == 1) {
7009  OperandAt(1)->representation());
7010  }
7011 
7012  DCHECK_EQ(index, 2);
7013  return RequiredValueRepresentation(elements_kind_, store_mode_);
7014  }
7015 
7018  if (IsDoubleOrFloatElementsKind(kind)) {
7019  return Representation::Double();
7020  }
7021 
7022  if (kind == FAST_SMI_ELEMENTS && SmiValuesAre32Bits() &&
7024  return Representation::Integer32();
7025  }
7026 
7027  if (IsFastSmiElementsKind(kind)) {
7028  return Representation::Smi();
7029  }
7030 
7031  return IsExternalArrayElementsKind(kind) ||
7035  }
7036 
7037  bool is_external() const {
7038  return IsExternalArrayElementsKind(elements_kind());
7039  }
7040 
7041  bool is_fixed_typed_array() const {
7042  return IsFixedTypedArrayElementsKind(elements_kind());
7043  }
7044 
7045  bool is_typed_elements() const {
7046  return is_external() || is_fixed_typed_array();
7047  }
7048 
7050  if (index < 2) return RequiredInputRepresentation(index);
7051  if (IsUninitialized()) {
7052  return Representation::None();
7053  }
7054  Representation r = RequiredValueRepresentation(elements_kind_, store_mode_);
7055  // For fast object elements kinds, don't assume anything.
7056  if (r.IsTagged()) return Representation::None();
7057  return r;
7058  }
7059 
7060  HValue* elements() const { return OperandAt(0); }
7061  HValue* key() const { return OperandAt(1); }
7062  HValue* value() const { return OperandAt(2); }
7063  bool value_is_smi() const {
7064  return IsFastSmiElementsKind(elements_kind_);
7065  }
7066  StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
7067  ElementsKind elements_kind() const { return elements_kind_; }
7068  uint32_t base_offset() const { return base_offset_; }
7069  bool TryIncreaseBaseOffset(uint32_t increase_by_value);
7070  HValue* GetKey() { return key(); }
7071  void SetKey(HValue* key) { SetOperandAt(1, key); }
7072  bool IsDehoisted() const { return is_dehoisted_; }
7073  void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
7074  bool IsUninitialized() { return is_uninitialized_; }
7075  void SetUninitialized(bool is_uninitialized) {
7076  is_uninitialized_ = is_uninitialized;
7077  }
7078 
7080  return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
7081  }
7082 
7083  virtual bool HandleSideEffectDominator(GVNFlag side_effect,
7084  HValue* dominator) OVERRIDE {
7085  DCHECK(side_effect == kNewSpacePromotion);
7086  dominator_ = dominator;
7087  return false;
7088  }
7089 
7090  HValue* dominator() const { return dominator_; }
7091 
7093  if (value_is_smi()) {
7094  return false;
7095  } else {
7096  return StoringValueNeedsWriteBarrier(value()) &&
7097  ReceiverObjectNeedsWriteBarrier(elements(), value(), dominator());
7098  }
7099  }
7100 
7102  return PointersToHereCheckForObject(value(), dominator());
7103  }
7104 
7106 
7107  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7108 
7109  DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
7110 
7111  private:
7112  HStoreKeyed(HValue* obj, HValue* key, HValue* val,
7113  ElementsKind elements_kind,
7115  int offset = kDefaultKeyedHeaderOffsetSentinel)
7116  : elements_kind_(elements_kind),
7117  base_offset_(offset == kDefaultKeyedHeaderOffsetSentinel
7118  ? GetDefaultHeaderSizeForElementsKind(elements_kind)
7119  : offset),
7120  is_dehoisted_(false),
7121  is_uninitialized_(false),
7122  store_mode_(store_mode),
7123  dominator_(NULL) {
7124  SetOperandAt(0, obj);
7125  SetOperandAt(1, key);
7126  SetOperandAt(2, val);
7127 
7128  if (IsFastObjectElementsKind(elements_kind)) {
7129  SetFlag(kTrackSideEffectDominators);
7130  SetDependsOnFlag(kNewSpacePromotion);
7131  }
7132  if (is_external()) {
7133  SetChangesFlag(kExternalMemory);
7134  SetFlag(kAllowUndefinedAsNaN);
7135  } else if (IsFastDoubleElementsKind(elements_kind)) {
7136  SetChangesFlag(kDoubleArrayElements);
7137  } else if (IsFastSmiElementsKind(elements_kind)) {
7138  SetChangesFlag(kArrayElements);
7139  } else if (is_fixed_typed_array()) {
7140  SetChangesFlag(kTypedArrayElements);
7141  SetFlag(kAllowUndefinedAsNaN);
7142  } else {
7143  SetChangesFlag(kArrayElements);
7144  }
7145 
7146  // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
7147  if ((elements_kind >= EXTERNAL_INT8_ELEMENTS &&
7148  elements_kind <= EXTERNAL_UINT32_ELEMENTS) ||
7149  (elements_kind >= UINT8_ELEMENTS &&
7150  elements_kind <= INT32_ELEMENTS)) {
7151  SetFlag(kTruncatingToInt32);
7152  }
7153  }
7154 
7155  ElementsKind elements_kind_;
7157  bool is_dehoisted_ : 1;
7158  bool is_uninitialized_ : 1;
7159  StoreFieldOrKeyedMode store_mode_: 1;
7160  HValue* dominator_;
7161 };
7162 
7163 
7164 class HStoreKeyedGeneric FINAL : public HTemplateInstruction<4> {
7165  public:
7167  HValue*, HValue*, StrictMode);
7168 
7169  HValue* object() const { return OperandAt(0); }
7170  HValue* key() const { return OperandAt(1); }
7171  HValue* value() const { return OperandAt(2); }
7172  HValue* context() const { return OperandAt(3); }
7173  StrictMode strict_mode() const { return strict_mode_; }
7174 
7176  // tagged[tagged] = tagged
7177  return Representation::Tagged();
7178  }
7179 
7180  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7181 
7182  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
7183 
7184  private:
7186  HValue* object,
7187  HValue* key,
7188  HValue* value,
7189  StrictMode strict_mode)
7190  : strict_mode_(strict_mode) {
7191  SetOperandAt(0, object);
7192  SetOperandAt(1, key);
7193  SetOperandAt(2, value);
7194  SetOperandAt(3, context);
7195  SetAllSideEffects();
7196  }
7197 
7198  StrictMode strict_mode_;
7199 };
7200 
7201 
7202 class HTransitionElementsKind FINAL : public HTemplateInstruction<2> {
7203  public:
7204  inline static HTransitionElementsKind* New(Zone* zone,
7205  HValue* context,
7206  HValue* object,
7207  Handle<Map> original_map,
7208  Handle<Map> transitioned_map) {
7209  return new(zone) HTransitionElementsKind(context, object,
7210  original_map, transitioned_map);
7211  }
7212 
7214  return Representation::Tagged();
7215  }
7216 
7217  HValue* object() const { return OperandAt(0); }
7218  HValue* context() const { return OperandAt(1); }
7219  Unique<Map> original_map() const { return original_map_; }
7220  Unique<Map> transitioned_map() const { return transitioned_map_; }
7221  ElementsKind from_kind() const { return from_kind_; }
7222  ElementsKind to_kind() const { return to_kind_; }
7223 
7224  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7225 
7226  DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
7227 
7228  protected:
7229  virtual bool DataEquals(HValue* other) OVERRIDE {
7230  HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
7231  return original_map_ == instr->original_map_ &&
7232  transitioned_map_ == instr->transitioned_map_;
7233  }
7234 
7235  virtual int RedefinedOperandIndex() { return 0; }
7236 
7237  private:
7239  HValue* object,
7240  Handle<Map> original_map,
7241  Handle<Map> transitioned_map)
7242  : original_map_(Unique<Map>(original_map)),
7243  transitioned_map_(Unique<Map>(transitioned_map)),
7244  from_kind_(original_map->elements_kind()),
7245  to_kind_(transitioned_map->elements_kind()) {
7246  SetOperandAt(0, object);
7247  SetOperandAt(1, context);
7248  SetFlag(kUseGVN);
7249  SetChangesFlag(kElementsKind);
7250  if (!IsSimpleMapChangeTransition(from_kind_, to_kind_)) {
7251  SetChangesFlag(kElementsPointer);
7252  SetChangesFlag(kNewSpacePromotion);
7253  }
7254  set_representation(Representation::Tagged());
7255  }
7256 
7261 };
7262 
7263 
7264 class HStringAdd FINAL : public HBinaryOperation {
7265  public:
7266  static HInstruction* New(Zone* zone,
7267  HValue* context,
7268  HValue* left,
7269  HValue* right,
7270  PretenureFlag pretenure_flag = NOT_TENURED,
7272  Handle<AllocationSite> allocation_site =
7274 
7275  StringAddFlags flags() const { return flags_; }
7276  PretenureFlag pretenure_flag() const { return pretenure_flag_; }
7277 
7279  return Representation::Tagged();
7280  }
7281 
7282  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7283 
7284  DECLARE_CONCRETE_INSTRUCTION(StringAdd)
7285 
7286  protected:
7287  virtual bool DataEquals(HValue* other) OVERRIDE {
7288  return flags_ == HStringAdd::cast(other)->flags_ &&
7289  pretenure_flag_ == HStringAdd::cast(other)->pretenure_flag_;
7290  }
7291 
7292  private:
7293  HStringAdd(HValue* context,
7294  HValue* left,
7295  HValue* right,
7296  PretenureFlag pretenure_flag,
7298  Handle<AllocationSite> allocation_site)
7299  : HBinaryOperation(context, left, right, HType::String()),
7300  flags_(flags), pretenure_flag_(pretenure_flag) {
7301  set_representation(Representation::Tagged());
7302  SetFlag(kUseGVN);
7303  SetDependsOnFlag(kMaps);
7304  SetChangesFlag(kNewSpacePromotion);
7305  if (FLAG_trace_pretenuring) {
7306  PrintF("HStringAdd with AllocationSite %p %s\n",
7307  allocation_site.is_null()
7308  ? static_cast<void*>(NULL)
7309  : static_cast<void*>(*allocation_site),
7310  pretenure_flag == TENURED ? "tenured" : "not tenured");
7311  }
7312  }
7313 
7314  // No side-effects except possible allocation:
7315  virtual bool IsDeletable() const OVERRIDE { return true; }
7316 
7319 };
7320 
7321 
7322 class HStringCharCodeAt FINAL : public HTemplateInstruction<3> {
7323  public:
7325  HValue*,
7326  HValue*);
7327 
7329  // The index is supposed to be Integer32.
7330  return index == 2
7333  }
7334 
7335  HValue* context() const { return OperandAt(0); }
7336  HValue* string() const { return OperandAt(1); }
7337  HValue* index() const { return OperandAt(2); }
7338 
7339  DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
7340 
7341  protected:
7342  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
7343 
7344  virtual Range* InferRange(Zone* zone) OVERRIDE {
7345  return new(zone) Range(0, String::kMaxUtf16CodeUnit);
7346  }
7347 
7348  private:
7349  HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
7350  SetOperandAt(0, context);
7351  SetOperandAt(1, string);
7352  SetOperandAt(2, index);
7353  set_representation(Representation::Integer32());
7354  SetFlag(kUseGVN);
7355  SetDependsOnFlag(kMaps);
7356  SetDependsOnFlag(kStringChars);
7357  SetChangesFlag(kNewSpacePromotion);
7358  }
7359 
7360  // No side effects: runtime function assumes string + number inputs.
7361  virtual bool IsDeletable() const OVERRIDE { return true; }
7362 };
7363 
7364 
7365 class HStringCharFromCode FINAL : public HTemplateInstruction<2> {
7366  public:
7367  static HInstruction* New(Zone* zone,
7368  HValue* context,
7369  HValue* char_code);
7370 
7372  return index == 0
7375  }
7376 
7377  HValue* context() const { return OperandAt(0); }
7378  HValue* value() const { return OperandAt(1); }
7379 
7380  virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
7381 
7382  DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
7383 
7384  private:
7385  HStringCharFromCode(HValue* context, HValue* char_code)
7386  : HTemplateInstruction<2>(HType::String()) {
7387  SetOperandAt(0, context);
7388  SetOperandAt(1, char_code);
7389  set_representation(Representation::Tagged());
7390  SetFlag(kUseGVN);
7391  SetChangesFlag(kNewSpacePromotion);
7392  }
7393 
7394  virtual bool IsDeletable() const OVERRIDE {
7395  return !value()->ToNumberCanBeObserved();
7396  }
7397 };
7398 
7399 
7400 template <int V>
7402  public:
7406  }
7407 
7408  HMaterializedLiteral<V>(int index, int depth)
7409  : literal_index_(index), depth_(depth),
7412  }
7413 
7414  int literal_index() const { return literal_index_; }
7415  int depth() const { return depth_; }
7417  return allocation_site_mode_;
7418  }
7419 
7420  private:
7421  virtual bool IsDeletable() const FINAL OVERRIDE { return true; }
7422 
7424  int depth_;
7426 };
7427 
7428 
7429 class HRegExpLiteral FINAL : public HMaterializedLiteral<1> {
7430  public:
7435  int);
7436 
7437  HValue* context() { return OperandAt(0); }
7438  Handle<FixedArray> literals() { return literals_; }
7439  Handle<String> pattern() { return pattern_; }
7440  Handle<String> flags() { return flags_; }
7441 
7443  return Representation::Tagged();
7444  }
7445 
7446  DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
7447 
7448  private:
7451  Handle<String> pattern,
7453  int literal_index)
7454  : HMaterializedLiteral<1>(literal_index, 0),
7455  literals_(literals),
7456  pattern_(pattern),
7457  flags_(flags) {
7458  SetOperandAt(0, context);
7459  SetAllSideEffects();
7460  set_type(HType::JSObject());
7461  }
7462 
7466 };
7467 
7468 
7469 class HFunctionLiteral FINAL : public HTemplateInstruction<1> {
7470  public:
7473  bool);
7474  HValue* context() { return OperandAt(0); }
7475 
7477  return Representation::Tagged();
7478  }
7479 
7480  DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral)
7481 
7482  Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
7483  bool pretenure() const { return pretenure_; }
7484  bool has_no_literals() const { return has_no_literals_; }
7485  bool is_arrow() const { return IsArrowFunction(kind_); }
7486  bool is_generator() const { return IsGeneratorFunction(kind_); }
7487  bool is_concise_method() const { return IsConciseMethod(kind_); }
7488  FunctionKind kind() const { return kind_; }
7489  StrictMode strict_mode() const { return strict_mode_; }
7490 
7491  private:
7493  bool pretenure)
7494  : HTemplateInstruction<1>(HType::JSObject()),
7495  shared_info_(shared),
7496  kind_(shared->kind()),
7497  pretenure_(pretenure),
7498  has_no_literals_(shared->num_literals() == 0),
7499  strict_mode_(shared->strict_mode()) {
7500  SetOperandAt(0, context);
7501  set_representation(Representation::Tagged());
7502  SetChangesFlag(kNewSpacePromotion);
7503  }
7504 
7505  virtual bool IsDeletable() const OVERRIDE { return true; }
7506 
7507  Handle<SharedFunctionInfo> shared_info_;
7509  bool pretenure_ : 1;
7511  StrictMode strict_mode_;
7512 };
7513 
7514 
7515 class HTypeof FINAL : public HTemplateInstruction<2> {
7516  public:
7518 
7519  HValue* context() const { return OperandAt(0); }
7520  HValue* value() const { return OperandAt(1); }
7521 
7522  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7523 
7525  return Representation::Tagged();
7526  }
7527 
7529 
7530  private:
7531  explicit HTypeof(HValue* context, HValue* value) {
7532  SetOperandAt(0, context);
7533  SetOperandAt(1, value);
7534  set_representation(Representation::Tagged());
7535  }
7536 
7537  virtual bool IsDeletable() const OVERRIDE { return true; }
7538 };
7539 
7540 
7541 class HTrapAllocationMemento FINAL : public HTemplateInstruction<1> {
7542  public:
7543  DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
7544 
7546  return Representation::Tagged();
7547  }
7548 
7549  HValue* object() { return OperandAt(0); }
7550 
7551  DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
7552 
7553  private:
7555  SetOperandAt(0, obj);
7556  }
7557 };
7558 
7559 
7560 class HToFastProperties FINAL : public HUnaryOperation {
7561  public:
7563 
7565  return Representation::Tagged();
7566  }
7567 
7568  DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
7569 
7570  private:
7571  explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
7572  set_representation(Representation::Tagged());
7573  SetChangesFlag(kNewSpacePromotion);
7574 
7575  // This instruction is not marked as kChangesMaps, but does
7576  // change the map of the input operand. Use it only when creating
7577  // object literals via a runtime call.
7578  DCHECK(value->IsCallRuntime());
7579 #ifdef DEBUG
7580  const Runtime::Function* function = HCallRuntime::cast(value)->function();
7581  DCHECK(function->function_id == Runtime::kCreateObjectLiteral);
7582 #endif
7583  }
7584 
7585  virtual bool IsDeletable() const OVERRIDE { return true; }
7586 };
7587 
7588 
7589 class HDateField FINAL : public HUnaryOperation {
7590  public:
7592 
7593  Smi* index() const { return index_; }
7594 
7596  return Representation::Tagged();
7597  }
7598 
7599  DECLARE_CONCRETE_INSTRUCTION(DateField)
7600 
7601  private:
7602  HDateField(HValue* date, Smi* index)
7603  : HUnaryOperation(date), index_(index) {
7604  set_representation(Representation::Tagged());
7605  }
7606 
7607  Smi* index_;
7608 };
7609 
7610 
7611 class HSeqStringGetChar FINAL : public HTemplateInstruction<2> {
7612  public:
7613  static HInstruction* New(Zone* zone,
7614  HValue* context,
7615  String::Encoding encoding,
7616  HValue* string,
7617  HValue* index);
7618 
7620  return (index == 0) ? Representation::Tagged()
7622  }
7623 
7624  String::Encoding encoding() const { return encoding_; }
7625  HValue* string() const { return OperandAt(0); }
7626  HValue* index() const { return OperandAt(1); }
7627 
7628  DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)
7629 
7630  protected:
7631  virtual bool DataEquals(HValue* other) OVERRIDE {
7632  return encoding() == HSeqStringGetChar::cast(other)->encoding();
7633  }
7634 
7635  virtual Range* InferRange(Zone* zone) OVERRIDE {
7636  if (encoding() == String::ONE_BYTE_ENCODING) {
7637  return new(zone) Range(0, String::kMaxOneByteCharCode);
7638  } else {
7639  DCHECK_EQ(String::TWO_BYTE_ENCODING, encoding());
7640  return new(zone) Range(0, String::kMaxUtf16CodeUnit);
7641  }
7642  }
7643 
7644  private:
7646  HValue* string,
7647  HValue* index) : encoding_(encoding) {
7648  SetOperandAt(0, string);
7649  SetOperandAt(1, index);
7650  set_representation(Representation::Integer32());
7651  SetFlag(kUseGVN);
7652  SetDependsOnFlag(kStringChars);
7653  }
7654 
7655  virtual bool IsDeletable() const OVERRIDE { return true; }
7656 
7658 };
7659 
7660 
7661 class HSeqStringSetChar FINAL : public HTemplateInstruction<4> {
7662  public:
7664  HSeqStringSetChar, String::Encoding,
7665  HValue*, HValue*, HValue*);
7666 
7667  String::Encoding encoding() { return encoding_; }
7668  HValue* context() { return OperandAt(0); }
7669  HValue* string() { return OperandAt(1); }
7670  HValue* index() { return OperandAt(2); }
7671  HValue* value() { return OperandAt(3); }
7672 
7674  return (index <= 1) ? Representation::Tagged()
7676  }
7677 
7678  DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
7679 
7680  private:
7682  String::Encoding encoding,
7683  HValue* string,
7684  HValue* index,
7685  HValue* value) : encoding_(encoding) {
7686  SetOperandAt(0, context);
7687  SetOperandAt(1, string);
7688  SetOperandAt(2, index);
7689  SetOperandAt(3, value);
7690  set_representation(Representation::Tagged());
7691  SetChangesFlag(kStringChars);
7692  }
7693 
7694  String::Encoding encoding_;
7695 };
7696 
7697 
7698 class HCheckMapValue FINAL : public HTemplateInstruction<2> {
7699  public:
7701 
7703  return Representation::Tagged();
7704  }
7705 
7706  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7707 
7709  if (value()->type().IsHeapObject()) return value()->type();
7710  return HType::HeapObject();
7711  }
7712 
7713  HValue* value() const { return OperandAt(0); }
7714  HValue* map() const { return OperandAt(1); }
7715 
7717 
7718  DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
7719 
7720  protected:
7721  virtual int RedefinedOperandIndex() { return 0; }
7722 
7723  virtual bool DataEquals(HValue* other) OVERRIDE {
7724  return true;
7725  }
7726 
7727  private:
7729  : HTemplateInstruction<2>(HType::HeapObject()) {
7730  SetOperandAt(0, value);
7731  SetOperandAt(1, map);
7732  set_representation(Representation::Tagged());
7733  SetFlag(kUseGVN);
7734  SetDependsOnFlag(kMaps);
7735  SetDependsOnFlag(kElementsKind);
7736  }
7737 };
7738 
7739 
7740 class HForInPrepareMap FINAL : public HTemplateInstruction<2> {
7741  public:
7743 
7745  return Representation::Tagged();
7746  }
7747 
7748  HValue* context() const { return OperandAt(0); }
7749  HValue* enumerable() const { return OperandAt(1); }
7750 
7751  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7752 
7754  return HType::Tagged();
7755  }
7756 
7758 
7759  private:
7761  HValue* object) {
7762  SetOperandAt(0, context);
7763  SetOperandAt(1, object);
7764  set_representation(Representation::Tagged());
7765  SetAllSideEffects();
7766  }
7767 };
7768 
7769 
7770 class HForInCacheArray FINAL : public HTemplateInstruction<2> {
7771  public:
7772  DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
7773 
7775  return Representation::Tagged();
7776  }
7777 
7778  HValue* enumerable() const { return OperandAt(0); }
7779  HValue* map() const { return OperandAt(1); }
7780  int idx() const { return idx_; }
7781 
7782  HForInCacheArray* index_cache() {
7783  return index_cache_;
7784  }
7785 
7786  void set_index_cache(HForInCacheArray* index_cache) {
7787  index_cache_ = index_cache;
7788  }
7789 
7790  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7791 
7793  return HType::Tagged();
7794  }
7795 
7797 
7798  private:
7800  HValue* keys,
7801  int idx) : idx_(idx) {
7802  SetOperandAt(0, enumerable);
7803  SetOperandAt(1, keys);
7804  set_representation(Representation::Tagged());
7805  }
7806 
7807  int idx_;
7808  HForInCacheArray* index_cache_;
7809 };
7810 
7811 
7812 class HLoadFieldByIndex FINAL : public HTemplateInstruction<2> {
7813  public:
7815 
7817  HValue* index) {
7818  SetOperandAt(0, object);
7819  SetOperandAt(1, index);
7820  SetChangesFlag(kNewSpacePromotion);
7821  set_representation(Representation::Tagged());
7822  }
7823 
7825  if (index == 1) {
7826  return Representation::Smi();
7827  } else {
7828  return Representation::Tagged();
7829  }
7830  }
7831 
7832  HValue* object() const { return OperandAt(0); }
7833  HValue* index() const { return OperandAt(1); }
7834 
7835  virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7836 
7838  return HType::Tagged();
7839  }
7840 
7841  DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
7842 
7843  private:
7844  virtual bool IsDeletable() const OVERRIDE { return true; }
7845 };
7846 
7847 
7849  public:
7851 
7852  HValue* context() { return OperandAt(0); }
7853 
7855  return Representation::Tagged();
7856  }
7857 
7858  DECLARE_CONCRETE_INSTRUCTION(StoreFrameContext)
7859  private:
7863  SetChangesFlag(kContextSlots);
7864  }
7865 };
7866 
7867 
7869  public:
7872  HValue* context() const { return OperandAt(0); }
7873  HValue* function() const { return OperandAt(1); }
7875 
7877  return Representation::Tagged();
7878  }
7879 
7880  virtual OStream& PrintDataTo(OStream& os) const; // NOLINT
7881 
7882  DECLARE_CONCRETE_INSTRUCTION(AllocateBlockContext)
7883 
7884  private:
7886  HValue* function,
7888  : scope_info_(scope_info) {
7889  SetOperandAt(0, context);
7890  SetOperandAt(1, function);
7892  }
7893 
7895 };
7896 
7897 
7898 
7899 #undef DECLARE_INSTRUCTION
7900 #undef DECLARE_CONCRETE_INSTRUCTION
7901 
7902 } } // namespace v8::internal
7903 
7904 #endif // V8_HYDROGEN_INSTRUCTIONS_H_
#define BASE_EMBEDDED
Definition: allocation.h:45
A primitive boolean value (ECMA-262, 4.3.14).
Definition: v8.h:1731
static const int kAllocationSiteOffset
Definition: objects.h:8286
static bool CanTrack(InstanceType type)
Definition: objects-inl.h:1614
static Representation KeyedAccessIndexRequirement(Representation r)
virtual bool TryIncreaseBaseOffset(uint32_t increase_by_value)=0
virtual void SetKey(HValue *key)=0
virtual void SetDehoisted(bool is_dehoisted)=0
virtual ElementsKind elements_kind() const =0
virtual bool IsDehoisted() const =0
HUseIterator(HUseListNode *head)
const HControlInstruction * instr_
bool Apply(HValue *other_base, int other_offset, int other_scale=0)
void SwapValues(HValue **other_base, int *other_offset, int *other_scale)
HSuccessorIterator(const HControlInstruction *instr)
static U update(U previous, T value)
Definition: utils.h:223
static T decode(U value)
Definition: utils.h:228
static const int kValueOffset
Definition: objects.h:9446
static const int kFirstOffset
Definition: objects.h:9061
static const int kSecondOffset
Definition: objects.h:9062
void Remove(E element)
Definition: utils.h:857
bool Contains(E element) const
Definition: utils.h:851
bool ContainsAnyOf(const EnumSet &set) const
Definition: utils.h:852
void Intersect(const EnumSet &set)
Definition: utils.h:860
void Add(E element)
Definition: utils.h:855
static const int kExternalPointerOffset
Definition: objects.h:4471
ChecksRelatedToLength(HValue *length, ChecksRelatedToLength *next)
void AddCheck(HBoundsCheck *check, int32_t upper_limit=kNoLimit)
void UseNewIndexInCurrentBlock(Token::Value token, int32_t mask, HValue *index_base, HValue *context)
InductionVariableCheck(HBoundsCheck *check, InductionVariableCheck *next, int32_t upper_limit=kNoLimit)
Source to read snapshot and builtins files from.
Definition: lithium-arm.h:372
HInnerAllocatedObject(HValue *value, HValue *offset, HType type)
Heap::RootListIndex index() const
HCallJSFunction(HValue *function, int argument_count, bool pass_argument_count, bool has_stack_check)
HHasCachedArrayIndexAndBranch(HValue *value)
static HObjectAccess ForGlobalObjectNativeContext()
HCheckMaps(HValue *value, const UniqueSet< Map > *maps, HValue *typecheck)
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadKeyedGeneric, HValue *, HValue *)
HLoadContextSlot(HValue *context, int slot_index, Mode mode)
DECLARE_INSTRUCTION_FACTORY_P3(HCompareHoleAndBranch, HValue *, HBasicBlock *, HBasicBlock *)
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HMathFloorOfDiv, HValue *, HValue *)
static HContext * New(Zone *zone)
HConstructDouble(HValue *hi, HValue *lo)
static HInnerAllocatedObject * New(Zone *zone, HValue *context, HValue *value, HValue *offset, HType type)
void UpdateClearNextMapWord(bool clear_next_map_word)
DECLARE_INSTRUCTION_FACTORY_P4(HBranch, HValue *, ToBooleanStub::Types, HBasicBlock *, HBasicBlock *)
CallFunctionFlags function_flags_
HConstant * closure_context() const
static HPushArguments * New(Zone *zone, HValue *context, HValue *arg1, HValue *arg2, HValue *arg3)
int32_t NumberValueAsInteger32() const
RemovableSimulate removable_
static bool ComputeInductionVariableLimit(HBasicBlock *block, InductionVariableLimitUpdate *additional_limit)
Range * CopyClearLower(Zone *zone) const
virtual Representation RequiredInputRepresentation(int index) FINAL OVERRIDE
HAdd(HValue *context, HValue *left, HValue *right)
HStringCharFromCode(HValue *context, HValue *char_code)
DECLARE_INSTRUCTION_FACTORY_P1(HToFastProperties, HValue *)
HTransitionElementsKind(HValue *context, HValue *object, Handle< Map > original_map, Handle< Map > transitioned_map)
HIsObjectAndBranch(HValue *value, HBasicBlock *true_target=NULL, HBasicBlock *false_target=NULL)
HBitwise(HValue *context, Token::Value op, HValue *left, HValue *right)
bool IsOldPointerSpaceAllocation() const
virtual bool HasEscapingOperandAt(int index) OVERRIDE
HUnaryMathOperation(HValue *context, HValue *value, BuiltinFunctionId op)
HStoreCodeEntry(HValue *function, HValue *code)
HShl(HValue *context, HValue *left, HValue *right)
DECLARE_INSTRUCTION_FACTORY_P5(HLoadNamedField, HValue *, HValue *, HObjectAccess, const UniqueSet< Map > *, HType)
DECLARE_CONCRETE_INSTRUCTION(DummyUse)
HSimulate(BailoutId ast_id, int pop_count, Zone *zone, RemovableSimulate removable)
Handle< Map > transition_map() const
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInvokeFunction, HValue *, int)
void SetVectorAndSlot(Handle< FixedArray > vector, int slot)
static HObjectAccess ForObservableJSObjectOffset(int offset, Representation representation=Representation::Tagged())
virtual HType CalculateInferredType() OVERRIDE
const Runtime::Function * c_function_
static HConstant * CreateAndInsertBefore(Zone *zone, Unique< Map > map, bool map_is_stable, HInstruction *instruction)
DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue *)
Unique< Map > original_map() const
FunctionKind kind() const
HForceRepresentation(HValue *value, Representation required_representation)
HBasicBlock * induction_exit_block_
HIsStringAndBranch(HValue *value, HBasicBlock *true_target=NULL, HBasicBlock *false_target=NULL)
int length() const
The number of Latin-1 characters in the string.
DECLARE_INSTRUCTION_FACTORY_P4(HApplyArguments, HValue *, HValue *, HValue *, HValue *)
HInstanceOfKnownGlobal(HValue *context, HValue *left, Handle< JSFunction > right)
const Heap::RootListIndex index_
HStackCheck(HValue *context, Type type)
virtual bool IsCommutative() const OVERRIDE
uint32_t base_offset() const
DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray)
DECLARE_INSTRUCTION_FACTORY_P2(HBranch, HValue *, ToBooleanStub::Types)
virtual bool HandleSideEffectDominator(GVNFlag side_effect, HValue *dominator) OVERRIDE
DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool)
DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId)
virtual int OperandCount() const OVERRIDE
virtual Opcode opcode() const OVERRIDE
HCallNew(HValue *context, HValue *constructor, int argument_count)
HLoadNamedField(HValue *object, HValue *dependency, HObjectAccess access, const UniqueSet< Map > *maps, HType type)
virtual Range * InferRange(Zone *zone) OVERRIDE
void Shl(int32_t value)
HTypeof(HValue *context, HValue *value)
DECLARE_INSTRUCTION_FACTORY_P2(HDoubleBits, HValue *, Bits)
virtual HValue * OperandAt(int i) const FINAL OVERRIDE
HCheckMaps(HValue *value, const UniqueSet< Map > *maps, bool maps_are_stable)
HObjectAccess(Portion portion, int offset, Representation representation=Representation::Tagged(), Handle< String > name=Handle< String >::null(), bool immutable=false, bool existing_inobject_property=true)
int32_t ComputeUpperLimit(int32_t and_mask, int32_t or_mask)
InstanceType GetInstanceType() const
virtual bool IsDeletable() const OVERRIDE
HBasicBlock * induction_exit_block()
DECLARE_INSTRUCTION_FACTORY_P2(HDateField, HValue *, Smi *)
HTailCallThroughMegamorphicCache(HValue *context, HValue *receiver, HValue *name, Code::Flags flags)
HCallNewArray(HValue *context, HValue *constructor, int argument_count, ElementsKind elements_kind)
bool CanBeReplacedWith(HStoreNamedField *that) const
Handle< FixedArray > literals()
HDiv(HValue *context, HValue *left, HValue *right)
static HInstruction * New(Zone *zone, HValue *context, HValue *char_code)
bool IsOldDataSpaceAllocation() const
void ReuseSideEffectsFromStore(HInstruction *store)
ElementsKind to_kind() const
DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned)
DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue *, HValue *, HValue *, ElementsKind, LoadKeyedHoleMode)
DECLARE_INSTRUCTION_FACTORY_P4(HStoreKeyed, HValue *, HValue *, HValue *, ElementsKind)
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HReturn, HValue *, HValue *)
HConstant(int32_t value, Representation r=Representation::None(), bool is_not_in_new_space=true, Unique< Object > optional=Unique< Object >(Handle< Object >::null()))
const char * reason() const
void AddValue(int index, HValue *value)
void Union(Range *other)
DECLARE_INSTRUCTION_FACTORY_P2(HParameter, unsigned, ParameterKind)
HLoadNamedField(HValue *object, HValue *dependency, HObjectAccess access)
static HPushArguments * New(Zone *zone, HValue *context, HValue *arg1)
HStoreNamedGeneric(HValue *context, HValue *object, Handle< String > name, HValue *value, StrictMode strict_mode)
virtual int RedefinedOperandIndex()
bool CanBeReplacedWith(HValue *other) const
Representation representation() const
HUnknownOSRValue(HEnvironment *environment, int index)
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOf, HValue *, HValue *)
void UpdateFreeSpaceFiller(int32_t filler_size)
HForInPrepareMap(HValue *context, HValue *object)
HBasicBlock * induction_exit_target()
Unique< Cell > cell() const
static HObjectAccess ForMapInstanceType()
StoreFieldOrKeyedMode store_mode() const
HLoadGlobalGeneric(HValue *context, HValue *global_object, Handle< String > name, bool for_typeof)
HDoubleBits(HValue *value, Bits bits)
virtual Handle< Map > GetMonomorphicJSObjectMap() OVERRIDE
ZoneList< int > assigned_indexes_
DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue *, HValue *)
static HInstruction * NewImul(Zone *zone, HValue *context, HValue *left, HValue *right)
static HObjectAccess ForJSArrayBufferViewByteLength()
SaveFPRegsMode save_doubles() const
virtual HSourcePosition position() const OVERRIDE
DECLARE_INSTRUCTION_FACTORY_P6(HLoadKeyed, HValue *, HValue *, HValue *, ElementsKind, LoadKeyedHoleMode, int)
HBoundsCheckBaseIndexInformation(HBoundsCheck *check)
static HObjectAccess ForMapAsInteger32()
DECLARE_INSTRUCTION_FACTORY_P1(HClampToUint8, HValue *)
InductionVariableData(HPhi *phi, HValue *base, int32_t increment)
HGetCachedArrayIndex(HValue *value)
HValue * base_object() const
static HObjectAccess ForMapInstanceSize()
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallNew, HValue *, int)
const UniqueSet< Map > * maps() const
Token::Value token() const
static HObjectAccess ForExternalArrayExternalPointer()
Handle< FixedArray > pairs_
const StringAddFlags flags_
static HPushArguments * New(Zone *zone, HValue *context, HValue *arg1, HValue *arg2, HValue *arg3, HValue *arg4)
Handle< FixedArray > feedback_vector_
bool SupportsFlexibleFloorAndRound() const
virtual Representation observed_input_representation(int index) OVERRIDE
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallStub, CodeStub::Major, int)
HBasicBlock * limit_validity()
bool Equals(HObjectAccess that) const
virtual bool IsDeletable() const FINAL OVERRIDE
void SetUninitialized(bool is_uninitialized)
static HObjectAccess ForAllocationMementoSite()
virtual ElementsKind elements_kind() const OVERRIDE
HGoto(HBasicBlock *target)
DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue *, HValue *, HObjectAccess)
Handle< String > type_literal() const
static HCheckValue * New(Zone *zone, HValue *context, HValue *value, Unique< HeapObject > target, bool object_in_new_space)
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallFunction, HValue *, int)
Handle< String > pattern()
static HObjectAccess ForHeapNumberValueHighestBits()
HArgumentsObject * arguments_object_
Handle< FixedArray > literals_
HValue * SimplifiedDividendForMathFloorOfDiv(HDiv *hdiv)
static HObjectAccess ForPrototypeOrInitialMap()
ToBooleanStub::Types expected_input_types_
HForInCacheArray(HValue *enumerable, HValue *keys, int idx)
static HObjectAccess ForCellValue()
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCallRuntime, Handle< String >, const Runtime::Function *, int)
static HObjectAccess ForAllocationSiteOffset(int offset)
int ToOperandIndex(int environment_index)
STATIC_ASSERT((kBitsForElementsKind+kBitsForBaseOffset+kBitsForIsDehoisted)<=sizeof(uint32_t) *8)
bool IsFoldable(HAllocate *allocate)
HConstant(double value, Representation r=Representation::None(), bool is_not_in_new_space=true, Unique< Object > optional=Unique< Object >(Handle< Object >::null()))
DECLARE_INSTRUCTION_FACTORY_P2(HLoadRoot, Heap::RootListIndex, HType)
String::Encoding encoding() const
DECLARE_INSTRUCTION_FACTORY_P4(HCompareMap, HValue *, Handle< Map >, HBasicBlock *, HBasicBlock *)
HObjectAccess WithRepresentation(Representation representation)
HPower(HValue *left, HValue *right)
Unique< HeapObject > object() const
static HObjectAccess ForStringHashField()
void SetTransition(HConstant *transition)
Handle< JSFunction > closure_
HMathFloorOfDiv(HValue *context, HValue *left, HValue *right)
static void ComputeLimitFromPredecessorBlock(HBasicBlock *block, LimitFromPredecessorBlock *result)
virtual void FinalizeUniqueness() OVERRIDE
ZoneList< HBasicBlock * > return_targets_
HConstant(Handle< Object > handle, Representation r=Representation::None())
virtual bool IsPurelyInformativeDefinition() OVERRIDE
virtual void RepresentationChanged(Representation to) OVERRIDE
DECLARE_INSTRUCTION_FACTORY_P0(HAbnormalExit)
static HObjectAccess ForElementsPointer()
bool deoptimize_on_minus_zero() const
HStoreContextSlot(HValue *context, int slot_index, Mode mode, HValue *value)
void Initialize(Representation r)
HSub(HValue *context, HValue *left, HValue *right)
static Representation RequiredValueRepresentation(ElementsKind kind, StoreFieldOrKeyedMode mode)
bool AllUsesCanTreatHoleAsNaN() const
DECLARE_INSTRUCTION_FACTORY_P1(HGetCachedArrayIndex, HValue *)
DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue *)
static HObjectAccess ForPropertiesPointer()
HFunctionLiteral(HValue *context, Handle< SharedFunctionInfo > shared, bool pretenure)
HCallRuntime(HValue *context, Handle< String > name, const Runtime::Function *c_function, int argument_count)
DECLARE_INSTRUCTION_FACTORY_P2(HLoadFieldByIndex, HValue *, HValue *)
ChecksRelatedToLength * checks_
DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference)
void GetCheckMaskAndTag(uint8_t *mask, uint8_t *tag)
HDeclareGlobals(HValue *context, Handle< FixedArray > pairs, int flags)
DECLARE_INSTRUCTION_FACTORY_P2(HClassOfTestAndBranch, HValue *, Handle< String >)
DECLARE_INSTRUCTION_FACTORY_P1(HBranch, HValue *)
HPhi(int merged_index, Zone *zone)
static InductionVariableData * GetInductionVariableData(HValue *v)
Unique< Map > ObjectMap() const
Handle< String > class_name() const
DECLARE_INSTRUCTION_FACTORY_P3(HIsObjectAndBranch, HValue *, HBasicBlock *, HBasicBlock *)
void UpdateValue(HValue *value)
int32_t Mask() const
void ClearNextMapWord(int offset)
virtual bool EmitAtUses() OVERRIDE
HLoadGlobalCell(Handle< Cell > cell, PropertyDetails details)
Unique< Map > transitioned_map() const
Deoptimizer::BailoutType type()
HStoreNamedField(HValue *obj, HObjectAccess access, HValue *val, StoreFieldOrKeyedMode store_mode=INITIALIZING_STORE)
String::Encoding encoding()
Representation field_representation() const
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCompareGeneric, HValue *, HValue *, Token::Value)
void set_maps(const UniqueSet< Map > *maps)
Handle< JSFunction > known_function_
HInvokeFunction(HValue *context, HValue *function, int argument_count)
bool ImmortalImmovable() const
static HObjectAccess ForCellPayload(Isolate *isolate)
static HObjectAccess ForStringLength()
virtual bool HasStackCheck() FINAL OVERRIDE
virtual int argument_count() const
static HPhi * cast(HValue *value)
HCompareHoleAndBranch(HValue *value, HBasicBlock *true_target=NULL, HBasicBlock *false_target=NULL)
int32_t Integer32Value() const
static HObjectAccess ForConsStringFirst()
virtual int RedefinedOperandIndex() OVERRIDE
void UpdateAdditionalLimit(InductionVariableLimitUpdate *update)
HAllocate * GetFoldableDominator(HAllocate *dominator)
DECLARE_INSTRUCTION_FACTORY_P6(HStoreKeyed, HValue *, HValue *, HValue *, ElementsKind, StoreFieldOrKeyedMode, int)
virtual Representation RepresentationFromInputs() OVERRIDE
static HObjectAccess ForFixedArrayLength()
DECLARE_INSTRUCTION_FACTORY_P1(HConstant, int32_t)
DECLARE_INSTRUCTION_FACTORY_P1(HIsObjectAndBranch, HValue *)
static HInstruction * New(Zone *zone, HValue *context, HValue *left, HValue *right, PretenureFlag pretenure_flag=NOT_TENURED, StringAddFlags flags=STRING_ADD_CHECK_BOTH, Handle< AllocationSite > allocation_site=Handle< AllocationSite >::null())
static HObjectAccess ForNameHashField()
ExternalReference external_reference_value_
virtual int OperandCount() const FINAL OVERRIDE
HCompareGeneric(HValue *context, HValue *left, HValue *right, Token::Value token)
HValue * SimplifiedDivisorForMathFloorOfDiv(HDiv *hdiv)
void set_size_upper_bound(HConstant *value)
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOfKnownGlobal, HValue *, Handle< JSFunction >)
DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue *, HValue *, int)
InliningKind inlining_kind() const
HChange(HValue *value, Representation to, bool is_truncating_to_smi, bool is_truncating_to_int32)
DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue *, Handle< String >)
DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue *, HObjectAccess, HValue *)
static HCheckValue * New(Zone *zone, HValue *context, HValue *value, Handle< JSFunction > func)
DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue *, HValue *)
Handle< JSFunction > known_function()
HShr(HValue *context, HValue *left, HValue *right)
HArgumentsObject * arguments_object()
bool CheckIfBranchIsLoopGuard(Token::Value token, HBasicBlock *current_branch, HBasicBlock *other_branch)
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCallFunction, HValue *, int, CallFunctionFlags)
void set_incoming_value(HPhi *value)
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadNamedGeneric, HValue *, Handle< Object >)
static HObjectAccess ForJSArrayBufferViewWeakNext()
HTypeofIsAndBranch(HValue *value, Handle< String > type_literal)
static HInstruction * New(Zone *zone, HValue *context, HValue *left, HValue *right, Operation op)
Handle< Object > name() const
HLoadNamedGeneric(HValue *context, HValue *object, Handle< Object > name)
static HObjectAccess ForHeapNumberValue()
HCheckInstanceType(HValue *value, Check check)
HValue * parameter_count() const
DECLARE_INSTRUCTION_FACTORY_P2(HUnknownOSRValue, HEnvironment *, int)
const ZoneList< HValue * > * arguments_values() const
bool HasValueForIndex(int index)
CallInterfaceDescriptor descriptor() const
static HObjectAccess ForFunctionContextPointer()
Token::Value op() const
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HDeclareGlobals, Handle< FixedArray >, int)
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HForInPrepareMap, HValue *)
static HInstruction * New(Zone *zone, HValue *context, HValue *left, HValue *right)
Unique< Object > GetUnique() const
static HObjectAccess ForMapAndOffset(Handle< Map > map, int offset, Representation representation=Representation::Tagged())
void AddCheck(HBoundsCheck *check, int32_t upper_limit=kNoLimit)
DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap)
static HStoreCodeEntry * New(Zone *zone, HValue *context, HValue *function, HValue *code)
virtual int argument_delta() const OVERRIDE
static HValue * IgnoreOsrValue(HValue *v)
HCapturedObject(int length, int id, Zone *zone)
StringAddFlags flags() const
static HInstruction * New(Zone *zone, HValue *context, Token::Value op, HValue *left, HValue *right)
DECLARE_INSTRUCTION_FACTORY_P3(HStoreGlobalCell, HValue *, Handle< PropertyCell >, PropertyDetails)
const UniqueSet< Map > * maps_
const char * GetCheckName() const
static HConstant * CreateAndInsertAfter(Zone *zone, HValue *context, int32_t value, Representation representation, HInstruction *instruction)
static HInstruction * New(Zone *zone, HValue *context, HValue *value, Representation required_representation)
DECLARE_INSTRUCTION_FACTORY_P0(HThisFunction)
HCallWithDescriptor(HValue *target, int argument_count, CallInterfaceDescriptor descriptor, const Vector< HValue * > &operands, Zone *zone)
void Intersect(Range *other)
HLoadKeyed(HValue *obj, HValue *key, HValue *dependency, ElementsKind elements_kind, LoadKeyedHoleMode mode=NEVER_RETURN_HOLE, int offset=kDefaultKeyedHeaderOffsetSentinel)
HLoadFunctionPrototype(HValue *function)
DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue *, int, Mode, HValue *)
static HCheckMaps * New(Zone *zone, HValue *context, HValue *value, SmallMapList *map_list, HValue *typecheck=NULL)
static HObjectAccess ForJSArrayOffset(int offset)
Handle< String > name() const
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCallNewArray, HValue *, int, ElementsKind)
static void DecomposeBitwise(HValue *value, BitwiseDecompositionResult *result)
virtual void InferRepresentation(HInferRepresentationPhase *h_infer) OVERRIDE
HObjectAccess access() const
static HObjectAccess ForLiteralsPointer()
HHasInstanceTypeAndBranch(HValue *value, InstanceType type)
Handle< String > StringValue() const
HBoundsCheck(HValue *index, HValue *length)
void AddConstant(int32_t value)
HCompareMinusZeroAndBranch(HValue *value)
HStoreKeyedGeneric(HValue *context, HValue *object, HValue *key, HValue *value, StrictMode strict_mode)
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HStringCharCodeAt, HValue *, HValue *)
FunctionLiteral * function_
Handle< FixedArray > feedback_vector() const
DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle< Object >)
static HConstant * CreateAndInsertBefore(Zone *zone, HValue *context, int32_t value, Representation representation, HInstruction *instruction)
void set_can_be_minus_zero(bool b)
virtual OStream & PrintDataTo(OStream &os) const
static HObjectAccess ForMapBitField2()
Handle< JSFunction > closure() const
HLoadRoot(Heap::RootListIndex index, HType type=HType::Tagged())
static HObjectAccess ForJSTypedArrayLength()
DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue *, HValue *)
static HObjectAccess ForConsStringSecond()
HConstant(ExternalReference reference)
Handle< String > class_name_
static HObjectAccess ForArrayLength(ElementsKind elements_kind)
void Sar(int32_t value)
DECLARE_INSTRUCTION_FACTORY_P2(HEnvironmentMarker, Kind, int)
DECLARE_INSTRUCTION_FACTORY_P3(HAccessArgumentsAt, HValue *, HValue *, HValue *)
ZoneList< HValue * > values_
void CombinedMin(Range *other)
void set_known_successor_index(int known_successor_index)
void AddOperand(HValue *v, Zone *zone)
ElementsKind elements_kind() const
void CombinedMax(Range *other)
static HObjectAccess ForMapBitField()
void GetCheckInterval(InstanceType *first, InstanceType *last)
HArgumentsElements(bool from_inlined)
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HRegExpLiteral, Handle< FixedArray >, Handle< String >, Handle< String >, int)
void AddInput(HValue *value)
HDateField(HValue *date, Smi *index)
void ReplayEnvironment(HEnvironment *env)
HBoundsCheck * bounds_check()
static HObjectAccess ForJSArrayBufferBackingStore()
virtual void InternalSetOperandAt(int index, HValue *value) OVERRIDE
virtual intptr_t Hashcode() OVERRIDE
LoadKeyedHoleMode hole_mode() const
DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex)
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HStackCheck, Type)
bool Includes(int value) const
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HFunctionLiteral, Handle< SharedFunctionInfo >, bool)
Unique< HeapObject > object_
Range * CopyClearUpper(Zone *zone) const
int GetAssignedIndexAt(int index) const
HWrapReceiver(HValue *receiver, HValue *function)
HParameter(unsigned index, ParameterKind kind=STACK_PARAMETER)
HEnvironmentMarker(Kind kind, int index)
Unique< PropertyCell > cell_
static HCallJSFunction * New(Zone *zone, HValue *context, HValue *function, int argument_count, bool pass_argument_count)
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadGlobalGeneric, HValue *, Handle< String >, bool)
static HObjectAccess ForCodeEntryPointer()
void CreateFreeSpaceFiller(int32_t filler_size)
DECLARE_INSTRUCTION_FACTORY_P1(HHasCachedArrayIndexAndBranch, HValue *)
HCheckValue(HValue *value, Unique< HeapObject > object, bool object_in_new_space)
DECLARE_INSTRUCTION_FACTORY_P0(HDebugBreak)
DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue *, HObjectAccess, HValue *, StoreFieldOrKeyedMode)
bool MulAndCheckOverflow(const Representation &r, Range *other)
HAccessArgumentsAt(HValue *arguments, HValue *length, HValue *index)
static HEnterInlined * New(Zone *zone, HValue *context, BailoutId return_id, Handle< JSFunction > closure, HConstant *closure_context, int arguments_count, FunctionLiteral *function, InliningKind inlining_kind, Variable *arguments_var, HArgumentsObject *arguments_object)
StoreFieldOrKeyedMode store_mode_
HBasicBlock * induction_exit_target_
virtual void UpdateRepresentation(Representation new_rep, HInferRepresentationPhase *h_infer, const char *reason) OVERRIDE
DECLARE_INSTRUCTION_FACTORY_P3(HHasInstanceTypeAndBranch, HValue *, InstanceType, InstanceType)
static HObjectAccess ForJSArrayBufferViewByteOffset()
void InternalSetOperandAt(int index, HValue *value) FINAL OVERRIDE
HStoreNamedField * filler_free_space_size_
static HObjectAccess ForSharedFunctionInfoPointer()
static HTransitionElementsKind * New(Zone *zone, HValue *context, HValue *object, Handle< Map > original_map, Handle< Map > transitioned_map)
void RegisterReturnTarget(HBasicBlock *return_target, Zone *zone)
void set_ast_id(BailoutId id)
DECLARE_CONCRETE_INSTRUCTION(EnvironmentMarker)
DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue *, Check)
virtual Representation KnownOptimalRepresentation() OVERRIDE
void SetGVNFlags(HValue *instr, PropertyAccessType access_type)
void set_known_initial_map(Handle< Map > known_initial_map)
static HAllocate * New(Zone *zone, HValue *context, HValue *size, HType type, PretenureFlag pretenure_flag, InstanceType instance_type, Handle< AllocationSite > allocation_site=Handle< AllocationSite >::null())
static HObjectAccess ForFixedArrayHeader(int offset)
bool existing_inobject_property() const
HCompareMap(HValue *value, Handle< Map > map, HBasicBlock *true_target=NULL, HBasicBlock *false_target=NULL)
HUseConst(HValue *old_value)
void set_next_simulate(HSimulate *simulate)
DECLARE_INSTRUCTION_FACTORY_P1(HIsUndetectableAndBranch, HValue *)
static HObjectAccess ForJSArrayBufferByteLength()
HEnvironment * environment()
DECLARE_INSTRUCTION_FACTORY_P1(HCompareHoleAndBranch, HValue *)
HLoadFieldByIndex(HValue *object, HValue *index)
HCallFunction(HValue *context, HValue *function, int argument_count, CallFunctionFlags flags=NO_CALL_FUNCTION_FLAGS)
DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue *)
virtual Representation RequiredInputRepresentation(int index)
HStringAdd(HValue *context, HValue *left, HValue *right, PretenureFlag pretenure_flag, StringAddFlags flags, Handle< AllocationSite > allocation_site)
HOsrEntry(BailoutId ast_id)
Representation to() const
CallFunctionFlags function_flags() const
HHasInstanceTypeAndBranch(HValue *value, InstanceType from, InstanceType to)
static HInvokeFunction * New(Zone *zone, HValue *context, HValue *function, Handle< JSFunction > known_function, int argument_count)
bool NeedsCanonicalization()
HSar(HValue *context, HValue *left, HValue *right)
bool MustAllocateDoubleAligned() const
HAllocate(HValue *context, HValue *size, HType type, PretenureFlag pretenure_flag, InstanceType instance_type, Handle< AllocationSite > allocation_site=Handle< AllocationSite >::null())
HLeaveInlined(HEnterInlined *entry, int drop_count)
HValue * GetRedundantReplacement()
DECLARE_INSTRUCTION_FACTORY_P3(HParameter, unsigned, ParameterKind, Representation)
HClassOfTestAndBranch(HValue *value, Handle< String > class_name)
void set_index_cache(HForInCacheArray *index_cache)
DECLARE_INSTRUCTION_FACTORY_P2(HCompareMap, HValue *, Handle< Map >)
ExternalReference ExternalReferenceValue() const
CodeStub::Major major_key()
bool TryIncreaseBaseOffset(uint32_t increase_by_value)
DECLARE_INSTRUCTION_FACTORY_P1(HLoadRoot, Heap::RootListIndex)
Handle< JSFunction > function_
HStoreKeyed(HValue *obj, HValue *key, HValue *val, ElementsKind elements_kind, StoreFieldOrKeyedMode store_mode=INITIALIZING_STORE, int offset=kDefaultKeyedHeaderOffsetSentinel)
StrictMode strict_mode() const
void AddIndirectUsesTo(int *use_count)
STATIC_ASSERT(kElementsKindCount<=(1<< kBitsForElementsKind))
HStoreGlobalCell(HValue *value, Handle< PropertyCell > cell, PropertyDetails details)
static HInstruction * New(Zone *zone, HValue *context, String::Encoding encoding, HValue *string, HValue *index)
HInstanceOf(HValue *context, HValue *left, HValue *right)
bool HasExternalReferenceValue() const
ToBooleanStub::Types expected_input_types() const
ChecksRelatedToLength * checks()
virtual OStream & PrintDataTo(OStream &os) const OVERRIDE
DECLARE_INSTRUCTION_FACTORY_P1(HIsSmiAndBranch, HValue *)
HBranch(HValue *value, ToBooleanStub::Types expected_input_types=ToBooleanStub::Types(), HBasicBlock *true_target=NULL, HBasicBlock *false_target=NULL)
DECLARE_INSTRUCTION_FACTORY_P3(HIsStringAndBranch, HValue *, HBasicBlock *, HBasicBlock *)
static HObjectAccess ForCodeOffset()
static HObjectAccess ForExternalUInteger8()
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreNamedGeneric, HValue *, Handle< String >, HValue *, StrictMode)
bool RequiresHoleCheck() const
const ZoneList< HValue * > * values() const
static HArgumentsObject * New(Zone *zone, HValue *context, int count)
Handle< Object > handle(Isolate *isolate)
HEnterInlined(BailoutId return_id, Handle< JSFunction > closure, HConstant *closure_context, int arguments_count, FunctionLiteral *function, InliningKind inlining_kind, Variable *arguments_var, HArgumentsObject *arguments_object, Zone *zone)
static HObjectAccess ForBackingStoreOffset(int offset, Representation representation=Representation::Tagged())
void AddArgument(HValue *argument, Zone *zone)
static HObjectAccess ForHeapNumberValueLowestBits()
HParameter(unsigned index, ParameterKind kind, Representation r)
virtual void DeleteFromGraph() OVERRIDE
ZoneList< HValue * > inputs_
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreKeyedGeneric, HValue *, HValue *, HValue *, StrictMode)
InductionVariableData * induction_variable_data()
static HObjectAccess ForJSArrayBufferViewBuffer()
virtual OStream & PrintTo(OStream &os) const OVERRIDE
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HTypeof, HValue *)
Handle< FixedArray > pairs() const
InductionVariableData * induction_variable_data_
HDeoptimize(const char *reason, Deoptimizer::BailoutType type, HBasicBlock *unreachable_continuation)
HValue * length() const
The number of Latin-1 characters in the string.
DECLARE_INSTRUCTION_FACTORY_P1(HMapEnumLength, HValue *)
DECLARE_INSTRUCTION_FACTORY_P2(HHasInstanceTypeAndBranch, HValue *, InstanceType)
HRor(HValue *context, HValue *left, HValue *right)
Unique< PropertyCell > cell() const
Unique< String > type_literal_
void InitRealUses(int id)
ElementsKind from_kind() const
DECLARE_INSTRUCTION_FACTORY_P1(HCompareMinusZeroAndBranch, HValue *)
HMod(HValue *context, HValue *left, HValue *right)
HMathMinMax(HValue *context, HValue *left, HValue *right, Operation op)
HRegExpLiteral(HValue *context, Handle< FixedArray > literals, Handle< String > pattern, Handle< String > flags, int literal_index)
static HObjectAccess ForPropertyCellValue()
static HObjectAccess ForMapInstanceTypeAndBitField()
static HConstant * CreateAndInsertAfter(Zone *zone, Unique< Map > map, bool map_is_stable, HInstruction *instruction)
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HReturn, HValue *)
HStringCharCodeAt(HValue *context, HValue *string, HValue *index)
static HObjectAccess ForNextFunctionLinkPointer()
static HObjectAccess ForAllocationSiteList()
static HCallWithDescriptor * New(Zone *zone, HValue *context, HValue *target, int argument_count, CallInterfaceDescriptor descriptor, const Vector< HValue * > &operands)
virtual HValue * OperandAt(int index) const OVERRIDE
void AddNonPhiUsesFrom(HPhi *other)
void set_save_doubles(SaveFPRegsMode save_doubles)
DECLARE_INSTRUCTION_FACTORY_P1(HIsStringAndBranch, HValue *)
virtual void InternalSetOperandAt(int i, HValue *value) FINAL OVERRIDE
void MergeWith(ZoneList< HSimulate * > *list)
bool HasAssignedIndexAt(int index) const
static HObjectAccess ForContextSlot(int index)
DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue *, HValue *, HValue *, ElementsKind, StoreFieldOrKeyedMode)
DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue *)
bool UsesMustHandleHole() const
Range(int32_t lower, int32_t upper)
DECLARE_INSTRUCTION_FACTORY_P2(HConstructDouble, HValue *, HValue *)
HForInCacheArray * index_cache_
static HPushArguments * New(Zone *zone, HValue *context)
virtual bool DataEquals(HValue *other) OVERRIDE
Range * Copy(Zone *zone) const
static InductionVariableData * ExaminePhi(HPhi *phi)
ParameterKind kind() const
Unique< Map > MapValue() const
HReturn(HValue *context, HValue *value, HValue *parameter_count=0)
virtual bool TryDecompose(DecompositionResult *decomposition) OVERRIDE
BailoutId ReturnId() const
static HObjectAccess ForJSArrayBufferWeakFirstView()
static HObjectAccess ForMap()
HConstant(Unique< Object > object, Unique< Map > object_map, bool has_stable_map_value, Representation r, HType type, bool is_not_in_new_space, bool boolean_value, bool is_undetectable, InstanceType instance_type)
static bool CompatibleInstanceTypes(InstanceType type1, InstanceType type2)
SmiCheck SmiCheckForWriteBarrier() const
DECLARE_INSTRUCTION_FACTORY_P3(HIsSmiAndBranch, HValue *, HBasicBlock *, HBasicBlock *)
void AddPushedValue(HValue *value)
virtual bool HasOutOfBoundsAccess(int size) OVERRIDE
bool AddAndCheckOverflow(const Representation &r, Range *other)
bool HasInternalizedStringValue() const
virtual Representation RequiredInputRepresentation(int index) OVERRIDE
const PretenureFlag pretenure_flag_
PointersToHereCheck PointersToHereCheckForValue() const
DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation)
HIsSmiAndBranch(HValue *value, HBasicBlock *true_target=NULL, HBasicBlock *false_target=NULL)
void SetDehoisted(bool is_dehoisted)
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HSeqStringSetChar, String::Encoding, HValue *, HValue *, HValue *)
HArgumentsObject(int count, Zone *zone)
DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double)
static HInstruction * New(Zone *zone, HValue *context, HValue *value, BuiltinFunctionId op)
HCheckMapValue(HValue *value, HValue *map)
Unique< Map > map() const
bool EqualsUnique(Unique< Object > other) const
static HCheckMaps * New(Zone *zone, HValue *context, HValue *value, Handle< Map > map, HValue *typecheck=NULL)
HMul(HValue *context, HValue *left, HValue *right)
const char * OpName() const
PretenureFlag pretenure_flag() const
DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue *)
HSeqStringGetChar(String::Encoding encoding, HValue *string, HValue *index)
HToFastProperties(HValue *value)
DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue *)
static int32_t ComputeIncrement(HPhi *phi, HValue *phi_operand)
Deoptimizer::BailoutType type_
static HCheckMaps * CreateAndInsertBefore(Zone *zone, HValue *value, const UniqueSet< Map > *maps, bool maps_are_stable, HInstruction *instr)
DECLARE_INSTRUCTION_FACTORY_P3(HIsUndetectableAndBranch, HValue *, HBasicBlock *, HBasicBlock *)
void StackUpon(Range *other)
virtual HValue * OperandAt(int index) const FINAL OVERRIDE
static Flags ComputeFlags(PretenureFlag pretenure_flag, InstanceType instance_type)
HApplyArguments(HValue *function, HValue *receiver, HValue *length, HValue *elements)
HInvokeFunction(HValue *context, HValue *function, Handle< JSFunction > known_function, int argument_count)
HIsUndetectableAndBranch(HValue *value, HBasicBlock *true_target=NULL, HBasicBlock *false_target=NULL)
DECLARE_INSTRUCTION_FACTORY_P4(HLoadKeyed, HValue *, HValue *, HValue *, ElementsKind)
ZoneList< HBasicBlock * > * return_targets()
static HObjectAccess ForCounter()
HForInCacheArray * index_cache()
virtual bool KnownSuccessorBlock(HBasicBlock **block) OVERRIDE
void AddAssignedValue(int index, HValue *value)
virtual HValue * Canonicalize() OVERRIDE
DECLARE_INSTRUCTION_FACTORY_P2(HLoadGlobalCell, Handle< Cell >, PropertyDetails)
Handle< String > flags()
Code::Flags flags() const
static HPushArguments * New(Zone *zone, HValue *context, HValue *arg1, HValue *arg2)
HSeqStringSetChar(HValue *context, String::Encoding encoding, HValue *string, HValue *index, HValue *value)
HCallStub(HValue *context, CodeStub::Major major_key, int argument_count)
bool SubAndCheckOverflow(const Representation &r, Range *other)
static HDeoptimize * New(Zone *zone, HValue *context, const char *reason, Deoptimizer::BailoutType type, HBasicBlock *unreachable_continuation)
static HObjectAccess ForOptimizedCodeMap()
void UpdateSize(HValue *size)
void SimplifyConstantInputs()
static HObjectAccess ForField(Handle< Map > map, int index, Representation representation, Handle< String > name)
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HTailCallThroughMegamorphicCache, HValue *, HValue *, Code::Flags)
static HObjectAccess ForMapInObjectProperties()
static const int kLengthOffset
Definition: objects.h:2392
static bool is_the_hole_nan(double value)
Definition: objects-inl.h:2200
static const int kNativeContextOffset
Definition: objects.h:7459
virtual OStream & PrintDataTo(OStream &os) const
HAllocateBlockContext(HValue *context, HValue *function, Handle< ScopeInfo > scope_info)
Handle< ScopeInfo > scope_info() const
DECLARE_INSTRUCTION_FACTORY_P3(HAllocateBlockContext, HValue *, HValue *, Handle< ScopeInfo >)
virtual Representation RequiredInputRepresentation(int index)
virtual void RepresentationChanged(Representation to) OVERRIDE
HArithmeticBinaryOperation(HValue *context, HValue *left, HValue *right)
virtual Representation RequiredInputRepresentation(int index) FINAL OVERRIDE
HBinaryCall(HValue *first, HValue *second, int argument_count)
virtual OStream & PrintDataTo(OStream &os) const OVERRIDE
virtual void UpdateRepresentation(Representation new_rep, HInferRepresentationPhase *h_infer, const char *reason) OVERRIDE
virtual Representation observed_input_representation(int index) OVERRIDE
virtual Representation RequiredInputRepresentation(int index) OVERRIDE
HBinaryOperation(HValue *context, HValue *left, HValue *right, HType type=HType::Tagged())
virtual OStream & PrintDataTo(OStream &os) const OVERRIDE
void set_observed_input_representation(int index, Representation rep)
virtual void initialize_output_representation(Representation observed)
virtual void AssumeRepresentation(Representation r) OVERRIDE
virtual Representation RepresentationFromInputs() OVERRIDE
void SetOperandPositions(Zone *zone, HSourcePosition left_pos, HSourcePosition right_pos)
bool IgnoreObservedOutputRepresentation(Representation current_rep)
virtual void InferRepresentation(HInferRepresentationPhase *h_infer) OVERRIDE
Representation observed_input_representation_[2]
virtual bool IsDeletable() const OVERRIDE
virtual void RepresentationChanged(Representation to) OVERRIDE
virtual Representation observed_input_representation(int index) OVERRIDE
virtual void UpdateRepresentation(Representation new_rep, HInferRepresentationPhase *h_infer, const char *reason) OVERRIDE
HBitwiseBinaryOperation(HValue *context, HValue *left, HValue *right, HType type=HType::TaggedNumber())
virtual void initialize_output_representation(Representation observed)
virtual HType CalculateInferredType() FINAL OVERRIDE
virtual int argument_delta() const OVERRIDE
virtual int argument_count() const
DECLARE_INSTRUCTION_FACTORY_P5(HCompareNumericAndBranch, HValue *, HValue *, Token::Value, HBasicBlock *, HBasicBlock *)
void set_observed_input_representation(Representation left, Representation right)
HCompareNumericAndBranch(HValue *left, HValue *right, Token::Value token, HBasicBlock *true_target=NULL, HBasicBlock *false_target=NULL)
virtual Representation RequiredInputRepresentation(int index) OVERRIDE
virtual OStream & PrintDataTo(OStream &os) const OVERRIDE
DECLARE_INSTRUCTION_FACTORY_P3(HCompareNumericAndBranch, HValue *, HValue *, Token::Value)
virtual void InferRepresentation(HInferRepresentationPhase *h_infer) OVERRIDE
void SetOperandPositions(Zone *zone, HSourcePosition left_pos, HSourcePosition right_pos)
virtual bool KnownSuccessorBlock(HBasicBlock **block) OVERRIDE
virtual Representation observed_input_representation(int index) OVERRIDE
HCompareObjectEqAndBranch(HValue *left, HValue *right, HBasicBlock *true_target=NULL, HBasicBlock *false_target=NULL)
virtual Representation RequiredInputRepresentation(int index) OVERRIDE
virtual bool KnownSuccessorBlock(HBasicBlock **block) OVERRIDE
void set_known_successor_index(int known_successor_index)
virtual OStream & PrintDataTo(OStream &os) const OVERRIDE
DECLARE_INSTRUCTION_FACTORY_P4(HCompareObjectEqAndBranch, HValue *, HValue *, HBasicBlock *, HBasicBlock *)
DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue *, HValue *)
virtual Representation observed_input_representation(int index) OVERRIDE
virtual OStream & PrintDataTo(OStream &os) const OVERRIDE
virtual int SuccessorCount() const =0
virtual bool KnownSuccessorBlock(HBasicBlock **block)
virtual void SetSuccessorAt(int i, HBasicBlock *block)=0
virtual HBasicBlock * SuccessorAt(int i) const =0
virtual HValue * OperandAt(int index) const FINAL OVERRIDE
virtual void InternalSetOperandAt(int index, HValue *value) FINAL OVERRIDE
virtual int OperandCount() const FINAL OVERRIDE
virtual bool HasEscapingOperandAt(int index) FINAL OVERRIDE
virtual Representation RequiredInputRepresentation(int index) FINAL OVERRIDE
void set_operand_position(Zone *zone, int index, HSourcePosition pos)
void InitializeAsFirst(HBasicBlock *block)
virtual HSourcePosition position() const OVERRIDE
void set_position(HSourcePosition position)
virtual LInstruction * CompileToLithium(LChunkBuilder *builder)=0
HInstruction * previous() const
void InsertAfter(HInstruction *previous)
virtual void DeleteFromGraph() OVERRIDE
HInstruction(HType type=HType::Tagged())
bool Dominates(HInstruction *other)
virtual OStream & PrintTo(OStream &os) const OVERRIDE
virtual HSourcePosition operand_position(int index) const OVERRIDE
virtual OStream & PrintDataTo(OStream &os) const
void InsertBefore(HInstruction *next)
virtual Representation RequiredInputRepresentation(int index) OVERRIDE
DECLARE_INSTRUCTION_FACTORY_P0(HIsConstructCallAndBranch)
virtual bool IsDeletable() const FINAL OVERRIDE
AllocationSiteMode allocation_site_mode() const
static const intptr_t kInstructionPosIndex
static const intptr_t kPositionTag
HSourcePosition operand_position(int idx) const
void set_operand_position(int idx, HSourcePosition pos)
static bool IsTaggedPosition(intptr_t val)
static intptr_t UntagPosition(intptr_t val)
HSourcePosition * operand_positions() const
HSourcePosition * operand_position_slot(int idx) const
static const intptr_t kPositionShift
void ensure_storage_for_operand_positions(Zone *zone, int operand_count)
void set_position(HSourcePosition pos)
static intptr_t TagPosition(intptr_t val)
HSourcePosition position() const
static const intptr_t kFirstOperandPosIndex
BitField< int, 9, 23 > PositionField
static HSourcePosition Unknown()
void set_inlining_id(int inlining_id)
HSourcePosition(const HSourcePosition &other)
BitField< int, 0, 9 > InliningIdField
virtual Representation RequiredInputRepresentation(int index)
DECLARE_INSTRUCTION_FACTORY_P1(HStoreFrameContext, HValue *)
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HStringCompareAndBranch, HValue *, HValue *, Token::Value)
HStringCompareAndBranch(HValue *context, HValue *left, HValue *right, Token::Value token)
virtual OStream & PrintDataTo(OStream &os) const OVERRIDE
virtual Representation RequiredInputRepresentation(int index) OVERRIDE
void SetSuccessorAt(int i, HBasicBlock *block) OVERRIDE
EmbeddedContainer< HBasicBlock *, S > successors_
EmbeddedContainer< HValue *, V > inputs_
void InternalSetOperandAt(int i, HValue *value) OVERRIDE
HBasicBlock * SuccessorAt(int i) const OVERRIDE
virtual int OperandCount() const FINAL OVERRIDE
virtual void InternalSetOperandAt(int i, HValue *value) FINAL OVERRIDE
HTemplateInstruction(HType type=HType::Tagged())
virtual HValue * OperandAt(int i) const FINAL OVERRIDE
EmbeddedContainer< HValue *, V > inputs_
HUnaryCall(HValue *value, int argument_count)
virtual OStream & PrintDataTo(OStream &os) const OVERRIDE
virtual Representation RequiredInputRepresentation(int index) FINAL OVERRIDE
virtual OStream & PrintDataTo(OStream &os) const OVERRIDE
HUnaryControlInstruction(HValue *value, HBasicBlock *true_target, HBasicBlock *false_target)
HUnaryOperation(HValue *value, HType type=HType::Tagged())
static HUnaryOperation * cast(HValue *value)
virtual OStream & PrintDataTo(OStream &os) const OVERRIDE
HUseListNode(HValue *value, int index, HUseListNode *tail)
void set_tail(HUseListNode *list)
static HValue * cast(HValue *value)
virtual void RepresentationChanged(Representation to)
virtual void InternalSetOperandAt(int index, HValue *value)=0
static const int kNoRedefinedOperand
bool Equals(HValue *other)
HValue(HType type=HType::Tagged())
void SetChangesFlag(GVNFlag f)
MinusZeroMode GetMinusZeroMode()
virtual bool TryDecompose(DecompositionResult *decomposition)
virtual Representation KnownOptimalRepresentation()
bool ToStringOrToNumberCanBeObserved() const
virtual void InferRepresentation(HInferRepresentationPhase *h_infer)
GVNFlagSet ObservableChangesFlags() const
GVNFlagSet SideEffectFlags() const
virtual HSourcePosition operand_position(int index) const
friend OStream & operator<<(OStream &os, const ChangesOf &v)
bool CheckDependsOnFlag(GVNFlag f) const
virtual Opcode opcode() const =0
virtual Representation observed_input_representation(int index)
virtual bool DataEquals(HValue *other)
void ReplaceAllUsesWith(HValue *other)
virtual void DeleteFromGraph()=0
bool HasObservableSideEffects() const
virtual int OperandCount() const =0
bool CheckUsesForFlag(Flag f) const
static GVNFlagSet AllObservableSideEffectsFlagSet()
void AddNewRange(Range *r, Zone *zone)
GVNFlagSet DependsOnFlags() const
void set_type(HType new_type)
bool IsDefinedAfter(HBasicBlock *other) const
HBasicBlock * block() const
GVNFlagSet ChangesFlags() const
void ChangeRepresentation(Representation r)
bool EqualsInteger32Constant(int32_t value)
virtual bool HasOutOfBoundsAccess(int size)
DISALLOW_COPY_AND_ASSIGN(HValue)
virtual void FinalizeUniqueness()
bool CheckChangesFlag(GVNFlag f) const
virtual HType CalculateInferredType()
void ClearDependsOnFlag(GVNFlag f)
virtual void AssumeRepresentation(Representation r)
Representation RepresentationFromUseRequirements()
void CopyFlag(Flag f, HValue *other)
virtual bool HasEscapingOperandAt(int index)
virtual Representation RepresentationFromInputs()
const char * Mnemonic() const
void AddDependantsToWorklist(HInferRepresentationPhase *h_infer)
virtual Representation RequiredInputRepresentation(int index)=0
virtual Handle< Map > GetMonomorphicJSObjectMap()
void ClearChangesFlag(GVNFlag f)
virtual intptr_t Hashcode()
void RegisterUse(int index, HValue *new_value)
virtual Range * InferRange(Zone *zone)
virtual bool IsDeletable() const
static GVNFlagSet AllFlagSet()
void set_representation(Representation r)
virtual OStream & PrintTo(OStream &os) const =0
Representation representation() const
void SetOperandAt(int index, HValue *value)
bool HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const
virtual HValue * Canonicalize()
virtual int argument_delta() const
bool CheckFlag(Flag f) const
virtual int RedefinedOperandIndex()
STATIC_ASSERT(kLastFlag< kBitsPerInt)
virtual bool IsPurelyInformativeDefinition()
HUseIterator uses() const
void SetBlock(HBasicBlock *block)
static GVNFlagSet AllSideEffectsFlagSet()
virtual HValue * OperandAt(int index) const =0
void DeleteAndReplaceWith(HValue *other)
virtual Representation RepresentationFromUses()
void SetDependsOnFlag(GVNFlag f)
HUseListNode * RemoveUse(HValue *value, int index)
virtual void UpdateRepresentation(Representation new_rep, HInferRepresentationPhase *h_infer, const char *reason)
virtual HSourcePosition position() const
void ComputeInitialRange(Zone *zone)
virtual bool HandleSideEffectDominator(GVNFlag side_effect, HValue *dominator)
static Handle< T > cast(Handle< S > that)
Definition: handles.h:116
bool is_null() const
Definition: handles.h:124
static const int kValueOffset
Definition: objects.h:1506
static const int kMapOffset
Definition: objects.h:1427
bool InNewSpace(Object *object)
Definition: heap-inl.h:322
static AllocationSpace TargetSpaceId(InstanceType type)
Definition: heap-inl.h:399
Factory * factory()
Definition: isolate.h:982
static const int kWeakNextOffset
Definition: objects.h:9916
static const int kByteOffsetOffset
Definition: objects.h:9914
static const int kByteLengthOffset
Definition: objects.h:9915
static const int kBufferOffset
Definition: objects.h:9913
static const int kByteLengthOffset
Definition: objects.h:9877
static const int kWeakFirstViewOffset
Definition: objects.h:9880
static const int kBackingStoreOffset
Definition: objects.h:9876
static const int kLengthOffset
Definition: objects.h:10072
static const int kNextFunctionLinkOffset
Definition: objects.h:7384
static const int kSharedFunctionInfoOffset
Definition: objects.h:7379
static const int kContextOffset
Definition: objects.h:7381
static const int kLiteralsOffset
Definition: objects.h:7382
static const int kCodeEntryOffset
Definition: objects.h:7376
static const int kPrototypeOrInitialMapOffset
Definition: objects.h:7377
static const int kPropertiesOffset
Definition: objects.h:2193
static const int kElementsOffset
Definition: objects.h:2194
static const int kLengthOffset
Definition: objects.h:9946
static const int kBitFieldOffset
Definition: objects.h:6228
static const int kInstanceTypeOffset
Definition: objects.h:6229
static const int kBitField2Offset
Definition: objects.h:6233
static const int kInstanceSizeOffset
Definition: objects.h:6210
static const int kInObjectPropertiesOffset
Definition: objects.h:6212
static const int kInstanceTypeAndBitFieldOffset
Definition: objects.h:6231
static const int kHashFieldOffset
Definition: objects.h:8486
static const int kNoPosition
Definition: assembler.h:317
static Representation Double()
static Representation UInteger8()
static Representation External()
static Representation Smi()
Representation generalize(Representation other)
static Representation Integer32()
bool Equals(const Representation &other) const
static Representation UInteger16()
static Representation Tagged()
static Representation None()
static Representation FromKind(Kind kind)
static const int kOptimizedCodeMapOffset
Definition: objects.h:6894
static const int kCodeOffset
Definition: objects.h:6893
static const int kMaxValue
Definition: objects.h:1272
static const int kMinValue
Definition: objects.h:1270
static const int32_t kMaxOneByteCharCode
Definition: objects.h:8811
static const int kMaxLength
Definition: objects.h:8820
static const int kLengthOffset
Definition: objects.h:8802
static const int kMaxUtf16CodeUnit
Definition: objects.h:8813
static bool IsCompareOp(Value op)
Definition: token.h:202
static bool IsEqualityOp(Value op)
Definition: token.h:210
static Unique< T > cast(Unique< S > that)
Definition: unique.h:103
static Unique< T > CreateUninitialized(Handle< T > handle)
Definition: unique.h:112
int length() const
Definition: vector.h:41
Isolate * isolate() const
Definition: zone.h:68
T * NewArray(int length)
Definition: zone.h:46
#define OVERRIDE
#define FINAL
#define V(NAME, Name, id)
Definition: execution.h:170
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in only print modified registers Trace simulator debug messages Implied by trace sim abort randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot A filename with extra code to be included in the A file to write the raw snapshot bytes to(mksnapshot only)") DEFINE_STRING(raw_context_file
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions true
enable harmony numeric literals(0o77, 0b11)") DEFINE_BOOL(harmony_object_literals
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in only print modified registers Trace simulator debug messages Implied by trace sim abort 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(profile_deserialization
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction pairs(ARM only)") DEFINE_BOOL(enable_unaligned_accesses
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
#define ADD_FLAG(Type)
#define DECLARE_ABSTRACT_INSTRUCTION(type)
#define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V)
#define DECLARE_CONCRETE_INSTRUCTION(type)
#define COUNT_FLAG(Type)
#define DECLARE_PREDICATE(type)
#define GVN_TRACKED_FLAG_LIST(V)
#define DECLARE_OPCODE(type)
#define DECLARE_FLAG(Type)
#define GVN_UNTRACKED_FLAG_LIST(V)
#define UNREACHABLE()
Definition: logging.h:30
#define DCHECK_NOT_NULL(p)
Definition: logging.h:213
#define DCHECK_NE(v1, v2)
Definition: logging.h:207
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
int int32_t
Definition: unicode.cc:24
bool IsPowerOfTwo32(uint32_t value)
Definition: bits.h:77
static GVNFlag GVNFlagFromInt(int i)
const int kPointerSize
Definition: globals.h:129
bool IsDoubleOrFloatElementsKind(ElementsKind kind)
const int kBitsPerInt
Definition: globals.h:165
@ STRING_ADD_CHECK_BOTH
Definition: code-stubs.h:1218
bool IsArrowFunction(FunctionKind kind)
Definition: globals.h:793
@ DONT_TRACK_ALLOCATION_SITE
Definition: objects.h:8084
bool IsExternalArrayElementsKind(ElementsKind kind)
Definition: elements-kind.h:95
static LifetimePosition Min(LifetimePosition a, LifetimePosition b)
bool IsFastSmiOrObjectElementsKind(ElementsKind kind)
static Object * DeclareGlobals(Isolate *isolate, Handle< GlobalObject > global, Handle< String > name, Handle< Object > value, PropertyAttributes attr, bool is_var, bool is_const, bool is_function)
Definition: runtime.cc:1038
bool IsGeneratorFunction(FunctionKind kind)
Definition: globals.h:799
bool StoringValueNeedsWriteBarrier(HValue *value)
bool IsConciseMethod(FunctionKind kind)
Definition: globals.h:805
bool IsHoleyElementsKind(ElementsKind kind)
EnumSet< GVNFlag, int32_t > GVNFlagSet
const int kElementsKindCount
Definition: elements-kind.h:66
const int kMaxInt
Definition: globals.h:109
@ FIXED_DOUBLE_ARRAY_TYPE
Definition: objects.h:692
@ FIRST_NONSTRING_TYPE
Definition: objects.h:758
@ PROPERTY_CELL_TYPE
Definition: objects.h:665
@ EXTERNAL_INT8_ELEMENTS
Definition: elements-kind.h:33
@ EXTERNAL_FLOAT32_ELEMENTS
Definition: elements-kind.h:39
@ EXTERNAL_FLOAT64_ELEMENTS
Definition: elements-kind.h:40
@ EXTERNAL_UINT32_ELEMENTS
Definition: elements-kind.h:38
bool IsSimpleMapChangeTransition(ElementsKind from_kind, ElementsKind to_kind)
bool IsFastDoubleElementsKind(ElementsKind kind)
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:146
bool CanBeZero(HValue *right)
Definition: hydrogen.cc:10159
@ FAIL_ON_MINUS_ZERO
Definition: globals.h:768
@ TREAT_MINUS_ZERO_AS_ZERO
Definition: globals.h:767
int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind)
OStream & operator<<(OStream &os, const BasicBlockProfiler &p)
static LifetimePosition Max(LifetimePosition a, LifetimePosition b)
const int kMinInt
Definition: globals.h:110
bool IsFastElementsKind(ElementsKind kind)
static bool SmiValuesAre32Bits()
Definition: v8.h:5808
void PrintF(const char *format,...)
Definition: utils.cc:80
PointersToHereCheck PointersToHereCheckForObject(HValue *object, HValue *dominator)
static bool IsInteger32(double value)
const int kIntSize
Definition: globals.h:124
@ OLD_POINTER_SPACE
Definition: globals.h:360
static bool SmiValuesAre31Bits()
Definition: v8.h:5807
static const int kDefaultKeyedHeaderOffsetSentinel
bool ReceiverObjectNeedsWriteBarrier(HValue *object, HValue *value, HValue *dominator)
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
bool IsFixedTypedArrayElementsKind(ElementsKind kind)
bool IsFastSmiElementsKind(ElementsKind kind)
@ NO_CALL_FUNCTION_FLAGS
Definition: globals.h:469
@ kPointersToHereAreAlwaysInteresting
bool IsFastObjectElementsKind(ElementsKind kind)
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
@ None
Definition: v8.h:2211
A simple Maybe type, representing an object which may or may not have a value.
Definition: v8.h:890
ChangesOf(const HValue *const v)
NameOf(const HValue *const v)
TypeOf(const HValue *const v)
#define T(name, string, precedence)
Definition: token.cc:25