1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef V8_HYDROGEN_INSTRUCTIONS_H_
6 #define V8_HYDROGEN_INSTRUCTIONS_H_
10 #include "allocation.h"
11 #include "code-stubs.h"
12 #include "conversions.h"
13 #include "data-flow.h"
14 #include "deoptimizer.h"
15 #include "small-pointer-list.h"
16 #include "string-stream.h"
24 // Forward declarations.
28 class HInferRepresentationPhase;
30 class HLoopInformation;
31 class HStoreNamedField;
36 #define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V) \
37 V(ArithmeticBinaryOperation) \
39 V(BitwiseBinaryOperation) \
40 V(ControlInstruction) \
44 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
46 V(AccessArgumentsAt) \
50 V(ArgumentsElements) \
56 V(BoundsCheckBaseIndexInformation) \
58 V(CallWithDescriptor) \
68 V(CheckInstanceType) \
74 V(ClassOfTestAndBranch) \
75 V(CompareNumericAndBranch) \
76 V(CompareHoleAndBranch) \
78 V(CompareMinusZeroAndBranch) \
79 V(CompareObjectEqAndBranch) \
92 V(EnvironmentMarker) \
93 V(ForceRepresentation) \
97 V(GetCachedArrayIndex) \
99 V(HasCachedArrayIndexAndBranch) \
100 V(HasInstanceTypeAndBranch) \
101 V(InnerAllocatedObject) \
103 V(InstanceOfKnownGlobal) \
105 V(IsConstructCallAndBranch) \
106 V(IsObjectAndBranch) \
107 V(IsStringAndBranch) \
109 V(IsUndetectableAndBranch) \
112 V(LoadFieldByIndex) \
113 V(LoadFunctionPrototype) \
115 V(LoadGlobalGeneric) \
117 V(LoadKeyedGeneric) \
119 V(LoadNamedGeneric) \
134 V(SeqStringGetChar) \
135 V(SeqStringSetChar) \
141 V(StoreContextSlot) \
144 V(StoreKeyedGeneric) \
146 V(StoreNamedGeneric) \
148 V(StringCharCodeAt) \
149 V(StringCharFromCode) \
150 V(StringCompareAndBranch) \
153 V(ToFastProperties) \
154 V(TransitionElementsKind) \
155 V(TrapAllocationMemento) \
157 V(TypeofIsAndBranch) \
158 V(UnaryMathOperation) \
159 V(NullarySIMDOperation) \
160 V(UnarySIMDOperation) \
161 V(BinarySIMDOperation) \
162 V(TernarySIMDOperation) \
163 V(QuarternarySIMDOperation) \
168 #define GVN_TRACKED_FLAG_LIST(V) \
171 #define GVN_UNTRACKED_FLAG_LIST(V) \
175 V(BackingStoreFields) \
178 V(DoubleArrayElements) \
188 V(TypedArrayElements)
191 #define DECLARE_ABSTRACT_INSTRUCTION(type) \
192 virtual bool Is##type() const V8_FINAL V8_OVERRIDE { return true; } \
193 static H##type* cast(HValue* value) { \
194 ASSERT(value->Is##type()); \
195 return reinterpret_cast<H##type*>(value); \
199 #define DECLARE_CONCRETE_INSTRUCTION(type) \
200 virtual LInstruction* CompileToLithium( \
201 LChunkBuilder* builder) V8_FINAL V8_OVERRIDE; \
202 static H##type* cast(HValue* value) { \
203 ASSERT(value->Is##type()); \
204 return reinterpret_cast<H##type*>(value); \
206 virtual Opcode opcode() const V8_FINAL V8_OVERRIDE { \
207 return HValue::k##type; \
211 enum PropertyAccessType { LOAD, STORE };
214 class Range V8_FINAL : public ZoneObject {
220 can_be_minus_zero_(false) { }
222 Range(int32_t lower, int32_t upper)
226 can_be_minus_zero_(false) { }
228 int32_t upper() const { return upper_; }
229 int32_t lower() const { return lower_; }
230 Range* next() const { return next_; }
231 Range* CopyClearLower(Zone* zone) const {
232 return new(zone) Range(kMinInt, upper_);
234 Range* CopyClearUpper(Zone* zone) const {
235 return new(zone) Range(lower_, kMaxInt);
237 Range* Copy(Zone* zone) const {
238 Range* result = new(zone) Range(lower_, upper_);
239 result->set_can_be_minus_zero(CanBeMinusZero());
242 int32_t Mask() const;
243 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
244 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
245 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
246 bool CanBeNegative() const { return lower_ < 0; }
247 bool CanBePositive() const { return upper_ > 0; }
248 bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
249 bool IsMostGeneric() const {
250 return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
252 bool IsInSmiRange() const {
253 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
256 lower_ = Max(lower_, Smi::kMinValue);
257 upper_ = Min(upper_, Smi::kMaxValue);
264 void StackUpon(Range* other) {
269 void Intersect(Range* other);
270 void Union(Range* other);
271 void CombinedMax(Range* other);
272 void CombinedMin(Range* other);
274 void AddConstant(int32_t value);
275 void Sar(int32_t value);
276 void Shl(int32_t value);
277 bool AddAndCheckOverflow(const Representation& r, Range* other);
278 bool SubAndCheckOverflow(const Representation& r, Range* other);
279 bool MulAndCheckOverflow(const Representation& r, Range* other);
285 bool can_be_minus_zero_;
289 class HType V8_FINAL {
291 static HType None() { return HType(kNone); }
292 static HType Tagged() { return HType(kTagged); }
293 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
294 static HType TaggedNumber() { return HType(kTaggedNumber); }
295 static HType Smi() { return HType(kSmi); }
296 static HType HeapNumber() { return HType(kHeapNumber); }
297 static HType Float32x4() { return HType(kFloat32x4); }
298 static HType Float64x2() { return HType(kFloat64x2); }
299 static HType Int32x4() { return HType(kInt32x4); }
300 static HType String() { return HType(kString); }
301 static HType Boolean() { return HType(kBoolean); }
302 static HType NonPrimitive() { return HType(kNonPrimitive); }
303 static HType JSArray() { return HType(kJSArray); }
304 static HType JSObject() { return HType(kJSObject); }
306 // Return the weakest (least precise) common type.
307 HType Combine(HType other) {
308 return HType(static_cast<Type>(type_ & other.type_));
311 bool Equals(const HType& other) const {
312 return type_ == other.type_;
315 bool IsSubtypeOf(const HType& other) {
316 return Combine(other).Equals(other);
319 bool IsTaggedPrimitive() const {
320 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
323 bool IsTaggedNumber() const {
324 return ((type_ & kTaggedNumber) == kTaggedNumber);
328 return ((type_ & kSmi) == kSmi);
331 bool IsHeapNumber() const {
332 return ((type_ & kHeapNumber) == kHeapNumber);
335 bool IsFloat32x4() const {
336 return ((type_ & kFloat32x4) == kFloat32x4);
339 bool IsFloat64x2() const {
340 return ((type_ & kFloat64x2) == kFloat64x2);
343 bool IsInt32x4() const {
344 return ((type_ & kInt32x4) == kInt32x4);
347 bool IsSIMD128() const {
348 return IsFloat32x4() || IsFloat64x2() || IsInt32x4();
351 bool IsString() const {
352 return ((type_ & kString) == kString);
355 bool IsNonString() const {
356 return IsTaggedPrimitive() || IsSmi() || IsHeapNumber() || IsSIMD128() ||
357 IsBoolean() || IsJSArray();
360 bool IsBoolean() const {
361 return ((type_ & kBoolean) == kBoolean);
364 bool IsNonPrimitive() const {
365 return ((type_ & kNonPrimitive) == kNonPrimitive);
368 bool IsJSArray() const {
369 return ((type_ & kJSArray) == kJSArray);
372 bool IsJSObject() const {
373 return ((type_ & kJSObject) == kJSObject);
376 bool IsHeapObject() const {
377 return IsHeapNumber() || IsSIMD128() || IsString() ||
378 IsBoolean() || IsNonPrimitive();
381 bool ToStringOrToNumberCanBeObserved(Representation representation) {
383 case kTaggedPrimitive: // fallthru
384 case kTaggedNumber: // fallthru
385 case kSmi: // fallthru
386 case kHeapNumber: // fallthru
387 case kFloat32x4: // fallthru
388 case kFloat64x2: // fallthru
389 case kInt32x4: // fallthru
390 case kString: // fallthru
393 case kJSArray: // fallthru
399 return !representation.IsSmiOrInteger32() && !representation.IsDouble();
402 static HType TypeFromValue(Handle<Object> value);
403 static HType TypeFromRepresentation(Representation representation);
405 const char* ToString();
409 kNone = 0x0, // 0000 0000 0000 0000
410 kTagged = 0x1, // 0000 0000 0000 0001
411 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
412 kTaggedNumber = 0xd, // 0000 0000 0000 1101
413 kSmi = 0x1d, // 0000 0000 0001 1101
414 kHeapNumber = 0x2d, // 0000 0000 0010 1101
415 kFloat32x4 = 0x45, // 0000 0000 0100 0101
416 kFloat64x2 = 0x85, // 0000 0000 1000 0101
417 kInt32x4 = 0x105, // 0000 0001 0000 0101
418 kString = 0x205, // 0000 0010 0000 0101
419 kBoolean = 0x405, // 0000 0100 1000 0101
420 kNonPrimitive = 0x801, // 0000 1000 0000 0001
421 kJSObject = 0x1801, // 0001 1000 0000 0001
422 kJSArray = 0x3801 // 0011 1000 0000 0001
425 // Make sure type fits in int16.
426 STATIC_ASSERT(kJSArray < (1 << (2 * kBitsPerByte)));
428 explicit HType(Type t) : type_(t) { }
434 class HUseListNode: public ZoneObject {
436 HUseListNode(HValue* value, int index, HUseListNode* tail)
437 : tail_(tail), value_(value), index_(index) {
440 HUseListNode* tail();
441 HValue* value() const { return value_; }
442 int index() const { return index_; }
444 void set_tail(HUseListNode* list) { tail_ = list; }
448 tail_ = reinterpret_cast<HUseListNode*>(1);
461 // We reuse use list nodes behind the scenes as uses are added and deleted.
462 // This class is the safe way to iterate uses while deleting them.
463 class HUseIterator V8_FINAL BASE_EMBEDDED {
465 bool Done() { return current_ == NULL; }
479 explicit HUseIterator(HUseListNode* head);
481 HUseListNode* current_;
490 // All tracked flags should appear before untracked ones.
492 // Declare global value numbering flags.
493 #define DECLARE_FLAG(Type) k##Type,
494 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
495 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
497 #define COUNT_FLAG(Type) + 1
498 kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG),
499 kNumberOfUntrackedSideEffects = 0 GVN_UNTRACKED_FLAG_LIST(COUNT_FLAG),
501 kNumberOfFlags = kNumberOfTrackedSideEffects + kNumberOfUntrackedSideEffects
505 static inline GVNFlag GVNFlagFromInt(int i) {
507 ASSERT(i < kNumberOfFlags);
508 return static_cast<GVNFlag>(i);
512 class DecompositionResult V8_FINAL BASE_EMBEDDED {
514 DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
516 HValue* base() { return base_; }
517 int offset() { return offset_; }
518 int scale() { return scale_; }
520 bool Apply(HValue* other_base, int other_offset, int other_scale = 0) {
523 offset_ = other_offset;
524 scale_ = other_scale;
529 offset_ += other_offset;
530 scale_ = other_scale;
538 void SwapValues(HValue** other_base, int* other_offset, int* other_scale) {
539 swap(&base_, other_base);
540 swap(&offset_, other_offset);
541 swap(&scale_, other_scale);
545 template <class T> void swap(T* a, T* b) {
557 typedef EnumSet<GVNFlag, int32_t> GVNFlagSet;
560 // This class encapsulates encoding and decoding of sources positions from
561 // which hydrogen values originated.
562 // When FLAG_track_hydrogen_positions is set this object encodes the
563 // identifier of the inlining and absolute offset from the start of the
565 // When the flag is not set we simply track absolute offset from the
567 class HSourcePosition {
569 HSourcePosition(const HSourcePosition& other) : value_(other.value_) { }
571 static HSourcePosition Unknown() {
572 return HSourcePosition(RelocInfo::kNoPosition);
575 bool IsUnknown() const { return value_ == RelocInfo::kNoPosition; }
577 int position() const { return PositionField::decode(value_); }
578 void set_position(int position) {
579 if (FLAG_hydrogen_track_positions) {
580 value_ = static_cast<int>(PositionField::update(value_, position));
586 int inlining_id() const { return InliningIdField::decode(value_); }
587 void set_inlining_id(int inlining_id) {
588 if (FLAG_hydrogen_track_positions) {
589 value_ = static_cast<int>(InliningIdField::update(value_, inlining_id));
593 int raw() const { return value_; }
595 void PrintTo(FILE* f);
598 typedef BitField<int, 0, 9> InliningIdField;
600 // Offset from the start of the inlined function.
601 typedef BitField<int, 9, 22> PositionField;
603 // On HPositionInfo can use this constructor.
604 explicit HSourcePosition(int value) : value_(value) { }
606 friend class HPositionInfo;
608 // If FLAG_hydrogen_track_positions is set contains bitfields InliningIdField
609 // and PositionField.
610 // Otherwise contains absolute offset from the script start.
615 class HValue : public ZoneObject {
617 static const int kNoNumber = -1;
620 kFlexibleRepresentation,
622 // Participate in Global Value Numbering, i.e. elimination of
623 // unnecessary recomputations. If an instruction sets this flag, it must
624 // implement DataEquals(), which will be used to determine if other
625 // occurrences of the instruction are indeed the same.
627 // Track instructions that are dominating side effects. If an instruction
628 // sets this flag, it must implement HandleSideEffectDominator() and should
629 // indicate which side effects to track by setting GVN flags.
630 kTrackSideEffectDominators,
637 kAllowUndefinedAsNaN,
640 kAllUsesTruncatingToInt32,
642 kAllUsesTruncatingToSmi,
643 // Set after an instruction is killed.
645 // Instructions that are allowed to produce full range unsigned integer
646 // values are marked with kUint32 flag. If arithmetic shift or a load from
647 // EXTERNAL_UINT32_ELEMENTS array is not marked with this flag
648 // it will deoptimize if result does not fit into signed integer range.
649 // HGraph::ComputeSafeUint32Operations is responsible for setting this
652 kHasNoObservableSideEffects,
653 // Indicates the instruction is live during dead code elimination.
656 // HEnvironmentMarkers are deleted before dead code
657 // elimination takes place, so they can repurpose the kIsLive flag:
658 kEndsLiveRange = kIsLive,
660 // TODO(everyone): Don't forget to update this!
664 STATIC_ASSERT(kLastFlag < kBitsPerInt);
666 static HValue* cast(HValue* value) { return value; }
669 // Declare a unique enum value for each hydrogen instruction.
670 #define DECLARE_OPCODE(type) k##type,
671 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
673 #undef DECLARE_OPCODE
675 virtual Opcode opcode() const = 0;
677 // Declare a non-virtual predicates for each concrete HInstruction or HValue.
678 #define DECLARE_PREDICATE(type) \
679 bool Is##type() const { return opcode() == k##type; }
680 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
681 #undef DECLARE_PREDICATE
682 bool IsPhi() const { return opcode() == kPhi; }
684 // Declare virtual predicates for abstract HInstruction or HValue
685 #define DECLARE_PREDICATE(type) \
686 virtual bool Is##type() const { return false; }
687 HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
688 #undef DECLARE_PREDICATE
690 HValue(HType type = HType::Tagged())
697 range_poisoned_(false),
702 virtual HSourcePosition position() const {
703 return HSourcePosition::Unknown();
705 virtual HSourcePosition operand_position(int index) const {
709 HBasicBlock* block() const { return block_; }
710 void SetBlock(HBasicBlock* block);
712 // Note: Never call this method for an unlinked value.
713 Isolate* isolate() const;
715 int id() const { return id_; }
716 void set_id(int id) { id_ = id; }
718 HUseIterator uses() const { return HUseIterator(use_list_); }
720 virtual bool EmitAtUses() { return false; }
722 Representation representation() const { return representation_; }
723 void ChangeRepresentation(Representation r) {
724 ASSERT(CheckFlag(kFlexibleRepresentation));
725 ASSERT(!CheckFlag(kCannotBeTagged) || !r.IsTagged());
726 RepresentationChanged(r);
729 // Tagged is the bottom of the lattice, don't go any further.
730 ClearFlag(kFlexibleRepresentation);
733 virtual void AssumeRepresentation(Representation r);
735 virtual Representation KnownOptimalRepresentation() {
736 Representation r = representation();
739 if (t.IsSmi()) return Representation::Smi();
740 if (t.IsHeapNumber()) return Representation::Double();
741 if (t.IsFloat32x4()) return Representation::Float32x4();
742 if (t.IsFloat64x2()) return Representation::Float64x2();
743 if (t.IsInt32x4()) return Representation::Int32x4();
744 if (t.IsHeapObject()) return r;
745 return Representation::None();
750 HType type() const { return type_; }
751 void set_type(HType new_type) {
752 ASSERT(new_type.IsSubtypeOf(type_));
756 bool IsHeapObject() {
757 return representation_.IsHeapObject() || type_.IsHeapObject();
760 // There are HInstructions that do not really change a value, they
761 // only add pieces of information to it (like bounds checks, map checks,
763 // We call these instructions "informative definitions", or "iDef".
764 // One of the iDef operands is special because it is the value that is
765 // "transferred" to the output, we call it the "redefined operand".
766 // If an HValue is an iDef it must override RedefinedOperandIndex() so that
767 // it does not return kNoRedefinedOperand;
768 static const int kNoRedefinedOperand = -1;
769 virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
770 bool IsInformativeDefinition() {
771 return RedefinedOperandIndex() != kNoRedefinedOperand;
773 HValue* RedefinedOperand() {
774 int index = RedefinedOperandIndex();
775 return index == kNoRedefinedOperand ? NULL : OperandAt(index);
778 bool CanReplaceWithDummyUses();
780 virtual int argument_delta() const { return 0; }
782 // A purely informative definition is an idef that will not emit code and
783 // should therefore be removed from the graph in the RestoreActualValues
784 // phase (so that live ranges will be shorter).
785 virtual bool IsPurelyInformativeDefinition() { return false; }
787 // This method must always return the original HValue SSA definition,
788 // regardless of any chain of iDefs of this value.
789 HValue* ActualValue() {
790 HValue* value = this;
792 while ((index = value->RedefinedOperandIndex()) != kNoRedefinedOperand) {
793 value = value->OperandAt(index);
798 bool IsInteger32Constant();
799 int32_t GetInteger32Constant();
800 bool EqualsInteger32Constant(int32_t value);
802 bool IsDefinedAfter(HBasicBlock* other) const;
805 virtual int OperandCount() = 0;
806 virtual HValue* OperandAt(int index) const = 0;
807 void SetOperandAt(int index, HValue* value);
809 void DeleteAndReplaceWith(HValue* other);
810 void ReplaceAllUsesWith(HValue* other);
811 bool HasNoUses() const { return use_list_ == NULL; }
812 bool HasMultipleUses() const {
813 return use_list_ != NULL && use_list_->tail() != NULL;
815 int UseCount() const;
817 // Mark this HValue as dead and to be removed from other HValues' use lists.
820 int flags() const { return flags_; }
821 void SetFlag(Flag f) { flags_ |= (1 << f); }
822 void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
823 bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
824 void CopyFlag(Flag f, HValue* other) {
825 if (other->CheckFlag(f)) SetFlag(f);
828 // Returns true if the flag specified is set for all uses, false otherwise.
829 bool CheckUsesForFlag(Flag f) const;
830 // Same as before and the first one without the flag is returned in value.
831 bool CheckUsesForFlag(Flag f, HValue** value) const;
832 // Returns true if the flag specified is set for all uses, and this set
833 // of uses is non-empty.
834 bool HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const;
836 GVNFlagSet ChangesFlags() const { return changes_flags_; }
837 GVNFlagSet DependsOnFlags() const { return depends_on_flags_; }
838 void SetChangesFlag(GVNFlag f) { changes_flags_.Add(f); }
839 void SetDependsOnFlag(GVNFlag f) { depends_on_flags_.Add(f); }
840 void ClearChangesFlag(GVNFlag f) { changes_flags_.Remove(f); }
841 void ClearDependsOnFlag(GVNFlag f) { depends_on_flags_.Remove(f); }
842 bool CheckChangesFlag(GVNFlag f) const {
843 return changes_flags_.Contains(f);
845 bool CheckDependsOnFlag(GVNFlag f) const {
846 return depends_on_flags_.Contains(f);
848 void SetAllSideEffects() { changes_flags_.Add(AllSideEffectsFlagSet()); }
849 void ClearAllSideEffects() {
850 changes_flags_.Remove(AllSideEffectsFlagSet());
852 bool HasSideEffects() const {
853 return changes_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
855 bool HasObservableSideEffects() const {
856 return !CheckFlag(kHasNoObservableSideEffects) &&
857 changes_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
860 GVNFlagSet SideEffectFlags() const {
861 GVNFlagSet result = ChangesFlags();
862 result.Intersect(AllSideEffectsFlagSet());
866 GVNFlagSet ObservableChangesFlags() const {
867 GVNFlagSet result = ChangesFlags();
868 result.Intersect(AllObservableSideEffectsFlagSet());
872 Range* range() const {
873 ASSERT(!range_poisoned_);
876 bool HasRange() const {
877 ASSERT(!range_poisoned_);
878 return range_ != NULL;
881 void PoisonRange() { range_poisoned_ = true; }
883 void AddNewRange(Range* r, Zone* zone);
884 void RemoveLastAddedRange();
885 void ComputeInitialRange(Zone* zone);
887 // Escape analysis helpers.
888 virtual bool HasEscapingOperandAt(int index) { return true; }
889 virtual bool HasOutOfBoundsAccess(int size) { return false; }
891 // Representation helpers.
892 virtual Representation observed_input_representation(int index) {
893 return Representation::None();
895 virtual Representation RequiredInputRepresentation(int index) = 0;
896 virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
898 // This gives the instruction an opportunity to replace itself with an
899 // instruction that does the same in some better way. To replace an
900 // instruction with a new one, first add the new instruction to the graph,
901 // then return it. Return NULL to have the instruction deleted.
902 virtual HValue* Canonicalize() { return this; }
904 bool Equals(HValue* other);
905 virtual intptr_t Hashcode();
907 // Compute unique ids upfront that is safe wrt GC and concurrent compilation.
908 virtual void FinalizeUniqueness() { }
911 virtual void PrintTo(StringStream* stream) = 0;
912 void PrintNameTo(StringStream* stream);
913 void PrintTypeTo(StringStream* stream);
914 void PrintChangesTo(StringStream* stream);
916 const char* Mnemonic() const;
918 // Type information helpers.
919 bool HasMonomorphicJSObjectType();
921 // TODO(mstarzinger): For now instructions can override this function to
922 // specify statically known types, once HType can convey more information
923 // it should be based on the HType.
924 virtual Handle<Map> GetMonomorphicJSObjectMap() { return Handle<Map>(); }
926 // Updated the inferred type of this instruction and returns true if
928 bool UpdateInferredType();
930 virtual HType CalculateInferredType();
932 // This function must be overridden for instructions which have the
933 // kTrackSideEffectDominators flag set, to track instructions that are
934 // dominating side effects.
935 // It returns true if it removed an instruction which had side effects.
936 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
942 // Check if this instruction has some reason that prevents elimination.
943 bool CannotBeEliminated() const {
944 return HasObservableSideEffects() || !IsDeletable();
948 virtual void Verify() = 0;
951 virtual bool TryDecompose(DecompositionResult* decomposition) {
952 if (RedefinedOperand() != NULL) {
953 return RedefinedOperand()->TryDecompose(decomposition);
959 // Returns true conservatively if the program might be able to observe a
960 // ToString() operation on this value.
961 bool ToStringCanBeObserved() const {
962 return type().ToStringOrToNumberCanBeObserved(representation());
965 // Returns true conservatively if the program might be able to observe a
966 // ToNumber() operation on this value.
967 bool ToNumberCanBeObserved() const {
968 return type().ToStringOrToNumberCanBeObserved(representation());
971 MinusZeroMode GetMinusZeroMode() {
972 return CheckFlag(kBailoutOnMinusZero)
973 ? FAIL_ON_MINUS_ZERO : TREAT_MINUS_ZERO_AS_ZERO;
977 // This function must be overridden for instructions with flag kUseGVN, to
978 // compare the non-Operand parts of the instruction.
979 virtual bool DataEquals(HValue* other) {
984 virtual Representation RepresentationFromInputs() {
985 return representation();
987 virtual Representation RepresentationFromUses();
988 Representation RepresentationFromUseRequirements();
990 virtual void UpdateRepresentation(Representation new_rep,
991 HInferRepresentationPhase* h_infer,
993 void AddDependantsToWorklist(HInferRepresentationPhase* h_infer);
995 virtual void RepresentationChanged(Representation to) { }
997 virtual Range* InferRange(Zone* zone);
998 virtual void DeleteFromGraph() = 0;
999 virtual void InternalSetOperandAt(int index, HValue* value) = 0;
1000 void clear_block() {
1001 ASSERT(block_ != NULL);
1005 void set_representation(Representation r) {
1006 ASSERT(representation_.IsNone() && !r.IsNone());
1007 representation_ = r;
1010 static GVNFlagSet AllFlagSet() {
1012 #define ADD_FLAG(Type) result.Add(k##Type);
1013 GVN_TRACKED_FLAG_LIST(ADD_FLAG)
1014 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
1019 // A flag mask to mark an instruction as having arbitrary side effects.
1020 static GVNFlagSet AllSideEffectsFlagSet() {
1021 GVNFlagSet result = AllFlagSet();
1022 result.Remove(kOsrEntries);
1026 // A flag mask of all side effects that can make observable changes in
1027 // an executing program (i.e. are not safe to repeat, move or remove);
1028 static GVNFlagSet AllObservableSideEffectsFlagSet() {
1029 GVNFlagSet result = AllFlagSet();
1030 result.Remove(kNewSpacePromotion);
1031 result.Remove(kElementsKind);
1032 result.Remove(kElementsPointer);
1033 result.Remove(kMaps);
1037 // Remove the matching use from the use list if present. Returns the
1038 // removed list node or NULL.
1039 HUseListNode* RemoveUse(HValue* value, int index);
1041 void RegisterUse(int index, HValue* new_value);
1043 HBasicBlock* block_;
1045 // The id of this instruction in the hydrogen graph, assigned when first
1046 // added to the graph. Reflects creation order.
1049 Representation representation_;
1051 HUseListNode* use_list_;
1054 bool range_poisoned_;
1057 GVNFlagSet changes_flags_;
1058 GVNFlagSet depends_on_flags_;
1061 virtual bool IsDeletable() const { return false; }
1063 DISALLOW_COPY_AND_ASSIGN(HValue);
1067 #define DECLARE_INSTRUCTION_FACTORY_P0(I) \
1068 static I* New(Zone* zone, HValue* context) { \
1069 return new(zone) I(); \
1072 #define DECLARE_INSTRUCTION_FACTORY_P1(I, P1) \
1073 static I* New(Zone* zone, HValue* context, P1 p1) { \
1074 return new(zone) I(p1); \
1077 #define DECLARE_INSTRUCTION_FACTORY_P2(I, P1, P2) \
1078 static I* New(Zone* zone, HValue* context, P1 p1, P2 p2) { \
1079 return new(zone) I(p1, p2); \
1082 #define DECLARE_INSTRUCTION_FACTORY_P3(I, P1, P2, P3) \
1083 static I* New(Zone* zone, HValue* context, P1 p1, P2 p2, P3 p3) { \
1084 return new(zone) I(p1, p2, p3); \
1087 #define DECLARE_INSTRUCTION_FACTORY_P4(I, P1, P2, P3, P4) \
1088 static I* New(Zone* zone, \
1094 return new(zone) I(p1, p2, p3, p4); \
1097 #define DECLARE_INSTRUCTION_FACTORY_P5(I, P1, P2, P3, P4, P5) \
1098 static I* New(Zone* zone, \
1105 return new(zone) I(p1, p2, p3, p4, p5); \
1108 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(I) \
1109 static I* New(Zone* zone, HValue* context) { \
1110 return new(zone) I(context); \
1113 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(I, P1) \
1114 static I* New(Zone* zone, HValue* context, P1 p1) { \
1115 return new(zone) I(context, p1); \
1118 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(I, P1, P2) \
1119 static I* New(Zone* zone, HValue* context, P1 p1, P2 p2) { \
1120 return new(zone) I(context, p1, p2); \
1123 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(I, P1, P2, P3) \
1124 static I* New(Zone* zone, HValue* context, P1 p1, P2 p2, P3 p3) { \
1125 return new(zone) I(context, p1, p2, p3); \
1128 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(I, P1, P2, P3, P4) \
1129 static I* New(Zone* zone, \
1135 return new(zone) I(context, p1, p2, p3, p4); \
1138 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(I, P1, P2, P3, P4, P5) \
1139 static I* New(Zone* zone, \
1146 return new(zone) I(context, p1, p2, p3, p4, p5); \
1150 // A helper class to represent per-operand position information attached to
1151 // the HInstruction in the compact form. Uses tagging to distinguish between
1152 // case when only instruction's position is available and case when operands'
1153 // positions are also available.
1154 // In the first case it contains intruction's position as a tagged value.
1155 // In the second case it points to an array which contains instruction's
1156 // position and operands' positions.
1157 class HPositionInfo {
1159 explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { }
1161 HSourcePosition position() const {
1162 if (has_operand_positions()) {
1163 return operand_positions()[kInstructionPosIndex];
1165 return HSourcePosition(static_cast<int>(UntagPosition(data_)));
1168 void set_position(HSourcePosition pos) {
1169 if (has_operand_positions()) {
1170 operand_positions()[kInstructionPosIndex] = pos;
1172 data_ = TagPosition(pos.raw());
1176 void ensure_storage_for_operand_positions(Zone* zone, int operand_count) {
1177 if (has_operand_positions()) {
1181 const int length = kFirstOperandPosIndex + operand_count;
1182 HSourcePosition* positions =
1183 zone->NewArray<HSourcePosition>(length);
1184 for (int i = 0; i < length; i++) {
1185 positions[i] = HSourcePosition::Unknown();
1188 const HSourcePosition pos = position();
1189 data_ = reinterpret_cast<intptr_t>(positions);
1192 ASSERT(has_operand_positions());
1195 HSourcePosition operand_position(int idx) const {
1196 if (!has_operand_positions()) {
1199 return *operand_position_slot(idx);
1202 void set_operand_position(int idx, HSourcePosition pos) {
1203 *operand_position_slot(idx) = pos;
1207 static const intptr_t kInstructionPosIndex = 0;
1208 static const intptr_t kFirstOperandPosIndex = 1;
1210 HSourcePosition* operand_position_slot(int idx) const {
1211 ASSERT(has_operand_positions());
1212 return &(operand_positions()[kFirstOperandPosIndex + idx]);
1215 bool has_operand_positions() const {
1216 return !IsTaggedPosition(data_);
1219 HSourcePosition* operand_positions() const {
1220 ASSERT(has_operand_positions());
1221 return reinterpret_cast<HSourcePosition*>(data_);
1224 static const intptr_t kPositionTag = 1;
1225 static const intptr_t kPositionShift = 1;
1226 static bool IsTaggedPosition(intptr_t val) {
1227 return (val & kPositionTag) != 0;
1229 static intptr_t UntagPosition(intptr_t val) {
1230 ASSERT(IsTaggedPosition(val));
1231 return val >> kPositionShift;
1233 static intptr_t TagPosition(intptr_t val) {
1234 const intptr_t result = (val << kPositionShift) | kPositionTag;
1235 ASSERT(UntagPosition(result) == val);
1243 class HInstruction : public HValue {
1245 HInstruction* next() const { return next_; }
1246 HInstruction* previous() const { return previous_; }
1248 virtual void PrintTo(StringStream* stream) V8_OVERRIDE;
1249 virtual void PrintDataTo(StringStream* stream);
1251 bool IsLinked() const { return block() != NULL; }
1254 void InsertBefore(HInstruction* next);
1256 template<class T> T* Prepend(T* instr) {
1257 instr->InsertBefore(this);
1261 void InsertAfter(HInstruction* previous);
1263 template<class T> T* Append(T* instr) {
1264 instr->InsertAfter(this);
1268 // The position is a write-once variable.
1269 virtual HSourcePosition position() const V8_OVERRIDE {
1270 return HSourcePosition(position_.position());
1272 bool has_position() const {
1273 return !position().IsUnknown();
1275 void set_position(HSourcePosition position) {
1276 ASSERT(!has_position());
1277 ASSERT(!position.IsUnknown());
1278 position_.set_position(position);
1281 virtual HSourcePosition operand_position(int index) const V8_OVERRIDE {
1282 const HSourcePosition pos = position_.operand_position(index);
1283 return pos.IsUnknown() ? position() : pos;
1285 void set_operand_position(Zone* zone, int index, HSourcePosition pos) {
1286 ASSERT(0 <= index && index < OperandCount());
1287 position_.ensure_storage_for_operand_positions(zone, OperandCount());
1288 position_.set_operand_position(index, pos);
1291 bool CanTruncateToSmi() const { return CheckFlag(kTruncatingToSmi); }
1292 bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
1294 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
1297 virtual void Verify() V8_OVERRIDE;
1300 bool CanDeoptimize();
1302 virtual bool HasStackCheck() { return false; }
1304 DECLARE_ABSTRACT_INSTRUCTION(Instruction)
1307 HInstruction(HType type = HType::Tagged())
1311 position_(RelocInfo::kNoPosition) {
1312 SetDependsOnFlag(kOsrEntries);
1315 virtual void DeleteFromGraph() V8_OVERRIDE { Unlink(); }
1318 void InitializeAsFirst(HBasicBlock* block) {
1319 ASSERT(!IsLinked());
1323 void PrintMnemonicTo(StringStream* stream);
1325 HInstruction* next_;
1326 HInstruction* previous_;
1327 HPositionInfo position_;
1329 friend class HBasicBlock;
1334 class HTemplateInstruction : public HInstruction {
1336 virtual int OperandCount() V8_FINAL V8_OVERRIDE { return V; }
1337 virtual HValue* OperandAt(int i) const V8_FINAL V8_OVERRIDE {
1342 HTemplateInstruction(HType type = HType::Tagged()) : HInstruction(type) {}
1344 virtual void InternalSetOperandAt(int i, HValue* value) V8_FINAL V8_OVERRIDE {
1349 EmbeddedContainer<HValue*, V> inputs_;
1353 class HControlInstruction : public HInstruction {
1355 virtual HBasicBlock* SuccessorAt(int i) = 0;
1356 virtual int SuccessorCount() = 0;
1357 virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
1359 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1361 virtual bool KnownSuccessorBlock(HBasicBlock** block) {
1366 HBasicBlock* FirstSuccessor() {
1367 return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
1369 HBasicBlock* SecondSuccessor() {
1370 return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
1374 HBasicBlock* swap = SuccessorAt(0);
1375 SetSuccessorAt(0, SuccessorAt(1));
1376 SetSuccessorAt(1, swap);
1379 DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
1383 class HSuccessorIterator V8_FINAL BASE_EMBEDDED {
1385 explicit HSuccessorIterator(HControlInstruction* instr)
1386 : instr_(instr), current_(0) { }
1388 bool Done() { return current_ >= instr_->SuccessorCount(); }
1389 HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
1390 void Advance() { current_++; }
1393 HControlInstruction* instr_;
1398 template<int S, int V>
1399 class HTemplateControlInstruction : public HControlInstruction {
1401 int SuccessorCount() V8_OVERRIDE { return S; }
1402 HBasicBlock* SuccessorAt(int i) V8_OVERRIDE { return successors_[i]; }
1403 void SetSuccessorAt(int i, HBasicBlock* block) V8_OVERRIDE {
1404 successors_[i] = block;
1407 int OperandCount() V8_OVERRIDE { return V; }
1408 HValue* OperandAt(int i) const V8_OVERRIDE { return inputs_[i]; }
1412 void InternalSetOperandAt(int i, HValue* value) V8_OVERRIDE {
1417 EmbeddedContainer<HBasicBlock*, S> successors_;
1418 EmbeddedContainer<HValue*, V> inputs_;
1422 class HBlockEntry V8_FINAL : public HTemplateInstruction<0> {
1424 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1425 return Representation::None();
1428 DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
1432 class HDummyUse V8_FINAL : public HTemplateInstruction<1> {
1434 explicit HDummyUse(HValue* value)
1435 : HTemplateInstruction<1>(HType::Smi()) {
1436 SetOperandAt(0, value);
1437 // Pretend to be a Smi so that the HChange instructions inserted
1438 // before any use generate as little code as possible.
1439 set_representation(Representation::Tagged());
1442 HValue* value() { return OperandAt(0); }
1444 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
1445 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1446 return Representation::None();
1449 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1451 DECLARE_CONCRETE_INSTRUCTION(DummyUse);
1455 // Inserts an int3/stop break instruction for debugging purposes.
1456 class HDebugBreak V8_FINAL : public HTemplateInstruction<0> {
1458 DECLARE_INSTRUCTION_FACTORY_P0(HDebugBreak);
1460 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1461 return Representation::None();
1464 DECLARE_CONCRETE_INSTRUCTION(DebugBreak)
1468 class HGoto V8_FINAL : public HTemplateControlInstruction<1, 0> {
1470 explicit HGoto(HBasicBlock* target) {
1471 SetSuccessorAt(0, target);
1474 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE {
1475 *block = FirstSuccessor();
1479 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1480 return Representation::None();
1483 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1485 DECLARE_CONCRETE_INSTRUCTION(Goto)
1489 class HDeoptimize V8_FINAL : public HTemplateControlInstruction<1, 0> {
1491 static HDeoptimize* New(Zone* zone,
1494 Deoptimizer::BailoutType type,
1495 HBasicBlock* unreachable_continuation) {
1496 return new(zone) HDeoptimize(reason, type, unreachable_continuation);
1499 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE {
1504 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1505 return Representation::None();
1508 const char* reason() const { return reason_; }
1509 Deoptimizer::BailoutType type() { return type_; }
1511 DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
1514 explicit HDeoptimize(const char* reason,
1515 Deoptimizer::BailoutType type,
1516 HBasicBlock* unreachable_continuation)
1517 : reason_(reason), type_(type) {
1518 SetSuccessorAt(0, unreachable_continuation);
1521 const char* reason_;
1522 Deoptimizer::BailoutType type_;
1526 class HUnaryControlInstruction : public HTemplateControlInstruction<2, 1> {
1528 HUnaryControlInstruction(HValue* value,
1529 HBasicBlock* true_target,
1530 HBasicBlock* false_target) {
1531 SetOperandAt(0, value);
1532 SetSuccessorAt(0, true_target);
1533 SetSuccessorAt(1, false_target);
1536 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1538 HValue* value() { return OperandAt(0); }
1542 class HBranch V8_FINAL : public HUnaryControlInstruction {
1544 DECLARE_INSTRUCTION_FACTORY_P1(HBranch, HValue*);
1545 DECLARE_INSTRUCTION_FACTORY_P2(HBranch, HValue*,
1546 ToBooleanStub::Types);
1547 DECLARE_INSTRUCTION_FACTORY_P4(HBranch, HValue*,
1548 ToBooleanStub::Types,
1549 HBasicBlock*, HBasicBlock*);
1551 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1552 return Representation::None();
1554 virtual Representation observed_input_representation(int index) V8_OVERRIDE;
1556 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
1558 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1560 ToBooleanStub::Types expected_input_types() const {
1561 return expected_input_types_;
1564 DECLARE_CONCRETE_INSTRUCTION(Branch)
1567 HBranch(HValue* value,
1568 ToBooleanStub::Types expected_input_types = ToBooleanStub::Types(),
1569 HBasicBlock* true_target = NULL,
1570 HBasicBlock* false_target = NULL)
1571 : HUnaryControlInstruction(value, true_target, false_target),
1572 expected_input_types_(expected_input_types) {
1573 SetFlag(kAllowUndefinedAsNaN);
1576 ToBooleanStub::Types expected_input_types_;
1580 class HCompareMap V8_FINAL : public HUnaryControlInstruction {
1582 DECLARE_INSTRUCTION_FACTORY_P2(HCompareMap, HValue*, Handle<Map>);
1583 DECLARE_INSTRUCTION_FACTORY_P4(HCompareMap, HValue*, Handle<Map>,
1584 HBasicBlock*, HBasicBlock*);
1586 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE {
1587 if (known_successor_index() != kNoKnownSuccessorIndex) {
1588 *block = SuccessorAt(known_successor_index());
1595 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1597 static const int kNoKnownSuccessorIndex = -1;
1598 int known_successor_index() const { return known_successor_index_; }
1599 void set_known_successor_index(int known_successor_index) {
1600 known_successor_index_ = known_successor_index;
1603 Unique<Map> map() const { return map_; }
1605 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1606 return Representation::Tagged();
1609 DECLARE_CONCRETE_INSTRUCTION(CompareMap)
1612 virtual int RedefinedOperandIndex() { return 0; }
1615 HCompareMap(HValue* value,
1617 HBasicBlock* true_target = NULL,
1618 HBasicBlock* false_target = NULL)
1619 : HUnaryControlInstruction(value, true_target, false_target),
1620 known_successor_index_(kNoKnownSuccessorIndex), map_(Unique<Map>(map)) {
1621 ASSERT(!map.is_null());
1622 set_representation(Representation::Tagged());
1625 int known_successor_index_;
1630 class HContext V8_FINAL : public HTemplateInstruction<0> {
1632 static HContext* New(Zone* zone) {
1633 return new(zone) HContext();
1636 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1637 return Representation::None();
1640 DECLARE_CONCRETE_INSTRUCTION(Context)
1643 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1647 set_representation(Representation::Tagged());
1651 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1655 class HReturn V8_FINAL : public HTemplateControlInstruction<0, 3> {
1657 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HReturn, HValue*, HValue*);
1658 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HReturn, HValue*);
1660 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1661 // TODO(titzer): require an Int32 input for faster returns.
1662 if (index == 2) return Representation::Smi();
1663 return Representation::Tagged();
1666 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1668 HValue* value() { return OperandAt(0); }
1669 HValue* context() { return OperandAt(1); }
1670 HValue* parameter_count() { return OperandAt(2); }
1672 DECLARE_CONCRETE_INSTRUCTION(Return)
1675 HReturn(HValue* context, HValue* value, HValue* parameter_count = 0) {
1676 SetOperandAt(0, value);
1677 SetOperandAt(1, context);
1678 SetOperandAt(2, parameter_count);
1683 class HAbnormalExit V8_FINAL : public HTemplateControlInstruction<0, 0> {
1685 DECLARE_INSTRUCTION_FACTORY_P0(HAbnormalExit);
1687 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1688 return Representation::None();
1691 DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
1697 class HUnaryOperation : public HTemplateInstruction<1> {
1699 HUnaryOperation(HValue* value, HType type = HType::Tagged())
1700 : HTemplateInstruction<1>(type) {
1701 SetOperandAt(0, value);
1704 static HUnaryOperation* cast(HValue* value) {
1705 return reinterpret_cast<HUnaryOperation*>(value);
1708 HValue* value() const { return OperandAt(0); }
1709 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1713 class HUseConst V8_FINAL : public HUnaryOperation {
1715 DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue*);
1717 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1718 return Representation::None();
1721 DECLARE_CONCRETE_INSTRUCTION(UseConst)
1724 explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
1728 class HForceRepresentation V8_FINAL : public HTemplateInstruction<1> {
1730 static HInstruction* New(Zone* zone, HValue* context, HValue* value,
1731 Representation required_representation);
1733 HValue* value() { return OperandAt(0); }
1735 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1736 return representation(); // Same as the output representation.
1739 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1741 DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
1744 HForceRepresentation(HValue* value, Representation required_representation) {
1745 SetOperandAt(0, value);
1746 set_representation(required_representation);
1751 class HChange V8_FINAL : public HUnaryOperation {
1753 HChange(HValue* value,
1755 bool is_truncating_to_smi,
1756 bool is_truncating_to_int32)
1757 : HUnaryOperation(value) {
1758 ASSERT(!value->representation().IsNone());
1759 ASSERT(!to.IsNone());
1760 ASSERT(!value->representation().Equals(to));
1761 set_representation(to);
1763 SetFlag(kCanOverflow);
1764 if (is_truncating_to_smi && to.IsSmi()) {
1765 SetFlag(kTruncatingToSmi);
1766 SetFlag(kTruncatingToInt32);
1768 if (is_truncating_to_int32) SetFlag(kTruncatingToInt32);
1769 if (value->representation().IsSmi() || value->type().IsSmi()) {
1770 set_type(HType::Smi());
1772 if (to.IsFloat32x4()) {
1773 set_type(HType::Float32x4());
1774 } else if (to.IsFloat64x2()) {
1775 set_type(HType::Float64x2());
1776 } else if (to.IsInt32x4()) {
1777 set_type(HType::Int32x4());
1779 set_type(HType::TaggedNumber());
1781 if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
1785 bool can_convert_undefined_to_nan() {
1786 return CheckUsesForFlag(kAllowUndefinedAsNaN);
1789 virtual HType CalculateInferredType() V8_OVERRIDE;
1790 virtual HValue* Canonicalize() V8_OVERRIDE;
1792 Representation from() const { return value()->representation(); }
1793 Representation to() const { return representation(); }
1794 bool deoptimize_on_minus_zero() const {
1795 return CheckFlag(kBailoutOnMinusZero);
1797 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1801 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
1803 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1805 DECLARE_CONCRETE_INSTRUCTION(Change)
1808 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1811 virtual bool IsDeletable() const V8_OVERRIDE {
1812 return !from().IsTagged() || value()->type().IsSmi();
1817 class HClampToUint8 V8_FINAL : public HUnaryOperation {
1819 DECLARE_INSTRUCTION_FACTORY_P1(HClampToUint8, HValue*);
1821 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1822 return Representation::None();
1825 DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
1828 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1831 explicit HClampToUint8(HValue* value)
1832 : HUnaryOperation(value) {
1833 set_representation(Representation::Integer32());
1834 SetFlag(kAllowUndefinedAsNaN);
1838 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1842 class HDoubleBits V8_FINAL : public HUnaryOperation {
1844 enum Bits { HIGH, LOW };
1845 DECLARE_INSTRUCTION_FACTORY_P2(HDoubleBits, HValue*, Bits);
1847 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1848 return Representation::Double();
1851 DECLARE_CONCRETE_INSTRUCTION(DoubleBits)
1853 Bits bits() { return bits_; }
1856 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
1857 return other->IsDoubleBits() && HDoubleBits::cast(other)->bits() == bits();
1861 HDoubleBits(HValue* value, Bits bits)
1862 : HUnaryOperation(value), bits_(bits) {
1863 set_representation(Representation::Integer32());
1867 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1873 class HConstructDouble V8_FINAL : public HTemplateInstruction<2> {
1875 DECLARE_INSTRUCTION_FACTORY_P2(HConstructDouble, HValue*, HValue*);
1877 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1878 return Representation::Integer32();
1881 DECLARE_CONCRETE_INSTRUCTION(ConstructDouble)
1883 HValue* hi() { return OperandAt(0); }
1884 HValue* lo() { return OperandAt(1); }
1887 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1890 explicit HConstructDouble(HValue* hi, HValue* lo) {
1891 set_representation(Representation::Double());
1893 SetOperandAt(0, hi);
1894 SetOperandAt(1, lo);
1897 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1901 enum RemovableSimulate {
1907 class HSimulate V8_FINAL : public HInstruction {
1909 HSimulate(BailoutId ast_id,
1912 RemovableSimulate removable)
1914 pop_count_(pop_count),
1916 assigned_indexes_(2, zone),
1918 removable_(removable),
1919 done_with_replay_(false) {}
1922 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1924 bool HasAstId() const { return !ast_id_.IsNone(); }
1925 BailoutId ast_id() const { return ast_id_; }
1926 void set_ast_id(BailoutId id) {
1927 ASSERT(!HasAstId());
1931 int pop_count() const { return pop_count_; }
1932 const ZoneList<HValue*>* values() const { return &values_; }
1933 int GetAssignedIndexAt(int index) const {
1934 ASSERT(HasAssignedIndexAt(index));
1935 return assigned_indexes_[index];
1937 bool HasAssignedIndexAt(int index) const {
1938 return assigned_indexes_[index] != kNoIndex;
1940 void AddAssignedValue(int index, HValue* value) {
1941 AddValue(index, value);
1943 void AddPushedValue(HValue* value) {
1944 AddValue(kNoIndex, value);
1946 int ToOperandIndex(int environment_index) {
1947 for (int i = 0; i < assigned_indexes_.length(); ++i) {
1948 if (assigned_indexes_[i] == environment_index) return i;
1952 virtual int OperandCount() V8_OVERRIDE { return values_.length(); }
1953 virtual HValue* OperandAt(int index) const V8_OVERRIDE {
1954 return values_[index];
1957 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
1958 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1959 return Representation::None();
1962 void MergeWith(ZoneList<HSimulate*>* list);
1963 bool is_candidate_for_removal() { return removable_ == REMOVABLE_SIMULATE; }
1965 // Replay effects of this instruction on the given environment.
1966 void ReplayEnvironment(HEnvironment* env);
1968 DECLARE_CONCRETE_INSTRUCTION(Simulate)
1971 virtual void Verify() V8_OVERRIDE;
1972 void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
1973 Handle<JSFunction> closure() const { return closure_; }
1977 virtual void InternalSetOperandAt(int index, HValue* value) V8_OVERRIDE {
1978 values_[index] = value;
1982 static const int kNoIndex = -1;
1983 void AddValue(int index, HValue* value) {
1984 assigned_indexes_.Add(index, zone_);
1985 // Resize the list of pushed values.
1986 values_.Add(NULL, zone_);
1987 // Set the operand through the base method in HValue to make sure that the
1988 // use lists are correctly updated.
1989 SetOperandAt(values_.length() - 1, value);
1991 bool HasValueForIndex(int index) {
1992 for (int i = 0; i < assigned_indexes_.length(); ++i) {
1993 if (assigned_indexes_[i] == index) return true;
1999 ZoneList<HValue*> values_;
2000 ZoneList<int> assigned_indexes_;
2002 RemovableSimulate removable_ : 2;
2003 bool done_with_replay_ : 1;
2006 Handle<JSFunction> closure_;
2011 class HEnvironmentMarker V8_FINAL : public HTemplateInstruction<1> {
2013 enum Kind { BIND, LOOKUP };
2015 DECLARE_INSTRUCTION_FACTORY_P2(HEnvironmentMarker, Kind, int);
2017 Kind kind() { return kind_; }
2018 int index() { return index_; }
2019 HSimulate* next_simulate() { return next_simulate_; }
2020 void set_next_simulate(HSimulate* simulate) {
2021 next_simulate_ = simulate;
2024 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2025 return Representation::None();
2028 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2031 void set_closure(Handle<JSFunction> closure) {
2032 ASSERT(closure_.is_null());
2033 ASSERT(!closure.is_null());
2036 Handle<JSFunction> closure() const { return closure_; }
2039 DECLARE_CONCRETE_INSTRUCTION(EnvironmentMarker);
2042 HEnvironmentMarker(Kind kind, int index)
2043 : kind_(kind), index_(index), next_simulate_(NULL) { }
2047 HSimulate* next_simulate_;
2050 Handle<JSFunction> closure_;
2055 class HStackCheck V8_FINAL : public HTemplateInstruction<1> {
2062 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HStackCheck, Type);
2064 HValue* context() { return OperandAt(0); }
2066 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2067 return Representation::Tagged();
2071 // The stack check eliminator might try to eliminate the same stack
2072 // check instruction multiple times.
2074 DeleteAndReplaceWith(NULL);
2078 bool is_function_entry() { return type_ == kFunctionEntry; }
2079 bool is_backwards_branch() { return type_ == kBackwardsBranch; }
2081 DECLARE_CONCRETE_INSTRUCTION(StackCheck)
2084 HStackCheck(HValue* context, Type type) : type_(type) {
2085 SetOperandAt(0, context);
2086 SetChangesFlag(kNewSpacePromotion);
2094 NORMAL_RETURN, // Drop the function from the environment on return.
2095 CONSTRUCT_CALL_RETURN, // Either use allocated receiver or return value.
2096 GETTER_CALL_RETURN, // Returning from a getter, need to restore context.
2097 SETTER_CALL_RETURN // Use the RHS of the assignment as the return value.
2101 class HArgumentsObject;
2104 class HEnterInlined V8_FINAL : public HTemplateInstruction<0> {
2106 static HEnterInlined* New(Zone* zone,
2108 BailoutId return_id,
2109 Handle<JSFunction> closure,
2110 int arguments_count,
2111 FunctionLiteral* function,
2112 InliningKind inlining_kind,
2113 Variable* arguments_var,
2114 HArgumentsObject* arguments_object) {
2115 return new(zone) HEnterInlined(return_id, closure, arguments_count,
2116 function, inlining_kind, arguments_var,
2117 arguments_object, zone);
2120 void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
2121 ZoneList<HBasicBlock*>* return_targets() { return &return_targets_; }
2123 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2125 Handle<JSFunction> closure() const { return closure_; }
2126 int arguments_count() const { return arguments_count_; }
2127 bool arguments_pushed() const { return arguments_pushed_; }
2128 void set_arguments_pushed() { arguments_pushed_ = true; }
2129 FunctionLiteral* function() const { return function_; }
2130 InliningKind inlining_kind() const { return inlining_kind_; }
2131 BailoutId ReturnId() const { return return_id_; }
2133 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2134 return Representation::None();
2137 Variable* arguments_var() { return arguments_var_; }
2138 HArgumentsObject* arguments_object() { return arguments_object_; }
2140 DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
2143 HEnterInlined(BailoutId return_id,
2144 Handle<JSFunction> closure,
2145 int arguments_count,
2146 FunctionLiteral* function,
2147 InliningKind inlining_kind,
2148 Variable* arguments_var,
2149 HArgumentsObject* arguments_object,
2151 : return_id_(return_id),
2153 arguments_count_(arguments_count),
2154 arguments_pushed_(false),
2155 function_(function),
2156 inlining_kind_(inlining_kind),
2157 arguments_var_(arguments_var),
2158 arguments_object_(arguments_object),
2159 return_targets_(2, zone) {
2162 BailoutId return_id_;
2163 Handle<JSFunction> closure_;
2164 int arguments_count_;
2165 bool arguments_pushed_;
2166 FunctionLiteral* function_;
2167 InliningKind inlining_kind_;
2168 Variable* arguments_var_;
2169 HArgumentsObject* arguments_object_;
2170 ZoneList<HBasicBlock*> return_targets_;
2174 class HLeaveInlined V8_FINAL : public HTemplateInstruction<0> {
2176 HLeaveInlined(HEnterInlined* entry,
2179 drop_count_(drop_count) { }
2181 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2182 return Representation::None();
2185 virtual int argument_delta() const V8_OVERRIDE {
2186 return entry_->arguments_pushed() ? -drop_count_ : 0;
2189 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
2192 HEnterInlined* entry_;
2197 class HPushArgument V8_FINAL : public HUnaryOperation {
2199 DECLARE_INSTRUCTION_FACTORY_P1(HPushArgument, HValue*);
2201 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2202 return Representation::Tagged();
2205 virtual int argument_delta() const V8_OVERRIDE { return 1; }
2206 HValue* argument() { return OperandAt(0); }
2208 DECLARE_CONCRETE_INSTRUCTION(PushArgument)
2211 explicit HPushArgument(HValue* value) : HUnaryOperation(value) {
2212 set_representation(Representation::Tagged());
2217 class HThisFunction V8_FINAL : public HTemplateInstruction<0> {
2219 DECLARE_INSTRUCTION_FACTORY_P0(HThisFunction);
2221 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2222 return Representation::None();
2225 DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
2228 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2232 set_representation(Representation::Tagged());
2236 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2240 class HDeclareGlobals V8_FINAL : public HUnaryOperation {
2242 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HDeclareGlobals,
2246 HValue* context() { return OperandAt(0); }
2247 Handle<FixedArray> pairs() const { return pairs_; }
2248 int flags() const { return flags_; }
2250 DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
2252 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2253 return Representation::Tagged();
2257 HDeclareGlobals(HValue* context,
2258 Handle<FixedArray> pairs,
2260 : HUnaryOperation(context),
2263 set_representation(Representation::Tagged());
2264 SetAllSideEffects();
2267 Handle<FixedArray> pairs_;
2273 class HCall : public HTemplateInstruction<V> {
2275 // The argument count includes the receiver.
2276 explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
2277 this->set_representation(Representation::Tagged());
2278 this->SetAllSideEffects();
2281 virtual HType CalculateInferredType() V8_FINAL V8_OVERRIDE {
2282 return HType::Tagged();
2285 virtual int argument_count() const {
2286 return argument_count_;
2289 virtual int argument_delta() const V8_OVERRIDE {
2290 return -argument_count();
2294 int argument_count_;
2298 class HUnaryCall : public HCall<1> {
2300 HUnaryCall(HValue* value, int argument_count)
2301 : HCall<1>(argument_count) {
2302 SetOperandAt(0, value);
2305 virtual Representation RequiredInputRepresentation(
2306 int index) V8_FINAL V8_OVERRIDE {
2307 return Representation::Tagged();
2310 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2312 HValue* value() { return OperandAt(0); }
2316 class HBinaryCall : public HCall<2> {
2318 HBinaryCall(HValue* first, HValue* second, int argument_count)
2319 : HCall<2>(argument_count) {
2320 SetOperandAt(0, first);
2321 SetOperandAt(1, second);
2324 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2326 virtual Representation RequiredInputRepresentation(
2327 int index) V8_FINAL V8_OVERRIDE {
2328 return Representation::Tagged();
2331 HValue* first() { return OperandAt(0); }
2332 HValue* second() { return OperandAt(1); }
2336 class HCallJSFunction V8_FINAL : public HCall<1> {
2338 static HCallJSFunction* New(Zone* zone,
2342 bool pass_argument_count);
2344 HValue* function() { return OperandAt(0); }
2346 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2348 virtual Representation RequiredInputRepresentation(
2349 int index) V8_FINAL V8_OVERRIDE {
2351 return Representation::Tagged();
2354 bool pass_argument_count() const { return pass_argument_count_; }
2356 virtual bool HasStackCheck() V8_FINAL V8_OVERRIDE {
2357 return has_stack_check_;
2360 DECLARE_CONCRETE_INSTRUCTION(CallJSFunction)
2363 // The argument count includes the receiver.
2364 HCallJSFunction(HValue* function,
2366 bool pass_argument_count,
2367 bool has_stack_check)
2368 : HCall<1>(argument_count),
2369 pass_argument_count_(pass_argument_count),
2370 has_stack_check_(has_stack_check) {
2371 SetOperandAt(0, function);
2374 bool pass_argument_count_;
2375 bool has_stack_check_;
2379 class HCallWithDescriptor V8_FINAL : public HInstruction {
2381 static HCallWithDescriptor* New(Zone* zone, HValue* context,
2384 const CallInterfaceDescriptor* descriptor,
2385 Vector<HValue*>& operands) {
2386 ASSERT(operands.length() == descriptor->environment_length());
2387 HCallWithDescriptor* res =
2388 new(zone) HCallWithDescriptor(target, argument_count,
2389 descriptor, operands, zone);
2393 virtual int OperandCount() V8_FINAL V8_OVERRIDE { return values_.length(); }
2394 virtual HValue* OperandAt(int index) const V8_FINAL V8_OVERRIDE {
2395 return values_[index];
2398 virtual Representation RequiredInputRepresentation(
2399 int index) V8_FINAL V8_OVERRIDE {
2401 return Representation::Tagged();
2403 int par_index = index - 1;
2404 ASSERT(par_index < descriptor_->environment_length());
2405 return descriptor_->GetParameterRepresentation(par_index);
2409 DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor)
2411 virtual HType CalculateInferredType() V8_FINAL V8_OVERRIDE {
2412 return HType::Tagged();
2415 virtual int argument_count() const {
2416 return argument_count_;
2419 virtual int argument_delta() const V8_OVERRIDE {
2420 return -argument_count_;
2423 const CallInterfaceDescriptor* descriptor() const {
2428 return OperandAt(0);
2431 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2434 // The argument count includes the receiver.
2435 HCallWithDescriptor(HValue* target,
2437 const CallInterfaceDescriptor* descriptor,
2438 Vector<HValue*>& operands,
2440 : descriptor_(descriptor),
2441 values_(descriptor->environment_length() + 1, zone) {
2442 argument_count_ = argument_count;
2443 AddOperand(target, zone);
2444 for (int i = 0; i < operands.length(); i++) {
2445 AddOperand(operands[i], zone);
2447 this->set_representation(Representation::Tagged());
2448 this->SetAllSideEffects();
2451 void AddOperand(HValue* v, Zone* zone) {
2452 values_.Add(NULL, zone);
2453 SetOperandAt(values_.length() - 1, v);
2456 void InternalSetOperandAt(int index,
2457 HValue* value) V8_FINAL V8_OVERRIDE {
2458 values_[index] = value;
2461 const CallInterfaceDescriptor* descriptor_;
2462 ZoneList<HValue*> values_;
2463 int argument_count_;
2467 class HInvokeFunction V8_FINAL : public HBinaryCall {
2469 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInvokeFunction, HValue*, int);
2471 HInvokeFunction(HValue* context,
2473 Handle<JSFunction> known_function,
2475 : HBinaryCall(context, function, argument_count),
2476 known_function_(known_function) {
2477 formal_parameter_count_ = known_function.is_null()
2478 ? 0 : known_function->shared()->formal_parameter_count();
2479 has_stack_check_ = !known_function.is_null() &&
2480 (known_function->code()->kind() == Code::FUNCTION ||
2481 known_function->code()->kind() == Code::OPTIMIZED_FUNCTION);
2484 static HInvokeFunction* New(Zone* zone,
2487 Handle<JSFunction> known_function,
2488 int argument_count) {
2489 return new(zone) HInvokeFunction(context, function,
2490 known_function, argument_count);
2493 HValue* context() { return first(); }
2494 HValue* function() { return second(); }
2495 Handle<JSFunction> known_function() { return known_function_; }
2496 int formal_parameter_count() const { return formal_parameter_count_; }
2498 virtual bool HasStackCheck() V8_FINAL V8_OVERRIDE {
2499 return has_stack_check_;
2502 DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
2505 HInvokeFunction(HValue* context, HValue* function, int argument_count)
2506 : HBinaryCall(context, function, argument_count),
2507 has_stack_check_(false) {
2510 Handle<JSFunction> known_function_;
2511 int formal_parameter_count_;
2512 bool has_stack_check_;
2516 class HCallFunction V8_FINAL : public HBinaryCall {
2518 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallFunction, HValue*, int);
2519 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(
2520 HCallFunction, HValue*, int, CallFunctionFlags);
2522 HValue* context() { return first(); }
2523 HValue* function() { return second(); }
2524 CallFunctionFlags function_flags() const { return function_flags_; }
2526 DECLARE_CONCRETE_INSTRUCTION(CallFunction)
2528 virtual int argument_delta() const V8_OVERRIDE { return -argument_count(); }
2531 HCallFunction(HValue* context,
2534 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS)
2535 : HBinaryCall(context, function, argument_count), function_flags_(flags) {
2537 CallFunctionFlags function_flags_;
2541 class HCallNew V8_FINAL : public HBinaryCall {
2543 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallNew, HValue*, int);
2545 HValue* context() { return first(); }
2546 HValue* constructor() { return second(); }
2548 DECLARE_CONCRETE_INSTRUCTION(CallNew)
2551 HCallNew(HValue* context, HValue* constructor, int argument_count)
2552 : HBinaryCall(context, constructor, argument_count) {}
2556 class HCallNewArray V8_FINAL : public HBinaryCall {
2558 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCallNewArray,
2563 HValue* context() { return first(); }
2564 HValue* constructor() { return second(); }
2566 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2568 ElementsKind elements_kind() const { return elements_kind_; }
2570 DECLARE_CONCRETE_INSTRUCTION(CallNewArray)
2573 HCallNewArray(HValue* context, HValue* constructor, int argument_count,
2574 ElementsKind elements_kind)
2575 : HBinaryCall(context, constructor, argument_count),
2576 elements_kind_(elements_kind) {}
2578 ElementsKind elements_kind_;
2582 class HCallRuntime V8_FINAL : public HCall<1> {
2584 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCallRuntime,
2586 const Runtime::Function*,
2589 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2591 HValue* context() { return OperandAt(0); }
2592 const Runtime::Function* function() const { return c_function_; }
2593 Handle<String> name() const { return name_; }
2594 SaveFPRegsMode save_doubles() const { return save_doubles_; }
2595 void set_save_doubles(SaveFPRegsMode save_doubles) {
2596 save_doubles_ = save_doubles;
2599 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2600 return Representation::Tagged();
2603 DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
2606 HCallRuntime(HValue* context,
2607 Handle<String> name,
2608 const Runtime::Function* c_function,
2610 : HCall<1>(argument_count), c_function_(c_function), name_(name),
2611 save_doubles_(kDontSaveFPRegs) {
2612 SetOperandAt(0, context);
2615 const Runtime::Function* c_function_;
2616 Handle<String> name_;
2617 SaveFPRegsMode save_doubles_;
2621 class HMapEnumLength V8_FINAL : public HUnaryOperation {
2623 DECLARE_INSTRUCTION_FACTORY_P1(HMapEnumLength, HValue*);
2625 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2626 return Representation::Tagged();
2629 DECLARE_CONCRETE_INSTRUCTION(MapEnumLength)
2632 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2635 explicit HMapEnumLength(HValue* value)
2636 : HUnaryOperation(value, HType::Smi()) {
2637 set_representation(Representation::Smi());
2639 SetDependsOnFlag(kMaps);
2642 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2646 class HUnaryMathOperation V8_FINAL : public HTemplateInstruction<2> {
2648 static HInstruction* New(Zone* zone,
2651 BuiltinFunctionId op);
2653 HValue* context() { return OperandAt(0); }
2654 HValue* value() { return OperandAt(1); }
2656 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2658 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2660 return Representation::Tagged();
2669 return Representation::Double();
2671 return representation();
2673 return Representation::Integer32();
2676 return Representation::None();
2681 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
2683 virtual HValue* Canonicalize() V8_OVERRIDE;
2684 virtual Representation RepresentationFromUses() V8_OVERRIDE;
2685 virtual Representation RepresentationFromInputs() V8_OVERRIDE;
2687 BuiltinFunctionId op() const { return op_; }
2688 const char* OpName() const;
2690 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
2693 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2694 HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
2695 return op_ == b->op();
2699 // Indicates if we support a double (and int32) output for Math.floor and
2701 bool SupportsFlexibleFloorAndRound() const {
2702 #ifdef V8_TARGET_ARCH_ARM64
2708 HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
2709 : HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
2710 SetOperandAt(0, context);
2711 SetOperandAt(1, value);
2715 if (SupportsFlexibleFloorAndRound()) {
2716 SetFlag(kFlexibleRepresentation);
2718 set_representation(Representation::Integer32());
2722 set_representation(Representation::Integer32());
2725 // Not setting representation here: it is None intentionally.
2726 SetFlag(kFlexibleRepresentation);
2727 // TODO(svenpanne) This flag is actually only needed if representation()
2728 // is tagged, and not when it is an unboxed double or unboxed integer.
2729 SetChangesFlag(kNewSpacePromotion);
2735 set_representation(Representation::Double());
2741 SetFlag(kAllowUndefinedAsNaN);
2744 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2746 HValue* SimplifiedDividendForMathFloorOfDiv(HDiv* hdiv);
2747 HValue* SimplifiedDivisorForMathFloorOfDiv(HDiv* hdiv);
2749 BuiltinFunctionId op_;
2753 class HLoadRoot V8_FINAL : public HTemplateInstruction<0> {
2755 DECLARE_INSTRUCTION_FACTORY_P1(HLoadRoot, Heap::RootListIndex);
2756 DECLARE_INSTRUCTION_FACTORY_P2(HLoadRoot, Heap::RootListIndex, HType);
2758 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2759 return Representation::None();
2762 Heap::RootListIndex index() const { return index_; }
2764 DECLARE_CONCRETE_INSTRUCTION(LoadRoot)
2767 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2768 HLoadRoot* b = HLoadRoot::cast(other);
2769 return index_ == b->index_;
2773 HLoadRoot(Heap::RootListIndex index, HType type = HType::Tagged())
2774 : HTemplateInstruction<0>(type), index_(index) {
2776 // TODO(bmeurer): We'll need kDependsOnRoots once we add the
2777 // corresponding HStoreRoot instruction.
2778 SetDependsOnFlag(kCalls);
2781 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2783 const Heap::RootListIndex index_;
2787 class HCheckMaps V8_FINAL : public HTemplateInstruction<2> {
2789 static HCheckMaps* New(Zone* zone, HValue* context, HValue* value,
2790 Handle<Map> map, HValue* typecheck = NULL) {
2791 return new(zone) HCheckMaps(value, new(zone) UniqueSet<Map>(
2792 Unique<Map>::CreateImmovable(map), zone), typecheck);
2794 static HCheckMaps* New(Zone* zone, HValue* context,
2795 HValue* value, SmallMapList* map_list,
2796 HValue* typecheck = NULL) {
2797 UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone);
2798 for (int i = 0; i < map_list->length(); ++i) {
2799 maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone);
2801 return new(zone) HCheckMaps(value, maps, typecheck);
2804 bool IsStabilityCheck() const { return is_stability_check_; }
2805 void MarkAsStabilityCheck() {
2806 has_migration_target_ = false;
2807 is_stability_check_ = true;
2808 ClearChangesFlag(kNewSpacePromotion);
2809 ClearDependsOnFlag(kElementsKind);
2810 ClearDependsOnFlag(kMaps);
2813 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
2814 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2815 return Representation::Tagged();
2817 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2819 HValue* value() { return OperandAt(0); }
2820 HValue* typecheck() { return OperandAt(1); }
2822 const UniqueSet<Map>* maps() const { return maps_; }
2823 void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; }
2825 bool maps_are_stable() const { return maps_are_stable_; }
2827 bool HasMigrationTarget() const { return has_migration_target_; }
2829 virtual HValue* Canonicalize() V8_OVERRIDE;
2831 DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
2834 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2835 return this->maps()->Equals(HCheckMaps::cast(other)->maps());
2838 virtual int RedefinedOperandIndex() { return 0; }
2841 // Clients should use one of the static New* methods above.
2842 HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck)
2843 : HTemplateInstruction<2>(value->type()), maps_(maps),
2844 has_migration_target_(false), is_stability_check_(false),
2845 maps_are_stable_(true) {
2846 ASSERT_NE(0, maps->size());
2847 SetOperandAt(0, value);
2848 // Use the object value for the dependency if NULL is passed.
2849 SetOperandAt(1, typecheck ? typecheck : value);
2850 set_representation(Representation::Tagged());
2852 SetDependsOnFlag(kMaps);
2853 SetDependsOnFlag(kElementsKind);
2854 for (int i = 0; i < maps->size(); ++i) {
2855 Handle<Map> map = maps->at(i).handle();
2856 if (map->is_migration_target()) has_migration_target_ = true;
2857 if (!map->is_stable()) maps_are_stable_ = false;
2859 if (has_migration_target_) SetChangesFlag(kNewSpacePromotion);
2862 const UniqueSet<Map>* maps_;
2863 bool has_migration_target_ : 1;
2864 bool is_stability_check_ : 1;
2865 bool maps_are_stable_ : 1;
2869 class HCheckValue V8_FINAL : public HUnaryOperation {
2871 static HCheckValue* New(Zone* zone, HValue* context,
2872 HValue* value, Handle<JSFunction> func) {
2873 bool in_new_space = zone->isolate()->heap()->InNewSpace(*func);
2874 // NOTE: We create an uninitialized Unique and initialize it later.
2875 // This is because a JSFunction can move due to GC during graph creation.
2876 // TODO(titzer): This is a migration crutch. Replace with some kind of
2877 // Uniqueness scope later.
2878 Unique<JSFunction> target = Unique<JSFunction>::CreateUninitialized(func);
2879 HCheckValue* check = new(zone) HCheckValue(value, target, in_new_space);
2882 static HCheckValue* New(Zone* zone, HValue* context,
2883 HValue* value, Unique<HeapObject> target,
2884 bool object_in_new_space) {
2885 return new(zone) HCheckValue(value, target, object_in_new_space);
2888 virtual void FinalizeUniqueness() V8_OVERRIDE {
2889 object_ = Unique<HeapObject>(object_.handle());
2892 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2893 return Representation::Tagged();
2895 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2897 virtual HValue* Canonicalize() V8_OVERRIDE;
2900 virtual void Verify() V8_OVERRIDE;
2903 Unique<HeapObject> object() const { return object_; }
2904 bool object_in_new_space() const { return object_in_new_space_; }
2906 DECLARE_CONCRETE_INSTRUCTION(CheckValue)
2909 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2910 HCheckValue* b = HCheckValue::cast(other);
2911 return object_ == b->object_;
2915 HCheckValue(HValue* value, Unique<HeapObject> object,
2916 bool object_in_new_space)
2917 : HUnaryOperation(value, value->type()),
2919 object_in_new_space_(object_in_new_space) {
2920 set_representation(Representation::Tagged());
2924 Unique<HeapObject> object_;
2925 bool object_in_new_space_;
2929 class HCheckInstanceType V8_FINAL : public HUnaryOperation {
2935 IS_INTERNALIZED_STRING,
2936 LAST_INTERVAL_CHECK = IS_JS_ARRAY
2939 DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue*, Check);
2941 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2943 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2944 return Representation::Tagged();
2947 virtual HValue* Canonicalize() V8_OVERRIDE;
2949 bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
2950 void GetCheckInterval(InstanceType* first, InstanceType* last);
2951 void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
2953 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
2956 // TODO(ager): It could be nice to allow the ommision of instance
2957 // type checks if we have already performed an instance type check
2958 // with a larger range.
2959 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2960 HCheckInstanceType* b = HCheckInstanceType::cast(other);
2961 return check_ == b->check_;
2964 virtual int RedefinedOperandIndex() { return 0; }
2967 const char* GetCheckName();
2969 HCheckInstanceType(HValue* value, Check check)
2970 : HUnaryOperation(value), check_(check) {
2971 set_representation(Representation::Tagged());
2979 class HCheckSmi V8_FINAL : public HUnaryOperation {
2981 DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue*);
2983 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2984 return Representation::Tagged();
2987 virtual HValue* Canonicalize() V8_OVERRIDE {
2988 HType value_type = value()->type();
2989 if (value_type.IsSmi()) {
2995 DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
2998 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3001 explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
3002 set_representation(Representation::Smi());
3008 class HCheckHeapObject V8_FINAL : public HUnaryOperation {
3010 DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
3012 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
3013 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3014 return Representation::Tagged();
3018 virtual void Verify() V8_OVERRIDE;
3021 virtual HValue* Canonicalize() V8_OVERRIDE {
3022 return value()->type().IsHeapObject() ? NULL : this;
3025 DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
3028 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3031 explicit HCheckHeapObject(HValue* value)
3032 : HUnaryOperation(value, HType::NonPrimitive()) {
3033 set_representation(Representation::Tagged());
3039 class InductionVariableData;
3042 struct InductionVariableLimitUpdate {
3043 InductionVariableData* updated_variable;
3045 bool limit_is_upper;
3046 bool limit_is_included;
3048 InductionVariableLimitUpdate()
3049 : updated_variable(NULL), limit(NULL),
3050 limit_is_upper(false), limit_is_included(false) {}
3060 class InductionVariableData V8_FINAL : public ZoneObject {
3062 class InductionVariableCheck : public ZoneObject {
3064 HBoundsCheck* check() { return check_; }
3065 InductionVariableCheck* next() { return next_; }
3066 bool HasUpperLimit() { return upper_limit_ >= 0; }
3067 int32_t upper_limit() {
3068 ASSERT(HasUpperLimit());
3069 return upper_limit_;
3071 void set_upper_limit(int32_t upper_limit) {
3072 upper_limit_ = upper_limit;
3075 bool processed() { return processed_; }
3076 void set_processed() { processed_ = true; }
3078 InductionVariableCheck(HBoundsCheck* check,
3079 InductionVariableCheck* next,
3080 int32_t upper_limit = kNoLimit)
3081 : check_(check), next_(next), upper_limit_(upper_limit),
3082 processed_(false) {}
3085 HBoundsCheck* check_;
3086 InductionVariableCheck* next_;
3087 int32_t upper_limit_;
3091 class ChecksRelatedToLength : public ZoneObject {
3093 HValue* length() { return length_; }
3094 ChecksRelatedToLength* next() { return next_; }
3095 InductionVariableCheck* checks() { return checks_; }
3097 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3098 void CloseCurrentBlock();
3100 ChecksRelatedToLength(HValue* length, ChecksRelatedToLength* next)
3101 : length_(length), next_(next), checks_(NULL),
3102 first_check_in_block_(NULL),
3104 added_constant_(NULL),
3105 current_and_mask_in_block_(0),
3106 current_or_mask_in_block_(0) {}
3109 void UseNewIndexInCurrentBlock(Token::Value token,
3114 HBoundsCheck* first_check_in_block() { return first_check_in_block_; }
3115 HBitwise* added_index() { return added_index_; }
3116 void set_added_index(HBitwise* index) { added_index_ = index; }
3117 HConstant* added_constant() { return added_constant_; }
3118 void set_added_constant(HConstant* constant) { added_constant_ = constant; }
3119 int32_t current_and_mask_in_block() { return current_and_mask_in_block_; }
3120 int32_t current_or_mask_in_block() { return current_or_mask_in_block_; }
3121 int32_t current_upper_limit() { return current_upper_limit_; }
3124 ChecksRelatedToLength* next_;
3125 InductionVariableCheck* checks_;
3127 HBoundsCheck* first_check_in_block_;
3128 HBitwise* added_index_;
3129 HConstant* added_constant_;
3130 int32_t current_and_mask_in_block_;
3131 int32_t current_or_mask_in_block_;
3132 int32_t current_upper_limit_;
3135 struct LimitFromPredecessorBlock {
3136 InductionVariableData* variable;
3139 HBasicBlock* other_target;
3141 bool LimitIsValid() { return token != Token::ILLEGAL; }
3143 bool LimitIsIncluded() {
3144 return Token::IsEqualityOp(token) ||
3145 token == Token::GTE || token == Token::LTE;
3147 bool LimitIsUpper() {
3148 return token == Token::LTE || token == Token::LT || token == Token::NE;
3151 LimitFromPredecessorBlock()
3153 token(Token::ILLEGAL),
3155 other_target(NULL) {}
3158 static const int32_t kNoLimit = -1;
3160 static InductionVariableData* ExaminePhi(HPhi* phi);
3161 static void ComputeLimitFromPredecessorBlock(
3163 LimitFromPredecessorBlock* result);
3164 static bool ComputeInductionVariableLimit(
3166 InductionVariableLimitUpdate* additional_limit);
3168 struct BitwiseDecompositionResult {
3174 BitwiseDecompositionResult()
3175 : base(NULL), and_mask(0), or_mask(0), context(NULL) {}
3177 static void DecomposeBitwise(HValue* value,
3178 BitwiseDecompositionResult* result);
3180 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3182 bool CheckIfBranchIsLoopGuard(Token::Value token,
3183 HBasicBlock* current_branch,
3184 HBasicBlock* other_branch);
3186 void UpdateAdditionalLimit(InductionVariableLimitUpdate* update);
3188 HPhi* phi() { return phi_; }
3189 HValue* base() { return base_; }
3190 int32_t increment() { return increment_; }
3191 HValue* limit() { return limit_; }
3192 bool limit_included() { return limit_included_; }
3193 HBasicBlock* limit_validity() { return limit_validity_; }
3194 HBasicBlock* induction_exit_block() { return induction_exit_block_; }
3195 HBasicBlock* induction_exit_target() { return induction_exit_target_; }
3196 ChecksRelatedToLength* checks() { return checks_; }
3197 HValue* additional_upper_limit() { return additional_upper_limit_; }
3198 bool additional_upper_limit_is_included() {
3199 return additional_upper_limit_is_included_;
3201 HValue* additional_lower_limit() { return additional_lower_limit_; }
3202 bool additional_lower_limit_is_included() {
3203 return additional_lower_limit_is_included_;
3206 bool LowerLimitIsNonNegativeConstant() {
3207 if (base()->IsInteger32Constant() && base()->GetInteger32Constant() >= 0) {
3210 if (additional_lower_limit() != NULL &&
3211 additional_lower_limit()->IsInteger32Constant() &&
3212 additional_lower_limit()->GetInteger32Constant() >= 0) {
3213 // Ignoring the corner case of !additional_lower_limit_is_included()
3214 // is safe, handling it adds unneeded complexity.
3220 int32_t ComputeUpperLimit(int32_t and_mask, int32_t or_mask);
3223 template <class T> void swap(T* a, T* b) {
3229 InductionVariableData(HPhi* phi, HValue* base, int32_t increment)
3230 : phi_(phi), base_(IgnoreOsrValue(base)), increment_(increment),
3231 limit_(NULL), limit_included_(false), limit_validity_(NULL),
3232 induction_exit_block_(NULL), induction_exit_target_(NULL),
3234 additional_upper_limit_(NULL),
3235 additional_upper_limit_is_included_(false),
3236 additional_lower_limit_(NULL),
3237 additional_lower_limit_is_included_(false) {}
3239 static int32_t ComputeIncrement(HPhi* phi, HValue* phi_operand);
3241 static HValue* IgnoreOsrValue(HValue* v);
3242 static InductionVariableData* GetInductionVariableData(HValue* v);
3248 bool limit_included_;
3249 HBasicBlock* limit_validity_;
3250 HBasicBlock* induction_exit_block_;
3251 HBasicBlock* induction_exit_target_;
3252 ChecksRelatedToLength* checks_;
3253 HValue* additional_upper_limit_;
3254 bool additional_upper_limit_is_included_;
3255 HValue* additional_lower_limit_;
3256 bool additional_lower_limit_is_included_;
3260 class HPhi V8_FINAL : public HValue {
3262 HPhi(int merged_index, Zone* zone)
3264 merged_index_(merged_index),
3266 induction_variable_data_(NULL) {
3267 for (int i = 0; i < Representation::kNumRepresentations; i++) {
3268 non_phi_uses_[i] = 0;
3269 indirect_uses_[i] = 0;
3271 ASSERT(merged_index >= 0 || merged_index == kInvalidMergedIndex);
3272 SetFlag(kFlexibleRepresentation);
3273 SetFlag(kAllowUndefinedAsNaN);
3276 virtual Representation RepresentationFromInputs() V8_OVERRIDE;
3278 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
3279 virtual void InferRepresentation(
3280 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
3281 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3282 return representation();
3284 virtual Representation KnownOptimalRepresentation() V8_OVERRIDE {
3285 return representation();
3287 virtual HType CalculateInferredType() V8_OVERRIDE;
3288 virtual int OperandCount() V8_OVERRIDE { return inputs_.length(); }
3289 virtual HValue* OperandAt(int index) const V8_OVERRIDE {
3290 return inputs_[index];
3292 HValue* GetRedundantReplacement();
3293 void AddInput(HValue* value);
3296 bool IsReceiver() const { return merged_index_ == 0; }
3297 bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
3299 virtual HSourcePosition position() const V8_OVERRIDE;
3301 int merged_index() const { return merged_index_; }
3303 InductionVariableData* induction_variable_data() {
3304 return induction_variable_data_;
3306 bool IsInductionVariable() {
3307 return induction_variable_data_ != NULL;
3309 bool IsLimitedInductionVariable() {
3310 return IsInductionVariable() &&
3311 induction_variable_data_->limit() != NULL;
3313 void DetectInductionVariable() {
3314 ASSERT(induction_variable_data_ == NULL);
3315 induction_variable_data_ = InductionVariableData::ExaminePhi(this);
3318 virtual void PrintTo(StringStream* stream) V8_OVERRIDE;
3321 virtual void Verify() V8_OVERRIDE;
3324 void InitRealUses(int id);
3325 void AddNonPhiUsesFrom(HPhi* other);
3326 void AddIndirectUsesTo(int* use_count);
3328 int tagged_non_phi_uses() const {
3329 return non_phi_uses_[Representation::kTagged];
3331 int smi_non_phi_uses() const {
3332 return non_phi_uses_[Representation::kSmi];
3334 int int32_non_phi_uses() const {
3335 return non_phi_uses_[Representation::kInteger32];
3337 int double_non_phi_uses() const {
3338 return non_phi_uses_[Representation::kDouble];
3340 int tagged_indirect_uses() const {
3341 return indirect_uses_[Representation::kTagged];
3343 int smi_indirect_uses() const {
3344 return indirect_uses_[Representation::kSmi];
3346 int int32_indirect_uses() const {
3347 return indirect_uses_[Representation::kInteger32];
3349 int double_indirect_uses() const {
3350 return indirect_uses_[Representation::kDouble];
3352 int phi_id() { return phi_id_; }
3354 static HPhi* cast(HValue* value) {
3355 ASSERT(value->IsPhi());
3356 return reinterpret_cast<HPhi*>(value);
3358 virtual Opcode opcode() const V8_OVERRIDE { return HValue::kPhi; }
3360 void SimplifyConstantInputs();
3362 // Marker value representing an invalid merge index.
3363 static const int kInvalidMergedIndex = -1;
3366 virtual void DeleteFromGraph() V8_OVERRIDE;
3367 virtual void InternalSetOperandAt(int index, HValue* value) V8_OVERRIDE {
3368 inputs_[index] = value;
3372 ZoneList<HValue*> inputs_;
3375 int non_phi_uses_[Representation::kNumRepresentations];
3376 int indirect_uses_[Representation::kNumRepresentations];
3378 InductionVariableData* induction_variable_data_;
3380 // TODO(titzer): we can't eliminate the receiver for generating backtraces
3381 virtual bool IsDeletable() const V8_OVERRIDE { return !IsReceiver(); }
3385 // Common base class for HArgumentsObject and HCapturedObject.
3386 class HDematerializedObject : public HInstruction {
3388 HDematerializedObject(int count, Zone* zone) : values_(count, zone) {}
3390 virtual int OperandCount() V8_FINAL V8_OVERRIDE { return values_.length(); }
3391 virtual HValue* OperandAt(int index) const V8_FINAL V8_OVERRIDE {
3392 return values_[index];
3395 virtual bool HasEscapingOperandAt(int index) V8_FINAL V8_OVERRIDE {
3398 virtual Representation RequiredInputRepresentation(
3399 int index) V8_FINAL V8_OVERRIDE {
3400 return Representation::None();
3404 virtual void InternalSetOperandAt(int index,
3405 HValue* value) V8_FINAL V8_OVERRIDE {
3406 values_[index] = value;
3409 // List of values tracked by this marker.
3410 ZoneList<HValue*> values_;
3414 class HArgumentsObject V8_FINAL : public HDematerializedObject {
3416 static HArgumentsObject* New(Zone* zone, HValue* context, int count) {
3417 return new(zone) HArgumentsObject(count, zone);
3420 // The values contain a list of all elements in the arguments object
3421 // including the receiver object, which is skipped when materializing.
3422 const ZoneList<HValue*>* arguments_values() const { return &values_; }
3423 int arguments_count() const { return values_.length(); }
3425 void AddArgument(HValue* argument, Zone* zone) {
3426 values_.Add(NULL, zone); // Resize list.
3427 SetOperandAt(values_.length() - 1, argument);
3430 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
3433 HArgumentsObject(int count, Zone* zone)
3434 : HDematerializedObject(count, zone) {
3435 set_representation(Representation::Tagged());
3436 SetFlag(kIsArguments);
3441 class HCapturedObject V8_FINAL : public HDematerializedObject {
3443 HCapturedObject(int length, int id, Zone* zone)
3444 : HDematerializedObject(length, zone), capture_id_(id) {
3445 set_representation(Representation::Tagged());
3446 values_.AddBlock(NULL, length, zone); // Resize list.
3449 // The values contain a list of all in-object properties inside the
3450 // captured object and is index by field index. Properties in the
3451 // properties or elements backing store are not tracked here.
3452 const ZoneList<HValue*>* values() const { return &values_; }
3453 int length() const { return values_.length(); }
3454 int capture_id() const { return capture_id_; }
3456 // Shortcut for the map value of this captured object.
3457 HValue* map_value() const { return values()->first(); }
3459 void ReuseSideEffectsFromStore(HInstruction* store) {
3460 ASSERT(store->HasObservableSideEffects());
3461 ASSERT(store->IsStoreNamedField());
3462 changes_flags_.Add(store->ChangesFlags());
3465 // Replay effects of this instruction on the given environment.
3466 void ReplayEnvironment(HEnvironment* env);
3468 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3470 DECLARE_CONCRETE_INSTRUCTION(CapturedObject)
3475 // Note that we cannot DCE captured objects as they are used to replay
3476 // the environment. This method is here as an explicit reminder.
3477 // TODO(mstarzinger): Turn HSimulates into full snapshots maybe?
3478 virtual bool IsDeletable() const V8_FINAL V8_OVERRIDE { return false; }
3482 class HConstant V8_FINAL : public HTemplateInstruction<0> {
3484 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, int32_t);
3485 DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation);
3486 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double);
3487 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle<Object>);
3488 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);
3490 static HConstant* CreateAndInsertAfter(Zone* zone,
3493 Representation representation,
3494 HInstruction* instruction) {
3495 return instruction->Append(HConstant::New(
3496 zone, context, value, representation));
3499 static HConstant* CreateAndInsertBefore(Zone* zone,
3502 Representation representation,
3503 HInstruction* instruction) {
3504 return instruction->Prepend(HConstant::New(
3505 zone, context, value, representation));
3508 static HConstant* CreateAndInsertBefore(Zone* zone,
3509 Unique<Object> unique,
3510 bool is_not_in_new_space,
3511 HInstruction* instruction) {
3512 return instruction->Prepend(new(zone) HConstant(
3513 unique, Representation::Tagged(), HType::Tagged(),
3514 is_not_in_new_space, false, false, kUnknownInstanceType));
3517 static HConstant* CreateAndInsertAfter(Zone* zone,
3519 HInstruction* instruction) {
3520 return instruction->Append(new(zone) HConstant(
3521 unique, Representation::Tagged(), HType::Tagged(),
3522 true, false, false, MAP_TYPE));
3525 Handle<Object> handle(Isolate* isolate) {
3526 if (object_.handle().is_null()) {
3527 // Default arguments to is_not_in_new_space depend on this heap number
3528 // to be tenured so that it's guaranteed not to be located in new space.
3529 object_ = Unique<Object>::CreateUninitialized(
3530 isolate->factory()->NewNumber(double_value_, TENURED));
3532 AllowDeferredHandleDereference smi_check;
3533 ASSERT(has_int32_value_ || !object_.handle()->IsSmi());
3534 return object_.handle();
3537 bool IsSpecialDouble() const {
3538 return has_double_value_ &&
3539 (BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) ||
3540 FixedDoubleArray::is_the_hole_nan(double_value_) ||
3541 std::isnan(double_value_));
3544 bool NotInNewSpace() const {
3545 return is_not_in_new_space_;
3548 bool ImmortalImmovable() const;
3550 bool IsCell() const {
3551 return instance_type_ == CELL_TYPE || instance_type_ == PROPERTY_CELL_TYPE;
3554 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3555 return Representation::None();
3558 virtual Representation KnownOptimalRepresentation() V8_OVERRIDE {
3559 if (HasSmiValue() && SmiValuesAre31Bits()) return Representation::Smi();
3560 if (HasInteger32Value()) return Representation::Integer32();
3561 if (HasNumberValue()) return Representation::Double();
3562 if (HasExternalReferenceValue()) return Representation::External();
3563 return Representation::Tagged();
3566 virtual bool EmitAtUses() V8_OVERRIDE;
3567 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3568 HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
3569 Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone);
3570 Maybe<HConstant*> CopyToTruncatedNumber(Zone* zone);
3571 bool HasInteger32Value() const { return has_int32_value_; }
3572 int32_t Integer32Value() const {
3573 ASSERT(HasInteger32Value());
3574 return int32_value_;
3576 bool HasSmiValue() const { return has_smi_value_; }
3577 bool HasDoubleValue() const { return has_double_value_; }
3578 double DoubleValue() const {
3579 ASSERT(HasDoubleValue());
3580 return double_value_;
3582 bool IsTheHole() const {
3583 if (HasDoubleValue() && FixedDoubleArray::is_the_hole_nan(double_value_)) {
3586 return object_.IsKnownGlobal(isolate()->heap()->the_hole_value());
3588 bool HasNumberValue() const { return has_double_value_; }
3589 int32_t NumberValueAsInteger32() const {
3590 ASSERT(HasNumberValue());
3591 // Irrespective of whether a numeric HConstant can be safely
3592 // represented as an int32, we store the (in some cases lossy)
3593 // representation of the number in int32_value_.
3594 return int32_value_;
3596 bool HasStringValue() const {
3597 if (has_double_value_ || has_int32_value_) return false;
3598 ASSERT(!object_.handle().is_null());
3599 return instance_type_ < FIRST_NONSTRING_TYPE;
3601 Handle<String> StringValue() const {
3602 ASSERT(HasStringValue());
3603 return Handle<String>::cast(object_.handle());
3605 bool HasInternalizedStringValue() const {
3606 return HasStringValue() && StringShape(instance_type_).IsInternalized();
3609 bool HasExternalReferenceValue() const {
3610 return has_external_reference_value_;
3612 ExternalReference ExternalReferenceValue() const {
3613 return external_reference_value_;
3616 bool HasBooleanValue() const { return type_.IsBoolean(); }
3617 bool BooleanValue() const { return boolean_value_; }
3618 bool IsUndetectable() const { return is_undetectable_; }
3619 InstanceType GetInstanceType() const { return instance_type_; }
3621 bool HasObjectMap() const { return !object_map_.IsNull(); }
3622 Unique<Map> ObjectMap() const {
3623 ASSERT(HasObjectMap());
3626 bool ObjectMapIsStable() const {
3627 ASSERT(HasObjectMap());
3628 return object_map_is_stable_;
3631 virtual intptr_t Hashcode() V8_OVERRIDE {
3632 if (has_int32_value_) {
3633 return static_cast<intptr_t>(int32_value_);
3634 } else if (has_double_value_) {
3635 return static_cast<intptr_t>(BitCast<int64_t>(double_value_));
3636 } else if (has_external_reference_value_) {
3637 return reinterpret_cast<intptr_t>(external_reference_value_.address());
3639 ASSERT(!object_.handle().is_null());
3640 return object_.Hashcode();
3644 virtual void FinalizeUniqueness() V8_OVERRIDE {
3645 if (!has_double_value_ && !has_external_reference_value_) {
3646 ASSERT(!object_.handle().is_null());
3647 object_ = Unique<Object>(object_.handle());
3651 Unique<Object> GetUnique() const {
3655 bool EqualsUnique(Unique<Object> other) const {
3656 return object_.IsInitialized() && object_ == other;
3659 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
3660 HConstant* other_constant = HConstant::cast(other);
3661 if (has_int32_value_) {
3662 return other_constant->has_int32_value_ &&
3663 int32_value_ == other_constant->int32_value_;
3664 } else if (has_double_value_) {
3665 return other_constant->has_double_value_ &&
3666 BitCast<int64_t>(double_value_) ==
3667 BitCast<int64_t>(other_constant->double_value_);
3668 } else if (has_external_reference_value_) {
3669 return other_constant->has_external_reference_value_ &&
3670 external_reference_value_ ==
3671 other_constant->external_reference_value_;
3673 if (other_constant->has_int32_value_ ||
3674 other_constant->has_double_value_ ||
3675 other_constant->has_external_reference_value_) {
3678 ASSERT(!object_.handle().is_null());
3679 return other_constant->object_ == object_;
3684 virtual void Verify() V8_OVERRIDE { }
3687 DECLARE_CONCRETE_INSTRUCTION(Constant)
3690 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
3693 friend class HGraph;
3694 HConstant(Handle<Object> handle, Representation r = Representation::None());
3695 HConstant(int32_t value,
3696 Representation r = Representation::None(),
3697 bool is_not_in_new_space = true,
3698 Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3699 HConstant(double value,
3700 Representation r = Representation::None(),
3701 bool is_not_in_new_space = true,
3702 Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3703 HConstant(Unique<Object> unique,
3706 bool is_not_in_new_space,
3708 bool is_undetectable,
3709 InstanceType instance_type);
3711 explicit HConstant(ExternalReference reference);
3713 void Initialize(Representation r);
3715 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
3717 // If this is a numerical constant, object_ either points to the
3718 // HeapObject the constant originated from or is null. If the
3719 // constant is non-numeric, object_ always points to a valid
3720 // constant HeapObject.
3721 Unique<Object> object_;
3723 // If this is a heap object, this points to the Map of the object.
3724 Unique<Map> object_map_;
3725 bool object_map_is_stable_ : 1;
3727 // We store the HConstant in the most specific form safely possible.
3728 // The two flags, has_int32_value_ and has_double_value_ tell us if
3729 // int32_value_ and double_value_ hold valid, safe representations
3730 // of the constant. has_int32_value_ implies has_double_value_ but
3731 // not the converse.
3732 bool has_smi_value_ : 1;
3733 bool has_int32_value_ : 1;
3734 bool has_double_value_ : 1;
3735 bool has_external_reference_value_ : 1;
3736 bool is_not_in_new_space_ : 1;
3737 bool boolean_value_ : 1;
3738 bool is_undetectable_: 1;
3739 int32_t int32_value_;
3740 double double_value_;
3741 ExternalReference external_reference_value_;
3743 static const InstanceType kUnknownInstanceType = FILLER_TYPE;
3744 InstanceType instance_type_;
3748 class HBinaryOperation : public HTemplateInstruction<3> {
3750 HBinaryOperation(HValue* context, HValue* left, HValue* right,
3751 HType type = HType::Tagged())
3752 : HTemplateInstruction<3>(type),
3753 observed_output_representation_(Representation::None()) {
3754 ASSERT(left != NULL && right != NULL);
3755 SetOperandAt(0, context);
3756 SetOperandAt(1, left);
3757 SetOperandAt(2, right);
3758 observed_input_representation_[0] = Representation::None();
3759 observed_input_representation_[1] = Representation::None();
3762 HValue* context() const { return OperandAt(0); }
3763 HValue* left() const { return OperandAt(1); }
3764 HValue* right() const { return OperandAt(2); }
3766 // True if switching left and right operands likely generates better code.
3767 bool AreOperandsBetterSwitched() {
3768 if (!IsCommutative()) return false;
3770 // Constant operands are better off on the right, they can be inlined in
3771 // many situations on most platforms.
3772 if (left()->IsConstant()) return true;
3773 if (right()->IsConstant()) return false;
3775 // Otherwise, if there is only one use of the right operand, it would be
3776 // better off on the left for platforms that only have 2-arg arithmetic
3777 // ops (e.g ia32, x64) that clobber the left operand.
3778 return right()->UseCount() == 1;
3781 HValue* BetterLeftOperand() {
3782 return AreOperandsBetterSwitched() ? right() : left();
3785 HValue* BetterRightOperand() {
3786 return AreOperandsBetterSwitched() ? left() : right();
3789 void set_observed_input_representation(int index, Representation rep) {
3790 ASSERT(index >= 1 && index <= 2);
3791 observed_input_representation_[index - 1] = rep;
3794 virtual void initialize_output_representation(Representation observed) {
3795 observed_output_representation_ = observed;
3798 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
3799 if (index == 0) return Representation::Tagged();
3800 return observed_input_representation_[index - 1];
3803 virtual void UpdateRepresentation(Representation new_rep,
3804 HInferRepresentationPhase* h_infer,
3805 const char* reason) V8_OVERRIDE {
3806 Representation rep = !FLAG_smi_binop && new_rep.IsSmi()
3807 ? Representation::Integer32() : new_rep;
3808 HValue::UpdateRepresentation(rep, h_infer, reason);
3811 virtual void InferRepresentation(
3812 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
3813 virtual Representation RepresentationFromInputs() V8_OVERRIDE;
3814 Representation RepresentationFromOutput();
3815 virtual void AssumeRepresentation(Representation r) V8_OVERRIDE;
3817 virtual bool IsCommutative() const { return false; }
3819 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3821 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3822 if (index == 0) return Representation::Tagged();
3823 return representation();
3826 void SetOperandPositions(Zone* zone,
3827 HSourcePosition left_pos,
3828 HSourcePosition right_pos) {
3829 set_operand_position(zone, 1, left_pos);
3830 set_operand_position(zone, 2, right_pos);
3833 bool RightIsPowerOf2() {
3834 if (!right()->IsInteger32Constant()) return false;
3835 int32_t value = right()->GetInteger32Constant();
3836 return IsPowerOf2(value) || IsPowerOf2(-value);
3839 DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
3842 bool IgnoreObservedOutputRepresentation(Representation current_rep);
3844 Representation observed_input_representation_[2];
3845 Representation observed_output_representation_;
3849 class HWrapReceiver V8_FINAL : public HTemplateInstruction<2> {
3851 DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
3853 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3855 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3856 return Representation::Tagged();
3859 HValue* receiver() { return OperandAt(0); }
3860 HValue* function() { return OperandAt(1); }
3862 virtual HValue* Canonicalize() V8_OVERRIDE;
3864 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3865 bool known_function() const { return known_function_; }
3867 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
3870 HWrapReceiver(HValue* receiver, HValue* function) {
3871 known_function_ = function->IsConstant() &&
3872 HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
3873 set_representation(Representation::Tagged());
3874 SetOperandAt(0, receiver);
3875 SetOperandAt(1, function);
3879 bool known_function_;
3883 class HApplyArguments V8_FINAL : public HTemplateInstruction<4> {
3885 DECLARE_INSTRUCTION_FACTORY_P4(HApplyArguments, HValue*, HValue*, HValue*,
3888 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3889 // The length is untagged, all other inputs are tagged.
3891 ? Representation::Integer32()
3892 : Representation::Tagged();
3895 HValue* function() { return OperandAt(0); }
3896 HValue* receiver() { return OperandAt(1); }
3897 HValue* length() { return OperandAt(2); }
3898 HValue* elements() { return OperandAt(3); }
3900 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
3903 HApplyArguments(HValue* function,
3907 set_representation(Representation::Tagged());
3908 SetOperandAt(0, function);
3909 SetOperandAt(1, receiver);
3910 SetOperandAt(2, length);
3911 SetOperandAt(3, elements);
3912 SetAllSideEffects();
3917 class HArgumentsElements V8_FINAL : public HTemplateInstruction<0> {
3919 DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
3921 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
3923 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3924 return Representation::None();
3927 bool from_inlined() const { return from_inlined_; }
3930 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3933 explicit HArgumentsElements(bool from_inlined) : from_inlined_(from_inlined) {
3934 // The value produced by this instruction is a pointer into the stack
3935 // that looks as if it was a smi because of alignment.
3936 set_representation(Representation::Tagged());
3940 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
3946 class HArgumentsLength V8_FINAL : public HUnaryOperation {
3948 DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue*);
3950 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3951 return Representation::Tagged();
3954 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
3957 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3960 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
3961 set_representation(Representation::Integer32());
3965 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
3969 class HAccessArgumentsAt V8_FINAL : public HTemplateInstruction<3> {
3971 DECLARE_INSTRUCTION_FACTORY_P3(HAccessArgumentsAt, HValue*, HValue*, HValue*);
3973 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3975 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3976 // The arguments elements is considered tagged.
3978 ? Representation::Tagged()
3979 : Representation::Integer32();
3982 HValue* arguments() { return OperandAt(0); }
3983 HValue* length() { return OperandAt(1); }
3984 HValue* index() { return OperandAt(2); }
3986 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
3989 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
3990 set_representation(Representation::Tagged());
3992 SetOperandAt(0, arguments);
3993 SetOperandAt(1, length);
3994 SetOperandAt(2, index);
3997 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4001 class HBoundsCheckBaseIndexInformation;
4004 class HBoundsCheck V8_FINAL : public HTemplateInstruction<2> {
4006 DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
4008 bool skip_check() const { return skip_check_; }
4009 void set_skip_check() { skip_check_ = true; }
4011 HValue* base() { return base_; }
4012 int offset() { return offset_; }
4013 int scale() { return scale_; }
4015 void ApplyIndexChange();
4016 bool DetectCompoundIndex() {
4017 ASSERT(base() == NULL);
4019 DecompositionResult decomposition;
4020 if (index()->TryDecompose(&decomposition)) {
4021 base_ = decomposition.base();
4022 offset_ = decomposition.offset();
4023 scale_ = decomposition.scale();
4033 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4034 return representation();
4037 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4038 virtual void InferRepresentation(
4039 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4041 HValue* index() { return OperandAt(0); }
4042 HValue* length() { return OperandAt(1); }
4043 bool allow_equality() { return allow_equality_; }
4044 void set_allow_equality(bool v) { allow_equality_ = v; }
4046 virtual int RedefinedOperandIndex() V8_OVERRIDE { return 0; }
4047 virtual bool IsPurelyInformativeDefinition() V8_OVERRIDE {
4048 return skip_check();
4051 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
4054 friend class HBoundsCheckBaseIndexInformation;
4056 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4058 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4063 bool allow_equality_;
4066 // Normally HBoundsCheck should be created using the
4067 // HGraphBuilder::AddBoundsCheck() helper.
4068 // However when building stubs, where we know that the arguments are Int32,
4069 // it makes sense to invoke this constructor directly.
4070 HBoundsCheck(HValue* index, HValue* length)
4071 : skip_check_(false),
4072 base_(NULL), offset_(0), scale_(0),
4073 allow_equality_(false) {
4074 SetOperandAt(0, index);
4075 SetOperandAt(1, length);
4076 SetFlag(kFlexibleRepresentation);
4080 virtual bool IsDeletable() const V8_OVERRIDE {
4081 return skip_check() && !FLAG_debug_code;
4086 class HBoundsCheckBaseIndexInformation V8_FINAL
4087 : public HTemplateInstruction<2> {
4089 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) {
4090 DecompositionResult decomposition;
4091 if (check->index()->TryDecompose(&decomposition)) {
4092 SetOperandAt(0, decomposition.base());
4093 SetOperandAt(1, check);
4099 HValue* base_index() { return OperandAt(0); }
4100 HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); }
4102 DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation)
4104 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4105 return representation();
4108 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4110 virtual int RedefinedOperandIndex() V8_OVERRIDE { return 0; }
4111 virtual bool IsPurelyInformativeDefinition() V8_OVERRIDE { return true; }
4115 class HBitwiseBinaryOperation : public HBinaryOperation {
4117 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
4118 HType type = HType::Tagged())
4119 : HBinaryOperation(context, left, right, type) {
4120 SetFlag(kFlexibleRepresentation);
4121 SetFlag(kTruncatingToInt32);
4122 SetFlag(kAllowUndefinedAsNaN);
4123 SetAllSideEffects();
4126 virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
4127 if (to.IsTagged() &&
4128 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
4129 SetAllSideEffects();
4132 ClearAllSideEffects();
4135 if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
4138 virtual void UpdateRepresentation(Representation new_rep,
4139 HInferRepresentationPhase* h_infer,
4140 const char* reason) V8_OVERRIDE {
4141 // We only generate either int32 or generic tagged bitwise operations.
4142 if (new_rep.IsDouble()) new_rep = Representation::Integer32();
4143 HBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4146 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4147 Representation r = HBinaryOperation::observed_input_representation(index);
4148 if (r.IsDouble()) return Representation::Integer32();
4152 virtual void initialize_output_representation(Representation observed) {
4153 if (observed.IsDouble()) observed = Representation::Integer32();
4154 HBinaryOperation::initialize_output_representation(observed);
4157 DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
4160 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4164 class HMathFloorOfDiv V8_FINAL : public HBinaryOperation {
4166 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HMathFloorOfDiv,
4170 DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
4173 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4176 HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
4177 : HBinaryOperation(context, left, right) {
4178 set_representation(Representation::Integer32());
4180 SetFlag(kCanOverflow);
4181 SetFlag(kCanBeDivByZero);
4182 SetFlag(kLeftCanBeMinInt);
4183 SetFlag(kLeftCanBeNegative);
4184 SetFlag(kLeftCanBePositive);
4185 SetFlag(kAllowUndefinedAsNaN);
4188 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4190 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4194 class HArithmeticBinaryOperation : public HBinaryOperation {
4196 HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right)
4197 : HBinaryOperation(context, left, right, HType::TaggedNumber()) {
4198 SetAllSideEffects();
4199 SetFlag(kFlexibleRepresentation);
4200 SetFlag(kAllowUndefinedAsNaN);
4203 virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
4204 if (to.IsTagged() &&
4205 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
4206 SetAllSideEffects();
4209 ClearAllSideEffects();
4212 if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
4215 DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
4218 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4222 class HCompareGeneric V8_FINAL : public HBinaryOperation {
4224 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCompareGeneric, HValue*,
4225 HValue*, Token::Value);
4227 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4229 ? Representation::Tagged()
4233 Token::Value token() const { return token_; }
4234 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4236 DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
4239 HCompareGeneric(HValue* context,
4243 : HBinaryOperation(context, left, right, HType::Boolean()),
4245 ASSERT(Token::IsCompareOp(token));
4246 set_representation(Representation::Tagged());
4247 SetAllSideEffects();
4250 Token::Value token_;
4254 class HCompareNumericAndBranch : public HTemplateControlInstruction<2, 2> {
4256 DECLARE_INSTRUCTION_FACTORY_P3(HCompareNumericAndBranch,
4257 HValue*, HValue*, Token::Value);
4258 DECLARE_INSTRUCTION_FACTORY_P5(HCompareNumericAndBranch,
4259 HValue*, HValue*, Token::Value,
4260 HBasicBlock*, HBasicBlock*);
4262 HValue* left() { return OperandAt(0); }
4263 HValue* right() { return OperandAt(1); }
4264 Token::Value token() const { return token_; }
4266 void set_observed_input_representation(Representation left,
4267 Representation right) {
4268 observed_input_representation_[0] = left;
4269 observed_input_representation_[1] = right;
4272 virtual void InferRepresentation(
4273 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4275 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4276 return representation();
4278 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4279 return observed_input_representation_[index];
4282 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4284 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4286 void SetOperandPositions(Zone* zone,
4287 HSourcePosition left_pos,
4288 HSourcePosition right_pos) {
4289 set_operand_position(zone, 0, left_pos);
4290 set_operand_position(zone, 1, right_pos);
4293 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
4296 HCompareNumericAndBranch(HValue* left,
4299 HBasicBlock* true_target = NULL,
4300 HBasicBlock* false_target = NULL)
4302 SetFlag(kFlexibleRepresentation);
4303 ASSERT(Token::IsCompareOp(token));
4304 SetOperandAt(0, left);
4305 SetOperandAt(1, right);
4306 SetSuccessorAt(0, true_target);
4307 SetSuccessorAt(1, false_target);
4310 Representation observed_input_representation_[2];
4311 Token::Value token_;
4315 class HCompareHoleAndBranch V8_FINAL : public HUnaryControlInstruction {
4317 DECLARE_INSTRUCTION_FACTORY_P1(HCompareHoleAndBranch, HValue*);
4318 DECLARE_INSTRUCTION_FACTORY_P3(HCompareHoleAndBranch, HValue*,
4319 HBasicBlock*, HBasicBlock*);
4321 virtual void InferRepresentation(
4322 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4324 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4325 return representation();
4328 DECLARE_CONCRETE_INSTRUCTION(CompareHoleAndBranch)
4331 HCompareHoleAndBranch(HValue* value,
4332 HBasicBlock* true_target = NULL,
4333 HBasicBlock* false_target = NULL)
4334 : HUnaryControlInstruction(value, true_target, false_target) {
4335 SetFlag(kFlexibleRepresentation);
4336 SetFlag(kAllowUndefinedAsNaN);
4341 class HCompareMinusZeroAndBranch V8_FINAL : public HUnaryControlInstruction {
4343 DECLARE_INSTRUCTION_FACTORY_P1(HCompareMinusZeroAndBranch, HValue*);
4345 virtual void InferRepresentation(
4346 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4348 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4349 return representation();
4352 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4354 DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch)
4357 explicit HCompareMinusZeroAndBranch(HValue* value)
4358 : HUnaryControlInstruction(value, NULL, NULL) {
4363 class HCompareObjectEqAndBranch : public HTemplateControlInstruction<2, 2> {
4365 DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue*, HValue*);
4366 DECLARE_INSTRUCTION_FACTORY_P4(HCompareObjectEqAndBranch, HValue*, HValue*,
4367 HBasicBlock*, HBasicBlock*);
4369 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4371 static const int kNoKnownSuccessorIndex = -1;
4372 int known_successor_index() const { return known_successor_index_; }
4373 void set_known_successor_index(int known_successor_index) {
4374 known_successor_index_ = known_successor_index;
4377 HValue* left() { return OperandAt(0); }
4378 HValue* right() { return OperandAt(1); }
4380 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4382 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4383 return Representation::Tagged();
4386 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4387 return Representation::Tagged();
4390 DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
4393 HCompareObjectEqAndBranch(HValue* left,
4395 HBasicBlock* true_target = NULL,
4396 HBasicBlock* false_target = NULL)
4397 : known_successor_index_(kNoKnownSuccessorIndex) {
4398 ASSERT(!left->IsConstant() ||
4399 (!HConstant::cast(left)->HasInteger32Value() ||
4400 HConstant::cast(left)->HasSmiValue()));
4401 ASSERT(!right->IsConstant() ||
4402 (!HConstant::cast(right)->HasInteger32Value() ||
4403 HConstant::cast(right)->HasSmiValue()));
4404 SetOperandAt(0, left);
4405 SetOperandAt(1, right);
4406 SetSuccessorAt(0, true_target);
4407 SetSuccessorAt(1, false_target);
4410 int known_successor_index_;
4414 class HIsObjectAndBranch V8_FINAL : public HUnaryControlInstruction {
4416 DECLARE_INSTRUCTION_FACTORY_P1(HIsObjectAndBranch, HValue*);
4417 DECLARE_INSTRUCTION_FACTORY_P3(HIsObjectAndBranch, HValue*,
4418 HBasicBlock*, HBasicBlock*);
4420 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4421 return Representation::Tagged();
4424 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4426 DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch)
4429 HIsObjectAndBranch(HValue* value,
4430 HBasicBlock* true_target = NULL,
4431 HBasicBlock* false_target = NULL)
4432 : HUnaryControlInstruction(value, true_target, false_target) {}
4436 class HIsStringAndBranch V8_FINAL : public HUnaryControlInstruction {
4438 DECLARE_INSTRUCTION_FACTORY_P1(HIsStringAndBranch, HValue*);
4439 DECLARE_INSTRUCTION_FACTORY_P3(HIsStringAndBranch, HValue*,
4440 HBasicBlock*, HBasicBlock*);
4442 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4443 return Representation::Tagged();
4446 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4448 DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
4451 virtual int RedefinedOperandIndex() { return 0; }
4454 HIsStringAndBranch(HValue* value,
4455 HBasicBlock* true_target = NULL,
4456 HBasicBlock* false_target = NULL)
4457 : HUnaryControlInstruction(value, true_target, false_target) {}
4461 class HIsSmiAndBranch V8_FINAL : public HUnaryControlInstruction {
4463 DECLARE_INSTRUCTION_FACTORY_P1(HIsSmiAndBranch, HValue*);
4464 DECLARE_INSTRUCTION_FACTORY_P3(HIsSmiAndBranch, HValue*,
4465 HBasicBlock*, HBasicBlock*);
4467 DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
4469 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4470 return Representation::Tagged();
4474 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4475 virtual int RedefinedOperandIndex() { return 0; }
4478 HIsSmiAndBranch(HValue* value,
4479 HBasicBlock* true_target = NULL,
4480 HBasicBlock* false_target = NULL)
4481 : HUnaryControlInstruction(value, true_target, false_target) {
4482 set_representation(Representation::Tagged());
4487 class HIsUndetectableAndBranch V8_FINAL : public HUnaryControlInstruction {
4489 DECLARE_INSTRUCTION_FACTORY_P1(HIsUndetectableAndBranch, HValue*);
4490 DECLARE_INSTRUCTION_FACTORY_P3(HIsUndetectableAndBranch, HValue*,
4491 HBasicBlock*, HBasicBlock*);
4493 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4494 return Representation::Tagged();
4497 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4499 DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
4502 HIsUndetectableAndBranch(HValue* value,
4503 HBasicBlock* true_target = NULL,
4504 HBasicBlock* false_target = NULL)
4505 : HUnaryControlInstruction(value, true_target, false_target) {}
4509 class HStringCompareAndBranch : public HTemplateControlInstruction<2, 3> {
4511 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HStringCompareAndBranch,
4516 HValue* context() { return OperandAt(0); }
4517 HValue* left() { return OperandAt(1); }
4518 HValue* right() { return OperandAt(2); }
4519 Token::Value token() const { return token_; }
4521 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4523 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4524 return Representation::Tagged();
4527 Representation GetInputRepresentation() const {
4528 return Representation::Tagged();
4531 DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
4534 HStringCompareAndBranch(HValue* context,
4539 ASSERT(Token::IsCompareOp(token));
4540 SetOperandAt(0, context);
4541 SetOperandAt(1, left);
4542 SetOperandAt(2, right);
4543 set_representation(Representation::Tagged());
4544 SetChangesFlag(kNewSpacePromotion);
4547 Token::Value token_;
4551 class HIsConstructCallAndBranch : public HTemplateControlInstruction<2, 0> {
4553 DECLARE_INSTRUCTION_FACTORY_P0(HIsConstructCallAndBranch);
4555 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4556 return Representation::None();
4559 DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch)
4561 HIsConstructCallAndBranch() {}
4565 class HHasInstanceTypeAndBranch V8_FINAL : public HUnaryControlInstruction {
4567 DECLARE_INSTRUCTION_FACTORY_P2(
4568 HHasInstanceTypeAndBranch, HValue*, InstanceType);
4569 DECLARE_INSTRUCTION_FACTORY_P3(
4570 HHasInstanceTypeAndBranch, HValue*, InstanceType, InstanceType);
4572 InstanceType from() { return from_; }
4573 InstanceType to() { return to_; }
4575 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4577 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4578 return Representation::Tagged();
4581 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4583 DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
4586 HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
4587 : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
4588 HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
4589 : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
4590 ASSERT(to == LAST_TYPE); // Others not implemented yet in backend.
4594 InstanceType to_; // Inclusive range, not all combinations work.
4598 class HHasCachedArrayIndexAndBranch V8_FINAL : public HUnaryControlInstruction {
4600 DECLARE_INSTRUCTION_FACTORY_P1(HHasCachedArrayIndexAndBranch, HValue*);
4602 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4603 return Representation::Tagged();
4606 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
4608 explicit HHasCachedArrayIndexAndBranch(HValue* value)
4609 : HUnaryControlInstruction(value, NULL, NULL) { }
4613 class HGetCachedArrayIndex V8_FINAL : public HUnaryOperation {
4615 DECLARE_INSTRUCTION_FACTORY_P1(HGetCachedArrayIndex, HValue*);
4617 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4618 return Representation::Tagged();
4621 DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
4624 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4627 explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
4628 set_representation(Representation::Tagged());
4632 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4636 class HClassOfTestAndBranch V8_FINAL : public HUnaryControlInstruction {
4638 DECLARE_INSTRUCTION_FACTORY_P2(HClassOfTestAndBranch, HValue*,
4641 DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
4643 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4644 return Representation::Tagged();
4647 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4649 Handle<String> class_name() const { return class_name_; }
4652 HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
4653 : HUnaryControlInstruction(value, NULL, NULL),
4654 class_name_(class_name) { }
4656 Handle<String> class_name_;
4660 class HTypeofIsAndBranch V8_FINAL : public HUnaryControlInstruction {
4662 DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle<String>);
4664 Handle<String> type_literal() { return type_literal_.handle(); }
4665 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4667 DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
4669 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4670 return Representation::None();
4673 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4675 virtual void FinalizeUniqueness() V8_OVERRIDE {
4676 type_literal_ = Unique<String>(type_literal_.handle());
4680 HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
4681 : HUnaryControlInstruction(value, NULL, NULL),
4682 type_literal_(Unique<String>::CreateUninitialized(type_literal)) { }
4684 Unique<String> type_literal_;
4688 class HInstanceOf V8_FINAL : public HBinaryOperation {
4690 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOf, HValue*, HValue*);
4692 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4693 return Representation::Tagged();
4696 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4698 DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
4701 HInstanceOf(HValue* context, HValue* left, HValue* right)
4702 : HBinaryOperation(context, left, right, HType::Boolean()) {
4703 set_representation(Representation::Tagged());
4704 SetAllSideEffects();
4709 class HInstanceOfKnownGlobal V8_FINAL : public HTemplateInstruction<2> {
4711 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOfKnownGlobal,
4713 Handle<JSFunction>);
4715 HValue* context() { return OperandAt(0); }
4716 HValue* left() { return OperandAt(1); }
4717 Handle<JSFunction> function() { return function_; }
4719 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4720 return Representation::Tagged();
4723 DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal)
4726 HInstanceOfKnownGlobal(HValue* context,
4728 Handle<JSFunction> right)
4729 : HTemplateInstruction<2>(HType::Boolean()), function_(right) {
4730 SetOperandAt(0, context);
4731 SetOperandAt(1, left);
4732 set_representation(Representation::Tagged());
4733 SetAllSideEffects();
4736 Handle<JSFunction> function_;
4740 class HPower V8_FINAL : public HTemplateInstruction<2> {
4742 static HInstruction* New(Zone* zone,
4747 HValue* left() { return OperandAt(0); }
4748 HValue* right() const { return OperandAt(1); }
4750 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4752 ? Representation::Double()
4753 : Representation::None();
4755 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4756 return RequiredInputRepresentation(index);
4759 DECLARE_CONCRETE_INSTRUCTION(Power)
4762 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4765 HPower(HValue* left, HValue* right) {
4766 SetOperandAt(0, left);
4767 SetOperandAt(1, right);
4768 set_representation(Representation::Double());
4770 SetChangesFlag(kNewSpacePromotion);
4773 virtual bool IsDeletable() const V8_OVERRIDE {
4774 return !right()->representation().IsTagged();
4779 class HAdd V8_FINAL : public HArithmeticBinaryOperation {
4781 static HInstruction* New(Zone* zone,
4786 // Add is only commutative if two integer values are added and not if two
4787 // tagged values are added (because it might be a String concatenation).
4788 // We also do not commute (pointer + offset).
4789 virtual bool IsCommutative() const V8_OVERRIDE {
4790 return !representation().IsTagged() && !representation().IsExternal();
4793 virtual HValue* Canonicalize() V8_OVERRIDE;
4795 virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
4796 if (left()->IsInteger32Constant()) {
4797 decomposition->Apply(right(), left()->GetInteger32Constant());
4799 } else if (right()->IsInteger32Constant()) {
4800 decomposition->Apply(left(), right()->GetInteger32Constant());
4807 virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
4808 if (to.IsTagged() &&
4809 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() ||
4810 left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) {
4811 SetAllSideEffects();
4814 ClearAllSideEffects();
4817 if (to.IsTagged()) {
4818 SetChangesFlag(kNewSpacePromotion);
4819 ClearFlag(kAllowUndefinedAsNaN);
4823 virtual Representation RepresentationFromInputs() V8_OVERRIDE;
4825 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE;
4827 DECLARE_CONCRETE_INSTRUCTION(Add)
4830 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4832 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4835 HAdd(HValue* context, HValue* left, HValue* right)
4836 : HArithmeticBinaryOperation(context, left, right) {
4837 SetFlag(kCanOverflow);
4842 class HSub V8_FINAL : public HArithmeticBinaryOperation {
4844 static HInstruction* New(Zone* zone,
4849 virtual HValue* Canonicalize() V8_OVERRIDE;
4851 virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
4852 if (right()->IsInteger32Constant()) {
4853 decomposition->Apply(left(), -right()->GetInteger32Constant());
4860 DECLARE_CONCRETE_INSTRUCTION(Sub)
4863 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4865 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4868 HSub(HValue* context, HValue* left, HValue* right)
4869 : HArithmeticBinaryOperation(context, left, right) {
4870 SetFlag(kCanOverflow);
4875 class HMul V8_FINAL : public HArithmeticBinaryOperation {
4877 static HInstruction* New(Zone* zone,
4882 static HInstruction* NewImul(Zone* zone,
4886 HInstruction* instr = HMul::New(zone, context, left, right);
4887 if (!instr->IsMul()) return instr;
4888 HMul* mul = HMul::cast(instr);
4889 // TODO(mstarzinger): Prevent bailout on minus zero for imul.
4890 mul->AssumeRepresentation(Representation::Integer32());
4891 mul->ClearFlag(HValue::kCanOverflow);
4895 virtual HValue* Canonicalize() V8_OVERRIDE;
4897 // Only commutative if it is certain that not two objects are multiplicated.
4898 virtual bool IsCommutative() const V8_OVERRIDE {
4899 return !representation().IsTagged();
4902 virtual void UpdateRepresentation(Representation new_rep,
4903 HInferRepresentationPhase* h_infer,
4904 const char* reason) V8_OVERRIDE {
4905 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4910 DECLARE_CONCRETE_INSTRUCTION(Mul)
4913 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4915 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4918 HMul(HValue* context, HValue* left, HValue* right)
4919 : HArithmeticBinaryOperation(context, left, right) {
4920 SetFlag(kCanOverflow);
4925 class HMod V8_FINAL : public HArithmeticBinaryOperation {
4927 static HInstruction* New(Zone* zone,
4932 virtual HValue* Canonicalize() V8_OVERRIDE;
4934 virtual void UpdateRepresentation(Representation new_rep,
4935 HInferRepresentationPhase* h_infer,
4936 const char* reason) V8_OVERRIDE {
4937 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4938 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4941 DECLARE_CONCRETE_INSTRUCTION(Mod)
4944 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4946 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4949 HMod(HValue* context,
4951 HValue* right) : HArithmeticBinaryOperation(context, left, right) {
4952 SetFlag(kCanBeDivByZero);
4953 SetFlag(kCanOverflow);
4954 SetFlag(kLeftCanBeNegative);
4959 class HDiv V8_FINAL : public HArithmeticBinaryOperation {
4961 static HInstruction* New(Zone* zone,
4966 virtual HValue* Canonicalize() V8_OVERRIDE;
4968 virtual void UpdateRepresentation(Representation new_rep,
4969 HInferRepresentationPhase* h_infer,
4970 const char* reason) V8_OVERRIDE {
4971 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4972 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4975 DECLARE_CONCRETE_INSTRUCTION(Div)
4978 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4980 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4983 HDiv(HValue* context, HValue* left, HValue* right)
4984 : HArithmeticBinaryOperation(context, left, right) {
4985 SetFlag(kCanBeDivByZero);
4986 SetFlag(kCanOverflow);
4991 class HMathMinMax V8_FINAL : public HArithmeticBinaryOperation {
4993 enum Operation { kMathMin, kMathMax };
4995 static HInstruction* New(Zone* zone,
5001 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
5002 return RequiredInputRepresentation(index);
5005 virtual void InferRepresentation(
5006 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
5008 virtual Representation RepresentationFromInputs() V8_OVERRIDE {
5009 Representation left_rep = left()->representation();
5010 Representation right_rep = right()->representation();
5011 Representation result = Representation::Smi();
5012 result = result.generalize(left_rep);
5013 result = result.generalize(right_rep);
5014 if (result.IsTagged()) return Representation::Double();
5018 virtual bool IsCommutative() const V8_OVERRIDE { return true; }
5020 Operation operation() { return operation_; }
5022 DECLARE_CONCRETE_INSTRUCTION(MathMinMax)
5025 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
5026 return other->IsMathMinMax() &&
5027 HMathMinMax::cast(other)->operation_ == operation_;
5030 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5033 HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
5034 : HArithmeticBinaryOperation(context, left, right),
5037 Operation operation_;
5041 class HBitwise V8_FINAL : public HBitwiseBinaryOperation {
5043 static HInstruction* New(Zone* zone,
5049 Token::Value op() const { return op_; }
5051 virtual bool IsCommutative() const V8_OVERRIDE { return true; }
5053 virtual HValue* Canonicalize() V8_OVERRIDE;
5055 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5057 DECLARE_CONCRETE_INSTRUCTION(Bitwise)
5060 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
5061 return op() == HBitwise::cast(other)->op();
5064 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5067 HBitwise(HValue* context,
5071 : HBitwiseBinaryOperation(context, left, right, HType::TaggedNumber()),
5073 ASSERT(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
5074 // BIT_AND with a smi-range positive value will always unset the
5075 // entire sign-extension of the smi-sign.
5076 if (op == Token::BIT_AND &&
5077 ((left->IsConstant() &&
5078 left->representation().IsSmi() &&
5079 HConstant::cast(left)->Integer32Value() >= 0) ||
5080 (right->IsConstant() &&
5081 right->representation().IsSmi() &&
5082 HConstant::cast(right)->Integer32Value() >= 0))) {
5083 SetFlag(kTruncatingToSmi);
5084 SetFlag(kTruncatingToInt32);
5085 // BIT_OR with a smi-range negative value will always set the entire
5086 // sign-extension of the smi-sign.
5087 } else if (op == Token::BIT_OR &&
5088 ((left->IsConstant() &&
5089 left->representation().IsSmi() &&
5090 HConstant::cast(left)->Integer32Value() < 0) ||
5091 (right->IsConstant() &&
5092 right->representation().IsSmi() &&
5093 HConstant::cast(right)->Integer32Value() < 0))) {
5094 SetFlag(kTruncatingToSmi);
5095 SetFlag(kTruncatingToInt32);
5103 class HShl V8_FINAL : public HBitwiseBinaryOperation {
5105 static HInstruction* New(Zone* zone,
5110 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5112 virtual void UpdateRepresentation(Representation new_rep,
5113 HInferRepresentationPhase* h_infer,
5114 const char* reason) V8_OVERRIDE {
5115 if (new_rep.IsSmi() &&
5116 !(right()->IsInteger32Constant() &&
5117 right()->GetInteger32Constant() >= 0)) {
5118 new_rep = Representation::Integer32();
5120 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5123 DECLARE_CONCRETE_INSTRUCTION(Shl)
5126 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5129 HShl(HValue* context, HValue* left, HValue* right)
5130 : HBitwiseBinaryOperation(context, left, right) { }
5134 class HShr V8_FINAL : public HBitwiseBinaryOperation {
5136 static HInstruction* New(Zone* zone,
5141 virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
5142 if (right()->IsInteger32Constant()) {
5143 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
5144 // This is intended to look for HAdd and HSub, to handle compounds
5145 // like ((base + offset) >> scale) with one single decomposition.
5146 left()->TryDecompose(decomposition);
5153 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5155 virtual void UpdateRepresentation(Representation new_rep,
5156 HInferRepresentationPhase* h_infer,
5157 const char* reason) V8_OVERRIDE {
5158 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5159 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5162 DECLARE_CONCRETE_INSTRUCTION(Shr)
5165 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5168 HShr(HValue* context, HValue* left, HValue* right)
5169 : HBitwiseBinaryOperation(context, left, right) { }
5173 class HSar V8_FINAL : public HBitwiseBinaryOperation {
5175 static HInstruction* New(Zone* zone,
5180 virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
5181 if (right()->IsInteger32Constant()) {
5182 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
5183 // This is intended to look for HAdd and HSub, to handle compounds
5184 // like ((base + offset) >> scale) with one single decomposition.
5185 left()->TryDecompose(decomposition);
5192 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5194 virtual void UpdateRepresentation(Representation new_rep,
5195 HInferRepresentationPhase* h_infer,
5196 const char* reason) V8_OVERRIDE {
5197 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5198 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5201 DECLARE_CONCRETE_INSTRUCTION(Sar)
5204 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5207 HSar(HValue* context, HValue* left, HValue* right)
5208 : HBitwiseBinaryOperation(context, left, right) { }
5212 class HRor V8_FINAL : public HBitwiseBinaryOperation {
5214 static HInstruction* New(Zone* zone,
5218 return new(zone) HRor(context, left, right);
5221 virtual void UpdateRepresentation(Representation new_rep,
5222 HInferRepresentationPhase* h_infer,
5223 const char* reason) V8_OVERRIDE {
5224 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5225 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5228 DECLARE_CONCRETE_INSTRUCTION(Ror)
5231 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5234 HRor(HValue* context, HValue* left, HValue* right)
5235 : HBitwiseBinaryOperation(context, left, right) {
5236 ChangeRepresentation(Representation::Integer32());
5241 class HOsrEntry V8_FINAL : public HTemplateInstruction<0> {
5243 DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId);
5245 BailoutId ast_id() const { return ast_id_; }
5247 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5248 return Representation::None();
5251 DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
5254 explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
5255 SetChangesFlag(kOsrEntries);
5256 SetChangesFlag(kNewSpacePromotion);
5263 class HParameter V8_FINAL : public HTemplateInstruction<0> {
5265 enum ParameterKind {
5270 DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned);
5271 DECLARE_INSTRUCTION_FACTORY_P2(HParameter, unsigned, ParameterKind);
5272 DECLARE_INSTRUCTION_FACTORY_P3(HParameter, unsigned, ParameterKind,
5275 unsigned index() const { return index_; }
5276 ParameterKind kind() const { return kind_; }
5278 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5280 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5281 return Representation::None();
5284 DECLARE_CONCRETE_INSTRUCTION(Parameter)
5287 explicit HParameter(unsigned index,
5288 ParameterKind kind = STACK_PARAMETER)
5291 set_representation(Representation::Tagged());
5294 explicit HParameter(unsigned index,
5299 set_representation(r);
5303 ParameterKind kind_;
5307 class HCallStub V8_FINAL : public HUnaryCall {
5309 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallStub, CodeStub::Major, int);
5310 CodeStub::Major major_key() { return major_key_; }
5312 HValue* context() { return value(); }
5314 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5316 DECLARE_CONCRETE_INSTRUCTION(CallStub)
5319 HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
5320 : HUnaryCall(context, argument_count),
5321 major_key_(major_key) {
5324 CodeStub::Major major_key_;
5328 class HUnknownOSRValue V8_FINAL : public HTemplateInstruction<0> {
5330 DECLARE_INSTRUCTION_FACTORY_P2(HUnknownOSRValue, HEnvironment*, int);
5332 virtual void PrintDataTo(StringStream* stream);
5334 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5335 return Representation::None();
5338 void set_incoming_value(HPhi* value) { incoming_value_ = value; }
5339 HPhi* incoming_value() { return incoming_value_; }
5340 HEnvironment *environment() { return environment_; }
5341 int index() { return index_; }
5343 virtual Representation KnownOptimalRepresentation() V8_OVERRIDE {
5344 if (incoming_value_ == NULL) return Representation::None();
5345 return incoming_value_->KnownOptimalRepresentation();
5348 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
5351 HUnknownOSRValue(HEnvironment* environment, int index)
5352 : environment_(environment),
5354 incoming_value_(NULL) {
5355 set_representation(Representation::Tagged());
5358 HEnvironment* environment_;
5360 HPhi* incoming_value_;
5364 class HLoadGlobalCell V8_FINAL : public HTemplateInstruction<0> {
5366 DECLARE_INSTRUCTION_FACTORY_P2(HLoadGlobalCell, Handle<Cell>,
5369 Unique<Cell> cell() const { return cell_; }
5370 bool RequiresHoleCheck() const;
5372 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5374 virtual intptr_t Hashcode() V8_OVERRIDE {
5375 return cell_.Hashcode();
5378 virtual void FinalizeUniqueness() V8_OVERRIDE {
5379 cell_ = Unique<Cell>(cell_.handle());
5382 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5383 return Representation::None();
5386 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell)
5389 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
5390 return cell_ == HLoadGlobalCell::cast(other)->cell_;
5394 HLoadGlobalCell(Handle<Cell> cell, PropertyDetails details)
5395 : cell_(Unique<Cell>::CreateUninitialized(cell)), details_(details) {
5396 set_representation(Representation::Tagged());
5398 SetDependsOnFlag(kGlobalVars);
5401 virtual bool IsDeletable() const V8_OVERRIDE { return !RequiresHoleCheck(); }
5404 PropertyDetails details_;
5408 class HLoadGlobalGeneric V8_FINAL : public HTemplateInstruction<2> {
5410 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadGlobalGeneric, HValue*,
5411 Handle<Object>, bool);
5413 HValue* context() { return OperandAt(0); }
5414 HValue* global_object() { return OperandAt(1); }
5415 Handle<Object> name() const { return name_; }
5416 bool for_typeof() const { return for_typeof_; }
5418 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5420 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5421 return Representation::Tagged();
5424 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
5427 HLoadGlobalGeneric(HValue* context,
5428 HValue* global_object,
5429 Handle<Object> name,
5432 for_typeof_(for_typeof) {
5433 SetOperandAt(0, context);
5434 SetOperandAt(1, global_object);
5435 set_representation(Representation::Tagged());
5436 SetAllSideEffects();
5439 Handle<Object> name_;
5444 class HAllocate V8_FINAL : public HTemplateInstruction<2> {
5446 static bool CompatibleInstanceTypes(InstanceType type1,
5447 InstanceType type2) {
5448 return ComputeFlags(TENURED, type1) == ComputeFlags(TENURED, type2) &&
5449 ComputeFlags(NOT_TENURED, type1) == ComputeFlags(NOT_TENURED, type2);
5452 static HAllocate* New(Zone* zone,
5456 PretenureFlag pretenure_flag,
5457 InstanceType instance_type,
5458 Handle<AllocationSite> allocation_site =
5459 Handle<AllocationSite>::null()) {
5460 return new(zone) HAllocate(context, size, type, pretenure_flag,
5461 instance_type, allocation_site);
5464 // Maximum instance size for which allocations will be inlined.
5465 static const int kMaxInlineSize = 64 * kPointerSize;
5467 HValue* context() { return OperandAt(0); }
5468 HValue* size() { return OperandAt(1); }
5470 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5472 return Representation::Tagged();
5474 return Representation::Integer32();
5478 virtual Handle<Map> GetMonomorphicJSObjectMap() {
5479 return known_initial_map_;
5482 void set_known_initial_map(Handle<Map> known_initial_map) {
5483 known_initial_map_ = known_initial_map;
5486 bool IsNewSpaceAllocation() const {
5487 return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
5490 bool IsOldDataSpaceAllocation() const {
5491 return (flags_ & ALLOCATE_IN_OLD_DATA_SPACE) != 0;
5494 bool IsOldPointerSpaceAllocation() const {
5495 return (flags_ & ALLOCATE_IN_OLD_POINTER_SPACE) != 0;
5498 bool MustAllocateDoubleAligned() const {
5499 return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
5502 bool MustPrefillWithFiller() const {
5503 return (flags_ & PREFILL_WITH_FILLER) != 0;
5506 void MakePrefillWithFiller() {
5507 flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
5510 bool MustClearNextMapWord() const {
5511 return (flags_ & CLEAR_NEXT_MAP_WORD) != 0;
5514 void MakeDoubleAligned() {
5515 flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
5518 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
5519 HValue* dominator) V8_OVERRIDE;
5521 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5523 DECLARE_CONCRETE_INSTRUCTION(Allocate)
5527 ALLOCATE_IN_NEW_SPACE = 1 << 0,
5528 ALLOCATE_IN_OLD_DATA_SPACE = 1 << 1,
5529 ALLOCATE_IN_OLD_POINTER_SPACE = 1 << 2,
5530 ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
5531 PREFILL_WITH_FILLER = 1 << 4,
5532 CLEAR_NEXT_MAP_WORD = 1 << 5
5535 HAllocate(HValue* context,
5538 PretenureFlag pretenure_flag,
5539 InstanceType instance_type,
5540 Handle<AllocationSite> allocation_site =
5541 Handle<AllocationSite>::null())
5542 : HTemplateInstruction<2>(type),
5543 flags_(ComputeFlags(pretenure_flag, instance_type)),
5544 dominating_allocate_(NULL),
5545 filler_free_space_size_(NULL) {
5546 SetOperandAt(0, context);
5547 SetOperandAt(1, size);
5548 set_representation(Representation::Tagged());
5549 SetFlag(kTrackSideEffectDominators);
5550 SetChangesFlag(kNewSpacePromotion);
5551 SetDependsOnFlag(kNewSpacePromotion);
5553 if (FLAG_trace_pretenuring) {
5554 PrintF("HAllocate with AllocationSite %p %s\n",
5555 allocation_site.is_null()
5556 ? static_cast<void*>(NULL)
5557 : static_cast<void*>(*allocation_site),
5558 pretenure_flag == TENURED ? "tenured" : "not tenured");
5562 static Flags ComputeFlags(PretenureFlag pretenure_flag,
5563 InstanceType instance_type) {
5564 Flags flags = pretenure_flag == TENURED
5565 ? (Heap::TargetSpaceId(instance_type) == OLD_POINTER_SPACE
5566 ? ALLOCATE_IN_OLD_POINTER_SPACE : ALLOCATE_IN_OLD_DATA_SPACE)
5567 : ALLOCATE_IN_NEW_SPACE;
5568 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
5569 flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED);
5571 // We have to fill the allocated object with one word fillers if we do
5572 // not use allocation folding since some allocations may depend on each
5573 // other, i.e., have a pointer to each other. A GC in between these
5574 // allocations may leave such objects behind in a not completely initialized
5576 if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
5577 flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER);
5579 if (pretenure_flag == NOT_TENURED &&
5580 AllocationSite::CanTrack(instance_type)) {
5581 flags = static_cast<Flags>(flags | CLEAR_NEXT_MAP_WORD);
5586 void UpdateClearNextMapWord(bool clear_next_map_word) {
5587 flags_ = static_cast<Flags>(clear_next_map_word
5588 ? flags_ | CLEAR_NEXT_MAP_WORD
5589 : flags_ & ~CLEAR_NEXT_MAP_WORD);
5592 void UpdateSize(HValue* size) {
5593 SetOperandAt(1, size);
5596 HAllocate* GetFoldableDominator(HAllocate* dominator);
5598 void UpdateFreeSpaceFiller(int32_t filler_size);
5600 void CreateFreeSpaceFiller(int32_t filler_size);
5602 bool IsFoldable(HAllocate* allocate) {
5603 return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) ||
5604 (IsOldDataSpaceAllocation() && allocate->IsOldDataSpaceAllocation()) ||
5605 (IsOldPointerSpaceAllocation() &&
5606 allocate->IsOldPointerSpaceAllocation());
5609 void ClearNextMapWord(int offset);
5612 Handle<Map> known_initial_map_;
5613 HAllocate* dominating_allocate_;
5614 HStoreNamedField* filler_free_space_size_;
5618 class HStoreCodeEntry V8_FINAL: public HTemplateInstruction<2> {
5620 static HStoreCodeEntry* New(Zone* zone,
5624 return new(zone) HStoreCodeEntry(function, code);
5627 virtual Representation RequiredInputRepresentation(int index) {
5628 return Representation::Tagged();
5631 HValue* function() { return OperandAt(0); }
5632 HValue* code_object() { return OperandAt(1); }
5634 DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry)
5637 HStoreCodeEntry(HValue* function, HValue* code) {
5638 SetOperandAt(0, function);
5639 SetOperandAt(1, code);
5644 class HInnerAllocatedObject V8_FINAL : public HTemplateInstruction<2> {
5646 static HInnerAllocatedObject* New(Zone* zone,
5650 HType type = HType::Tagged()) {
5651 return new(zone) HInnerAllocatedObject(value, offset, type);
5654 HValue* base_object() { return OperandAt(0); }
5655 HValue* offset() { return OperandAt(1); }
5657 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5658 return index == 0 ? Representation::Tagged() : Representation::Integer32();
5661 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5663 DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
5666 HInnerAllocatedObject(HValue* value,
5668 HType type = HType::Tagged())
5669 : HTemplateInstruction<2>(type) {
5670 ASSERT(value->IsAllocate());
5671 SetOperandAt(0, value);
5672 SetOperandAt(1, offset);
5674 set_representation(Representation::Tagged());
5679 inline bool StoringValueNeedsWriteBarrier(HValue* value) {
5680 return !value->type().IsBoolean()
5681 && !value->type().IsSmi()
5682 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
5686 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
5688 HValue* new_space_dominator) {
5689 while (object->IsInnerAllocatedObject()) {
5690 object = HInnerAllocatedObject::cast(object)->base_object();
5692 if (object->IsConstant() && HConstant::cast(object)->IsCell()) {
5695 if (object->IsConstant() &&
5696 HConstant::cast(object)->HasExternalReferenceValue()) {
5697 // Stores to external references require no write barriers
5700 if (object != new_space_dominator) return true;
5701 if (object->IsAllocate()) {
5702 // Stores to new space allocations require no write barriers if the object
5703 // is the new space dominator.
5704 if (HAllocate::cast(object)->IsNewSpaceAllocation()) {
5707 // Likewise we don't need a write barrier if we store a value that
5708 // originates from the same allocation (via allocation folding).
5709 while (value->IsInnerAllocatedObject()) {
5710 value = HInnerAllocatedObject::cast(value)->base_object();
5712 return object != value;
5718 class HStoreGlobalCell V8_FINAL : public HUnaryOperation {
5720 DECLARE_INSTRUCTION_FACTORY_P3(HStoreGlobalCell, HValue*,
5721 Handle<PropertyCell>, PropertyDetails);
5723 Unique<PropertyCell> cell() const { return cell_; }
5724 bool RequiresHoleCheck() {
5725 return !details_.IsDontDelete() || details_.IsReadOnly();
5727 bool NeedsWriteBarrier() {
5728 return StoringValueNeedsWriteBarrier(value());
5731 virtual void FinalizeUniqueness() V8_OVERRIDE {
5732 cell_ = Unique<PropertyCell>(cell_.handle());
5735 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5736 return Representation::Tagged();
5738 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5740 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell)
5743 HStoreGlobalCell(HValue* value,
5744 Handle<PropertyCell> cell,
5745 PropertyDetails details)
5746 : HUnaryOperation(value),
5747 cell_(Unique<PropertyCell>::CreateUninitialized(cell)),
5749 SetChangesFlag(kGlobalVars);
5752 Unique<PropertyCell> cell_;
5753 PropertyDetails details_;
5757 class HLoadContextSlot V8_FINAL : public HUnaryOperation {
5760 // Perform a normal load of the context slot without checking its value.
5762 // Load and check the value of the context slot. Deoptimize if it's the
5763 // hole value. This is used for checking for loading of uninitialized
5764 // harmony bindings where we deoptimize into full-codegen generated code
5765 // which will subsequently throw a reference error.
5767 // Load and check the value of the context slot. Return undefined if it's
5768 // the hole value. This is used for non-harmony const assignments
5769 kCheckReturnUndefined
5772 HLoadContextSlot(HValue* context, Variable* var)
5773 : HUnaryOperation(context), slot_index_(var->index()) {
5774 ASSERT(var->IsContextSlot());
5775 switch (var->mode()) {
5778 mode_ = kCheckDeoptimize;
5781 mode_ = kCheckReturnUndefined;
5786 set_representation(Representation::Tagged());
5788 SetDependsOnFlag(kContextSlots);
5791 int slot_index() const { return slot_index_; }
5792 Mode mode() const { return mode_; }
5794 bool DeoptimizesOnHole() {
5795 return mode_ == kCheckDeoptimize;
5798 bool RequiresHoleCheck() const {
5799 return mode_ != kNoCheck;
5802 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5803 return Representation::Tagged();
5806 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5808 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
5811 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
5812 HLoadContextSlot* b = HLoadContextSlot::cast(other);
5813 return (slot_index() == b->slot_index());
5817 virtual bool IsDeletable() const V8_OVERRIDE { return !RequiresHoleCheck(); }
5824 class HStoreContextSlot V8_FINAL : public HTemplateInstruction<2> {
5827 // Perform a normal store to the context slot without checking its previous
5830 // Check the previous value of the context slot and deoptimize if it's the
5831 // hole value. This is used for checking for assignments to uninitialized
5832 // harmony bindings where we deoptimize into full-codegen generated code
5833 // which will subsequently throw a reference error.
5835 // Check the previous value and ignore assignment if it isn't a hole value
5836 kCheckIgnoreAssignment
5839 DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
5842 HValue* context() { return OperandAt(0); }
5843 HValue* value() { return OperandAt(1); }
5844 int slot_index() const { return slot_index_; }
5845 Mode mode() const { return mode_; }
5847 bool NeedsWriteBarrier() {
5848 return StoringValueNeedsWriteBarrier(value());
5851 bool DeoptimizesOnHole() {
5852 return mode_ == kCheckDeoptimize;
5855 bool RequiresHoleCheck() {
5856 return mode_ != kNoCheck;
5859 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5860 return Representation::Tagged();
5863 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5865 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
5868 HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
5869 : slot_index_(slot_index), mode_(mode) {
5870 SetOperandAt(0, context);
5871 SetOperandAt(1, value);
5872 SetChangesFlag(kContextSlots);
5880 // Represents an access to a portion of an object, such as the map pointer,
5881 // array elements pointer, etc, but not accesses to array elements themselves.
5882 class HObjectAccess V8_FINAL {
5884 inline bool IsInobject() const {
5885 return portion() != kBackingStore && portion() != kExternalMemory;
5888 inline bool IsExternalMemory() const {
5889 return portion() == kExternalMemory;
5892 inline bool IsStringLength() const {
5893 return portion() == kStringLengths;
5896 inline bool IsMap() const {
5897 return portion() == kMaps;
5900 inline int offset() const {
5901 return OffsetField::decode(value_);
5904 inline Representation representation() const {
5905 return Representation::FromKind(RepresentationField::decode(value_));
5908 inline Handle<String> name() const {
5912 inline bool immutable() const {
5913 return ImmutableField::decode(value_);
5916 // Returns true if access is being made to an in-object property that
5917 // was already added to the object.
5918 inline bool existing_inobject_property() const {
5919 return ExistingInobjectPropertyField::decode(value_);
5922 inline HObjectAccess WithRepresentation(Representation representation) {
5923 return HObjectAccess(portion(), offset(), representation, name(),
5924 immutable(), existing_inobject_property());
5927 static HObjectAccess ForHeapNumberValue() {
5928 return HObjectAccess(
5929 kDouble, HeapNumber::kValueOffset, Representation::Double());
5932 static HObjectAccess ForHeapNumberValueLowestBits() {
5933 return HObjectAccess(kDouble,
5934 HeapNumber::kValueOffset,
5935 Representation::Integer32());
5938 static HObjectAccess ForHeapNumberValueHighestBits() {
5939 return HObjectAccess(kDouble,
5940 HeapNumber::kValueOffset + kIntSize,
5941 Representation::Integer32());
5944 static HObjectAccess ForSIMD128Double0() {
5945 return HObjectAccess(
5946 kDouble, Float32x4::kValueOffset, Representation::Double());
5949 static HObjectAccess ForSIMD128Double1() {
5950 return HObjectAccess(kDouble,
5951 Float32x4::kValueOffset + kDoubleSize,
5952 Representation::Double());
5955 static HObjectAccess ForElementsPointer() {
5956 return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
5959 static HObjectAccess ForLiteralsPointer() {
5960 return HObjectAccess(kInobject, JSFunction::kLiteralsOffset);
5963 static HObjectAccess ForNextFunctionLinkPointer() {
5964 return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
5967 static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
5968 return HObjectAccess(
5970 JSArray::kLengthOffset,
5971 IsFastElementsKind(elements_kind)
5972 ? Representation::Smi() : Representation::Tagged());
5975 static HObjectAccess ForAllocationSiteOffset(int offset);
5977 static HObjectAccess ForAllocationSiteList() {
5978 return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
5979 Handle<String>::null(), false, false);
5982 static HObjectAccess ForFixedArrayLength() {
5983 return HObjectAccess(
5985 FixedArray::kLengthOffset,
5986 Representation::Smi());
5989 static HObjectAccess ForStringHashField() {
5990 return HObjectAccess(kInobject,
5991 String::kHashFieldOffset,
5992 Representation::Integer32());
5995 static HObjectAccess ForStringLength() {
5996 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
5997 return HObjectAccess(
5999 String::kLengthOffset,
6000 Representation::Smi());
6003 static HObjectAccess ForConsStringFirst() {
6004 return HObjectAccess(kInobject, ConsString::kFirstOffset);
6007 static HObjectAccess ForConsStringSecond() {
6008 return HObjectAccess(kInobject, ConsString::kSecondOffset);
6011 static HObjectAccess ForPropertiesPointer() {
6012 return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
6015 static HObjectAccess ForPrototypeOrInitialMap() {
6016 return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
6019 static HObjectAccess ForSharedFunctionInfoPointer() {
6020 return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
6023 static HObjectAccess ForCodeEntryPointer() {
6024 return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
6027 static HObjectAccess ForCodeOffset() {
6028 return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
6031 static HObjectAccess ForOptimizedCodeMap() {
6032 return HObjectAccess(kInobject,
6033 SharedFunctionInfo::kOptimizedCodeMapOffset);
6036 static HObjectAccess ForFunctionContextPointer() {
6037 return HObjectAccess(kInobject, JSFunction::kContextOffset);
6040 static HObjectAccess ForMap() {
6041 return HObjectAccess(kMaps, JSObject::kMapOffset);
6044 static HObjectAccess ForMapInstanceSize() {
6045 return HObjectAccess(kInobject,
6046 Map::kInstanceSizeOffset,
6047 Representation::UInteger8());
6050 static HObjectAccess ForMapInstanceType() {
6051 return HObjectAccess(kInobject,
6052 Map::kInstanceTypeOffset,
6053 Representation::UInteger8());
6056 static HObjectAccess ForMapPrototype() {
6057 return HObjectAccess(kInobject, Map::kPrototypeOffset);
6060 static HObjectAccess ForPropertyCellValue() {
6061 return HObjectAccess(kInobject, PropertyCell::kValueOffset);
6064 static HObjectAccess ForCellValue() {
6065 return HObjectAccess(kInobject, Cell::kValueOffset);
6068 static HObjectAccess ForAllocationMementoSite() {
6069 return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
6072 static HObjectAccess ForCounter() {
6073 return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
6074 Handle<String>::null(), false, false);
6077 // Create an access to an offset in a fixed array header.
6078 static HObjectAccess ForFixedArrayHeader(int offset);
6080 // Create an access to an in-object property in a JSObject.
6081 // This kind of access must be used when the object |map| is known and
6082 // in-object properties are being accessed. Accesses of the in-object
6083 // properties can have different semantics depending on whether corresponding
6084 // property was added to the map or not.
6085 static HObjectAccess ForMapAndOffset(Handle<Map> map, int offset,
6086 Representation representation = Representation::Tagged());
6088 // Create an access to an in-object property in a JSObject.
6089 // This kind of access can be used for accessing object header fields or
6090 // in-object properties if the map of the object is not known.
6091 static HObjectAccess ForObservableJSObjectOffset(int offset,
6092 Representation representation = Representation::Tagged()) {
6093 return ForMapAndOffset(Handle<Map>::null(), offset, representation);
6096 // Create an access to an in-object property in a JSArray.
6097 static HObjectAccess ForJSArrayOffset(int offset);
6099 static HObjectAccess ForContextSlot(int index);
6101 // Create an access to the backing store of an object.
6102 static HObjectAccess ForBackingStoreOffset(int offset,
6103 Representation representation = Representation::Tagged());
6105 // Create an access to a resolved field (in-object or backing store).
6106 static HObjectAccess ForField(Handle<Map> map,
6107 LookupResult *lookup, Handle<String> name = Handle<String>::null());
6109 // Create an access for the payload of a Cell or JSGlobalPropertyCell.
6110 static HObjectAccess ForCellPayload(Isolate* isolate);
6112 static HObjectAccess ForJSTypedArrayLength() {
6113 return HObjectAccess::ForObservableJSObjectOffset(
6114 JSTypedArray::kLengthOffset);
6117 static HObjectAccess ForJSArrayBufferBackingStore() {
6118 return HObjectAccess::ForObservableJSObjectOffset(
6119 JSArrayBuffer::kBackingStoreOffset, Representation::External());
6122 static HObjectAccess ForJSArrayBufferByteLength() {
6123 return HObjectAccess::ForObservableJSObjectOffset(
6124 JSArrayBuffer::kByteLengthOffset, Representation::Tagged());
6127 static HObjectAccess ForExternalArrayExternalPointer() {
6128 return HObjectAccess::ForObservableJSObjectOffset(
6129 ExternalArray::kExternalPointerOffset, Representation::External());
6132 static HObjectAccess ForJSArrayBufferViewWeakNext() {
6133 return HObjectAccess::ForObservableJSObjectOffset(
6134 JSArrayBufferView::kWeakNextOffset);
6137 static HObjectAccess ForJSArrayBufferWeakFirstView() {
6138 return HObjectAccess::ForObservableJSObjectOffset(
6139 JSArrayBuffer::kWeakFirstViewOffset);
6142 static HObjectAccess ForJSArrayBufferViewBuffer() {
6143 return HObjectAccess::ForObservableJSObjectOffset(
6144 JSArrayBufferView::kBufferOffset);
6147 static HObjectAccess ForJSArrayBufferViewByteOffset() {
6148 return HObjectAccess::ForObservableJSObjectOffset(
6149 JSArrayBufferView::kByteOffsetOffset);
6152 static HObjectAccess ForJSArrayBufferViewByteLength() {
6153 return HObjectAccess::ForObservableJSObjectOffset(
6154 JSArrayBufferView::kByteLengthOffset);
6157 static HObjectAccess ForGlobalObjectNativeContext() {
6158 return HObjectAccess(kInobject, GlobalObject::kNativeContextOffset);
6161 void PrintTo(StringStream* stream) const;
6163 inline bool Equals(HObjectAccess that) const {
6164 return value_ == that.value_; // portion and offset must match
6168 void SetGVNFlags(HValue *instr, PropertyAccessType access_type);
6171 // internal use only; different parts of an object or array
6173 kMaps, // map of an object
6174 kArrayLengths, // the length of an array
6175 kStringLengths, // the length of a string
6176 kElementsPointer, // elements pointer
6177 kBackingStore, // some field in the backing store
6178 kDouble, // some double field
6179 kInobject, // some other in-object field
6180 kExternalMemory // some field in external memory
6183 HObjectAccess() : value_(0) {}
6185 HObjectAccess(Portion portion, int offset,
6186 Representation representation = Representation::Tagged(),
6187 Handle<String> name = Handle<String>::null(),
6188 bool immutable = false,
6189 bool existing_inobject_property = true)
6190 : value_(PortionField::encode(portion) |
6191 RepresentationField::encode(representation.kind()) |
6192 ImmutableField::encode(immutable ? 1 : 0) |
6193 ExistingInobjectPropertyField::encode(
6194 existing_inobject_property ? 1 : 0) |
6195 OffsetField::encode(offset)),
6197 // assert that the fields decode correctly
6198 ASSERT(this->offset() == offset);
6199 ASSERT(this->portion() == portion);
6200 ASSERT(this->immutable() == immutable);
6201 ASSERT(this->existing_inobject_property() == existing_inobject_property);
6202 ASSERT(RepresentationField::decode(value_) == representation.kind());
6203 ASSERT(!this->existing_inobject_property() || IsInobject());
6206 class PortionField : public BitField<Portion, 0, 3> {};
6207 class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
6208 class ImmutableField : public BitField<bool, 7, 1> {};
6209 class ExistingInobjectPropertyField : public BitField<bool, 8, 1> {};
6210 class OffsetField : public BitField<int, 9, 23> {};
6212 uint32_t value_; // encodes portion, representation, immutable, and offset
6213 Handle<String> name_;
6215 friend class HLoadNamedField;
6216 friend class HStoreNamedField;
6217 friend class SideEffectsTracker;
6219 inline Portion portion() const {
6220 return PortionField::decode(value_);
6225 class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> {
6227 static HLoadNamedField* New(Zone* zone, HValue* context,
6228 HValue* object, HValue* dependency,
6229 HObjectAccess access) {
6230 return new(zone) HLoadNamedField(
6231 object, dependency, access, new(zone) UniqueSet<Map>());
6233 static HLoadNamedField* New(Zone* zone, HValue* context,
6234 HValue* object, HValue* dependency,
6235 HObjectAccess access, SmallMapList* map_list,
6236 CompilationInfo* info) {
6237 UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone);
6238 for (int i = 0; i < map_list->length(); ++i) {
6239 Handle<Map> map = map_list->at(i);
6240 maps->Add(Unique<Map>::CreateImmovable(map), zone);
6241 // TODO(bmeurer): Get rid of this shit!
6242 if (map->CanTransition()) {
6243 Map::AddDependentCompilationInfo(
6244 map, DependentCode::kPrototypeCheckGroup, info);
6247 return new(zone) HLoadNamedField(object, dependency, access, maps);
6250 HValue* object() { return OperandAt(0); }
6251 HValue* dependency() {
6252 ASSERT(HasDependency());
6253 return OperandAt(1);
6255 bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
6256 HObjectAccess access() const { return access_; }
6257 Representation field_representation() const {
6258 return access_.representation();
6261 const UniqueSet<Map>* maps() const { return maps_; }
6263 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
6264 virtual bool HasOutOfBoundsAccess(int size) V8_OVERRIDE {
6265 return !access().IsInobject() || access().offset() >= size;
6267 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6268 if (index == 0 && access().IsExternalMemory()) {
6269 // object must be external in case of external memory access
6270 return Representation::External();
6272 return Representation::Tagged();
6274 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
6275 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6277 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
6280 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
6281 HLoadNamedField* b = HLoadNamedField::cast(other);
6282 return access_.Equals(b->access_) && this->maps()->Equals(b->maps());
6286 HLoadNamedField(HValue* object,
6288 HObjectAccess access,
6289 const UniqueSet<Map>* maps)
6290 : access_(access), maps_(maps) {
6291 ASSERT(object != NULL);
6292 SetOperandAt(0, object);
6293 SetOperandAt(1, dependency != NULL ? dependency : object);
6295 Representation representation = access.representation();
6296 if (representation.IsInteger8() ||
6297 representation.IsUInteger8() ||
6298 representation.IsInteger16() ||
6299 representation.IsUInteger16()) {
6300 set_representation(Representation::Integer32());
6301 } else if (representation.IsSmi()) {
6302 set_type(HType::Smi());
6303 if (SmiValuesAre32Bits()) {
6304 set_representation(Representation::Integer32());
6306 set_representation(representation);
6308 } else if (representation.IsDouble() ||
6309 representation.IsExternal() ||
6310 representation.IsInteger32()) {
6311 set_representation(representation);
6312 } else if (representation.IsHeapObject()) {
6313 set_type(HType::NonPrimitive());
6314 set_representation(Representation::Tagged());
6316 set_representation(Representation::Tagged());
6318 access.SetGVNFlags(this, LOAD);
6321 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
6323 HObjectAccess access_;
6324 const UniqueSet<Map>* maps_;
6328 class HLoadNamedGeneric V8_FINAL : public HTemplateInstruction<2> {
6330 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadNamedGeneric, HValue*,
6333 HValue* context() { return OperandAt(0); }
6334 HValue* object() { return OperandAt(1); }
6335 Handle<Object> name() const { return name_; }
6337 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6338 return Representation::Tagged();
6341 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6343 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
6346 HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
6348 SetOperandAt(0, context);
6349 SetOperandAt(1, object);
6350 set_representation(Representation::Tagged());
6351 SetAllSideEffects();
6354 Handle<Object> name_;
6358 class HLoadFunctionPrototype V8_FINAL : public HUnaryOperation {
6360 DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);
6362 HValue* function() { return OperandAt(0); }
6364 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6365 return Representation::Tagged();
6368 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
6371 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
6374 explicit HLoadFunctionPrototype(HValue* function)
6375 : HUnaryOperation(function) {
6376 set_representation(Representation::Tagged());
6378 SetDependsOnFlag(kCalls);
6382 class ArrayInstructionInterface {
6384 virtual HValue* GetKey() = 0;
6385 virtual void SetKey(HValue* key) = 0;
6386 virtual void SetIndexOffset(uint32_t index_offset) = 0;
6387 virtual int MaxIndexOffsetBits() = 0;
6388 virtual bool IsDehoisted() = 0;
6389 virtual void SetDehoisted(bool is_dehoisted) = 0;
6390 virtual ~ArrayInstructionInterface() { };
6392 static Representation KeyedAccessIndexRequirement(Representation r) {
6393 return r.IsInteger32() || SmiValuesAre32Bits()
6394 ? Representation::Integer32() : Representation::Smi();
6399 enum LoadKeyedHoleMode {
6405 class HLoadKeyed V8_FINAL
6406 : public HTemplateInstruction<3>, public ArrayInstructionInterface {
6408 DECLARE_INSTRUCTION_FACTORY_P4(HLoadKeyed, HValue*, HValue*, HValue*,
6410 DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*,
6411 ElementsKind, LoadKeyedHoleMode);
6413 bool is_external() const {
6414 return IsExternalArrayElementsKind(elements_kind());
6416 bool is_fixed_typed_array() const {
6417 return IsFixedTypedArrayElementsKind(elements_kind());
6419 bool is_typed_elements() const {
6420 return is_external() || is_fixed_typed_array();
6422 HValue* elements() { return OperandAt(0); }
6423 HValue* key() { return OperandAt(1); }
6424 HValue* dependency() {
6425 ASSERT(HasDependency());
6426 return OperandAt(2);
6428 bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
6429 uint32_t index_offset() { return IndexOffsetField::decode(bit_field_); }
6430 void SetIndexOffset(uint32_t index_offset) {
6431 bit_field_ = IndexOffsetField::update(bit_field_, index_offset);
6433 virtual int MaxIndexOffsetBits() {
6434 return kBitsForIndexOffset;
6436 HValue* GetKey() { return key(); }
6437 void SetKey(HValue* key) { SetOperandAt(1, key); }
6438 bool IsDehoisted() { return IsDehoistedField::decode(bit_field_); }
6439 void SetDehoisted(bool is_dehoisted) {
6440 bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
6442 ElementsKind elements_kind() const {
6443 return ElementsKindField::decode(bit_field_);
6445 LoadKeyedHoleMode hole_mode() const {
6446 return HoleModeField::decode(bit_field_);
6449 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6450 // kind_fast: tagged[int32] (none)
6451 // kind_double: tagged[int32] (none)
6452 // kind_fixed_typed_array: tagged[int32] (none)
6453 // kind_external: external[int32] (none)
6455 return is_external() ? Representation::External()
6456 : Representation::Tagged();
6459 return ArrayInstructionInterface::KeyedAccessIndexRequirement(
6460 OperandAt(1)->representation());
6462 return Representation::None();
6465 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
6466 return RequiredInputRepresentation(index);
6469 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6471 bool UsesMustHandleHole() const;
6472 bool AllUsesCanTreatHoleAsNaN() const;
6473 bool RequiresHoleCheck() const;
6475 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
6477 DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)
6480 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
6481 if (!other->IsLoadKeyed()) return false;
6482 HLoadKeyed* other_load = HLoadKeyed::cast(other);
6484 if (IsDehoisted() && index_offset() != other_load->index_offset())
6486 return elements_kind() == other_load->elements_kind();
6490 HLoadKeyed(HValue* obj,
6493 ElementsKind elements_kind,
6494 LoadKeyedHoleMode mode = NEVER_RETURN_HOLE)
6496 bit_field_ = ElementsKindField::encode(elements_kind) |
6497 HoleModeField::encode(mode);
6499 SetOperandAt(0, obj);
6500 SetOperandAt(1, key);
6501 SetOperandAt(2, dependency != NULL ? dependency : obj);
6503 if (!is_typed_elements()) {
6504 // I can detect the case between storing double (holey and fast) and
6505 // smi/object by looking at elements_kind_.
6506 ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
6507 IsFastDoubleElementsKind(elements_kind));
6509 if (IsFastSmiOrObjectElementsKind(elements_kind)) {
6510 if (IsFastSmiElementsKind(elements_kind) &&
6511 (!IsHoleyElementsKind(elements_kind) ||
6512 mode == NEVER_RETURN_HOLE)) {
6513 set_type(HType::Smi());
6514 if (SmiValuesAre32Bits() && !RequiresHoleCheck()) {
6515 set_representation(Representation::Integer32());
6517 set_representation(Representation::Smi());
6520 set_representation(Representation::Tagged());
6523 SetDependsOnFlag(kArrayElements);
6525 set_representation(Representation::Double());
6526 SetDependsOnFlag(kDoubleArrayElements);
6529 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
6530 elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
6531 elements_kind == FLOAT32_ELEMENTS ||
6532 elements_kind == FLOAT64_ELEMENTS) {
6533 set_representation(Representation::Double());
6534 } else if (IsFloat32x4ElementsKind(elements_kind)) {
6535 set_representation(CpuFeatures::SupportsSIMD128InCrankshaft() ?
6536 Representation::Float32x4() : Representation::Tagged());
6537 } else if (IsFloat64x2ElementsKind(elements_kind)) {
6538 set_representation(CpuFeatures::SupportsSIMD128InCrankshaft() ?
6539 Representation::Float64x2() : Representation::Tagged());
6540 } else if (IsInt32x4ElementsKind(elements_kind)) {
6541 set_representation(CpuFeatures::SupportsSIMD128InCrankshaft() ?
6542 Representation::Int32x4() : Representation::Tagged());
6544 set_representation(Representation::Integer32());
6547 if (is_external()) {
6548 SetDependsOnFlag(kExternalMemory);
6549 } else if (is_fixed_typed_array()) {
6550 SetDependsOnFlag(kTypedArrayElements);
6554 // Native code could change the specialized array.
6555 SetDependsOnFlag(kCalls);
6561 virtual bool IsDeletable() const V8_OVERRIDE {
6562 return !RequiresHoleCheck();
6565 // Establish some checks around our packed fields
6566 enum LoadKeyedBits {
6567 kBitsForElementsKind = 5,
6568 kBitsForHoleMode = 1,
6569 kBitsForIndexOffset = 25,
6570 kBitsForIsDehoisted = 1,
6572 kStartElementsKind = 0,
6573 kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
6574 kStartIndexOffset = kStartHoleMode + kBitsForHoleMode,
6575 kStartIsDehoisted = kStartIndexOffset + kBitsForIndexOffset
6578 STATIC_ASSERT((kBitsForElementsKind + kBitsForIndexOffset +
6579 kBitsForIsDehoisted) <= sizeof(uint32_t)*8);
6580 STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
6581 class ElementsKindField:
6582 public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
6584 class HoleModeField:
6585 public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
6587 class IndexOffsetField:
6588 public BitField<uint32_t, kStartIndexOffset, kBitsForIndexOffset>
6590 class IsDehoistedField:
6591 public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
6593 uint32_t bit_field_;
6597 class HLoadKeyedGeneric V8_FINAL : public HTemplateInstruction<3> {
6599 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadKeyedGeneric, HValue*,
6601 HValue* object() { return OperandAt(0); }
6602 HValue* key() { return OperandAt(1); }
6603 HValue* context() { return OperandAt(2); }
6605 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6607 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6609 return Representation::Tagged();
6612 virtual HValue* Canonicalize() V8_OVERRIDE;
6614 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
6617 HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key) {
6618 set_representation(Representation::Tagged());
6619 SetOperandAt(0, obj);
6620 SetOperandAt(1, key);
6621 SetOperandAt(2, context);
6622 SetAllSideEffects();
6627 // Indicates whether the store is a store to an entry that was previously
6628 // initialized or not.
6629 enum StoreFieldOrKeyedMode {
6630 // The entry could be either previously initialized or not.
6632 // At the time of this store it is guaranteed that the entry is already
6634 STORE_TO_INITIALIZED_ENTRY
6638 class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> {
6640 DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
6641 HObjectAccess, HValue*);
6642 DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue*,
6643 HObjectAccess, HValue*, StoreFieldOrKeyedMode);
6645 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
6647 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE {
6650 virtual bool HasOutOfBoundsAccess(int size) V8_OVERRIDE {
6651 return !access().IsInobject() || access().offset() >= size;
6653 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6654 if (index == 0 && access().IsExternalMemory()) {
6655 // object must be external in case of external memory access
6656 return Representation::External();
6657 } else if (index == 1) {
6658 if (field_representation().IsInteger8() ||
6659 field_representation().IsUInteger8() ||
6660 field_representation().IsInteger16() ||
6661 field_representation().IsUInteger16() ||
6662 field_representation().IsInteger32()) {
6663 return Representation::Integer32();
6664 } else if (field_representation().IsDouble()) {
6665 return field_representation();
6666 } else if (field_representation().IsSmi()) {
6667 if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
6668 return Representation::Integer32();
6670 return field_representation();
6671 } else if (field_representation().IsExternal()) {
6672 return Representation::External();
6675 return Representation::Tagged();
6677 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
6678 HValue* dominator) V8_OVERRIDE {
6679 ASSERT(side_effect == kNewSpacePromotion);
6680 if (!FLAG_use_write_barrier_elimination) return false;
6681 new_space_dominator_ = dominator;
6684 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6686 void SkipWriteBarrier() { write_barrier_mode_ = SKIP_WRITE_BARRIER; }
6687 bool IsSkipWriteBarrier() const {
6688 return write_barrier_mode_ == SKIP_WRITE_BARRIER;
6691 HValue* object() const { return OperandAt(0); }
6692 HValue* value() const { return OperandAt(1); }
6693 HValue* transition() const { return OperandAt(2); }
6695 HObjectAccess access() const { return access_; }
6696 HValue* new_space_dominator() const { return new_space_dominator_; }
6697 bool has_transition() const { return has_transition_; }
6698 StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
6700 Handle<Map> transition_map() const {
6701 if (has_transition()) {
6702 return Handle<Map>::cast(
6703 HConstant::cast(transition())->handle(Isolate::Current()));
6705 return Handle<Map>();
6709 void SetTransition(HConstant* transition) {
6710 ASSERT(!has_transition()); // Only set once.
6711 SetOperandAt(2, transition);
6712 has_transition_ = true;
6715 bool NeedsWriteBarrier() {
6716 ASSERT(!field_representation().IsDouble() || !has_transition());
6717 if (IsSkipWriteBarrier()) return false;
6718 if (field_representation().IsDouble()) return false;
6719 if (field_representation().IsSmi()) return false;
6720 if (field_representation().IsInteger32()) return false;
6721 if (field_representation().IsExternal()) return false;
6722 return StoringValueNeedsWriteBarrier(value()) &&
6723 ReceiverObjectNeedsWriteBarrier(object(), value(),
6724 new_space_dominator());
6727 bool NeedsWriteBarrierForMap() {
6728 if (IsSkipWriteBarrier()) return false;
6729 return ReceiverObjectNeedsWriteBarrier(object(), transition(),
6730 new_space_dominator());
6733 Representation field_representation() const {
6734 return access_.representation();
6737 void UpdateValue(HValue* value) {
6738 SetOperandAt(1, value);
6742 HStoreNamedField(HValue* obj,
6743 HObjectAccess access,
6745 StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
6747 new_space_dominator_(NULL),
6748 write_barrier_mode_(UPDATE_WRITE_BARRIER),
6749 has_transition_(false),
6750 store_mode_(store_mode) {
6751 // Stores to a non existing in-object property are allowed only to the
6752 // newly allocated objects (via HAllocate or HInnerAllocatedObject).
6753 ASSERT(!access.IsInobject() || access.existing_inobject_property() ||
6754 obj->IsAllocate() || obj->IsInnerAllocatedObject());
6755 SetOperandAt(0, obj);
6756 SetOperandAt(1, val);
6757 SetOperandAt(2, obj);
6758 access.SetGVNFlags(this, STORE);
6761 HObjectAccess access_;
6762 HValue* new_space_dominator_;
6763 WriteBarrierMode write_barrier_mode_ : 1;
6764 bool has_transition_ : 1;
6765 StoreFieldOrKeyedMode store_mode_ : 1;
6769 class HStoreNamedGeneric V8_FINAL : public HTemplateInstruction<3> {
6771 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreNamedGeneric, HValue*,
6772 Handle<String>, HValue*,
6774 HValue* object() { return OperandAt(0); }
6775 HValue* value() { return OperandAt(1); }
6776 HValue* context() { return OperandAt(2); }
6777 Handle<String> name() { return name_; }
6778 StrictMode strict_mode() { return strict_mode_; }
6780 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6782 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6783 return Representation::Tagged();
6786 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
6789 HStoreNamedGeneric(HValue* context,
6791 Handle<String> name,
6793 StrictMode strict_mode)
6795 strict_mode_(strict_mode) {
6796 SetOperandAt(0, object);
6797 SetOperandAt(1, value);
6798 SetOperandAt(2, context);
6799 SetAllSideEffects();
6802 Handle<String> name_;
6803 StrictMode strict_mode_;
6807 class HStoreKeyed V8_FINAL
6808 : public HTemplateInstruction<3>, public ArrayInstructionInterface {
6810 DECLARE_INSTRUCTION_FACTORY_P4(HStoreKeyed, HValue*, HValue*, HValue*,
6812 DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*,
6813 ElementsKind, StoreFieldOrKeyedMode);
6815 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6816 // kind_fast: tagged[int32] = tagged
6817 // kind_double: tagged[int32] = double
6818 // kind_smi : tagged[int32] = smi
6819 // kind_fixed_typed_array: tagged[int32] = (double | int32)
6820 // kind_external: external[int32] = (double | int32)
6822 return is_external() ? Representation::External()
6823 : Representation::Tagged();
6824 } else if (index == 1) {
6825 return ArrayInstructionInterface::KeyedAccessIndexRequirement(
6826 OperandAt(1)->representation());
6829 ASSERT_EQ(index, 2);
6831 if (IsDoubleOrFloatElementsKind(elements_kind())) {
6832 return Representation::Double();
6834 if (IsFloat32x4ElementsKind(elements_kind())) {
6835 return CpuFeatures::SupportsSIMD128InCrankshaft() ?
6836 Representation::Float32x4() : Representation::Tagged();
6838 if (IsFloat64x2ElementsKind(elements_kind())) {
6839 return CpuFeatures::SupportsSIMD128InCrankshaft() ?
6840 Representation::Float64x2() : Representation::Tagged();
6842 if (IsInt32x4ElementsKind(elements_kind())) {
6843 return CpuFeatures::SupportsSIMD128InCrankshaft() ?
6844 Representation::Int32x4() : Representation::Tagged();
6846 if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
6847 return Representation::Integer32();
6849 if (IsFastSmiElementsKind(elements_kind())) {
6850 return Representation::Smi();
6853 return is_external() || is_fixed_typed_array()
6854 ? Representation::Integer32()
6855 : Representation::Tagged();
6858 bool is_external() const {
6859 return IsExternalArrayElementsKind(elements_kind());
6862 bool is_fixed_typed_array() const {
6863 return IsFixedTypedArrayElementsKind(elements_kind());
6866 bool is_typed_elements() const {
6867 return is_external() || is_fixed_typed_array();
6870 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
6871 if (index < 2) return RequiredInputRepresentation(index);
6872 if (IsUninitialized()) {
6873 return Representation::None();
6875 if (IsDoubleOrFloatElementsKind(elements_kind())) {
6876 return Representation::Double();
6878 if (IsFloat32x4ElementsKind(elements_kind())) {
6879 return CpuFeatures::SupportsSIMD128InCrankshaft() ?
6880 Representation::Float32x4() : Representation::Tagged();
6882 if (IsFloat64x2ElementsKind(elements_kind())) {
6883 return CpuFeatures::SupportsSIMD128InCrankshaft() ?
6884 Representation::Float64x2() : Representation::Tagged();
6886 if (IsInt32x4ElementsKind(elements_kind())) {
6887 return CpuFeatures::SupportsSIMD128InCrankshaft() ?
6888 Representation::Int32x4() : Representation::Tagged();
6890 if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
6891 return Representation::Integer32();
6893 if (IsFastSmiElementsKind(elements_kind())) {
6894 return Representation::Smi();
6896 if (is_typed_elements()) {
6897 return Representation::Integer32();
6899 // For fast object elements kinds, don't assume anything.
6900 return Representation::None();
6903 HValue* elements() { return OperandAt(0); }
6904 HValue* key() { return OperandAt(1); }
6905 HValue* value() { return OperandAt(2); }
6906 bool value_is_smi() const {
6907 return IsFastSmiElementsKind(elements_kind_);
6909 StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
6910 ElementsKind elements_kind() const { return elements_kind_; }
6911 uint32_t index_offset() { return index_offset_; }
6912 void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
6913 virtual int MaxIndexOffsetBits() {
6914 return 31 - ElementsKindToShiftSize(elements_kind_);
6916 HValue* GetKey() { return key(); }
6917 void SetKey(HValue* key) { SetOperandAt(1, key); }
6918 bool IsDehoisted() { return is_dehoisted_; }
6919 void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
6920 bool IsUninitialized() { return is_uninitialized_; }
6921 void SetUninitialized(bool is_uninitialized) {
6922 is_uninitialized_ = is_uninitialized;
6925 bool IsConstantHoleStore() {
6926 return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
6929 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
6930 HValue* dominator) V8_OVERRIDE {
6931 ASSERT(side_effect == kNewSpacePromotion);
6932 new_space_dominator_ = dominator;
6936 HValue* new_space_dominator() const { return new_space_dominator_; }
6938 bool NeedsWriteBarrier() {
6939 if (value_is_smi()) {
6942 return StoringValueNeedsWriteBarrier(value()) &&
6943 ReceiverObjectNeedsWriteBarrier(elements(), value(),
6944 new_space_dominator());
6948 bool NeedsCanonicalization();
6950 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6952 DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
6955 HStoreKeyed(HValue* obj, HValue* key, HValue* val,
6956 ElementsKind elements_kind,
6957 StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
6958 : elements_kind_(elements_kind),
6960 is_dehoisted_(false),
6961 is_uninitialized_(false),
6962 store_mode_(store_mode),
6963 new_space_dominator_(NULL) {
6964 SetOperandAt(0, obj);
6965 SetOperandAt(1, key);
6966 SetOperandAt(2, val);
6968 ASSERT(store_mode != STORE_TO_INITIALIZED_ENTRY ||
6969 elements_kind == FAST_SMI_ELEMENTS);
6971 if (IsFastObjectElementsKind(elements_kind)) {
6972 SetFlag(kTrackSideEffectDominators);
6973 SetDependsOnFlag(kNewSpacePromotion);
6975 if (is_external()) {
6976 SetChangesFlag(kExternalMemory);
6977 SetFlag(kAllowUndefinedAsNaN);
6978 } else if (IsFastDoubleElementsKind(elements_kind)) {
6979 SetChangesFlag(kDoubleArrayElements);
6980 } else if (IsFastSmiElementsKind(elements_kind)) {
6981 SetChangesFlag(kArrayElements);
6982 } else if (is_fixed_typed_array()) {
6983 SetChangesFlag(kTypedArrayElements);
6984 SetFlag(kAllowUndefinedAsNaN);
6986 SetChangesFlag(kArrayElements);
6989 // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
6990 if ((elements_kind >= EXTERNAL_INT8_ELEMENTS &&
6991 elements_kind <= EXTERNAL_UINT32_ELEMENTS) ||
6992 (elements_kind >= UINT8_ELEMENTS &&
6993 elements_kind <= INT32_ELEMENTS)) {
6994 SetFlag(kTruncatingToInt32);
6998 ElementsKind elements_kind_;
6999 uint32_t index_offset_;
7000 bool is_dehoisted_ : 1;
7001 bool is_uninitialized_ : 1;
7002 StoreFieldOrKeyedMode store_mode_: 1;
7003 HValue* new_space_dominator_;
7007 class HStoreKeyedGeneric V8_FINAL : public HTemplateInstruction<4> {
7009 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreKeyedGeneric, HValue*,
7010 HValue*, HValue*, StrictMode);
7012 HValue* object() { return OperandAt(0); }
7013 HValue* key() { return OperandAt(1); }
7014 HValue* value() { return OperandAt(2); }
7015 HValue* context() { return OperandAt(3); }
7016 StrictMode strict_mode() { return strict_mode_; }
7018 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7019 // tagged[tagged] = tagged
7020 return Representation::Tagged();
7023 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7025 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
7028 HStoreKeyedGeneric(HValue* context,
7032 StrictMode strict_mode)
7033 : strict_mode_(strict_mode) {
7034 SetOperandAt(0, object);
7035 SetOperandAt(1, key);
7036 SetOperandAt(2, value);
7037 SetOperandAt(3, context);
7038 SetAllSideEffects();
7041 StrictMode strict_mode_;
7045 class HTransitionElementsKind V8_FINAL : public HTemplateInstruction<2> {
7047 inline static HTransitionElementsKind* New(Zone* zone,
7050 Handle<Map> original_map,
7051 Handle<Map> transitioned_map) {
7052 return new(zone) HTransitionElementsKind(context, object,
7053 original_map, transitioned_map);
7056 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7057 return Representation::Tagged();
7060 HValue* object() { return OperandAt(0); }
7061 HValue* context() { return OperandAt(1); }
7062 Unique<Map> original_map() { return original_map_; }
7063 Unique<Map> transitioned_map() { return transitioned_map_; }
7064 ElementsKind from_kind() { return from_kind_; }
7065 ElementsKind to_kind() { return to_kind_; }
7067 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7069 DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
7072 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7073 HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
7074 return original_map_ == instr->original_map_ &&
7075 transitioned_map_ == instr->transitioned_map_;
7078 virtual int RedefinedOperandIndex() { return 0; }
7081 HTransitionElementsKind(HValue* context,
7083 Handle<Map> original_map,
7084 Handle<Map> transitioned_map)
7085 : original_map_(Unique<Map>(original_map)),
7086 transitioned_map_(Unique<Map>(transitioned_map)),
7087 from_kind_(original_map->elements_kind()),
7088 to_kind_(transitioned_map->elements_kind()) {
7089 SetOperandAt(0, object);
7090 SetOperandAt(1, context);
7092 SetChangesFlag(kElementsKind);
7093 if (!IsSimpleMapChangeTransition(from_kind_, to_kind_)) {
7094 SetChangesFlag(kElementsPointer);
7095 SetChangesFlag(kNewSpacePromotion);
7097 set_representation(Representation::Tagged());
7100 Unique<Map> original_map_;
7101 Unique<Map> transitioned_map_;
7102 ElementsKind from_kind_;
7103 ElementsKind to_kind_;
7107 class HStringAdd V8_FINAL : public HBinaryOperation {
7109 static HInstruction* New(Zone* zone,
7113 PretenureFlag pretenure_flag = NOT_TENURED,
7114 StringAddFlags flags = STRING_ADD_CHECK_BOTH,
7115 Handle<AllocationSite> allocation_site =
7116 Handle<AllocationSite>::null());
7118 StringAddFlags flags() const { return flags_; }
7119 PretenureFlag pretenure_flag() const { return pretenure_flag_; }
7121 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7122 return Representation::Tagged();
7125 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7127 DECLARE_CONCRETE_INSTRUCTION(StringAdd)
7130 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7131 return flags_ == HStringAdd::cast(other)->flags_ &&
7132 pretenure_flag_ == HStringAdd::cast(other)->pretenure_flag_;
7136 HStringAdd(HValue* context,
7139 PretenureFlag pretenure_flag,
7140 StringAddFlags flags,
7141 Handle<AllocationSite> allocation_site)
7142 : HBinaryOperation(context, left, right, HType::String()),
7143 flags_(flags), pretenure_flag_(pretenure_flag) {
7144 set_representation(Representation::Tagged());
7146 SetDependsOnFlag(kMaps);
7147 SetChangesFlag(kNewSpacePromotion);
7148 if (FLAG_trace_pretenuring) {
7149 PrintF("HStringAdd with AllocationSite %p %s\n",
7150 allocation_site.is_null()
7151 ? static_cast<void*>(NULL)
7152 : static_cast<void*>(*allocation_site),
7153 pretenure_flag == TENURED ? "tenured" : "not tenured");
7157 // No side-effects except possible allocation:
7158 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7160 const StringAddFlags flags_;
7161 const PretenureFlag pretenure_flag_;
7165 class HStringCharCodeAt V8_FINAL : public HTemplateInstruction<3> {
7167 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HStringCharCodeAt,
7171 virtual Representation RequiredInputRepresentation(int index) {
7172 // The index is supposed to be Integer32.
7174 ? Representation::Integer32()
7175 : Representation::Tagged();
7178 HValue* context() const { return OperandAt(0); }
7179 HValue* string() const { return OperandAt(1); }
7180 HValue* index() const { return OperandAt(2); }
7182 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
7185 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
7187 virtual Range* InferRange(Zone* zone) V8_OVERRIDE {
7188 return new(zone) Range(0, String::kMaxUtf16CodeUnit);
7192 HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
7193 SetOperandAt(0, context);
7194 SetOperandAt(1, string);
7195 SetOperandAt(2, index);
7196 set_representation(Representation::Integer32());
7198 SetDependsOnFlag(kMaps);
7199 SetDependsOnFlag(kStringChars);
7200 SetChangesFlag(kNewSpacePromotion);
7203 // No side effects: runtime function assumes string + number inputs.
7204 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7208 class HStringCharFromCode V8_FINAL : public HTemplateInstruction<2> {
7210 static HInstruction* New(Zone* zone,
7214 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7216 ? Representation::Tagged()
7217 : Representation::Integer32();
7220 HValue* context() const { return OperandAt(0); }
7221 HValue* value() const { return OperandAt(1); }
7223 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
7225 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
7228 HStringCharFromCode(HValue* context, HValue* char_code)
7229 : HTemplateInstruction<2>(HType::String()) {
7230 SetOperandAt(0, context);
7231 SetOperandAt(1, char_code);
7232 set_representation(Representation::Tagged());
7234 SetChangesFlag(kNewSpacePromotion);
7237 virtual bool IsDeletable() const V8_OVERRIDE {
7238 return !value()->ToNumberCanBeObserved();
7244 class HMaterializedLiteral : public HTemplateInstruction<V> {
7246 HMaterializedLiteral<V>(int index, int depth, AllocationSiteMode mode)
7247 : literal_index_(index), depth_(depth), allocation_site_mode_(mode) {
7248 this->set_representation(Representation::Tagged());
7251 HMaterializedLiteral<V>(int index, int depth)
7252 : literal_index_(index), depth_(depth),
7253 allocation_site_mode_(DONT_TRACK_ALLOCATION_SITE) {
7254 this->set_representation(Representation::Tagged());
7257 int literal_index() const { return literal_index_; }
7258 int depth() const { return depth_; }
7259 AllocationSiteMode allocation_site_mode() const {
7260 return allocation_site_mode_;
7264 virtual bool IsDeletable() const V8_FINAL V8_OVERRIDE { return true; }
7268 AllocationSiteMode allocation_site_mode_;
7272 class HRegExpLiteral V8_FINAL : public HMaterializedLiteral<1> {
7274 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HRegExpLiteral,
7280 HValue* context() { return OperandAt(0); }
7281 Handle<FixedArray> literals() { return literals_; }
7282 Handle<String> pattern() { return pattern_; }
7283 Handle<String> flags() { return flags_; }
7285 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7286 return Representation::Tagged();
7289 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
7292 HRegExpLiteral(HValue* context,
7293 Handle<FixedArray> literals,
7294 Handle<String> pattern,
7295 Handle<String> flags,
7297 : HMaterializedLiteral<1>(literal_index, 0),
7298 literals_(literals),
7301 SetOperandAt(0, context);
7302 SetAllSideEffects();
7303 set_type(HType::JSObject());
7306 Handle<FixedArray> literals_;
7307 Handle<String> pattern_;
7308 Handle<String> flags_;
7312 class HFunctionLiteral V8_FINAL : public HTemplateInstruction<1> {
7314 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HFunctionLiteral,
7315 Handle<SharedFunctionInfo>,
7317 HValue* context() { return OperandAt(0); }
7319 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7320 return Representation::Tagged();
7323 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral)
7325 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
7326 bool pretenure() const { return pretenure_; }
7327 bool has_no_literals() const { return has_no_literals_; }
7328 bool is_generator() const { return is_generator_; }
7329 StrictMode strict_mode() const { return strict_mode_; }
7332 HFunctionLiteral(HValue* context,
7333 Handle<SharedFunctionInfo> shared,
7335 : HTemplateInstruction<1>(HType::JSObject()),
7336 shared_info_(shared),
7337 pretenure_(pretenure),
7338 has_no_literals_(shared->num_literals() == 0),
7339 is_generator_(shared->is_generator()),
7340 strict_mode_(shared->strict_mode()) {
7341 SetOperandAt(0, context);
7342 set_representation(Representation::Tagged());
7343 SetChangesFlag(kNewSpacePromotion);
7346 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7348 Handle<SharedFunctionInfo> shared_info_;
7349 bool pretenure_ : 1;
7350 bool has_no_literals_ : 1;
7351 bool is_generator_ : 1;
7352 StrictMode strict_mode_;
7356 class HTypeof V8_FINAL : public HTemplateInstruction<2> {
7358 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HTypeof, HValue*);
7360 HValue* context() { return OperandAt(0); }
7361 HValue* value() { return OperandAt(1); }
7363 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7365 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7366 return Representation::Tagged();
7369 DECLARE_CONCRETE_INSTRUCTION(Typeof)
7372 explicit HTypeof(HValue* context, HValue* value) {
7373 SetOperandAt(0, context);
7374 SetOperandAt(1, value);
7375 set_representation(Representation::Tagged());
7378 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7382 class HTrapAllocationMemento V8_FINAL : public HTemplateInstruction<1> {
7384 DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
7386 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7387 return Representation::Tagged();
7390 HValue* object() { return OperandAt(0); }
7392 DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
7395 explicit HTrapAllocationMemento(HValue* obj) {
7396 SetOperandAt(0, obj);
7401 class HToFastProperties V8_FINAL : public HUnaryOperation {
7403 DECLARE_INSTRUCTION_FACTORY_P1(HToFastProperties, HValue*);
7405 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7406 return Representation::Tagged();
7409 DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
7412 explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
7413 set_representation(Representation::Tagged());
7414 SetChangesFlag(kNewSpacePromotion);
7416 // This instruction is not marked as kChangesMaps, but does
7417 // change the map of the input operand. Use it only when creating
7418 // object literals via a runtime call.
7419 ASSERT(value->IsCallRuntime());
7421 const Runtime::Function* function = HCallRuntime::cast(value)->function();
7422 ASSERT(function->function_id == Runtime::kHiddenCreateObjectLiteral);
7426 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7430 class HDateField V8_FINAL : public HUnaryOperation {
7432 DECLARE_INSTRUCTION_FACTORY_P2(HDateField, HValue*, Smi*);
7434 Smi* index() const { return index_; }
7436 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7437 return Representation::Tagged();
7440 DECLARE_CONCRETE_INSTRUCTION(DateField)
7443 HDateField(HValue* date, Smi* index)
7444 : HUnaryOperation(date), index_(index) {
7445 set_representation(Representation::Tagged());
7452 class HSeqStringGetChar V8_FINAL : public HTemplateInstruction<2> {
7454 static HInstruction* New(Zone* zone,
7456 String::Encoding encoding,
7460 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7461 return (index == 0) ? Representation::Tagged()
7462 : Representation::Integer32();
7465 String::Encoding encoding() const { return encoding_; }
7466 HValue* string() const { return OperandAt(0); }
7467 HValue* index() const { return OperandAt(1); }
7469 DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)
7472 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7473 return encoding() == HSeqStringGetChar::cast(other)->encoding();
7476 virtual Range* InferRange(Zone* zone) V8_OVERRIDE {
7477 if (encoding() == String::ONE_BYTE_ENCODING) {
7478 return new(zone) Range(0, String::kMaxOneByteCharCode);
7480 ASSERT_EQ(String::TWO_BYTE_ENCODING, encoding());
7481 return new(zone) Range(0, String::kMaxUtf16CodeUnit);
7486 HSeqStringGetChar(String::Encoding encoding,
7488 HValue* index) : encoding_(encoding) {
7489 SetOperandAt(0, string);
7490 SetOperandAt(1, index);
7491 set_representation(Representation::Integer32());
7493 SetDependsOnFlag(kStringChars);
7496 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7498 String::Encoding encoding_;
7502 class HSeqStringSetChar V8_FINAL : public HTemplateInstruction<4> {
7504 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(
7505 HSeqStringSetChar, String::Encoding,
7506 HValue*, HValue*, HValue*);
7508 String::Encoding encoding() { return encoding_; }
7509 HValue* context() { return OperandAt(0); }
7510 HValue* string() { return OperandAt(1); }
7511 HValue* index() { return OperandAt(2); }
7512 HValue* value() { return OperandAt(3); }
7514 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7515 return (index <= 1) ? Representation::Tagged()
7516 : Representation::Integer32();
7519 DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
7522 HSeqStringSetChar(HValue* context,
7523 String::Encoding encoding,
7526 HValue* value) : encoding_(encoding) {
7527 SetOperandAt(0, context);
7528 SetOperandAt(1, string);
7529 SetOperandAt(2, index);
7530 SetOperandAt(3, value);
7531 set_representation(Representation::Tagged());
7532 SetChangesFlag(kStringChars);
7535 String::Encoding encoding_;
7539 class HCheckMapValue V8_FINAL : public HTemplateInstruction<2> {
7541 DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);
7543 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7544 return Representation::Tagged();
7547 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7549 virtual HType CalculateInferredType() V8_OVERRIDE {
7550 return HType::Tagged();
7553 HValue* value() { return OperandAt(0); }
7554 HValue* map() { return OperandAt(1); }
7556 DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
7559 virtual int RedefinedOperandIndex() { return 0; }
7561 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7566 HCheckMapValue(HValue* value,
7568 SetOperandAt(0, value);
7569 SetOperandAt(1, map);
7570 set_representation(Representation::Tagged());
7572 SetDependsOnFlag(kMaps);
7573 SetDependsOnFlag(kElementsKind);
7578 class HForInPrepareMap V8_FINAL : public HTemplateInstruction<2> {
7580 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HForInPrepareMap, HValue*);
7582 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7583 return Representation::Tagged();
7586 HValue* context() { return OperandAt(0); }
7587 HValue* enumerable() { return OperandAt(1); }
7589 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7591 virtual HType CalculateInferredType() V8_OVERRIDE {
7592 return HType::Tagged();
7595 DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
7598 HForInPrepareMap(HValue* context,
7600 SetOperandAt(0, context);
7601 SetOperandAt(1, object);
7602 set_representation(Representation::Tagged());
7603 SetAllSideEffects();
7608 class HForInCacheArray V8_FINAL : public HTemplateInstruction<2> {
7610 DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
7612 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7613 return Representation::Tagged();
7616 HValue* enumerable() { return OperandAt(0); }
7617 HValue* map() { return OperandAt(1); }
7618 int idx() { return idx_; }
7620 HForInCacheArray* index_cache() {
7621 return index_cache_;
7624 void set_index_cache(HForInCacheArray* index_cache) {
7625 index_cache_ = index_cache;
7628 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7630 virtual HType CalculateInferredType() V8_OVERRIDE {
7631 return HType::Tagged();
7634 DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
7637 HForInCacheArray(HValue* enumerable,
7639 int idx) : idx_(idx) {
7640 SetOperandAt(0, enumerable);
7641 SetOperandAt(1, keys);
7642 set_representation(Representation::Tagged());
7646 HForInCacheArray* index_cache_;
7650 class HLoadFieldByIndex V8_FINAL : public HTemplateInstruction<2> {
7652 HLoadFieldByIndex(HValue* object,
7654 SetOperandAt(0, object);
7655 SetOperandAt(1, index);
7656 SetChangesFlag(kNewSpacePromotion);
7657 set_representation(Representation::Tagged());
7660 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7661 return Representation::Tagged();
7664 HValue* object() { return OperandAt(0); }
7665 HValue* index() { return OperandAt(1); }
7667 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7669 virtual HType CalculateInferredType() V8_OVERRIDE {
7670 return HType::Tagged();
7673 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
7676 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7680 class HNullarySIMDOperation V8_FINAL : public HTemplateInstruction<1> {
7682 static HInstruction* New(Zone* zone,
7684 BuiltinFunctionId op);
7686 HValue* context() { return OperandAt(0); }
7688 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7690 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7691 return Representation::Tagged();
7694 BuiltinFunctionId op() const { return op_; }
7695 const char* OpName() const;
7697 DECLARE_CONCRETE_INSTRUCTION(NullarySIMDOperation)
7700 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7701 HNullarySIMDOperation* b = HNullarySIMDOperation::cast(other);
7702 return op_ == b->op();
7706 HNullarySIMDOperation(HValue* context, BuiltinFunctionId op)
7707 : HTemplateInstruction<1>(HType::None()), op_(op) {
7708 SetOperandAt(0, context);
7710 #define SIMD_NULLARY_OPERATION_CASE_ITEM(p1, p2, name, representation) \
7712 set_representation(Representation::representation()); \
7713 set_type(HType::TypeFromRepresentation(representation_)); \
7715 SIMD_NULLARY_OPERATIONS(SIMD_NULLARY_OPERATION_CASE_ITEM)
7716 #undef SIMD_NULLARY_OPERATION_CASE_ITEM
7723 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7725 BuiltinFunctionId op_;
7729 class HUnarySIMDOperation V8_FINAL : public HTemplateInstruction<2> {
7731 static HInstruction* New(Zone* zone,
7734 BuiltinFunctionId op,
7735 Representation to = Representation::Float32x4());
7737 HValue* context() { return OperandAt(0); }
7738 HValue* value() { return OperandAt(1); }
7740 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7742 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7744 return Representation::Tagged();
7745 } else if (op_ == kSIMD128Change) {
7746 return value()->representation();
7749 #define SIMD_UNARY_OPERATION_CASE_ITEM(p1, p2, name, p4, representation) \
7751 return Representation::representation();
7752 SIMD_UNARY_OPERATIONS(SIMD_UNARY_OPERATION_CASE_ITEM)
7753 SIMD_UNARY_OPERATIONS_FOR_PROPERTY_ACCESS(SIMD_UNARY_OPERATION_CASE_ITEM)
7754 #undef SIMD_UNARY_OPERATION_CASE_ITEM
7757 return Representation::None();
7762 BuiltinFunctionId op() const { return op_; }
7763 const char* OpName() const;
7765 DECLARE_CONCRETE_INSTRUCTION(UnarySIMDOperation)
7768 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7769 HUnarySIMDOperation* b = HUnarySIMDOperation::cast(other);
7770 return op_ == b->op();
7774 HUnarySIMDOperation(HValue* context, HValue* value, BuiltinFunctionId op,
7775 Representation to = Representation::Float32x4())
7776 : HTemplateInstruction<2>(HType::None()), op_(op) {
7777 SetOperandAt(0, context);
7778 SetOperandAt(1, value);
7780 case kSIMD128Change:
7781 set_representation(to);
7782 set_type(HType::TypeFromRepresentation(to));
7784 #define SIMD_UNARY_OPERATION_CASE_ITEM(p1, p2, name, representation, p5) \
7786 set_representation(Representation::representation()); \
7787 set_type(HType::TypeFromRepresentation(representation_)); \
7788 if (Representation::p5().IsInteger32()) { \
7789 SetFlag(kTruncatingToInt32); \
7792 SIMD_UNARY_OPERATIONS(SIMD_UNARY_OPERATION_CASE_ITEM)
7793 SIMD_UNARY_OPERATIONS_FOR_PROPERTY_ACCESS(SIMD_UNARY_OPERATION_CASE_ITEM)
7794 #undef SIMD_UNARY_OPERATION_CASE_ITEM
7801 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7803 BuiltinFunctionId op_;
7807 class HBinarySIMDOperation V8_FINAL : public HTemplateInstruction<3> {
7809 static HInstruction* New(Zone* zone,
7813 BuiltinFunctionId op);
7815 HValue* context() { return OperandAt(0); }
7816 HValue* left() { return OperandAt(1); }
7817 HValue* right() { return OperandAt(2); }
7819 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7821 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7823 return Representation::Tagged();
7826 #define SIMD_BINARY_OPERATION_CASE_ITEM(p1, p2, name, p4, left_representation, \
7827 right_representation) \
7829 return index == 1 ? Representation::left_representation() \
7830 : Representation::right_representation(); \
7832 SIMD_BINARY_OPERATIONS(SIMD_BINARY_OPERATION_CASE_ITEM)
7833 #undef SIMD_BINARY_OPERATION_CASE_ITEM
7836 return Representation::None();
7841 BuiltinFunctionId op() const { return op_; }
7842 const char* OpName() const;
7844 DECLARE_CONCRETE_INSTRUCTION(BinarySIMDOperation)
7847 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7848 HBinarySIMDOperation* b = HBinarySIMDOperation::cast(other);
7849 return op_ == b->op();
7853 HBinarySIMDOperation(HValue* context, HValue* left, HValue* right,
7854 BuiltinFunctionId op)
7855 : HTemplateInstruction<3>(HType::None()), op_(op) {
7856 SetOperandAt(0, context);
7857 SetOperandAt(1, left);
7858 SetOperandAt(2, right);
7860 #define SIMD_BINARY_OPERATION_CASE_ITEM(p1, p2, name, representation, p5, p6) \
7862 set_representation(Representation::representation()); \
7863 set_type(HType::TypeFromRepresentation(representation_)); \
7864 if (Representation::p5().IsInteger32() || \
7865 Representation::p6().IsInteger32()) { \
7866 SetFlag(kTruncatingToInt32); \
7869 SIMD_BINARY_OPERATIONS(SIMD_BINARY_OPERATION_CASE_ITEM)
7870 #undef SIMD_BINARY_OPERATION_CASE_ITEM
7877 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7879 BuiltinFunctionId op_;
7883 class HTernarySIMDOperation V8_FINAL : public HTemplateInstruction<4> {
7885 static HInstruction* New(Zone* zone,
7890 BuiltinFunctionId op);
7892 HValue* context() { return OperandAt(0); }
7893 HValue* first() { return OperandAt(1); }
7894 HValue* second() { return OperandAt(2); }
7895 HValue* third() { return OperandAt(3); }
7897 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7899 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7901 return Representation::Tagged();
7904 #define SIMD_TERNARY_OPERATION_CASE_ITEM(p1, p2, name, p4, \
7905 first_representation, second_representation, third_representation) \
7908 case 1: return Representation::first_representation(); \
7909 case 2: return Representation::second_representation(); \
7910 case 3: return Representation::third_representation(); \
7913 return Representation::None(); \
7915 SIMD_TERNARY_OPERATIONS(SIMD_TERNARY_OPERATION_CASE_ITEM)
7916 #undef SIMD_TERNARY_OPERATION_CASE_ITEM
7919 return Representation::None();
7924 BuiltinFunctionId op() const { return op_; }
7925 const char* OpName() const;
7927 DECLARE_CONCRETE_INSTRUCTION(TernarySIMDOperation)
7930 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7931 HTernarySIMDOperation* b = HTernarySIMDOperation::cast(other);
7932 return op_ == b->op();
7936 HTernarySIMDOperation(HValue* context, HValue* first, HValue* second,
7937 HValue* third, BuiltinFunctionId op)
7938 : HTemplateInstruction<4>(HType::None()), op_(op) {
7939 SetOperandAt(0, context);
7940 SetOperandAt(1, first);
7941 SetOperandAt(2, second);
7942 SetOperandAt(3, third);
7944 #define SIMD_TERNARY_OPERATION_CASE_ITEM(p1, p2, name, representation, p5, \
7947 set_representation(Representation::representation()); \
7948 set_type(HType::TypeFromRepresentation(representation_)); \
7949 if (Representation::p5().IsInteger32() || \
7950 Representation::p6().IsInteger32() || \
7951 Representation::p7().IsInteger32()) { \
7952 SetFlag(kTruncatingToInt32); \
7955 SIMD_TERNARY_OPERATIONS(SIMD_TERNARY_OPERATION_CASE_ITEM)
7956 #undef SIMD_TERNARY_OPERATION_CASE_ITEM
7963 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7965 BuiltinFunctionId op_;
7969 class HQuarternarySIMDOperation V8_FINAL : public HTemplateInstruction<5> {
7971 static HInstruction* New(Zone* zone,
7977 BuiltinFunctionId op);
7979 HValue* context() { return OperandAt(0); }
7980 HValue* x() { return OperandAt(1); }
7981 HValue* y() { return OperandAt(2); }
7982 HValue* z() { return OperandAt(3); }
7983 HValue* w() { return OperandAt(4); }
7985 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7987 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7989 return Representation::Tagged();
7992 #define SIMD_QUARTERNARY_OPERATION_CASE_ITEM(p1, p2, name, p4, \
7993 first_representation, second_representation, third_representation, \
7994 fourth_representation) \
7997 case 1: return Representation::first_representation(); \
7998 case 2: return Representation::second_representation(); \
7999 case 3: return Representation::third_representation(); \
8000 case 4: return Representation::fourth_representation(); \
8003 return Representation::None(); \
8005 SIMD_QUARTERNARY_OPERATIONS(SIMD_QUARTERNARY_OPERATION_CASE_ITEM)
8006 #undef SIMD_QUARTERNARY_OPERATION_CASE_ITEM
8009 return Representation::None();
8014 BuiltinFunctionId op() const { return op_; }
8015 const char* OpName() const;
8017 DECLARE_CONCRETE_INSTRUCTION(QuarternarySIMDOperation)
8020 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
8021 HQuarternarySIMDOperation* b = HQuarternarySIMDOperation::cast(other);
8022 return op_ == b->op();
8026 HQuarternarySIMDOperation(HValue* context, HValue* x, HValue* y, HValue* z,
8027 HValue* w, BuiltinFunctionId op)
8028 : HTemplateInstruction<5>(HType::None()), op_(op) {
8029 SetOperandAt(0, context);
8035 #define SIMD_QUARTERNARY_OPERATION_CASE_ITEM(p1, p2, name, representation, p5, \
8038 set_representation(Representation::representation()); \
8039 set_type(HType::TypeFromRepresentation(representation_)); \
8040 if (Representation::p5().IsInteger32() || \
8041 Representation::p6().IsInteger32() || \
8042 Representation::p7().IsInteger32() || \
8043 Representation::p8().IsInteger32()) { \
8044 SetFlag(kTruncatingToInt32); \
8047 SIMD_QUARTERNARY_OPERATIONS(SIMD_QUARTERNARY_OPERATION_CASE_ITEM)
8048 #undef SIMD_QUARTERNARY_OPERATION_CASE_ITEM
8055 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
8057 BuiltinFunctionId op_;
8061 #undef DECLARE_INSTRUCTION
8062 #undef DECLARE_CONCRETE_INSTRUCTION
8064 } } // namespace v8::internal
8066 #endif // V8_HYDROGEN_INSTRUCTIONS_H_