v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
hydrogen-instructions.h
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #ifndef V8_HYDROGEN_INSTRUCTIONS_H_
29 #define V8_HYDROGEN_INSTRUCTIONS_H_
30 
31 #include "v8.h"
32 
33 #include "allocation.h"
34 #include "code-stubs.h"
35 #include "data-flow.h"
36 #include "deoptimizer.h"
37 #include "small-pointer-list.h"
38 #include "string-stream.h"
39 #include "unique.h"
40 #include "v8conversions.h"
41 #include "v8utils.h"
42 #include "zone.h"
43 
44 namespace v8 {
45 namespace internal {
46 
47 // Forward declarations.
48 class HBasicBlock;
49 class HDiv;
50 class HEnvironment;
51 class HInferRepresentationPhase;
52 class HInstruction;
53 class HLoopInformation;
54 class HStoreNamedField;
55 class HValue;
56 class LInstruction;
57 class LChunkBuilder;
58 
59 #define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V) \
60  V(ArithmeticBinaryOperation) \
61  V(BinaryOperation) \
62  V(BitwiseBinaryOperation) \
63  V(ControlInstruction) \
64  V(Instruction) \
65 
66 
67 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
68  V(AbnormalExit) \
69  V(AccessArgumentsAt) \
70  V(Add) \
71  V(Allocate) \
72  V(ApplyArguments) \
73  V(ArgumentsElements) \
74  V(ArgumentsLength) \
75  V(ArgumentsObject) \
76  V(Bitwise) \
77  V(BlockEntry) \
78  V(BoundsCheck) \
79  V(BoundsCheckBaseIndexInformation) \
80  V(Branch) \
81  V(CallWithDescriptor) \
82  V(CallJSFunction) \
83  V(CallFunction) \
84  V(CallNew) \
85  V(CallNewArray) \
86  V(CallRuntime) \
87  V(CallStub) \
88  V(CapturedObject) \
89  V(Change) \
90  V(CheckHeapObject) \
91  V(CheckInstanceType) \
92  V(CheckMaps) \
93  V(CheckMapValue) \
94  V(CheckSmi) \
95  V(CheckValue) \
96  V(ClampToUint8) \
97  V(ClassOfTestAndBranch) \
98  V(CompareNumericAndBranch) \
99  V(CompareHoleAndBranch) \
100  V(CompareGeneric) \
101  V(CompareMinusZeroAndBranch) \
102  V(CompareObjectEqAndBranch) \
103  V(CompareMap) \
104  V(Constant) \
105  V(ConstructDouble) \
106  V(Context) \
107  V(DateField) \
108  V(DebugBreak) \
109  V(DeclareGlobals) \
110  V(Deoptimize) \
111  V(Div) \
112  V(DoubleBits) \
113  V(DummyUse) \
114  V(EnterInlined) \
115  V(EnvironmentMarker) \
116  V(ForceRepresentation) \
117  V(ForInCacheArray) \
118  V(ForInPrepareMap) \
119  V(FunctionLiteral) \
120  V(GetCachedArrayIndex) \
121  V(Goto) \
122  V(HasCachedArrayIndexAndBranch) \
123  V(HasInstanceTypeAndBranch) \
124  V(InnerAllocatedObject) \
125  V(InstanceOf) \
126  V(InstanceOfKnownGlobal) \
127  V(InvokeFunction) \
128  V(IsConstructCallAndBranch) \
129  V(IsObjectAndBranch) \
130  V(IsStringAndBranch) \
131  V(IsSmiAndBranch) \
132  V(IsUndetectableAndBranch) \
133  V(LeaveInlined) \
134  V(LoadContextSlot) \
135  V(LoadFieldByIndex) \
136  V(LoadFunctionPrototype) \
137  V(LoadGlobalCell) \
138  V(LoadGlobalGeneric) \
139  V(LoadKeyed) \
140  V(LoadKeyedGeneric) \
141  V(LoadNamedField) \
142  V(LoadNamedGeneric) \
143  V(LoadRoot) \
144  V(MapEnumLength) \
145  V(MathFloorOfDiv) \
146  V(MathMinMax) \
147  V(Mod) \
148  V(Mul) \
149  V(OsrEntry) \
150  V(Parameter) \
151  V(Power) \
152  V(PushArgument) \
153  V(RegExpLiteral) \
154  V(Return) \
155  V(Ror) \
156  V(Sar) \
157  V(SeqStringGetChar) \
158  V(SeqStringSetChar) \
159  V(Shl) \
160  V(Shr) \
161  V(Simulate) \
162  V(StackCheck) \
163  V(StoreCodeEntry) \
164  V(StoreContextSlot) \
165  V(StoreGlobalCell) \
166  V(StoreKeyed) \
167  V(StoreKeyedGeneric) \
168  V(StoreNamedField) \
169  V(StoreNamedGeneric) \
170  V(StringAdd) \
171  V(StringCharCodeAt) \
172  V(StringCharFromCode) \
173  V(StringCompareAndBranch) \
174  V(Sub) \
175  V(ThisFunction) \
176  V(ToFastProperties) \
177  V(TransitionElementsKind) \
178  V(TrapAllocationMemento) \
179  V(Typeof) \
180  V(TypeofIsAndBranch) \
181  V(UnaryMathOperation) \
182  V(UnknownOSRValue) \
183  V(UseConst) \
184  V(WrapReceiver)
185 
186 #define GVN_TRACKED_FLAG_LIST(V) \
187  V(Maps) \
188  V(NewSpacePromotion)
189 
190 #define GVN_UNTRACKED_FLAG_LIST(V) \
191  V(ArrayElements) \
192  V(ArrayLengths) \
193  V(StringLengths) \
194  V(BackingStoreFields) \
195  V(Calls) \
196  V(ContextSlots) \
197  V(DoubleArrayElements) \
198  V(DoubleFields) \
199  V(ElementsKind) \
200  V(ElementsPointer) \
201  V(GlobalVars) \
202  V(InobjectFields) \
203  V(OsrEntries) \
204  V(ExternalMemory) \
205  V(StringChars) \
206  V(TypedArrayElements)
207 
208 
209 #define DECLARE_ABSTRACT_INSTRUCTION(type) \
210  virtual bool Is##type() const V8_FINAL V8_OVERRIDE { return true; } \
211  static H##type* cast(HValue* value) { \
212  ASSERT(value->Is##type()); \
213  return reinterpret_cast<H##type*>(value); \
214  }
215 
216 
217 #define DECLARE_CONCRETE_INSTRUCTION(type) \
218  virtual LInstruction* CompileToLithium( \
219  LChunkBuilder* builder) V8_FINAL V8_OVERRIDE; \
220  static H##type* cast(HValue* value) { \
221  ASSERT(value->Is##type()); \
222  return reinterpret_cast<H##type*>(value); \
223  } \
224  virtual Opcode opcode() const V8_FINAL V8_OVERRIDE { \
225  return HValue::k##type; \
226  }
227 
228 
230 
231 
232 class Range V8_FINAL : public ZoneObject {
233  public:
235  : lower_(kMinInt),
236  upper_(kMaxInt),
237  next_(NULL),
238  can_be_minus_zero_(false) { }
239 
240  Range(int32_t lower, int32_t upper)
241  : lower_(lower),
242  upper_(upper),
243  next_(NULL),
244  can_be_minus_zero_(false) { }
245 
246  int32_t upper() const { return upper_; }
247  int32_t lower() const { return lower_; }
248  Range* next() const { return next_; }
249  Range* CopyClearLower(Zone* zone) const {
250  return new(zone) Range(kMinInt, upper_);
251  }
252  Range* CopyClearUpper(Zone* zone) const {
253  return new(zone) Range(lower_, kMaxInt);
254  }
255  Range* Copy(Zone* zone) const {
256  Range* result = new(zone) Range(lower_, upper_);
257  result->set_can_be_minus_zero(CanBeMinusZero());
258  return result;
259  }
260  int32_t Mask() const;
261  void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
262  bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
263  bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
264  bool CanBeNegative() const { return lower_ < 0; }
265  bool CanBePositive() const { return upper_ > 0; }
266  bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
267  bool IsMostGeneric() const {
268  return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
269  }
270  bool IsInSmiRange() const {
271  return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
272  }
273  void ClampToSmi() {
274  lower_ = Max(lower_, Smi::kMinValue);
275  upper_ = Min(upper_, Smi::kMaxValue);
276  }
277  void KeepOrder();
278 #ifdef DEBUG
279  void Verify() const;
280 #endif
281 
282  void StackUpon(Range* other) {
283  Intersect(other);
284  next_ = other;
285  }
286 
287  void Intersect(Range* other);
288  void Union(Range* other);
289  void CombinedMax(Range* other);
290  void CombinedMin(Range* other);
291 
292  void AddConstant(int32_t value);
293  void Sar(int32_t value);
294  void Shl(int32_t value);
295  bool AddAndCheckOverflow(const Representation& r, Range* other);
296  bool SubAndCheckOverflow(const Representation& r, Range* other);
297  bool MulAndCheckOverflow(const Representation& r, Range* other);
298 
299  private:
300  int32_t lower_;
301  int32_t upper_;
302  Range* next_;
303  bool can_be_minus_zero_;
304 };
305 
306 
307 class HType V8_FINAL {
308  public:
309  static HType None() { return HType(kNone); }
310  static HType Tagged() { return HType(kTagged); }
311  static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
312  static HType TaggedNumber() { return HType(kTaggedNumber); }
313  static HType Smi() { return HType(kSmi); }
314  static HType HeapNumber() { return HType(kHeapNumber); }
315  static HType String() { return HType(kString); }
316  static HType Boolean() { return HType(kBoolean); }
317  static HType NonPrimitive() { return HType(kNonPrimitive); }
318  static HType JSArray() { return HType(kJSArray); }
319  static HType JSObject() { return HType(kJSObject); }
320 
321  // Return the weakest (least precise) common type.
322  HType Combine(HType other) {
323  return HType(static_cast<Type>(type_ & other.type_));
324  }
325 
326  bool Equals(const HType& other) const {
327  return type_ == other.type_;
328  }
329 
330  bool IsSubtypeOf(const HType& other) {
331  return Combine(other).Equals(other);
332  }
333 
334  bool IsTaggedPrimitive() const {
335  return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
336  }
337 
338  bool IsTaggedNumber() const {
339  return ((type_ & kTaggedNumber) == kTaggedNumber);
340  }
341 
342  bool IsSmi() const {
343  return ((type_ & kSmi) == kSmi);
344  }
345 
346  bool IsHeapNumber() const {
347  return ((type_ & kHeapNumber) == kHeapNumber);
348  }
349 
350  bool IsString() const {
351  return ((type_ & kString) == kString);
352  }
353 
354  bool IsNonString() const {
355  return IsTaggedPrimitive() || IsSmi() || IsHeapNumber() ||
356  IsBoolean() || IsJSArray();
357  }
358 
359  bool IsBoolean() const {
360  return ((type_ & kBoolean) == kBoolean);
361  }
362 
363  bool IsNonPrimitive() const {
364  return ((type_ & kNonPrimitive) == kNonPrimitive);
365  }
366 
367  bool IsJSArray() const {
368  return ((type_ & kJSArray) == kJSArray);
369  }
370 
371  bool IsJSObject() const {
372  return ((type_ & kJSObject) == kJSObject);
373  }
374 
375  bool IsHeapObject() const {
376  return IsHeapNumber() || IsString() || IsBoolean() || IsNonPrimitive();
377  }
378 
380  switch (type_) {
381  case kTaggedPrimitive: // fallthru
382  case kTaggedNumber: // fallthru
383  case kSmi: // fallthru
384  case kHeapNumber: // fallthru
385  case kString: // fallthru
386  case kBoolean:
387  return false;
388  case kJSArray: // fallthru
389  case kJSObject:
390  return true;
391  case kTagged:
392  break;
393  }
394  return !representation.IsSmiOrInteger32() && !representation.IsDouble();
395  }
396 
397  static HType TypeFromValue(Handle<Object> value);
398 
399  const char* ToString();
400 
401  private:
402  enum Type {
403  kNone = 0x0, // 0000 0000 0000 0000
404  kTagged = 0x1, // 0000 0000 0000 0001
405  kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
406  kTaggedNumber = 0xd, // 0000 0000 0000 1101
407  kSmi = 0x1d, // 0000 0000 0001 1101
408  kHeapNumber = 0x2d, // 0000 0000 0010 1101
409  kString = 0x45, // 0000 0000 0100 0101
410  kBoolean = 0x85, // 0000 0000 1000 0101
411  kNonPrimitive = 0x101, // 0000 0001 0000 0001
412  kJSObject = 0x301, // 0000 0011 0000 0001
413  kJSArray = 0x701 // 0000 0111 0000 0001
414  };
415 
416  // Make sure type fits in int16.
417  STATIC_ASSERT(kJSArray < (1 << (2 * kBitsPerByte)));
418 
419  explicit HType(Type t) : type_(t) { }
420 
421  int16_t type_;
422 };
423 
424 
425 class HUseListNode: public ZoneObject {
426  public:
428  : tail_(tail), value_(value), index_(index) {
429  }
430 
431  HUseListNode* tail();
432  HValue* value() const { return value_; }
433  int index() const { return index_; }
434 
435  void set_tail(HUseListNode* list) { tail_ = list; }
436 
437 #ifdef DEBUG
438  void Zap() {
439  tail_ = reinterpret_cast<HUseListNode*>(1);
440  value_ = NULL;
441  index_ = -1;
442  }
443 #endif
444 
445  private:
446  HUseListNode* tail_;
447  HValue* value_;
448  int index_;
449 };
450 
451 
452 // We reuse use list nodes behind the scenes as uses are added and deleted.
453 // This class is the safe way to iterate uses while deleting them.
454 class HUseIterator V8_FINAL BASE_EMBEDDED {
455  public:
456  bool Done() { return current_ == NULL; }
457  void Advance();
458 
460  ASSERT(!Done());
461  return value_;
462  }
463 
464  int index() {
465  ASSERT(!Done());
466  return index_;
467  }
468 
469  private:
470  explicit HUseIterator(HUseListNode* head);
471 
473  HUseListNode* next_;
474  HValue* value_;
475  int index_;
476 
477  friend class HValue;
478 };
479 
480 
481 // All tracked flags should appear before untracked ones.
482 enum GVNFlag {
483  // Declare global value numbering flags.
484 #define DECLARE_FLAG(Type) k##Type,
487 #undef DECLARE_FLAG
488 #define COUNT_FLAG(Type) + 1
491 #undef COUNT_FLAG
493 };
494 
495 
496 static inline GVNFlag GVNFlagFromInt(int i) {
497  ASSERT(i >= 0);
498  ASSERT(i < kNumberOfFlags);
499  return static_cast<GVNFlag>(i);
500 }
501 
502 
503 class DecompositionResult V8_FINAL BASE_EMBEDDED {
504  public:
505  DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
506 
507  HValue* base() { return base_; }
508  int offset() { return offset_; }
509  int scale() { return scale_; }
510 
511  bool Apply(HValue* other_base, int other_offset, int other_scale = 0) {
512  if (base_ == NULL) {
513  base_ = other_base;
514  offset_ = other_offset;
515  scale_ = other_scale;
516  return true;
517  } else {
518  if (scale_ == 0) {
519  base_ = other_base;
520  offset_ += other_offset;
521  scale_ = other_scale;
522  return true;
523  } else {
524  return false;
525  }
526  }
527  }
528 
529  void SwapValues(HValue** other_base, int* other_offset, int* other_scale) {
530  swap(&base_, other_base);
531  swap(&offset_, other_offset);
532  swap(&scale_, other_scale);
533  }
534 
535  private:
536  template <class T> void swap(T* a, T* b) {
537  T c(*a);
538  *a = *b;
539  *b = c;
540  }
541 
542  HValue* base_;
543  int offset_;
544  int scale_;
545 };
546 
547 
549 
550 
551 // This class encapsulates encoding and decoding of sources positions from
552 // which hydrogen values originated.
553 // When FLAG_track_hydrogen_positions is set this object encodes the
554 // identifier of the inlining and absolute offset from the start of the
555 // inlined function.
556 // When the flag is not set we simply track absolute offset from the
557 // script start.
559  public:
560  HSourcePosition(const HSourcePosition& other) : value_(other.value_) { }
561 
563  return HSourcePosition(RelocInfo::kNoPosition);
564  }
565 
566  bool IsUnknown() const { return value_ == RelocInfo::kNoPosition; }
567 
568  int position() const { return PositionField::decode(value_); }
569  void set_position(int position) {
570  if (FLAG_hydrogen_track_positions) {
571  value_ = static_cast<int>(PositionField::update(value_, position));
572  } else {
573  value_ = position;
574  }
575  }
576 
577  int inlining_id() const { return InliningIdField::decode(value_); }
579  if (FLAG_hydrogen_track_positions) {
580  value_ = static_cast<int>(InliningIdField::update(value_, inlining_id));
581  }
582  }
583 
584  int raw() const { return value_; }
585 
586  void PrintTo(FILE* f);
587 
588  private:
589  typedef BitField<int, 0, 9> InliningIdField;
590 
591  // Offset from the start of the inlined function.
592  typedef BitField<int, 9, 22> PositionField;
593 
594  // On HPositionInfo can use this constructor.
595  explicit HSourcePosition(int value) : value_(value) { }
596 
597  friend class HPositionInfo;
598 
599  // If FLAG_hydrogen_track_positions is set contains bitfields InliningIdField
600  // and PositionField.
601  // Otherwise contains absolute offset from the script start.
602  int value_;
603 };
604 
605 
606 class HValue : public ZoneObject {
607  public:
608  static const int kNoNumber = -1;
609 
610  enum Flag {
613  // Participate in Global Value Numbering, i.e. elimination of
614  // unnecessary recomputations. If an instruction sets this flag, it must
615  // implement DataEquals(), which will be used to determine if other
616  // occurrences of the instruction are indeed the same.
618  // Track instructions that are dominating side effects. If an instruction
619  // sets this flag, it must implement HandleSideEffectDominator() and should
620  // indicate which side effects to track by setting GVN flags.
634  // Set after an instruction is killed.
636  // Instructions that are allowed to produce full range unsigned integer
637  // values are marked with kUint32 flag. If arithmetic shift or a load from
638  // EXTERNAL_UINT32_ELEMENTS array is not marked with this flag
639  // it will deoptimize if result does not fit into signed integer range.
640  // HGraph::ComputeSafeUint32Operations is responsible for setting this
641  // flag.
644  // Indicates the instruction is live during dead code elimination.
646 
647  // HEnvironmentMarkers are deleted before dead code
648  // elimination takes place, so they can repurpose the kIsLive flag:
650 
651  // TODO(everyone): Don't forget to update this!
653  };
654 
656 
657  static HValue* cast(HValue* value) { return value; }
658 
659  enum Opcode {
660  // Declare a unique enum value for each hydrogen instruction.
661  #define DECLARE_OPCODE(type) k##type,
664  #undef DECLARE_OPCODE
665  };
666  virtual Opcode opcode() const = 0;
667 
668  // Declare a non-virtual predicates for each concrete HInstruction or HValue.
669  #define DECLARE_PREDICATE(type) \
670  bool Is##type() const { return opcode() == k##type; }
672  #undef DECLARE_PREDICATE
673  bool IsPhi() const { return opcode() == kPhi; }
674 
675  // Declare virtual predicates for abstract HInstruction or HValue
676  #define DECLARE_PREDICATE(type) \
677  virtual bool Is##type() const { return false; }
679  #undef DECLARE_PREDICATE
680 
681  HValue(HType type = HType::Tagged())
682  : block_(NULL),
683  id_(kNoNumber),
684  type_(type),
685  use_list_(NULL),
686  range_(NULL),
687  flags_(0) {}
688  virtual ~HValue() {}
689 
690  virtual HSourcePosition position() const {
691  return HSourcePosition::Unknown();
692  }
693  virtual HSourcePosition operand_position(int index) const {
694  return position();
695  }
696 
697  HBasicBlock* block() const { return block_; }
698  void SetBlock(HBasicBlock* block);
699 
700  // Note: Never call this method for an unlinked value.
701  Isolate* isolate() const;
702 
703  int id() const { return id_; }
704  void set_id(int id) { id_ = id; }
705 
706  HUseIterator uses() const { return HUseIterator(use_list_); }
707 
708  virtual bool EmitAtUses() { return false; }
709 
715  representation_ = r;
716  if (r.IsTagged()) {
717  // Tagged is the bottom of the lattice, don't go any further.
719  }
720  }
721  virtual void AssumeRepresentation(Representation r);
722 
725  if (r.IsTagged()) {
726  HType t = type();
727  if (t.IsSmi()) return Representation::Smi();
728  if (t.IsHeapNumber()) return Representation::Double();
729  if (t.IsHeapObject()) return r;
730  return Representation::None();
731  }
732  return r;
733  }
734 
735  HType type() const { return type_; }
736  void set_type(HType new_type) {
737  ASSERT(new_type.IsSubtypeOf(type_));
738  type_ = new_type;
739  }
740 
741  bool IsHeapObject() {
742  return representation_.IsHeapObject() || type_.IsHeapObject();
743  }
744 
745  // There are HInstructions that do not really change a value, they
746  // only add pieces of information to it (like bounds checks, map checks,
747  // smi checks...).
748  // We call these instructions "informative definitions", or "iDef".
749  // One of the iDef operands is special because it is the value that is
750  // "transferred" to the output, we call it the "redefined operand".
751  // If an HValue is an iDef it must override RedefinedOperandIndex() so that
752  // it does not return kNoRedefinedOperand;
753  static const int kNoRedefinedOperand = -1;
754  virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
757  }
759  int index = RedefinedOperandIndex();
760  return index == kNoRedefinedOperand ? NULL : OperandAt(index);
761  }
762 
764 
765  virtual int argument_delta() const { return 0; }
766 
767  // A purely informative definition is an idef that will not emit code and
768  // should therefore be removed from the graph in the RestoreActualValues
769  // phase (so that live ranges will be shorter).
770  virtual bool IsPurelyInformativeDefinition() { return false; }
771 
772  // This method must always return the original HValue SSA definition,
773  // regardless of any chain of iDefs of this value.
775  HValue* value = this;
776  int index;
777  while ((index = value->RedefinedOperandIndex()) != kNoRedefinedOperand) {
778  value = value->OperandAt(index);
779  }
780  return value;
781  }
782 
783  bool IsInteger32Constant();
785  bool EqualsInteger32Constant(int32_t value);
786 
787  bool IsDefinedAfter(HBasicBlock* other) const;
788 
789  // Operands.
790  virtual int OperandCount() = 0;
791  virtual HValue* OperandAt(int index) const = 0;
792  void SetOperandAt(int index, HValue* value);
793 
794  void DeleteAndReplaceWith(HValue* other);
795  void ReplaceAllUsesWith(HValue* other);
796  bool HasNoUses() const { return use_list_ == NULL; }
797  bool HasMultipleUses() const {
798  return use_list_ != NULL && use_list_->tail() != NULL;
799  }
800  int UseCount() const;
801 
802  // Mark this HValue as dead and to be removed from other HValues' use lists.
803  void Kill();
804 
805  int flags() const { return flags_; }
806  void SetFlag(Flag f) { flags_ |= (1 << f); }
807  void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
808  bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
809  void CopyFlag(Flag f, HValue* other) {
810  if (other->CheckFlag(f)) SetFlag(f);
811  }
812 
813  // Returns true if the flag specified is set for all uses, false otherwise.
814  bool CheckUsesForFlag(Flag f) const;
815  // Same as before and the first one without the flag is returned in value.
816  bool CheckUsesForFlag(Flag f, HValue** value) const;
817  // Returns true if the flag specified is set for all uses, and this set
818  // of uses is non-empty.
820 
827  bool CheckChangesFlag(GVNFlag f) const {
828  return changes_flags_.Contains(f);
829  }
830  bool CheckDependsOnFlag(GVNFlag f) const {
831  return depends_on_flags_.Contains(f);
832  }
836  }
837  bool HasSideEffects() const {
839  }
843  }
844 
846  GVNFlagSet result = ChangesFlags();
848  return result;
849  }
850 
852  GVNFlagSet result = ChangesFlags();
854  return result;
855  }
856 
857  Range* range() const { return range_; }
858  // TODO(svenpanne) We should really use the null object pattern here.
859  bool HasRange() const { return range_ != NULL; }
860  void AddNewRange(Range* r, Zone* zone);
861  void RemoveLastAddedRange();
862  void ComputeInitialRange(Zone* zone);
863 
864  // Escape analysis helpers.
865  virtual bool HasEscapingOperandAt(int index) { return true; }
866  virtual bool HasOutOfBoundsAccess(int size) { return false; }
867 
868  // Representation helpers.
870  return Representation::None();
871  }
872  virtual Representation RequiredInputRepresentation(int index) = 0;
873  virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
874 
875  // This gives the instruction an opportunity to replace itself with an
876  // instruction that does the same in some better way. To replace an
877  // instruction with a new one, first add the new instruction to the graph,
878  // then return it. Return NULL to have the instruction deleted.
879  virtual HValue* Canonicalize() { return this; }
880 
881  bool Equals(HValue* other);
882  virtual intptr_t Hashcode();
883 
884  // Compute unique ids upfront that is safe wrt GC and concurrent compilation.
885  virtual void FinalizeUniqueness() { }
886 
887  // Printing support.
888  virtual void PrintTo(StringStream* stream) = 0;
889  void PrintNameTo(StringStream* stream);
890  void PrintTypeTo(StringStream* stream);
891  void PrintRangeTo(StringStream* stream);
892  void PrintChangesTo(StringStream* stream);
893 
894  const char* Mnemonic() const;
895 
896  // Type information helpers.
898 
899  // TODO(mstarzinger): For now instructions can override this function to
900  // specify statically known types, once HType can convey more information
901  // it should be based on the HType.
903 
904  // Updated the inferred type of this instruction and returns true if
905  // it has changed.
906  bool UpdateInferredType();
907 
908  virtual HType CalculateInferredType();
909 
910  // This function must be overridden for instructions which have the
911  // kTrackSideEffectDominators flag set, to track instructions that are
912  // dominating side effects.
913  // It returns true if it removed an instruction which had side effects.
914  virtual bool HandleSideEffectDominator(GVNFlag side_effect,
915  HValue* dominator) {
916  UNREACHABLE();
917  return false;
918  }
919 
920  // Check if this instruction has some reason that prevents elimination.
921  bool CannotBeEliminated() const {
922  return HasObservableSideEffects() || !IsDeletable();
923  }
924 
925 #ifdef DEBUG
926  virtual void Verify() = 0;
927 #endif
928 
929  virtual bool TryDecompose(DecompositionResult* decomposition) {
930  if (RedefinedOperand() != NULL) {
931  return RedefinedOperand()->TryDecompose(decomposition);
932  } else {
933  return false;
934  }
935  }
936 
937  // Returns true conservatively if the program might be able to observe a
938  // ToString() operation on this value.
939  bool ToStringCanBeObserved() const {
940  return type().ToStringOrToNumberCanBeObserved(representation());
941  }
942 
943  // Returns true conservatively if the program might be able to observe a
944  // ToNumber() operation on this value.
945  bool ToNumberCanBeObserved() const {
946  return type().ToStringOrToNumberCanBeObserved(representation());
947  }
948 
952  }
953 
954  protected:
955  // This function must be overridden for instructions with flag kUseGVN, to
956  // compare the non-Operand parts of the instruction.
957  virtual bool DataEquals(HValue* other) {
958  UNREACHABLE();
959  return false;
960  }
961 
963  return representation();
964  }
967  bool HasNonSmiUse();
968  virtual void UpdateRepresentation(Representation new_rep,
969  HInferRepresentationPhase* h_infer,
970  const char* reason);
972 
974 
975  virtual Range* InferRange(Zone* zone);
976  virtual void DeleteFromGraph() = 0;
977  virtual void InternalSetOperandAt(int index, HValue* value) = 0;
978  void clear_block() {
979  ASSERT(block_ != NULL);
980  block_ = NULL;
981  }
982 
984  ASSERT(representation_.IsNone() && !r.IsNone());
985  representation_ = r;
986  }
987 
989  GVNFlagSet result;
990 #define ADD_FLAG(Type) result.Add(k##Type);
993 #undef ADD_FLAG
994  return result;
995  }
996 
997  // A flag mask to mark an instruction as having arbitrary side effects.
999  GVNFlagSet result = AllFlagSet();
1000  result.Remove(kOsrEntries);
1001  return result;
1002  }
1003 
1004  // A flag mask of all side effects that can make observable changes in
1005  // an executing program (i.e. are not safe to repeat, move or remove);
1007  GVNFlagSet result = AllFlagSet();
1008  result.Remove(kNewSpacePromotion);
1009  result.Remove(kElementsKind);
1010  result.Remove(kElementsPointer);
1011  result.Remove(kMaps);
1012  return result;
1013  }
1014 
1015  // Remove the matching use from the use list if present. Returns the
1016  // removed list node or NULL.
1017  HUseListNode* RemoveUse(HValue* value, int index);
1018 
1019  void RegisterUse(int index, HValue* new_value);
1020 
1021  HBasicBlock* block_;
1022 
1023  // The id of this instruction in the hydrogen graph, assigned when first
1024  // added to the graph. Reflects creation order.
1025  int id_;
1026 
1028  HType type_;
1030  Range* range_;
1031  int flags_;
1034 
1035  private:
1036  virtual bool IsDeletable() const { return false; }
1037 
1038  DISALLOW_COPY_AND_ASSIGN(HValue);
1039 };
1040 
1041 
1042 #define DECLARE_INSTRUCTION_FACTORY_P0(I) \
1043  static I* New(Zone* zone, HValue* context) { \
1044  return new(zone) I(); \
1045 }
1046 
1047 #define DECLARE_INSTRUCTION_FACTORY_P1(I, P1) \
1048  static I* New(Zone* zone, HValue* context, P1 p1) { \
1049  return new(zone) I(p1); \
1050  }
1051 
1052 #define DECLARE_INSTRUCTION_FACTORY_P2(I, P1, P2) \
1053  static I* New(Zone* zone, HValue* context, P1 p1, P2 p2) { \
1054  return new(zone) I(p1, p2); \
1055  }
1056 
1057 #define DECLARE_INSTRUCTION_FACTORY_P3(I, P1, P2, P3) \
1058  static I* New(Zone* zone, HValue* context, P1 p1, P2 p2, P3 p3) { \
1059  return new(zone) I(p1, p2, p3); \
1060  }
1061 
1062 #define DECLARE_INSTRUCTION_FACTORY_P4(I, P1, P2, P3, P4) \
1063  static I* New(Zone* zone, \
1064  HValue* context, \
1065  P1 p1, \
1066  P2 p2, \
1067  P3 p3, \
1068  P4 p4) { \
1069  return new(zone) I(p1, p2, p3, p4); \
1070  }
1071 
1072 #define DECLARE_INSTRUCTION_FACTORY_P5(I, P1, P2, P3, P4, P5) \
1073  static I* New(Zone* zone, \
1074  HValue* context, \
1075  P1 p1, \
1076  P2 p2, \
1077  P3 p3, \
1078  P4 p4, \
1079  P5 p5) { \
1080  return new(zone) I(p1, p2, p3, p4, p5); \
1081  }
1082 
1083 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(I) \
1084  static I* New(Zone* zone, HValue* context) { \
1085  return new(zone) I(context); \
1086  }
1087 
1088 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(I, P1) \
1089  static I* New(Zone* zone, HValue* context, P1 p1) { \
1090  return new(zone) I(context, p1); \
1091  }
1092 
1093 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(I, P1, P2) \
1094  static I* New(Zone* zone, HValue* context, P1 p1, P2 p2) { \
1095  return new(zone) I(context, p1, p2); \
1096  }
1097 
1098 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(I, P1, P2, P3) \
1099  static I* New(Zone* zone, HValue* context, P1 p1, P2 p2, P3 p3) { \
1100  return new(zone) I(context, p1, p2, p3); \
1101  }
1102 
1103 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(I, P1, P2, P3, P4) \
1104  static I* New(Zone* zone, \
1105  HValue* context, \
1106  P1 p1, \
1107  P2 p2, \
1108  P3 p3, \
1109  P4 p4) { \
1110  return new(zone) I(context, p1, p2, p3, p4); \
1111  }
1112 
1113 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(I, P1, P2, P3, P4, P5) \
1114  static I* New(Zone* zone, \
1115  HValue* context, \
1116  P1 p1, \
1117  P2 p2, \
1118  P3 p3, \
1119  P4 p4, \
1120  P5 p5) { \
1121  return new(zone) I(context, p1, p2, p3, p4, p5); \
1122  }
1123 
1124 
1125 // A helper class to represent per-operand position information attached to
1126 // the HInstruction in the compact form. Uses tagging to distinguish between
1127 // case when only instruction's position is available and case when operands'
1128 // positions are also available.
1129 // In the first case it contains intruction's position as a tagged value.
1130 // In the second case it points to an array which contains instruction's
1131 // position and operands' positions.
1133  public:
1134  explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { }
1135 
1137  if (has_operand_positions()) {
1138  return operand_positions()[kInstructionPosIndex];
1139  }
1140  return HSourcePosition(static_cast<int>(UntagPosition(data_)));
1141  }
1142 
1144  if (has_operand_positions()) {
1145  operand_positions()[kInstructionPosIndex] = pos;
1146  } else {
1147  data_ = TagPosition(pos.raw());
1148  }
1149  }
1150 
1151  void ensure_storage_for_operand_positions(Zone* zone, int operand_count) {
1152  if (has_operand_positions()) {
1153  return;
1154  }
1155 
1156  const int length = kFirstOperandPosIndex + operand_count;
1157  HSourcePosition* positions =
1158  zone->NewArray<HSourcePosition>(length);
1159  for (int i = 0; i < length; i++) {
1160  positions[i] = HSourcePosition::Unknown();
1161  }
1162 
1163  const HSourcePosition pos = position();
1164  data_ = reinterpret_cast<intptr_t>(positions);
1165  set_position(pos);
1166 
1167  ASSERT(has_operand_positions());
1168  }
1169 
1171  if (!has_operand_positions()) {
1172  return position();
1173  }
1174  return *operand_position_slot(idx);
1175  }
1176 
1178  *operand_position_slot(idx) = pos;
1179  }
1180 
1181  private:
1182  static const intptr_t kInstructionPosIndex = 0;
1183  static const intptr_t kFirstOperandPosIndex = 1;
1184 
1185  HSourcePosition* operand_position_slot(int idx) const {
1186  ASSERT(has_operand_positions());
1187  return &(operand_positions()[kFirstOperandPosIndex + idx]);
1188  }
1189 
1190  bool has_operand_positions() const {
1191  return !IsTaggedPosition(data_);
1192  }
1193 
1194  HSourcePosition* operand_positions() const {
1195  ASSERT(has_operand_positions());
1196  return reinterpret_cast<HSourcePosition*>(data_);
1197  }
1198 
1199  static const intptr_t kPositionTag = 1;
1200  static const intptr_t kPositionShift = 1;
1201  static bool IsTaggedPosition(intptr_t val) {
1202  return (val & kPositionTag) != 0;
1203  }
1204  static intptr_t UntagPosition(intptr_t val) {
1205  ASSERT(IsTaggedPosition(val));
1206  return val >> kPositionShift;
1207  }
1208  static intptr_t TagPosition(intptr_t val) {
1209  const intptr_t result = (val << kPositionShift) | kPositionTag;
1210  ASSERT(UntagPosition(result) == val);
1211  return result;
1212  }
1213 
1214  intptr_t data_;
1215 };
1216 
1217 
1218 class HInstruction : public HValue {
1219  public:
1220  HInstruction* next() const { return next_; }
1221  HInstruction* previous() const { return previous_; }
1222 
1223  virtual void PrintTo(StringStream* stream) V8_OVERRIDE;
1224  virtual void PrintDataTo(StringStream* stream);
1225 
1226  bool IsLinked() const { return block() != NULL; }
1227  void Unlink();
1228 
1230 
1231  template<class T> T* Prepend(T* instr) {
1232  instr->InsertBefore(this);
1233  return instr;
1234  }
1235 
1237 
1238  template<class T> T* Append(T* instr) {
1239  instr->InsertAfter(this);
1240  return instr;
1241  }
1242 
1243  // The position is a write-once variable.
1245  return HSourcePosition(position_.position());
1246  }
1247  bool has_position() const {
1248  return !position().IsUnknown();
1249  }
1251  ASSERT(!has_position());
1252  ASSERT(!position.IsUnknown());
1253  position_.set_position(position);
1254  }
1255 
1256  virtual HSourcePosition operand_position(int index) const V8_OVERRIDE {
1257  const HSourcePosition pos = position_.operand_position(index);
1258  return pos.IsUnknown() ? position() : pos;
1259  }
1260  void set_operand_position(Zone* zone, int index, HSourcePosition pos) {
1261  ASSERT(0 <= index && index < OperandCount());
1263  position_.set_operand_position(index, pos);
1264  }
1265 
1267 
1268  virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
1269 
1270 #ifdef DEBUG
1271  virtual void Verify() V8_OVERRIDE;
1272 #endif
1273 
1274  bool CanDeoptimize();
1275 
1276  virtual bool HasStackCheck() { return false; }
1277 
1279 
1280  protected:
1281  HInstruction(HType type = HType::Tagged())
1282  : HValue(type),
1283  next_(NULL),
1284  previous_(NULL),
1285  position_(RelocInfo::kNoPosition) {
1286  SetDependsOnFlag(kOsrEntries);
1287  }
1288 
1289  virtual void DeleteFromGraph() V8_OVERRIDE { Unlink(); }
1290 
1291  private:
1292  void InitializeAsFirst(HBasicBlock* block) {
1293  ASSERT(!IsLinked());
1294  SetBlock(block);
1295  }
1296 
1297  void PrintMnemonicTo(StringStream* stream);
1298 
1299  HInstruction* next_;
1300  HInstruction* previous_;
1301  HPositionInfo position_;
1302 
1303  friend class HBasicBlock;
1304 };
1305 
1306 
1307 template<int V>
1309  public:
1310  virtual int OperandCount() V8_FINAL V8_OVERRIDE { return V; }
1311  virtual HValue* OperandAt(int i) const V8_FINAL V8_OVERRIDE {
1312  return inputs_[i];
1313  }
1314 
1315  protected:
1316  HTemplateInstruction(HType type = HType::Tagged()) : HInstruction(type) {}
1317 
1318  virtual void InternalSetOperandAt(int i, HValue* value) V8_FINAL V8_OVERRIDE {
1319  inputs_[i] = value;
1320  }
1321 
1322  private:
1324 };
1325 
1326 
1328  public:
1329  virtual HBasicBlock* SuccessorAt(int i) = 0;
1330  virtual int SuccessorCount() = 0;
1331  virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
1332 
1333  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1334 
1335  virtual bool KnownSuccessorBlock(HBasicBlock** block) {
1336  *block = NULL;
1337  return false;
1338  }
1339 
1341  return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
1342  }
1344  return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
1345  }
1346 
1347  void Not() {
1348  HBasicBlock* swap = SuccessorAt(0);
1349  SetSuccessorAt(0, SuccessorAt(1));
1350  SetSuccessorAt(1, swap);
1351  }
1352 
1353  DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
1354 };
1355 
1356 
1357 class HSuccessorIterator V8_FINAL BASE_EMBEDDED {
1358  public:
1360  : instr_(instr), current_(0) { }
1361 
1362  bool Done() { return current_ >= instr_->SuccessorCount(); }
1363  HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
1364  void Advance() { current_++; }
1365 
1366  private:
1367  HControlInstruction* instr_;
1368  int current_;
1369 };
1370 
1371 
1372 template<int S, int V>
1374  public:
1375  int SuccessorCount() V8_OVERRIDE { return S; }
1376  HBasicBlock* SuccessorAt(int i) V8_OVERRIDE { return successors_[i]; }
1378  successors_[i] = block;
1379  }
1380 
1381  int OperandCount() V8_OVERRIDE { return V; }
1382  HValue* OperandAt(int i) const V8_OVERRIDE { return inputs_[i]; }
1383 
1384 
1385  protected:
1387  inputs_[i] = value;
1388  }
1389 
1390  private:
1393 };
1394 
1395 
1396 class HBlockEntry V8_FINAL : public HTemplateInstruction<0> {
1397  public:
1399  return Representation::None();
1400  }
1401 
1402  DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
1403 };
1404 
1405 
1406 class HDummyUse V8_FINAL : public HTemplateInstruction<1> {
1407  public:
1408  explicit HDummyUse(HValue* value)
1409  : HTemplateInstruction<1>(HType::Smi()) {
1410  SetOperandAt(0, value);
1411  // Pretend to be a Smi so that the HChange instructions inserted
1412  // before any use generate as little code as possible.
1413  set_representation(Representation::Tagged());
1414  }
1415 
1416  HValue* value() { return OperandAt(0); }
1417 
1418  virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
1420  return Representation::None();
1421  }
1422 
1423  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1424 
1425  DECLARE_CONCRETE_INSTRUCTION(DummyUse);
1426 };
1427 
1428 
1429 // Inserts an int3/stop break instruction for debugging purposes.
1430 class HDebugBreak V8_FINAL : public HTemplateInstruction<0> {
1431  public:
1432  DECLARE_INSTRUCTION_FACTORY_P0(HDebugBreak);
1433 
1435  return Representation::None();
1436  }
1437 
1438  DECLARE_CONCRETE_INSTRUCTION(DebugBreak)
1439 };
1440 
1441 
1442 class HGoto V8_FINAL : public HTemplateControlInstruction<1, 0> {
1443  public:
1444  explicit HGoto(HBasicBlock* target) {
1445  SetSuccessorAt(0, target);
1446  }
1447 
1448  virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE {
1449  *block = FirstSuccessor();
1450  return true;
1451  }
1452 
1454  return Representation::None();
1455  }
1456 
1457  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1458 
1460 };
1461 
1462 
1463 class HDeoptimize V8_FINAL : public HTemplateControlInstruction<1, 0> {
1464  public:
1465  static HDeoptimize* New(Zone* zone,
1466  HValue* context,
1467  const char* reason,
1469  HBasicBlock* unreachable_continuation) {
1470  return new(zone) HDeoptimize(reason, type, unreachable_continuation);
1471  }
1472 
1473  virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE {
1474  *block = NULL;
1475  return true;
1476  }
1477 
1479  return Representation::None();
1480  }
1481 
1482  const char* reason() const { return reason_; }
1483  Deoptimizer::BailoutType type() { return type_; }
1484 
1485  DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
1486 
1487  private:
1488  explicit HDeoptimize(const char* reason,
1489  Deoptimizer::BailoutType type,
1490  HBasicBlock* unreachable_continuation)
1491  : reason_(reason), type_(type) {
1492  SetSuccessorAt(0, unreachable_continuation);
1493  }
1494 
1495  const char* reason_;
1497 };
1498 
1499 
1501  public:
1503  HBasicBlock* true_target,
1504  HBasicBlock* false_target) {
1505  SetOperandAt(0, value);
1506  SetSuccessorAt(0, true_target);
1507  SetSuccessorAt(1, false_target);
1508  }
1509 
1510  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1511 
1512  HValue* value() { return OperandAt(0); }
1513 };
1514 
1515 
1516 class HBranch V8_FINAL : public HUnaryControlInstruction {
1517  public:
1518  DECLARE_INSTRUCTION_FACTORY_P1(HBranch, HValue*);
1519  DECLARE_INSTRUCTION_FACTORY_P2(HBranch, HValue*,
1520  ToBooleanStub::Types);
1521  DECLARE_INSTRUCTION_FACTORY_P4(HBranch, HValue*,
1522  ToBooleanStub::Types,
1523  HBasicBlock*, HBasicBlock*);
1524 
1526  return Representation::None();
1527  }
1528  virtual Representation observed_input_representation(int index) V8_OVERRIDE;
1529 
1530  virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
1531 
1533  return expected_input_types_;
1534  }
1535 
1537 
1538  private:
1539  HBranch(HValue* value,
1540  ToBooleanStub::Types expected_input_types = ToBooleanStub::Types(),
1541  HBasicBlock* true_target = NULL,
1542  HBasicBlock* false_target = NULL)
1543  : HUnaryControlInstruction(value, true_target, false_target),
1544  expected_input_types_(expected_input_types) {
1545  SetFlag(kAllowUndefinedAsNaN);
1546  }
1547 
1548  ToBooleanStub::Types expected_input_types_;
1549 };
1550 
1551 
1552 class HCompareMap V8_FINAL : public HUnaryControlInstruction {
1553  public:
1554  DECLARE_INSTRUCTION_FACTORY_P2(HCompareMap, HValue*, Handle<Map>);
1555  DECLARE_INSTRUCTION_FACTORY_P4(HCompareMap, HValue*, Handle<Map>,
1556  HBasicBlock*, HBasicBlock*);
1557 
1558  virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE {
1559  if (known_successor_index() != kNoKnownSuccessorIndex) {
1560  *block = SuccessorAt(known_successor_index());
1561  return true;
1562  }
1563  *block = NULL;
1564  return false;
1565  }
1566 
1567  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1568 
1569  static const int kNoKnownSuccessorIndex = -1;
1570  int known_successor_index() const { return known_successor_index_; }
1571  void set_known_successor_index(int known_successor_index) {
1572  known_successor_index_ = known_successor_index;
1573  }
1574 
1575  Unique<Map> map() const { return map_; }
1576 
1578  return Representation::Tagged();
1579  }
1580 
1581  DECLARE_CONCRETE_INSTRUCTION(CompareMap)
1582 
1583  protected:
1584  virtual int RedefinedOperandIndex() { return 0; }
1585 
1586  private:
1587  HCompareMap(HValue* value,
1588  Handle<Map> map,
1589  HBasicBlock* true_target = NULL,
1590  HBasicBlock* false_target = NULL)
1591  : HUnaryControlInstruction(value, true_target, false_target),
1592  known_successor_index_(kNoKnownSuccessorIndex), map_(Unique<Map>(map)) {
1593  ASSERT(!map.is_null());
1594  set_representation(Representation::Tagged());
1595  }
1596 
1597  int known_successor_index_;
1598  Unique<Map> map_;
1599 };
1600 
1601 
1602 class HContext V8_FINAL : public HTemplateInstruction<0> {
1603  public:
1604  static HContext* New(Zone* zone) {
1605  return new(zone) HContext();
1606  }
1607 
1609  return Representation::None();
1610  }
1611 
1613 
1614  protected:
1615  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1616 
1617  private:
1618  HContext() {
1619  set_representation(Representation::Tagged());
1620  SetFlag(kUseGVN);
1621  }
1622 
1623  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1624 };
1625 
1626 
1627 class HReturn V8_FINAL : public HTemplateControlInstruction<0, 3> {
1628  public:
1629  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HReturn, HValue*, HValue*);
1631 
1633  // TODO(titzer): require an Int32 input for faster returns.
1634  if (index == 2) return Representation::Smi();
1635  return Representation::Tagged();
1636  }
1637 
1638  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1639 
1640  HValue* value() { return OperandAt(0); }
1641  HValue* context() { return OperandAt(1); }
1642  HValue* parameter_count() { return OperandAt(2); }
1643 
1645 
1646  private:
1647  HReturn(HValue* context, HValue* value, HValue* parameter_count = 0) {
1648  SetOperandAt(0, value);
1649  SetOperandAt(1, context);
1650  SetOperandAt(2, parameter_count);
1651  }
1652 };
1653 
1654 
1655 class HAbnormalExit V8_FINAL : public HTemplateControlInstruction<0, 0> {
1656  public:
1657  DECLARE_INSTRUCTION_FACTORY_P0(HAbnormalExit);
1658 
1660  return Representation::None();
1661  }
1662 
1663  DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
1664  private:
1665  HAbnormalExit() {}
1666 };
1667 
1668 
1670  public:
1671  HUnaryOperation(HValue* value, HType type = HType::Tagged())
1672  : HTemplateInstruction<1>(type) {
1673  SetOperandAt(0, value);
1674  }
1675 
1676  static HUnaryOperation* cast(HValue* value) {
1677  return reinterpret_cast<HUnaryOperation*>(value);
1678  }
1679 
1680  HValue* value() const { return OperandAt(0); }
1681  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1682 };
1683 
1684 
1685 class HUseConst V8_FINAL : public HUnaryOperation {
1686  public:
1687  DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue*);
1688 
1690  return Representation::None();
1691  }
1692 
1694 
1695  private:
1696  explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
1697 };
1698 
1699 
1700 class HForceRepresentation V8_FINAL : public HTemplateInstruction<1> {
1701  public:
1702  static HInstruction* New(Zone* zone, HValue* context, HValue* value,
1703  Representation required_representation);
1704 
1705  HValue* value() { return OperandAt(0); }
1706 
1708  return representation(); // Same as the output representation.
1709  }
1710 
1711  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1712 
1713  DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
1714 
1715  private:
1716  HForceRepresentation(HValue* value, Representation required_representation) {
1717  SetOperandAt(0, value);
1718  set_representation(required_representation);
1719  }
1720 };
1721 
1722 
1723 class HChange V8_FINAL : public HUnaryOperation {
1724  public:
1725  HChange(HValue* value,
1726  Representation to,
1727  bool is_truncating_to_smi,
1728  bool is_truncating_to_int32)
1729  : HUnaryOperation(value) {
1730  ASSERT(!value->representation().IsNone());
1731  ASSERT(!to.IsNone());
1732  ASSERT(!value->representation().Equals(to));
1733  set_representation(to);
1734  SetFlag(kUseGVN);
1735  SetFlag(kCanOverflow);
1736  if (is_truncating_to_smi) {
1737  SetFlag(kTruncatingToSmi);
1738  SetFlag(kTruncatingToInt32);
1739  }
1740  if (is_truncating_to_int32) SetFlag(kTruncatingToInt32);
1741  if (value->representation().IsSmi() || value->type().IsSmi()) {
1742  set_type(HType::Smi());
1743  } else {
1744  set_type(HType::TaggedNumber());
1745  if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
1746  }
1747  }
1748 
1750  return CheckUsesForFlag(kAllowUndefinedAsNaN);
1751  }
1752 
1753  virtual HType CalculateInferredType() V8_OVERRIDE;
1754  virtual HValue* Canonicalize() V8_OVERRIDE;
1755 
1756  Representation from() const { return value()->representation(); }
1757  Representation to() const { return representation(); }
1759  return CheckFlag(kBailoutOnMinusZero);
1760  }
1762  return from();
1763  }
1764 
1765  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
1766 
1767  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1768 
1770 
1771  protected:
1772  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1773 
1774  private:
1775  virtual bool IsDeletable() const V8_OVERRIDE {
1776  return !from().IsTagged() || value()->type().IsSmi();
1777  }
1778 };
1779 
1780 
1781 class HClampToUint8 V8_FINAL : public HUnaryOperation {
1782  public:
1783  DECLARE_INSTRUCTION_FACTORY_P1(HClampToUint8, HValue*);
1784 
1786  return Representation::None();
1787  }
1788 
1789  DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
1790 
1791  protected:
1792  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1793 
1794  private:
1795  explicit HClampToUint8(HValue* value)
1796  : HUnaryOperation(value) {
1797  set_representation(Representation::Integer32());
1798  SetFlag(kAllowUndefinedAsNaN);
1799  SetFlag(kUseGVN);
1800  }
1801 
1802  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1803 };
1804 
1805 
1806 class HDoubleBits V8_FINAL : public HUnaryOperation {
1807  public:
1808  enum Bits { HIGH, LOW };
1809  DECLARE_INSTRUCTION_FACTORY_P2(HDoubleBits, HValue*, Bits);
1810 
1812  return Representation::Double();
1813  }
1814 
1815  DECLARE_CONCRETE_INSTRUCTION(DoubleBits)
1816 
1817  Bits bits() { return bits_; }
1818 
1819  protected:
1820  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
1821  return other->IsDoubleBits() && HDoubleBits::cast(other)->bits() == bits();
1822  }
1823 
1824  private:
1825  HDoubleBits(HValue* value, Bits bits)
1826  : HUnaryOperation(value), bits_(bits) {
1827  set_representation(Representation::Integer32());
1828  SetFlag(kUseGVN);
1829  }
1830 
1831  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1832 
1833  Bits bits_;
1834 };
1835 
1836 
1837 class HConstructDouble V8_FINAL : public HTemplateInstruction<2> {
1838  public:
1839  DECLARE_INSTRUCTION_FACTORY_P2(HConstructDouble, HValue*, HValue*);
1840 
1842  return Representation::Integer32();
1843  }
1844 
1845  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble)
1846 
1847  HValue* hi() { return OperandAt(0); }
1848  HValue* lo() { return OperandAt(1); }
1849 
1850  protected:
1851  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1852 
1853  private:
1854  explicit HConstructDouble(HValue* hi, HValue* lo) {
1855  set_representation(Representation::Double());
1856  SetFlag(kUseGVN);
1857  SetOperandAt(0, hi);
1858  SetOperandAt(1, lo);
1859  }
1860 
1861  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1862 };
1863 
1864 
1868 };
1869 
1870 
1871 class HSimulate V8_FINAL : public HInstruction {
1872  public:
1874  int pop_count,
1875  Zone* zone,
1876  RemovableSimulate removable)
1877  : ast_id_(ast_id),
1878  pop_count_(pop_count),
1879  values_(2, zone),
1880  assigned_indexes_(2, zone),
1881  zone_(zone),
1882  removable_(removable),
1883  done_with_replay_(false) {}
1885 
1886  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1887 
1888  bool HasAstId() const { return !ast_id_.IsNone(); }
1889  BailoutId ast_id() const { return ast_id_; }
1891  ASSERT(!HasAstId());
1892  ast_id_ = id;
1893  }
1894 
1895  int pop_count() const { return pop_count_; }
1896  const ZoneList<HValue*>* values() const { return &values_; }
1897  int GetAssignedIndexAt(int index) const {
1898  ASSERT(HasAssignedIndexAt(index));
1899  return assigned_indexes_[index];
1900  }
1901  bool HasAssignedIndexAt(int index) const {
1902  return assigned_indexes_[index] != kNoIndex;
1903  }
1904  void AddAssignedValue(int index, HValue* value) {
1905  AddValue(index, value);
1906  }
1907  void AddPushedValue(HValue* value) {
1908  AddValue(kNoIndex, value);
1909  }
1910  int ToOperandIndex(int environment_index) {
1911  for (int i = 0; i < assigned_indexes_.length(); ++i) {
1912  if (assigned_indexes_[i] == environment_index) return i;
1913  }
1914  return -1;
1915  }
1916  virtual int OperandCount() V8_OVERRIDE { return values_.length(); }
1917  virtual HValue* OperandAt(int index) const V8_OVERRIDE {
1918  return values_[index];
1919  }
1920 
1921  virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
1923  return Representation::None();
1924  }
1925 
1926  void MergeWith(ZoneList<HSimulate*>* list);
1927  bool is_candidate_for_removal() { return removable_ == REMOVABLE_SIMULATE; }
1928 
1929  // Replay effects of this instruction on the given environment.
1930  void ReplayEnvironment(HEnvironment* env);
1931 
1933 
1934 #ifdef DEBUG
1935  virtual void Verify() V8_OVERRIDE;
1936  void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
1937  Handle<JSFunction> closure() const { return closure_; }
1938 #endif
1939 
1940  protected:
1941  virtual void InternalSetOperandAt(int index, HValue* value) V8_OVERRIDE {
1942  values_[index] = value;
1943  }
1944 
1945  private:
1946  static const int kNoIndex = -1;
1947  void AddValue(int index, HValue* value) {
1948  assigned_indexes_.Add(index, zone_);
1949  // Resize the list of pushed values.
1950  values_.Add(NULL, zone_);
1951  // Set the operand through the base method in HValue to make sure that the
1952  // use lists are correctly updated.
1953  SetOperandAt(values_.length() - 1, value);
1954  }
1955  bool HasValueForIndex(int index) {
1956  for (int i = 0; i < assigned_indexes_.length(); ++i) {
1957  if (assigned_indexes_[i] == index) return true;
1958  }
1959  return false;
1960  }
1961  BailoutId ast_id_;
1962  int pop_count_;
1963  ZoneList<HValue*> values_;
1964  ZoneList<int> assigned_indexes_;
1965  Zone* zone_;
1966  RemovableSimulate removable_ : 2;
1967  bool done_with_replay_ : 1;
1968 
1969 #ifdef DEBUG
1970  Handle<JSFunction> closure_;
1971 #endif
1972 };
1973 
1974 
1975 class HEnvironmentMarker V8_FINAL : public HTemplateInstruction<1> {
1976  public:
1977  enum Kind { BIND, LOOKUP };
1978 
1979  DECLARE_INSTRUCTION_FACTORY_P2(HEnvironmentMarker, Kind, int);
1980 
1981  Kind kind() { return kind_; }
1982  int index() { return index_; }
1983  HSimulate* next_simulate() { return next_simulate_; }
1984  void set_next_simulate(HSimulate* simulate) {
1985  next_simulate_ = simulate;
1986  }
1987 
1989  return Representation::None();
1990  }
1991 
1992  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1993 
1994 #ifdef DEBUG
1995  void set_closure(Handle<JSFunction> closure) {
1996  ASSERT(closure_.is_null());
1997  ASSERT(!closure.is_null());
1998  closure_ = closure;
1999  }
2000  Handle<JSFunction> closure() const { return closure_; }
2001 #endif
2002 
2003  DECLARE_CONCRETE_INSTRUCTION(EnvironmentMarker);
2004 
2005  private:
2006  HEnvironmentMarker(Kind kind, int index)
2007  : kind_(kind), index_(index), next_simulate_(NULL) { }
2008 
2009  Kind kind_;
2010  int index_;
2011  HSimulate* next_simulate_;
2012 
2013 #ifdef DEBUG
2014  Handle<JSFunction> closure_;
2015 #endif
2016 };
2017 
2018 
2019 class HStackCheck V8_FINAL : public HTemplateInstruction<1> {
2020  public:
2021  enum Type {
2023  kBackwardsBranch
2024  };
2025 
2027 
2028  HValue* context() { return OperandAt(0); }
2029 
2031  return Representation::Tagged();
2032  }
2033 
2034  void Eliminate() {
2035  // The stack check eliminator might try to eliminate the same stack
2036  // check instruction multiple times.
2037  if (IsLinked()) {
2038  DeleteAndReplaceWith(NULL);
2039  }
2040  }
2041 
2042  bool is_function_entry() { return type_ == kFunctionEntry; }
2043  bool is_backwards_branch() { return type_ == kBackwardsBranch; }
2044 
2045  DECLARE_CONCRETE_INSTRUCTION(StackCheck)
2046 
2047  private:
2048  HStackCheck(HValue* context, Type type) : type_(type) {
2049  SetOperandAt(0, context);
2050  SetChangesFlag(kNewSpacePromotion);
2051  }
2052 
2053  Type type_;
2054 };
2055 
2056 
2058  NORMAL_RETURN, // Drop the function from the environment on return.
2059  CONSTRUCT_CALL_RETURN, // Either use allocated receiver or return value.
2060  GETTER_CALL_RETURN, // Returning from a getter, need to restore context.
2061  SETTER_CALL_RETURN // Use the RHS of the assignment as the return value.
2062 };
2063 
2064 
2065 class HArgumentsObject;
2066 
2067 
2068 class HEnterInlined V8_FINAL : public HTemplateInstruction<0> {
2069  public:
2070  static HEnterInlined* New(Zone* zone,
2071  HValue* context,
2072  Handle<JSFunction> closure,
2073  int arguments_count,
2074  FunctionLiteral* function,
2075  InliningKind inlining_kind,
2076  Variable* arguments_var,
2077  HArgumentsObject* arguments_object) {
2078  return new(zone) HEnterInlined(closure, arguments_count, function,
2079  inlining_kind, arguments_var,
2080  arguments_object, zone);
2081  }
2082 
2083  void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
2084  ZoneList<HBasicBlock*>* return_targets() { return &return_targets_; }
2085 
2086  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2087 
2088  Handle<JSFunction> closure() const { return closure_; }
2089  int arguments_count() const { return arguments_count_; }
2090  bool arguments_pushed() const { return arguments_pushed_; }
2091  void set_arguments_pushed() { arguments_pushed_ = true; }
2092  FunctionLiteral* function() const { return function_; }
2093  InliningKind inlining_kind() const { return inlining_kind_; }
2094 
2096  return Representation::None();
2097  }
2098 
2099  Variable* arguments_var() { return arguments_var_; }
2100  HArgumentsObject* arguments_object() { return arguments_object_; }
2101 
2102  DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
2103 
2104  private:
2105  HEnterInlined(Handle<JSFunction> closure,
2106  int arguments_count,
2107  FunctionLiteral* function,
2108  InliningKind inlining_kind,
2109  Variable* arguments_var,
2110  HArgumentsObject* arguments_object,
2111  Zone* zone)
2112  : closure_(closure),
2113  arguments_count_(arguments_count),
2114  arguments_pushed_(false),
2115  function_(function),
2116  inlining_kind_(inlining_kind),
2117  arguments_var_(arguments_var),
2118  arguments_object_(arguments_object),
2119  return_targets_(2, zone) {
2120  }
2121 
2122  Handle<JSFunction> closure_;
2123  int arguments_count_;
2124  bool arguments_pushed_;
2125  FunctionLiteral* function_;
2126  InliningKind inlining_kind_;
2127  Variable* arguments_var_;
2128  HArgumentsObject* arguments_object_;
2129  ZoneList<HBasicBlock*> return_targets_;
2130 };
2131 
2132 
2133 class HLeaveInlined V8_FINAL : public HTemplateInstruction<0> {
2134  public:
2135  HLeaveInlined(HEnterInlined* entry,
2136  int drop_count)
2137  : entry_(entry),
2138  drop_count_(drop_count) { }
2139 
2141  return Representation::None();
2142  }
2143 
2144  virtual int argument_delta() const V8_OVERRIDE {
2145  return entry_->arguments_pushed() ? -drop_count_ : 0;
2146  }
2147 
2148  DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
2149 
2150  private:
2151  HEnterInlined* entry_;
2152  int drop_count_;
2153 };
2154 
2155 
2156 class HPushArgument V8_FINAL : public HUnaryOperation {
2157  public:
2158  DECLARE_INSTRUCTION_FACTORY_P1(HPushArgument, HValue*);
2159 
2161  return Representation::Tagged();
2162  }
2163 
2164  virtual int argument_delta() const V8_OVERRIDE { return 1; }
2165  HValue* argument() { return OperandAt(0); }
2166 
2167  DECLARE_CONCRETE_INSTRUCTION(PushArgument)
2168 
2169  private:
2170  explicit HPushArgument(HValue* value) : HUnaryOperation(value) {
2171  set_representation(Representation::Tagged());
2172  }
2173 };
2174 
2175 
2176 class HThisFunction V8_FINAL : public HTemplateInstruction<0> {
2177  public:
2178  DECLARE_INSTRUCTION_FACTORY_P0(HThisFunction);
2179 
2181  return Representation::None();
2182  }
2183 
2184  DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
2185 
2186  protected:
2187  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2188 
2189  private:
2190  HThisFunction() {
2191  set_representation(Representation::Tagged());
2192  SetFlag(kUseGVN);
2193  }
2194 
2195  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2196 };
2197 
2198 
2199 class HDeclareGlobals V8_FINAL : public HUnaryOperation {
2200  public:
2202  Handle<FixedArray>,
2203  int);
2204 
2205  HValue* context() { return OperandAt(0); }
2206  Handle<FixedArray> pairs() const { return pairs_; }
2207  int flags() const { return flags_; }
2208 
2209  DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
2210 
2211  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2212  return Representation::Tagged();
2213  }
2214 
2215  private:
2216  HDeclareGlobals(HValue* context,
2218  int flags)
2219  : HUnaryOperation(context),
2220  pairs_(pairs),
2221  flags_(flags) {
2222  set_representation(Representation::Tagged());
2223  SetAllSideEffects();
2224  }
2225 
2226  Handle<FixedArray> pairs_;
2227  int flags_;
2228 };
2229 
2230 
2231 template <int V>
2232 class HCall : public HTemplateInstruction<V> {
2233  public:
2234  // The argument count includes the receiver.
2235  explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
2236  this->set_representation(Representation::Tagged());
2237  this->SetAllSideEffects();
2238  }
2239 
2241  return HType::Tagged();
2242  }
2243 
2244  virtual int argument_count() const {
2245  return argument_count_;
2246  }
2247 
2248  virtual int argument_delta() const V8_OVERRIDE {
2249  return -argument_count();
2250  }
2251 
2252  private:
2253  int argument_count_;
2254 };
2255 
2256 
2257 class HUnaryCall : public HCall<1> {
2258  public:
2259  HUnaryCall(HValue* value, int argument_count)
2260  : HCall<1>(argument_count) {
2261  SetOperandAt(0, value);
2262  }
2263 
2265  int index) V8_FINAL V8_OVERRIDE {
2266  return Representation::Tagged();
2267  }
2268 
2269  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2270 
2271  HValue* value() { return OperandAt(0); }
2272 };
2273 
2274 
2275 class HBinaryCall : public HCall<2> {
2276  public:
2277  HBinaryCall(HValue* first, HValue* second, int argument_count)
2278  : HCall<2>(argument_count) {
2279  SetOperandAt(0, first);
2280  SetOperandAt(1, second);
2281  }
2282 
2283  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2284 
2286  int index) V8_FINAL V8_OVERRIDE {
2287  return Representation::Tagged();
2288  }
2289 
2290  HValue* first() { return OperandAt(0); }
2291  HValue* second() { return OperandAt(1); }
2292 };
2293 
2294 
2295 class HCallJSFunction V8_FINAL : public HCall<1> {
2296  public:
2297  static HCallJSFunction* New(Zone* zone,
2298  HValue* context,
2299  HValue* function,
2300  int argument_count,
2301  bool pass_argument_count);
2302 
2303  HValue* function() { return OperandAt(0); }
2304 
2305  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2306 
2308  int index) V8_FINAL V8_OVERRIDE {
2309  ASSERT(index == 0);
2310  return Representation::Tagged();
2311  }
2312 
2313  bool pass_argument_count() const { return pass_argument_count_; }
2314 
2316  return has_stack_check_;
2317  }
2318 
2319  DECLARE_CONCRETE_INSTRUCTION(CallJSFunction)
2320 
2321  private:
2322  // The argument count includes the receiver.
2323  HCallJSFunction(HValue* function,
2324  int argument_count,
2325  bool pass_argument_count,
2326  bool has_stack_check)
2327  : HCall<1>(argument_count),
2328  pass_argument_count_(pass_argument_count),
2329  has_stack_check_(has_stack_check) {
2330  SetOperandAt(0, function);
2331  }
2332 
2333  bool pass_argument_count_;
2334  bool has_stack_check_;
2335 };
2336 
2337 
2338 class HCallWithDescriptor V8_FINAL : public HInstruction {
2339  public:
2340  static HCallWithDescriptor* New(Zone* zone, HValue* context,
2341  HValue* target,
2342  int argument_count,
2343  const CallInterfaceDescriptor* descriptor,
2344  Vector<HValue*>& operands) {
2345  ASSERT(operands.length() == descriptor->environment_length());
2346  HCallWithDescriptor* res =
2347  new(zone) HCallWithDescriptor(target, argument_count,
2348  descriptor, operands, zone);
2349  return res;
2350  }
2351 
2352  virtual int OperandCount() V8_FINAL V8_OVERRIDE { return values_.length(); }
2353  virtual HValue* OperandAt(int index) const V8_FINAL V8_OVERRIDE {
2354  return values_[index];
2355  }
2356 
2358  int index) V8_FINAL V8_OVERRIDE {
2359  if (index == 0) {
2360  return Representation::Tagged();
2361  } else {
2362  int par_index = index - 1;
2363  ASSERT(par_index < descriptor_->environment_length());
2364  return descriptor_->GetParameterRepresentation(par_index);
2365  }
2366  }
2367 
2368  DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor)
2369 
2370  virtual HType CalculateInferredType() V8_FINAL V8_OVERRIDE {
2371  return HType::Tagged();
2372  }
2373 
2374  virtual int argument_count() const {
2375  return argument_count_;
2376  }
2377 
2378  virtual int argument_delta() const V8_OVERRIDE {
2379  return -argument_count_;
2380  }
2381 
2383  return descriptor_;
2384  }
2385 
2387  return OperandAt(0);
2388  }
2389 
2390  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2391 
2392  private:
2393  // The argument count includes the receiver.
2394  HCallWithDescriptor(HValue* target,
2395  int argument_count,
2396  const CallInterfaceDescriptor* descriptor,
2397  Vector<HValue*>& operands,
2398  Zone* zone)
2399  : descriptor_(descriptor),
2400  values_(descriptor->environment_length() + 1, zone) {
2401  argument_count_ = argument_count;
2402  AddOperand(target, zone);
2403  for (int i = 0; i < operands.length(); i++) {
2404  AddOperand(operands[i], zone);
2405  }
2406  this->set_representation(Representation::Tagged());
2407  this->SetAllSideEffects();
2408  }
2409 
2410  void AddOperand(HValue* v, Zone* zone) {
2411  values_.Add(NULL, zone);
2412  SetOperandAt(values_.length() - 1, v);
2413  }
2414 
2415  void InternalSetOperandAt(int index,
2416  HValue* value) V8_FINAL V8_OVERRIDE {
2417  values_[index] = value;
2418  }
2419 
2420  const CallInterfaceDescriptor* descriptor_;
2421  ZoneList<HValue*> values_;
2422  int argument_count_;
2423 };
2424 
2425 
2426 class HInvokeFunction V8_FINAL : public HBinaryCall {
2427  public:
2428  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInvokeFunction, HValue*, int);
2429 
2431  HValue* function,
2432  Handle<JSFunction> known_function,
2433  int argument_count)
2434  : HBinaryCall(context, function, argument_count),
2435  known_function_(known_function) {
2436  formal_parameter_count_ = known_function.is_null()
2437  ? 0 : known_function->shared()->formal_parameter_count();
2438  has_stack_check_ = !known_function.is_null() &&
2439  (known_function->code()->kind() == Code::FUNCTION ||
2440  known_function->code()->kind() == Code::OPTIMIZED_FUNCTION);
2441  }
2442 
2443  static HInvokeFunction* New(Zone* zone,
2444  HValue* context,
2445  HValue* function,
2446  Handle<JSFunction> known_function,
2447  int argument_count) {
2448  return new(zone) HInvokeFunction(context, function,
2449  known_function, argument_count);
2450  }
2451 
2452  HValue* context() { return first(); }
2453  HValue* function() { return second(); }
2454  Handle<JSFunction> known_function() { return known_function_; }
2455  int formal_parameter_count() const { return formal_parameter_count_; }
2456 
2458  return has_stack_check_;
2459  }
2460 
2461  DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
2462 
2463  private:
2464  HInvokeFunction(HValue* context, HValue* function, int argument_count)
2465  : HBinaryCall(context, function, argument_count),
2466  has_stack_check_(false) {
2467  }
2468 
2469  Handle<JSFunction> known_function_;
2470  int formal_parameter_count_;
2471  bool has_stack_check_;
2472 };
2473 
2474 
2475 class HCallFunction V8_FINAL : public HBinaryCall {
2476  public:
2477  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallFunction, HValue*, int);
2479  HCallFunction, HValue*, int, CallFunctionFlags);
2480 
2481  HValue* context() { return first(); }
2482  HValue* function() { return second(); }
2483  CallFunctionFlags function_flags() const { return function_flags_; }
2484 
2485  DECLARE_CONCRETE_INSTRUCTION(CallFunction)
2486 
2487  virtual int argument_delta() const V8_OVERRIDE { return -argument_count(); }
2488 
2489  private:
2490  HCallFunction(HValue* context,
2491  HValue* function,
2492  int argument_count,
2494  : HBinaryCall(context, function, argument_count), function_flags_(flags) {
2495  }
2496  CallFunctionFlags function_flags_;
2497 };
2498 
2499 
2500 class HCallNew V8_FINAL : public HBinaryCall {
2501  public:
2502  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallNew, HValue*, int);
2503 
2504  HValue* context() { return first(); }
2505  HValue* constructor() { return second(); }
2506 
2508 
2509  private:
2510  HCallNew(HValue* context, HValue* constructor, int argument_count)
2511  : HBinaryCall(context, constructor, argument_count) {}
2512 };
2513 
2514 
2515 class HCallNewArray V8_FINAL : public HBinaryCall {
2516  public:
2518  HValue*,
2519  int,
2520  ElementsKind);
2521 
2522  HValue* context() { return first(); }
2523  HValue* constructor() { return second(); }
2524 
2525  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2526 
2527  ElementsKind elements_kind() const { return elements_kind_; }
2528 
2529  DECLARE_CONCRETE_INSTRUCTION(CallNewArray)
2530 
2531  private:
2532  HCallNewArray(HValue* context, HValue* constructor, int argument_count,
2533  ElementsKind elements_kind)
2534  : HBinaryCall(context, constructor, argument_count),
2535  elements_kind_(elements_kind) {}
2536 
2537  ElementsKind elements_kind_;
2538 };
2539 
2540 
2541 class HCallRuntime V8_FINAL : public HCall<1> {
2542  public:
2544  Handle<String>,
2545  const Runtime::Function*,
2546  int);
2547 
2548  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2549 
2550  HValue* context() { return OperandAt(0); }
2551  const Runtime::Function* function() const { return c_function_; }
2552  Handle<String> name() const { return name_; }
2553  SaveFPRegsMode save_doubles() const { return save_doubles_; }
2554  void set_save_doubles(SaveFPRegsMode save_doubles) {
2555  save_doubles_ = save_doubles;
2556  }
2557 
2559  return Representation::Tagged();
2560  }
2561 
2562  DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
2563 
2564  private:
2565  HCallRuntime(HValue* context,
2566  Handle<String> name,
2567  const Runtime::Function* c_function,
2568  int argument_count)
2569  : HCall<1>(argument_count), c_function_(c_function), name_(name),
2570  save_doubles_(kDontSaveFPRegs) {
2571  SetOperandAt(0, context);
2572  }
2573 
2574  const Runtime::Function* c_function_;
2575  Handle<String> name_;
2576  SaveFPRegsMode save_doubles_;
2577 };
2578 
2579 
2580 class HMapEnumLength V8_FINAL : public HUnaryOperation {
2581  public:
2582  DECLARE_INSTRUCTION_FACTORY_P1(HMapEnumLength, HValue*);
2583 
2585  return Representation::Tagged();
2586  }
2587 
2588  DECLARE_CONCRETE_INSTRUCTION(MapEnumLength)
2589 
2590  protected:
2591  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2592 
2593  private:
2594  explicit HMapEnumLength(HValue* value)
2595  : HUnaryOperation(value, HType::Smi()) {
2596  set_representation(Representation::Smi());
2597  SetFlag(kUseGVN);
2598  SetDependsOnFlag(kMaps);
2599  }
2600 
2601  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2602 };
2603 
2604 
2605 class HUnaryMathOperation V8_FINAL : public HTemplateInstruction<2> {
2606  public:
2607  static HInstruction* New(Zone* zone,
2608  HValue* context,
2609  HValue* value,
2610  BuiltinFunctionId op);
2611 
2612  HValue* context() { return OperandAt(0); }
2613  HValue* value() { return OperandAt(1); }
2614 
2615  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2616 
2618  if (index == 0) {
2619  return Representation::Tagged();
2620  } else {
2621  switch (op_) {
2622  case kMathFloor:
2623  case kMathRound:
2624  case kMathSqrt:
2625  case kMathPowHalf:
2626  case kMathLog:
2627  case kMathExp:
2628  return Representation::Double();
2629  case kMathAbs:
2630  return representation();
2631  case kMathClz32:
2632  return Representation::Integer32();
2633  default:
2634  UNREACHABLE();
2635  return Representation::None();
2636  }
2637  }
2638  }
2639 
2640  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
2641 
2642  virtual HValue* Canonicalize() V8_OVERRIDE;
2643  virtual Representation RepresentationFromInputs() V8_OVERRIDE;
2644 
2645  BuiltinFunctionId op() const { return op_; }
2646  const char* OpName() const;
2647 
2648  DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
2649 
2650  protected:
2651  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2652  HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
2653  return op_ == b->op();
2654  }
2655 
2656  private:
2657  HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
2658  : HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
2659  SetOperandAt(0, context);
2660  SetOperandAt(1, value);
2661  switch (op) {
2662  case kMathFloor:
2663  case kMathRound:
2664  case kMathClz32:
2665  set_representation(Representation::Integer32());
2666  break;
2667  case kMathAbs:
2668  // Not setting representation here: it is None intentionally.
2669  SetFlag(kFlexibleRepresentation);
2670  // TODO(svenpanne) This flag is actually only needed if representation()
2671  // is tagged, and not when it is an unboxed double or unboxed integer.
2672  SetChangesFlag(kNewSpacePromotion);
2673  break;
2674  case kMathLog:
2675  case kMathExp:
2676  case kMathSqrt:
2677  case kMathPowHalf:
2678  set_representation(Representation::Double());
2679  break;
2680  default:
2681  UNREACHABLE();
2682  }
2683  SetFlag(kUseGVN);
2684  SetFlag(kAllowUndefinedAsNaN);
2685  }
2686 
2687  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2688 
2689  HValue* SimplifiedDividendForMathFloorOfDiv(HDiv* hdiv);
2690  HValue* SimplifiedDivisorForMathFloorOfDiv(HDiv* hdiv);
2691 
2692  BuiltinFunctionId op_;
2693 };
2694 
2695 
2696 class HLoadRoot V8_FINAL : public HTemplateInstruction<0> {
2697  public:
2700 
2702  return Representation::None();
2703  }
2704 
2705  Heap::RootListIndex index() const { return index_; }
2706 
2708 
2709  protected:
2710  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2711  HLoadRoot* b = HLoadRoot::cast(other);
2712  return index_ == b->index_;
2713  }
2714 
2715  private:
2716  HLoadRoot(Heap::RootListIndex index, HType type = HType::Tagged())
2717  : HTemplateInstruction<0>(type), index_(index) {
2718  SetFlag(kUseGVN);
2719  // TODO(bmeurer): We'll need kDependsOnRoots once we add the
2720  // corresponding HStoreRoot instruction.
2721  SetDependsOnFlag(kCalls);
2722  }
2723 
2724  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2725 
2726  const Heap::RootListIndex index_;
2727 };
2728 
2729 
2730 class HCheckMaps V8_FINAL : public HTemplateInstruction<2> {
2731  public:
2732  static HCheckMaps* New(Zone* zone, HValue* context, HValue* value,
2733  Handle<Map> map, CompilationInfo* info,
2734  HValue* typecheck = NULL);
2735  static HCheckMaps* New(Zone* zone, HValue* context,
2736  HValue* value, SmallMapList* maps,
2737  HValue* typecheck = NULL) {
2738  HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck);
2739  for (int i = 0; i < maps->length(); i++) {
2740  check_map->Add(maps->at(i), zone);
2741  }
2742  return check_map;
2743  }
2744 
2745  bool CanOmitMapChecks() { return omit_; }
2746 
2747  virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
2749  return Representation::Tagged();
2750  }
2751  virtual bool HandleSideEffectDominator(GVNFlag side_effect,
2752  HValue* dominator) V8_OVERRIDE;
2753  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2754 
2755  HValue* value() { return OperandAt(0); }
2756  HValue* typecheck() { return OperandAt(1); }
2757 
2758  Unique<Map> first_map() const { return map_set_.at(0); }
2759  UniqueSet<Map> map_set() const { return map_set_; }
2760 
2761  void set_map_set(UniqueSet<Map>* maps, Zone *zone) {
2762  map_set_.Clear();
2763  for (int i = 0; i < maps->size(); i++) {
2764  map_set_.Add(maps->at(i), zone);
2765  }
2766  }
2767 
2768  bool has_migration_target() const {
2769  return has_migration_target_;
2770  }
2771 
2772  DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
2773 
2774  protected:
2775  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2776  return this->map_set_.Equals(&HCheckMaps::cast(other)->map_set_);
2777  }
2778 
2779  virtual int RedefinedOperandIndex() { return 0; }
2780 
2781  private:
2782  void Add(Handle<Map> map, Zone* zone) {
2783  map_set_.Add(Unique<Map>(map), zone);
2784  SetDependsOnFlag(kMaps);
2785  SetDependsOnFlag(kElementsKind);
2786 
2787  if (!has_migration_target_ && map->is_migration_target()) {
2788  has_migration_target_ = true;
2789  SetChangesFlag(kNewSpacePromotion);
2790  }
2791  }
2792 
2793  // Clients should use one of the static New* methods above.
2794  HCheckMaps(HValue* value, Zone *zone, HValue* typecheck)
2795  : HTemplateInstruction<2>(value->type()),
2796  omit_(false), has_migration_target_(false) {
2797  SetOperandAt(0, value);
2798  // Use the object value for the dependency if NULL is passed.
2799  SetOperandAt(1, typecheck != NULL ? typecheck : value);
2800  set_representation(Representation::Tagged());
2801  SetFlag(kUseGVN);
2802  SetFlag(kTrackSideEffectDominators);
2803  }
2804 
2805  bool omit_;
2806  bool has_migration_target_;
2807  UniqueSet<Map> map_set_;
2808 };
2809 
2810 
2811 class HCheckValue V8_FINAL : public HUnaryOperation {
2812  public:
2813  static HCheckValue* New(Zone* zone, HValue* context,
2814  HValue* value, Handle<JSFunction> func) {
2815  bool in_new_space = zone->isolate()->heap()->InNewSpace(*func);
2816  // NOTE: We create an uninitialized Unique and initialize it later.
2817  // This is because a JSFunction can move due to GC during graph creation.
2818  // TODO(titzer): This is a migration crutch. Replace with some kind of
2819  // Uniqueness scope later.
2820  Unique<JSFunction> target = Unique<JSFunction>::CreateUninitialized(func);
2821  HCheckValue* check = new(zone) HCheckValue(value, target, in_new_space);
2822  return check;
2823  }
2824  static HCheckValue* New(Zone* zone, HValue* context,
2825  HValue* value, Unique<HeapObject> target,
2826  bool object_in_new_space) {
2827  return new(zone) HCheckValue(value, target, object_in_new_space);
2828  }
2829 
2831  object_ = Unique<HeapObject>(object_.handle());
2832  }
2833 
2835  return Representation::Tagged();
2836  }
2837  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2838 
2839  virtual HValue* Canonicalize() V8_OVERRIDE;
2840 
2841 #ifdef DEBUG
2842  virtual void Verify() V8_OVERRIDE;
2843 #endif
2844 
2845  Unique<HeapObject> object() const { return object_; }
2846  bool object_in_new_space() const { return object_in_new_space_; }
2847 
2848  DECLARE_CONCRETE_INSTRUCTION(CheckValue)
2849 
2850  protected:
2851  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2852  HCheckValue* b = HCheckValue::cast(other);
2853  return object_ == b->object_;
2854  }
2855 
2856  private:
2857  HCheckValue(HValue* value, Unique<HeapObject> object,
2858  bool object_in_new_space)
2859  : HUnaryOperation(value, value->type()),
2860  object_(object),
2861  object_in_new_space_(object_in_new_space) {
2862  set_representation(Representation::Tagged());
2863  SetFlag(kUseGVN);
2864  }
2865 
2866  Unique<HeapObject> object_;
2867  bool object_in_new_space_;
2868 };
2869 
2870 
2871 class HCheckInstanceType V8_FINAL : public HUnaryOperation {
2872  public:
2873  enum Check {
2878  LAST_INTERVAL_CHECK = IS_JS_ARRAY
2879  };
2880 
2881  DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue*, Check);
2882 
2883  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2884 
2886  return Representation::Tagged();
2887  }
2888 
2889  virtual HValue* Canonicalize() V8_OVERRIDE;
2890 
2891  bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
2892  void GetCheckInterval(InstanceType* first, InstanceType* last);
2893  void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
2894 
2895  DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
2896 
2897  protected:
2898  // TODO(ager): It could be nice to allow the ommision of instance
2899  // type checks if we have already performed an instance type check
2900  // with a larger range.
2901  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2902  HCheckInstanceType* b = HCheckInstanceType::cast(other);
2903  return check_ == b->check_;
2904  }
2905 
2906  virtual int RedefinedOperandIndex() { return 0; }
2907 
2908  private:
2909  const char* GetCheckName();
2910 
2911  HCheckInstanceType(HValue* value, Check check)
2912  : HUnaryOperation(value), check_(check) {
2913  set_representation(Representation::Tagged());
2914  SetFlag(kUseGVN);
2915  }
2916 
2917  const Check check_;
2918 };
2919 
2920 
2921 class HCheckSmi V8_FINAL : public HUnaryOperation {
2922  public:
2923  DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue*);
2924 
2926  return Representation::Tagged();
2927  }
2928 
2930  HType value_type = value()->type();
2931  if (value_type.IsSmi()) {
2932  return NULL;
2933  }
2934  return this;
2935  }
2936 
2938 
2939  protected:
2940  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2941 
2942  private:
2943  explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
2944  set_representation(Representation::Smi());
2945  SetFlag(kUseGVN);
2946  }
2947 };
2948 
2949 
2950 class HCheckHeapObject V8_FINAL : public HUnaryOperation {
2951  public:
2952  DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
2953 
2954  virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
2956  return Representation::Tagged();
2957  }
2958 
2959 #ifdef DEBUG
2960  virtual void Verify() V8_OVERRIDE;
2961 #endif
2962 
2964  return value()->type().IsHeapObject() ? NULL : this;
2965  }
2966 
2967  DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
2968 
2969  protected:
2970  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2971 
2972  private:
2973  explicit HCheckHeapObject(HValue* value)
2974  : HUnaryOperation(value, HType::NonPrimitive()) {
2975  set_representation(Representation::Tagged());
2976  SetFlag(kUseGVN);
2977  }
2978 };
2979 
2980 
2981 class InductionVariableData;
2982 
2983 
2985  InductionVariableData* updated_variable;
2989 
2991  : updated_variable(NULL), limit(NULL),
2992  limit_is_upper(false), limit_is_included(false) {}
2993 };
2994 
2995 
2996 class HBoundsCheck;
2997 class HPhi;
2998 class HConstant;
2999 class HBitwise;
3000 
3001 
3002 class InductionVariableData V8_FINAL : public ZoneObject {
3003  public:
3005  public:
3006  HBoundsCheck* check() { return check_; }
3007  InductionVariableCheck* next() { return next_; }
3008  bool HasUpperLimit() { return upper_limit_ >= 0; }
3010  ASSERT(HasUpperLimit());
3011  return upper_limit_;
3012  }
3013  void set_upper_limit(int32_t upper_limit) {
3014  upper_limit_ = upper_limit;
3015  }
3016 
3017  bool processed() { return processed_; }
3018  void set_processed() { processed_ = true; }
3019 
3021  InductionVariableCheck* next,
3022  int32_t upper_limit = kNoLimit)
3023  : check_(check), next_(next), upper_limit_(upper_limit),
3024  processed_(false) {}
3025 
3026  private:
3027  HBoundsCheck* check_;
3028  InductionVariableCheck* next_;
3029  int32_t upper_limit_;
3030  bool processed_;
3031  };
3032 
3034  public:
3035  HValue* length() { return length_; }
3036  ChecksRelatedToLength* next() { return next_; }
3037  InductionVariableCheck* checks() { return checks_; }
3038 
3039  void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3040  void CloseCurrentBlock();
3041 
3043  : length_(length), next_(next), checks_(NULL),
3044  first_check_in_block_(NULL),
3045  added_index_(NULL),
3046  added_constant_(NULL),
3047  current_and_mask_in_block_(0),
3048  current_or_mask_in_block_(0) {}
3049 
3050  private:
3051  void UseNewIndexInCurrentBlock(Token::Value token,
3052  int32_t mask,
3053  HValue* index_base,
3054  HValue* context);
3055 
3056  HBoundsCheck* first_check_in_block() { return first_check_in_block_; }
3057  HBitwise* added_index() { return added_index_; }
3058  void set_added_index(HBitwise* index) { added_index_ = index; }
3059  HConstant* added_constant() { return added_constant_; }
3060  void set_added_constant(HConstant* constant) { added_constant_ = constant; }
3061  int32_t current_and_mask_in_block() { return current_and_mask_in_block_; }
3062  int32_t current_or_mask_in_block() { return current_or_mask_in_block_; }
3063  int32_t current_upper_limit() { return current_upper_limit_; }
3064 
3065  HValue* length_;
3066  ChecksRelatedToLength* next_;
3067  InductionVariableCheck* checks_;
3068 
3069  HBoundsCheck* first_check_in_block_;
3070  HBitwise* added_index_;
3071  HConstant* added_constant_;
3072  int32_t current_and_mask_in_block_;
3073  int32_t current_or_mask_in_block_;
3074  int32_t current_upper_limit_;
3075  };
3076 
3078  InductionVariableData* variable;
3081  HBasicBlock* other_target;
3082 
3083  bool LimitIsValid() { return token != Token::ILLEGAL; }
3084 
3086  return Token::IsEqualityOp(token) ||
3087  token == Token::GTE || token == Token::LTE;
3088  }
3089  bool LimitIsUpper() {
3090  return token == Token::LTE || token == Token::LT || token == Token::NE;
3091  }
3092 
3094  : variable(NULL),
3095  token(Token::ILLEGAL),
3096  limit(NULL),
3097  other_target(NULL) {}
3098  };
3099 
3100  static const int32_t kNoLimit = -1;
3101 
3102  static InductionVariableData* ExaminePhi(HPhi* phi);
3103  static void ComputeLimitFromPredecessorBlock(
3104  HBasicBlock* block,
3105  LimitFromPredecessorBlock* result);
3106  static bool ComputeInductionVariableLimit(
3107  HBasicBlock* block,
3108  InductionVariableLimitUpdate* additional_limit);
3109 
3115 
3117  : base(NULL), and_mask(0), or_mask(0), context(NULL) {}
3118  };
3119  static void DecomposeBitwise(HValue* value,
3120  BitwiseDecompositionResult* result);
3121 
3122  void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3123 
3124  bool CheckIfBranchIsLoopGuard(Token::Value token,
3125  HBasicBlock* current_branch,
3126  HBasicBlock* other_branch);
3127 
3128  void UpdateAdditionalLimit(InductionVariableLimitUpdate* update);
3129 
3130  HPhi* phi() { return phi_; }
3131  HValue* base() { return base_; }
3132  int32_t increment() { return increment_; }
3133  HValue* limit() { return limit_; }
3134  bool limit_included() { return limit_included_; }
3135  HBasicBlock* limit_validity() { return limit_validity_; }
3136  HBasicBlock* induction_exit_block() { return induction_exit_block_; }
3137  HBasicBlock* induction_exit_target() { return induction_exit_target_; }
3138  ChecksRelatedToLength* checks() { return checks_; }
3139  HValue* additional_upper_limit() { return additional_upper_limit_; }
3141  return additional_upper_limit_is_included_;
3142  }
3143  HValue* additional_lower_limit() { return additional_lower_limit_; }
3145  return additional_lower_limit_is_included_;
3146  }
3147 
3149  if (base()->IsInteger32Constant() && base()->GetInteger32Constant() >= 0) {
3150  return true;
3151  }
3152  if (additional_lower_limit() != NULL &&
3153  additional_lower_limit()->IsInteger32Constant() &&
3154  additional_lower_limit()->GetInteger32Constant() >= 0) {
3155  // Ignoring the corner case of !additional_lower_limit_is_included()
3156  // is safe, handling it adds unneeded complexity.
3157  return true;
3158  }
3159  return false;
3160  }
3161 
3162  int32_t ComputeUpperLimit(int32_t and_mask, int32_t or_mask);
3163 
3164  private:
3165  template <class T> void swap(T* a, T* b) {
3166  T c(*a);
3167  *a = *b;
3168  *b = c;
3169  }
3170 
3171  InductionVariableData(HPhi* phi, HValue* base, int32_t increment)
3172  : phi_(phi), base_(IgnoreOsrValue(base)), increment_(increment),
3173  limit_(NULL), limit_included_(false), limit_validity_(NULL),
3174  induction_exit_block_(NULL), induction_exit_target_(NULL),
3175  checks_(NULL),
3176  additional_upper_limit_(NULL),
3177  additional_upper_limit_is_included_(false),
3178  additional_lower_limit_(NULL),
3179  additional_lower_limit_is_included_(false) {}
3180 
3181  static int32_t ComputeIncrement(HPhi* phi, HValue* phi_operand);
3182 
3183  static HValue* IgnoreOsrValue(HValue* v);
3184  static InductionVariableData* GetInductionVariableData(HValue* v);
3185 
3186  HPhi* phi_;
3187  HValue* base_;
3188  int32_t increment_;
3189  HValue* limit_;
3190  bool limit_included_;
3191  HBasicBlock* limit_validity_;
3192  HBasicBlock* induction_exit_block_;
3193  HBasicBlock* induction_exit_target_;
3194  ChecksRelatedToLength* checks_;
3195  HValue* additional_upper_limit_;
3196  bool additional_upper_limit_is_included_;
3197  HValue* additional_lower_limit_;
3198  bool additional_lower_limit_is_included_;
3199 };
3200 
3201 
3202 class HPhi V8_FINAL : public HValue {
3203  public:
3204  HPhi(int merged_index, Zone* zone)
3205  : inputs_(2, zone),
3206  merged_index_(merged_index),
3207  phi_id_(-1),
3208  induction_variable_data_(NULL) {
3209  for (int i = 0; i < Representation::kNumRepresentations; i++) {
3210  non_phi_uses_[i] = 0;
3211  indirect_uses_[i] = 0;
3212  }
3213  ASSERT(merged_index >= 0 || merged_index == kInvalidMergedIndex);
3214  SetFlag(kFlexibleRepresentation);
3215  SetFlag(kAllowUndefinedAsNaN);
3216  }
3217 
3218  virtual Representation RepresentationFromInputs() V8_OVERRIDE;
3219 
3220  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
3221  virtual void InferRepresentation(
3222  HInferRepresentationPhase* h_infer) V8_OVERRIDE;
3223  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3224  return representation();
3225  }
3227  return representation();
3228  }
3229  virtual HType CalculateInferredType() V8_OVERRIDE;
3230  virtual int OperandCount() V8_OVERRIDE { return inputs_.length(); }
3231  virtual HValue* OperandAt(int index) const V8_OVERRIDE {
3232  return inputs_[index];
3233  }
3234  HValue* GetRedundantReplacement();
3235  void AddInput(HValue* value);
3236  bool HasRealUses();
3237 
3238  bool IsReceiver() const { return merged_index_ == 0; }
3239  bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
3240 
3241  virtual HSourcePosition position() const V8_OVERRIDE;
3242 
3243  int merged_index() const { return merged_index_; }
3244 
3245  InductionVariableData* induction_variable_data() {
3246  return induction_variable_data_;
3247  }
3249  return induction_variable_data_ != NULL;
3250  }
3252  return IsInductionVariable() &&
3253  induction_variable_data_->limit() != NULL;
3254  }
3256  ASSERT(induction_variable_data_ == NULL);
3257  induction_variable_data_ = InductionVariableData::ExaminePhi(this);
3258  }
3259 
3260  virtual void PrintTo(StringStream* stream) V8_OVERRIDE;
3261 
3262 #ifdef DEBUG
3263  virtual void Verify() V8_OVERRIDE;
3264 #endif
3265 
3266  void InitRealUses(int id);
3267  void AddNonPhiUsesFrom(HPhi* other);
3268  void AddIndirectUsesTo(int* use_count);
3269 
3270  int tagged_non_phi_uses() const {
3271  return non_phi_uses_[Representation::kTagged];
3272  }
3273  int smi_non_phi_uses() const {
3274  return non_phi_uses_[Representation::kSmi];
3275  }
3276  int int32_non_phi_uses() const {
3277  return non_phi_uses_[Representation::kInteger32];
3278  }
3279  int double_non_phi_uses() const {
3280  return non_phi_uses_[Representation::kDouble];
3281  }
3282  int tagged_indirect_uses() const {
3283  return indirect_uses_[Representation::kTagged];
3284  }
3285  int smi_indirect_uses() const {
3286  return indirect_uses_[Representation::kSmi];
3287  }
3288  int int32_indirect_uses() const {
3289  return indirect_uses_[Representation::kInteger32];
3290  }
3291  int double_indirect_uses() const {
3292  return indirect_uses_[Representation::kDouble];
3293  }
3294  int phi_id() { return phi_id_; }
3295 
3296  static HPhi* cast(HValue* value) {
3297  ASSERT(value->IsPhi());
3298  return reinterpret_cast<HPhi*>(value);
3299  }
3300  virtual Opcode opcode() const V8_OVERRIDE { return HValue::kPhi; }
3301 
3302  void SimplifyConstantInputs();
3303 
3304  // Marker value representing an invalid merge index.
3305  static const int kInvalidMergedIndex = -1;
3306 
3307  protected:
3308  virtual void DeleteFromGraph() V8_OVERRIDE;
3309  virtual void InternalSetOperandAt(int index, HValue* value) V8_OVERRIDE {
3310  inputs_[index] = value;
3311  }
3312 
3313  private:
3314  ZoneList<HValue*> inputs_;
3315  int merged_index_;
3316 
3317  int non_phi_uses_[Representation::kNumRepresentations];
3318  int indirect_uses_[Representation::kNumRepresentations];
3319  int phi_id_;
3320  InductionVariableData* induction_variable_data_;
3321 
3322  // TODO(titzer): we can't eliminate the receiver for generating backtraces
3323  virtual bool IsDeletable() const V8_OVERRIDE { return !IsReceiver(); }
3324 };
3325 
3326 
3327 // Common base class for HArgumentsObject and HCapturedObject.
3329  public:
3330  HDematerializedObject(int count, Zone* zone) : values_(count, zone) {}
3331 
3332  virtual int OperandCount() V8_FINAL V8_OVERRIDE { return values_.length(); }
3333  virtual HValue* OperandAt(int index) const V8_FINAL V8_OVERRIDE {
3334  return values_[index];
3335  }
3336 
3337  virtual bool HasEscapingOperandAt(int index) V8_FINAL V8_OVERRIDE {
3338  return false;
3339  }
3341  int index) V8_FINAL V8_OVERRIDE {
3342  return Representation::None();
3343  }
3344 
3345  protected:
3346  virtual void InternalSetOperandAt(int index,
3347  HValue* value) V8_FINAL V8_OVERRIDE {
3348  values_[index] = value;
3349  }
3350 
3351  // List of values tracked by this marker.
3353 };
3354 
3355 
3356 class HArgumentsObject V8_FINAL : public HDematerializedObject {
3357  public:
3358  static HArgumentsObject* New(Zone* zone, HValue* context, int count) {
3359  return new(zone) HArgumentsObject(count, zone);
3360  }
3361 
3362  // The values contain a list of all elements in the arguments object
3363  // including the receiver object, which is skipped when materializing.
3364  const ZoneList<HValue*>* arguments_values() const { return &values_; }
3365  int arguments_count() const { return values_.length(); }
3366 
3367  void AddArgument(HValue* argument, Zone* zone) {
3368  values_.Add(NULL, zone); // Resize list.
3369  SetOperandAt(values_.length() - 1, argument);
3370  }
3371 
3372  DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
3373 
3374  private:
3375  HArgumentsObject(int count, Zone* zone)
3376  : HDematerializedObject(count, zone) {
3377  set_representation(Representation::Tagged());
3378  SetFlag(kIsArguments);
3379  }
3380 
3381  virtual bool IsDeletable() const V8_FINAL V8_OVERRIDE { return true; }
3382 };
3383 
3384 
3385 class HCapturedObject V8_FINAL : public HDematerializedObject {
3386  public:
3387  HCapturedObject(int length, int id, Zone* zone)
3388  : HDematerializedObject(length, zone), capture_id_(id) {
3389  set_representation(Representation::Tagged());
3390  values_.AddBlock(NULL, length, zone); // Resize list.
3391  }
3392 
3393  // The values contain a list of all in-object properties inside the
3394  // captured object and is index by field index. Properties in the
3395  // properties or elements backing store are not tracked here.
3396  const ZoneList<HValue*>* values() const { return &values_; }
3397  int length() const { return values_.length(); }
3398  int capture_id() const { return capture_id_; }
3399 
3400  // Shortcut for the map value of this captured object.
3401  HValue* map_value() const { return values()->first(); }
3402 
3404  ASSERT(store->HasObservableSideEffects());
3405  ASSERT(store->IsStoreNamedField());
3406  changes_flags_.Add(store->ChangesFlags());
3407  }
3408 
3409  // Replay effects of this instruction on the given environment.
3410  void ReplayEnvironment(HEnvironment* env);
3411 
3412  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3413 
3414  DECLARE_CONCRETE_INSTRUCTION(CapturedObject)
3415 
3416  private:
3417  int capture_id_;
3418 
3419  // Note that we cannot DCE captured objects as they are used to replay
3420  // the environment. This method is here as an explicit reminder.
3421  // TODO(mstarzinger): Turn HSimulates into full snapshots maybe?
3422  virtual bool IsDeletable() const V8_FINAL V8_OVERRIDE { return false; }
3423 };
3424 
3425 
3426 class HConstant V8_FINAL : public HTemplateInstruction<0> {
3427  public:
3429  DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation);
3430  DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double);
3431  DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle<Object>);
3432  DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);
3433 
3434  static HConstant* CreateAndInsertAfter(Zone* zone,
3435  HValue* context,
3436  int32_t value,
3437  Representation representation,
3438  HInstruction* instruction) {
3439  return instruction->Append(HConstant::New(
3440  zone, context, value, representation));
3441  }
3442 
3443  static HConstant* CreateAndInsertBefore(Zone* zone,
3444  HValue* context,
3445  int32_t value,
3446  Representation representation,
3447  HInstruction* instruction) {
3448  return instruction->Prepend(HConstant::New(
3449  zone, context, value, representation));
3450  }
3451 
3452  static HConstant* CreateAndInsertBefore(Zone* zone,
3453  Unique<Object> unique,
3454  bool is_not_in_new_space,
3455  HInstruction* instruction) {
3456  return instruction->Prepend(new(zone) HConstant(
3457  unique, Representation::Tagged(), HType::Tagged(),
3458  is_not_in_new_space, false, false, kUnknownInstanceType));
3459  }
3460 
3462  if (object_.handle().is_null()) {
3463  // Default arguments to is_not_in_new_space depend on this heap number
3464  // to be tenured so that it's guaranteed not to be located in new space.
3465  object_ = Unique<Object>::CreateUninitialized(
3466  isolate->factory()->NewNumber(double_value_, TENURED));
3467  }
3469  ASSERT(has_int32_value_ || !object_.handle()->IsSmi());
3470  return object_.handle();
3471  }
3472 
3473  bool HasMap(Handle<Map> map) {
3474  Handle<Object> constant_object = handle(map->GetIsolate());
3475  return constant_object->IsHeapObject() &&
3476  Handle<HeapObject>::cast(constant_object)->map() == *map;
3477  }
3478 
3479  bool IsSpecialDouble() const {
3480  return has_double_value_ &&
3481  (BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) ||
3482  FixedDoubleArray::is_the_hole_nan(double_value_) ||
3483  std::isnan(double_value_));
3484  }
3485 
3486  bool NotInNewSpace() const {
3487  return is_not_in_new_space_;
3488  }
3489 
3490  bool ImmortalImmovable() const;
3491 
3492  bool IsCell() const {
3493  return instance_type_ == CELL_TYPE || instance_type_ == PROPERTY_CELL_TYPE;
3494  }
3495 
3497  return Representation::None();
3498  }
3499 
3501  if (HasSmiValue() && SmiValuesAre31Bits()) return Representation::Smi();
3502  if (HasInteger32Value()) return Representation::Integer32();
3503  if (HasNumberValue()) return Representation::Double();
3504  if (HasExternalReferenceValue()) return Representation::External();
3505  return Representation::Tagged();
3506  }
3507 
3508  virtual bool EmitAtUses() V8_OVERRIDE;
3509  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3510  HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
3511  Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone);
3512  Maybe<HConstant*> CopyToTruncatedNumber(Zone* zone);
3513  bool HasInteger32Value() const { return has_int32_value_; }
3515  ASSERT(HasInteger32Value());
3516  return int32_value_;
3517  }
3518  bool HasSmiValue() const { return has_smi_value_; }
3519  bool HasDoubleValue() const { return has_double_value_; }
3520  double DoubleValue() const {
3521  ASSERT(HasDoubleValue());
3522  return double_value_;
3523  }
3524  bool IsTheHole() const {
3525  if (HasDoubleValue() && FixedDoubleArray::is_the_hole_nan(double_value_)) {
3526  return true;
3527  }
3528  return object_.IsKnownGlobal(isolate()->heap()->the_hole_value());
3529  }
3530  bool HasNumberValue() const { return has_double_value_; }
3532  ASSERT(HasNumberValue());
3533  // Irrespective of whether a numeric HConstant can be safely
3534  // represented as an int32, we store the (in some cases lossy)
3535  // representation of the number in int32_value_.
3536  return int32_value_;
3537  }
3538  bool HasStringValue() const {
3539  if (has_double_value_ || has_int32_value_) return false;
3540  ASSERT(!object_.handle().is_null());
3541  return instance_type_ < FIRST_NONSTRING_TYPE;
3542  }
3544  ASSERT(HasStringValue());
3545  return Handle<String>::cast(object_.handle());
3546  }
3548  return HasStringValue() && StringShape(instance_type_).IsInternalized();
3549  }
3550 
3552  return has_external_reference_value_;
3553  }
3554  ExternalReference ExternalReferenceValue() const {
3555  return external_reference_value_;
3556  }
3557 
3558  bool HasBooleanValue() const { return type_.IsBoolean(); }
3559  bool BooleanValue() const { return boolean_value_; }
3560  bool IsUndetectable() const { return is_undetectable_; }
3561  InstanceType GetInstanceType() const { return instance_type_; }
3562 
3563  virtual intptr_t Hashcode() V8_OVERRIDE {
3564  if (has_int32_value_) {
3565  return static_cast<intptr_t>(int32_value_);
3566  } else if (has_double_value_) {
3567  return static_cast<intptr_t>(BitCast<int64_t>(double_value_));
3568  } else if (has_external_reference_value_) {
3569  return reinterpret_cast<intptr_t>(external_reference_value_.address());
3570  } else {
3571  ASSERT(!object_.handle().is_null());
3572  return object_.Hashcode();
3573  }
3574  }
3575 
3577  if (!has_double_value_ && !has_external_reference_value_) {
3578  ASSERT(!object_.handle().is_null());
3579  object_ = Unique<Object>(object_.handle());
3580  }
3581  }
3582 
3583  Unique<Object> GetUnique() const {
3584  return object_;
3585  }
3586 
3587  bool EqualsUnique(Unique<Object> other) const {
3588  return object_.IsInitialized() && object_ == other;
3589  }
3590 
3591  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
3592  HConstant* other_constant = HConstant::cast(other);
3593  if (has_int32_value_) {
3594  return other_constant->has_int32_value_ &&
3595  int32_value_ == other_constant->int32_value_;
3596  } else if (has_double_value_) {
3597  return other_constant->has_double_value_ &&
3598  BitCast<int64_t>(double_value_) ==
3599  BitCast<int64_t>(other_constant->double_value_);
3600  } else if (has_external_reference_value_) {
3601  return other_constant->has_external_reference_value_ &&
3602  external_reference_value_ ==
3603  other_constant->external_reference_value_;
3604  } else {
3605  if (other_constant->has_int32_value_ ||
3606  other_constant->has_double_value_ ||
3607  other_constant->has_external_reference_value_) {
3608  return false;
3609  }
3610  ASSERT(!object_.handle().is_null());
3611  return other_constant->object_ == object_;
3612  }
3613  }
3614 
3615 #ifdef DEBUG
3616  virtual void Verify() V8_OVERRIDE { }
3617 #endif
3618 
3620 
3621  protected:
3622  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
3623 
3624  private:
3625  friend class HGraph;
3626  HConstant(Handle<Object> handle, Representation r = Representation::None());
3627  HConstant(int32_t value,
3628  Representation r = Representation::None(),
3629  bool is_not_in_new_space = true,
3630  Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3631  HConstant(double value,
3632  Representation r = Representation::None(),
3633  bool is_not_in_new_space = true,
3634  Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3635  HConstant(Unique<Object> unique,
3636  Representation r,
3637  HType type,
3638  bool is_not_in_new_space,
3639  bool boolean_value,
3640  bool is_undetectable,
3641  InstanceType instance_type);
3642 
3643  explicit HConstant(ExternalReference reference);
3644 
3645  void Initialize(Representation r);
3646 
3647  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
3648 
3649  // If this is a numerical constant, object_ either points to the
3650  // HeapObject the constant originated from or is null. If the
3651  // constant is non-numeric, object_ always points to a valid
3652  // constant HeapObject.
3653  Unique<Object> object_;
3654 
3655  // We store the HConstant in the most specific form safely possible.
3656  // The two flags, has_int32_value_ and has_double_value_ tell us if
3657  // int32_value_ and double_value_ hold valid, safe representations
3658  // of the constant. has_int32_value_ implies has_double_value_ but
3659  // not the converse.
3660  bool has_smi_value_ : 1;
3661  bool has_int32_value_ : 1;
3662  bool has_double_value_ : 1;
3663  bool has_external_reference_value_ : 1;
3664  bool is_not_in_new_space_ : 1;
3665  bool boolean_value_ : 1;
3666  bool is_undetectable_: 1;
3667  int32_t int32_value_;
3668  double double_value_;
3669  ExternalReference external_reference_value_;
3670 
3671  static const InstanceType kUnknownInstanceType = FILLER_TYPE;
3672  InstanceType instance_type_;
3673 };
3674 
3675 
3677  public:
3678  HBinaryOperation(HValue* context, HValue* left, HValue* right,
3679  HType type = HType::Tagged())
3680  : HTemplateInstruction<3>(type),
3681  observed_output_representation_(Representation::None()) {
3682  ASSERT(left != NULL && right != NULL);
3683  SetOperandAt(0, context);
3684  SetOperandAt(1, left);
3685  SetOperandAt(2, right);
3686  observed_input_representation_[0] = Representation::None();
3687  observed_input_representation_[1] = Representation::None();
3688  }
3689 
3690  HValue* context() const { return OperandAt(0); }
3691  HValue* left() const { return OperandAt(1); }
3692  HValue* right() const { return OperandAt(2); }
3693 
3694  // True if switching left and right operands likely generates better code.
3696  if (!IsCommutative()) return false;
3697 
3698  // Constant operands are better off on the right, they can be inlined in
3699  // many situations on most platforms.
3700  if (left()->IsConstant()) return true;
3701  if (right()->IsConstant()) return false;
3702 
3703  // Otherwise, if there is only one use of the right operand, it would be
3704  // better off on the left for platforms that only have 2-arg arithmetic
3705  // ops (e.g ia32, x64) that clobber the left operand.
3706  return right()->UseCount() == 1;
3707  }
3708 
3710  return AreOperandsBetterSwitched() ? right() : left();
3711  }
3712 
3714  return AreOperandsBetterSwitched() ? left() : right();
3715  }
3716 
3718  ASSERT(index >= 1 && index <= 2);
3719  observed_input_representation_[index - 1] = rep;
3720  }
3721 
3723  observed_output_representation_ = observed;
3724  }
3725 
3727  if (index == 0) return Representation::Tagged();
3728  return observed_input_representation_[index - 1];
3729  }
3730 
3731  virtual void UpdateRepresentation(Representation new_rep,
3732  HInferRepresentationPhase* h_infer,
3733  const char* reason) V8_OVERRIDE {
3734  Representation rep = !FLAG_smi_binop && new_rep.IsSmi()
3735  ? Representation::Integer32() : new_rep;
3736  HValue::UpdateRepresentation(rep, h_infer, reason);
3737  }
3738 
3739  virtual void InferRepresentation(
3741  virtual Representation RepresentationFromInputs() V8_OVERRIDE;
3742  Representation RepresentationFromOutput();
3743  virtual void AssumeRepresentation(Representation r) V8_OVERRIDE;
3744 
3745  virtual bool IsCommutative() const { return false; }
3746 
3747  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3748 
3750  if (index == 0) return Representation::Tagged();
3751  return representation();
3752  }
3753 
3755  HSourcePosition left_pos,
3756  HSourcePosition right_pos) {
3757  set_operand_position(zone, 1, left_pos);
3758  set_operand_position(zone, 2, right_pos);
3759  }
3760 
3762  if (!right()->IsInteger32Constant()) return false;
3763  int32_t value = right()->GetInteger32Constant();
3764  return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
3765  }
3766 
3767  DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
3768 
3769  private:
3770  bool IgnoreObservedOutputRepresentation(Representation current_rep);
3771 
3772  Representation observed_input_representation_[2];
3773  Representation observed_output_representation_;
3774 };
3775 
3776 
3777 class HWrapReceiver V8_FINAL : public HTemplateInstruction<2> {
3778  public:
3779  DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
3780 
3781  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3782 
3784  return Representation::Tagged();
3785  }
3786 
3787  HValue* receiver() { return OperandAt(0); }
3788  HValue* function() { return OperandAt(1); }
3789 
3790  virtual HValue* Canonicalize() V8_OVERRIDE;
3791 
3792  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3793  bool known_function() const { return known_function_; }
3794 
3795  DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
3796 
3797  private:
3798  HWrapReceiver(HValue* receiver, HValue* function) {
3799  known_function_ = function->IsConstant() &&
3800  HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
3801  set_representation(Representation::Tagged());
3802  SetOperandAt(0, receiver);
3803  SetOperandAt(1, function);
3804  SetFlag(kUseGVN);
3805  }
3806 
3807  bool known_function_;
3808 };
3809 
3810 
3811 class HApplyArguments V8_FINAL : public HTemplateInstruction<4> {
3812  public:
3813  DECLARE_INSTRUCTION_FACTORY_P4(HApplyArguments, HValue*, HValue*, HValue*,
3814  HValue*);
3815 
3817  // The length is untagged, all other inputs are tagged.
3818  return (index == 2)
3821  }
3822 
3823  HValue* function() { return OperandAt(0); }
3824  HValue* receiver() { return OperandAt(1); }
3825  HValue* length() { return OperandAt(2); }
3826  HValue* elements() { return OperandAt(3); }
3827 
3828  DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
3829 
3830  private:
3831  HApplyArguments(HValue* function,
3832  HValue* receiver,
3833  HValue* length,
3834  HValue* elements) {
3835  set_representation(Representation::Tagged());
3836  SetOperandAt(0, function);
3837  SetOperandAt(1, receiver);
3838  SetOperandAt(2, length);
3839  SetOperandAt(3, elements);
3840  SetAllSideEffects();
3841  }
3842 };
3843 
3844 
3845 class HArgumentsElements V8_FINAL : public HTemplateInstruction<0> {
3846  public:
3847  DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
3848 
3849  DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
3850 
3851  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3852  return Representation::None();
3853  }
3854 
3855  bool from_inlined() const { return from_inlined_; }
3856 
3857  protected:
3858  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3859 
3860  private:
3861  explicit HArgumentsElements(bool from_inlined) : from_inlined_(from_inlined) {
3862  // The value produced by this instruction is a pointer into the stack
3863  // that looks as if it was a smi because of alignment.
3864  set_representation(Representation::Tagged());
3865  SetFlag(kUseGVN);
3866  }
3867 
3868  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
3869 
3870  bool from_inlined_;
3871 };
3872 
3873 
3874 class HArgumentsLength V8_FINAL : public HUnaryOperation {
3875  public:
3876  DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue*);
3877 
3879  return Representation::Tagged();
3880  }
3881 
3882  DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
3883 
3884  protected:
3885  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3886 
3887  private:
3888  explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
3889  set_representation(Representation::Integer32());
3890  SetFlag(kUseGVN);
3891  }
3892 
3893  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
3894 };
3895 
3896 
3897 class HAccessArgumentsAt V8_FINAL : public HTemplateInstruction<3> {
3898  public:
3899  DECLARE_INSTRUCTION_FACTORY_P3(HAccessArgumentsAt, HValue*, HValue*, HValue*);
3900 
3901  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3902 
3904  // The arguments elements is considered tagged.
3905  return index == 0
3908  }
3909 
3910  HValue* arguments() { return OperandAt(0); }
3911  HValue* length() { return OperandAt(1); }
3912  HValue* index() { return OperandAt(2); }
3913 
3914  DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
3915 
3916  private:
3917  HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
3918  set_representation(Representation::Tagged());
3919  SetFlag(kUseGVN);
3920  SetOperandAt(0, arguments);
3921  SetOperandAt(1, length);
3922  SetOperandAt(2, index);
3923  }
3924 
3925  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3926 };
3927 
3928 
3929 class HBoundsCheckBaseIndexInformation;
3930 
3931 
3932 class HBoundsCheck V8_FINAL : public HTemplateInstruction<2> {
3933  public:
3934  DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
3935 
3936  bool skip_check() const { return skip_check_; }
3937  void set_skip_check() { skip_check_ = true; }
3938 
3939  HValue* base() { return base_; }
3940  int offset() { return offset_; }
3941  int scale() { return scale_; }
3942 
3943  void ApplyIndexChange();
3945  ASSERT(base() == NULL);
3946 
3947  DecompositionResult decomposition;
3948  if (index()->TryDecompose(&decomposition)) {
3949  base_ = decomposition.base();
3950  offset_ = decomposition.offset();
3951  scale_ = decomposition.scale();
3952  return true;
3953  } else {
3954  base_ = index();
3955  offset_ = 0;
3956  scale_ = 0;
3957  return false;
3958  }
3959  }
3960 
3962  return representation();
3963  }
3964 
3965  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3966  virtual void InferRepresentation(
3968 
3969  HValue* index() { return OperandAt(0); }
3970  HValue* length() { return OperandAt(1); }
3971  bool allow_equality() { return allow_equality_; }
3972  void set_allow_equality(bool v) { allow_equality_ = v; }
3973 
3974  virtual int RedefinedOperandIndex() V8_OVERRIDE { return 0; }
3976  return skip_check();
3977  }
3978 
3979  DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
3980 
3981  protected:
3982  friend class HBoundsCheckBaseIndexInformation;
3983 
3984  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
3985 
3986  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3988  HValue* base_;
3989  int offset_;
3990  int scale_;
3992 
3993  private:
3994  // Normally HBoundsCheck should be created using the
3995  // HGraphBuilder::AddBoundsCheck() helper.
3996  // However when building stubs, where we know that the arguments are Int32,
3997  // it makes sense to invoke this constructor directly.
3998  HBoundsCheck(HValue* index, HValue* length)
3999  : skip_check_(false),
4000  base_(NULL), offset_(0), scale_(0),
4001  allow_equality_(false) {
4002  SetOperandAt(0, index);
4003  SetOperandAt(1, length);
4004  SetFlag(kFlexibleRepresentation);
4005  SetFlag(kUseGVN);
4006  }
4007 
4008  virtual bool IsDeletable() const V8_OVERRIDE {
4009  return skip_check() && !FLAG_debug_code;
4010  }
4011 };
4012 
4013 
4014 class HBoundsCheckBaseIndexInformation V8_FINAL
4015  : public HTemplateInstruction<2> {
4016  public:
4017  explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) {
4018  DecompositionResult decomposition;
4019  if (check->index()->TryDecompose(&decomposition)) {
4020  SetOperandAt(0, decomposition.base());
4021  SetOperandAt(1, check);
4022  } else {
4023  UNREACHABLE();
4024  }
4025  }
4026 
4027  HValue* base_index() { return OperandAt(0); }
4028  HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); }
4029 
4030  DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation)
4031 
4032  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4033  return representation();
4034  }
4035 
4036  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4037 
4038  virtual int RedefinedOperandIndex() V8_OVERRIDE { return 0; }
4039  virtual bool IsPurelyInformativeDefinition() V8_OVERRIDE { return true; }
4040 };
4041 
4042 
4044  public:
4045  HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
4046  HType type = HType::Tagged())
4047  : HBinaryOperation(context, left, right, type) {
4048  SetFlag(kFlexibleRepresentation);
4049  SetFlag(kTruncatingToInt32);
4050  SetFlag(kAllowUndefinedAsNaN);
4051  SetAllSideEffects();
4052  }
4053 
4055  if (to.IsTagged() &&
4056  (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
4057  SetAllSideEffects();
4058  ClearFlag(kUseGVN);
4059  } else {
4060  ClearAllSideEffects();
4061  SetFlag(kUseGVN);
4062  }
4063  if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
4064  }
4065 
4066  virtual void UpdateRepresentation(Representation new_rep,
4067  HInferRepresentationPhase* h_infer,
4068  const char* reason) V8_OVERRIDE {
4069  // We only generate either int32 or generic tagged bitwise operations.
4070  if (new_rep.IsDouble()) new_rep = Representation::Integer32();
4071  HBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4072  }
4073 
4076  if (r.IsDouble()) return Representation::Integer32();
4077  return r;
4078  }
4079 
4081  if (observed.IsDouble()) observed = Representation::Integer32();
4083  }
4084 
4085  DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
4086 
4087  private:
4088  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4089 };
4090 
4091 
4092 class HMathFloorOfDiv V8_FINAL : public HBinaryOperation {
4093  public:
4095  HValue*,
4096  HValue*);
4097 
4098  DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
4099 
4100  protected:
4101  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4102 
4103  private:
4104  HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
4105  : HBinaryOperation(context, left, right) {
4106  set_representation(Representation::Integer32());
4107  SetFlag(kUseGVN);
4108  SetFlag(kCanOverflow);
4109  SetFlag(kCanBeDivByZero);
4110  SetFlag(kLeftCanBeMinInt);
4111  SetFlag(kLeftCanBeNegative);
4112  SetFlag(kLeftCanBePositive);
4113  SetFlag(kAllowUndefinedAsNaN);
4114  }
4115 
4116  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4117 
4118  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4119 };
4120 
4121 
4123  public:
4125  : HBinaryOperation(context, left, right, HType::TaggedNumber()) {
4126  SetAllSideEffects();
4127  SetFlag(kFlexibleRepresentation);
4128  SetFlag(kAllowUndefinedAsNaN);
4129  }
4130 
4132  if (to.IsTagged() &&
4133  (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
4134  SetAllSideEffects();
4135  ClearFlag(kUseGVN);
4136  } else {
4137  ClearAllSideEffects();
4138  SetFlag(kUseGVN);
4139  }
4140  if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
4141  }
4142 
4143  DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
4144 
4145  private:
4146  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4147 };
4148 
4149 
4150 class HCompareGeneric V8_FINAL : public HBinaryOperation {
4151  public:
4152  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCompareGeneric, HValue*,
4153  HValue*, Token::Value);
4154 
4156  return index == 0
4158  : representation();
4159  }
4160 
4161  Token::Value token() const { return token_; }
4162  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4163 
4164  DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
4165 
4166  private:
4167  HCompareGeneric(HValue* context,
4168  HValue* left,
4169  HValue* right,
4170  Token::Value token)
4171  : HBinaryOperation(context, left, right, HType::Boolean()),
4172  token_(token) {
4173  ASSERT(Token::IsCompareOp(token));
4174  set_representation(Representation::Tagged());
4175  SetAllSideEffects();
4176  }
4177 
4178  Token::Value token_;
4179 };
4180 
4181 
4183  public:
4185  HValue*, HValue*, Token::Value);
4188  HBasicBlock*, HBasicBlock*);
4189 
4190  HValue* left() { return OperandAt(0); }
4191  HValue* right() { return OperandAt(1); }
4192  Token::Value token() const { return token_; }
4193 
4195  Representation right) {
4196  observed_input_representation_[0] = left;
4197  observed_input_representation_[1] = right;
4198  }
4199 
4200  virtual void InferRepresentation(
4202 
4204  return representation();
4205  }
4207  return observed_input_representation_[index];
4208  }
4209  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4210 
4212  HSourcePosition left_pos,
4213  HSourcePosition right_pos) {
4214  set_operand_position(zone, 0, left_pos);
4215  set_operand_position(zone, 1, right_pos);
4216  }
4217 
4218  DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
4219 
4220  private:
4222  HValue* right,
4223  Token::Value token,
4224  HBasicBlock* true_target = NULL,
4225  HBasicBlock* false_target = NULL)
4226  : token_(token) {
4227  SetFlag(kFlexibleRepresentation);
4228  ASSERT(Token::IsCompareOp(token));
4229  SetOperandAt(0, left);
4230  SetOperandAt(1, right);
4231  SetSuccessorAt(0, true_target);
4232  SetSuccessorAt(1, false_target);
4233  }
4234 
4235  Representation observed_input_representation_[2];
4236  Token::Value token_;
4237 };
4238 
4239 
4240 class HCompareHoleAndBranch V8_FINAL : public HUnaryControlInstruction {
4241  public:
4242  DECLARE_INSTRUCTION_FACTORY_P1(HCompareHoleAndBranch, HValue*);
4243  DECLARE_INSTRUCTION_FACTORY_P3(HCompareHoleAndBranch, HValue*,
4244  HBasicBlock*, HBasicBlock*);
4245 
4246  virtual void InferRepresentation(
4247  HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4248 
4250  return representation();
4251  }
4252 
4253  DECLARE_CONCRETE_INSTRUCTION(CompareHoleAndBranch)
4254 
4255  private:
4256  HCompareHoleAndBranch(HValue* value,
4257  HBasicBlock* true_target = NULL,
4258  HBasicBlock* false_target = NULL)
4259  : HUnaryControlInstruction(value, true_target, false_target) {
4260  SetFlag(kFlexibleRepresentation);
4261  SetFlag(kAllowUndefinedAsNaN);
4262  }
4263 };
4264 
4265 
4266 class HCompareMinusZeroAndBranch V8_FINAL : public HUnaryControlInstruction {
4267  public:
4268  DECLARE_INSTRUCTION_FACTORY_P1(HCompareMinusZeroAndBranch, HValue*);
4269 
4270  virtual void InferRepresentation(
4271  HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4272 
4274  return representation();
4275  }
4276 
4277  virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4278 
4279  DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch)
4280 
4281  private:
4282  explicit HCompareMinusZeroAndBranch(HValue* value)
4283  : HUnaryControlInstruction(value, NULL, NULL) {
4284  }
4285 };
4286 
4287 
4289  public:
4292  HBasicBlock*, HBasicBlock*);
4293 
4294  virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4295 
4296  static const int kNoKnownSuccessorIndex = -1;
4297  int known_successor_index() const { return known_successor_index_; }
4298  void set_known_successor_index(int known_successor_index) {
4299  known_successor_index_ = known_successor_index;
4300  }
4301 
4302  HValue* left() { return OperandAt(0); }
4303  HValue* right() { return OperandAt(1); }
4304 
4305  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4306 
4308  return Representation::Tagged();
4309  }
4310 
4312  return Representation::Tagged();
4313  }
4314 
4315  DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
4316 
4317  private:
4319  HValue* right,
4320  HBasicBlock* true_target = NULL,
4321  HBasicBlock* false_target = NULL)
4322  : known_successor_index_(kNoKnownSuccessorIndex) {
4323  ASSERT(!left->IsConstant() ||
4324  (!HConstant::cast(left)->HasInteger32Value() ||
4325  HConstant::cast(left)->HasSmiValue()));
4326  ASSERT(!right->IsConstant() ||
4327  (!HConstant::cast(right)->HasInteger32Value() ||
4328  HConstant::cast(right)->HasSmiValue()));
4329  SetOperandAt(0, left);
4330  SetOperandAt(1, right);
4331  SetSuccessorAt(0, true_target);
4332  SetSuccessorAt(1, false_target);
4333  }
4334 
4335  int known_successor_index_;
4336 };
4337 
4338 
4339 class HIsObjectAndBranch V8_FINAL : public HUnaryControlInstruction {
4340  public:
4341  DECLARE_INSTRUCTION_FACTORY_P1(HIsObjectAndBranch, HValue*);
4342  DECLARE_INSTRUCTION_FACTORY_P3(HIsObjectAndBranch, HValue*,
4343  HBasicBlock*, HBasicBlock*);
4344 
4346  return Representation::Tagged();
4347  }
4348 
4349  virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4350 
4351  DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch)
4352 
4353  private:
4354  HIsObjectAndBranch(HValue* value,
4355  HBasicBlock* true_target = NULL,
4356  HBasicBlock* false_target = NULL)
4357  : HUnaryControlInstruction(value, true_target, false_target) {}
4358 };
4359 
4360 
4361 class HIsStringAndBranch V8_FINAL : public HUnaryControlInstruction {
4362  public:
4363  DECLARE_INSTRUCTION_FACTORY_P1(HIsStringAndBranch, HValue*);
4364  DECLARE_INSTRUCTION_FACTORY_P3(HIsStringAndBranch, HValue*,
4365  HBasicBlock*, HBasicBlock*);
4366 
4368  return Representation::Tagged();
4369  }
4370 
4371  virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4372 
4373  DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
4374 
4375  protected:
4376  virtual int RedefinedOperandIndex() { return 0; }
4377 
4378  private:
4379  HIsStringAndBranch(HValue* value,
4380  HBasicBlock* true_target = NULL,
4381  HBasicBlock* false_target = NULL)
4382  : HUnaryControlInstruction(value, true_target, false_target) {}
4383 };
4384 
4385 
4386 class HIsSmiAndBranch V8_FINAL : public HUnaryControlInstruction {
4387  public:
4388  DECLARE_INSTRUCTION_FACTORY_P1(HIsSmiAndBranch, HValue*);
4389  DECLARE_INSTRUCTION_FACTORY_P3(HIsSmiAndBranch, HValue*,
4390  HBasicBlock*, HBasicBlock*);
4391 
4392  DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
4393 
4394  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4395  return Representation::Tagged();
4396  }
4397 
4398  protected:
4399  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4400  virtual int RedefinedOperandIndex() { return 0; }
4401 
4402  private:
4403  HIsSmiAndBranch(HValue* value,
4404  HBasicBlock* true_target = NULL,
4405  HBasicBlock* false_target = NULL)
4406  : HUnaryControlInstruction(value, true_target, false_target) {
4407  set_representation(Representation::Tagged());
4408  }
4409 };
4410 
4411 
4412 class HIsUndetectableAndBranch V8_FINAL : public HUnaryControlInstruction {
4413  public:
4414  DECLARE_INSTRUCTION_FACTORY_P1(HIsUndetectableAndBranch, HValue*);
4415  DECLARE_INSTRUCTION_FACTORY_P3(HIsUndetectableAndBranch, HValue*,
4416  HBasicBlock*, HBasicBlock*);
4417 
4419  return Representation::Tagged();
4420  }
4421 
4422  virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4423 
4424  DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
4425 
4426  private:
4427  HIsUndetectableAndBranch(HValue* value,
4428  HBasicBlock* true_target = NULL,
4429  HBasicBlock* false_target = NULL)
4430  : HUnaryControlInstruction(value, true_target, false_target) {}
4431 };
4432 
4433 
4435  public:
4437  HValue*,
4438  HValue*,
4439  Token::Value);
4440 
4441  HValue* context() { return OperandAt(0); }
4442  HValue* left() { return OperandAt(1); }
4443  HValue* right() { return OperandAt(2); }
4444  Token::Value token() const { return token_; }
4445 
4446  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4447 
4449  return Representation::Tagged();
4450  }
4451 
4453  return Representation::Tagged();
4454  }
4455 
4456  DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
4457 
4458  private:
4460  HValue* left,
4461  HValue* right,
4462  Token::Value token)
4463  : token_(token) {
4464  ASSERT(Token::IsCompareOp(token));
4465  SetOperandAt(0, context);
4466  SetOperandAt(1, left);
4467  SetOperandAt(2, right);
4468  set_representation(Representation::Tagged());
4469  SetChangesFlag(kNewSpacePromotion);
4470  }
4471 
4472  Token::Value token_;
4473 };
4474 
4475 
4477  public:
4479 
4481  return Representation::None();
4482  }
4483 
4484  DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch)
4485  private:
4487 };
4488 
4489 
4490 class HHasInstanceTypeAndBranch V8_FINAL : public HUnaryControlInstruction {
4491  public:
4493  HHasInstanceTypeAndBranch, HValue*, InstanceType);
4495  HHasInstanceTypeAndBranch, HValue*, InstanceType, InstanceType);
4496 
4497  InstanceType from() { return from_; }
4498  InstanceType to() { return to_; }
4499 
4500  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4501 
4503  return Representation::Tagged();
4504  }
4505 
4506  virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4507 
4508  DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
4509 
4510  private:
4511  HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
4512  : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
4513  HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
4514  : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
4515  ASSERT(to == LAST_TYPE); // Others not implemented yet in backend.
4516  }
4517 
4518  InstanceType from_;
4519  InstanceType to_; // Inclusive range, not all combinations work.
4520 };
4521 
4522 
4523 class HHasCachedArrayIndexAndBranch V8_FINAL : public HUnaryControlInstruction {
4524  public:
4525  DECLARE_INSTRUCTION_FACTORY_P1(HHasCachedArrayIndexAndBranch, HValue*);
4526 
4528  return Representation::Tagged();
4529  }
4530 
4531  DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
4532  private:
4533  explicit HHasCachedArrayIndexAndBranch(HValue* value)
4534  : HUnaryControlInstruction(value, NULL, NULL) { }
4535 };
4536 
4537 
4538 class HGetCachedArrayIndex V8_FINAL : public HUnaryOperation {
4539  public:
4540  DECLARE_INSTRUCTION_FACTORY_P1(HGetCachedArrayIndex, HValue*);
4541 
4543  return Representation::Tagged();
4544  }
4545 
4546  DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
4547 
4548  protected:
4549  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4550 
4551  private:
4552  explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
4553  set_representation(Representation::Tagged());
4554  SetFlag(kUseGVN);
4555  }
4556 
4557  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4558 };
4559 
4560 
4561 class HClassOfTestAndBranch V8_FINAL : public HUnaryControlInstruction {
4562  public:
4563  DECLARE_INSTRUCTION_FACTORY_P2(HClassOfTestAndBranch, HValue*,
4564  Handle<String>);
4565 
4566  DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
4567 
4568  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4569  return Representation::Tagged();
4570  }
4571 
4572  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4573 
4574  Handle<String> class_name() const { return class_name_; }
4575 
4576  private:
4577  HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
4578  : HUnaryControlInstruction(value, NULL, NULL),
4579  class_name_(class_name) { }
4580 
4581  Handle<String> class_name_;
4582 };
4583 
4584 
4585 class HTypeofIsAndBranch V8_FINAL : public HUnaryControlInstruction {
4586  public:
4587  DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle<String>);
4588 
4589  Handle<String> type_literal() { return type_literal_.handle(); }
4590  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4591 
4592  DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
4593 
4594  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4595  return Representation::None();
4596  }
4597 
4598  virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4599 
4601  type_literal_ = Unique<String>(type_literal_.handle());
4602  }
4603 
4604  private:
4605  HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
4606  : HUnaryControlInstruction(value, NULL, NULL),
4607  type_literal_(Unique<String>::CreateUninitialized(type_literal)) { }
4608 
4609  Unique<String> type_literal_;
4610 };
4611 
4612 
4613 class HInstanceOf V8_FINAL : public HBinaryOperation {
4614  public:
4615  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOf, HValue*, HValue*);
4616 
4618  return Representation::Tagged();
4619  }
4620 
4621  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4622 
4623  DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
4624 
4625  private:
4626  HInstanceOf(HValue* context, HValue* left, HValue* right)
4627  : HBinaryOperation(context, left, right, HType::Boolean()) {
4628  set_representation(Representation::Tagged());
4629  SetAllSideEffects();
4630  }
4631 };
4632 
4633 
4634 class HInstanceOfKnownGlobal V8_FINAL : public HTemplateInstruction<2> {
4635  public:
4636  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOfKnownGlobal,
4637  HValue*,
4638  Handle<JSFunction>);
4639 
4640  HValue* context() { return OperandAt(0); }
4641  HValue* left() { return OperandAt(1); }
4642  Handle<JSFunction> function() { return function_; }
4643 
4645  return Representation::Tagged();
4646  }
4647 
4648  DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal)
4649 
4650  private:
4651  HInstanceOfKnownGlobal(HValue* context,
4652  HValue* left,
4653  Handle<JSFunction> right)
4654  : HTemplateInstruction<2>(HType::Boolean()), function_(right) {
4655  SetOperandAt(0, context);
4656  SetOperandAt(1, left);
4657  set_representation(Representation::Tagged());
4658  SetAllSideEffects();
4659  }
4660 
4661  Handle<JSFunction> function_;
4662 };
4663 
4664 
4665 class HPower V8_FINAL : public HTemplateInstruction<2> {
4666  public:
4667  static HInstruction* New(Zone* zone,
4668  HValue* context,
4669  HValue* left,
4670  HValue* right);
4671 
4672  HValue* left() { return OperandAt(0); }
4673  HValue* right() const { return OperandAt(1); }
4674 
4676  return index == 0
4679  }
4681  return RequiredInputRepresentation(index);
4682  }
4683 
4685 
4686  protected:
4687  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4688 
4689  private:
4690  HPower(HValue* left, HValue* right) {
4691  SetOperandAt(0, left);
4692  SetOperandAt(1, right);
4693  set_representation(Representation::Double());
4694  SetFlag(kUseGVN);
4695  SetChangesFlag(kNewSpacePromotion);
4696  }
4697 
4698  virtual bool IsDeletable() const V8_OVERRIDE {
4699  return !right()->representation().IsTagged();
4700  }
4701 };
4702 
4703 
4704 class HAdd V8_FINAL : public HArithmeticBinaryOperation {
4705  public:
4706  static HInstruction* New(Zone* zone,
4707  HValue* context,
4708  HValue* left,
4709  HValue* right);
4710 
4711  // Add is only commutative if two integer values are added and not if two
4712  // tagged values are added (because it might be a String concatenation).
4713  // We also do not commute (pointer + offset).
4714  virtual bool IsCommutative() const V8_OVERRIDE {
4715  return !representation().IsTagged() && !representation().IsExternal();
4716  }
4717 
4718  virtual HValue* Canonicalize() V8_OVERRIDE;
4719 
4720  virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
4721  if (left()->IsInteger32Constant()) {
4722  decomposition->Apply(right(), left()->GetInteger32Constant());
4723  return true;
4724  } else if (right()->IsInteger32Constant()) {
4725  decomposition->Apply(left(), right()->GetInteger32Constant());
4726  return true;
4727  } else {
4728  return false;
4729  }
4730  }
4731 
4733  if (to.IsTagged() &&
4734  (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() ||
4735  left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) {
4736  SetAllSideEffects();
4737  ClearFlag(kUseGVN);
4738  } else {
4739  ClearAllSideEffects();
4740  SetFlag(kUseGVN);
4741  }
4742  if (to.IsTagged()) {
4743  SetChangesFlag(kNewSpacePromotion);
4744  ClearFlag(kAllowUndefinedAsNaN);
4745  }
4746  }
4747 
4748  virtual Representation RepresentationFromInputs() V8_OVERRIDE;
4749 
4750  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE;
4751 
4753 
4754  protected:
4755  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4756 
4757  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4758 
4759  private:
4760  HAdd(HValue* context, HValue* left, HValue* right)
4761  : HArithmeticBinaryOperation(context, left, right) {
4762  SetFlag(kCanOverflow);
4763  }
4764 };
4765 
4766 
4767 class HSub V8_FINAL : public HArithmeticBinaryOperation {
4768  public:
4769  static HInstruction* New(Zone* zone,
4770  HValue* context,
4771  HValue* left,
4772  HValue* right);
4773 
4774  virtual HValue* Canonicalize() V8_OVERRIDE;
4775 
4776  virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
4777  if (right()->IsInteger32Constant()) {
4778  decomposition->Apply(left(), -right()->GetInteger32Constant());
4779  return true;
4780  } else {
4781  return false;
4782  }
4783  }
4784 
4786 
4787  protected:
4788  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4789 
4790  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4791 
4792  private:
4793  HSub(HValue* context, HValue* left, HValue* right)
4794  : HArithmeticBinaryOperation(context, left, right) {
4795  SetFlag(kCanOverflow);
4796  }
4797 };
4798 
4799 
4800 class HMul V8_FINAL : public HArithmeticBinaryOperation {
4801  public:
4802  static HInstruction* New(Zone* zone,
4803  HValue* context,
4804  HValue* left,
4805  HValue* right);
4806 
4807  static HInstruction* NewImul(Zone* zone,
4808  HValue* context,
4809  HValue* left,
4810  HValue* right) {
4811  HInstruction* instr = HMul::New(zone, context, left, right);
4812  if (!instr->IsMul()) return instr;
4813  HMul* mul = HMul::cast(instr);
4814  // TODO(mstarzinger): Prevent bailout on minus zero for imul.
4815  mul->AssumeRepresentation(Representation::Integer32());
4816  mul->ClearFlag(HValue::kCanOverflow);
4817  return mul;
4818  }
4819 
4820  virtual HValue* Canonicalize() V8_OVERRIDE;
4821 
4822  // Only commutative if it is certain that not two objects are multiplicated.
4823  virtual bool IsCommutative() const V8_OVERRIDE {
4824  return !representation().IsTagged();
4825  }
4826 
4827  virtual void UpdateRepresentation(Representation new_rep,
4828  HInferRepresentationPhase* h_infer,
4829  const char* reason) V8_OVERRIDE {
4830  HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4831  }
4832 
4833  bool MulMinusOne();
4834 
4836 
4837  protected:
4838  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4839 
4840  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4841 
4842  private:
4843  HMul(HValue* context, HValue* left, HValue* right)
4844  : HArithmeticBinaryOperation(context, left, right) {
4845  SetFlag(kCanOverflow);
4846  }
4847 };
4848 
4849 
4850 class HMod V8_FINAL : public HArithmeticBinaryOperation {
4851  public:
4852  static HInstruction* New(Zone* zone,
4853  HValue* context,
4854  HValue* left,
4855  HValue* right);
4856 
4857  virtual HValue* Canonicalize() V8_OVERRIDE;
4858 
4859  virtual void UpdateRepresentation(Representation new_rep,
4860  HInferRepresentationPhase* h_infer,
4861  const char* reason) V8_OVERRIDE {
4862  if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4863  HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4864  }
4865 
4867 
4868  protected:
4869  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4870 
4871  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4872 
4873  private:
4874  HMod(HValue* context,
4875  HValue* left,
4876  HValue* right) : HArithmeticBinaryOperation(context, left, right) {
4877  SetFlag(kCanBeDivByZero);
4878  SetFlag(kCanOverflow);
4879  SetFlag(kLeftCanBeNegative);
4880  }
4881 };
4882 
4883 
4884 class HDiv V8_FINAL : public HArithmeticBinaryOperation {
4885  public:
4886  static HInstruction* New(Zone* zone,
4887  HValue* context,
4888  HValue* left,
4889  HValue* right);
4890 
4891  virtual HValue* Canonicalize() V8_OVERRIDE;
4892 
4893  virtual void UpdateRepresentation(Representation new_rep,
4894  HInferRepresentationPhase* h_infer,
4895  const char* reason) V8_OVERRIDE {
4896  if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4897  HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4898  }
4899 
4901 
4902  protected:
4903  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4904 
4905  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4906 
4907  private:
4908  HDiv(HValue* context, HValue* left, HValue* right)
4909  : HArithmeticBinaryOperation(context, left, right) {
4910  SetFlag(kCanBeDivByZero);
4911  SetFlag(kCanOverflow);
4912  }
4913 };
4914 
4915 
4916 class HMathMinMax V8_FINAL : public HArithmeticBinaryOperation {
4917  public:
4918  enum Operation { kMathMin, kMathMax };
4919 
4920  static HInstruction* New(Zone* zone,
4921  HValue* context,
4922  HValue* left,
4923  HValue* right,
4924  Operation op);
4925 
4927  return RequiredInputRepresentation(index);
4928  }
4929 
4930  virtual void InferRepresentation(
4932 
4934  Representation left_rep = left()->representation();
4935  Representation right_rep = right()->representation();
4937  result = result.generalize(left_rep);
4938  result = result.generalize(right_rep);
4939  if (result.IsTagged()) return Representation::Double();
4940  return result;
4941  }
4942 
4943  virtual bool IsCommutative() const V8_OVERRIDE { return true; }
4944 
4945  Operation operation() { return operation_; }
4946 
4947  DECLARE_CONCRETE_INSTRUCTION(MathMinMax)
4948 
4949  protected:
4950  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
4951  return other->IsMathMinMax() &&
4952  HMathMinMax::cast(other)->operation_ == operation_;
4953  }
4954 
4955  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4956 
4957  private:
4958  HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
4959  : HArithmeticBinaryOperation(context, left, right),
4960  operation_(op) { }
4961 
4962  Operation operation_;
4963 };
4964 
4965 
4966 class HBitwise V8_FINAL : public HBitwiseBinaryOperation {
4967  public:
4968  static HInstruction* New(Zone* zone,
4969  HValue* context,
4970  Token::Value op,
4971  HValue* left,
4972  HValue* right);
4973 
4974  Token::Value op() const { return op_; }
4975 
4976  virtual bool IsCommutative() const V8_OVERRIDE { return true; }
4977 
4978  virtual HValue* Canonicalize() V8_OVERRIDE;
4979 
4980  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4981 
4983 
4984  protected:
4985  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
4986  return op() == HBitwise::cast(other)->op();
4987  }
4988 
4989  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4990 
4991  private:
4992  HBitwise(HValue* context,
4993  Token::Value op,
4994  HValue* left,
4995  HValue* right)
4996  : HBitwiseBinaryOperation(context, left, right, HType::TaggedNumber()),
4997  op_(op) {
4998  ASSERT(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
4999  // BIT_AND with a smi-range positive value will always unset the
5000  // entire sign-extension of the smi-sign.
5001  if (op == Token::BIT_AND &&
5002  ((left->IsConstant() &&
5003  left->representation().IsSmi() &&
5004  HConstant::cast(left)->Integer32Value() >= 0) ||
5005  (right->IsConstant() &&
5006  right->representation().IsSmi() &&
5007  HConstant::cast(right)->Integer32Value() >= 0))) {
5008  SetFlag(kTruncatingToSmi);
5009  SetFlag(kTruncatingToInt32);
5010  // BIT_OR with a smi-range negative value will always set the entire
5011  // sign-extension of the smi-sign.
5012  } else if (op == Token::BIT_OR &&
5013  ((left->IsConstant() &&
5014  left->representation().IsSmi() &&
5015  HConstant::cast(left)->Integer32Value() < 0) ||
5016  (right->IsConstant() &&
5017  right->representation().IsSmi() &&
5018  HConstant::cast(right)->Integer32Value() < 0))) {
5019  SetFlag(kTruncatingToSmi);
5020  SetFlag(kTruncatingToInt32);
5021  }
5022  }
5023 
5024  Token::Value op_;
5025 };
5026 
5027 
5028 class HShl V8_FINAL : public HBitwiseBinaryOperation {
5029  public:
5030  static HInstruction* New(Zone* zone,
5031  HValue* context,
5032  HValue* left,
5033  HValue* right);
5034 
5035  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5036 
5037  virtual void UpdateRepresentation(Representation new_rep,
5038  HInferRepresentationPhase* h_infer,
5039  const char* reason) V8_OVERRIDE {
5040  if (new_rep.IsSmi() &&
5041  !(right()->IsInteger32Constant() &&
5042  right()->GetInteger32Constant() >= 0)) {
5043  new_rep = Representation::Integer32();
5044  }
5045  HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5046  }
5047 
5049 
5050  protected:
5051  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5052 
5053  private:
5054  HShl(HValue* context, HValue* left, HValue* right)
5055  : HBitwiseBinaryOperation(context, left, right) { }
5056 };
5057 
5058 
5059 class HShr V8_FINAL : public HBitwiseBinaryOperation {
5060  public:
5061  static HInstruction* New(Zone* zone,
5062  HValue* context,
5063  HValue* left,
5064  HValue* right);
5065 
5066  virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
5067  if (right()->IsInteger32Constant()) {
5068  if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
5069  // This is intended to look for HAdd and HSub, to handle compounds
5070  // like ((base + offset) >> scale) with one single decomposition.
5071  left()->TryDecompose(decomposition);
5072  return true;
5073  }
5074  }
5075  return false;
5076  }
5077 
5078  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5079 
5080  virtual void UpdateRepresentation(Representation new_rep,
5081  HInferRepresentationPhase* h_infer,
5082  const char* reason) V8_OVERRIDE {
5083  if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5084  HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5085  }
5086 
5088 
5089  protected:
5090  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5091 
5092  private:
5093  HShr(HValue* context, HValue* left, HValue* right)
5094  : HBitwiseBinaryOperation(context, left, right) { }
5095 };
5096 
5097 
5098 class HSar V8_FINAL : public HBitwiseBinaryOperation {
5099  public:
5100  static HInstruction* New(Zone* zone,
5101  HValue* context,
5102  HValue* left,
5103  HValue* right);
5104 
5105  virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
5106  if (right()->IsInteger32Constant()) {
5107  if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
5108  // This is intended to look for HAdd and HSub, to handle compounds
5109  // like ((base + offset) >> scale) with one single decomposition.
5110  left()->TryDecompose(decomposition);
5111  return true;
5112  }
5113  }
5114  return false;
5115  }
5116 
5117  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5118 
5119  virtual void UpdateRepresentation(Representation new_rep,
5120  HInferRepresentationPhase* h_infer,
5121  const char* reason) V8_OVERRIDE {
5122  if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5123  HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5124  }
5125 
5127 
5128  protected:
5129  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5130 
5131  private:
5132  HSar(HValue* context, HValue* left, HValue* right)
5133  : HBitwiseBinaryOperation(context, left, right) { }
5134 };
5135 
5136 
5137 class HRor V8_FINAL : public HBitwiseBinaryOperation {
5138  public:
5139  static HInstruction* New(Zone* zone,
5140  HValue* context,
5141  HValue* left,
5142  HValue* right) {
5143  return new(zone) HRor(context, left, right);
5144  }
5145 
5146  virtual void UpdateRepresentation(Representation new_rep,
5147  HInferRepresentationPhase* h_infer,
5148  const char* reason) V8_OVERRIDE {
5149  if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5150  HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5151  }
5152 
5154 
5155  protected:
5156  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5157 
5158  private:
5159  HRor(HValue* context, HValue* left, HValue* right)
5160  : HBitwiseBinaryOperation(context, left, right) {
5161  ChangeRepresentation(Representation::Integer32());
5162  }
5163 };
5164 
5165 
5166 class HOsrEntry V8_FINAL : public HTemplateInstruction<0> {
5167  public:
5168  DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId);
5169 
5170  BailoutId ast_id() const { return ast_id_; }
5171 
5173  return Representation::None();
5174  }
5175 
5177 
5178  private:
5179  explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
5180  SetChangesFlag(kOsrEntries);
5181  SetChangesFlag(kNewSpacePromotion);
5182  }
5183 
5184  BailoutId ast_id_;
5185 };
5186 
5187 
5188 class HParameter V8_FINAL : public HTemplateInstruction<0> {
5189  public:
5192  REGISTER_PARAMETER
5193  };
5194 
5195  DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned);
5196  DECLARE_INSTRUCTION_FACTORY_P2(HParameter, unsigned, ParameterKind);
5197  DECLARE_INSTRUCTION_FACTORY_P3(HParameter, unsigned, ParameterKind,
5198  Representation);
5199 
5200  unsigned index() const { return index_; }
5201  ParameterKind kind() const { return kind_; }
5202 
5203  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5204 
5206  return Representation::None();
5207  }
5208 
5209  DECLARE_CONCRETE_INSTRUCTION(Parameter)
5210 
5211  private:
5212  explicit HParameter(unsigned index,
5213  ParameterKind kind = STACK_PARAMETER)
5214  : index_(index),
5215  kind_(kind) {
5216  set_representation(Representation::Tagged());
5217  }
5218 
5219  explicit HParameter(unsigned index,
5220  ParameterKind kind,
5221  Representation r)
5222  : index_(index),
5223  kind_(kind) {
5224  set_representation(r);
5225  }
5226 
5227  unsigned index_;
5228  ParameterKind kind_;
5229 };
5230 
5231 
5232 class HCallStub V8_FINAL : public HUnaryCall {
5233  public:
5234  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallStub, CodeStub::Major, int);
5235  CodeStub::Major major_key() { return major_key_; }
5236 
5237  HValue* context() { return value(); }
5238 
5239  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5240 
5242 
5243  private:
5244  HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
5245  : HUnaryCall(context, argument_count),
5246  major_key_(major_key) {
5247  }
5248 
5249  CodeStub::Major major_key_;
5250 };
5251 
5252 
5253 class HUnknownOSRValue V8_FINAL : public HTemplateInstruction<0> {
5254  public:
5255  DECLARE_INSTRUCTION_FACTORY_P2(HUnknownOSRValue, HEnvironment*, int);
5256 
5257  virtual void PrintDataTo(StringStream* stream);
5258 
5260  return Representation::None();
5261  }
5262 
5263  void set_incoming_value(HPhi* value) { incoming_value_ = value; }
5264  HPhi* incoming_value() { return incoming_value_; }
5265  HEnvironment *environment() { return environment_; }
5266  int index() { return index_; }
5267 
5269  if (incoming_value_ == NULL) return Representation::None();
5270  return incoming_value_->KnownOptimalRepresentation();
5271  }
5272 
5273  DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
5274 
5275  private:
5276  HUnknownOSRValue(HEnvironment* environment, int index)
5277  : environment_(environment),
5278  index_(index),
5279  incoming_value_(NULL) {
5280  set_representation(Representation::Tagged());
5281  }
5282 
5283  HEnvironment* environment_;
5284  int index_;
5285  HPhi* incoming_value_;
5286 };
5287 
5288 
5289 class HLoadGlobalCell V8_FINAL : public HTemplateInstruction<0> {
5290  public:
5291  DECLARE_INSTRUCTION_FACTORY_P2(HLoadGlobalCell, Handle<Cell>,
5292  PropertyDetails);
5293 
5294  Unique<Cell> cell() const { return cell_; }
5295  bool RequiresHoleCheck() const;
5296 
5297  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5298 
5299  virtual intptr_t Hashcode() V8_OVERRIDE {
5300  return cell_.Hashcode();
5301  }
5302 
5304  cell_ = Unique<Cell>(cell_.handle());
5305  }
5306 
5308  return Representation::None();
5309  }
5310 
5311  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell)
5312 
5313  protected:
5314  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
5315  return cell_ == HLoadGlobalCell::cast(other)->cell_;
5316  }
5317 
5318  private:
5319  HLoadGlobalCell(Handle<Cell> cell, PropertyDetails details)
5320  : cell_(Unique<Cell>::CreateUninitialized(cell)), details_(details) {
5321  set_representation(Representation::Tagged());
5322  SetFlag(kUseGVN);
5323  SetDependsOnFlag(kGlobalVars);
5324  }
5325 
5326  virtual bool IsDeletable() const V8_OVERRIDE { return !RequiresHoleCheck(); }
5327 
5328  Unique<Cell> cell_;
5329  PropertyDetails details_;
5330 };
5331 
5332 
5333 class HLoadGlobalGeneric V8_FINAL : public HTemplateInstruction<2> {
5334  public:
5335  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadGlobalGeneric, HValue*,
5336  Handle<Object>, bool);
5337 
5338  HValue* context() { return OperandAt(0); }
5339  HValue* global_object() { return OperandAt(1); }
5340  Handle<Object> name() const { return name_; }
5341  bool for_typeof() const { return for_typeof_; }
5342 
5343  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5344 
5346  return Representation::Tagged();
5347  }
5348 
5349  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
5350 
5351  private:
5352  HLoadGlobalGeneric(HValue* context,
5353  HValue* global_object,
5354  Handle<Object> name,
5355  bool for_typeof)
5356  : name_(name),
5357  for_typeof_(for_typeof) {
5358  SetOperandAt(0, context);
5359  SetOperandAt(1, global_object);
5360  set_representation(Representation::Tagged());
5361  SetAllSideEffects();
5362  }
5363 
5364  Handle<Object> name_;
5365  bool for_typeof_;
5366 };
5367 
5368 
5369 class HAllocate V8_FINAL : public HTemplateInstruction<2> {
5370  public:
5372  InstanceType type2) {
5373  return ComputeFlags(TENURED, type1) == ComputeFlags(TENURED, type2) &&
5374  ComputeFlags(NOT_TENURED, type1) == ComputeFlags(NOT_TENURED, type2);
5375  }
5376 
5377  static HAllocate* New(Zone* zone,
5378  HValue* context,
5379  HValue* size,
5380  HType type,
5381  PretenureFlag pretenure_flag,
5382  InstanceType instance_type,
5383  Handle<AllocationSite> allocation_site =
5385  return new(zone) HAllocate(context, size, type, pretenure_flag,
5386  instance_type, allocation_site);
5387  }
5388 
5389  // Maximum instance size for which allocations will be inlined.
5390  static const int kMaxInlineSize = 64 * kPointerSize;
5391 
5392  HValue* context() { return OperandAt(0); }
5393  HValue* size() { return OperandAt(1); }
5394 
5396  if (index == 0) {
5397  return Representation::Tagged();
5398  } else {
5399  return Representation::Integer32();
5400  }
5401  }
5402 
5404  return known_initial_map_;
5405  }
5406 
5407  void set_known_initial_map(Handle<Map> known_initial_map) {
5408  known_initial_map_ = known_initial_map;
5409  }
5410 
5411  bool IsNewSpaceAllocation() const {
5412  return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
5413  }
5414 
5416  return (flags_ & ALLOCATE_IN_OLD_DATA_SPACE) != 0;
5417  }
5418 
5420  return (flags_ & ALLOCATE_IN_OLD_POINTER_SPACE) != 0;
5421  }
5422 
5424  return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
5425  }
5426 
5427  bool MustPrefillWithFiller() const {
5428  return (flags_ & PREFILL_WITH_FILLER) != 0;
5429  }
5430 
5432  flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
5433  }
5434 
5435  bool MustClearNextMapWord() const {
5436  return (flags_ & CLEAR_NEXT_MAP_WORD) != 0;
5437  }
5438 
5440  flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
5441  }
5442 
5443  virtual bool HandleSideEffectDominator(GVNFlag side_effect,
5444  HValue* dominator) V8_OVERRIDE;
5445 
5446  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5447 
5449 
5450  private:
5451  enum Flags {
5452  ALLOCATE_IN_NEW_SPACE = 1 << 0,
5453  ALLOCATE_IN_OLD_DATA_SPACE = 1 << 1,
5454  ALLOCATE_IN_OLD_POINTER_SPACE = 1 << 2,
5455  ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
5456  PREFILL_WITH_FILLER = 1 << 4,
5457  CLEAR_NEXT_MAP_WORD = 1 << 5
5458  };
5459 
5460  HAllocate(HValue* context,
5461  HValue* size,
5462  HType type,
5463  PretenureFlag pretenure_flag,
5464  InstanceType instance_type,
5465  Handle<AllocationSite> allocation_site =
5467  : HTemplateInstruction<2>(type),
5468  flags_(ComputeFlags(pretenure_flag, instance_type)),
5469  dominating_allocate_(NULL),
5470  filler_free_space_size_(NULL) {
5471  SetOperandAt(0, context);
5472  SetOperandAt(1, size);
5473  set_representation(Representation::Tagged());
5474  SetFlag(kTrackSideEffectDominators);
5475  SetChangesFlag(kNewSpacePromotion);
5476  SetDependsOnFlag(kNewSpacePromotion);
5477 
5478  if (FLAG_trace_pretenuring) {
5479  PrintF("HAllocate with AllocationSite %p %s\n",
5480  allocation_site.is_null()
5481  ? static_cast<void*>(NULL)
5482  : static_cast<void*>(*allocation_site),
5483  pretenure_flag == TENURED ? "tenured" : "not tenured");
5484  }
5485  }
5486 
5487  static Flags ComputeFlags(PretenureFlag pretenure_flag,
5488  InstanceType instance_type) {
5489  Flags flags = pretenure_flag == TENURED
5490  ? (Heap::TargetSpaceId(instance_type) == OLD_POINTER_SPACE
5491  ? ALLOCATE_IN_OLD_POINTER_SPACE : ALLOCATE_IN_OLD_DATA_SPACE)
5492  : ALLOCATE_IN_NEW_SPACE;
5493  if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
5494  flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED);
5495  }
5496  // We have to fill the allocated object with one word fillers if we do
5497  // not use allocation folding since some allocations may depend on each
5498  // other, i.e., have a pointer to each other. A GC in between these
5499  // allocations may leave such objects behind in a not completely initialized
5500  // state.
5501  if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
5502  flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER);
5503  }
5504  if (pretenure_flag == NOT_TENURED &&
5505  AllocationSite::CanTrack(instance_type)) {
5506  flags = static_cast<Flags>(flags | CLEAR_NEXT_MAP_WORD);
5507  }
5508  return flags;
5509  }
5510 
5511  void UpdateClearNextMapWord(bool clear_next_map_word) {
5512  flags_ = static_cast<Flags>(clear_next_map_word
5513  ? flags_ | CLEAR_NEXT_MAP_WORD
5514  : flags_ & ~CLEAR_NEXT_MAP_WORD);
5515  }
5516 
5517  void UpdateSize(HValue* size) {
5518  SetOperandAt(1, size);
5519  }
5520 
5521  HAllocate* GetFoldableDominator(HAllocate* dominator);
5522 
5523  void UpdateFreeSpaceFiller(int32_t filler_size);
5524 
5525  void CreateFreeSpaceFiller(int32_t filler_size);
5526 
5527  bool IsFoldable(HAllocate* allocate) {
5528  return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) ||
5529  (IsOldDataSpaceAllocation() && allocate->IsOldDataSpaceAllocation()) ||
5530  (IsOldPointerSpaceAllocation() &&
5531  allocate->IsOldPointerSpaceAllocation());
5532  }
5533 
5534  void ClearNextMapWord(int offset);
5535 
5536  Flags flags_;
5537  Handle<Map> known_initial_map_;
5538  HAllocate* dominating_allocate_;
5539  HStoreNamedField* filler_free_space_size_;
5540 };
5541 
5542 
5543 class HStoreCodeEntry V8_FINAL: public HTemplateInstruction<2> {
5544  public:
5545  static HStoreCodeEntry* New(Zone* zone,
5546  HValue* context,
5547  HValue* function,
5548  HValue* code) {
5549  return new(zone) HStoreCodeEntry(function, code);
5550  }
5551 
5553  return Representation::Tagged();
5554  }
5555 
5556  HValue* function() { return OperandAt(0); }
5557  HValue* code_object() { return OperandAt(1); }
5558 
5559  DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry)
5560 
5561  private:
5562  HStoreCodeEntry(HValue* function, HValue* code) {
5563  SetOperandAt(0, function);
5564  SetOperandAt(1, code);
5565  }
5566 };
5567 
5568 
5569 class HInnerAllocatedObject V8_FINAL : public HTemplateInstruction<2> {
5570  public:
5571  static HInnerAllocatedObject* New(Zone* zone,
5572  HValue* context,
5573  HValue* value,
5574  HValue* offset,
5575  HType type = HType::Tagged()) {
5576  return new(zone) HInnerAllocatedObject(value, offset, type);
5577  }
5578 
5579  HValue* base_object() { return OperandAt(0); }
5580  HValue* offset() { return OperandAt(1); }
5581 
5583  return index == 0 ? Representation::Tagged() : Representation::Integer32();
5584  }
5585 
5586  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5587 
5588  DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
5589 
5590  private:
5591  HInnerAllocatedObject(HValue* value,
5592  HValue* offset,
5593  HType type = HType::Tagged())
5594  : HTemplateInstruction<2>(type) {
5595  ASSERT(value->IsAllocate());
5596  SetOperandAt(0, value);
5597  SetOperandAt(1, offset);
5598  set_type(type);
5599  set_representation(Representation::Tagged());
5600  }
5601 };
5602 
5603 
5605  return !value->type().IsBoolean()
5606  && !value->type().IsSmi()
5607  && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
5608 }
5609 
5610 
5612  HValue* value,
5613  HValue* new_space_dominator) {
5614  while (object->IsInnerAllocatedObject()) {
5615  object = HInnerAllocatedObject::cast(object)->base_object();
5616  }
5617  if (object->IsConstant() && HConstant::cast(object)->IsCell()) {
5618  return false;
5619  }
5620  if (object->IsConstant() &&
5621  HConstant::cast(object)->HasExternalReferenceValue()) {
5622  // Stores to external references require no write barriers
5623  return false;
5624  }
5625  if (object != new_space_dominator) return true;
5626  if (object->IsAllocate()) {
5627  // Stores to new space allocations require no write barriers if the object
5628  // is the new space dominator.
5629  if (HAllocate::cast(object)->IsNewSpaceAllocation()) {
5630  return false;
5631  }
5632  // Likewise we don't need a write barrier if we store a value that
5633  // originates from the same allocation (via allocation folding).
5634  while (value->IsInnerAllocatedObject()) {
5635  value = HInnerAllocatedObject::cast(value)->base_object();
5636  }
5637  return object != value;
5638  }
5639  return true;
5640 }
5641 
5642 
5643 class HStoreGlobalCell V8_FINAL : public HUnaryOperation {
5644  public:
5645  DECLARE_INSTRUCTION_FACTORY_P3(HStoreGlobalCell, HValue*,
5646  Handle<PropertyCell>, PropertyDetails);
5647 
5648  Unique<PropertyCell> cell() const { return cell_; }
5650  return !details_.IsDontDelete() || details_.IsReadOnly();
5651  }
5653  return StoringValueNeedsWriteBarrier(value());
5654  }
5655 
5657  cell_ = Unique<PropertyCell>(cell_.handle());
5658  }
5659 
5661  return Representation::Tagged();
5662  }
5663  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5664 
5665  DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell)
5666 
5667  private:
5668  HStoreGlobalCell(HValue* value,
5669  Handle<PropertyCell> cell,
5670  PropertyDetails details)
5671  : HUnaryOperation(value),
5672  cell_(Unique<PropertyCell>::CreateUninitialized(cell)),
5673  details_(details) {
5674  SetChangesFlag(kGlobalVars);
5675  }
5676 
5677  Unique<PropertyCell> cell_;
5678  PropertyDetails details_;
5679 };
5680 
5681 
5682 class HLoadContextSlot V8_FINAL : public HUnaryOperation {
5683  public:
5684  enum Mode {
5685  // Perform a normal load of the context slot without checking its value.
5687  // Load and check the value of the context slot. Deoptimize if it's the
5688  // hole value. This is used for checking for loading of uninitialized
5689  // harmony bindings where we deoptimize into full-codegen generated code
5690  // which will subsequently throw a reference error.
5692  // Load and check the value of the context slot. Return undefined if it's
5693  // the hole value. This is used for non-harmony const assignments
5694  kCheckReturnUndefined
5695  };
5696 
5698  : HUnaryOperation(context), slot_index_(var->index()) {
5699  ASSERT(var->IsContextSlot());
5700  switch (var->mode()) {
5701  case LET:
5702  case CONST:
5703  mode_ = kCheckDeoptimize;
5704  break;
5705  case CONST_LEGACY:
5706  mode_ = kCheckReturnUndefined;
5707  break;
5708  default:
5709  mode_ = kNoCheck;
5710  }
5711  set_representation(Representation::Tagged());
5712  SetFlag(kUseGVN);
5713  SetDependsOnFlag(kContextSlots);
5714  }
5715 
5716  int slot_index() const { return slot_index_; }
5717  Mode mode() const { return mode_; }
5718 
5720  return mode_ == kCheckDeoptimize;
5721  }
5722 
5723  bool RequiresHoleCheck() const {
5724  return mode_ != kNoCheck;
5725  }
5726 
5728  return Representation::Tagged();
5729  }
5730 
5731  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5732 
5733  DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
5734 
5735  protected:
5736  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
5737  HLoadContextSlot* b = HLoadContextSlot::cast(other);
5738  return (slot_index() == b->slot_index());
5739  }
5740 
5741  private:
5742  virtual bool IsDeletable() const V8_OVERRIDE { return !RequiresHoleCheck(); }
5743 
5744  int slot_index_;
5745  Mode mode_;
5746 };
5747 
5748 
5749 class HStoreContextSlot V8_FINAL : public HTemplateInstruction<2> {
5750  public:
5751  enum Mode {
5752  // Perform a normal store to the context slot without checking its previous
5753  // value.
5754  kNoCheck,
5755  // Check the previous value of the context slot and deoptimize if it's the
5756  // hole value. This is used for checking for assignments to uninitialized
5757  // harmony bindings where we deoptimize into full-codegen generated code
5758  // which will subsequently throw a reference error.
5759  kCheckDeoptimize,
5760  // Check the previous value and ignore assignment if it isn't a hole value
5761  kCheckIgnoreAssignment
5762  };
5763 
5764  DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
5765  Mode, HValue*);
5766 
5767  HValue* context() { return OperandAt(0); }
5768  HValue* value() { return OperandAt(1); }
5769  int slot_index() const { return slot_index_; }
5770  Mode mode() const { return mode_; }
5771 
5773  return StoringValueNeedsWriteBarrier(value());
5774  }
5775 
5777  return mode_ == kCheckDeoptimize;
5778  }
5779 
5781  return mode_ != kNoCheck;
5782  }
5783 
5785  return Representation::Tagged();
5786  }
5787 
5788  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5789 
5790  DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
5791 
5792  private:
5793  HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
5794  : slot_index_(slot_index), mode_(mode) {
5795  SetOperandAt(0, context);
5796  SetOperandAt(1, value);
5797  SetChangesFlag(kContextSlots);
5798  }
5799 
5800  int slot_index_;
5801  Mode mode_;
5802 };
5803 
5804 
5805 // Represents an access to a portion of an object, such as the map pointer,
5806 // array elements pointer, etc, but not accesses to array elements themselves.
5807 class HObjectAccess V8_FINAL {
5808  public:
5809  inline bool IsInobject() const {
5810  return portion() != kBackingStore && portion() != kExternalMemory;
5811  }
5812 
5813  inline bool IsExternalMemory() const {
5814  return portion() == kExternalMemory;
5815  }
5816 
5817  inline bool IsStringLength() const {
5818  return portion() == kStringLengths;
5819  }
5820 
5821  inline int offset() const {
5822  return OffsetField::decode(value_);
5823  }
5824 
5826  return Representation::FromKind(RepresentationField::decode(value_));
5827  }
5828 
5829  inline Handle<String> name() const {
5830  return name_;
5831  }
5832 
5833  inline bool immutable() const {
5834  return ImmutableField::decode(value_);
5835  }
5836 
5837  // Returns true if access is being made to an in-object property that
5838  // was already added to the object.
5839  inline bool existing_inobject_property() const {
5840  return ExistingInobjectPropertyField::decode(value_);
5841  }
5842 
5843  inline HObjectAccess WithRepresentation(Representation representation) {
5844  return HObjectAccess(portion(), offset(), representation, name(),
5845  immutable(), existing_inobject_property());
5846  }
5847 
5848  static HObjectAccess ForHeapNumberValue() {
5849  return HObjectAccess(
5851  }
5852 
5853  static HObjectAccess ForHeapNumberValueLowestBits() {
5854  return HObjectAccess(kDouble,
5857  }
5858 
5859  static HObjectAccess ForHeapNumberValueHighestBits() {
5860  return HObjectAccess(kDouble,
5863  }
5864 
5865  static HObjectAccess ForElementsPointer() {
5866  return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
5867  }
5868 
5869  static HObjectAccess ForLiteralsPointer() {
5870  return HObjectAccess(kInobject, JSFunction::kLiteralsOffset);
5871  }
5872 
5873  static HObjectAccess ForNextFunctionLinkPointer() {
5874  return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
5875  }
5876 
5877  static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
5878  return HObjectAccess(
5879  kArrayLengths,
5881  IsFastElementsKind(elements_kind)
5883  }
5884 
5885  static HObjectAccess ForAllocationSiteOffset(int offset);
5886 
5887  static HObjectAccess ForAllocationSiteList() {
5888  return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
5889  Handle<String>::null(), false, false);
5890  }
5891 
5892  static HObjectAccess ForFixedArrayLength() {
5893  return HObjectAccess(
5894  kArrayLengths,
5897  }
5898 
5899  static HObjectAccess ForStringHashField() {
5900  return HObjectAccess(kInobject,
5903  }
5904 
5905  static HObjectAccess ForStringLength() {
5907  return HObjectAccess(
5908  kStringLengths,
5911  }
5912 
5913  static HObjectAccess ForConsStringFirst() {
5914  return HObjectAccess(kInobject, ConsString::kFirstOffset);
5915  }
5916 
5917  static HObjectAccess ForConsStringSecond() {
5918  return HObjectAccess(kInobject, ConsString::kSecondOffset);
5919  }
5920 
5921  static HObjectAccess ForPropertiesPointer() {
5922  return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
5923  }
5924 
5925  static HObjectAccess ForPrototypeOrInitialMap() {
5926  return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
5927  }
5928 
5929  static HObjectAccess ForSharedFunctionInfoPointer() {
5930  return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
5931  }
5932 
5933  static HObjectAccess ForCodeEntryPointer() {
5934  return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
5935  }
5936 
5937  static HObjectAccess ForCodeOffset() {
5938  return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
5939  }
5940 
5941  static HObjectAccess ForOptimizedCodeMap() {
5942  return HObjectAccess(kInobject,
5944  }
5945 
5946  static HObjectAccess ForFunctionContextPointer() {
5947  return HObjectAccess(kInobject, JSFunction::kContextOffset);
5948  }
5949 
5950  static HObjectAccess ForMap() {
5951  return HObjectAccess(kMaps, JSObject::kMapOffset);
5952  }
5953 
5954  static HObjectAccess ForMapInstanceSize() {
5955  return HObjectAccess(kInobject,
5958  }
5959 
5960  static HObjectAccess ForMapInstanceType() {
5961  return HObjectAccess(kInobject,
5964  }
5965 
5966  static HObjectAccess ForPropertyCellValue() {
5967  return HObjectAccess(kInobject, PropertyCell::kValueOffset);
5968  }
5969 
5970  static HObjectAccess ForCellValue() {
5971  return HObjectAccess(kInobject, Cell::kValueOffset);
5972  }
5973 
5974  static HObjectAccess ForAllocationMementoSite() {
5975  return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
5976  }
5977 
5978  static HObjectAccess ForCounter() {
5979  return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
5980  Handle<String>::null(), false, false);
5981  }
5982 
5983  // Create an access to an offset in a fixed array header.
5984  static HObjectAccess ForFixedArrayHeader(int offset);
5985 
5986  // Create an access to an in-object property in a JSObject.
5987  // This kind of access must be used when the object |map| is known and
5988  // in-object properties are being accessed. Accesses of the in-object
5989  // properties can have different semantics depending on whether corresponding
5990  // property was added to the map or not.
5991  static HObjectAccess ForMapAndOffset(Handle<Map> map, int offset,
5992  Representation representation = Representation::Tagged());
5993 
5994  // Create an access to an in-object property in a JSObject.
5995  // This kind of access can be used for accessing object header fields or
5996  // in-object properties if the map of the object is not known.
5997  static HObjectAccess ForObservableJSObjectOffset(int offset,
5998  Representation representation = Representation::Tagged()) {
5999  return ForMapAndOffset(Handle<Map>::null(), offset, representation);
6000  }
6001 
6002  // Create an access to an in-object property in a JSArray.
6003  static HObjectAccess ForJSArrayOffset(int offset);
6004 
6005  static HObjectAccess ForContextSlot(int index);
6006 
6007  // Create an access to the backing store of an object.
6008  static HObjectAccess ForBackingStoreOffset(int offset,
6009  Representation representation = Representation::Tagged());
6010 
6011  // Create an access to a resolved field (in-object or backing store).
6012  static HObjectAccess ForField(Handle<Map> map,
6013  LookupResult *lookup, Handle<String> name = Handle<String>::null());
6014 
6015  // Create an access for the payload of a Cell or JSGlobalPropertyCell.
6016  static HObjectAccess ForCellPayload(Isolate* isolate);
6017 
6018  static HObjectAccess ForJSTypedArrayLength() {
6019  return HObjectAccess::ForObservableJSObjectOffset(
6021  }
6022 
6023  static HObjectAccess ForJSArrayBufferBackingStore() {
6024  return HObjectAccess::ForObservableJSObjectOffset(
6026  }
6027 
6028  static HObjectAccess ForExternalArrayExternalPointer() {
6029  return HObjectAccess::ForObservableJSObjectOffset(
6031  }
6032 
6033  static HObjectAccess ForJSArrayBufferViewWeakNext() {
6034  return HObjectAccess::ForObservableJSObjectOffset(
6036  }
6037 
6038  static HObjectAccess ForJSArrayBufferWeakFirstView() {
6039  return HObjectAccess::ForObservableJSObjectOffset(
6041  }
6042 
6043  static HObjectAccess ForJSArrayBufferViewBuffer() {
6044  return HObjectAccess::ForObservableJSObjectOffset(
6046  }
6047 
6048  static HObjectAccess ForJSArrayBufferViewByteOffset() {
6049  return HObjectAccess::ForObservableJSObjectOffset(
6051  }
6052 
6053  static HObjectAccess ForJSArrayBufferViewByteLength() {
6054  return HObjectAccess::ForObservableJSObjectOffset(
6056  }
6057 
6058  static HObjectAccess ForGlobalObjectNativeContext() {
6059  return HObjectAccess(kInobject, GlobalObject::kNativeContextOffset);
6060  }
6061 
6062  void PrintTo(StringStream* stream) const;
6063 
6064  inline bool Equals(HObjectAccess that) const {
6065  return value_ == that.value_; // portion and offset must match
6066  }
6067 
6068  protected:
6069  void SetGVNFlags(HValue *instr, PropertyAccessType access_type);
6070 
6071  private:
6072  // internal use only; different parts of an object or array
6073  enum Portion {
6074  kMaps, // map of an object
6075  kArrayLengths, // the length of an array
6076  kStringLengths, // the length of a string
6077  kElementsPointer, // elements pointer
6078  kBackingStore, // some field in the backing store
6079  kDouble, // some double field
6080  kInobject, // some other in-object field
6081  kExternalMemory // some field in external memory
6082  };
6083 
6084  HObjectAccess() : value_(0) {}
6085 
6086  HObjectAccess(Portion portion, int offset,
6087  Representation representation = Representation::Tagged(),
6088  Handle<String> name = Handle<String>::null(),
6089  bool immutable = false,
6090  bool existing_inobject_property = true)
6091  : value_(PortionField::encode(portion) |
6092  RepresentationField::encode(representation.kind()) |
6093  ImmutableField::encode(immutable ? 1 : 0) |
6094  ExistingInobjectPropertyField::encode(
6095  existing_inobject_property ? 1 : 0) |
6096  OffsetField::encode(offset)),
6097  name_(name) {
6098  // assert that the fields decode correctly
6099  ASSERT(this->offset() == offset);
6100  ASSERT(this->portion() == portion);
6101  ASSERT(this->immutable() == immutable);
6102  ASSERT(this->existing_inobject_property() == existing_inobject_property);
6103  ASSERT(RepresentationField::decode(value_) == representation.kind());
6104  ASSERT(!this->existing_inobject_property() || IsInobject());
6105  }
6106 
6107  class PortionField : public BitField<Portion, 0, 3> {};
6108  class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
6109  class ImmutableField : public BitField<bool, 7, 1> {};
6110  class ExistingInobjectPropertyField : public BitField<bool, 8, 1> {};
6111  class OffsetField : public BitField<int, 9, 23> {};
6112 
6113  uint32_t value_; // encodes portion, representation, immutable, and offset
6114  Handle<String> name_;
6115 
6116  friend class HLoadNamedField;
6117  friend class HStoreNamedField;
6118  friend class SideEffectsTracker;
6119 
6120  inline Portion portion() const {
6121  return PortionField::decode(value_);
6122  }
6123 };
6124 
6125 
6126 class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> {
6127  public:
6128  DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*, HValue*,
6129  HObjectAccess);
6130 
6131  HValue* object() { return OperandAt(0); }
6133  ASSERT(HasDependency());
6134  return OperandAt(1);
6135  }
6136  bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
6137  HObjectAccess access() const { return access_; }
6139  return access_.representation();
6140  }
6141 
6142  virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
6143  virtual bool HasOutOfBoundsAccess(int size) V8_OVERRIDE {
6144  return !access().IsInobject() || access().offset() >= size;
6145  }
6147  if (index == 0 && access().IsExternalMemory()) {
6148  // object must be external in case of external memory access
6149  return Representation::External();
6150  }
6151  return Representation::Tagged();
6152  }
6153  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
6154  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6155 
6156  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
6157 
6158  protected:
6159  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
6160  HLoadNamedField* b = HLoadNamedField::cast(other);
6161  return access_.Equals(b->access_);
6162  }
6163 
6164  private:
6165  HLoadNamedField(HValue* object,
6166  HValue* dependency,
6167  HObjectAccess access) : access_(access) {
6168  ASSERT(object != NULL);
6169  SetOperandAt(0, object);
6170  SetOperandAt(1, dependency != NULL ? dependency : object);
6171 
6172  Representation representation = access.representation();
6173  if (representation.IsInteger8() ||
6174  representation.IsUInteger8() ||
6175  representation.IsInteger16() ||
6176  representation.IsUInteger16()) {
6177  set_representation(Representation::Integer32());
6178  } else if (representation.IsSmi()) {
6179  set_type(HType::Smi());
6180  if (SmiValuesAre32Bits()) {
6181  set_representation(Representation::Integer32());
6182  } else {
6183  set_representation(representation);
6184  }
6185  } else if (representation.IsDouble() ||
6186  representation.IsExternal() ||
6187  representation.IsInteger32()) {
6188  set_representation(representation);
6189  } else if (representation.IsHeapObject()) {
6190  set_type(HType::NonPrimitive());
6191  set_representation(Representation::Tagged());
6192  } else {
6193  set_representation(Representation::Tagged());
6194  }
6195  access.SetGVNFlags(this, LOAD);
6196  }
6197 
6198  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
6199 
6200  HObjectAccess access_;
6201 };
6202 
6203 
6204 class HLoadNamedGeneric V8_FINAL : public HTemplateInstruction<2> {
6205  public:
6206  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadNamedGeneric, HValue*,
6207  Handle<Object>);
6208 
6209  HValue* context() { return OperandAt(0); }
6210  HValue* object() { return OperandAt(1); }
6211  Handle<Object> name() const { return name_; }
6212 
6214  return Representation::Tagged();
6215  }
6216 
6217  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6218 
6219  DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
6220 
6221  private:
6222  HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
6223  : name_(name) {
6224  SetOperandAt(0, context);
6225  SetOperandAt(1, object);
6226  set_representation(Representation::Tagged());
6227  SetAllSideEffects();
6228  }
6229 
6230  Handle<Object> name_;
6231 };
6232 
6233 
6234 class HLoadFunctionPrototype V8_FINAL : public HUnaryOperation {
6235  public:
6236  DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);
6237 
6238  HValue* function() { return OperandAt(0); }
6239 
6241  return Representation::Tagged();
6242  }
6243 
6244  DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
6245 
6246  protected:
6247  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
6248 
6249  private:
6250  explicit HLoadFunctionPrototype(HValue* function)
6251  : HUnaryOperation(function) {
6252  set_representation(Representation::Tagged());
6253  SetFlag(kUseGVN);
6254  SetDependsOnFlag(kCalls);
6255  }
6256 };
6257 
6259  public:
6260  virtual HValue* GetKey() = 0;
6261  virtual void SetKey(HValue* key) = 0;
6262  virtual void SetIndexOffset(uint32_t index_offset) = 0;
6263  virtual int MaxIndexOffsetBits() = 0;
6264  virtual bool IsDehoisted() = 0;
6265  virtual void SetDehoisted(bool is_dehoisted) = 0;
6267 
6269  return r.IsInteger32() || SmiValuesAre32Bits()
6271  }
6272 };
6273 
6274 
6278 };
6279 
6280 
6281 class HLoadKeyed V8_FINAL
6282  : public HTemplateInstruction<3>, public ArrayInstructionInterface {
6283  public:
6284  DECLARE_INSTRUCTION_FACTORY_P4(HLoadKeyed, HValue*, HValue*, HValue*,
6285  ElementsKind);
6286  DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*,
6288 
6289  bool is_external() const {
6290  return IsExternalArrayElementsKind(elements_kind());
6291  }
6292  bool is_fixed_typed_array() const {
6293  return IsFixedTypedArrayElementsKind(elements_kind());
6294  }
6295  bool is_typed_elements() const {
6296  return is_external() || is_fixed_typed_array();
6297  }
6298  HValue* elements() { return OperandAt(0); }
6299  HValue* key() { return OperandAt(1); }
6301  ASSERT(HasDependency());
6302  return OperandAt(2);
6303  }
6304  bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
6305  uint32_t index_offset() { return IndexOffsetField::decode(bit_field_); }
6306  void SetIndexOffset(uint32_t index_offset) {
6307  bit_field_ = IndexOffsetField::update(bit_field_, index_offset);
6308  }
6309  virtual int MaxIndexOffsetBits() {
6310  return kBitsForIndexOffset;
6311  }
6312  HValue* GetKey() { return key(); }
6313  void SetKey(HValue* key) { SetOperandAt(1, key); }
6314  bool IsDehoisted() { return IsDehoistedField::decode(bit_field_); }
6315  void SetDehoisted(bool is_dehoisted) {
6316  bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
6317  }
6319  return ElementsKindField::decode(bit_field_);
6320  }
6322  return HoleModeField::decode(bit_field_);
6323  }
6324 
6326  // kind_fast: tagged[int32] (none)
6327  // kind_double: tagged[int32] (none)
6328  // kind_fixed_typed_array: tagged[int32] (none)
6329  // kind_external: external[int32] (none)
6330  if (index == 0) {
6331  return is_external() ? Representation::External()
6333  }
6334  if (index == 1) {
6336  OperandAt(1)->representation());
6337  }
6338  return Representation::None();
6339  }
6340 
6342  return RequiredInputRepresentation(index);
6343  }
6344 
6345  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6346 
6347  bool UsesMustHandleHole() const;
6348  bool AllUsesCanTreatHoleAsNaN() const;
6349  bool RequiresHoleCheck() const;
6350 
6351  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
6352 
6353  DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)
6354 
6355  protected:
6356  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
6357  if (!other->IsLoadKeyed()) return false;
6358  HLoadKeyed* other_load = HLoadKeyed::cast(other);
6359 
6360  if (IsDehoisted() && index_offset() != other_load->index_offset())
6361  return false;
6362  return elements_kind() == other_load->elements_kind();
6363  }
6364 
6365  private:
6366  HLoadKeyed(HValue* obj,
6367  HValue* key,
6368  HValue* dependency,
6369  ElementsKind elements_kind,
6371  : bit_field_(0) {
6372  bit_field_ = ElementsKindField::encode(elements_kind) |
6373  HoleModeField::encode(mode);
6374 
6375  SetOperandAt(0, obj);
6376  SetOperandAt(1, key);
6377  SetOperandAt(2, dependency != NULL ? dependency : obj);
6378 
6379  if (!is_typed_elements()) {
6380  // I can detect the case between storing double (holey and fast) and
6381  // smi/object by looking at elements_kind_.
6382  ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
6383  IsFastDoubleElementsKind(elements_kind));
6384 
6385  if (IsFastSmiOrObjectElementsKind(elements_kind)) {
6386  if (IsFastSmiElementsKind(elements_kind) &&
6387  (!IsHoleyElementsKind(elements_kind) ||
6388  mode == NEVER_RETURN_HOLE)) {
6389  set_type(HType::Smi());
6390  if (SmiValuesAre32Bits() && !RequiresHoleCheck()) {
6391  set_representation(Representation::Integer32());
6392  } else {
6393  set_representation(Representation::Smi());
6394  }
6395  } else {
6396  set_representation(Representation::Tagged());
6397  }
6398 
6399  SetDependsOnFlag(kArrayElements);
6400  } else {
6401  set_representation(Representation::Double());
6402  SetDependsOnFlag(kDoubleArrayElements);
6403  }
6404  } else {
6405  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
6406  elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
6407  elements_kind == FLOAT32_ELEMENTS ||
6408  elements_kind == FLOAT64_ELEMENTS) {
6409  set_representation(Representation::Double());
6410  } else {
6411  set_representation(Representation::Integer32());
6412  }
6413 
6414  if (is_external()) {
6415  SetDependsOnFlag(kExternalMemory);
6416  } else if (is_fixed_typed_array()) {
6417  SetDependsOnFlag(kTypedArrayElements);
6418  } else {
6419  UNREACHABLE();
6420  }
6421  // Native code could change the specialized array.
6422  SetDependsOnFlag(kCalls);
6423  }
6424 
6425  SetFlag(kUseGVN);
6426  }
6427 
6428  virtual bool IsDeletable() const V8_OVERRIDE {
6429  return !RequiresHoleCheck();
6430  }
6431 
6432  // Establish some checks around our packed fields
6433  enum LoadKeyedBits {
6434  kBitsForElementsKind = 5,
6435  kBitsForHoleMode = 1,
6436  kBitsForIndexOffset = 25,
6437  kBitsForIsDehoisted = 1,
6438 
6439  kStartElementsKind = 0,
6440  kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
6441  kStartIndexOffset = kStartHoleMode + kBitsForHoleMode,
6442  kStartIsDehoisted = kStartIndexOffset + kBitsForIndexOffset
6443  };
6444 
6445  STATIC_ASSERT((kBitsForElementsKind + kBitsForIndexOffset +
6446  kBitsForIsDehoisted) <= sizeof(uint32_t)*8);
6447  STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
6448  class ElementsKindField:
6449  public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
6450  {}; // NOLINT
6451  class HoleModeField:
6452  public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
6453  {}; // NOLINT
6454  class IndexOffsetField:
6455  public BitField<uint32_t, kStartIndexOffset, kBitsForIndexOffset>
6456  {}; // NOLINT
6457  class IsDehoistedField:
6458  public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
6459  {}; // NOLINT
6460  uint32_t bit_field_;
6461 };
6462 
6463 
6464 class HLoadKeyedGeneric V8_FINAL : public HTemplateInstruction<3> {
6465  public:
6466  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadKeyedGeneric, HValue*,
6467  HValue*);
6468  HValue* object() { return OperandAt(0); }
6469  HValue* key() { return OperandAt(1); }
6470  HValue* context() { return OperandAt(2); }
6471 
6472  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6473 
6475  // tagged[tagged]
6476  return Representation::Tagged();
6477  }
6478 
6479  virtual HValue* Canonicalize() V8_OVERRIDE;
6480 
6481  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
6482 
6483  private:
6484  HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key) {
6485  set_representation(Representation::Tagged());
6486  SetOperandAt(0, obj);
6487  SetOperandAt(1, key);
6488  SetOperandAt(2, context);
6489  SetAllSideEffects();
6490  }
6491 };
6492 
6493 
6494 // Indicates whether the store is a store to an entry that was previously
6495 // initialized or not.
6497  // The entry could be either previously initialized or not.
6499  // At the time of this store it is guaranteed that the entry is already
6500  // initialized.
6502 };
6503 
6504 
6505 class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> {
6506  public:
6507  DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
6508  HObjectAccess, HValue*);
6509  DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue*,
6510  HObjectAccess, HValue*, StoreFieldOrKeyedMode);
6511 
6512  DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
6513 
6514  virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE {
6515  return index == 1;
6516  }
6517  virtual bool HasOutOfBoundsAccess(int size) V8_OVERRIDE {
6518  return !access().IsInobject() || access().offset() >= size;
6519  }
6521  if (index == 0 && access().IsExternalMemory()) {
6522  // object must be external in case of external memory access
6523  return Representation::External();
6524  } else if (index == 1) {
6525  if (field_representation().IsInteger8() ||
6526  field_representation().IsUInteger8() ||
6527  field_representation().IsInteger16() ||
6528  field_representation().IsUInteger16() ||
6529  field_representation().IsInteger32()) {
6530  return Representation::Integer32();
6531  } else if (field_representation().IsDouble()) {
6532  return field_representation();
6533  } else if (field_representation().IsSmi()) {
6534  if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
6535  return Representation::Integer32();
6536  }
6537  return field_representation();
6538  } else if (field_representation().IsExternal()) {
6539  return Representation::External();
6540  }
6541  }
6542  return Representation::Tagged();
6543  }
6544  virtual bool HandleSideEffectDominator(GVNFlag side_effect,
6545  HValue* dominator) V8_OVERRIDE {
6546  ASSERT(side_effect == kNewSpacePromotion);
6547  if (!FLAG_use_write_barrier_elimination) return false;
6548  new_space_dominator_ = dominator;
6549  return false;
6550  }
6551  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6552 
6553  void SkipWriteBarrier() { write_barrier_mode_ = SKIP_WRITE_BARRIER; }
6554  bool IsSkipWriteBarrier() const {
6555  return write_barrier_mode_ == SKIP_WRITE_BARRIER;
6556  }
6557 
6558  HValue* object() const { return OperandAt(0); }
6559  HValue* value() const { return OperandAt(1); }
6560  HValue* transition() const { return OperandAt(2); }
6561 
6562  HObjectAccess access() const { return access_; }
6563  HValue* new_space_dominator() const { return new_space_dominator_; }
6564  bool has_transition() const { return has_transition_; }
6565  StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
6566 
6568  if (has_transition()) {
6569  return Handle<Map>::cast(
6570  HConstant::cast(transition())->handle(Isolate::Current()));
6571  } else {
6572  return Handle<Map>();
6573  }
6574  }
6575 
6576  void SetTransition(HConstant* map_constant, CompilationInfo* info) {
6577  ASSERT(!has_transition()); // Only set once.
6578  Handle<Map> map = Handle<Map>::cast(map_constant->handle(info->isolate()));
6579  if (map->CanBeDeprecated()) {
6580  map->AddDependentCompilationInfo(DependentCode::kTransitionGroup, info);
6581  }
6582  SetOperandAt(2, map_constant);
6583  has_transition_ = true;
6584  }
6585 
6587  ASSERT(!field_representation().IsDouble() || !has_transition());
6588  if (IsSkipWriteBarrier()) return false;
6589  if (field_representation().IsDouble()) return false;
6590  if (field_representation().IsSmi()) return false;
6591  if (field_representation().IsInteger32()) return false;
6592  if (field_representation().IsExternal()) return false;
6593  return StoringValueNeedsWriteBarrier(value()) &&
6594  ReceiverObjectNeedsWriteBarrier(object(), value(),
6595  new_space_dominator());
6596  }
6597 
6599  if (IsSkipWriteBarrier()) return false;
6600  return ReceiverObjectNeedsWriteBarrier(object(), transition(),
6601  new_space_dominator());
6602  }
6603 
6605  return access_.representation();
6606  }
6607 
6608  void UpdateValue(HValue* value) {
6609  SetOperandAt(1, value);
6610  }
6611 
6612  private:
6613  HStoreNamedField(HValue* obj,
6614  HObjectAccess access,
6615  HValue* val,
6617  : access_(access),
6618  new_space_dominator_(NULL),
6619  write_barrier_mode_(UPDATE_WRITE_BARRIER),
6620  has_transition_(false),
6621  store_mode_(store_mode) {
6622  // Stores to a non existing in-object property are allowed only to the
6623  // newly allocated objects (via HAllocate or HInnerAllocatedObject).
6624  ASSERT(!access.IsInobject() || access.existing_inobject_property() ||
6625  obj->IsAllocate() || obj->IsInnerAllocatedObject());
6626  SetOperandAt(0, obj);
6627  SetOperandAt(1, val);
6628  SetOperandAt(2, obj);
6629  access.SetGVNFlags(this, STORE);
6630  }
6631 
6632  HObjectAccess access_;
6633  HValue* new_space_dominator_;
6634  WriteBarrierMode write_barrier_mode_ : 1;
6635  bool has_transition_ : 1;
6636  StoreFieldOrKeyedMode store_mode_ : 1;
6637 };
6638 
6639 
6640 class HStoreNamedGeneric V8_FINAL : public HTemplateInstruction<3> {
6641  public:
6642  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreNamedGeneric, HValue*,
6643  Handle<String>, HValue*,
6644  StrictMode);
6645  HValue* object() { return OperandAt(0); }
6646  HValue* value() { return OperandAt(1); }
6647  HValue* context() { return OperandAt(2); }
6648  Handle<String> name() { return name_; }
6649  StrictMode strict_mode() { return strict_mode_; }
6650 
6651  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6652 
6654  return Representation::Tagged();
6655  }
6656 
6657  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
6658 
6659  private:
6660  HStoreNamedGeneric(HValue* context,
6661  HValue* object,
6662  Handle<String> name,
6663  HValue* value,
6664  StrictMode strict_mode)
6665  : name_(name),
6666  strict_mode_(strict_mode) {
6667  SetOperandAt(0, object);
6668  SetOperandAt(1, value);
6669  SetOperandAt(2, context);
6670  SetAllSideEffects();
6671  }
6672 
6673  Handle<String> name_;
6674  StrictMode strict_mode_;
6675 };
6676 
6677 
6678 class HStoreKeyed V8_FINAL
6679  : public HTemplateInstruction<3>, public ArrayInstructionInterface {
6680  public:
6681  DECLARE_INSTRUCTION_FACTORY_P4(HStoreKeyed, HValue*, HValue*, HValue*,
6682  ElementsKind);
6683  DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*,
6685 
6687  // kind_fast: tagged[int32] = tagged
6688  // kind_double: tagged[int32] = double
6689  // kind_smi : tagged[int32] = smi
6690  // kind_fixed_typed_array: tagged[int32] = (double | int32)
6691  // kind_external: external[int32] = (double | int32)
6692  if (index == 0) {
6693  return is_external() ? Representation::External()
6695  } else if (index == 1) {
6697  OperandAt(1)->representation());
6698  }
6699 
6700  ASSERT_EQ(index, 2);
6701  if (IsDoubleOrFloatElementsKind(elements_kind())) {
6702  return Representation::Double();
6703  }
6704  if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
6705  return Representation::Integer32();
6706  }
6707  if (IsFastSmiElementsKind(elements_kind())) {
6708  return Representation::Smi();
6709  }
6710 
6711  return is_external() || is_fixed_typed_array()
6714  }
6715 
6716  bool is_external() const {
6717  return IsExternalArrayElementsKind(elements_kind());
6718  }
6719 
6720  bool is_fixed_typed_array() const {
6721  return IsFixedTypedArrayElementsKind(elements_kind());
6722  }
6723 
6724  bool is_typed_elements() const {
6725  return is_external() || is_fixed_typed_array();
6726  }
6727 
6729  if (index < 2) return RequiredInputRepresentation(index);
6730  if (IsUninitialized()) {
6731  return Representation::None();
6732  }
6733  if (IsDoubleOrFloatElementsKind(elements_kind())) {
6734  return Representation::Double();
6735  }
6736  if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
6737  return Representation::Integer32();
6738  }
6739  if (IsFastSmiElementsKind(elements_kind())) {
6740  return Representation::Smi();
6741  }
6742  if (is_typed_elements()) {
6743  return Representation::Integer32();
6744  }
6745  // For fast object elements kinds, don't assume anything.
6746  return Representation::None();
6747  }
6748 
6749  HValue* elements() { return OperandAt(0); }
6750  HValue* key() { return OperandAt(1); }
6751  HValue* value() { return OperandAt(2); }
6752  bool value_is_smi() const {
6753  return IsFastSmiElementsKind(elements_kind_);
6754  }
6755  StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
6756  ElementsKind elements_kind() const { return elements_kind_; }
6757  uint32_t index_offset() { return index_offset_; }
6758  void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
6759  virtual int MaxIndexOffsetBits() {
6760  return 31 - ElementsKindToShiftSize(elements_kind_);
6761  }
6762  HValue* GetKey() { return key(); }
6763  void SetKey(HValue* key) { SetOperandAt(1, key); }
6764  bool IsDehoisted() { return is_dehoisted_; }
6765  void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
6766  bool IsUninitialized() { return is_uninitialized_; }
6767  void SetUninitialized(bool is_uninitialized) {
6768  is_uninitialized_ = is_uninitialized;
6769  }
6770 
6772  return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
6773  }
6774 
6775  virtual bool HandleSideEffectDominator(GVNFlag side_effect,
6776  HValue* dominator) V8_OVERRIDE {
6777  ASSERT(side_effect == kNewSpacePromotion);
6778  new_space_dominator_ = dominator;
6779  return false;
6780  }
6781 
6782  HValue* new_space_dominator() const { return new_space_dominator_; }
6783 
6785  if (value_is_smi()) {
6786  return false;
6787  } else {
6788  return StoringValueNeedsWriteBarrier(value()) &&
6789  ReceiverObjectNeedsWriteBarrier(elements(), value(),
6790  new_space_dominator());
6791  }
6792  }
6793 
6794  bool NeedsCanonicalization();
6795 
6796  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6797 
6798  DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
6799 
6800  private:
6801  HStoreKeyed(HValue* obj, HValue* key, HValue* val,
6802  ElementsKind elements_kind,
6804  : elements_kind_(elements_kind),
6805  index_offset_(0),
6806  is_dehoisted_(false),
6807  is_uninitialized_(false),
6808  store_mode_(store_mode),
6809  new_space_dominator_(NULL) {
6810  SetOperandAt(0, obj);
6811  SetOperandAt(1, key);
6812  SetOperandAt(2, val);
6813 
6814  ASSERT(store_mode != STORE_TO_INITIALIZED_ENTRY ||
6815  elements_kind == FAST_SMI_ELEMENTS);
6816 
6817  if (IsFastObjectElementsKind(elements_kind)) {
6818  SetFlag(kTrackSideEffectDominators);
6819  SetDependsOnFlag(kNewSpacePromotion);
6820  }
6821  if (is_external()) {
6822  SetChangesFlag(kExternalMemory);
6823  SetFlag(kAllowUndefinedAsNaN);
6824  } else if (IsFastDoubleElementsKind(elements_kind)) {
6825  SetChangesFlag(kDoubleArrayElements);
6826  } else if (IsFastSmiElementsKind(elements_kind)) {
6827  SetChangesFlag(kArrayElements);
6828  } else if (is_fixed_typed_array()) {
6829  SetChangesFlag(kTypedArrayElements);
6830  SetFlag(kAllowUndefinedAsNaN);
6831  } else {
6832  SetChangesFlag(kArrayElements);
6833  }
6834 
6835  // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
6836  if ((elements_kind >= EXTERNAL_INT8_ELEMENTS &&
6837  elements_kind <= EXTERNAL_UINT32_ELEMENTS) ||
6838  (elements_kind >= UINT8_ELEMENTS &&
6839  elements_kind <= INT32_ELEMENTS)) {
6840  SetFlag(kTruncatingToInt32);
6841  }
6842  }
6843 
6844  ElementsKind elements_kind_;
6845  uint32_t index_offset_;
6846  bool is_dehoisted_ : 1;
6847  bool is_uninitialized_ : 1;
6848  StoreFieldOrKeyedMode store_mode_: 1;
6849  HValue* new_space_dominator_;
6850 };
6851 
6852 
6853 class HStoreKeyedGeneric V8_FINAL : public HTemplateInstruction<4> {
6854  public:
6855  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreKeyedGeneric, HValue*,
6856  HValue*, HValue*, StrictMode);
6857 
6858  HValue* object() { return OperandAt(0); }
6859  HValue* key() { return OperandAt(1); }
6860  HValue* value() { return OperandAt(2); }
6861  HValue* context() { return OperandAt(3); }
6862  StrictMode strict_mode() { return strict_mode_; }
6863 
6865  // tagged[tagged] = tagged
6866  return Representation::Tagged();
6867  }
6868 
6869  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6870 
6871  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
6872 
6873  private:
6874  HStoreKeyedGeneric(HValue* context,
6875  HValue* object,
6876  HValue* key,
6877  HValue* value,
6878  StrictMode strict_mode)
6879  : strict_mode_(strict_mode) {
6880  SetOperandAt(0, object);
6881  SetOperandAt(1, key);
6882  SetOperandAt(2, value);
6883  SetOperandAt(3, context);
6884  SetAllSideEffects();
6885  }
6886 
6887  StrictMode strict_mode_;
6888 };
6889 
6890 
6891 class HTransitionElementsKind V8_FINAL : public HTemplateInstruction<2> {
6892  public:
6893  inline static HTransitionElementsKind* New(Zone* zone,
6894  HValue* context,
6895  HValue* object,
6896  Handle<Map> original_map,
6897  Handle<Map> transitioned_map) {
6898  return new(zone) HTransitionElementsKind(context, object,
6899  original_map, transitioned_map);
6900  }
6901 
6903  return Representation::Tagged();
6904  }
6905 
6906  HValue* object() { return OperandAt(0); }
6907  HValue* context() { return OperandAt(1); }
6908  Unique<Map> original_map() { return original_map_; }
6909  Unique<Map> transitioned_map() { return transitioned_map_; }
6910  ElementsKind from_kind() { return from_kind_; }
6911  ElementsKind to_kind() { return to_kind_; }
6912 
6913  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6914 
6915  DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
6916 
6917  protected:
6918  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
6919  HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
6920  return original_map_ == instr->original_map_ &&
6921  transitioned_map_ == instr->transitioned_map_;
6922  }
6923 
6924  virtual int RedefinedOperandIndex() { return 0; }
6925 
6926  private:
6927  HTransitionElementsKind(HValue* context,
6928  HValue* object,
6929  Handle<Map> original_map,
6930  Handle<Map> transitioned_map)
6931  : original_map_(Unique<Map>(original_map)),
6932  transitioned_map_(Unique<Map>(transitioned_map)),
6933  from_kind_(original_map->elements_kind()),
6934  to_kind_(transitioned_map->elements_kind()) {
6935  SetOperandAt(0, object);
6936  SetOperandAt(1, context);
6937  SetFlag(kUseGVN);
6938  SetChangesFlag(kElementsKind);
6939  if (!IsSimpleMapChangeTransition(from_kind_, to_kind_)) {
6940  SetChangesFlag(kElementsPointer);
6941  SetChangesFlag(kNewSpacePromotion);
6942  }
6943  set_representation(Representation::Tagged());
6944  }
6945 
6946  Unique<Map> original_map_;
6947  Unique<Map> transitioned_map_;
6948  ElementsKind from_kind_;
6949  ElementsKind to_kind_;
6950 };
6951 
6952 
6953 class HStringAdd V8_FINAL : public HBinaryOperation {
6954  public:
6955  static HInstruction* New(Zone* zone,
6956  HValue* context,
6957  HValue* left,
6958  HValue* right,
6959  PretenureFlag pretenure_flag = NOT_TENURED,
6961  Handle<AllocationSite> allocation_site =
6962  Handle<AllocationSite>::null());
6963 
6964  StringAddFlags flags() const { return flags_; }
6965  PretenureFlag pretenure_flag() const { return pretenure_flag_; }
6966 
6968  return Representation::Tagged();
6969  }
6970 
6971  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6972 
6973  DECLARE_CONCRETE_INSTRUCTION(StringAdd)
6974 
6975  protected:
6976  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
6977  return flags_ == HStringAdd::cast(other)->flags_ &&
6978  pretenure_flag_ == HStringAdd::cast(other)->pretenure_flag_;
6979  }
6980 
6981  private:
6982  HStringAdd(HValue* context,
6983  HValue* left,
6984  HValue* right,
6985  PretenureFlag pretenure_flag,
6986  StringAddFlags flags,
6987  Handle<AllocationSite> allocation_site)
6988  : HBinaryOperation(context, left, right, HType::String()),
6989  flags_(flags), pretenure_flag_(pretenure_flag) {
6990  set_representation(Representation::Tagged());
6991  SetFlag(kUseGVN);
6992  SetDependsOnFlag(kMaps);
6993  SetChangesFlag(kNewSpacePromotion);
6994  if (FLAG_trace_pretenuring) {
6995  PrintF("HStringAdd with AllocationSite %p %s\n",
6996  allocation_site.is_null()
6997  ? static_cast<void*>(NULL)
6998  : static_cast<void*>(*allocation_site),
6999  pretenure_flag == TENURED ? "tenured" : "not tenured");
7000  }
7001  }
7002 
7003  // No side-effects except possible allocation:
7004  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7005 
7006  const StringAddFlags flags_;
7007  const PretenureFlag pretenure_flag_;
7008 };
7009 
7010 
7011 class HStringCharCodeAt V8_FINAL : public HTemplateInstruction<3> {
7012  public:
7014  HValue*,
7015  HValue*);
7016 
7018  // The index is supposed to be Integer32.
7019  return index == 2
7022  }
7023 
7024  HValue* context() const { return OperandAt(0); }
7025  HValue* string() const { return OperandAt(1); }
7026  HValue* index() const { return OperandAt(2); }
7027 
7028  DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
7029 
7030  protected:
7031  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
7032 
7033  virtual Range* InferRange(Zone* zone) V8_OVERRIDE {
7034  return new(zone) Range(0, String::kMaxUtf16CodeUnit);
7035  }
7036 
7037  private:
7038  HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
7039  SetOperandAt(0, context);
7040  SetOperandAt(1, string);
7041  SetOperandAt(2, index);
7042  set_representation(Representation::Integer32());
7043  SetFlag(kUseGVN);
7044  SetDependsOnFlag(kMaps);
7045  SetDependsOnFlag(kStringChars);
7046  SetChangesFlag(kNewSpacePromotion);
7047  }
7048 
7049  // No side effects: runtime function assumes string + number inputs.
7050  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7051 };
7052 
7053 
7054 class HStringCharFromCode V8_FINAL : public HTemplateInstruction<2> {
7055  public:
7056  static HInstruction* New(Zone* zone,
7057  HValue* context,
7058  HValue* char_code);
7059 
7061  return index == 0
7064  }
7065 
7066  HValue* context() const { return OperandAt(0); }
7067  HValue* value() const { return OperandAt(1); }
7068 
7069  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
7070 
7071  DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
7072 
7073  private:
7074  HStringCharFromCode(HValue* context, HValue* char_code)
7075  : HTemplateInstruction<2>(HType::String()) {
7076  SetOperandAt(0, context);
7077  SetOperandAt(1, char_code);
7078  set_representation(Representation::Tagged());
7079  SetFlag(kUseGVN);
7080  SetChangesFlag(kNewSpacePromotion);
7081  }
7082 
7083  virtual bool IsDeletable() const V8_OVERRIDE {
7084  return !value()->ToNumberCanBeObserved();
7085  }
7086 };
7087 
7088 
7089 template <int V>
7090 class HMaterializedLiteral : public HTemplateInstruction<V> {
7091  public:
7093  : literal_index_(index), depth_(depth), allocation_site_mode_(mode) {
7094  this->set_representation(Representation::Tagged());
7095  }
7096 
7097  HMaterializedLiteral<V>(int index, int depth)
7098  : literal_index_(index), depth_(depth),
7099  allocation_site_mode_(DONT_TRACK_ALLOCATION_SITE) {
7100  this->set_representation(Representation::Tagged());
7101  }
7102 
7103  int literal_index() const { return literal_index_; }
7104  int depth() const { return depth_; }
7106  return allocation_site_mode_;
7107  }
7108 
7109  private:
7110  virtual bool IsDeletable() const V8_FINAL V8_OVERRIDE { return true; }
7111 
7112  int literal_index_;
7113  int depth_;
7114  AllocationSiteMode allocation_site_mode_;
7115 };
7116 
7117 
7118 class HRegExpLiteral V8_FINAL : public HMaterializedLiteral<1> {
7119  public:
7121  Handle<FixedArray>,
7122  Handle<String>,
7123  Handle<String>,
7124  int);
7125 
7126  HValue* context() { return OperandAt(0); }
7127  Handle<FixedArray> literals() { return literals_; }
7128  Handle<String> pattern() { return pattern_; }
7129  Handle<String> flags() { return flags_; }
7130 
7132  return Representation::Tagged();
7133  }
7134 
7135  DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
7136 
7137  private:
7138  HRegExpLiteral(HValue* context,
7140  Handle<String> pattern,
7141  Handle<String> flags,
7142  int literal_index)
7143  : HMaterializedLiteral<1>(literal_index, 0),
7144  literals_(literals),
7145  pattern_(pattern),
7146  flags_(flags) {
7147  SetOperandAt(0, context);
7148  SetAllSideEffects();
7149  set_type(HType::JSObject());
7150  }
7151 
7152  Handle<FixedArray> literals_;
7153  Handle<String> pattern_;
7154  Handle<String> flags_;
7155 };
7156 
7157 
7158 class HFunctionLiteral V8_FINAL : public HTemplateInstruction<1> {
7159  public:
7161  Handle<SharedFunctionInfo>,
7162  bool);
7163  HValue* context() { return OperandAt(0); }
7164 
7166  return Representation::Tagged();
7167  }
7168 
7169  DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral)
7170 
7171  Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
7172  bool pretenure() const { return pretenure_; }
7173  bool has_no_literals() const { return has_no_literals_; }
7174  bool is_generator() const { return is_generator_; }
7175  StrictMode strict_mode() const { return strict_mode_; }
7176 
7177  private:
7178  HFunctionLiteral(HValue* context,
7180  bool pretenure)
7181  : HTemplateInstruction<1>(HType::JSObject()),
7182  shared_info_(shared),
7183  pretenure_(pretenure),
7184  has_no_literals_(shared->num_literals() == 0),
7185  is_generator_(shared->is_generator()),
7186  strict_mode_(shared->strict_mode()) {
7187  SetOperandAt(0, context);
7188  set_representation(Representation::Tagged());
7189  SetChangesFlag(kNewSpacePromotion);
7190  }
7191 
7192  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7193 
7194  Handle<SharedFunctionInfo> shared_info_;
7195  bool pretenure_ : 1;
7196  bool has_no_literals_ : 1;
7197  bool is_generator_ : 1;
7198  StrictMode strict_mode_;
7199 };
7200 
7201 
7202 class HTypeof V8_FINAL : public HTemplateInstruction<2> {
7203  public:
7205 
7206  HValue* context() { return OperandAt(0); }
7207  HValue* value() { return OperandAt(1); }
7208 
7209  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7210 
7212  return Representation::Tagged();
7213  }
7214 
7216 
7217  private:
7218  explicit HTypeof(HValue* context, HValue* value) {
7219  SetOperandAt(0, context);
7220  SetOperandAt(1, value);
7221  set_representation(Representation::Tagged());
7222  }
7223 
7224  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7225 };
7226 
7227 
7228 class HTrapAllocationMemento V8_FINAL : public HTemplateInstruction<1> {
7229  public:
7230  DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
7231 
7233  return Representation::Tagged();
7234  }
7235 
7236  HValue* object() { return OperandAt(0); }
7237 
7238  DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
7239 
7240  private:
7241  explicit HTrapAllocationMemento(HValue* obj) {
7242  SetOperandAt(0, obj);
7243  }
7244 };
7245 
7246 
7247 class HToFastProperties V8_FINAL : public HUnaryOperation {
7248  public:
7249  DECLARE_INSTRUCTION_FACTORY_P1(HToFastProperties, HValue*);
7250 
7252  return Representation::Tagged();
7253  }
7254 
7255  DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
7256 
7257  private:
7258  explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
7259  set_representation(Representation::Tagged());
7260  SetChangesFlag(kNewSpacePromotion);
7261 
7262  // This instruction is not marked as kChangesMaps, but does
7263  // change the map of the input operand. Use it only when creating
7264  // object literals via a runtime call.
7265  ASSERT(value->IsCallRuntime());
7266 #ifdef DEBUG
7267  const Runtime::Function* function = HCallRuntime::cast(value)->function();
7268  ASSERT(function->function_id == Runtime::kHiddenCreateObjectLiteral);
7269 #endif
7270  }
7271 
7272  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7273 };
7274 
7275 
7276 class HDateField V8_FINAL : public HUnaryOperation {
7277  public:
7278  DECLARE_INSTRUCTION_FACTORY_P2(HDateField, HValue*, Smi*);
7279 
7280  Smi* index() const { return index_; }
7281 
7283  return Representation::Tagged();
7284  }
7285 
7286  DECLARE_CONCRETE_INSTRUCTION(DateField)
7287 
7288  private:
7289  HDateField(HValue* date, Smi* index)
7290  : HUnaryOperation(date), index_(index) {
7291  set_representation(Representation::Tagged());
7292  }
7293 
7294  Smi* index_;
7295 };
7296 
7297 
7298 class HSeqStringGetChar V8_FINAL : public HTemplateInstruction<2> {
7299  public:
7300  static HInstruction* New(Zone* zone,
7301  HValue* context,
7302  String::Encoding encoding,
7303  HValue* string,
7304  HValue* index);
7305 
7307  return (index == 0) ? Representation::Tagged()
7309  }
7310 
7311  String::Encoding encoding() const { return encoding_; }
7312  HValue* string() const { return OperandAt(0); }
7313  HValue* index() const { return OperandAt(1); }
7314 
7315  DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)
7316 
7317  protected:
7318  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7319  return encoding() == HSeqStringGetChar::cast(other)->encoding();
7320  }
7321 
7322  virtual Range* InferRange(Zone* zone) V8_OVERRIDE {
7323  if (encoding() == String::ONE_BYTE_ENCODING) {
7324  return new(zone) Range(0, String::kMaxOneByteCharCode);
7325  } else {
7326  ASSERT_EQ(String::TWO_BYTE_ENCODING, encoding());
7327  return new(zone) Range(0, String::kMaxUtf16CodeUnit);
7328  }
7329  }
7330 
7331  private:
7332  HSeqStringGetChar(String::Encoding encoding,
7333  HValue* string,
7334  HValue* index) : encoding_(encoding) {
7335  SetOperandAt(0, string);
7336  SetOperandAt(1, index);
7337  set_representation(Representation::Integer32());
7338  SetFlag(kUseGVN);
7339  SetDependsOnFlag(kStringChars);
7340  }
7341 
7342  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7343 
7344  String::Encoding encoding_;
7345 };
7346 
7347 
7348 class HSeqStringSetChar V8_FINAL : public HTemplateInstruction<4> {
7349  public:
7351  HSeqStringSetChar, String::Encoding,
7352  HValue*, HValue*, HValue*);
7353 
7354  String::Encoding encoding() { return encoding_; }
7355  HValue* context() { return OperandAt(0); }
7356  HValue* string() { return OperandAt(1); }
7357  HValue* index() { return OperandAt(2); }
7358  HValue* value() { return OperandAt(3); }
7359 
7361  return (index <= 1) ? Representation::Tagged()
7363  }
7364 
7365  DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
7366 
7367  private:
7368  HSeqStringSetChar(HValue* context,
7369  String::Encoding encoding,
7370  HValue* string,
7371  HValue* index,
7372  HValue* value) : encoding_(encoding) {
7373  SetOperandAt(0, context);
7374  SetOperandAt(1, string);
7375  SetOperandAt(2, index);
7376  SetOperandAt(3, value);
7377  set_representation(Representation::Tagged());
7378  SetChangesFlag(kStringChars);
7379  }
7380 
7381  String::Encoding encoding_;
7382 };
7383 
7384 
7385 class HCheckMapValue V8_FINAL : public HTemplateInstruction<2> {
7386  public:
7387  DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);
7388 
7390  return Representation::Tagged();
7391  }
7392 
7393  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7394 
7396  return HType::Tagged();
7397  }
7398 
7399  HValue* value() { return OperandAt(0); }
7400  HValue* map() { return OperandAt(1); }
7401 
7402  DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
7403 
7404  protected:
7405  virtual int RedefinedOperandIndex() { return 0; }
7406 
7407  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7408  return true;
7409  }
7410 
7411  private:
7412  HCheckMapValue(HValue* value,
7413  HValue* map) {
7414  SetOperandAt(0, value);
7415  SetOperandAt(1, map);
7416  set_representation(Representation::Tagged());
7417  SetFlag(kUseGVN);
7418  SetDependsOnFlag(kMaps);
7419  SetDependsOnFlag(kElementsKind);
7420  }
7421 };
7422 
7423 
7424 class HForInPrepareMap V8_FINAL : public HTemplateInstruction<2> {
7425  public:
7426  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HForInPrepareMap, HValue*);
7427 
7429  return Representation::Tagged();
7430  }
7431 
7432  HValue* context() { return OperandAt(0); }
7433  HValue* enumerable() { return OperandAt(1); }
7434 
7435  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7436 
7438  return HType::Tagged();
7439  }
7440 
7441  DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
7442 
7443  private:
7444  HForInPrepareMap(HValue* context,
7445  HValue* object) {
7446  SetOperandAt(0, context);
7447  SetOperandAt(1, object);
7448  set_representation(Representation::Tagged());
7449  SetAllSideEffects();
7450  }
7451 };
7452 
7453 
7454 class HForInCacheArray V8_FINAL : public HTemplateInstruction<2> {
7455  public:
7456  DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
7457 
7459  return Representation::Tagged();
7460  }
7461 
7462  HValue* enumerable() { return OperandAt(0); }
7463  HValue* map() { return OperandAt(1); }
7464  int idx() { return idx_; }
7465 
7466  HForInCacheArray* index_cache() {
7467  return index_cache_;
7468  }
7469 
7470  void set_index_cache(HForInCacheArray* index_cache) {
7471  index_cache_ = index_cache;
7472  }
7473 
7474  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7475 
7477  return HType::Tagged();
7478  }
7479 
7480  DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
7481 
7482  private:
7483  HForInCacheArray(HValue* enumerable,
7484  HValue* keys,
7485  int idx) : idx_(idx) {
7486  SetOperandAt(0, enumerable);
7487  SetOperandAt(1, keys);
7488  set_representation(Representation::Tagged());
7489  }
7490 
7491  int idx_;
7492  HForInCacheArray* index_cache_;
7493 };
7494 
7495 
7496 class HLoadFieldByIndex V8_FINAL : public HTemplateInstruction<2> {
7497  public:
7499  HValue* index) {
7500  SetOperandAt(0, object);
7501  SetOperandAt(1, index);
7502  set_representation(Representation::Tagged());
7503  }
7504 
7506  return Representation::Tagged();
7507  }
7508 
7509  HValue* object() { return OperandAt(0); }
7510  HValue* index() { return OperandAt(1); }
7511 
7512  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7513 
7515  return HType::Tagged();
7516  }
7517 
7518  DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
7519 
7520  private:
7521  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7522 };
7523 
7524 
7525 #undef DECLARE_INSTRUCTION
7526 #undef DECLARE_CONCRETE_INSTRUCTION
7527 
7528 } } // namespace v8::internal
7529 
7530 #endif // V8_HYDROGEN_INSTRUCTIONS_H_
static HObjectAccess ForFunctionContextPointer()
StoreFieldOrKeyedMode store_mode() const
HSourcePosition position() const
bool HasObservableSideEffects() const
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
static HObjectAccess ForCounter()
virtual bool IsPurelyInformativeDefinition() V8_OVERRIDE
void StackUpon(Range *other)
virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE
static const int kHashFieldOffset
Definition: objects.h:8629
const int kMinInt
Definition: globals.h:249
void SetDependsOnFlag(GVNFlag f)
void SetChangesFlag(GVNFlag f)
static HContext * New(Zone *zone)
HPhi(int merged_index, Zone *zone)
void SetOperandPositions(Zone *zone, HSourcePosition left_pos, HSourcePosition right_pos)
static Representation UInteger8()
virtual Opcode opcode() const V8_OVERRIDE
static HInvokeFunction * New(Zone *zone, HValue *context, HValue *function, Handle< JSFunction > known_function, int argument_count)
void set_incoming_value(HPhi *value)
static HSourcePosition Unknown()
virtual Representation observed_input_representation(int index) V8_OVERRIDE
static const int kCodeOffset
Definition: objects.h:7103
static bool is_the_hole_nan(double value)
Definition: objects-inl.h:2156
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown 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
bool IsExternalArrayElementsKind(ElementsKind kind)
bool IsHoleyElementsKind(ElementsKind kind)
static const int kCodeEntryOffset
Definition: objects.h:7518
static HObjectAccess ForStringHashField()
#define DECLARE_INSTRUCTION_FACTORY_P2(I, P1, P2)
virtual Representation RequiredInputRepresentation(int index) V8_FINAL V8_OVERRIDE
virtual void RepresentationChanged(Representation to) V8_OVERRIDE
void AddPushedValue(HValue *value)
Handle< String > name() const
#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(I, P1, P2, P3, P4)
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE
static const int kPrototypeOrInitialMapOffset
Definition: objects.h:7519
virtual intptr_t Hashcode() V8_OVERRIDE
#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(I, P1, P2, P3)
static const int kValueOffset
Definition: objects.h:9547
const CallInterfaceDescriptor * descriptor() const
virtual void FinalizeUniqueness() V8_OVERRIDE
uint16_t current_
ToBooleanStub::Types expected_input_types() const
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths true
Definition: flags.cc:208
static Representation Smi()
void CopyFlag(Flag f, HValue *other)
void PrintF(const char *format,...)
Definition: v8utils.cc:40
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf map
Definition: flags.cc:350
Heap::RootListIndex index() const
virtual void initialize_output_representation(Representation observed)
bool InNewSpace(Object *object)
Definition: heap-inl.h:307
virtual bool DataEquals(HValue *other)
static const int kMaxUtf16CodeUnit
Definition: objects.h:8916
Deoptimizer::BailoutType type()
virtual HValue * Canonicalize()
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE
static HObjectAccess ForConsStringSecond()
Definition: v8.h:1407
static HDeoptimize * New(Zone *zone, HValue *context, const char *reason, Deoptimizer::BailoutType type, HBasicBlock *unreachable_continuation)
HUseListNode * RemoveUse(HValue *value, int index)
HInstruction * previous() const
HSuccessorIterator(HControlInstruction *instr)
bool IsFastObjectElementsKind(ElementsKind kind)
virtual bool KnownSuccessorBlock(HBasicBlock **block)
bool CheckChangesFlag(GVNFlag f) const
virtual void InternalSetOperandAt(int index, HValue *value) V8_FINAL V8_OVERRIDE
StrictMode strict_mode() const
void ClearDependsOnFlag(GVNFlag f)
static const int kOptimizedCodeMapOffset
Definition: objects.h:7104
const ZoneList< HValue * > * arguments_values() const
virtual int OperandCount() V8_FINAL V8_OVERRIDE
static HObjectAccess ForAllocationMementoSite()
Handle< JSFunction > known_function()
HBasicBlock * block() const
static bool IsCompareOp(Value op)
Definition: token.h:220
static Handle< T > cast(Handle< S > that)
Definition: handles.h:75
virtual Representation observed_input_representation(int index) V8_OVERRIDE
static Representation Integer32()
T Max(T a, T b)
Definition: utils.h:227
static HObjectAccess ForHeapNumberValue()
void set_observed_input_representation(Representation left, Representation right)
Handle< Object > name() const
virtual Representation observed_input_representation(int index) V8_OVERRIDE
HLoadFieldByIndex(HValue *object, HValue *index)
HUnaryOperation(HValue *value, HType type=HType::Tagged())
virtual LInstruction * CompileToLithium(LChunkBuilder *builder)=0
virtual int OperandCount() V8_FINAL V8_OVERRIDE
HUseListNode(HValue *value, int index, HUseListNode *tail)
Range * CopyClearUpper(Zone *zone) const
Encoding
Definition: v8.h:1663
TypeImpl< ZoneTypeConfig > Type
int int32_t
Definition: unicode.cc:47
static HObjectAccess ForAllocationSiteList()
bool Includes(int value) const
HArgumentsObject * arguments_object()
HValue * new_space_dominator() const
virtual void AssumeRepresentation(Representation r)
Range * Copy(Zone *zone) const
virtual void PrintDataTo(StringStream *stream) V8_OVERRIDE
static const int kExternalPointerOffset
Definition: objects.h:4702
const int kMaxInt
Definition: globals.h:248
bool EqualsInteger32Constant(int32_t value)
static HObjectAccess ForArrayLength(ElementsKind elements_kind)
static const int kNoRedefinedOperand
void set_index_cache(HForInCacheArray *index_cache)
Isolate * isolate() const
Definition: compiler.h:67
bool Apply(HValue *other_base, int other_offset, int other_scale=0)
virtual void InternalSetOperandAt(int index, HValue *value) V8_OVERRIDE
virtual Representation observed_input_representation(int index) V8_OVERRIDE
static const int kByteLengthOffset
Definition: objects.h:9917
virtual HBasicBlock * SuccessorAt(int i)=0
ParameterKind kind() const
void set_known_initial_map(Handle< Map > known_initial_map)
unibrow::Mapping< unibrow::Ecma262Canonicalize > Canonicalize
void SwapValues(HValue **other_base, int *other_offset, int *other_scale)
static HInstruction * New(Zone *zone, HValue *context, HValue *left, HValue *right)
static HEnterInlined * New(Zone *zone, HValue *context, Handle< JSFunction > closure, int arguments_count, FunctionLiteral *function, InliningKind inlining_kind, Variable *arguments_var, HArgumentsObject *arguments_object)
#define ASSERT(condition)
Definition: checks.h:329
bool ToStringCanBeObserved() const
virtual void RepresentationChanged(Representation to) V8_OVERRIDE
virtual void InferRepresentation(HInferRepresentationPhase *h_infer)
HChange(HValue *value, Representation to, bool is_truncating_to_smi, bool is_truncating_to_int32)
static const int kInstanceSizeOffset
Definition: objects.h:6448
AllocationSiteMode allocation_site_mode() const
virtual Representation KnownOptimalRepresentation() V8_OVERRIDE
HObjectAccess WithRepresentation(Representation representation)
virtual void PrintDataTo(StringStream *stream)
virtual Representation KnownOptimalRepresentation()
void SetTransition(HConstant *map_constant, CompilationInfo *info)
Range * CopyClearLower(Zone *zone) const
static HObjectAccess ForOptimizedCodeMap()
Handle< Object > NewNumber(double value, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:998
static Representation Double()
static HObjectAccess ForNextFunctionLinkPointer()
virtual Representation RequiredInputRepresentation(int index) V8_FINAL V8_OVERRIDE
LoadKeyedHoleMode hole_mode() const
bool ContainsAnyOf(const EnumSet &set) const
Definition: utils.h:1056
void set_observed_input_representation(int index, Representation rep)
#define DECLARE_FLAG(Type)
void AddDependantsToWorklist(HInferRepresentationPhase *h_infer)
Factory * factory()
Definition: isolate.h:995
bool IsFastElementsKind(ElementsKind kind)
bool IsSimpleMapChangeTransition(ElementsKind from_kind, ElementsKind to_kind)
Token::Value op() const
Representation representation() const
static const int kContextOffset
Definition: objects.h:7523
MinusZeroMode GetMinusZeroMode()
static HCheckValue * New(Zone *zone, HValue *context, HValue *value, Unique< HeapObject > target, bool object_in_new_space)
void set_operand_position(int idx, HSourcePosition pos)
static HObjectAccess ForExternalArrayExternalPointer()
Representation representation() const
Unique< Object > GetUnique() const
Isolate * isolate()
Definition: zone.h:90
GVNFlagSet DependsOnFlags() const
virtual int OperandCount() V8_OVERRIDE
bool HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const
void set_representation(Representation r)
const int kIntSize
Definition: globals.h:263
virtual int argument_count() const
#define DECLARE_OPCODE(type)
void set_next_simulate(HSimulate *simulate)
InductionVariableCheck(HBoundsCheck *check, InductionVariableCheck *next, int32_t upper_limit=kNoLimit)
#define DECLARE_INSTRUCTION_FACTORY_P0(I)
void AddAssignedValue(int index, HValue *value)
virtual bool HasEscapingOperandAt(int index)
HBinaryCall(HValue *first, HValue *second, int argument_count)
int isnan(double x)
HBasicBlock * induction_exit_block()
GVNFlagSet ObservableChangesFlags() const
InductionVariableData * induction_variable_data()
HBinaryOperation(HValue *context, HValue *left, HValue *right, HType type=HType::Tagged())
#define DECLARE_ABSTRACT_INSTRUCTION(type)
void set_known_successor_index(int known_successor_index)
static const int kFirstOffset
Definition: objects.h:9165
Range(int32_t lower, int32_t upper)
virtual HValue * OperandAt(int index) const V8_FINAL V8_OVERRIDE
static HObjectAccess ForCodeOffset()
static const int kWeakFirstViewOffset
Definition: objects.h:9881
const ZoneList< HValue * > * values() const
virtual void UpdateRepresentation(Representation new_rep, HInferRepresentationPhase *h_infer, const char *reason) V8_OVERRIDE
#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
static HCallWithDescriptor * New(Zone *zone, HValue *context, HValue *target, int argument_count, const CallInterfaceDescriptor *descriptor, Vector< HValue * > &operands)
virtual Representation RequiredInputRepresentation(int index) V8_FINAL V8_OVERRIDE
Handle< String > StringValue() const
CallFunctionFlags function_flags() const
virtual HType CalculateInferredType()
virtual Range * InferRange(Zone *zone) V8_OVERRIDE
static const int kLiteralsOffset
Definition: objects.h:7524
virtual bool HandleSideEffectDominator(GVNFlag side_effect, HValue *dominator)
void AddNewRange(Range *r, Zone *zone)
virtual int OperandCount()=0
#define UNREACHABLE()
Definition: checks.h:52
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction pairs(ARM only)") DEFINE_bool(enable_unaligned_accesses
virtual int RedefinedOperandIndex() V8_OVERRIDE
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_string(expose_natives_as
bool Equals(HValue *other)
HSourcePosition operand_position(int idx) const
#define DECLARE_INSTRUCTION_FACTORY_P3(I, P1, P2, P3)
virtual Representation RequiredInputRepresentation(int index)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object size
Definition: flags.cc:211
void PrintRangeTo(StringStream *stream)
static HObjectAccess ForGlobalObjectNativeContext()
static const int kLengthOffset
Definition: objects.h:8905
virtual HType CalculateInferredType() V8_FINAL V8_OVERRIDE
static HObjectAccess ForPropertyCellValue()
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
Definition: v8.h:917
static HArgumentsObject * New(Zone *zone, HValue *context, int count)
static Representation FromKind(Kind kind)
static GVNFlagSet AllSideEffectsFlagSet()
VariableMode mode() const
Definition: variables.h:97
static const int kValueOffset
Definition: objects.h:1971
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including flags
Definition: flags.cc:665
HValue(HType type=HType::Tagged())
void PrintChangesTo(StringStream *stream)
virtual bool HasOutOfBoundsAccess(int size)
static HConstant * CreateAndInsertBefore(Zone *zone, Unique< Object > unique, bool is_not_in_new_space, HInstruction *instruction)
virtual void RepresentationChanged(Representation to)
virtual void DeleteFromGraph() V8_OVERRIDE
bool HasMap(Handle< Map > map)
static HUnaryOperation * cast(HValue *value)
static HStoreCodeEntry * New(Zone *zone, HValue *context, HValue *function, HValue *code)
static uint32_t update(uint32_tprevious, T value)
Definition: utils.h:296
bool CheckDependsOnFlag(GVNFlag f) const
void ReuseSideEffectsFromStore(HInstruction *store)
virtual void PrintDataTo(StringStream *stream) V8_OVERRIDE
static HObjectAccess ForMap()
bool HasInternalizedStringValue() const
static const int kMinValue
Definition: objects.h:1679
HArithmeticBinaryOperation(HValue *context, HValue *left, HValue *right)
static const int kBufferOffset
Definition: objects.h:9915
virtual int argument_delta() const V8_OVERRIDE
const int kPointerSize
Definition: globals.h:268
void check(i::Vector< const uint8_t > string)
bool StoringValueNeedsWriteBarrier(HValue *value)
void set_map_set(UniqueSet< Map > *maps, Zone *zone)
Representation RepresentationFromUses()
#define DECLARE_PREDICATE(type)
Representation field_representation() const
bool IsDefinedAfter(HBasicBlock *other) const
static HObjectAccess ForFixedArrayLength()
static HObjectAccess ForJSArrayBufferViewByteLength()
static HObjectAccess ForJSTypedArrayLength()
void ComputeInitialRange(Zone *zone)
bool ReceiverObjectNeedsWriteBarrier(HValue *object, HValue *value, HValue *new_space_dominator)
bool Equals(const Representation &other) const
virtual Representation RepresentationFromInputs() V8_OVERRIDE
bool IsOldPointerSpaceAllocation() const
static GVNFlagSet AllObservableSideEffectsFlagSet()
#define GVN_TRACKED_FLAG_LIST(V)
static HCheckValue * New(Zone *zone, HValue *context, HValue *value, Handle< JSFunction > func)
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE
virtual void UpdateRepresentation(Representation new_rep, HInferRepresentationPhase *h_infer, const char *reason) V8_OVERRIDE
const char * reason() const
static const int kBackingStoreOffset
Definition: objects.h:9877
HSimulate(BailoutId ast_id, int pop_count, Zone *zone, RemovableSimulate removable)
static HObjectAccess ForSharedFunctionInfoPointer()
virtual void PrintDataTo(StringStream *stream) V8_OVERRIDE
virtual Handle< Map > GetMonomorphicJSObjectMap()
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
static HInstruction * NewImul(Zone *zone, HValue *context, HValue *left, HValue *right)
HBoundsCheckBaseIndexInformation(HBoundsCheck *check)
ElementsKind elements_kind() const
static HObjectAccess ForObservableJSObjectOffset(int offset, Representation representation=Representation::Tagged())
GVNFlagSet ChangesFlags() const
HValue * OperandAt(int i) const V8_OVERRIDE
void set_operand_position(Zone *zone, int index, HSourcePosition pos)
ExternalReference ExternalReferenceValue() const
bool IsSubtypeOf(const HType &other)
bool IsFixedTypedArrayElementsKind(ElementsKind kind)
virtual void PrintTo(StringStream *stream) V8_OVERRIDE
ContainedInLattice Combine(ContainedInLattice a, ContainedInLattice b)
Definition: jsregexp.h:1231
int length() const
Definition: utils.h:420
static const int kPropertiesOffset
Definition: objects.h:2755
HInstruction * next() const
void Intersect(const EnumSet &set)
Definition: utils.h:1064
virtual HSourcePosition operand_position(int index) const
bool IsContextSlot() const
Definition: variables.h:119
virtual void initialize_output_representation(Representation observed)
bool Equals(HObjectAccess that) const
bool existing_inobject_property() const
void ensure_storage_for_operand_positions(Zone *zone, int operand_count)
StringAddFlags flags() const
#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(I, P1, P2)
bool IsFastSmiElementsKind(ElementsKind kind)
static const int kByteOffsetOffset
Definition: objects.h:9916
void set_known_successor_index(int known_successor_index)
void set_type(HType new_type)
static const int kNextFunctionLinkOffset
Definition: objects.h:7526
const int kBitsPerByte
Definition: globals.h:287
static const int kElementsOffset
Definition: objects.h:2756
bool IsPowerOf2(T x)
Definition: utils.h:51
Unique< Map > map() const
virtual Handle< Map > GetMonomorphicJSObjectMap()
static HObjectAccess ForJSArrayBufferViewBuffer()
static bool IsEqualityOp(Value op)
Definition: token.h:228
static Representation External()
static const int kLengthOffset
Definition: objects.h:9949
#define BASE_EMBEDDED
Definition: allocation.h:68
T * NewArray(int length)
Definition: zone-inl.h:93
HBasicBlock * SuccessorAt(int i) V8_OVERRIDE
void set_save_doubles(SaveFPRegsMode save_doubles)
virtual HType CalculateInferredType() V8_OVERRIDE
const int kBitsPerInt
Definition: globals.h:290
Representation RepresentationFromUseRequirements()
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE
HTemplateInstruction(HType type=HType::Tagged())
void DeleteAndReplaceWith(HValue *other)
int ElementsKindToShiftSize(ElementsKind elements_kind)
static HPhi * cast(HValue *value)
static HObjectAccess ForConsStringFirst()
#define GVN_UNTRACKED_FLAG_LIST(V)
int32_t NumberValueAsInteger32() const
void SetSuccessorAt(int i, HBasicBlock *block) V8_OVERRIDE
virtual intptr_t Hashcode()
int ToOperandIndex(int environment_index)
static const int kLengthOffset
Definition: objects.h:10076
virtual HSourcePosition operand_position(int index) const V8_OVERRIDE
virtual bool TryDecompose(DecompositionResult *decomposition)
#define T(name, string, precedence)
Definition: token.cc:48
Handle< FixedArray > literals()
Unique< HeapObject > object() const
virtual int RedefinedOperandIndex()
virtual HValue * OperandAt(int index) const V8_OVERRIDE
InstanceType GetInstanceType() const
static bool CompatibleInstanceTypes(InstanceType type1, InstanceType type2)
virtual HValue * OperandAt(int i) const V8_FINAL V8_OVERRIDE
bool IsFastSmiOrObjectElementsKind(ElementsKind kind)
#define DECLARE_INSTRUCTION_FACTORY_P4(I, P1, P2, P3, P4)
HLeaveInlined(HEnterInlined *entry, int drop_count)
void PrintNameTo(StringStream *stream)
Representation generalize(Representation other)
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE
virtual void UpdateRepresentation(Representation new_rep, HInferRepresentationPhase *h_infer, const char *reason) V8_OVERRIDE
const int kElementsKindCount
Definition: elements-kind.h:89
Definition: v8.h:2107
void InsertAfter(HInstruction *previous)
virtual Representation RequiredInputRepresentation(int index) V8_FINAL V8_OVERRIDE
virtual Representation observed_input_representation(int index) V8_OVERRIDE
HLoadContextSlot(HValue *context, Variable *var)
virtual Opcode opcode() const =0
virtual void DeleteFromGraph()=0
bool EqualsUnique(Unique< Object > other) const
virtual void SetSuccessorAt(int i, HBasicBlock *block)=0
static const int kMapOffset
Definition: objects.h:1890
static HObjectAccess ForHeapNumberValueHighestBits()
void UpdateValue(HValue *value)
Handle< FixedArray > pairs() const
virtual Representation RequiredInputRepresentation(int index)=0
virtual HValue * OperandAt(int index) const V8_FINAL V8_OVERRIDE
virtual HSourcePosition position() const
void InternalSetOperandAt(int i, HValue *value) V8_OVERRIDE
static HObjectAccess ForPropertiesPointer()
virtual HSourcePosition position() const V8_OVERRIDE
virtual bool IsPurelyInformativeDefinition()
virtual void FinalizeUniqueness()
static const int kLengthOffset
Definition: objects.h:3015
void ChangeRepresentation(Representation r)
virtual int argument_count() const
static const int kSecondOffset
Definition: objects.h:9166
static HConstant * CreateAndInsertBefore(Zone *zone, HValue *context, int32_t value, Representation representation, HInstruction *instruction)
#define V8_OVERRIDE
Definition: v8config.h:402
bool is_null() const
Definition: handles.h:81
bool HasAssignedIndexAt(int index) const
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:103
bool Contains(E element) const
Definition: utils.h:1055
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
Definition: flags.cc:317
virtual bool HandleSideEffectDominator(GVNFlag side_effect, HValue *dominator) V8_OVERRIDE
static HObjectAccess ForJSArrayBufferWeakFirstView()
void SetOperandAt(int index, HValue *value)
PretenureFlag pretenure_flag() const
#define COUNT_FLAG(Type)
virtual int argument_delta() const V8_OVERRIDE
virtual Range * InferRange(Zone *zone)
void SetDehoisted(bool is_dehoisted)
bool CheckFlag(Flag f) const
bool ToStringOrToNumberCanBeObserved(Representation representation)
static HObjectAccess ForStringLength()
void set_position(HSourcePosition pos)
HUnaryCall(HValue *value, int argument_count)
#define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V)
#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(I, P1)
static HObjectAccess ForMapInstanceType()
void set_position(HSourcePosition position)
int GetAssignedIndexAt(int index) const
virtual Representation RepresentationFromInputs()
void InsertBefore(HInstruction *next)
static HInnerAllocatedObject * New(Zone *zone, HValue *context, HValue *value, HValue *offset, HType type=HType::Tagged())
virtual HValue * Canonicalize() V8_OVERRIDE
bool Equals(const HType &other) const
GVNFlagSet SideEffectFlags() const
static Handle< String > null()
Definition: handles.h:80
static Representation KeyedAccessIndexRequirement(Representation r)
void set_inlining_id(int inlining_id)
Unique< Cell > cell() const
static const int kAllocationSiteOffset
Definition: objects.h:8443
#define ASSERT_EQ(v1, v2)
Definition: checks.h:330
HObjectAccess access() const
bool IsDoubleOrFloatElementsKind(ElementsKind kind)
virtual bool HasOutOfBoundsAccess(int size) V8_OVERRIDE
void SetBlock(HBasicBlock *block)
bool CanBeZero(HValue *right)
Definition: hydrogen.cc:9114
Handle< String > class_name() const
#define DECLARE_CONCRETE_INSTRUCTION(type)
virtual void InternalSetOperandAt(int i, HValue *value) V8_FINAL V8_OVERRIDE
virtual Representation observed_input_representation(int index)
virtual HValue * OperandAt(int index) const =0
static const int kWeakNextOffset
Definition: objects.h:9918
void SetUninitialized(bool is_uninitialized)
bool CheckUsesForFlag(Flag f) const
static HObjectAccess ForJSArrayBufferViewByteOffset()
HSourcePosition(const HSourcePosition &other)
void SetIndexOffset(uint32_t index_offset)
static HObjectAccess ForElementsPointer()
static HObjectAccess ForJSArrayBufferViewWeakNext()
#define ADD_FLAG(Type)
virtual int argument_delta() const
virtual bool HasEscapingOperandAt(int index) V8_FINAL V8_OVERRIDE
const char * Mnemonic() const
HUnaryControlInstruction(HValue *value, HBasicBlock *true_target, HBasicBlock *false_target)
virtual void RepresentationChanged(Representation to) V8_OVERRIDE
HeapObject * obj
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric literals(0o77, 0b11)") DEFINE_bool(harmony_strings
void ClearChangesFlag(GVNFlag f)
bool ToNumberCanBeObserved() const
String::Encoding encoding() const
EnumSet< GVNFlag, int32_t > GVNFlagSet
ZoneList< HBasicBlock * > * return_targets()
static Representation None()
virtual void PrintTo(StringStream *stream)=0
virtual void InternalSetOperandAt(int index, HValue *value)=0
static const int kMaxLength
Definition: objects.h:8922
static HObjectAccess ForLiteralsPointer()
Token::Value token() const
void set_tail(HUseListNode *list)
Unique< Map > first_map() const
void SetOperandPositions(Zone *zone, HSourcePosition left_pos, HSourcePosition right_pos)
UniqueSet< Map > map_set() const
static Representation Tagged()
static const int kNativeContextOffset
Definition: objects.h:7611
Handle< Map > transition_map() const
Handle< JSFunction > closure() const
static HObjectAccess ForMapInstanceSize()
Handle< Object > handle(Isolate *isolate)
void PrintTypeTo(StringStream *stream)
virtual bool HasStackCheck() V8_FINAL V8_OVERRIDE
virtual void UpdateRepresentation(Representation new_rep, HInferRepresentationPhase *h_infer, const char *reason)
virtual bool TryDecompose(DecompositionResult *decomposition) V8_OVERRIDE
virtual bool IsCommutative() const V8_OVERRIDE
HInvokeFunction(HValue *context, HValue *function, Handle< JSFunction > known_function, int argument_count)
static HObjectAccess ForCodeEntryPointer()
T Min(T a, T b)
Definition: utils.h:234
signed short int16_t
Definition: unicode.cc:45
HInstruction(HType type=HType::Tagged())
static const int kSharedFunctionInfoOffset
Definition: objects.h:7521
HBasicBlock * induction_exit_target()
void Remove(E element)
Definition: utils.h:1061
virtual int OperandCount() V8_FINAL V8_OVERRIDE
STATIC_ASSERT(kLastFlag< kBitsPerInt)
Isolate * isolate() const
void RegisterUse(int index, HValue *new_value)
void Add(E element)
Definition: utils.h:1059
static HObjectAccess ForCellValue()
static bool CanTrack(InstanceType type)
Definition: objects-inl.h:1500
static const int kMaxValue
Definition: objects.h:1681
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
Definition: flags.cc:505
#define DECLARE_INSTRUCTION_FACTORY_P5(I, P1, P2, P3, P4, P5)
static HValue * cast(HValue *value)
void AddArgument(HValue *argument, Zone *zone)
void ReplaceAllUsesWith(HValue *other)
HBitwiseBinaryOperation(HValue *context, HValue *left, HValue *right, HType type=HType::Tagged())
static const int32_t kMaxOneByteCharCode
Definition: objects.h:8914
static HConstant * CreateAndInsertAfter(Zone *zone, HValue *context, int32_t value, Representation representation, HInstruction *instruction)
HForInCacheArray * index_cache()
static HAllocate * New(Zone *zone, HValue *context, HValue *size, HType type, PretenureFlag pretenure_flag, InstanceType instance_type, Handle< AllocationSite > allocation_site=Handle< AllocationSite >::null())
SaveFPRegsMode save_doubles() const
static HCheckMaps * New(Zone *zone, HValue *context, HValue *value, SmallMapList *maps, HValue *typecheck=NULL)
static HTransitionElementsKind * New(Zone *zone, HValue *context, HValue *object, Handle< Map > original_map, Handle< Map > transitioned_map)
static HObjectAccess ForHeapNumberValueLowestBits()
Unique< PropertyCell > cell() const
static AllocationSpace TargetSpaceId(InstanceType type)
Definition: heap-inl.h:393
virtual bool KnownSuccessorBlock(HBasicBlock **block) V8_OVERRIDE
virtual bool DataEquals(HValue *other) V8_OVERRIDE
static HObjectAccess ForPrototypeOrInitialMap()
Handle< String > type_literal()
bool IsFastDoubleElementsKind(ElementsKind kind)
static GVNFlagSet AllFlagSet()
HCapturedObject(int length, int id, Zone *zone)
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE
#define DECLARE_INSTRUCTION_FACTORY_P1(I, P1)
static const int kInstanceTypeOffset
Definition: objects.h:6459
HUseIterator uses() const
ChecksRelatedToLength * checks()
InliningKind inlining_kind() const
static HObjectAccess ForJSArrayBufferBackingStore()
HGoto(HBasicBlock *target)
Representation to() const