1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #ifndef V8_HYDROGEN_INSTRUCTIONS_H_
29 #define V8_HYDROGEN_INSTRUCTIONS_H_
33 #include "allocation.h"
34 #include "code-stubs.h"
35 #include "data-flow.h"
36 #include "deoptimizer.h"
37 #include "small-pointer-list.h"
38 #include "string-stream.h"
40 #include "v8conversions.h"
47 // Forward declarations.
51 class HInferRepresentationPhase;
53 class HLoopInformation;
54 class HStoreNamedField;
59 #define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V) \
60 V(ArithmeticBinaryOperation) \
62 V(BitwiseBinaryOperation) \
63 V(ControlInstruction) \
67 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
69 V(AccessArgumentsAt) \
73 V(ArgumentsElements) \
79 V(BoundsCheckBaseIndexInformation) \
81 V(CallWithDescriptor) \
91 V(CheckInstanceType) \
97 V(ClassOfTestAndBranch) \
98 V(CompareNumericAndBranch) \
99 V(CompareHoleAndBranch) \
101 V(CompareMinusZeroAndBranch) \
102 V(CompareObjectEqAndBranch) \
115 V(EnvironmentMarker) \
116 V(ForceRepresentation) \
120 V(GetCachedArrayIndex) \
122 V(HasCachedArrayIndexAndBranch) \
123 V(HasInstanceTypeAndBranch) \
124 V(InnerAllocatedObject) \
126 V(InstanceOfKnownGlobal) \
128 V(IsConstructCallAndBranch) \
129 V(IsObjectAndBranch) \
130 V(IsStringAndBranch) \
132 V(IsUndetectableAndBranch) \
135 V(LoadFieldByIndex) \
136 V(LoadFunctionPrototype) \
138 V(LoadGlobalGeneric) \
140 V(LoadKeyedGeneric) \
142 V(LoadNamedGeneric) \
157 V(SeqStringGetChar) \
158 V(SeqStringSetChar) \
164 V(StoreContextSlot) \
167 V(StoreKeyedGeneric) \
169 V(StoreNamedGeneric) \
171 V(StringCharCodeAt) \
172 V(StringCharFromCode) \
173 V(StringCompareAndBranch) \
176 V(ToFastProperties) \
177 V(TransitionElementsKind) \
178 V(TrapAllocationMemento) \
180 V(TypeofIsAndBranch) \
181 V(UnaryMathOperation) \
182 V(NullarySIMDOperation) \
183 V(UnarySIMDOperation) \
184 V(BinarySIMDOperation) \
185 V(TernarySIMDOperation) \
186 V(QuarternarySIMDOperation) \
191 #define GVN_TRACKED_FLAG_LIST(V) \
195 #define GVN_UNTRACKED_FLAG_LIST(V) \
199 V(BackingStoreFields) \
202 V(DoubleArrayElements) \
211 V(TypedArrayElements)
214 #define DECLARE_ABSTRACT_INSTRUCTION(type) \
215 virtual bool Is##type() const V8_FINAL V8_OVERRIDE { return true; } \
216 static H##type* cast(HValue* value) { \
217 ASSERT(value->Is##type()); \
218 return reinterpret_cast<H##type*>(value); \
222 #define DECLARE_CONCRETE_INSTRUCTION(type) \
223 virtual LInstruction* CompileToLithium( \
224 LChunkBuilder* builder) V8_FINAL V8_OVERRIDE; \
225 static H##type* cast(HValue* value) { \
226 ASSERT(value->Is##type()); \
227 return reinterpret_cast<H##type*>(value); \
229 virtual Opcode opcode() const V8_FINAL V8_OVERRIDE { \
230 return HValue::k##type; \
234 enum PropertyAccessType { LOAD, STORE };
237 class Range V8_FINAL : public ZoneObject {
243 can_be_minus_zero_(false) { }
245 Range(int32_t lower, int32_t upper)
249 can_be_minus_zero_(false) { }
251 int32_t upper() const { return upper_; }
252 int32_t lower() const { return lower_; }
253 Range* next() const { return next_; }
254 Range* CopyClearLower(Zone* zone) const {
255 return new(zone) Range(kMinInt, upper_);
257 Range* CopyClearUpper(Zone* zone) const {
258 return new(zone) Range(lower_, kMaxInt);
260 Range* Copy(Zone* zone) const {
261 Range* result = new(zone) Range(lower_, upper_);
262 result->set_can_be_minus_zero(CanBeMinusZero());
265 int32_t Mask() const;
266 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
267 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
268 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
269 bool CanBeNegative() const { return lower_ < 0; }
270 bool CanBePositive() const { return upper_ > 0; }
271 bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
272 bool IsMostGeneric() const {
273 return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
275 bool IsInSmiRange() const {
276 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
279 lower_ = Max(lower_, Smi::kMinValue);
280 upper_ = Min(upper_, Smi::kMaxValue);
287 void StackUpon(Range* other) {
292 void Intersect(Range* other);
293 void Union(Range* other);
294 void CombinedMax(Range* other);
295 void CombinedMin(Range* other);
297 void AddConstant(int32_t value);
298 void Sar(int32_t value);
299 void Shl(int32_t value);
300 bool AddAndCheckOverflow(const Representation& r, Range* other);
301 bool SubAndCheckOverflow(const Representation& r, Range* other);
302 bool MulAndCheckOverflow(const Representation& r, Range* other);
308 bool can_be_minus_zero_;
312 class HType V8_FINAL {
314 static HType None() { return HType(kNone); }
315 static HType Tagged() { return HType(kTagged); }
316 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
317 static HType TaggedNumber() { return HType(kTaggedNumber); }
318 static HType Smi() { return HType(kSmi); }
319 static HType HeapNumber() { return HType(kHeapNumber); }
320 static HType Float32x4() { return HType(kFloat32x4); }
321 static HType Int32x4() { return HType(kInt32x4); }
322 static HType String() { return HType(kString); }
323 static HType Boolean() { return HType(kBoolean); }
324 static HType NonPrimitive() { return HType(kNonPrimitive); }
325 static HType JSArray() { return HType(kJSArray); }
326 static HType JSObject() { return HType(kJSObject); }
328 // Return the weakest (least precise) common type.
329 HType Combine(HType other) {
330 return HType(static_cast<Type>(type_ & other.type_));
333 bool Equals(const HType& other) const {
334 return type_ == other.type_;
337 bool IsSubtypeOf(const HType& other) {
338 return Combine(other).Equals(other);
341 bool IsTaggedPrimitive() const {
342 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
345 bool IsTaggedNumber() const {
346 return ((type_ & kTaggedNumber) == kTaggedNumber);
350 return ((type_ & kSmi) == kSmi);
353 bool IsHeapNumber() const {
354 return ((type_ & kHeapNumber) == kHeapNumber);
357 bool IsFloat32x4() const {
358 return ((type_ & kFloat32x4) == kFloat32x4);
361 bool IsInt32x4() const {
362 return ((type_ & kInt32x4) == kInt32x4);
365 bool IsSIMD128() const {
366 return IsFloat32x4() || IsInt32x4();
369 bool IsString() const {
370 return ((type_ & kString) == kString);
373 bool IsNonString() const {
374 return IsTaggedPrimitive() || IsSmi() || IsHeapNumber() || IsSIMD128() ||
375 IsBoolean() || IsJSArray();
378 bool IsBoolean() const {
379 return ((type_ & kBoolean) == kBoolean);
382 bool IsNonPrimitive() const {
383 return ((type_ & kNonPrimitive) == kNonPrimitive);
386 bool IsJSArray() const {
387 return ((type_ & kJSArray) == kJSArray);
390 bool IsJSObject() const {
391 return ((type_ & kJSObject) == kJSObject);
394 bool IsHeapObject() const {
395 return IsHeapNumber() || IsSIMD128() || IsString() ||
396 IsBoolean() || IsNonPrimitive();
399 bool ToStringOrToNumberCanBeObserved(Representation representation) {
401 case kTaggedPrimitive: // fallthru
402 case kTaggedNumber: // fallthru
403 case kSmi: // fallthru
404 case kHeapNumber: // fallthru
405 case kFloat32x4: // fallthru
406 case kInt32x4: // fallthru
407 case kString: // fallthru
410 case kJSArray: // fallthru
416 return !representation.IsSmiOrInteger32() && !representation.IsDouble();
419 static HType TypeFromValue(Handle<Object> value);
420 static HType TypeFromRepresentation(Representation representation);
422 const char* ToString();
426 kNone = 0x0, // 0000 0000 0000 0000
427 kTagged = 0x1, // 0000 0000 0000 0001
428 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
429 kTaggedNumber = 0xd, // 0000 0000 0000 1101
430 kSmi = 0x1d, // 0000 0000 0001 1101
431 kHeapNumber = 0x2d, // 0000 0000 0010 1101
432 kFloat32x4 = 0x45, // 0000 0000 0100 0101
433 kInt32x4 = 0x85, // 0000 0000 1000 0101
434 kString = 0x105, // 0000 0001 0000 0101
435 kBoolean = 0x205, // 0000 0010 1000 0101
436 kNonPrimitive = 0x401, // 0000 0100 0000 0001
437 kJSObject = 0xc01, // 0000 1100 0000 0001
438 kJSArray = 0x1c01 // 0001 1100 0000 0001
441 // Make sure type fits in int16.
442 STATIC_ASSERT(kJSArray < (1 << (2 * kBitsPerByte)));
444 explicit HType(Type t) : type_(t) { }
450 class HUseListNode: public ZoneObject {
452 HUseListNode(HValue* value, int index, HUseListNode* tail)
453 : tail_(tail), value_(value), index_(index) {
456 HUseListNode* tail();
457 HValue* value() const { return value_; }
458 int index() const { return index_; }
460 void set_tail(HUseListNode* list) { tail_ = list; }
464 tail_ = reinterpret_cast<HUseListNode*>(1);
477 // We reuse use list nodes behind the scenes as uses are added and deleted.
478 // This class is the safe way to iterate uses while deleting them.
479 class HUseIterator V8_FINAL BASE_EMBEDDED {
481 bool Done() { return current_ == NULL; }
495 explicit HUseIterator(HUseListNode* head);
497 HUseListNode* current_;
506 // All tracked flags should appear before untracked ones.
508 // Declare global value numbering flags.
509 #define DECLARE_FLAG(Type) k##Type,
510 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
511 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
513 #define COUNT_FLAG(Type) + 1
514 kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG),
515 kNumberOfUntrackedSideEffects = 0 GVN_UNTRACKED_FLAG_LIST(COUNT_FLAG),
517 kNumberOfFlags = kNumberOfTrackedSideEffects + kNumberOfUntrackedSideEffects
521 static inline GVNFlag GVNFlagFromInt(int i) {
523 ASSERT(i < kNumberOfFlags);
524 return static_cast<GVNFlag>(i);
528 class DecompositionResult V8_FINAL BASE_EMBEDDED {
530 DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
532 HValue* base() { return base_; }
533 int offset() { return offset_; }
534 int scale() { return scale_; }
536 bool Apply(HValue* other_base, int other_offset, int other_scale = 0) {
539 offset_ = other_offset;
540 scale_ = other_scale;
545 offset_ += other_offset;
546 scale_ = other_scale;
554 void SwapValues(HValue** other_base, int* other_offset, int* other_scale) {
555 swap(&base_, other_base);
556 swap(&offset_, other_offset);
557 swap(&scale_, other_scale);
561 template <class T> void swap(T* a, T* b) {
573 typedef EnumSet<GVNFlag, int32_t> GVNFlagSet;
576 // This class encapsulates encoding and decoding of sources positions from
577 // which hydrogen values originated.
578 // When FLAG_track_hydrogen_positions is set this object encodes the
579 // identifier of the inlining and absolute offset from the start of the
581 // When the flag is not set we simply track absolute offset from the
583 class HSourcePosition {
585 HSourcePosition(const HSourcePosition& other) : value_(other.value_) { }
587 static HSourcePosition Unknown() {
588 return HSourcePosition(RelocInfo::kNoPosition);
591 bool IsUnknown() const { return value_ == RelocInfo::kNoPosition; }
593 int position() const { return PositionField::decode(value_); }
594 void set_position(int position) {
595 if (FLAG_hydrogen_track_positions) {
596 value_ = static_cast<int>(PositionField::update(value_, position));
602 int inlining_id() const { return InliningIdField::decode(value_); }
603 void set_inlining_id(int inlining_id) {
604 if (FLAG_hydrogen_track_positions) {
605 value_ = static_cast<int>(InliningIdField::update(value_, inlining_id));
609 int raw() const { return value_; }
611 void PrintTo(FILE* f);
614 typedef BitField<int, 0, 9> InliningIdField;
616 // Offset from the start of the inlined function.
617 typedef BitField<int, 9, 22> PositionField;
619 // On HPositionInfo can use this constructor.
620 explicit HSourcePosition(int value) : value_(value) { }
622 friend class HPositionInfo;
624 // If FLAG_hydrogen_track_positions is set contains bitfields InliningIdField
625 // and PositionField.
626 // Otherwise contains absolute offset from the script start.
631 class HValue : public ZoneObject {
633 static const int kNoNumber = -1;
636 kFlexibleRepresentation,
638 // Participate in Global Value Numbering, i.e. elimination of
639 // unnecessary recomputations. If an instruction sets this flag, it must
640 // implement DataEquals(), which will be used to determine if other
641 // occurrences of the instruction are indeed the same.
643 // Track instructions that are dominating side effects. If an instruction
644 // sets this flag, it must implement HandleSideEffectDominator() and should
645 // indicate which side effects to track by setting GVN flags.
646 kTrackSideEffectDominators,
653 kAllowUndefinedAsNaN,
656 kAllUsesTruncatingToInt32,
658 kAllUsesTruncatingToSmi,
659 // Set after an instruction is killed.
661 // Instructions that are allowed to produce full range unsigned integer
662 // values are marked with kUint32 flag. If arithmetic shift or a load from
663 // EXTERNAL_UINT32_ELEMENTS array is not marked with this flag
664 // it will deoptimize if result does not fit into signed integer range.
665 // HGraph::ComputeSafeUint32Operations is responsible for setting this
668 kHasNoObservableSideEffects,
669 // Indicates the instruction is live during dead code elimination.
672 // HEnvironmentMarkers are deleted before dead code
673 // elimination takes place, so they can repurpose the kIsLive flag:
674 kEndsLiveRange = kIsLive,
676 // TODO(everyone): Don't forget to update this!
680 STATIC_ASSERT(kLastFlag < kBitsPerInt);
682 static HValue* cast(HValue* value) { return value; }
685 // Declare a unique enum value for each hydrogen instruction.
686 #define DECLARE_OPCODE(type) k##type,
687 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
689 #undef DECLARE_OPCODE
691 virtual Opcode opcode() const = 0;
693 // Declare a non-virtual predicates for each concrete HInstruction or HValue.
694 #define DECLARE_PREDICATE(type) \
695 bool Is##type() const { return opcode() == k##type; }
696 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
697 #undef DECLARE_PREDICATE
698 bool IsPhi() const { return opcode() == kPhi; }
700 // Declare virtual predicates for abstract HInstruction or HValue
701 #define DECLARE_PREDICATE(type) \
702 virtual bool Is##type() const { return false; }
703 HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
704 #undef DECLARE_PREDICATE
706 HValue(HType type = HType::Tagged())
715 virtual HSourcePosition position() const {
716 return HSourcePosition::Unknown();
718 virtual HSourcePosition operand_position(int index) const {
722 HBasicBlock* block() const { return block_; }
723 void SetBlock(HBasicBlock* block);
725 // Note: Never call this method for an unlinked value.
726 Isolate* isolate() const;
728 int id() const { return id_; }
729 void set_id(int id) { id_ = id; }
731 HUseIterator uses() const { return HUseIterator(use_list_); }
733 virtual bool EmitAtUses() { return false; }
735 Representation representation() const { return representation_; }
736 void ChangeRepresentation(Representation r) {
737 ASSERT(CheckFlag(kFlexibleRepresentation));
738 ASSERT(!CheckFlag(kCannotBeTagged) || !r.IsTagged());
739 RepresentationChanged(r);
742 // Tagged is the bottom of the lattice, don't go any further.
743 ClearFlag(kFlexibleRepresentation);
746 virtual void AssumeRepresentation(Representation r);
748 virtual Representation KnownOptimalRepresentation() {
749 Representation r = representation();
752 if (t.IsSmi()) return Representation::Smi();
753 if (t.IsHeapNumber()) return Representation::Double();
754 if (t.IsFloat32x4()) return Representation::Float32x4();
755 if (t.IsInt32x4()) return Representation::Int32x4();
756 if (t.IsHeapObject()) return r;
757 return Representation::None();
762 HType type() const { return type_; }
763 void set_type(HType new_type) {
764 ASSERT(new_type.IsSubtypeOf(type_));
768 bool IsHeapObject() {
769 return representation_.IsHeapObject() || type_.IsHeapObject();
772 // There are HInstructions that do not really change a value, they
773 // only add pieces of information to it (like bounds checks, map checks,
775 // We call these instructions "informative definitions", or "iDef".
776 // One of the iDef operands is special because it is the value that is
777 // "transferred" to the output, we call it the "redefined operand".
778 // If an HValue is an iDef it must override RedefinedOperandIndex() so that
779 // it does not return kNoRedefinedOperand;
780 static const int kNoRedefinedOperand = -1;
781 virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
782 bool IsInformativeDefinition() {
783 return RedefinedOperandIndex() != kNoRedefinedOperand;
785 HValue* RedefinedOperand() {
786 int index = RedefinedOperandIndex();
787 return index == kNoRedefinedOperand ? NULL : OperandAt(index);
790 bool CanReplaceWithDummyUses();
792 virtual int argument_delta() const { return 0; }
794 // A purely informative definition is an idef that will not emit code and
795 // should therefore be removed from the graph in the RestoreActualValues
796 // phase (so that live ranges will be shorter).
797 virtual bool IsPurelyInformativeDefinition() { return false; }
799 // This method must always return the original HValue SSA definition,
800 // regardless of any chain of iDefs of this value.
801 HValue* ActualValue() {
802 HValue* value = this;
804 while ((index = value->RedefinedOperandIndex()) != kNoRedefinedOperand) {
805 value = value->OperandAt(index);
810 bool IsInteger32Constant();
811 int32_t GetInteger32Constant();
812 bool EqualsInteger32Constant(int32_t value);
814 bool IsDefinedAfter(HBasicBlock* other) const;
817 virtual int OperandCount() = 0;
818 virtual HValue* OperandAt(int index) const = 0;
819 void SetOperandAt(int index, HValue* value);
821 void DeleteAndReplaceWith(HValue* other);
822 void ReplaceAllUsesWith(HValue* other);
823 bool HasNoUses() const { return use_list_ == NULL; }
824 bool HasMultipleUses() const {
825 return use_list_ != NULL && use_list_->tail() != NULL;
827 int UseCount() const;
829 // Mark this HValue as dead and to be removed from other HValues' use lists.
832 int flags() const { return flags_; }
833 void SetFlag(Flag f) { flags_ |= (1 << f); }
834 void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
835 bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
836 void CopyFlag(Flag f, HValue* other) {
837 if (other->CheckFlag(f)) SetFlag(f);
840 // Returns true if the flag specified is set for all uses, false otherwise.
841 bool CheckUsesForFlag(Flag f) const;
842 // Same as before and the first one without the flag is returned in value.
843 bool CheckUsesForFlag(Flag f, HValue** value) const;
844 // Returns true if the flag specified is set for all uses, and this set
845 // of uses is non-empty.
846 bool HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const;
848 GVNFlagSet ChangesFlags() const { return changes_flags_; }
849 GVNFlagSet DependsOnFlags() const { return depends_on_flags_; }
850 void SetChangesFlag(GVNFlag f) { changes_flags_.Add(f); }
851 void SetDependsOnFlag(GVNFlag f) { depends_on_flags_.Add(f); }
852 void ClearChangesFlag(GVNFlag f) { changes_flags_.Remove(f); }
853 void ClearDependsOnFlag(GVNFlag f) { depends_on_flags_.Remove(f); }
854 bool CheckChangesFlag(GVNFlag f) const {
855 return changes_flags_.Contains(f);
857 bool CheckDependsOnFlag(GVNFlag f) const {
858 return depends_on_flags_.Contains(f);
860 void SetAllSideEffects() { changes_flags_.Add(AllSideEffectsFlagSet()); }
861 void ClearAllSideEffects() {
862 changes_flags_.Remove(AllSideEffectsFlagSet());
864 bool HasSideEffects() const {
865 return changes_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
867 bool HasObservableSideEffects() const {
868 return !CheckFlag(kHasNoObservableSideEffects) &&
869 changes_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
872 GVNFlagSet SideEffectFlags() const {
873 GVNFlagSet result = ChangesFlags();
874 result.Intersect(AllSideEffectsFlagSet());
878 GVNFlagSet ObservableChangesFlags() const {
879 GVNFlagSet result = ChangesFlags();
880 result.Intersect(AllObservableSideEffectsFlagSet());
884 Range* range() const { return range_; }
885 // TODO(svenpanne) We should really use the null object pattern here.
886 bool HasRange() const { return range_ != NULL; }
887 void AddNewRange(Range* r, Zone* zone);
888 void RemoveLastAddedRange();
889 void ComputeInitialRange(Zone* zone);
891 // Escape analysis helpers.
892 virtual bool HasEscapingOperandAt(int index) { return true; }
893 virtual bool HasOutOfBoundsAccess(int size) { return false; }
895 // Representation helpers.
896 virtual Representation observed_input_representation(int index) {
897 return Representation::None();
899 virtual Representation RequiredInputRepresentation(int index) = 0;
900 virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
902 // This gives the instruction an opportunity to replace itself with an
903 // instruction that does the same in some better way. To replace an
904 // instruction with a new one, first add the new instruction to the graph,
905 // then return it. Return NULL to have the instruction deleted.
906 virtual HValue* Canonicalize() { return this; }
908 bool Equals(HValue* other);
909 virtual intptr_t Hashcode();
911 // Compute unique ids upfront that is safe wrt GC and concurrent compilation.
912 virtual void FinalizeUniqueness() { }
915 virtual void PrintTo(StringStream* stream) = 0;
916 void PrintNameTo(StringStream* stream);
917 void PrintTypeTo(StringStream* stream);
918 void PrintRangeTo(StringStream* stream);
919 void PrintChangesTo(StringStream* stream);
921 const char* Mnemonic() const;
923 // Type information helpers.
924 bool HasMonomorphicJSObjectType();
926 // TODO(mstarzinger): For now instructions can override this function to
927 // specify statically known types, once HType can convey more information
928 // it should be based on the HType.
929 virtual Handle<Map> GetMonomorphicJSObjectMap() { return Handle<Map>(); }
931 // Updated the inferred type of this instruction and returns true if
933 bool UpdateInferredType();
935 virtual HType CalculateInferredType();
937 // This function must be overridden for instructions which have the
938 // kTrackSideEffectDominators flag set, to track instructions that are
939 // dominating side effects.
940 // It returns true if it removed an instruction which had side effects.
941 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
947 // Check if this instruction has some reason that prevents elimination.
948 bool CannotBeEliminated() const {
949 return HasObservableSideEffects() || !IsDeletable();
953 virtual void Verify() = 0;
956 virtual bool TryDecompose(DecompositionResult* decomposition) {
957 if (RedefinedOperand() != NULL) {
958 return RedefinedOperand()->TryDecompose(decomposition);
964 // Returns true conservatively if the program might be able to observe a
965 // ToString() operation on this value.
966 bool ToStringCanBeObserved() const {
967 return type().ToStringOrToNumberCanBeObserved(representation());
970 // Returns true conservatively if the program might be able to observe a
971 // ToNumber() operation on this value.
972 bool ToNumberCanBeObserved() const {
973 return type().ToStringOrToNumberCanBeObserved(representation());
976 MinusZeroMode GetMinusZeroMode() {
977 return CheckFlag(kBailoutOnMinusZero)
978 ? FAIL_ON_MINUS_ZERO : TREAT_MINUS_ZERO_AS_ZERO;
982 // This function must be overridden for instructions with flag kUseGVN, to
983 // compare the non-Operand parts of the instruction.
984 virtual bool DataEquals(HValue* other) {
989 virtual Representation RepresentationFromInputs() {
990 return representation();
992 Representation RepresentationFromUses();
993 Representation RepresentationFromUseRequirements();
995 virtual void UpdateRepresentation(Representation new_rep,
996 HInferRepresentationPhase* h_infer,
998 void AddDependantsToWorklist(HInferRepresentationPhase* h_infer);
1000 virtual void RepresentationChanged(Representation to) { }
1002 virtual Range* InferRange(Zone* zone);
1003 virtual void DeleteFromGraph() = 0;
1004 virtual void InternalSetOperandAt(int index, HValue* value) = 0;
1005 void clear_block() {
1006 ASSERT(block_ != NULL);
1010 void set_representation(Representation r) {
1011 ASSERT(representation_.IsNone() && !r.IsNone());
1012 representation_ = r;
1015 static GVNFlagSet AllFlagSet() {
1017 #define ADD_FLAG(Type) result.Add(k##Type);
1018 GVN_TRACKED_FLAG_LIST(ADD_FLAG)
1019 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
1024 // A flag mask to mark an instruction as having arbitrary side effects.
1025 static GVNFlagSet AllSideEffectsFlagSet() {
1026 GVNFlagSet result = AllFlagSet();
1027 result.Remove(kOsrEntries);
1031 // A flag mask of all side effects that can make observable changes in
1032 // an executing program (i.e. are not safe to repeat, move or remove);
1033 static GVNFlagSet AllObservableSideEffectsFlagSet() {
1034 GVNFlagSet result = AllFlagSet();
1035 result.Remove(kNewSpacePromotion);
1036 result.Remove(kElementsKind);
1037 result.Remove(kElementsPointer);
1038 result.Remove(kMaps);
1042 // Remove the matching use from the use list if present. Returns the
1043 // removed list node or NULL.
1044 HUseListNode* RemoveUse(HValue* value, int index);
1046 void RegisterUse(int index, HValue* new_value);
1048 HBasicBlock* block_;
1050 // The id of this instruction in the hydrogen graph, assigned when first
1051 // added to the graph. Reflects creation order.
1054 Representation representation_;
1056 HUseListNode* use_list_;
1059 GVNFlagSet changes_flags_;
1060 GVNFlagSet depends_on_flags_;
1063 virtual bool IsDeletable() const { return false; }
1065 DISALLOW_COPY_AND_ASSIGN(HValue);
1069 #define DECLARE_INSTRUCTION_FACTORY_P0(I) \
1070 static I* New(Zone* zone, HValue* context) { \
1071 return new(zone) I(); \
1074 #define DECLARE_INSTRUCTION_FACTORY_P1(I, P1) \
1075 static I* New(Zone* zone, HValue* context, P1 p1) { \
1076 return new(zone) I(p1); \
1079 #define DECLARE_INSTRUCTION_FACTORY_P2(I, P1, P2) \
1080 static I* New(Zone* zone, HValue* context, P1 p1, P2 p2) { \
1081 return new(zone) I(p1, p2); \
1084 #define DECLARE_INSTRUCTION_FACTORY_P3(I, P1, P2, P3) \
1085 static I* New(Zone* zone, HValue* context, P1 p1, P2 p2, P3 p3) { \
1086 return new(zone) I(p1, p2, p3); \
1089 #define DECLARE_INSTRUCTION_FACTORY_P4(I, P1, P2, P3, P4) \
1090 static I* New(Zone* zone, \
1096 return new(zone) I(p1, p2, p3, p4); \
1099 #define DECLARE_INSTRUCTION_FACTORY_P5(I, P1, P2, P3, P4, P5) \
1100 static I* New(Zone* zone, \
1107 return new(zone) I(p1, p2, p3, p4, p5); \
1110 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(I) \
1111 static I* New(Zone* zone, HValue* context) { \
1112 return new(zone) I(context); \
1115 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(I, P1) \
1116 static I* New(Zone* zone, HValue* context, P1 p1) { \
1117 return new(zone) I(context, p1); \
1120 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(I, P1, P2) \
1121 static I* New(Zone* zone, HValue* context, P1 p1, P2 p2) { \
1122 return new(zone) I(context, p1, p2); \
1125 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(I, P1, P2, P3) \
1126 static I* New(Zone* zone, HValue* context, P1 p1, P2 p2, P3 p3) { \
1127 return new(zone) I(context, p1, p2, p3); \
1130 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(I, P1, P2, P3, P4) \
1131 static I* New(Zone* zone, \
1137 return new(zone) I(context, p1, p2, p3, p4); \
1140 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(I, P1, P2, P3, P4, P5) \
1141 static I* New(Zone* zone, \
1148 return new(zone) I(context, p1, p2, p3, p4, p5); \
1152 // A helper class to represent per-operand position information attached to
1153 // the HInstruction in the compact form. Uses tagging to distinguish between
1154 // case when only instruction's position is available and case when operands'
1155 // positions are also available.
1156 // In the first case it contains intruction's position as a tagged value.
1157 // In the second case it points to an array which contains instruction's
1158 // position and operands' positions.
1159 class HPositionInfo {
1161 explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { }
1163 HSourcePosition position() const {
1164 if (has_operand_positions()) {
1165 return operand_positions()[kInstructionPosIndex];
1167 return HSourcePosition(static_cast<int>(UntagPosition(data_)));
1170 void set_position(HSourcePosition pos) {
1171 if (has_operand_positions()) {
1172 operand_positions()[kInstructionPosIndex] = pos;
1174 data_ = TagPosition(pos.raw());
1178 void ensure_storage_for_operand_positions(Zone* zone, int operand_count) {
1179 if (has_operand_positions()) {
1183 const int length = kFirstOperandPosIndex + operand_count;
1184 HSourcePosition* positions =
1185 zone->NewArray<HSourcePosition>(length);
1186 for (int i = 0; i < length; i++) {
1187 positions[i] = HSourcePosition::Unknown();
1190 const HSourcePosition pos = position();
1191 data_ = reinterpret_cast<intptr_t>(positions);
1194 ASSERT(has_operand_positions());
1197 HSourcePosition operand_position(int idx) const {
1198 if (!has_operand_positions()) {
1201 return *operand_position_slot(idx);
1204 void set_operand_position(int idx, HSourcePosition pos) {
1205 *operand_position_slot(idx) = pos;
1209 static const intptr_t kInstructionPosIndex = 0;
1210 static const intptr_t kFirstOperandPosIndex = 1;
1212 HSourcePosition* operand_position_slot(int idx) const {
1213 ASSERT(has_operand_positions());
1214 return &(operand_positions()[kFirstOperandPosIndex + idx]);
1217 bool has_operand_positions() const {
1218 return !IsTaggedPosition(data_);
1221 HSourcePosition* operand_positions() const {
1222 ASSERT(has_operand_positions());
1223 return reinterpret_cast<HSourcePosition*>(data_);
1226 static const intptr_t kPositionTag = 1;
1227 static const intptr_t kPositionShift = 1;
1228 static bool IsTaggedPosition(intptr_t val) {
1229 return (val & kPositionTag) != 0;
1231 static intptr_t UntagPosition(intptr_t val) {
1232 ASSERT(IsTaggedPosition(val));
1233 return val >> kPositionShift;
1235 static intptr_t TagPosition(intptr_t val) {
1236 const intptr_t result = (val << kPositionShift) | kPositionTag;
1237 ASSERT(UntagPosition(result) == val);
1245 class HInstruction : public HValue {
1247 HInstruction* next() const { return next_; }
1248 HInstruction* previous() const { return previous_; }
1250 virtual void PrintTo(StringStream* stream) V8_OVERRIDE;
1251 virtual void PrintDataTo(StringStream* stream);
1253 bool IsLinked() const { return block() != NULL; }
1256 void InsertBefore(HInstruction* next);
1258 template<class T> T* Prepend(T* instr) {
1259 instr->InsertBefore(this);
1263 void InsertAfter(HInstruction* previous);
1265 template<class T> T* Append(T* instr) {
1266 instr->InsertAfter(this);
1270 // The position is a write-once variable.
1271 virtual HSourcePosition position() const V8_OVERRIDE {
1272 return HSourcePosition(position_.position());
1274 bool has_position() const {
1275 return !position().IsUnknown();
1277 void set_position(HSourcePosition position) {
1278 ASSERT(!has_position());
1279 ASSERT(!position.IsUnknown());
1280 position_.set_position(position);
1283 virtual HSourcePosition operand_position(int index) const V8_OVERRIDE {
1284 const HSourcePosition pos = position_.operand_position(index);
1285 return pos.IsUnknown() ? position() : pos;
1287 void set_operand_position(Zone* zone, int index, HSourcePosition pos) {
1288 ASSERT(0 <= index && index < OperandCount());
1289 position_.ensure_storage_for_operand_positions(zone, OperandCount());
1290 position_.set_operand_position(index, pos);
1293 bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
1295 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
1298 virtual void Verify() V8_OVERRIDE;
1301 bool CanDeoptimize();
1303 virtual bool HasStackCheck() { return false; }
1305 DECLARE_ABSTRACT_INSTRUCTION(Instruction)
1308 HInstruction(HType type = HType::Tagged())
1312 position_(RelocInfo::kNoPosition) {
1313 SetDependsOnFlag(kOsrEntries);
1316 virtual void DeleteFromGraph() V8_OVERRIDE { Unlink(); }
1319 void InitializeAsFirst(HBasicBlock* block) {
1320 ASSERT(!IsLinked());
1324 void PrintMnemonicTo(StringStream* stream);
1326 HInstruction* next_;
1327 HInstruction* previous_;
1328 HPositionInfo position_;
1330 friend class HBasicBlock;
1335 class HTemplateInstruction : public HInstruction {
1337 virtual int OperandCount() V8_FINAL V8_OVERRIDE { return V; }
1338 virtual HValue* OperandAt(int i) const V8_FINAL V8_OVERRIDE {
1343 HTemplateInstruction(HType type = HType::Tagged()) : HInstruction(type) {}
1345 virtual void InternalSetOperandAt(int i, HValue* value) V8_FINAL V8_OVERRIDE {
1350 EmbeddedContainer<HValue*, V> inputs_;
1354 class HControlInstruction : public HInstruction {
1356 virtual HBasicBlock* SuccessorAt(int i) = 0;
1357 virtual int SuccessorCount() = 0;
1358 virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
1360 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1362 virtual bool KnownSuccessorBlock(HBasicBlock** block) {
1367 HBasicBlock* FirstSuccessor() {
1368 return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
1370 HBasicBlock* SecondSuccessor() {
1371 return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
1375 HBasicBlock* swap = SuccessorAt(0);
1376 SetSuccessorAt(0, SuccessorAt(1));
1377 SetSuccessorAt(1, swap);
1380 DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
1384 class HSuccessorIterator V8_FINAL BASE_EMBEDDED {
1386 explicit HSuccessorIterator(HControlInstruction* instr)
1387 : instr_(instr), current_(0) { }
1389 bool Done() { return current_ >= instr_->SuccessorCount(); }
1390 HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
1391 void Advance() { current_++; }
1394 HControlInstruction* instr_;
1399 template<int S, int V>
1400 class HTemplateControlInstruction : public HControlInstruction {
1402 int SuccessorCount() V8_OVERRIDE { return S; }
1403 HBasicBlock* SuccessorAt(int i) V8_OVERRIDE { return successors_[i]; }
1404 void SetSuccessorAt(int i, HBasicBlock* block) V8_OVERRIDE {
1405 successors_[i] = block;
1408 int OperandCount() V8_OVERRIDE { return V; }
1409 HValue* OperandAt(int i) const V8_OVERRIDE { return inputs_[i]; }
1413 void InternalSetOperandAt(int i, HValue* value) V8_OVERRIDE {
1418 EmbeddedContainer<HBasicBlock*, S> successors_;
1419 EmbeddedContainer<HValue*, V> inputs_;
1423 class HBlockEntry V8_FINAL : public HTemplateInstruction<0> {
1425 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1426 return Representation::None();
1429 DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
1433 class HDummyUse V8_FINAL : public HTemplateInstruction<1> {
1435 explicit HDummyUse(HValue* value)
1436 : HTemplateInstruction<1>(HType::Smi()) {
1437 SetOperandAt(0, value);
1438 // Pretend to be a Smi so that the HChange instructions inserted
1439 // before any use generate as little code as possible.
1440 set_representation(Representation::Tagged());
1443 HValue* value() { return OperandAt(0); }
1445 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
1446 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1447 return Representation::None();
1450 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1452 DECLARE_CONCRETE_INSTRUCTION(DummyUse);
1456 // Inserts an int3/stop break instruction for debugging purposes.
1457 class HDebugBreak V8_FINAL : public HTemplateInstruction<0> {
1459 DECLARE_INSTRUCTION_FACTORY_P0(HDebugBreak);
1461 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1462 return Representation::None();
1465 DECLARE_CONCRETE_INSTRUCTION(DebugBreak)
1469 class HGoto V8_FINAL : public HTemplateControlInstruction<1, 0> {
1471 explicit HGoto(HBasicBlock* target) {
1472 SetSuccessorAt(0, target);
1475 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE {
1476 *block = FirstSuccessor();
1480 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1481 return Representation::None();
1484 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1486 DECLARE_CONCRETE_INSTRUCTION(Goto)
1490 class HDeoptimize V8_FINAL : public HTemplateControlInstruction<1, 0> {
1492 static HDeoptimize* New(Zone* zone,
1495 Deoptimizer::BailoutType type,
1496 HBasicBlock* unreachable_continuation) {
1497 return new(zone) HDeoptimize(reason, type, unreachable_continuation);
1500 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE {
1505 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1506 return Representation::None();
1509 const char* reason() const { return reason_; }
1510 Deoptimizer::BailoutType type() { return type_; }
1512 DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
1515 explicit HDeoptimize(const char* reason,
1516 Deoptimizer::BailoutType type,
1517 HBasicBlock* unreachable_continuation)
1518 : reason_(reason), type_(type) {
1519 SetSuccessorAt(0, unreachable_continuation);
1522 const char* reason_;
1523 Deoptimizer::BailoutType type_;
1527 class HUnaryControlInstruction : public HTemplateControlInstruction<2, 1> {
1529 HUnaryControlInstruction(HValue* value,
1530 HBasicBlock* true_target,
1531 HBasicBlock* false_target) {
1532 SetOperandAt(0, value);
1533 SetSuccessorAt(0, true_target);
1534 SetSuccessorAt(1, false_target);
1537 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1539 HValue* value() { return OperandAt(0); }
1543 class HBranch V8_FINAL : public HUnaryControlInstruction {
1545 DECLARE_INSTRUCTION_FACTORY_P1(HBranch, HValue*);
1546 DECLARE_INSTRUCTION_FACTORY_P2(HBranch, HValue*,
1547 ToBooleanStub::Types);
1548 DECLARE_INSTRUCTION_FACTORY_P4(HBranch, HValue*,
1549 ToBooleanStub::Types,
1550 HBasicBlock*, HBasicBlock*);
1552 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1553 return Representation::None();
1555 virtual Representation observed_input_representation(int index) V8_OVERRIDE;
1557 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
1559 ToBooleanStub::Types expected_input_types() const {
1560 return expected_input_types_;
1563 DECLARE_CONCRETE_INSTRUCTION(Branch)
1566 HBranch(HValue* value,
1567 ToBooleanStub::Types expected_input_types = ToBooleanStub::Types(),
1568 HBasicBlock* true_target = NULL,
1569 HBasicBlock* false_target = NULL)
1570 : HUnaryControlInstruction(value, true_target, false_target),
1571 expected_input_types_(expected_input_types) {
1572 SetFlag(kAllowUndefinedAsNaN);
1575 ToBooleanStub::Types expected_input_types_;
1579 class HCompareMap V8_FINAL : public HUnaryControlInstruction {
1581 DECLARE_INSTRUCTION_FACTORY_P2(HCompareMap, HValue*, Handle<Map>);
1582 DECLARE_INSTRUCTION_FACTORY_P4(HCompareMap, HValue*, Handle<Map>,
1583 HBasicBlock*, HBasicBlock*);
1585 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE {
1586 if (known_successor_index() != kNoKnownSuccessorIndex) {
1587 *block = SuccessorAt(known_successor_index());
1594 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1596 static const int kNoKnownSuccessorIndex = -1;
1597 int known_successor_index() const { return known_successor_index_; }
1598 void set_known_successor_index(int known_successor_index) {
1599 known_successor_index_ = known_successor_index;
1602 Unique<Map> map() const { return map_; }
1604 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1605 return Representation::Tagged();
1608 DECLARE_CONCRETE_INSTRUCTION(CompareMap)
1611 virtual int RedefinedOperandIndex() { return 0; }
1614 HCompareMap(HValue* value,
1616 HBasicBlock* true_target = NULL,
1617 HBasicBlock* false_target = NULL)
1618 : HUnaryControlInstruction(value, true_target, false_target),
1619 known_successor_index_(kNoKnownSuccessorIndex), map_(Unique<Map>(map)) {
1620 ASSERT(!map.is_null());
1621 set_representation(Representation::Tagged());
1624 int known_successor_index_;
1629 class HContext V8_FINAL : public HTemplateInstruction<0> {
1631 static HContext* New(Zone* zone) {
1632 return new(zone) HContext();
1635 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1636 return Representation::None();
1639 DECLARE_CONCRETE_INSTRUCTION(Context)
1642 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1646 set_representation(Representation::Tagged());
1650 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1654 class HReturn V8_FINAL : public HTemplateControlInstruction<0, 3> {
1656 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HReturn, HValue*, HValue*);
1657 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HReturn, HValue*);
1659 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1660 // TODO(titzer): require an Int32 input for faster returns.
1661 if (index == 2) return Representation::Smi();
1662 return Representation::Tagged();
1665 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1667 HValue* value() { return OperandAt(0); }
1668 HValue* context() { return OperandAt(1); }
1669 HValue* parameter_count() { return OperandAt(2); }
1671 DECLARE_CONCRETE_INSTRUCTION(Return)
1674 HReturn(HValue* context, HValue* value, HValue* parameter_count = 0) {
1675 SetOperandAt(0, value);
1676 SetOperandAt(1, context);
1677 SetOperandAt(2, parameter_count);
1682 class HAbnormalExit V8_FINAL : public HTemplateControlInstruction<0, 0> {
1684 DECLARE_INSTRUCTION_FACTORY_P0(HAbnormalExit);
1686 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1687 return Representation::None();
1690 DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
1696 class HUnaryOperation : public HTemplateInstruction<1> {
1698 HUnaryOperation(HValue* value, HType type = HType::Tagged())
1699 : HTemplateInstruction<1>(type) {
1700 SetOperandAt(0, value);
1703 static HUnaryOperation* cast(HValue* value) {
1704 return reinterpret_cast<HUnaryOperation*>(value);
1707 HValue* value() const { return OperandAt(0); }
1708 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1712 class HUseConst V8_FINAL : public HUnaryOperation {
1714 DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue*);
1716 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1717 return Representation::None();
1720 DECLARE_CONCRETE_INSTRUCTION(UseConst)
1723 explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
1727 class HForceRepresentation V8_FINAL : public HTemplateInstruction<1> {
1729 static HInstruction* New(Zone* zone, HValue* context, HValue* value,
1730 Representation required_representation);
1732 HValue* value() { return OperandAt(0); }
1734 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1735 return representation(); // Same as the output representation.
1738 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1740 DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
1743 HForceRepresentation(HValue* value, Representation required_representation) {
1744 SetOperandAt(0, value);
1745 set_representation(required_representation);
1750 class HChange V8_FINAL : public HUnaryOperation {
1752 HChange(HValue* value,
1754 bool is_truncating_to_smi,
1755 bool is_truncating_to_int32)
1756 : HUnaryOperation(value) {
1757 ASSERT(!value->representation().IsNone());
1758 ASSERT(!to.IsNone());
1759 ASSERT(!value->representation().Equals(to));
1760 set_representation(to);
1762 SetFlag(kCanOverflow);
1763 if (is_truncating_to_smi) {
1764 SetFlag(kTruncatingToSmi);
1765 SetFlag(kTruncatingToInt32);
1767 if (is_truncating_to_int32) SetFlag(kTruncatingToInt32);
1768 if (value->representation().IsSmi() || value->type().IsSmi()) {
1769 set_type(HType::Smi());
1771 if (to.IsFloat32x4()) {
1772 set_type(HType::Float32x4());
1773 } else if (to.IsInt32x4()) {
1774 set_type(HType::Int32x4());
1776 set_type(HType::TaggedNumber());
1778 if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
1782 bool can_convert_undefined_to_nan() {
1783 return CheckUsesForFlag(kAllowUndefinedAsNaN);
1786 virtual HType CalculateInferredType() V8_OVERRIDE;
1787 virtual HValue* Canonicalize() V8_OVERRIDE;
1789 Representation from() const { return value()->representation(); }
1790 Representation to() const { return representation(); }
1791 bool deoptimize_on_minus_zero() const {
1792 return CheckFlag(kBailoutOnMinusZero);
1794 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1798 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
1800 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1802 DECLARE_CONCRETE_INSTRUCTION(Change)
1805 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1808 virtual bool IsDeletable() const V8_OVERRIDE {
1809 return !from().IsTagged() || value()->type().IsSmi();
1814 class HClampToUint8 V8_FINAL : public HUnaryOperation {
1816 DECLARE_INSTRUCTION_FACTORY_P1(HClampToUint8, HValue*);
1818 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1819 return Representation::None();
1822 DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
1825 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1828 explicit HClampToUint8(HValue* value)
1829 : HUnaryOperation(value) {
1830 set_representation(Representation::Integer32());
1831 SetFlag(kAllowUndefinedAsNaN);
1835 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1839 class HDoubleBits V8_FINAL : public HUnaryOperation {
1841 enum Bits { HIGH, LOW };
1842 DECLARE_INSTRUCTION_FACTORY_P2(HDoubleBits, HValue*, Bits);
1844 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1845 return Representation::Double();
1848 DECLARE_CONCRETE_INSTRUCTION(DoubleBits)
1850 Bits bits() { return bits_; }
1853 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
1854 return other->IsDoubleBits() && HDoubleBits::cast(other)->bits() == bits();
1858 HDoubleBits(HValue* value, Bits bits)
1859 : HUnaryOperation(value), bits_(bits) {
1860 set_representation(Representation::Integer32());
1864 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1870 class HConstructDouble V8_FINAL : public HTemplateInstruction<2> {
1872 DECLARE_INSTRUCTION_FACTORY_P2(HConstructDouble, HValue*, HValue*);
1874 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1875 return Representation::Integer32();
1878 DECLARE_CONCRETE_INSTRUCTION(ConstructDouble)
1880 HValue* hi() { return OperandAt(0); }
1881 HValue* lo() { return OperandAt(1); }
1884 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1887 explicit HConstructDouble(HValue* hi, HValue* lo) {
1888 set_representation(Representation::Double());
1890 SetOperandAt(0, hi);
1891 SetOperandAt(1, lo);
1894 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1898 enum RemovableSimulate {
1904 class HSimulate V8_FINAL : public HInstruction {
1906 HSimulate(BailoutId ast_id,
1909 RemovableSimulate removable)
1911 pop_count_(pop_count),
1913 assigned_indexes_(2, zone),
1915 removable_(removable),
1916 done_with_replay_(false) {}
1919 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1921 bool HasAstId() const { return !ast_id_.IsNone(); }
1922 BailoutId ast_id() const { return ast_id_; }
1923 void set_ast_id(BailoutId id) {
1924 ASSERT(!HasAstId());
1928 int pop_count() const { return pop_count_; }
1929 const ZoneList<HValue*>* values() const { return &values_; }
1930 int GetAssignedIndexAt(int index) const {
1931 ASSERT(HasAssignedIndexAt(index));
1932 return assigned_indexes_[index];
1934 bool HasAssignedIndexAt(int index) const {
1935 return assigned_indexes_[index] != kNoIndex;
1937 void AddAssignedValue(int index, HValue* value) {
1938 AddValue(index, value);
1940 void AddPushedValue(HValue* value) {
1941 AddValue(kNoIndex, value);
1943 int ToOperandIndex(int environment_index) {
1944 for (int i = 0; i < assigned_indexes_.length(); ++i) {
1945 if (assigned_indexes_[i] == environment_index) return i;
1949 virtual int OperandCount() V8_OVERRIDE { return values_.length(); }
1950 virtual HValue* OperandAt(int index) const V8_OVERRIDE {
1951 return values_[index];
1954 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
1955 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1956 return Representation::None();
1959 void MergeWith(ZoneList<HSimulate*>* list);
1960 bool is_candidate_for_removal() { return removable_ == REMOVABLE_SIMULATE; }
1962 // Replay effects of this instruction on the given environment.
1963 void ReplayEnvironment(HEnvironment* env);
1965 DECLARE_CONCRETE_INSTRUCTION(Simulate)
1968 virtual void Verify() V8_OVERRIDE;
1969 void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
1970 Handle<JSFunction> closure() const { return closure_; }
1974 virtual void InternalSetOperandAt(int index, HValue* value) V8_OVERRIDE {
1975 values_[index] = value;
1979 static const int kNoIndex = -1;
1980 void AddValue(int index, HValue* value) {
1981 assigned_indexes_.Add(index, zone_);
1982 // Resize the list of pushed values.
1983 values_.Add(NULL, zone_);
1984 // Set the operand through the base method in HValue to make sure that the
1985 // use lists are correctly updated.
1986 SetOperandAt(values_.length() - 1, value);
1988 bool HasValueForIndex(int index) {
1989 for (int i = 0; i < assigned_indexes_.length(); ++i) {
1990 if (assigned_indexes_[i] == index) return true;
1996 ZoneList<HValue*> values_;
1997 ZoneList<int> assigned_indexes_;
1999 RemovableSimulate removable_ : 2;
2000 bool done_with_replay_ : 1;
2003 Handle<JSFunction> closure_;
2008 class HEnvironmentMarker V8_FINAL : public HTemplateInstruction<1> {
2010 enum Kind { BIND, LOOKUP };
2012 DECLARE_INSTRUCTION_FACTORY_P2(HEnvironmentMarker, Kind, int);
2014 Kind kind() { return kind_; }
2015 int index() { return index_; }
2016 HSimulate* next_simulate() { return next_simulate_; }
2017 void set_next_simulate(HSimulate* simulate) {
2018 next_simulate_ = simulate;
2021 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2022 return Representation::None();
2025 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2028 void set_closure(Handle<JSFunction> closure) {
2029 ASSERT(closure_.is_null());
2030 ASSERT(!closure.is_null());
2033 Handle<JSFunction> closure() const { return closure_; }
2036 DECLARE_CONCRETE_INSTRUCTION(EnvironmentMarker);
2039 HEnvironmentMarker(Kind kind, int index)
2040 : kind_(kind), index_(index), next_simulate_(NULL) { }
2044 HSimulate* next_simulate_;
2047 Handle<JSFunction> closure_;
2052 class HStackCheck V8_FINAL : public HTemplateInstruction<1> {
2059 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HStackCheck, Type);
2061 HValue* context() { return OperandAt(0); }
2063 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2064 return Representation::Tagged();
2068 // The stack check eliminator might try to eliminate the same stack
2069 // check instruction multiple times.
2071 DeleteAndReplaceWith(NULL);
2075 bool is_function_entry() { return type_ == kFunctionEntry; }
2076 bool is_backwards_branch() { return type_ == kBackwardsBranch; }
2078 DECLARE_CONCRETE_INSTRUCTION(StackCheck)
2081 HStackCheck(HValue* context, Type type) : type_(type) {
2082 SetOperandAt(0, context);
2083 SetChangesFlag(kNewSpacePromotion);
2091 NORMAL_RETURN, // Drop the function from the environment on return.
2092 CONSTRUCT_CALL_RETURN, // Either use allocated receiver or return value.
2093 GETTER_CALL_RETURN, // Returning from a getter, need to restore context.
2094 SETTER_CALL_RETURN // Use the RHS of the assignment as the return value.
2098 class HArgumentsObject;
2101 class HEnterInlined V8_FINAL : public HTemplateInstruction<0> {
2103 static HEnterInlined* New(Zone* zone,
2105 Handle<JSFunction> closure,
2106 int arguments_count,
2107 FunctionLiteral* function,
2108 InliningKind inlining_kind,
2109 Variable* arguments_var,
2110 HArgumentsObject* arguments_object) {
2111 return new(zone) HEnterInlined(closure, arguments_count, function,
2112 inlining_kind, arguments_var,
2113 arguments_object, zone);
2116 void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
2117 ZoneList<HBasicBlock*>* return_targets() { return &return_targets_; }
2119 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2121 Handle<JSFunction> closure() const { return closure_; }
2122 int arguments_count() const { return arguments_count_; }
2123 bool arguments_pushed() const { return arguments_pushed_; }
2124 void set_arguments_pushed() { arguments_pushed_ = true; }
2125 FunctionLiteral* function() const { return function_; }
2126 InliningKind inlining_kind() const { return inlining_kind_; }
2128 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2129 return Representation::None();
2132 Variable* arguments_var() { return arguments_var_; }
2133 HArgumentsObject* arguments_object() { return arguments_object_; }
2135 DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
2138 HEnterInlined(Handle<JSFunction> closure,
2139 int arguments_count,
2140 FunctionLiteral* function,
2141 InliningKind inlining_kind,
2142 Variable* arguments_var,
2143 HArgumentsObject* arguments_object,
2145 : closure_(closure),
2146 arguments_count_(arguments_count),
2147 arguments_pushed_(false),
2148 function_(function),
2149 inlining_kind_(inlining_kind),
2150 arguments_var_(arguments_var),
2151 arguments_object_(arguments_object),
2152 return_targets_(2, zone) {
2155 Handle<JSFunction> closure_;
2156 int arguments_count_;
2157 bool arguments_pushed_;
2158 FunctionLiteral* function_;
2159 InliningKind inlining_kind_;
2160 Variable* arguments_var_;
2161 HArgumentsObject* arguments_object_;
2162 ZoneList<HBasicBlock*> return_targets_;
2166 class HLeaveInlined V8_FINAL : public HTemplateInstruction<0> {
2168 HLeaveInlined(HEnterInlined* entry,
2171 drop_count_(drop_count) { }
2173 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2174 return Representation::None();
2177 virtual int argument_delta() const V8_OVERRIDE {
2178 return entry_->arguments_pushed() ? -drop_count_ : 0;
2181 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
2184 HEnterInlined* entry_;
2189 class HPushArgument V8_FINAL : public HUnaryOperation {
2191 DECLARE_INSTRUCTION_FACTORY_P1(HPushArgument, HValue*);
2193 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2194 return Representation::Tagged();
2197 virtual int argument_delta() const V8_OVERRIDE { return 1; }
2198 HValue* argument() { return OperandAt(0); }
2200 DECLARE_CONCRETE_INSTRUCTION(PushArgument)
2203 explicit HPushArgument(HValue* value) : HUnaryOperation(value) {
2204 set_representation(Representation::Tagged());
2209 class HThisFunction V8_FINAL : public HTemplateInstruction<0> {
2211 DECLARE_INSTRUCTION_FACTORY_P0(HThisFunction);
2213 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2214 return Representation::None();
2217 DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
2220 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2224 set_representation(Representation::Tagged());
2228 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2232 class HDeclareGlobals V8_FINAL : public HUnaryOperation {
2234 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HDeclareGlobals,
2238 HValue* context() { return OperandAt(0); }
2239 Handle<FixedArray> pairs() const { return pairs_; }
2240 int flags() const { return flags_; }
2242 DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
2244 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2245 return Representation::Tagged();
2249 HDeclareGlobals(HValue* context,
2250 Handle<FixedArray> pairs,
2252 : HUnaryOperation(context),
2255 set_representation(Representation::Tagged());
2256 SetAllSideEffects();
2259 Handle<FixedArray> pairs_;
2265 class HCall : public HTemplateInstruction<V> {
2267 // The argument count includes the receiver.
2268 explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
2269 this->set_representation(Representation::Tagged());
2270 this->SetAllSideEffects();
2273 virtual HType CalculateInferredType() V8_FINAL V8_OVERRIDE {
2274 return HType::Tagged();
2277 virtual int argument_count() const {
2278 return argument_count_;
2281 virtual int argument_delta() const V8_OVERRIDE {
2282 return -argument_count();
2286 int argument_count_;
2290 class HUnaryCall : public HCall<1> {
2292 HUnaryCall(HValue* value, int argument_count)
2293 : HCall<1>(argument_count) {
2294 SetOperandAt(0, value);
2297 virtual Representation RequiredInputRepresentation(
2298 int index) V8_FINAL V8_OVERRIDE {
2299 return Representation::Tagged();
2302 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2304 HValue* value() { return OperandAt(0); }
2308 class HBinaryCall : public HCall<2> {
2310 HBinaryCall(HValue* first, HValue* second, int argument_count)
2311 : HCall<2>(argument_count) {
2312 SetOperandAt(0, first);
2313 SetOperandAt(1, second);
2316 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2318 virtual Representation RequiredInputRepresentation(
2319 int index) V8_FINAL V8_OVERRIDE {
2320 return Representation::Tagged();
2323 HValue* first() { return OperandAt(0); }
2324 HValue* second() { return OperandAt(1); }
2328 class HCallJSFunction V8_FINAL : public HCall<1> {
2330 static HCallJSFunction* New(Zone* zone,
2334 bool pass_argument_count);
2336 HValue* function() { return OperandAt(0); }
2338 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2340 virtual Representation RequiredInputRepresentation(
2341 int index) V8_FINAL V8_OVERRIDE {
2343 return Representation::Tagged();
2346 bool pass_argument_count() const { return pass_argument_count_; }
2348 virtual bool HasStackCheck() V8_FINAL V8_OVERRIDE {
2349 return has_stack_check_;
2352 DECLARE_CONCRETE_INSTRUCTION(CallJSFunction)
2355 // The argument count includes the receiver.
2356 HCallJSFunction(HValue* function,
2358 bool pass_argument_count,
2359 bool has_stack_check)
2360 : HCall<1>(argument_count),
2361 pass_argument_count_(pass_argument_count),
2362 has_stack_check_(has_stack_check) {
2363 SetOperandAt(0, function);
2366 bool pass_argument_count_;
2367 bool has_stack_check_;
2371 class HCallWithDescriptor V8_FINAL : public HInstruction {
2373 static HCallWithDescriptor* New(Zone* zone, HValue* context,
2376 const CallInterfaceDescriptor* descriptor,
2377 Vector<HValue*>& operands) {
2378 ASSERT(operands.length() == descriptor->environment_length());
2379 HCallWithDescriptor* res =
2380 new(zone) HCallWithDescriptor(target, argument_count,
2381 descriptor, operands, zone);
2385 virtual int OperandCount() V8_FINAL V8_OVERRIDE { return values_.length(); }
2386 virtual HValue* OperandAt(int index) const V8_FINAL V8_OVERRIDE {
2387 return values_[index];
2390 virtual Representation RequiredInputRepresentation(
2391 int index) V8_FINAL V8_OVERRIDE {
2393 return Representation::Tagged();
2395 int par_index = index - 1;
2396 ASSERT(par_index < descriptor_->environment_length());
2397 return descriptor_->GetParameterRepresentation(par_index);
2401 DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor)
2403 virtual HType CalculateInferredType() V8_FINAL V8_OVERRIDE {
2404 return HType::Tagged();
2407 virtual int argument_count() const {
2408 return argument_count_;
2411 virtual int argument_delta() const V8_OVERRIDE {
2412 return -argument_count_;
2415 const CallInterfaceDescriptor* descriptor() const {
2420 return OperandAt(0);
2423 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2426 // The argument count includes the receiver.
2427 HCallWithDescriptor(HValue* target,
2429 const CallInterfaceDescriptor* descriptor,
2430 Vector<HValue*>& operands,
2432 : descriptor_(descriptor),
2433 values_(descriptor->environment_length() + 1, zone) {
2434 argument_count_ = argument_count;
2435 AddOperand(target, zone);
2436 for (int i = 0; i < operands.length(); i++) {
2437 AddOperand(operands[i], zone);
2439 this->set_representation(Representation::Tagged());
2440 this->SetAllSideEffects();
2443 void AddOperand(HValue* v, Zone* zone) {
2444 values_.Add(NULL, zone);
2445 SetOperandAt(values_.length() - 1, v);
2448 void InternalSetOperandAt(int index,
2449 HValue* value) V8_FINAL V8_OVERRIDE {
2450 values_[index] = value;
2453 const CallInterfaceDescriptor* descriptor_;
2454 ZoneList<HValue*> values_;
2455 int argument_count_;
2459 class HInvokeFunction V8_FINAL : public HBinaryCall {
2461 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInvokeFunction, HValue*, int);
2463 HInvokeFunction(HValue* context,
2465 Handle<JSFunction> known_function,
2467 : HBinaryCall(context, function, argument_count),
2468 known_function_(known_function) {
2469 formal_parameter_count_ = known_function.is_null()
2470 ? 0 : known_function->shared()->formal_parameter_count();
2471 has_stack_check_ = !known_function.is_null() &&
2472 (known_function->code()->kind() == Code::FUNCTION ||
2473 known_function->code()->kind() == Code::OPTIMIZED_FUNCTION);
2476 static HInvokeFunction* New(Zone* zone,
2479 Handle<JSFunction> known_function,
2480 int argument_count) {
2481 return new(zone) HInvokeFunction(context, function,
2482 known_function, argument_count);
2485 HValue* context() { return first(); }
2486 HValue* function() { return second(); }
2487 Handle<JSFunction> known_function() { return known_function_; }
2488 int formal_parameter_count() const { return formal_parameter_count_; }
2490 virtual bool HasStackCheck() V8_FINAL V8_OVERRIDE {
2491 return has_stack_check_;
2494 DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
2497 HInvokeFunction(HValue* context, HValue* function, int argument_count)
2498 : HBinaryCall(context, function, argument_count),
2499 has_stack_check_(false) {
2502 Handle<JSFunction> known_function_;
2503 int formal_parameter_count_;
2504 bool has_stack_check_;
2508 class HCallFunction V8_FINAL : public HBinaryCall {
2510 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallFunction, HValue*, int);
2511 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(
2512 HCallFunction, HValue*, int, CallFunctionFlags);
2514 HValue* context() { return first(); }
2515 HValue* function() { return second(); }
2516 CallFunctionFlags function_flags() const { return function_flags_; }
2518 DECLARE_CONCRETE_INSTRUCTION(CallFunction)
2520 virtual int argument_delta() const V8_OVERRIDE { return -argument_count(); }
2523 HCallFunction(HValue* context,
2526 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS)
2527 : HBinaryCall(context, function, argument_count), function_flags_(flags) {
2529 CallFunctionFlags function_flags_;
2533 class HCallNew V8_FINAL : public HBinaryCall {
2535 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallNew, HValue*, int);
2537 HValue* context() { return first(); }
2538 HValue* constructor() { return second(); }
2540 DECLARE_CONCRETE_INSTRUCTION(CallNew)
2543 HCallNew(HValue* context, HValue* constructor, int argument_count)
2544 : HBinaryCall(context, constructor, argument_count) {}
2548 class HCallNewArray V8_FINAL : public HBinaryCall {
2550 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCallNewArray,
2555 HValue* context() { return first(); }
2556 HValue* constructor() { return second(); }
2558 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2560 ElementsKind elements_kind() const { return elements_kind_; }
2562 DECLARE_CONCRETE_INSTRUCTION(CallNewArray)
2565 HCallNewArray(HValue* context, HValue* constructor, int argument_count,
2566 ElementsKind elements_kind)
2567 : HBinaryCall(context, constructor, argument_count),
2568 elements_kind_(elements_kind) {}
2570 ElementsKind elements_kind_;
2574 class HCallRuntime V8_FINAL : public HCall<1> {
2576 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCallRuntime,
2578 const Runtime::Function*,
2581 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2583 HValue* context() { return OperandAt(0); }
2584 const Runtime::Function* function() const { return c_function_; }
2585 Handle<String> name() const { return name_; }
2586 SaveFPRegsMode save_doubles() const { return save_doubles_; }
2587 void set_save_doubles(SaveFPRegsMode save_doubles) {
2588 save_doubles_ = save_doubles;
2591 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2592 return Representation::Tagged();
2595 DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
2598 HCallRuntime(HValue* context,
2599 Handle<String> name,
2600 const Runtime::Function* c_function,
2602 : HCall<1>(argument_count), c_function_(c_function), name_(name),
2603 save_doubles_(kDontSaveFPRegs) {
2604 SetOperandAt(0, context);
2607 const Runtime::Function* c_function_;
2608 Handle<String> name_;
2609 SaveFPRegsMode save_doubles_;
2613 class HMapEnumLength V8_FINAL : public HUnaryOperation {
2615 DECLARE_INSTRUCTION_FACTORY_P1(HMapEnumLength, HValue*);
2617 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2618 return Representation::Tagged();
2621 DECLARE_CONCRETE_INSTRUCTION(MapEnumLength)
2624 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2627 explicit HMapEnumLength(HValue* value)
2628 : HUnaryOperation(value, HType::Smi()) {
2629 set_representation(Representation::Smi());
2631 SetDependsOnFlag(kMaps);
2634 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2638 class HUnaryMathOperation V8_FINAL : public HTemplateInstruction<2> {
2640 static HInstruction* New(Zone* zone,
2643 BuiltinFunctionId op);
2645 HValue* context() { return OperandAt(0); }
2646 HValue* value() { return OperandAt(1); }
2648 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2650 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2652 return Representation::Tagged();
2661 return Representation::Double();
2663 return representation();
2665 return Representation::Integer32();
2668 return Representation::None();
2673 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
2675 virtual HValue* Canonicalize() V8_OVERRIDE;
2676 virtual Representation RepresentationFromInputs() V8_OVERRIDE;
2678 BuiltinFunctionId op() const { return op_; }
2679 const char* OpName() const;
2681 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
2684 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2685 HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
2686 return op_ == b->op();
2690 HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
2691 : HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
2692 SetOperandAt(0, context);
2693 SetOperandAt(1, value);
2698 set_representation(Representation::Integer32());
2701 // Not setting representation here: it is None intentionally.
2702 SetFlag(kFlexibleRepresentation);
2703 // TODO(svenpanne) This flag is actually only needed if representation()
2704 // is tagged, and not when it is an unboxed double or unboxed integer.
2705 SetChangesFlag(kNewSpacePromotion);
2711 set_representation(Representation::Double());
2717 SetFlag(kAllowUndefinedAsNaN);
2720 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2722 HValue* SimplifiedDividendForMathFloorOfDiv(HDiv* hdiv);
2723 HValue* SimplifiedDivisorForMathFloorOfDiv(HDiv* hdiv);
2725 BuiltinFunctionId op_;
2729 class HLoadRoot V8_FINAL : public HTemplateInstruction<0> {
2731 DECLARE_INSTRUCTION_FACTORY_P1(HLoadRoot, Heap::RootListIndex);
2732 DECLARE_INSTRUCTION_FACTORY_P2(HLoadRoot, Heap::RootListIndex, HType);
2734 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2735 return Representation::None();
2738 Heap::RootListIndex index() const { return index_; }
2740 DECLARE_CONCRETE_INSTRUCTION(LoadRoot)
2743 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2744 HLoadRoot* b = HLoadRoot::cast(other);
2745 return index_ == b->index_;
2749 HLoadRoot(Heap::RootListIndex index, HType type = HType::Tagged())
2750 : HTemplateInstruction<0>(type), index_(index) {
2752 // TODO(bmeurer): We'll need kDependsOnRoots once we add the
2753 // corresponding HStoreRoot instruction.
2754 SetDependsOnFlag(kCalls);
2757 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2759 const Heap::RootListIndex index_;
2763 class HCheckMaps V8_FINAL : public HTemplateInstruction<2> {
2765 static HCheckMaps* New(Zone* zone, HValue* context, HValue* value,
2766 Handle<Map> map, CompilationInfo* info,
2767 HValue* typecheck = NULL);
2768 static HCheckMaps* New(Zone* zone, HValue* context,
2769 HValue* value, SmallMapList* maps,
2770 HValue* typecheck = NULL) {
2771 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck);
2772 for (int i = 0; i < maps->length(); i++) {
2773 check_map->Add(maps->at(i), zone);
2778 bool CanOmitMapChecks() { return omit_; }
2780 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
2781 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2782 return Representation::Tagged();
2784 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
2785 HValue* dominator) V8_OVERRIDE;
2786 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2788 HValue* value() { return OperandAt(0); }
2789 HValue* typecheck() { return OperandAt(1); }
2791 Unique<Map> first_map() const { return map_set_.at(0); }
2792 UniqueSet<Map> map_set() const { return map_set_; }
2794 void set_map_set(UniqueSet<Map>* maps, Zone *zone) {
2796 for (int i = 0; i < maps->size(); i++) {
2797 map_set_.Add(maps->at(i), zone);
2801 bool has_migration_target() const {
2802 return has_migration_target_;
2805 DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
2808 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2809 return this->map_set_.Equals(&HCheckMaps::cast(other)->map_set_);
2812 virtual int RedefinedOperandIndex() { return 0; }
2815 void Add(Handle<Map> map, Zone* zone) {
2816 map_set_.Add(Unique<Map>(map), zone);
2817 SetDependsOnFlag(kMaps);
2818 SetDependsOnFlag(kElementsKind);
2820 if (!has_migration_target_ && map->is_migration_target()) {
2821 has_migration_target_ = true;
2822 SetChangesFlag(kNewSpacePromotion);
2826 // Clients should use one of the static New* methods above.
2827 HCheckMaps(HValue* value, Zone *zone, HValue* typecheck)
2828 : HTemplateInstruction<2>(value->type()),
2829 omit_(false), has_migration_target_(false) {
2830 SetOperandAt(0, value);
2831 // Use the object value for the dependency if NULL is passed.
2832 SetOperandAt(1, typecheck != NULL ? typecheck : value);
2833 set_representation(Representation::Tagged());
2835 SetFlag(kTrackSideEffectDominators);
2839 bool has_migration_target_;
2840 UniqueSet<Map> map_set_;
2844 class HCheckValue V8_FINAL : public HUnaryOperation {
2846 static HCheckValue* New(Zone* zone, HValue* context,
2847 HValue* value, Handle<JSFunction> func) {
2848 bool in_new_space = zone->isolate()->heap()->InNewSpace(*func);
2849 // NOTE: We create an uninitialized Unique and initialize it later.
2850 // This is because a JSFunction can move due to GC during graph creation.
2851 // TODO(titzer): This is a migration crutch. Replace with some kind of
2852 // Uniqueness scope later.
2853 Unique<JSFunction> target = Unique<JSFunction>::CreateUninitialized(func);
2854 HCheckValue* check = new(zone) HCheckValue(value, target, in_new_space);
2857 static HCheckValue* New(Zone* zone, HValue* context,
2858 HValue* value, Unique<HeapObject> target,
2859 bool object_in_new_space) {
2860 return new(zone) HCheckValue(value, target, object_in_new_space);
2863 virtual void FinalizeUniqueness() V8_OVERRIDE {
2864 object_ = Unique<HeapObject>(object_.handle());
2867 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2868 return Representation::Tagged();
2870 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2872 virtual HValue* Canonicalize() V8_OVERRIDE;
2875 virtual void Verify() V8_OVERRIDE;
2878 Unique<HeapObject> object() const { return object_; }
2879 bool object_in_new_space() const { return object_in_new_space_; }
2881 DECLARE_CONCRETE_INSTRUCTION(CheckValue)
2884 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2885 HCheckValue* b = HCheckValue::cast(other);
2886 return object_ == b->object_;
2890 HCheckValue(HValue* value, Unique<HeapObject> object,
2891 bool object_in_new_space)
2892 : HUnaryOperation(value, value->type()),
2894 object_in_new_space_(object_in_new_space) {
2895 set_representation(Representation::Tagged());
2899 Unique<HeapObject> object_;
2900 bool object_in_new_space_;
2904 class HCheckInstanceType V8_FINAL : public HUnaryOperation {
2910 IS_INTERNALIZED_STRING,
2911 LAST_INTERVAL_CHECK = IS_JS_ARRAY
2914 DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue*, Check);
2916 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2918 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2919 return Representation::Tagged();
2922 virtual HValue* Canonicalize() V8_OVERRIDE;
2924 bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
2925 void GetCheckInterval(InstanceType* first, InstanceType* last);
2926 void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
2928 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
2931 // TODO(ager): It could be nice to allow the ommision of instance
2932 // type checks if we have already performed an instance type check
2933 // with a larger range.
2934 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2935 HCheckInstanceType* b = HCheckInstanceType::cast(other);
2936 return check_ == b->check_;
2939 virtual int RedefinedOperandIndex() { return 0; }
2942 const char* GetCheckName();
2944 HCheckInstanceType(HValue* value, Check check)
2945 : HUnaryOperation(value), check_(check) {
2946 set_representation(Representation::Tagged());
2954 class HCheckSmi V8_FINAL : public HUnaryOperation {
2956 DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue*);
2958 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2959 return Representation::Tagged();
2962 virtual HValue* Canonicalize() V8_OVERRIDE {
2963 HType value_type = value()->type();
2964 if (value_type.IsSmi()) {
2970 DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
2973 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2976 explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
2977 set_representation(Representation::Smi());
2983 class HCheckHeapObject V8_FINAL : public HUnaryOperation {
2985 DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
2987 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
2988 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2989 return Representation::Tagged();
2993 virtual void Verify() V8_OVERRIDE;
2996 virtual HValue* Canonicalize() V8_OVERRIDE {
2997 return value()->type().IsHeapObject() ? NULL : this;
3000 DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
3003 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3006 explicit HCheckHeapObject(HValue* value)
3007 : HUnaryOperation(value, HType::NonPrimitive()) {
3008 set_representation(Representation::Tagged());
3014 class InductionVariableData;
3017 struct InductionVariableLimitUpdate {
3018 InductionVariableData* updated_variable;
3020 bool limit_is_upper;
3021 bool limit_is_included;
3023 InductionVariableLimitUpdate()
3024 : updated_variable(NULL), limit(NULL),
3025 limit_is_upper(false), limit_is_included(false) {}
3035 class InductionVariableData V8_FINAL : public ZoneObject {
3037 class InductionVariableCheck : public ZoneObject {
3039 HBoundsCheck* check() { return check_; }
3040 InductionVariableCheck* next() { return next_; }
3041 bool HasUpperLimit() { return upper_limit_ >= 0; }
3042 int32_t upper_limit() {
3043 ASSERT(HasUpperLimit());
3044 return upper_limit_;
3046 void set_upper_limit(int32_t upper_limit) {
3047 upper_limit_ = upper_limit;
3050 bool processed() { return processed_; }
3051 void set_processed() { processed_ = true; }
3053 InductionVariableCheck(HBoundsCheck* check,
3054 InductionVariableCheck* next,
3055 int32_t upper_limit = kNoLimit)
3056 : check_(check), next_(next), upper_limit_(upper_limit),
3057 processed_(false) {}
3060 HBoundsCheck* check_;
3061 InductionVariableCheck* next_;
3062 int32_t upper_limit_;
3066 class ChecksRelatedToLength : public ZoneObject {
3068 HValue* length() { return length_; }
3069 ChecksRelatedToLength* next() { return next_; }
3070 InductionVariableCheck* checks() { return checks_; }
3072 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3073 void CloseCurrentBlock();
3075 ChecksRelatedToLength(HValue* length, ChecksRelatedToLength* next)
3076 : length_(length), next_(next), checks_(NULL),
3077 first_check_in_block_(NULL),
3079 added_constant_(NULL),
3080 current_and_mask_in_block_(0),
3081 current_or_mask_in_block_(0) {}
3084 void UseNewIndexInCurrentBlock(Token::Value token,
3089 HBoundsCheck* first_check_in_block() { return first_check_in_block_; }
3090 HBitwise* added_index() { return added_index_; }
3091 void set_added_index(HBitwise* index) { added_index_ = index; }
3092 HConstant* added_constant() { return added_constant_; }
3093 void set_added_constant(HConstant* constant) { added_constant_ = constant; }
3094 int32_t current_and_mask_in_block() { return current_and_mask_in_block_; }
3095 int32_t current_or_mask_in_block() { return current_or_mask_in_block_; }
3096 int32_t current_upper_limit() { return current_upper_limit_; }
3099 ChecksRelatedToLength* next_;
3100 InductionVariableCheck* checks_;
3102 HBoundsCheck* first_check_in_block_;
3103 HBitwise* added_index_;
3104 HConstant* added_constant_;
3105 int32_t current_and_mask_in_block_;
3106 int32_t current_or_mask_in_block_;
3107 int32_t current_upper_limit_;
3110 struct LimitFromPredecessorBlock {
3111 InductionVariableData* variable;
3114 HBasicBlock* other_target;
3116 bool LimitIsValid() { return token != Token::ILLEGAL; }
3118 bool LimitIsIncluded() {
3119 return Token::IsEqualityOp(token) ||
3120 token == Token::GTE || token == Token::LTE;
3122 bool LimitIsUpper() {
3123 return token == Token::LTE || token == Token::LT || token == Token::NE;
3126 LimitFromPredecessorBlock()
3128 token(Token::ILLEGAL),
3130 other_target(NULL) {}
3133 static const int32_t kNoLimit = -1;
3135 static InductionVariableData* ExaminePhi(HPhi* phi);
3136 static void ComputeLimitFromPredecessorBlock(
3138 LimitFromPredecessorBlock* result);
3139 static bool ComputeInductionVariableLimit(
3141 InductionVariableLimitUpdate* additional_limit);
3143 struct BitwiseDecompositionResult {
3149 BitwiseDecompositionResult()
3150 : base(NULL), and_mask(0), or_mask(0), context(NULL) {}
3152 static void DecomposeBitwise(HValue* value,
3153 BitwiseDecompositionResult* result);
3155 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3157 bool CheckIfBranchIsLoopGuard(Token::Value token,
3158 HBasicBlock* current_branch,
3159 HBasicBlock* other_branch);
3161 void UpdateAdditionalLimit(InductionVariableLimitUpdate* update);
3163 HPhi* phi() { return phi_; }
3164 HValue* base() { return base_; }
3165 int32_t increment() { return increment_; }
3166 HValue* limit() { return limit_; }
3167 bool limit_included() { return limit_included_; }
3168 HBasicBlock* limit_validity() { return limit_validity_; }
3169 HBasicBlock* induction_exit_block() { return induction_exit_block_; }
3170 HBasicBlock* induction_exit_target() { return induction_exit_target_; }
3171 ChecksRelatedToLength* checks() { return checks_; }
3172 HValue* additional_upper_limit() { return additional_upper_limit_; }
3173 bool additional_upper_limit_is_included() {
3174 return additional_upper_limit_is_included_;
3176 HValue* additional_lower_limit() { return additional_lower_limit_; }
3177 bool additional_lower_limit_is_included() {
3178 return additional_lower_limit_is_included_;
3181 bool LowerLimitIsNonNegativeConstant() {
3182 if (base()->IsInteger32Constant() && base()->GetInteger32Constant() >= 0) {
3185 if (additional_lower_limit() != NULL &&
3186 additional_lower_limit()->IsInteger32Constant() &&
3187 additional_lower_limit()->GetInteger32Constant() >= 0) {
3188 // Ignoring the corner case of !additional_lower_limit_is_included()
3189 // is safe, handling it adds unneeded complexity.
3195 int32_t ComputeUpperLimit(int32_t and_mask, int32_t or_mask);
3198 template <class T> void swap(T* a, T* b) {
3204 InductionVariableData(HPhi* phi, HValue* base, int32_t increment)
3205 : phi_(phi), base_(IgnoreOsrValue(base)), increment_(increment),
3206 limit_(NULL), limit_included_(false), limit_validity_(NULL),
3207 induction_exit_block_(NULL), induction_exit_target_(NULL),
3209 additional_upper_limit_(NULL),
3210 additional_upper_limit_is_included_(false),
3211 additional_lower_limit_(NULL),
3212 additional_lower_limit_is_included_(false) {}
3214 static int32_t ComputeIncrement(HPhi* phi, HValue* phi_operand);
3216 static HValue* IgnoreOsrValue(HValue* v);
3217 static InductionVariableData* GetInductionVariableData(HValue* v);
3223 bool limit_included_;
3224 HBasicBlock* limit_validity_;
3225 HBasicBlock* induction_exit_block_;
3226 HBasicBlock* induction_exit_target_;
3227 ChecksRelatedToLength* checks_;
3228 HValue* additional_upper_limit_;
3229 bool additional_upper_limit_is_included_;
3230 HValue* additional_lower_limit_;
3231 bool additional_lower_limit_is_included_;
3235 class HPhi V8_FINAL : public HValue {
3237 HPhi(int merged_index, Zone* zone)
3239 merged_index_(merged_index),
3241 induction_variable_data_(NULL) {
3242 for (int i = 0; i < Representation::kNumRepresentations; i++) {
3243 non_phi_uses_[i] = 0;
3244 indirect_uses_[i] = 0;
3246 ASSERT(merged_index >= 0 || merged_index == kInvalidMergedIndex);
3247 SetFlag(kFlexibleRepresentation);
3248 SetFlag(kAllowUndefinedAsNaN);
3251 virtual Representation RepresentationFromInputs() V8_OVERRIDE;
3253 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
3254 virtual void InferRepresentation(
3255 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
3256 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3257 return representation();
3259 virtual Representation KnownOptimalRepresentation() V8_OVERRIDE {
3260 return representation();
3262 virtual HType CalculateInferredType() V8_OVERRIDE;
3263 virtual int OperandCount() V8_OVERRIDE { return inputs_.length(); }
3264 virtual HValue* OperandAt(int index) const V8_OVERRIDE {
3265 return inputs_[index];
3267 HValue* GetRedundantReplacement();
3268 void AddInput(HValue* value);
3271 bool IsReceiver() const { return merged_index_ == 0; }
3272 bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
3274 virtual HSourcePosition position() const V8_OVERRIDE;
3276 int merged_index() const { return merged_index_; }
3278 InductionVariableData* induction_variable_data() {
3279 return induction_variable_data_;
3281 bool IsInductionVariable() {
3282 return induction_variable_data_ != NULL;
3284 bool IsLimitedInductionVariable() {
3285 return IsInductionVariable() &&
3286 induction_variable_data_->limit() != NULL;
3288 void DetectInductionVariable() {
3289 ASSERT(induction_variable_data_ == NULL);
3290 induction_variable_data_ = InductionVariableData::ExaminePhi(this);
3293 virtual void PrintTo(StringStream* stream) V8_OVERRIDE;
3296 virtual void Verify() V8_OVERRIDE;
3299 void InitRealUses(int id);
3300 void AddNonPhiUsesFrom(HPhi* other);
3301 void AddIndirectUsesTo(int* use_count);
3303 int tagged_non_phi_uses() const {
3304 return non_phi_uses_[Representation::kTagged];
3306 int smi_non_phi_uses() const {
3307 return non_phi_uses_[Representation::kSmi];
3309 int int32_non_phi_uses() const {
3310 return non_phi_uses_[Representation::kInteger32];
3312 int double_non_phi_uses() const {
3313 return non_phi_uses_[Representation::kDouble];
3315 int tagged_indirect_uses() const {
3316 return indirect_uses_[Representation::kTagged];
3318 int smi_indirect_uses() const {
3319 return indirect_uses_[Representation::kSmi];
3321 int int32_indirect_uses() const {
3322 return indirect_uses_[Representation::kInteger32];
3324 int double_indirect_uses() const {
3325 return indirect_uses_[Representation::kDouble];
3327 int phi_id() { return phi_id_; }
3329 static HPhi* cast(HValue* value) {
3330 ASSERT(value->IsPhi());
3331 return reinterpret_cast<HPhi*>(value);
3333 virtual Opcode opcode() const V8_OVERRIDE { return HValue::kPhi; }
3335 void SimplifyConstantInputs();
3337 // Marker value representing an invalid merge index.
3338 static const int kInvalidMergedIndex = -1;
3341 virtual void DeleteFromGraph() V8_OVERRIDE;
3342 virtual void InternalSetOperandAt(int index, HValue* value) V8_OVERRIDE {
3343 inputs_[index] = value;
3347 ZoneList<HValue*> inputs_;
3350 int non_phi_uses_[Representation::kNumRepresentations];
3351 int indirect_uses_[Representation::kNumRepresentations];
3353 InductionVariableData* induction_variable_data_;
3355 // TODO(titzer): we can't eliminate the receiver for generating backtraces
3356 virtual bool IsDeletable() const V8_OVERRIDE { return !IsReceiver(); }
3360 // Common base class for HArgumentsObject and HCapturedObject.
3361 class HDematerializedObject : public HInstruction {
3363 HDematerializedObject(int count, Zone* zone) : values_(count, zone) {}
3365 virtual int OperandCount() V8_FINAL V8_OVERRIDE { return values_.length(); }
3366 virtual HValue* OperandAt(int index) const V8_FINAL V8_OVERRIDE {
3367 return values_[index];
3370 virtual bool HasEscapingOperandAt(int index) V8_FINAL V8_OVERRIDE {
3373 virtual Representation RequiredInputRepresentation(
3374 int index) V8_FINAL V8_OVERRIDE {
3375 return Representation::None();
3379 virtual void InternalSetOperandAt(int index,
3380 HValue* value) V8_FINAL V8_OVERRIDE {
3381 values_[index] = value;
3384 // List of values tracked by this marker.
3385 ZoneList<HValue*> values_;
3389 class HArgumentsObject V8_FINAL : public HDematerializedObject {
3391 static HArgumentsObject* New(Zone* zone, HValue* context, int count) {
3392 return new(zone) HArgumentsObject(count, zone);
3395 // The values contain a list of all elements in the arguments object
3396 // including the receiver object, which is skipped when materializing.
3397 const ZoneList<HValue*>* arguments_values() const { return &values_; }
3398 int arguments_count() const { return values_.length(); }
3400 void AddArgument(HValue* argument, Zone* zone) {
3401 values_.Add(NULL, zone); // Resize list.
3402 SetOperandAt(values_.length() - 1, argument);
3405 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
3408 HArgumentsObject(int count, Zone* zone)
3409 : HDematerializedObject(count, zone) {
3410 set_representation(Representation::Tagged());
3411 SetFlag(kIsArguments);
3414 virtual bool IsDeletable() const V8_FINAL V8_OVERRIDE { return true; }
3418 class HCapturedObject V8_FINAL : public HDematerializedObject {
3420 HCapturedObject(int length, int id, Zone* zone)
3421 : HDematerializedObject(length, zone), capture_id_(id) {
3422 set_representation(Representation::Tagged());
3423 values_.AddBlock(NULL, length, zone); // Resize list.
3426 // The values contain a list of all in-object properties inside the
3427 // captured object and is index by field index. Properties in the
3428 // properties or elements backing store are not tracked here.
3429 const ZoneList<HValue*>* values() const { return &values_; }
3430 int length() const { return values_.length(); }
3431 int capture_id() const { return capture_id_; }
3433 // Shortcut for the map value of this captured object.
3434 HValue* map_value() const { return values()->first(); }
3436 void ReuseSideEffectsFromStore(HInstruction* store) {
3437 ASSERT(store->HasObservableSideEffects());
3438 ASSERT(store->IsStoreNamedField());
3439 changes_flags_.Add(store->ChangesFlags());
3442 // Replay effects of this instruction on the given environment.
3443 void ReplayEnvironment(HEnvironment* env);
3445 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3447 DECLARE_CONCRETE_INSTRUCTION(CapturedObject)
3452 // Note that we cannot DCE captured objects as they are used to replay
3453 // the environment. This method is here as an explicit reminder.
3454 // TODO(mstarzinger): Turn HSimulates into full snapshots maybe?
3455 virtual bool IsDeletable() const V8_FINAL V8_OVERRIDE { return false; }
3459 class HConstant V8_FINAL : public HTemplateInstruction<0> {
3461 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, int32_t);
3462 DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation);
3463 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double);
3464 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle<Object>);
3465 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);
3467 static HConstant* CreateAndInsertAfter(Zone* zone,
3470 Representation representation,
3471 HInstruction* instruction) {
3472 return instruction->Append(HConstant::New(
3473 zone, context, value, representation));
3476 static HConstant* CreateAndInsertBefore(Zone* zone,
3479 Representation representation,
3480 HInstruction* instruction) {
3481 return instruction->Prepend(HConstant::New(
3482 zone, context, value, representation));
3485 static HConstant* CreateAndInsertBefore(Zone* zone,
3486 Unique<Object> unique,
3487 bool is_not_in_new_space,
3488 HInstruction* instruction) {
3489 return instruction->Prepend(new(zone) HConstant(
3490 unique, Representation::Tagged(), HType::Tagged(),
3491 is_not_in_new_space, false, false, kUnknownInstanceType));
3494 Handle<Object> handle(Isolate* isolate) {
3495 if (object_.handle().is_null()) {
3496 // Default arguments to is_not_in_new_space depend on this heap number
3497 // to be tenured so that it's guaranteed not to be located in new space.
3498 object_ = Unique<Object>::CreateUninitialized(
3499 isolate->factory()->NewNumber(double_value_, TENURED));
3501 AllowDeferredHandleDereference smi_check;
3502 ASSERT(has_int32_value_ || !object_.handle()->IsSmi());
3503 return object_.handle();
3506 bool HasMap(Handle<Map> map) {
3507 Handle<Object> constant_object = handle(map->GetIsolate());
3508 return constant_object->IsHeapObject() &&
3509 Handle<HeapObject>::cast(constant_object)->map() == *map;
3512 bool IsSpecialDouble() const {
3513 return has_double_value_ &&
3514 (BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) ||
3515 FixedDoubleArray::is_the_hole_nan(double_value_) ||
3516 std::isnan(double_value_));
3519 bool NotInNewSpace() const {
3520 return is_not_in_new_space_;
3523 bool ImmortalImmovable() const;
3525 bool IsCell() const {
3526 return instance_type_ == CELL_TYPE || instance_type_ == PROPERTY_CELL_TYPE;
3529 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3530 return Representation::None();
3533 virtual Representation KnownOptimalRepresentation() V8_OVERRIDE {
3534 if (HasSmiValue() && SmiValuesAre31Bits()) return Representation::Smi();
3535 if (HasInteger32Value()) return Representation::Integer32();
3536 if (HasNumberValue()) return Representation::Double();
3537 if (HasExternalReferenceValue()) return Representation::External();
3538 return Representation::Tagged();
3541 virtual bool EmitAtUses() V8_OVERRIDE;
3542 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3543 HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
3544 Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone);
3545 Maybe<HConstant*> CopyToTruncatedNumber(Zone* zone);
3546 bool HasInteger32Value() const { return has_int32_value_; }
3547 int32_t Integer32Value() const {
3548 ASSERT(HasInteger32Value());
3549 return int32_value_;
3551 bool HasSmiValue() const { return has_smi_value_; }
3552 bool HasDoubleValue() const { return has_double_value_; }
3553 double DoubleValue() const {
3554 ASSERT(HasDoubleValue());
3555 return double_value_;
3557 bool IsTheHole() const {
3558 if (HasDoubleValue() && FixedDoubleArray::is_the_hole_nan(double_value_)) {
3561 return object_.IsKnownGlobal(isolate()->heap()->the_hole_value());
3563 bool HasNumberValue() const { return has_double_value_; }
3564 int32_t NumberValueAsInteger32() const {
3565 ASSERT(HasNumberValue());
3566 // Irrespective of whether a numeric HConstant can be safely
3567 // represented as an int32, we store the (in some cases lossy)
3568 // representation of the number in int32_value_.
3569 return int32_value_;
3571 bool HasStringValue() const {
3572 if (has_double_value_ || has_int32_value_) return false;
3573 ASSERT(!object_.handle().is_null());
3574 return instance_type_ < FIRST_NONSTRING_TYPE;
3576 Handle<String> StringValue() const {
3577 ASSERT(HasStringValue());
3578 return Handle<String>::cast(object_.handle());
3580 bool HasInternalizedStringValue() const {
3581 return HasStringValue() && StringShape(instance_type_).IsInternalized();
3584 bool HasExternalReferenceValue() const {
3585 return has_external_reference_value_;
3587 ExternalReference ExternalReferenceValue() const {
3588 return external_reference_value_;
3591 bool HasBooleanValue() const { return type_.IsBoolean(); }
3592 bool BooleanValue() const { return boolean_value_; }
3593 bool IsUndetectable() const { return is_undetectable_; }
3594 InstanceType GetInstanceType() const { return instance_type_; }
3596 virtual intptr_t Hashcode() V8_OVERRIDE {
3597 if (has_int32_value_) {
3598 return static_cast<intptr_t>(int32_value_);
3599 } else if (has_double_value_) {
3600 return static_cast<intptr_t>(BitCast<int64_t>(double_value_));
3601 } else if (has_external_reference_value_) {
3602 return reinterpret_cast<intptr_t>(external_reference_value_.address());
3604 ASSERT(!object_.handle().is_null());
3605 return object_.Hashcode();
3609 virtual void FinalizeUniqueness() V8_OVERRIDE {
3610 if (!has_double_value_ && !has_external_reference_value_) {
3611 ASSERT(!object_.handle().is_null());
3612 object_ = Unique<Object>(object_.handle());
3616 Unique<Object> GetUnique() const {
3620 bool EqualsUnique(Unique<Object> other) const {
3621 return object_.IsInitialized() && object_ == other;
3624 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
3625 HConstant* other_constant = HConstant::cast(other);
3626 if (has_int32_value_) {
3627 return other_constant->has_int32_value_ &&
3628 int32_value_ == other_constant->int32_value_;
3629 } else if (has_double_value_) {
3630 return other_constant->has_double_value_ &&
3631 BitCast<int64_t>(double_value_) ==
3632 BitCast<int64_t>(other_constant->double_value_);
3633 } else if (has_external_reference_value_) {
3634 return other_constant->has_external_reference_value_ &&
3635 external_reference_value_ ==
3636 other_constant->external_reference_value_;
3638 if (other_constant->has_int32_value_ ||
3639 other_constant->has_double_value_ ||
3640 other_constant->has_external_reference_value_) {
3643 ASSERT(!object_.handle().is_null());
3644 return other_constant->object_ == object_;
3649 virtual void Verify() V8_OVERRIDE { }
3652 DECLARE_CONCRETE_INSTRUCTION(Constant)
3655 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
3658 friend class HGraph;
3659 HConstant(Handle<Object> handle, Representation r = Representation::None());
3660 HConstant(int32_t value,
3661 Representation r = Representation::None(),
3662 bool is_not_in_new_space = true,
3663 Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3664 HConstant(double value,
3665 Representation r = Representation::None(),
3666 bool is_not_in_new_space = true,
3667 Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3668 HConstant(Unique<Object> unique,
3671 bool is_not_in_new_space,
3673 bool is_undetectable,
3674 InstanceType instance_type);
3676 explicit HConstant(ExternalReference reference);
3678 void Initialize(Representation r);
3680 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
3682 // If this is a numerical constant, object_ either points to the
3683 // HeapObject the constant originated from or is null. If the
3684 // constant is non-numeric, object_ always points to a valid
3685 // constant HeapObject.
3686 Unique<Object> object_;
3688 // We store the HConstant in the most specific form safely possible.
3689 // The two flags, has_int32_value_ and has_double_value_ tell us if
3690 // int32_value_ and double_value_ hold valid, safe representations
3691 // of the constant. has_int32_value_ implies has_double_value_ but
3692 // not the converse.
3693 bool has_smi_value_ : 1;
3694 bool has_int32_value_ : 1;
3695 bool has_double_value_ : 1;
3696 bool has_external_reference_value_ : 1;
3697 bool is_not_in_new_space_ : 1;
3698 bool boolean_value_ : 1;
3699 bool is_undetectable_: 1;
3700 int32_t int32_value_;
3701 double double_value_;
3702 ExternalReference external_reference_value_;
3704 static const InstanceType kUnknownInstanceType = FILLER_TYPE;
3705 InstanceType instance_type_;
3709 class HBinaryOperation : public HTemplateInstruction<3> {
3711 HBinaryOperation(HValue* context, HValue* left, HValue* right,
3712 HType type = HType::Tagged())
3713 : HTemplateInstruction<3>(type),
3714 observed_output_representation_(Representation::None()) {
3715 ASSERT(left != NULL && right != NULL);
3716 SetOperandAt(0, context);
3717 SetOperandAt(1, left);
3718 SetOperandAt(2, right);
3719 observed_input_representation_[0] = Representation::None();
3720 observed_input_representation_[1] = Representation::None();
3723 HValue* context() const { return OperandAt(0); }
3724 HValue* left() const { return OperandAt(1); }
3725 HValue* right() const { return OperandAt(2); }
3727 // True if switching left and right operands likely generates better code.
3728 bool AreOperandsBetterSwitched() {
3729 if (!IsCommutative()) return false;
3731 // Constant operands are better off on the right, they can be inlined in
3732 // many situations on most platforms.
3733 if (left()->IsConstant()) return true;
3734 if (right()->IsConstant()) return false;
3736 // Otherwise, if there is only one use of the right operand, it would be
3737 // better off on the left for platforms that only have 2-arg arithmetic
3738 // ops (e.g ia32, x64) that clobber the left operand.
3739 return right()->UseCount() == 1;
3742 HValue* BetterLeftOperand() {
3743 return AreOperandsBetterSwitched() ? right() : left();
3746 HValue* BetterRightOperand() {
3747 return AreOperandsBetterSwitched() ? left() : right();
3750 void set_observed_input_representation(int index, Representation rep) {
3751 ASSERT(index >= 1 && index <= 2);
3752 observed_input_representation_[index - 1] = rep;
3755 virtual void initialize_output_representation(Representation observed) {
3756 observed_output_representation_ = observed;
3759 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
3760 if (index == 0) return Representation::Tagged();
3761 return observed_input_representation_[index - 1];
3764 virtual void UpdateRepresentation(Representation new_rep,
3765 HInferRepresentationPhase* h_infer,
3766 const char* reason) V8_OVERRIDE {
3767 Representation rep = !FLAG_smi_binop && new_rep.IsSmi()
3768 ? Representation::Integer32() : new_rep;
3769 HValue::UpdateRepresentation(rep, h_infer, reason);
3772 virtual void InferRepresentation(
3773 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
3774 virtual Representation RepresentationFromInputs() V8_OVERRIDE;
3775 Representation RepresentationFromOutput();
3776 virtual void AssumeRepresentation(Representation r) V8_OVERRIDE;
3778 virtual bool IsCommutative() const { return false; }
3780 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3782 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3783 if (index == 0) return Representation::Tagged();
3784 return representation();
3787 void SetOperandPositions(Zone* zone,
3788 HSourcePosition left_pos,
3789 HSourcePosition right_pos) {
3790 set_operand_position(zone, 1, left_pos);
3791 set_operand_position(zone, 2, right_pos);
3794 bool RightIsPowerOf2() {
3795 if (!right()->IsInteger32Constant()) return false;
3796 int32_t value = right()->GetInteger32Constant();
3797 return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
3800 DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
3803 bool IgnoreObservedOutputRepresentation(Representation current_rep);
3805 Representation observed_input_representation_[2];
3806 Representation observed_output_representation_;
3810 class HWrapReceiver V8_FINAL : public HTemplateInstruction<2> {
3812 DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
3814 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3816 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3817 return Representation::Tagged();
3820 HValue* receiver() { return OperandAt(0); }
3821 HValue* function() { return OperandAt(1); }
3823 virtual HValue* Canonicalize() V8_OVERRIDE;
3825 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3826 bool known_function() const { return known_function_; }
3828 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
3831 HWrapReceiver(HValue* receiver, HValue* function) {
3832 known_function_ = function->IsConstant() &&
3833 HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
3834 set_representation(Representation::Tagged());
3835 SetOperandAt(0, receiver);
3836 SetOperandAt(1, function);
3840 bool known_function_;
3844 class HApplyArguments V8_FINAL : public HTemplateInstruction<4> {
3846 DECLARE_INSTRUCTION_FACTORY_P4(HApplyArguments, HValue*, HValue*, HValue*,
3849 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3850 // The length is untagged, all other inputs are tagged.
3852 ? Representation::Integer32()
3853 : Representation::Tagged();
3856 HValue* function() { return OperandAt(0); }
3857 HValue* receiver() { return OperandAt(1); }
3858 HValue* length() { return OperandAt(2); }
3859 HValue* elements() { return OperandAt(3); }
3861 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
3864 HApplyArguments(HValue* function,
3868 set_representation(Representation::Tagged());
3869 SetOperandAt(0, function);
3870 SetOperandAt(1, receiver);
3871 SetOperandAt(2, length);
3872 SetOperandAt(3, elements);
3873 SetAllSideEffects();
3878 class HArgumentsElements V8_FINAL : public HTemplateInstruction<0> {
3880 DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
3882 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
3884 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3885 return Representation::None();
3888 bool from_inlined() const { return from_inlined_; }
3891 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3894 explicit HArgumentsElements(bool from_inlined) : from_inlined_(from_inlined) {
3895 // The value produced by this instruction is a pointer into the stack
3896 // that looks as if it was a smi because of alignment.
3897 set_representation(Representation::Tagged());
3901 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
3907 class HArgumentsLength V8_FINAL : public HUnaryOperation {
3909 DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue*);
3911 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3912 return Representation::Tagged();
3915 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
3918 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3921 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
3922 set_representation(Representation::Integer32());
3926 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
3930 class HAccessArgumentsAt V8_FINAL : public HTemplateInstruction<3> {
3932 DECLARE_INSTRUCTION_FACTORY_P3(HAccessArgumentsAt, HValue*, HValue*, HValue*);
3934 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3936 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3937 // The arguments elements is considered tagged.
3939 ? Representation::Tagged()
3940 : Representation::Integer32();
3943 HValue* arguments() { return OperandAt(0); }
3944 HValue* length() { return OperandAt(1); }
3945 HValue* index() { return OperandAt(2); }
3947 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
3950 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
3951 set_representation(Representation::Tagged());
3953 SetOperandAt(0, arguments);
3954 SetOperandAt(1, length);
3955 SetOperandAt(2, index);
3958 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3962 class HBoundsCheckBaseIndexInformation;
3965 class HBoundsCheck V8_FINAL : public HTemplateInstruction<2> {
3967 DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
3969 bool skip_check() const { return skip_check_; }
3970 void set_skip_check() { skip_check_ = true; }
3972 HValue* base() { return base_; }
3973 int offset() { return offset_; }
3974 int scale() { return scale_; }
3976 void ApplyIndexChange();
3977 bool DetectCompoundIndex() {
3978 ASSERT(base() == NULL);
3980 DecompositionResult decomposition;
3981 if (index()->TryDecompose(&decomposition)) {
3982 base_ = decomposition.base();
3983 offset_ = decomposition.offset();
3984 scale_ = decomposition.scale();
3994 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3995 return representation();
3998 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3999 virtual void InferRepresentation(
4000 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4002 HValue* index() { return OperandAt(0); }
4003 HValue* length() { return OperandAt(1); }
4004 bool allow_equality() { return allow_equality_; }
4005 void set_allow_equality(bool v) { allow_equality_ = v; }
4007 virtual int RedefinedOperandIndex() V8_OVERRIDE { return 0; }
4008 virtual bool IsPurelyInformativeDefinition() V8_OVERRIDE {
4009 return skip_check();
4012 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
4015 friend class HBoundsCheckBaseIndexInformation;
4017 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4019 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4024 bool allow_equality_;
4027 // Normally HBoundsCheck should be created using the
4028 // HGraphBuilder::AddBoundsCheck() helper.
4029 // However when building stubs, where we know that the arguments are Int32,
4030 // it makes sense to invoke this constructor directly.
4031 HBoundsCheck(HValue* index, HValue* length)
4032 : skip_check_(false),
4033 base_(NULL), offset_(0), scale_(0),
4034 allow_equality_(false) {
4035 SetOperandAt(0, index);
4036 SetOperandAt(1, length);
4037 SetFlag(kFlexibleRepresentation);
4041 virtual bool IsDeletable() const V8_OVERRIDE {
4042 return skip_check() && !FLAG_debug_code;
4047 class HBoundsCheckBaseIndexInformation V8_FINAL
4048 : public HTemplateInstruction<2> {
4050 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) {
4051 DecompositionResult decomposition;
4052 if (check->index()->TryDecompose(&decomposition)) {
4053 SetOperandAt(0, decomposition.base());
4054 SetOperandAt(1, check);
4060 HValue* base_index() { return OperandAt(0); }
4061 HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); }
4063 DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation)
4065 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4066 return representation();
4069 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4071 virtual int RedefinedOperandIndex() V8_OVERRIDE { return 0; }
4072 virtual bool IsPurelyInformativeDefinition() V8_OVERRIDE { return true; }
4076 class HBitwiseBinaryOperation : public HBinaryOperation {
4078 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
4079 HType type = HType::Tagged())
4080 : HBinaryOperation(context, left, right, type) {
4081 SetFlag(kFlexibleRepresentation);
4082 SetFlag(kTruncatingToInt32);
4083 SetFlag(kAllowUndefinedAsNaN);
4084 SetAllSideEffects();
4087 virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
4088 if (to.IsTagged() &&
4089 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
4090 SetAllSideEffects();
4093 ClearAllSideEffects();
4096 if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
4099 virtual void UpdateRepresentation(Representation new_rep,
4100 HInferRepresentationPhase* h_infer,
4101 const char* reason) V8_OVERRIDE {
4102 // We only generate either int32 or generic tagged bitwise operations.
4103 if (new_rep.IsDouble()) new_rep = Representation::Integer32();
4104 HBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4107 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4108 Representation r = HBinaryOperation::observed_input_representation(index);
4109 if (r.IsDouble()) return Representation::Integer32();
4113 virtual void initialize_output_representation(Representation observed) {
4114 if (observed.IsDouble()) observed = Representation::Integer32();
4115 HBinaryOperation::initialize_output_representation(observed);
4118 DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
4121 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4125 class HMathFloorOfDiv V8_FINAL : public HBinaryOperation {
4127 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HMathFloorOfDiv,
4131 DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
4134 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4137 HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
4138 : HBinaryOperation(context, left, right) {
4139 set_representation(Representation::Integer32());
4141 SetFlag(kCanOverflow);
4142 SetFlag(kCanBeDivByZero);
4143 SetFlag(kLeftCanBeMinInt);
4144 SetFlag(kLeftCanBeNegative);
4145 SetFlag(kLeftCanBePositive);
4146 SetFlag(kAllowUndefinedAsNaN);
4149 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4151 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4155 class HArithmeticBinaryOperation : public HBinaryOperation {
4157 HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right)
4158 : HBinaryOperation(context, left, right, HType::TaggedNumber()) {
4159 SetAllSideEffects();
4160 SetFlag(kFlexibleRepresentation);
4161 SetFlag(kAllowUndefinedAsNaN);
4164 virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
4165 if (to.IsTagged() &&
4166 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
4167 SetAllSideEffects();
4170 ClearAllSideEffects();
4173 if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
4176 DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
4179 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4183 class HCompareGeneric V8_FINAL : public HBinaryOperation {
4185 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCompareGeneric, HValue*,
4186 HValue*, Token::Value);
4188 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4190 ? Representation::Tagged()
4194 Token::Value token() const { return token_; }
4195 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4197 DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
4200 HCompareGeneric(HValue* context,
4204 : HBinaryOperation(context, left, right, HType::Boolean()),
4206 ASSERT(Token::IsCompareOp(token));
4207 set_representation(Representation::Tagged());
4208 SetAllSideEffects();
4211 Token::Value token_;
4215 class HCompareNumericAndBranch : public HTemplateControlInstruction<2, 2> {
4217 DECLARE_INSTRUCTION_FACTORY_P3(HCompareNumericAndBranch,
4218 HValue*, HValue*, Token::Value);
4219 DECLARE_INSTRUCTION_FACTORY_P5(HCompareNumericAndBranch,
4220 HValue*, HValue*, Token::Value,
4221 HBasicBlock*, HBasicBlock*);
4223 HValue* left() { return OperandAt(0); }
4224 HValue* right() { return OperandAt(1); }
4225 Token::Value token() const { return token_; }
4227 void set_observed_input_representation(Representation left,
4228 Representation right) {
4229 observed_input_representation_[0] = left;
4230 observed_input_representation_[1] = right;
4233 virtual void InferRepresentation(
4234 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4236 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4237 return representation();
4239 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4240 return observed_input_representation_[index];
4242 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4244 void SetOperandPositions(Zone* zone,
4245 HSourcePosition left_pos,
4246 HSourcePosition right_pos) {
4247 set_operand_position(zone, 0, left_pos);
4248 set_operand_position(zone, 1, right_pos);
4251 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
4254 HCompareNumericAndBranch(HValue* left,
4257 HBasicBlock* true_target = NULL,
4258 HBasicBlock* false_target = NULL)
4260 SetFlag(kFlexibleRepresentation);
4261 ASSERT(Token::IsCompareOp(token));
4262 SetOperandAt(0, left);
4263 SetOperandAt(1, right);
4264 SetSuccessorAt(0, true_target);
4265 SetSuccessorAt(1, false_target);
4268 Representation observed_input_representation_[2];
4269 Token::Value token_;
4273 class HCompareHoleAndBranch V8_FINAL : public HUnaryControlInstruction {
4275 DECLARE_INSTRUCTION_FACTORY_P1(HCompareHoleAndBranch, HValue*);
4276 DECLARE_INSTRUCTION_FACTORY_P3(HCompareHoleAndBranch, HValue*,
4277 HBasicBlock*, HBasicBlock*);
4279 virtual void InferRepresentation(
4280 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4282 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4283 return representation();
4286 DECLARE_CONCRETE_INSTRUCTION(CompareHoleAndBranch)
4289 HCompareHoleAndBranch(HValue* value,
4290 HBasicBlock* true_target = NULL,
4291 HBasicBlock* false_target = NULL)
4292 : HUnaryControlInstruction(value, true_target, false_target) {
4293 SetFlag(kFlexibleRepresentation);
4294 SetFlag(kAllowUndefinedAsNaN);
4299 class HCompareMinusZeroAndBranch V8_FINAL : public HUnaryControlInstruction {
4301 DECLARE_INSTRUCTION_FACTORY_P1(HCompareMinusZeroAndBranch, HValue*);
4303 virtual void InferRepresentation(
4304 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4306 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4307 return representation();
4310 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4312 DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch)
4315 explicit HCompareMinusZeroAndBranch(HValue* value)
4316 : HUnaryControlInstruction(value, NULL, NULL) {
4321 class HCompareObjectEqAndBranch : public HTemplateControlInstruction<2, 2> {
4323 DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue*, HValue*);
4324 DECLARE_INSTRUCTION_FACTORY_P4(HCompareObjectEqAndBranch, HValue*, HValue*,
4325 HBasicBlock*, HBasicBlock*);
4327 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4329 static const int kNoKnownSuccessorIndex = -1;
4330 int known_successor_index() const { return known_successor_index_; }
4331 void set_known_successor_index(int known_successor_index) {
4332 known_successor_index_ = known_successor_index;
4335 HValue* left() { return OperandAt(0); }
4336 HValue* right() { return OperandAt(1); }
4338 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4340 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4341 return Representation::Tagged();
4344 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4345 return Representation::Tagged();
4348 DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
4351 HCompareObjectEqAndBranch(HValue* left,
4353 HBasicBlock* true_target = NULL,
4354 HBasicBlock* false_target = NULL)
4355 : known_successor_index_(kNoKnownSuccessorIndex) {
4356 ASSERT(!left->IsConstant() ||
4357 (!HConstant::cast(left)->HasInteger32Value() ||
4358 HConstant::cast(left)->HasSmiValue()));
4359 ASSERT(!right->IsConstant() ||
4360 (!HConstant::cast(right)->HasInteger32Value() ||
4361 HConstant::cast(right)->HasSmiValue()));
4362 SetOperandAt(0, left);
4363 SetOperandAt(1, right);
4364 SetSuccessorAt(0, true_target);
4365 SetSuccessorAt(1, false_target);
4368 int known_successor_index_;
4372 class HIsObjectAndBranch V8_FINAL : public HUnaryControlInstruction {
4374 DECLARE_INSTRUCTION_FACTORY_P1(HIsObjectAndBranch, HValue*);
4375 DECLARE_INSTRUCTION_FACTORY_P3(HIsObjectAndBranch, HValue*,
4376 HBasicBlock*, HBasicBlock*);
4378 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4379 return Representation::Tagged();
4382 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4384 DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch)
4387 HIsObjectAndBranch(HValue* value,
4388 HBasicBlock* true_target = NULL,
4389 HBasicBlock* false_target = NULL)
4390 : HUnaryControlInstruction(value, true_target, false_target) {}
4394 class HIsStringAndBranch V8_FINAL : public HUnaryControlInstruction {
4396 DECLARE_INSTRUCTION_FACTORY_P1(HIsStringAndBranch, HValue*);
4397 DECLARE_INSTRUCTION_FACTORY_P3(HIsStringAndBranch, HValue*,
4398 HBasicBlock*, HBasicBlock*);
4400 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4401 return Representation::Tagged();
4404 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4406 DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
4409 virtual int RedefinedOperandIndex() { return 0; }
4412 HIsStringAndBranch(HValue* value,
4413 HBasicBlock* true_target = NULL,
4414 HBasicBlock* false_target = NULL)
4415 : HUnaryControlInstruction(value, true_target, false_target) {}
4419 class HIsSmiAndBranch V8_FINAL : public HUnaryControlInstruction {
4421 DECLARE_INSTRUCTION_FACTORY_P1(HIsSmiAndBranch, HValue*);
4422 DECLARE_INSTRUCTION_FACTORY_P3(HIsSmiAndBranch, HValue*,
4423 HBasicBlock*, HBasicBlock*);
4425 DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
4427 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4428 return Representation::Tagged();
4432 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4433 virtual int RedefinedOperandIndex() { return 0; }
4436 HIsSmiAndBranch(HValue* value,
4437 HBasicBlock* true_target = NULL,
4438 HBasicBlock* false_target = NULL)
4439 : HUnaryControlInstruction(value, true_target, false_target) {
4440 set_representation(Representation::Tagged());
4445 class HIsUndetectableAndBranch V8_FINAL : public HUnaryControlInstruction {
4447 DECLARE_INSTRUCTION_FACTORY_P1(HIsUndetectableAndBranch, HValue*);
4448 DECLARE_INSTRUCTION_FACTORY_P3(HIsUndetectableAndBranch, HValue*,
4449 HBasicBlock*, HBasicBlock*);
4451 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4452 return Representation::Tagged();
4455 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4457 DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
4460 HIsUndetectableAndBranch(HValue* value,
4461 HBasicBlock* true_target = NULL,
4462 HBasicBlock* false_target = NULL)
4463 : HUnaryControlInstruction(value, true_target, false_target) {}
4467 class HStringCompareAndBranch : public HTemplateControlInstruction<2, 3> {
4469 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HStringCompareAndBranch,
4474 HValue* context() { return OperandAt(0); }
4475 HValue* left() { return OperandAt(1); }
4476 HValue* right() { return OperandAt(2); }
4477 Token::Value token() const { return token_; }
4479 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4481 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4482 return Representation::Tagged();
4485 Representation GetInputRepresentation() const {
4486 return Representation::Tagged();
4489 DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
4492 HStringCompareAndBranch(HValue* context,
4497 ASSERT(Token::IsCompareOp(token));
4498 SetOperandAt(0, context);
4499 SetOperandAt(1, left);
4500 SetOperandAt(2, right);
4501 set_representation(Representation::Tagged());
4502 SetChangesFlag(kNewSpacePromotion);
4505 Token::Value token_;
4509 class HIsConstructCallAndBranch : public HTemplateControlInstruction<2, 0> {
4511 DECLARE_INSTRUCTION_FACTORY_P0(HIsConstructCallAndBranch);
4513 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4514 return Representation::None();
4517 DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch)
4519 HIsConstructCallAndBranch() {}
4523 class HHasInstanceTypeAndBranch V8_FINAL : public HUnaryControlInstruction {
4525 DECLARE_INSTRUCTION_FACTORY_P2(
4526 HHasInstanceTypeAndBranch, HValue*, InstanceType);
4527 DECLARE_INSTRUCTION_FACTORY_P3(
4528 HHasInstanceTypeAndBranch, HValue*, InstanceType, InstanceType);
4530 InstanceType from() { return from_; }
4531 InstanceType to() { return to_; }
4533 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4535 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4536 return Representation::Tagged();
4539 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4541 DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
4544 HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
4545 : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
4546 HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
4547 : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
4548 ASSERT(to == LAST_TYPE); // Others not implemented yet in backend.
4552 InstanceType to_; // Inclusive range, not all combinations work.
4556 class HHasCachedArrayIndexAndBranch V8_FINAL : public HUnaryControlInstruction {
4558 DECLARE_INSTRUCTION_FACTORY_P1(HHasCachedArrayIndexAndBranch, HValue*);
4560 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4561 return Representation::Tagged();
4564 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
4566 explicit HHasCachedArrayIndexAndBranch(HValue* value)
4567 : HUnaryControlInstruction(value, NULL, NULL) { }
4571 class HGetCachedArrayIndex V8_FINAL : public HUnaryOperation {
4573 DECLARE_INSTRUCTION_FACTORY_P1(HGetCachedArrayIndex, HValue*);
4575 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4576 return Representation::Tagged();
4579 DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
4582 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4585 explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
4586 set_representation(Representation::Tagged());
4590 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4594 class HClassOfTestAndBranch V8_FINAL : public HUnaryControlInstruction {
4596 DECLARE_INSTRUCTION_FACTORY_P2(HClassOfTestAndBranch, HValue*,
4599 DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
4601 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4602 return Representation::Tagged();
4605 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4607 Handle<String> class_name() const { return class_name_; }
4610 HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
4611 : HUnaryControlInstruction(value, NULL, NULL),
4612 class_name_(class_name) { }
4614 Handle<String> class_name_;
4618 class HTypeofIsAndBranch V8_FINAL : public HUnaryControlInstruction {
4620 DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle<String>);
4622 Handle<String> type_literal() { return type_literal_.handle(); }
4623 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4625 DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
4627 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4628 return Representation::None();
4631 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4633 virtual void FinalizeUniqueness() V8_OVERRIDE {
4634 type_literal_ = Unique<String>(type_literal_.handle());
4638 HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
4639 : HUnaryControlInstruction(value, NULL, NULL),
4640 type_literal_(Unique<String>::CreateUninitialized(type_literal)) { }
4642 Unique<String> type_literal_;
4646 class HInstanceOf V8_FINAL : public HBinaryOperation {
4648 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOf, HValue*, HValue*);
4650 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4651 return Representation::Tagged();
4654 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4656 DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
4659 HInstanceOf(HValue* context, HValue* left, HValue* right)
4660 : HBinaryOperation(context, left, right, HType::Boolean()) {
4661 set_representation(Representation::Tagged());
4662 SetAllSideEffects();
4667 class HInstanceOfKnownGlobal V8_FINAL : public HTemplateInstruction<2> {
4669 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOfKnownGlobal,
4671 Handle<JSFunction>);
4673 HValue* context() { return OperandAt(0); }
4674 HValue* left() { return OperandAt(1); }
4675 Handle<JSFunction> function() { return function_; }
4677 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4678 return Representation::Tagged();
4681 DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal)
4684 HInstanceOfKnownGlobal(HValue* context,
4686 Handle<JSFunction> right)
4687 : HTemplateInstruction<2>(HType::Boolean()), function_(right) {
4688 SetOperandAt(0, context);
4689 SetOperandAt(1, left);
4690 set_representation(Representation::Tagged());
4691 SetAllSideEffects();
4694 Handle<JSFunction> function_;
4698 class HPower V8_FINAL : public HTemplateInstruction<2> {
4700 static HInstruction* New(Zone* zone,
4705 HValue* left() { return OperandAt(0); }
4706 HValue* right() const { return OperandAt(1); }
4708 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4710 ? Representation::Double()
4711 : Representation::None();
4713 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4714 return RequiredInputRepresentation(index);
4717 DECLARE_CONCRETE_INSTRUCTION(Power)
4720 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4723 HPower(HValue* left, HValue* right) {
4724 SetOperandAt(0, left);
4725 SetOperandAt(1, right);
4726 set_representation(Representation::Double());
4728 SetChangesFlag(kNewSpacePromotion);
4731 virtual bool IsDeletable() const V8_OVERRIDE {
4732 return !right()->representation().IsTagged();
4737 class HAdd V8_FINAL : public HArithmeticBinaryOperation {
4739 static HInstruction* New(Zone* zone,
4744 // Add is only commutative if two integer values are added and not if two
4745 // tagged values are added (because it might be a String concatenation).
4746 // We also do not commute (pointer + offset).
4747 virtual bool IsCommutative() const V8_OVERRIDE {
4748 return !representation().IsTagged() && !representation().IsExternal();
4751 virtual HValue* Canonicalize() V8_OVERRIDE;
4753 virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
4754 if (left()->IsInteger32Constant()) {
4755 decomposition->Apply(right(), left()->GetInteger32Constant());
4757 } else if (right()->IsInteger32Constant()) {
4758 decomposition->Apply(left(), right()->GetInteger32Constant());
4765 virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
4766 if (to.IsTagged() &&
4767 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() ||
4768 left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) {
4769 SetAllSideEffects();
4772 ClearAllSideEffects();
4775 if (to.IsTagged()) {
4776 SetChangesFlag(kNewSpacePromotion);
4777 ClearFlag(kAllowUndefinedAsNaN);
4781 virtual Representation RepresentationFromInputs() V8_OVERRIDE;
4783 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE;
4785 DECLARE_CONCRETE_INSTRUCTION(Add)
4788 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4790 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4793 HAdd(HValue* context, HValue* left, HValue* right)
4794 : HArithmeticBinaryOperation(context, left, right) {
4795 SetFlag(kCanOverflow);
4800 class HSub V8_FINAL : public HArithmeticBinaryOperation {
4802 static HInstruction* New(Zone* zone,
4807 virtual HValue* Canonicalize() V8_OVERRIDE;
4809 virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
4810 if (right()->IsInteger32Constant()) {
4811 decomposition->Apply(left(), -right()->GetInteger32Constant());
4818 DECLARE_CONCRETE_INSTRUCTION(Sub)
4821 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4823 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4826 HSub(HValue* context, HValue* left, HValue* right)
4827 : HArithmeticBinaryOperation(context, left, right) {
4828 SetFlag(kCanOverflow);
4833 class HMul V8_FINAL : public HArithmeticBinaryOperation {
4835 static HInstruction* New(Zone* zone,
4840 static HInstruction* NewImul(Zone* zone,
4844 HInstruction* instr = HMul::New(zone, context, left, right);
4845 if (!instr->IsMul()) return instr;
4846 HMul* mul = HMul::cast(instr);
4847 // TODO(mstarzinger): Prevent bailout on minus zero for imul.
4848 mul->AssumeRepresentation(Representation::Integer32());
4849 mul->ClearFlag(HValue::kCanOverflow);
4853 virtual HValue* Canonicalize() V8_OVERRIDE;
4855 // Only commutative if it is certain that not two objects are multiplicated.
4856 virtual bool IsCommutative() const V8_OVERRIDE {
4857 return !representation().IsTagged();
4860 virtual void UpdateRepresentation(Representation new_rep,
4861 HInferRepresentationPhase* h_infer,
4862 const char* reason) V8_OVERRIDE {
4863 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4868 DECLARE_CONCRETE_INSTRUCTION(Mul)
4871 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4873 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4876 HMul(HValue* context, HValue* left, HValue* right)
4877 : HArithmeticBinaryOperation(context, left, right) {
4878 SetFlag(kCanOverflow);
4883 class HMod V8_FINAL : public HArithmeticBinaryOperation {
4885 static HInstruction* New(Zone* zone,
4890 virtual HValue* Canonicalize() V8_OVERRIDE;
4892 virtual void UpdateRepresentation(Representation new_rep,
4893 HInferRepresentationPhase* h_infer,
4894 const char* reason) V8_OVERRIDE {
4895 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4896 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4899 DECLARE_CONCRETE_INSTRUCTION(Mod)
4902 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4904 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4907 HMod(HValue* context,
4909 HValue* right) : HArithmeticBinaryOperation(context, left, right) {
4910 SetFlag(kCanBeDivByZero);
4911 SetFlag(kCanOverflow);
4912 SetFlag(kLeftCanBeNegative);
4917 class HDiv V8_FINAL : public HArithmeticBinaryOperation {
4919 static HInstruction* New(Zone* zone,
4924 virtual HValue* Canonicalize() V8_OVERRIDE;
4926 virtual void UpdateRepresentation(Representation new_rep,
4927 HInferRepresentationPhase* h_infer,
4928 const char* reason) V8_OVERRIDE {
4929 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4930 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4933 DECLARE_CONCRETE_INSTRUCTION(Div)
4936 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4938 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4941 HDiv(HValue* context, HValue* left, HValue* right)
4942 : HArithmeticBinaryOperation(context, left, right) {
4943 SetFlag(kCanBeDivByZero);
4944 SetFlag(kCanOverflow);
4949 class HMathMinMax V8_FINAL : public HArithmeticBinaryOperation {
4951 enum Operation { kMathMin, kMathMax };
4953 static HInstruction* New(Zone* zone,
4959 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4960 return RequiredInputRepresentation(index);
4963 virtual void InferRepresentation(
4964 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4966 virtual Representation RepresentationFromInputs() V8_OVERRIDE {
4967 Representation left_rep = left()->representation();
4968 Representation right_rep = right()->representation();
4969 Representation result = Representation::Smi();
4970 result = result.generalize(left_rep);
4971 result = result.generalize(right_rep);
4972 if (result.IsTagged()) return Representation::Double();
4976 virtual bool IsCommutative() const V8_OVERRIDE { return true; }
4978 Operation operation() { return operation_; }
4980 DECLARE_CONCRETE_INSTRUCTION(MathMinMax)
4983 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
4984 return other->IsMathMinMax() &&
4985 HMathMinMax::cast(other)->operation_ == operation_;
4988 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4991 HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
4992 : HArithmeticBinaryOperation(context, left, right),
4995 Operation operation_;
4999 class HBitwise V8_FINAL : public HBitwiseBinaryOperation {
5001 static HInstruction* New(Zone* zone,
5007 Token::Value op() const { return op_; }
5009 virtual bool IsCommutative() const V8_OVERRIDE { return true; }
5011 virtual HValue* Canonicalize() V8_OVERRIDE;
5013 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5015 DECLARE_CONCRETE_INSTRUCTION(Bitwise)
5018 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
5019 return op() == HBitwise::cast(other)->op();
5022 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5025 HBitwise(HValue* context,
5029 : HBitwiseBinaryOperation(context, left, right, HType::TaggedNumber()),
5031 ASSERT(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
5032 // BIT_AND with a smi-range positive value will always unset the
5033 // entire sign-extension of the smi-sign.
5034 if (op == Token::BIT_AND &&
5035 ((left->IsConstant() &&
5036 left->representation().IsSmi() &&
5037 HConstant::cast(left)->Integer32Value() >= 0) ||
5038 (right->IsConstant() &&
5039 right->representation().IsSmi() &&
5040 HConstant::cast(right)->Integer32Value() >= 0))) {
5041 SetFlag(kTruncatingToSmi);
5042 SetFlag(kTruncatingToInt32);
5043 // BIT_OR with a smi-range negative value will always set the entire
5044 // sign-extension of the smi-sign.
5045 } else if (op == Token::BIT_OR &&
5046 ((left->IsConstant() &&
5047 left->representation().IsSmi() &&
5048 HConstant::cast(left)->Integer32Value() < 0) ||
5049 (right->IsConstant() &&
5050 right->representation().IsSmi() &&
5051 HConstant::cast(right)->Integer32Value() < 0))) {
5052 SetFlag(kTruncatingToSmi);
5053 SetFlag(kTruncatingToInt32);
5061 class HShl V8_FINAL : public HBitwiseBinaryOperation {
5063 static HInstruction* New(Zone* zone,
5068 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5070 virtual void UpdateRepresentation(Representation new_rep,
5071 HInferRepresentationPhase* h_infer,
5072 const char* reason) V8_OVERRIDE {
5073 if (new_rep.IsSmi() &&
5074 !(right()->IsInteger32Constant() &&
5075 right()->GetInteger32Constant() >= 0)) {
5076 new_rep = Representation::Integer32();
5078 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5081 DECLARE_CONCRETE_INSTRUCTION(Shl)
5084 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5087 HShl(HValue* context, HValue* left, HValue* right)
5088 : HBitwiseBinaryOperation(context, left, right) { }
5092 class HShr V8_FINAL : public HBitwiseBinaryOperation {
5094 static HInstruction* New(Zone* zone,
5099 virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
5100 if (right()->IsInteger32Constant()) {
5101 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
5102 // This is intended to look for HAdd and HSub, to handle compounds
5103 // like ((base + offset) >> scale) with one single decomposition.
5104 left()->TryDecompose(decomposition);
5111 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5113 virtual void UpdateRepresentation(Representation new_rep,
5114 HInferRepresentationPhase* h_infer,
5115 const char* reason) V8_OVERRIDE {
5116 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5117 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5120 DECLARE_CONCRETE_INSTRUCTION(Shr)
5123 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5126 HShr(HValue* context, HValue* left, HValue* right)
5127 : HBitwiseBinaryOperation(context, left, right) { }
5131 class HSar V8_FINAL : public HBitwiseBinaryOperation {
5133 static HInstruction* New(Zone* zone,
5138 virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
5139 if (right()->IsInteger32Constant()) {
5140 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
5141 // This is intended to look for HAdd and HSub, to handle compounds
5142 // like ((base + offset) >> scale) with one single decomposition.
5143 left()->TryDecompose(decomposition);
5150 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5152 virtual void UpdateRepresentation(Representation new_rep,
5153 HInferRepresentationPhase* h_infer,
5154 const char* reason) V8_OVERRIDE {
5155 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5156 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5159 DECLARE_CONCRETE_INSTRUCTION(Sar)
5162 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5165 HSar(HValue* context, HValue* left, HValue* right)
5166 : HBitwiseBinaryOperation(context, left, right) { }
5170 class HRor V8_FINAL : public HBitwiseBinaryOperation {
5172 static HInstruction* New(Zone* zone,
5176 return new(zone) HRor(context, left, right);
5179 virtual void UpdateRepresentation(Representation new_rep,
5180 HInferRepresentationPhase* h_infer,
5181 const char* reason) V8_OVERRIDE {
5182 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5183 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5186 DECLARE_CONCRETE_INSTRUCTION(Ror)
5189 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5192 HRor(HValue* context, HValue* left, HValue* right)
5193 : HBitwiseBinaryOperation(context, left, right) {
5194 ChangeRepresentation(Representation::Integer32());
5199 class HOsrEntry V8_FINAL : public HTemplateInstruction<0> {
5201 DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId);
5203 BailoutId ast_id() const { return ast_id_; }
5205 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5206 return Representation::None();
5209 DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
5212 explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
5213 SetChangesFlag(kOsrEntries);
5214 SetChangesFlag(kNewSpacePromotion);
5221 class HParameter V8_FINAL : public HTemplateInstruction<0> {
5223 enum ParameterKind {
5228 DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned);
5229 DECLARE_INSTRUCTION_FACTORY_P2(HParameter, unsigned, ParameterKind);
5230 DECLARE_INSTRUCTION_FACTORY_P3(HParameter, unsigned, ParameterKind,
5233 unsigned index() const { return index_; }
5234 ParameterKind kind() const { return kind_; }
5236 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5238 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5239 return Representation::None();
5242 DECLARE_CONCRETE_INSTRUCTION(Parameter)
5245 explicit HParameter(unsigned index,
5246 ParameterKind kind = STACK_PARAMETER)
5249 set_representation(Representation::Tagged());
5252 explicit HParameter(unsigned index,
5257 set_representation(r);
5261 ParameterKind kind_;
5265 class HCallStub V8_FINAL : public HUnaryCall {
5267 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallStub, CodeStub::Major, int);
5268 CodeStub::Major major_key() { return major_key_; }
5270 HValue* context() { return value(); }
5272 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5274 DECLARE_CONCRETE_INSTRUCTION(CallStub)
5277 HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
5278 : HUnaryCall(context, argument_count),
5279 major_key_(major_key) {
5282 CodeStub::Major major_key_;
5286 class HUnknownOSRValue V8_FINAL : public HTemplateInstruction<0> {
5288 DECLARE_INSTRUCTION_FACTORY_P2(HUnknownOSRValue, HEnvironment*, int);
5290 virtual void PrintDataTo(StringStream* stream);
5292 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5293 return Representation::None();
5296 void set_incoming_value(HPhi* value) { incoming_value_ = value; }
5297 HPhi* incoming_value() { return incoming_value_; }
5298 HEnvironment *environment() { return environment_; }
5299 int index() { return index_; }
5301 virtual Representation KnownOptimalRepresentation() V8_OVERRIDE {
5302 if (incoming_value_ == NULL) return Representation::None();
5303 return incoming_value_->KnownOptimalRepresentation();
5306 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
5309 HUnknownOSRValue(HEnvironment* environment, int index)
5310 : environment_(environment),
5312 incoming_value_(NULL) {
5313 set_representation(Representation::Tagged());
5316 HEnvironment* environment_;
5318 HPhi* incoming_value_;
5322 class HLoadGlobalCell V8_FINAL : public HTemplateInstruction<0> {
5324 DECLARE_INSTRUCTION_FACTORY_P2(HLoadGlobalCell, Handle<Cell>,
5327 Unique<Cell> cell() const { return cell_; }
5328 bool RequiresHoleCheck() const;
5330 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5332 virtual intptr_t Hashcode() V8_OVERRIDE {
5333 return cell_.Hashcode();
5336 virtual void FinalizeUniqueness() V8_OVERRIDE {
5337 cell_ = Unique<Cell>(cell_.handle());
5340 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5341 return Representation::None();
5344 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell)
5347 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
5348 return cell_ == HLoadGlobalCell::cast(other)->cell_;
5352 HLoadGlobalCell(Handle<Cell> cell, PropertyDetails details)
5353 : cell_(Unique<Cell>::CreateUninitialized(cell)), details_(details) {
5354 set_representation(Representation::Tagged());
5356 SetDependsOnFlag(kGlobalVars);
5359 virtual bool IsDeletable() const V8_OVERRIDE { return !RequiresHoleCheck(); }
5362 PropertyDetails details_;
5366 class HLoadGlobalGeneric V8_FINAL : public HTemplateInstruction<2> {
5368 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadGlobalGeneric, HValue*,
5369 Handle<Object>, bool);
5371 HValue* context() { return OperandAt(0); }
5372 HValue* global_object() { return OperandAt(1); }
5373 Handle<Object> name() const { return name_; }
5374 bool for_typeof() const { return for_typeof_; }
5376 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5378 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5379 return Representation::Tagged();
5382 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
5385 HLoadGlobalGeneric(HValue* context,
5386 HValue* global_object,
5387 Handle<Object> name,
5390 for_typeof_(for_typeof) {
5391 SetOperandAt(0, context);
5392 SetOperandAt(1, global_object);
5393 set_representation(Representation::Tagged());
5394 SetAllSideEffects();
5397 Handle<Object> name_;
5402 class HAllocate V8_FINAL : public HTemplateInstruction<2> {
5404 static bool CompatibleInstanceTypes(InstanceType type1,
5405 InstanceType type2) {
5406 return ComputeFlags(TENURED, type1) == ComputeFlags(TENURED, type2) &&
5407 ComputeFlags(NOT_TENURED, type1) == ComputeFlags(NOT_TENURED, type2);
5410 static HAllocate* New(Zone* zone,
5414 PretenureFlag pretenure_flag,
5415 InstanceType instance_type,
5416 Handle<AllocationSite> allocation_site =
5417 Handle<AllocationSite>::null()) {
5418 return new(zone) HAllocate(context, size, type, pretenure_flag,
5419 instance_type, allocation_site);
5422 // Maximum instance size for which allocations will be inlined.
5423 static const int kMaxInlineSize = 64 * kPointerSize;
5425 HValue* context() { return OperandAt(0); }
5426 HValue* size() { return OperandAt(1); }
5428 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5430 return Representation::Tagged();
5432 return Representation::Integer32();
5436 virtual Handle<Map> GetMonomorphicJSObjectMap() {
5437 return known_initial_map_;
5440 void set_known_initial_map(Handle<Map> known_initial_map) {
5441 known_initial_map_ = known_initial_map;
5444 bool IsNewSpaceAllocation() const {
5445 return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
5448 bool IsOldDataSpaceAllocation() const {
5449 return (flags_ & ALLOCATE_IN_OLD_DATA_SPACE) != 0;
5452 bool IsOldPointerSpaceAllocation() const {
5453 return (flags_ & ALLOCATE_IN_OLD_POINTER_SPACE) != 0;
5456 bool MustAllocateDoubleAligned() const {
5457 return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
5460 bool MustPrefillWithFiller() const {
5461 return (flags_ & PREFILL_WITH_FILLER) != 0;
5464 void MakePrefillWithFiller() {
5465 flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
5468 bool MustClearNextMapWord() const {
5469 return (flags_ & CLEAR_NEXT_MAP_WORD) != 0;
5472 void MakeDoubleAligned() {
5473 flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
5476 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
5477 HValue* dominator) V8_OVERRIDE;
5479 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5481 DECLARE_CONCRETE_INSTRUCTION(Allocate)
5485 ALLOCATE_IN_NEW_SPACE = 1 << 0,
5486 ALLOCATE_IN_OLD_DATA_SPACE = 1 << 1,
5487 ALLOCATE_IN_OLD_POINTER_SPACE = 1 << 2,
5488 ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
5489 PREFILL_WITH_FILLER = 1 << 4,
5490 CLEAR_NEXT_MAP_WORD = 1 << 5
5493 HAllocate(HValue* context,
5496 PretenureFlag pretenure_flag,
5497 InstanceType instance_type,
5498 Handle<AllocationSite> allocation_site =
5499 Handle<AllocationSite>::null())
5500 : HTemplateInstruction<2>(type),
5501 flags_(ComputeFlags(pretenure_flag, instance_type)),
5502 dominating_allocate_(NULL),
5503 filler_free_space_size_(NULL) {
5504 SetOperandAt(0, context);
5505 SetOperandAt(1, size);
5506 set_representation(Representation::Tagged());
5507 SetFlag(kTrackSideEffectDominators);
5508 SetChangesFlag(kNewSpacePromotion);
5509 SetDependsOnFlag(kNewSpacePromotion);
5511 if (FLAG_trace_pretenuring) {
5512 PrintF("HAllocate with AllocationSite %p %s\n",
5513 allocation_site.is_null()
5514 ? static_cast<void*>(NULL)
5515 : static_cast<void*>(*allocation_site),
5516 pretenure_flag == TENURED ? "tenured" : "not tenured");
5520 static Flags ComputeFlags(PretenureFlag pretenure_flag,
5521 InstanceType instance_type) {
5522 Flags flags = pretenure_flag == TENURED
5523 ? (Heap::TargetSpaceId(instance_type) == OLD_POINTER_SPACE
5524 ? ALLOCATE_IN_OLD_POINTER_SPACE : ALLOCATE_IN_OLD_DATA_SPACE)
5525 : ALLOCATE_IN_NEW_SPACE;
5526 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
5527 flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED);
5529 // We have to fill the allocated object with one word fillers if we do
5530 // not use allocation folding since some allocations may depend on each
5531 // other, i.e., have a pointer to each other. A GC in between these
5532 // allocations may leave such objects behind in a not completely initialized
5534 if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
5535 flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER);
5537 if (pretenure_flag == NOT_TENURED &&
5538 AllocationSite::CanTrack(instance_type)) {
5539 flags = static_cast<Flags>(flags | CLEAR_NEXT_MAP_WORD);
5544 void UpdateClearNextMapWord(bool clear_next_map_word) {
5545 flags_ = static_cast<Flags>(clear_next_map_word
5546 ? flags_ | CLEAR_NEXT_MAP_WORD
5547 : flags_ & ~CLEAR_NEXT_MAP_WORD);
5550 void UpdateSize(HValue* size) {
5551 SetOperandAt(1, size);
5554 HAllocate* GetFoldableDominator(HAllocate* dominator);
5556 void UpdateFreeSpaceFiller(int32_t filler_size);
5558 void CreateFreeSpaceFiller(int32_t filler_size);
5560 bool IsFoldable(HAllocate* allocate) {
5561 return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) ||
5562 (IsOldDataSpaceAllocation() && allocate->IsOldDataSpaceAllocation()) ||
5563 (IsOldPointerSpaceAllocation() &&
5564 allocate->IsOldPointerSpaceAllocation());
5567 void ClearNextMapWord(int offset);
5570 Handle<Map> known_initial_map_;
5571 HAllocate* dominating_allocate_;
5572 HStoreNamedField* filler_free_space_size_;
5576 class HStoreCodeEntry V8_FINAL: public HTemplateInstruction<2> {
5578 static HStoreCodeEntry* New(Zone* zone,
5582 return new(zone) HStoreCodeEntry(function, code);
5585 virtual Representation RequiredInputRepresentation(int index) {
5586 return Representation::Tagged();
5589 HValue* function() { return OperandAt(0); }
5590 HValue* code_object() { return OperandAt(1); }
5592 DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry)
5595 HStoreCodeEntry(HValue* function, HValue* code) {
5596 SetOperandAt(0, function);
5597 SetOperandAt(1, code);
5602 class HInnerAllocatedObject V8_FINAL : public HTemplateInstruction<2> {
5604 static HInnerAllocatedObject* New(Zone* zone,
5608 HType type = HType::Tagged()) {
5609 return new(zone) HInnerAllocatedObject(value, offset, type);
5612 HValue* base_object() { return OperandAt(0); }
5613 HValue* offset() { return OperandAt(1); }
5615 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5616 return index == 0 ? Representation::Tagged() : Representation::Integer32();
5619 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5621 DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
5624 HInnerAllocatedObject(HValue* value,
5626 HType type = HType::Tagged())
5627 : HTemplateInstruction<2>(type) {
5628 ASSERT(value->IsAllocate());
5629 SetOperandAt(0, value);
5630 SetOperandAt(1, offset);
5632 set_representation(Representation::Tagged());
5637 inline bool StoringValueNeedsWriteBarrier(HValue* value) {
5638 return !value->type().IsBoolean()
5639 && !value->type().IsSmi()
5640 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
5644 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
5646 HValue* new_space_dominator) {
5647 while (object->IsInnerAllocatedObject()) {
5648 object = HInnerAllocatedObject::cast(object)->base_object();
5650 if (object->IsConstant() && HConstant::cast(object)->IsCell()) {
5653 if (object->IsConstant() &&
5654 HConstant::cast(object)->HasExternalReferenceValue()) {
5655 // Stores to external references require no write barriers
5658 if (object != new_space_dominator) return true;
5659 if (object->IsAllocate()) {
5660 // Stores to new space allocations require no write barriers if the object
5661 // is the new space dominator.
5662 if (HAllocate::cast(object)->IsNewSpaceAllocation()) {
5665 // Likewise we don't need a write barrier if we store a value that
5666 // originates from the same allocation (via allocation folding).
5667 while (value->IsInnerAllocatedObject()) {
5668 value = HInnerAllocatedObject::cast(value)->base_object();
5670 return object != value;
5676 class HStoreGlobalCell V8_FINAL : public HUnaryOperation {
5678 DECLARE_INSTRUCTION_FACTORY_P3(HStoreGlobalCell, HValue*,
5679 Handle<PropertyCell>, PropertyDetails);
5681 Unique<PropertyCell> cell() const { return cell_; }
5682 bool RequiresHoleCheck() {
5683 return !details_.IsDontDelete() || details_.IsReadOnly();
5685 bool NeedsWriteBarrier() {
5686 return StoringValueNeedsWriteBarrier(value());
5689 virtual void FinalizeUniqueness() V8_OVERRIDE {
5690 cell_ = Unique<PropertyCell>(cell_.handle());
5693 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5694 return Representation::Tagged();
5696 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5698 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell)
5701 HStoreGlobalCell(HValue* value,
5702 Handle<PropertyCell> cell,
5703 PropertyDetails details)
5704 : HUnaryOperation(value),
5705 cell_(Unique<PropertyCell>::CreateUninitialized(cell)),
5707 SetChangesFlag(kGlobalVars);
5710 Unique<PropertyCell> cell_;
5711 PropertyDetails details_;
5715 class HLoadContextSlot V8_FINAL : public HUnaryOperation {
5718 // Perform a normal load of the context slot without checking its value.
5720 // Load and check the value of the context slot. Deoptimize if it's the
5721 // hole value. This is used for checking for loading of uninitialized
5722 // harmony bindings where we deoptimize into full-codegen generated code
5723 // which will subsequently throw a reference error.
5725 // Load and check the value of the context slot. Return undefined if it's
5726 // the hole value. This is used for non-harmony const assignments
5727 kCheckReturnUndefined
5730 HLoadContextSlot(HValue* context, Variable* var)
5731 : HUnaryOperation(context), slot_index_(var->index()) {
5732 ASSERT(var->IsContextSlot());
5733 switch (var->mode()) {
5736 mode_ = kCheckDeoptimize;
5739 mode_ = kCheckReturnUndefined;
5744 set_representation(Representation::Tagged());
5746 SetDependsOnFlag(kContextSlots);
5749 int slot_index() const { return slot_index_; }
5750 Mode mode() const { return mode_; }
5752 bool DeoptimizesOnHole() {
5753 return mode_ == kCheckDeoptimize;
5756 bool RequiresHoleCheck() const {
5757 return mode_ != kNoCheck;
5760 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5761 return Representation::Tagged();
5764 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5766 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
5769 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
5770 HLoadContextSlot* b = HLoadContextSlot::cast(other);
5771 return (slot_index() == b->slot_index());
5775 virtual bool IsDeletable() const V8_OVERRIDE { return !RequiresHoleCheck(); }
5782 class HStoreContextSlot V8_FINAL : public HTemplateInstruction<2> {
5785 // Perform a normal store to the context slot without checking its previous
5788 // Check the previous value of the context slot and deoptimize if it's the
5789 // hole value. This is used for checking for assignments to uninitialized
5790 // harmony bindings where we deoptimize into full-codegen generated code
5791 // which will subsequently throw a reference error.
5793 // Check the previous value and ignore assignment if it isn't a hole value
5794 kCheckIgnoreAssignment
5797 DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
5800 HValue* context() { return OperandAt(0); }
5801 HValue* value() { return OperandAt(1); }
5802 int slot_index() const { return slot_index_; }
5803 Mode mode() const { return mode_; }
5805 bool NeedsWriteBarrier() {
5806 return StoringValueNeedsWriteBarrier(value());
5809 bool DeoptimizesOnHole() {
5810 return mode_ == kCheckDeoptimize;
5813 bool RequiresHoleCheck() {
5814 return mode_ != kNoCheck;
5817 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5818 return Representation::Tagged();
5821 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5823 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
5826 HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
5827 : slot_index_(slot_index), mode_(mode) {
5828 SetOperandAt(0, context);
5829 SetOperandAt(1, value);
5830 SetChangesFlag(kContextSlots);
5838 // Represents an access to a portion of an object, such as the map pointer,
5839 // array elements pointer, etc, but not accesses to array elements themselves.
5840 class HObjectAccess V8_FINAL {
5842 inline bool IsInobject() const {
5843 return portion() != kBackingStore && portion() != kExternalMemory;
5846 inline bool IsExternalMemory() const {
5847 return portion() == kExternalMemory;
5850 inline bool IsStringLength() const {
5851 return portion() == kStringLengths;
5854 inline int offset() const {
5855 return OffsetField::decode(value_);
5858 inline Representation representation() const {
5859 return Representation::FromKind(RepresentationField::decode(value_));
5862 inline Handle<String> name() const {
5866 inline bool immutable() const {
5867 return ImmutableField::decode(value_);
5870 // Returns true if access is being made to an in-object property that
5871 // was already added to the object.
5872 inline bool existing_inobject_property() const {
5873 return ExistingInobjectPropertyField::decode(value_);
5876 inline HObjectAccess WithRepresentation(Representation representation) {
5877 return HObjectAccess(portion(), offset(), representation, name(),
5878 immutable(), existing_inobject_property());
5881 static HObjectAccess ForHeapNumberValue() {
5882 return HObjectAccess(
5883 kDouble, HeapNumber::kValueOffset, Representation::Double());
5886 static HObjectAccess ForHeapNumberValueLowestBits() {
5887 return HObjectAccess(kDouble,
5888 HeapNumber::kValueOffset,
5889 Representation::Integer32());
5892 static HObjectAccess ForHeapNumberValueHighestBits() {
5893 return HObjectAccess(kDouble,
5894 HeapNumber::kValueOffset + kIntSize,
5895 Representation::Integer32());
5898 static HObjectAccess ForElementsPointer() {
5899 return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
5902 static HObjectAccess ForLiteralsPointer() {
5903 return HObjectAccess(kInobject, JSFunction::kLiteralsOffset);
5906 static HObjectAccess ForNextFunctionLinkPointer() {
5907 return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
5910 static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
5911 return HObjectAccess(
5913 JSArray::kLengthOffset,
5914 IsFastElementsKind(elements_kind)
5915 ? Representation::Smi() : Representation::Tagged());
5918 static HObjectAccess ForAllocationSiteOffset(int offset);
5920 static HObjectAccess ForAllocationSiteList() {
5921 return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
5922 Handle<String>::null(), false, false);
5925 static HObjectAccess ForFixedArrayLength() {
5926 return HObjectAccess(
5928 FixedArray::kLengthOffset,
5929 Representation::Smi());
5932 static HObjectAccess ForStringHashField() {
5933 return HObjectAccess(kInobject,
5934 String::kHashFieldOffset,
5935 Representation::Integer32());
5938 static HObjectAccess ForStringLength() {
5939 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
5940 return HObjectAccess(
5942 String::kLengthOffset,
5943 Representation::Smi());
5946 static HObjectAccess ForConsStringFirst() {
5947 return HObjectAccess(kInobject, ConsString::kFirstOffset);
5950 static HObjectAccess ForConsStringSecond() {
5951 return HObjectAccess(kInobject, ConsString::kSecondOffset);
5954 static HObjectAccess ForPropertiesPointer() {
5955 return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
5958 static HObjectAccess ForPrototypeOrInitialMap() {
5959 return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
5962 static HObjectAccess ForSharedFunctionInfoPointer() {
5963 return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
5966 static HObjectAccess ForCodeEntryPointer() {
5967 return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
5970 static HObjectAccess ForCodeOffset() {
5971 return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
5974 static HObjectAccess ForOptimizedCodeMap() {
5975 return HObjectAccess(kInobject,
5976 SharedFunctionInfo::kOptimizedCodeMapOffset);
5979 static HObjectAccess ForFunctionContextPointer() {
5980 return HObjectAccess(kInobject, JSFunction::kContextOffset);
5983 static HObjectAccess ForMap() {
5984 return HObjectAccess(kMaps, JSObject::kMapOffset);
5987 static HObjectAccess ForMapInstanceSize() {
5988 return HObjectAccess(kInobject,
5989 Map::kInstanceSizeOffset,
5990 Representation::UInteger8());
5993 static HObjectAccess ForMapInstanceType() {
5994 return HObjectAccess(kInobject,
5995 Map::kInstanceTypeOffset,
5996 Representation::UInteger8());
5999 static HObjectAccess ForMapPrototype() {
6000 return HObjectAccess(kInobject, Map::kPrototypeOffset);
6003 static HObjectAccess ForPropertyCellValue() {
6004 return HObjectAccess(kInobject, PropertyCell::kValueOffset);
6007 static HObjectAccess ForCellValue() {
6008 return HObjectAccess(kInobject, Cell::kValueOffset);
6011 static HObjectAccess ForAllocationMementoSite() {
6012 return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
6015 static HObjectAccess ForCounter() {
6016 return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
6017 Handle<String>::null(), false, false);
6020 // Create an access to an offset in a fixed array header.
6021 static HObjectAccess ForFixedArrayHeader(int offset);
6023 // Create an access to an in-object property in a JSObject.
6024 // This kind of access must be used when the object |map| is known and
6025 // in-object properties are being accessed. Accesses of the in-object
6026 // properties can have different semantics depending on whether corresponding
6027 // property was added to the map or not.
6028 static HObjectAccess ForMapAndOffset(Handle<Map> map, int offset,
6029 Representation representation = Representation::Tagged());
6031 // Create an access to an in-object property in a JSObject.
6032 // This kind of access can be used for accessing object header fields or
6033 // in-object properties if the map of the object is not known.
6034 static HObjectAccess ForObservableJSObjectOffset(int offset,
6035 Representation representation = Representation::Tagged()) {
6036 return ForMapAndOffset(Handle<Map>::null(), offset, representation);
6039 // Create an access to an in-object property in a JSArray.
6040 static HObjectAccess ForJSArrayOffset(int offset);
6042 static HObjectAccess ForContextSlot(int index);
6044 // Create an access to the backing store of an object.
6045 static HObjectAccess ForBackingStoreOffset(int offset,
6046 Representation representation = Representation::Tagged());
6048 // Create an access to a resolved field (in-object or backing store).
6049 static HObjectAccess ForField(Handle<Map> map,
6050 LookupResult *lookup, Handle<String> name = Handle<String>::null());
6052 // Create an access for the payload of a Cell or JSGlobalPropertyCell.
6053 static HObjectAccess ForCellPayload(Isolate* isolate);
6055 static HObjectAccess ForJSTypedArrayLength() {
6056 return HObjectAccess::ForObservableJSObjectOffset(
6057 JSTypedArray::kLengthOffset);
6060 static HObjectAccess ForJSArrayBufferBackingStore() {
6061 return HObjectAccess::ForObservableJSObjectOffset(
6062 JSArrayBuffer::kBackingStoreOffset, Representation::External());
6065 static HObjectAccess ForExternalArrayExternalPointer() {
6066 return HObjectAccess::ForObservableJSObjectOffset(
6067 ExternalArray::kExternalPointerOffset, Representation::External());
6070 static HObjectAccess ForJSArrayBufferViewWeakNext() {
6071 return HObjectAccess::ForObservableJSObjectOffset(
6072 JSArrayBufferView::kWeakNextOffset);
6075 static HObjectAccess ForJSArrayBufferWeakFirstView() {
6076 return HObjectAccess::ForObservableJSObjectOffset(
6077 JSArrayBuffer::kWeakFirstViewOffset);
6080 static HObjectAccess ForJSArrayBufferViewBuffer() {
6081 return HObjectAccess::ForObservableJSObjectOffset(
6082 JSArrayBufferView::kBufferOffset);
6085 static HObjectAccess ForJSArrayBufferViewByteOffset() {
6086 return HObjectAccess::ForObservableJSObjectOffset(
6087 JSArrayBufferView::kByteOffsetOffset);
6090 static HObjectAccess ForJSArrayBufferViewByteLength() {
6091 return HObjectAccess::ForObservableJSObjectOffset(
6092 JSArrayBufferView::kByteLengthOffset);
6095 static HObjectAccess ForGlobalObjectNativeContext() {
6096 return HObjectAccess(kInobject, GlobalObject::kNativeContextOffset);
6099 void PrintTo(StringStream* stream) const;
6101 inline bool Equals(HObjectAccess that) const {
6102 return value_ == that.value_; // portion and offset must match
6106 void SetGVNFlags(HValue *instr, PropertyAccessType access_type);
6109 // internal use only; different parts of an object or array
6111 kMaps, // map of an object
6112 kArrayLengths, // the length of an array
6113 kStringLengths, // the length of a string
6114 kElementsPointer, // elements pointer
6115 kBackingStore, // some field in the backing store
6116 kDouble, // some double field
6117 kInobject, // some other in-object field
6118 kExternalMemory // some field in external memory
6121 HObjectAccess() : value_(0) {}
6123 HObjectAccess(Portion portion, int offset,
6124 Representation representation = Representation::Tagged(),
6125 Handle<String> name = Handle<String>::null(),
6126 bool immutable = false,
6127 bool existing_inobject_property = true)
6128 : value_(PortionField::encode(portion) |
6129 RepresentationField::encode(representation.kind()) |
6130 ImmutableField::encode(immutable ? 1 : 0) |
6131 ExistingInobjectPropertyField::encode(
6132 existing_inobject_property ? 1 : 0) |
6133 OffsetField::encode(offset)),
6135 // assert that the fields decode correctly
6136 ASSERT(this->offset() == offset);
6137 ASSERT(this->portion() == portion);
6138 ASSERT(this->immutable() == immutable);
6139 ASSERT(this->existing_inobject_property() == existing_inobject_property);
6140 ASSERT(RepresentationField::decode(value_) == representation.kind());
6141 ASSERT(!this->existing_inobject_property() || IsInobject());
6144 class PortionField : public BitField<Portion, 0, 3> {};
6145 class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
6146 class ImmutableField : public BitField<bool, 7, 1> {};
6147 class ExistingInobjectPropertyField : public BitField<bool, 8, 1> {};
6148 class OffsetField : public BitField<int, 9, 23> {};
6150 uint32_t value_; // encodes portion, representation, immutable, and offset
6151 Handle<String> name_;
6153 friend class HLoadNamedField;
6154 friend class HStoreNamedField;
6155 friend class SideEffectsTracker;
6157 inline Portion portion() const {
6158 return PortionField::decode(value_);
6163 class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> {
6165 DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*, HValue*,
6168 HValue* object() { return OperandAt(0); }
6169 HValue* dependency() {
6170 ASSERT(HasDependency());
6171 return OperandAt(1);
6173 bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
6174 HObjectAccess access() const { return access_; }
6175 Representation field_representation() const {
6176 return access_.representation();
6179 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
6180 virtual bool HasOutOfBoundsAccess(int size) V8_OVERRIDE {
6181 return !access().IsInobject() || access().offset() >= size;
6183 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6184 if (index == 0 && access().IsExternalMemory()) {
6185 // object must be external in case of external memory access
6186 return Representation::External();
6188 return Representation::Tagged();
6190 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
6191 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6193 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
6196 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
6197 HLoadNamedField* b = HLoadNamedField::cast(other);
6198 return access_.Equals(b->access_);
6202 HLoadNamedField(HValue* object,
6204 HObjectAccess access) : access_(access) {
6205 ASSERT(object != NULL);
6206 SetOperandAt(0, object);
6207 SetOperandAt(1, dependency != NULL ? dependency : object);
6209 Representation representation = access.representation();
6210 if (representation.IsInteger8() ||
6211 representation.IsUInteger8() ||
6212 representation.IsInteger16() ||
6213 representation.IsUInteger16()) {
6214 set_representation(Representation::Integer32());
6215 } else if (representation.IsSmi()) {
6216 set_type(HType::Smi());
6217 if (SmiValuesAre32Bits()) {
6218 set_representation(Representation::Integer32());
6220 set_representation(representation);
6222 } else if (representation.IsDouble() ||
6223 representation.IsExternal() ||
6224 representation.IsInteger32()) {
6225 set_representation(representation);
6226 } else if (representation.IsHeapObject()) {
6227 set_type(HType::NonPrimitive());
6228 set_representation(Representation::Tagged());
6230 set_representation(Representation::Tagged());
6232 access.SetGVNFlags(this, LOAD);
6235 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
6237 HObjectAccess access_;
6241 class HLoadNamedGeneric V8_FINAL : public HTemplateInstruction<2> {
6243 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadNamedGeneric, HValue*,
6246 HValue* context() { return OperandAt(0); }
6247 HValue* object() { return OperandAt(1); }
6248 Handle<Object> name() const { return name_; }
6250 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6251 return Representation::Tagged();
6254 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6256 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
6259 HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
6261 SetOperandAt(0, context);
6262 SetOperandAt(1, object);
6263 set_representation(Representation::Tagged());
6264 SetAllSideEffects();
6267 Handle<Object> name_;
6271 class HLoadFunctionPrototype V8_FINAL : public HUnaryOperation {
6273 DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);
6275 HValue* function() { return OperandAt(0); }
6277 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6278 return Representation::Tagged();
6281 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
6284 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
6287 explicit HLoadFunctionPrototype(HValue* function)
6288 : HUnaryOperation(function) {
6289 set_representation(Representation::Tagged());
6291 SetDependsOnFlag(kCalls);
6295 class ArrayInstructionInterface {
6297 virtual HValue* GetKey() = 0;
6298 virtual void SetKey(HValue* key) = 0;
6299 virtual void SetIndexOffset(uint32_t index_offset) = 0;
6300 virtual int MaxIndexOffsetBits() = 0;
6301 virtual bool IsDehoisted() = 0;
6302 virtual void SetDehoisted(bool is_dehoisted) = 0;
6303 virtual ~ArrayInstructionInterface() { };
6305 static Representation KeyedAccessIndexRequirement(Representation r) {
6306 return r.IsInteger32() || SmiValuesAre32Bits()
6307 ? Representation::Integer32() : Representation::Smi();
6312 enum LoadKeyedHoleMode {
6318 class HLoadKeyed V8_FINAL
6319 : public HTemplateInstruction<3>, public ArrayInstructionInterface {
6321 DECLARE_INSTRUCTION_FACTORY_P4(HLoadKeyed, HValue*, HValue*, HValue*,
6323 DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*,
6324 ElementsKind, LoadKeyedHoleMode);
6326 bool is_external() const {
6327 return IsExternalArrayElementsKind(elements_kind());
6329 bool is_fixed_typed_array() const {
6330 return IsFixedTypedArrayElementsKind(elements_kind());
6332 bool is_typed_elements() const {
6333 return is_external() || is_fixed_typed_array();
6335 HValue* elements() { return OperandAt(0); }
6336 HValue* key() { return OperandAt(1); }
6337 HValue* dependency() {
6338 ASSERT(HasDependency());
6339 return OperandAt(2);
6341 bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
6342 uint32_t index_offset() { return IndexOffsetField::decode(bit_field_); }
6343 void SetIndexOffset(uint32_t index_offset) {
6344 bit_field_ = IndexOffsetField::update(bit_field_, index_offset);
6346 virtual int MaxIndexOffsetBits() {
6347 return kBitsForIndexOffset;
6349 HValue* GetKey() { return key(); }
6350 void SetKey(HValue* key) { SetOperandAt(1, key); }
6351 bool IsDehoisted() { return IsDehoistedField::decode(bit_field_); }
6352 void SetDehoisted(bool is_dehoisted) {
6353 bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
6355 ElementsKind elements_kind() const {
6356 return ElementsKindField::decode(bit_field_);
6358 LoadKeyedHoleMode hole_mode() const {
6359 return HoleModeField::decode(bit_field_);
6362 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6363 // kind_fast: tagged[int32] (none)
6364 // kind_double: tagged[int32] (none)
6365 // kind_fixed_typed_array: tagged[int32] (none)
6366 // kind_external: external[int32] (none)
6368 return is_external() ? Representation::External()
6369 : Representation::Tagged();
6372 return ArrayInstructionInterface::KeyedAccessIndexRequirement(
6373 OperandAt(1)->representation());
6375 return Representation::None();
6378 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
6379 return RequiredInputRepresentation(index);
6382 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6384 bool UsesMustHandleHole() const;
6385 bool AllUsesCanTreatHoleAsNaN() const;
6386 bool RequiresHoleCheck() const;
6388 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
6390 DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)
6393 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
6394 if (!other->IsLoadKeyed()) return false;
6395 HLoadKeyed* other_load = HLoadKeyed::cast(other);
6397 if (IsDehoisted() && index_offset() != other_load->index_offset())
6399 return elements_kind() == other_load->elements_kind();
6403 HLoadKeyed(HValue* obj,
6406 ElementsKind elements_kind,
6407 LoadKeyedHoleMode mode = NEVER_RETURN_HOLE)
6409 bit_field_ = ElementsKindField::encode(elements_kind) |
6410 HoleModeField::encode(mode);
6412 SetOperandAt(0, obj);
6413 SetOperandAt(1, key);
6414 SetOperandAt(2, dependency != NULL ? dependency : obj);
6416 if (!is_typed_elements()) {
6417 // I can detect the case between storing double (holey and fast) and
6418 // smi/object by looking at elements_kind_.
6419 ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
6420 IsFastDoubleElementsKind(elements_kind));
6422 if (IsFastSmiOrObjectElementsKind(elements_kind)) {
6423 if (IsFastSmiElementsKind(elements_kind) &&
6424 (!IsHoleyElementsKind(elements_kind) ||
6425 mode == NEVER_RETURN_HOLE)) {
6426 set_type(HType::Smi());
6427 if (SmiValuesAre32Bits() && !RequiresHoleCheck()) {
6428 set_representation(Representation::Integer32());
6430 set_representation(Representation::Smi());
6433 set_representation(Representation::Tagged());
6436 SetDependsOnFlag(kArrayElements);
6438 set_representation(Representation::Double());
6439 SetDependsOnFlag(kDoubleArrayElements);
6442 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
6443 elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
6444 elements_kind == FLOAT32_ELEMENTS ||
6445 elements_kind == FLOAT64_ELEMENTS) {
6446 set_representation(Representation::Double());
6447 } else if (IsFloat32x4ElementsKind(elements_kind)) {
6448 set_representation(CPU::SupportsSIMD128InCrankshaft() ?
6449 Representation::Float32x4() : Representation::Tagged());
6450 } else if (IsInt32x4ElementsKind(elements_kind)) {
6451 set_representation(CPU::SupportsSIMD128InCrankshaft() ?
6452 Representation::Int32x4() : Representation::Tagged());
6454 set_representation(Representation::Integer32());
6457 if (is_external()) {
6458 SetDependsOnFlag(kExternalMemory);
6459 } else if (is_fixed_typed_array()) {
6460 SetDependsOnFlag(kTypedArrayElements);
6464 // Native code could change the specialized array.
6465 SetDependsOnFlag(kCalls);
6471 virtual bool IsDeletable() const V8_OVERRIDE {
6472 return !RequiresHoleCheck();
6475 // Establish some checks around our packed fields
6476 enum LoadKeyedBits {
6477 kBitsForElementsKind = 5,
6478 kBitsForHoleMode = 1,
6479 kBitsForIndexOffset = 25,
6480 kBitsForIsDehoisted = 1,
6482 kStartElementsKind = 0,
6483 kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
6484 kStartIndexOffset = kStartHoleMode + kBitsForHoleMode,
6485 kStartIsDehoisted = kStartIndexOffset + kBitsForIndexOffset
6488 STATIC_ASSERT((kBitsForElementsKind + kBitsForIndexOffset +
6489 kBitsForIsDehoisted) <= sizeof(uint32_t)*8);
6490 STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
6491 class ElementsKindField:
6492 public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
6494 class HoleModeField:
6495 public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
6497 class IndexOffsetField:
6498 public BitField<uint32_t, kStartIndexOffset, kBitsForIndexOffset>
6500 class IsDehoistedField:
6501 public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
6503 uint32_t bit_field_;
6507 class HLoadKeyedGeneric V8_FINAL : public HTemplateInstruction<3> {
6509 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadKeyedGeneric, HValue*,
6511 HValue* object() { return OperandAt(0); }
6512 HValue* key() { return OperandAt(1); }
6513 HValue* context() { return OperandAt(2); }
6515 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6517 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6519 return Representation::Tagged();
6522 virtual HValue* Canonicalize() V8_OVERRIDE;
6524 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
6527 HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key) {
6528 set_representation(Representation::Tagged());
6529 SetOperandAt(0, obj);
6530 SetOperandAt(1, key);
6531 SetOperandAt(2, context);
6532 SetAllSideEffects();
6537 // Indicates whether the store is a store to an entry that was previously
6538 // initialized or not.
6539 enum StoreFieldOrKeyedMode {
6540 // The entry could be either previously initialized or not.
6542 // At the time of this store it is guaranteed that the entry is already
6544 STORE_TO_INITIALIZED_ENTRY
6548 class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> {
6550 DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
6551 HObjectAccess, HValue*);
6552 DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue*,
6553 HObjectAccess, HValue*, StoreFieldOrKeyedMode);
6555 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
6557 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE {
6560 virtual bool HasOutOfBoundsAccess(int size) V8_OVERRIDE {
6561 return !access().IsInobject() || access().offset() >= size;
6563 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6564 if (index == 0 && access().IsExternalMemory()) {
6565 // object must be external in case of external memory access
6566 return Representation::External();
6567 } else if (index == 1) {
6568 if (field_representation().IsInteger8() ||
6569 field_representation().IsUInteger8() ||
6570 field_representation().IsInteger16() ||
6571 field_representation().IsUInteger16() ||
6572 field_representation().IsInteger32()) {
6573 return Representation::Integer32();
6574 } else if (field_representation().IsDouble()) {
6575 return field_representation();
6576 } else if (field_representation().IsSmi()) {
6577 if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
6578 return Representation::Integer32();
6580 return field_representation();
6581 } else if (field_representation().IsExternal()) {
6582 return Representation::External();
6585 return Representation::Tagged();
6587 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
6588 HValue* dominator) V8_OVERRIDE {
6589 ASSERT(side_effect == kNewSpacePromotion);
6590 if (!FLAG_use_write_barrier_elimination) return false;
6591 new_space_dominator_ = dominator;
6594 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6596 void SkipWriteBarrier() { write_barrier_mode_ = SKIP_WRITE_BARRIER; }
6597 bool IsSkipWriteBarrier() const {
6598 return write_barrier_mode_ == SKIP_WRITE_BARRIER;
6601 HValue* object() const { return OperandAt(0); }
6602 HValue* value() const { return OperandAt(1); }
6603 HValue* transition() const { return OperandAt(2); }
6605 HObjectAccess access() const { return access_; }
6606 HValue* new_space_dominator() const { return new_space_dominator_; }
6607 bool has_transition() const { return has_transition_; }
6608 StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
6610 Handle<Map> transition_map() const {
6611 if (has_transition()) {
6612 return Handle<Map>::cast(
6613 HConstant::cast(transition())->handle(Isolate::Current()));
6615 return Handle<Map>();
6619 void SetTransition(HConstant* map_constant, CompilationInfo* info) {
6620 ASSERT(!has_transition()); // Only set once.
6621 Handle<Map> map = Handle<Map>::cast(map_constant->handle(info->isolate()));
6622 if (map->CanBeDeprecated()) {
6623 map->AddDependentCompilationInfo(DependentCode::kTransitionGroup, info);
6625 SetOperandAt(2, map_constant);
6626 has_transition_ = true;
6629 bool NeedsWriteBarrier() {
6630 ASSERT(!field_representation().IsDouble() || !has_transition());
6631 if (IsSkipWriteBarrier()) return false;
6632 if (field_representation().IsDouble()) return false;
6633 if (field_representation().IsSmi()) return false;
6634 if (field_representation().IsInteger32()) return false;
6635 if (field_representation().IsExternal()) return false;
6636 return StoringValueNeedsWriteBarrier(value()) &&
6637 ReceiverObjectNeedsWriteBarrier(object(), value(),
6638 new_space_dominator());
6641 bool NeedsWriteBarrierForMap() {
6642 if (IsSkipWriteBarrier()) return false;
6643 return ReceiverObjectNeedsWriteBarrier(object(), transition(),
6644 new_space_dominator());
6647 Representation field_representation() const {
6648 return access_.representation();
6651 void UpdateValue(HValue* value) {
6652 SetOperandAt(1, value);
6656 HStoreNamedField(HValue* obj,
6657 HObjectAccess access,
6659 StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
6661 new_space_dominator_(NULL),
6662 write_barrier_mode_(UPDATE_WRITE_BARRIER),
6663 has_transition_(false),
6664 store_mode_(store_mode) {
6665 // Stores to a non existing in-object property are allowed only to the
6666 // newly allocated objects (via HAllocate or HInnerAllocatedObject).
6667 ASSERT(!access.IsInobject() || access.existing_inobject_property() ||
6668 obj->IsAllocate() || obj->IsInnerAllocatedObject());
6669 SetOperandAt(0, obj);
6670 SetOperandAt(1, val);
6671 SetOperandAt(2, obj);
6672 access.SetGVNFlags(this, STORE);
6675 HObjectAccess access_;
6676 HValue* new_space_dominator_;
6677 WriteBarrierMode write_barrier_mode_ : 1;
6678 bool has_transition_ : 1;
6679 StoreFieldOrKeyedMode store_mode_ : 1;
6683 class HStoreNamedGeneric V8_FINAL : public HTemplateInstruction<3> {
6685 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreNamedGeneric, HValue*,
6686 Handle<String>, HValue*,
6688 HValue* object() { return OperandAt(0); }
6689 HValue* value() { return OperandAt(1); }
6690 HValue* context() { return OperandAt(2); }
6691 Handle<String> name() { return name_; }
6692 StrictMode strict_mode() { return strict_mode_; }
6694 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6696 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6697 return Representation::Tagged();
6700 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
6703 HStoreNamedGeneric(HValue* context,
6705 Handle<String> name,
6707 StrictMode strict_mode)
6709 strict_mode_(strict_mode) {
6710 SetOperandAt(0, object);
6711 SetOperandAt(1, value);
6712 SetOperandAt(2, context);
6713 SetAllSideEffects();
6716 Handle<String> name_;
6717 StrictMode strict_mode_;
6721 class HStoreKeyed V8_FINAL
6722 : public HTemplateInstruction<3>, public ArrayInstructionInterface {
6724 DECLARE_INSTRUCTION_FACTORY_P4(HStoreKeyed, HValue*, HValue*, HValue*,
6726 DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*,
6727 ElementsKind, StoreFieldOrKeyedMode);
6729 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6730 // kind_fast: tagged[int32] = tagged
6731 // kind_double: tagged[int32] = double
6732 // kind_smi : tagged[int32] = smi
6733 // kind_fixed_typed_array: tagged[int32] = (double | int32)
6734 // kind_external: external[int32] = (double | int32)
6736 return is_external() ? Representation::External()
6737 : Representation::Tagged();
6738 } else if (index == 1) {
6739 return ArrayInstructionInterface::KeyedAccessIndexRequirement(
6740 OperandAt(1)->representation());
6743 ASSERT_EQ(index, 2);
6745 if (IsDoubleOrFloatElementsKind(elements_kind())) {
6746 return Representation::Double();
6748 if (IsFloat32x4ElementsKind(elements_kind())) {
6749 return CPU::SupportsSIMD128InCrankshaft() ?
6750 Representation::Float32x4() : Representation::Tagged();
6752 if (IsInt32x4ElementsKind(elements_kind())) {
6753 return CPU::SupportsSIMD128InCrankshaft() ?
6754 Representation::Int32x4() : Representation::Tagged();
6756 if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
6757 return Representation::Integer32();
6759 if (IsFastSmiElementsKind(elements_kind())) {
6760 return Representation::Smi();
6763 return is_external() || is_fixed_typed_array()
6764 ? Representation::Integer32()
6765 : Representation::Tagged();
6768 bool is_external() const {
6769 return IsExternalArrayElementsKind(elements_kind());
6772 bool is_fixed_typed_array() const {
6773 return IsFixedTypedArrayElementsKind(elements_kind());
6776 bool is_typed_elements() const {
6777 return is_external() || is_fixed_typed_array();
6780 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
6781 if (index < 2) return RequiredInputRepresentation(index);
6782 if (IsUninitialized()) {
6783 return Representation::None();
6785 if (IsDoubleOrFloatElementsKind(elements_kind())) {
6786 return Representation::Double();
6788 if (IsFloat32x4ElementsKind(elements_kind())) {
6789 return CPU::SupportsSIMD128InCrankshaft() ?
6790 Representation::Float32x4() : Representation::Tagged();
6792 if (IsInt32x4ElementsKind(elements_kind())) {
6793 return CPU::SupportsSIMD128InCrankshaft() ?
6794 Representation::Int32x4() : Representation::Tagged();
6796 if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
6797 return Representation::Integer32();
6799 if (IsFastSmiElementsKind(elements_kind())) {
6800 return Representation::Smi();
6802 if (is_typed_elements()) {
6803 return Representation::Integer32();
6805 // For fast object elements kinds, don't assume anything.
6806 return Representation::None();
6809 HValue* elements() { return OperandAt(0); }
6810 HValue* key() { return OperandAt(1); }
6811 HValue* value() { return OperandAt(2); }
6812 bool value_is_smi() const {
6813 return IsFastSmiElementsKind(elements_kind_);
6815 StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
6816 ElementsKind elements_kind() const { return elements_kind_; }
6817 uint32_t index_offset() { return index_offset_; }
6818 void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
6819 virtual int MaxIndexOffsetBits() {
6820 return 31 - ElementsKindToShiftSize(elements_kind_);
6822 HValue* GetKey() { return key(); }
6823 void SetKey(HValue* key) { SetOperandAt(1, key); }
6824 bool IsDehoisted() { return is_dehoisted_; }
6825 void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
6826 bool IsUninitialized() { return is_uninitialized_; }
6827 void SetUninitialized(bool is_uninitialized) {
6828 is_uninitialized_ = is_uninitialized;
6831 bool IsConstantHoleStore() {
6832 return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
6835 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
6836 HValue* dominator) V8_OVERRIDE {
6837 ASSERT(side_effect == kNewSpacePromotion);
6838 new_space_dominator_ = dominator;
6842 HValue* new_space_dominator() const { return new_space_dominator_; }
6844 bool NeedsWriteBarrier() {
6845 if (value_is_smi()) {
6848 return StoringValueNeedsWriteBarrier(value()) &&
6849 ReceiverObjectNeedsWriteBarrier(elements(), value(),
6850 new_space_dominator());
6854 bool NeedsCanonicalization();
6856 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6858 DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
6861 HStoreKeyed(HValue* obj, HValue* key, HValue* val,
6862 ElementsKind elements_kind,
6863 StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
6864 : elements_kind_(elements_kind),
6866 is_dehoisted_(false),
6867 is_uninitialized_(false),
6868 store_mode_(store_mode),
6869 new_space_dominator_(NULL) {
6870 SetOperandAt(0, obj);
6871 SetOperandAt(1, key);
6872 SetOperandAt(2, val);
6874 ASSERT(store_mode != STORE_TO_INITIALIZED_ENTRY ||
6875 elements_kind == FAST_SMI_ELEMENTS);
6877 if (IsFastObjectElementsKind(elements_kind)) {
6878 SetFlag(kTrackSideEffectDominators);
6879 SetDependsOnFlag(kNewSpacePromotion);
6881 if (is_external()) {
6882 SetChangesFlag(kExternalMemory);
6883 SetFlag(kAllowUndefinedAsNaN);
6884 } else if (IsFastDoubleElementsKind(elements_kind)) {
6885 SetChangesFlag(kDoubleArrayElements);
6886 } else if (IsFastSmiElementsKind(elements_kind)) {
6887 SetChangesFlag(kArrayElements);
6888 } else if (is_fixed_typed_array()) {
6889 SetChangesFlag(kTypedArrayElements);
6890 SetFlag(kAllowUndefinedAsNaN);
6892 SetChangesFlag(kArrayElements);
6895 // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
6896 if ((elements_kind >= EXTERNAL_INT8_ELEMENTS &&
6897 elements_kind <= EXTERNAL_UINT32_ELEMENTS) ||
6898 (elements_kind >= UINT8_ELEMENTS &&
6899 elements_kind <= INT32_ELEMENTS)) {
6900 SetFlag(kTruncatingToInt32);
6904 ElementsKind elements_kind_;
6905 uint32_t index_offset_;
6906 bool is_dehoisted_ : 1;
6907 bool is_uninitialized_ : 1;
6908 StoreFieldOrKeyedMode store_mode_: 1;
6909 HValue* new_space_dominator_;
6913 class HStoreKeyedGeneric V8_FINAL : public HTemplateInstruction<4> {
6915 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreKeyedGeneric, HValue*,
6916 HValue*, HValue*, StrictMode);
6918 HValue* object() { return OperandAt(0); }
6919 HValue* key() { return OperandAt(1); }
6920 HValue* value() { return OperandAt(2); }
6921 HValue* context() { return OperandAt(3); }
6922 StrictMode strict_mode() { return strict_mode_; }
6924 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6925 // tagged[tagged] = tagged
6926 return Representation::Tagged();
6929 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6931 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
6934 HStoreKeyedGeneric(HValue* context,
6938 StrictMode strict_mode)
6939 : strict_mode_(strict_mode) {
6940 SetOperandAt(0, object);
6941 SetOperandAt(1, key);
6942 SetOperandAt(2, value);
6943 SetOperandAt(3, context);
6944 SetAllSideEffects();
6947 StrictMode strict_mode_;
6951 class HTransitionElementsKind V8_FINAL : public HTemplateInstruction<2> {
6953 inline static HTransitionElementsKind* New(Zone* zone,
6956 Handle<Map> original_map,
6957 Handle<Map> transitioned_map) {
6958 return new(zone) HTransitionElementsKind(context, object,
6959 original_map, transitioned_map);
6962 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6963 return Representation::Tagged();
6966 HValue* object() { return OperandAt(0); }
6967 HValue* context() { return OperandAt(1); }
6968 Unique<Map> original_map() { return original_map_; }
6969 Unique<Map> transitioned_map() { return transitioned_map_; }
6970 ElementsKind from_kind() { return from_kind_; }
6971 ElementsKind to_kind() { return to_kind_; }
6973 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6975 DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
6978 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
6979 HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
6980 return original_map_ == instr->original_map_ &&
6981 transitioned_map_ == instr->transitioned_map_;
6984 virtual int RedefinedOperandIndex() { return 0; }
6987 HTransitionElementsKind(HValue* context,
6989 Handle<Map> original_map,
6990 Handle<Map> transitioned_map)
6991 : original_map_(Unique<Map>(original_map)),
6992 transitioned_map_(Unique<Map>(transitioned_map)),
6993 from_kind_(original_map->elements_kind()),
6994 to_kind_(transitioned_map->elements_kind()) {
6995 SetOperandAt(0, object);
6996 SetOperandAt(1, context);
6998 SetChangesFlag(kElementsKind);
6999 if (!IsSimpleMapChangeTransition(from_kind_, to_kind_)) {
7000 SetChangesFlag(kElementsPointer);
7001 SetChangesFlag(kNewSpacePromotion);
7003 set_representation(Representation::Tagged());
7006 Unique<Map> original_map_;
7007 Unique<Map> transitioned_map_;
7008 ElementsKind from_kind_;
7009 ElementsKind to_kind_;
7013 class HStringAdd V8_FINAL : public HBinaryOperation {
7015 static HInstruction* New(Zone* zone,
7019 PretenureFlag pretenure_flag = NOT_TENURED,
7020 StringAddFlags flags = STRING_ADD_CHECK_BOTH,
7021 Handle<AllocationSite> allocation_site =
7022 Handle<AllocationSite>::null());
7024 StringAddFlags flags() const { return flags_; }
7025 PretenureFlag pretenure_flag() const { return pretenure_flag_; }
7027 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7028 return Representation::Tagged();
7031 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7033 DECLARE_CONCRETE_INSTRUCTION(StringAdd)
7036 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7037 return flags_ == HStringAdd::cast(other)->flags_ &&
7038 pretenure_flag_ == HStringAdd::cast(other)->pretenure_flag_;
7042 HStringAdd(HValue* context,
7045 PretenureFlag pretenure_flag,
7046 StringAddFlags flags,
7047 Handle<AllocationSite> allocation_site)
7048 : HBinaryOperation(context, left, right, HType::String()),
7049 flags_(flags), pretenure_flag_(pretenure_flag) {
7050 set_representation(Representation::Tagged());
7052 SetDependsOnFlag(kMaps);
7053 SetChangesFlag(kNewSpacePromotion);
7054 if (FLAG_trace_pretenuring) {
7055 PrintF("HStringAdd with AllocationSite %p %s\n",
7056 allocation_site.is_null()
7057 ? static_cast<void*>(NULL)
7058 : static_cast<void*>(*allocation_site),
7059 pretenure_flag == TENURED ? "tenured" : "not tenured");
7063 // No side-effects except possible allocation:
7064 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7066 const StringAddFlags flags_;
7067 const PretenureFlag pretenure_flag_;
7071 class HStringCharCodeAt V8_FINAL : public HTemplateInstruction<3> {
7073 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HStringCharCodeAt,
7077 virtual Representation RequiredInputRepresentation(int index) {
7078 // The index is supposed to be Integer32.
7080 ? Representation::Integer32()
7081 : Representation::Tagged();
7084 HValue* context() const { return OperandAt(0); }
7085 HValue* string() const { return OperandAt(1); }
7086 HValue* index() const { return OperandAt(2); }
7088 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
7091 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
7093 virtual Range* InferRange(Zone* zone) V8_OVERRIDE {
7094 return new(zone) Range(0, String::kMaxUtf16CodeUnit);
7098 HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
7099 SetOperandAt(0, context);
7100 SetOperandAt(1, string);
7101 SetOperandAt(2, index);
7102 set_representation(Representation::Integer32());
7104 SetDependsOnFlag(kMaps);
7105 SetDependsOnFlag(kStringChars);
7106 SetChangesFlag(kNewSpacePromotion);
7109 // No side effects: runtime function assumes string + number inputs.
7110 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7114 class HStringCharFromCode V8_FINAL : public HTemplateInstruction<2> {
7116 static HInstruction* New(Zone* zone,
7120 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7122 ? Representation::Tagged()
7123 : Representation::Integer32();
7126 HValue* context() const { return OperandAt(0); }
7127 HValue* value() const { return OperandAt(1); }
7129 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
7131 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
7134 HStringCharFromCode(HValue* context, HValue* char_code)
7135 : HTemplateInstruction<2>(HType::String()) {
7136 SetOperandAt(0, context);
7137 SetOperandAt(1, char_code);
7138 set_representation(Representation::Tagged());
7140 SetChangesFlag(kNewSpacePromotion);
7143 virtual bool IsDeletable() const V8_OVERRIDE {
7144 return !value()->ToNumberCanBeObserved();
7150 class HMaterializedLiteral : public HTemplateInstruction<V> {
7152 HMaterializedLiteral<V>(int index, int depth, AllocationSiteMode mode)
7153 : literal_index_(index), depth_(depth), allocation_site_mode_(mode) {
7154 this->set_representation(Representation::Tagged());
7157 HMaterializedLiteral<V>(int index, int depth)
7158 : literal_index_(index), depth_(depth),
7159 allocation_site_mode_(DONT_TRACK_ALLOCATION_SITE) {
7160 this->set_representation(Representation::Tagged());
7163 int literal_index() const { return literal_index_; }
7164 int depth() const { return depth_; }
7165 AllocationSiteMode allocation_site_mode() const {
7166 return allocation_site_mode_;
7170 virtual bool IsDeletable() const V8_FINAL V8_OVERRIDE { return true; }
7174 AllocationSiteMode allocation_site_mode_;
7178 class HRegExpLiteral V8_FINAL : public HMaterializedLiteral<1> {
7180 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HRegExpLiteral,
7186 HValue* context() { return OperandAt(0); }
7187 Handle<FixedArray> literals() { return literals_; }
7188 Handle<String> pattern() { return pattern_; }
7189 Handle<String> flags() { return flags_; }
7191 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7192 return Representation::Tagged();
7195 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
7198 HRegExpLiteral(HValue* context,
7199 Handle<FixedArray> literals,
7200 Handle<String> pattern,
7201 Handle<String> flags,
7203 : HMaterializedLiteral<1>(literal_index, 0),
7204 literals_(literals),
7207 SetOperandAt(0, context);
7208 SetAllSideEffects();
7209 set_type(HType::JSObject());
7212 Handle<FixedArray> literals_;
7213 Handle<String> pattern_;
7214 Handle<String> flags_;
7218 class HFunctionLiteral V8_FINAL : public HTemplateInstruction<1> {
7220 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HFunctionLiteral,
7221 Handle<SharedFunctionInfo>,
7223 HValue* context() { return OperandAt(0); }
7225 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7226 return Representation::Tagged();
7229 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral)
7231 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
7232 bool pretenure() const { return pretenure_; }
7233 bool has_no_literals() const { return has_no_literals_; }
7234 bool is_generator() const { return is_generator_; }
7235 StrictMode strict_mode() const { return strict_mode_; }
7238 HFunctionLiteral(HValue* context,
7239 Handle<SharedFunctionInfo> shared,
7241 : HTemplateInstruction<1>(HType::JSObject()),
7242 shared_info_(shared),
7243 pretenure_(pretenure),
7244 has_no_literals_(shared->num_literals() == 0),
7245 is_generator_(shared->is_generator()),
7246 strict_mode_(shared->strict_mode()) {
7247 SetOperandAt(0, context);
7248 set_representation(Representation::Tagged());
7249 SetChangesFlag(kNewSpacePromotion);
7252 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7254 Handle<SharedFunctionInfo> shared_info_;
7255 bool pretenure_ : 1;
7256 bool has_no_literals_ : 1;
7257 bool is_generator_ : 1;
7258 StrictMode strict_mode_;
7262 class HTypeof V8_FINAL : public HTemplateInstruction<2> {
7264 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HTypeof, HValue*);
7266 HValue* context() { return OperandAt(0); }
7267 HValue* value() { return OperandAt(1); }
7269 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7271 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7272 return Representation::Tagged();
7275 DECLARE_CONCRETE_INSTRUCTION(Typeof)
7278 explicit HTypeof(HValue* context, HValue* value) {
7279 SetOperandAt(0, context);
7280 SetOperandAt(1, value);
7281 set_representation(Representation::Tagged());
7284 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7288 class HTrapAllocationMemento V8_FINAL : public HTemplateInstruction<1> {
7290 DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
7292 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7293 return Representation::Tagged();
7296 HValue* object() { return OperandAt(0); }
7298 DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
7301 explicit HTrapAllocationMemento(HValue* obj) {
7302 SetOperandAt(0, obj);
7307 class HToFastProperties V8_FINAL : public HUnaryOperation {
7309 DECLARE_INSTRUCTION_FACTORY_P1(HToFastProperties, HValue*);
7311 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7312 return Representation::Tagged();
7315 DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
7318 explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
7319 set_representation(Representation::Tagged());
7320 SetChangesFlag(kNewSpacePromotion);
7322 // This instruction is not marked as kChangesMaps, but does
7323 // change the map of the input operand. Use it only when creating
7324 // object literals via a runtime call.
7325 ASSERT(value->IsCallRuntime());
7327 const Runtime::Function* function = HCallRuntime::cast(value)->function();
7328 ASSERT(function->function_id == Runtime::kHiddenCreateObjectLiteral);
7332 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7336 class HDateField V8_FINAL : public HUnaryOperation {
7338 DECLARE_INSTRUCTION_FACTORY_P2(HDateField, HValue*, Smi*);
7340 Smi* index() const { return index_; }
7342 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7343 return Representation::Tagged();
7346 DECLARE_CONCRETE_INSTRUCTION(DateField)
7349 HDateField(HValue* date, Smi* index)
7350 : HUnaryOperation(date), index_(index) {
7351 set_representation(Representation::Tagged());
7358 class HSeqStringGetChar V8_FINAL : public HTemplateInstruction<2> {
7360 static HInstruction* New(Zone* zone,
7362 String::Encoding encoding,
7366 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7367 return (index == 0) ? Representation::Tagged()
7368 : Representation::Integer32();
7371 String::Encoding encoding() const { return encoding_; }
7372 HValue* string() const { return OperandAt(0); }
7373 HValue* index() const { return OperandAt(1); }
7375 DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)
7378 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7379 return encoding() == HSeqStringGetChar::cast(other)->encoding();
7382 virtual Range* InferRange(Zone* zone) V8_OVERRIDE {
7383 if (encoding() == String::ONE_BYTE_ENCODING) {
7384 return new(zone) Range(0, String::kMaxOneByteCharCode);
7386 ASSERT_EQ(String::TWO_BYTE_ENCODING, encoding());
7387 return new(zone) Range(0, String::kMaxUtf16CodeUnit);
7392 HSeqStringGetChar(String::Encoding encoding,
7394 HValue* index) : encoding_(encoding) {
7395 SetOperandAt(0, string);
7396 SetOperandAt(1, index);
7397 set_representation(Representation::Integer32());
7399 SetDependsOnFlag(kStringChars);
7402 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7404 String::Encoding encoding_;
7408 class HSeqStringSetChar V8_FINAL : public HTemplateInstruction<4> {
7410 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(
7411 HSeqStringSetChar, String::Encoding,
7412 HValue*, HValue*, HValue*);
7414 String::Encoding encoding() { return encoding_; }
7415 HValue* context() { return OperandAt(0); }
7416 HValue* string() { return OperandAt(1); }
7417 HValue* index() { return OperandAt(2); }
7418 HValue* value() { return OperandAt(3); }
7420 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7421 return (index <= 1) ? Representation::Tagged()
7422 : Representation::Integer32();
7425 DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
7428 HSeqStringSetChar(HValue* context,
7429 String::Encoding encoding,
7432 HValue* value) : encoding_(encoding) {
7433 SetOperandAt(0, context);
7434 SetOperandAt(1, string);
7435 SetOperandAt(2, index);
7436 SetOperandAt(3, value);
7437 set_representation(Representation::Tagged());
7438 SetChangesFlag(kStringChars);
7441 String::Encoding encoding_;
7445 class HCheckMapValue V8_FINAL : public HTemplateInstruction<2> {
7447 DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);
7449 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7450 return Representation::Tagged();
7453 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7455 virtual HType CalculateInferredType() V8_OVERRIDE {
7456 return HType::Tagged();
7459 HValue* value() { return OperandAt(0); }
7460 HValue* map() { return OperandAt(1); }
7462 DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
7465 virtual int RedefinedOperandIndex() { return 0; }
7467 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7472 HCheckMapValue(HValue* value,
7474 SetOperandAt(0, value);
7475 SetOperandAt(1, map);
7476 set_representation(Representation::Tagged());
7478 SetDependsOnFlag(kMaps);
7479 SetDependsOnFlag(kElementsKind);
7484 class HForInPrepareMap V8_FINAL : public HTemplateInstruction<2> {
7486 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HForInPrepareMap, HValue*);
7488 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7489 return Representation::Tagged();
7492 HValue* context() { return OperandAt(0); }
7493 HValue* enumerable() { return OperandAt(1); }
7495 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7497 virtual HType CalculateInferredType() V8_OVERRIDE {
7498 return HType::Tagged();
7501 DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
7504 HForInPrepareMap(HValue* context,
7506 SetOperandAt(0, context);
7507 SetOperandAt(1, object);
7508 set_representation(Representation::Tagged());
7509 SetAllSideEffects();
7514 class HForInCacheArray V8_FINAL : public HTemplateInstruction<2> {
7516 DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
7518 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7519 return Representation::Tagged();
7522 HValue* enumerable() { return OperandAt(0); }
7523 HValue* map() { return OperandAt(1); }
7524 int idx() { return idx_; }
7526 HForInCacheArray* index_cache() {
7527 return index_cache_;
7530 void set_index_cache(HForInCacheArray* index_cache) {
7531 index_cache_ = index_cache;
7534 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7536 virtual HType CalculateInferredType() V8_OVERRIDE {
7537 return HType::Tagged();
7540 DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
7543 HForInCacheArray(HValue* enumerable,
7545 int idx) : idx_(idx) {
7546 SetOperandAt(0, enumerable);
7547 SetOperandAt(1, keys);
7548 set_representation(Representation::Tagged());
7552 HForInCacheArray* index_cache_;
7556 class HLoadFieldByIndex V8_FINAL : public HTemplateInstruction<2> {
7558 HLoadFieldByIndex(HValue* object,
7560 SetOperandAt(0, object);
7561 SetOperandAt(1, index);
7562 set_representation(Representation::Tagged());
7565 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7566 return Representation::Tagged();
7569 HValue* object() { return OperandAt(0); }
7570 HValue* index() { return OperandAt(1); }
7572 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7574 virtual HType CalculateInferredType() V8_OVERRIDE {
7575 return HType::Tagged();
7578 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
7581 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7585 class HNullarySIMDOperation V8_FINAL : public HTemplateInstruction<1> {
7587 static HInstruction* New(Zone* zone,
7589 BuiltinFunctionId op);
7591 HValue* context() { return OperandAt(0); }
7593 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7595 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7596 return Representation::Tagged();
7599 BuiltinFunctionId op() const { return op_; }
7600 const char* OpName() const;
7602 DECLARE_CONCRETE_INSTRUCTION(NullarySIMDOperation)
7605 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7606 HNullarySIMDOperation* b = HNullarySIMDOperation::cast(other);
7607 return op_ == b->op();
7611 HNullarySIMDOperation(HValue* context, BuiltinFunctionId op)
7612 : HTemplateInstruction<1>(HType::None()), op_(op) {
7613 SetOperandAt(0, context);
7615 #define SIMD_NULLARY_OPERATION_CASE_ITEM(p1, p2, name, representation) \
7617 set_representation(Representation::representation()); \
7618 set_type(HType::TypeFromRepresentation(representation_)); \
7620 SIMD_NULLARY_OPERATIONS(SIMD_NULLARY_OPERATION_CASE_ITEM)
7621 #undef SIMD_NULLARY_OPERATION_CASE_ITEM
7628 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7630 BuiltinFunctionId op_;
7634 class HUnarySIMDOperation V8_FINAL : public HTemplateInstruction<2> {
7636 static HInstruction* New(Zone* zone,
7639 BuiltinFunctionId op,
7640 Representation to = Representation::Float32x4());
7642 HValue* context() { return OperandAt(0); }
7643 HValue* value() { return OperandAt(1); }
7645 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7647 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7649 return Representation::Tagged();
7650 } else if (op_ == kSIMD128Change) {
7651 return value()->representation();
7654 #define SIMD_UNARY_OPERATION_CASE_ITEM(p1, p2, name, p4, representation) \
7656 return Representation::representation();
7657 SIMD_UNARY_OPERATIONS(SIMD_UNARY_OPERATION_CASE_ITEM)
7658 SIMD_UNARY_OPERATIONS_FOR_PROPERTY_ACCESS(SIMD_UNARY_OPERATION_CASE_ITEM)
7659 #undef SIMD_UNARY_OPERATION_CASE_ITEM
7662 return Representation::None();
7667 BuiltinFunctionId op() const { return op_; }
7668 const char* OpName() const;
7670 DECLARE_CONCRETE_INSTRUCTION(UnarySIMDOperation)
7673 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7674 HUnarySIMDOperation* b = HUnarySIMDOperation::cast(other);
7675 return op_ == b->op();
7679 HUnarySIMDOperation(HValue* context, HValue* value, BuiltinFunctionId op,
7680 Representation to = Representation::Float32x4())
7681 : HTemplateInstruction<2>(HType::None()), op_(op) {
7682 SetOperandAt(0, context);
7683 SetOperandAt(1, value);
7685 case kSIMD128Change:
7686 set_representation(to);
7687 set_type(HType::TypeFromRepresentation(to));
7689 #define SIMD_UNARY_OPERATION_CASE_ITEM(p1, p2, name, representation, p5) \
7691 set_representation(Representation::representation()); \
7692 set_type(HType::TypeFromRepresentation(representation_)); \
7694 SIMD_UNARY_OPERATIONS(SIMD_UNARY_OPERATION_CASE_ITEM)
7695 SIMD_UNARY_OPERATIONS_FOR_PROPERTY_ACCESS(SIMD_UNARY_OPERATION_CASE_ITEM)
7696 #undef SIMD_UNARY_OPERATION_CASE_ITEM
7703 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7705 BuiltinFunctionId op_;
7709 class HBinarySIMDOperation V8_FINAL : public HTemplateInstruction<3> {
7711 static HInstruction* New(Zone* zone,
7715 BuiltinFunctionId op);
7717 HValue* context() { return OperandAt(0); }
7718 HValue* left() { return OperandAt(1); }
7719 HValue* right() { return OperandAt(2); }
7721 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7723 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7725 return Representation::Tagged();
7728 #define SIMD_BINARY_OPERATION_CASE_ITEM(p1, p2, name, p4, left_representation, \
7729 right_representation) \
7731 return index == 1 ? Representation::left_representation() \
7732 : Representation::right_representation(); \
7734 SIMD_BINARY_OPERATIONS(SIMD_BINARY_OPERATION_CASE_ITEM)
7735 #undef SIMD_BINARY_OPERATION_CASE_ITEM
7738 return Representation::None();
7743 BuiltinFunctionId op() const { return op_; }
7744 const char* OpName() const;
7746 DECLARE_CONCRETE_INSTRUCTION(BinarySIMDOperation)
7749 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7750 HBinarySIMDOperation* b = HBinarySIMDOperation::cast(other);
7751 return op_ == b->op();
7755 HBinarySIMDOperation(HValue* context, HValue* left, HValue* right,
7756 BuiltinFunctionId op)
7757 : HTemplateInstruction<3>(HType::None()), op_(op) {
7758 SetOperandAt(0, context);
7759 SetOperandAt(1, left);
7760 SetOperandAt(2, right);
7762 #define SIMD_BINARY_OPERATION_CASE_ITEM(p1, p2, name, representation, p5, p6) \
7764 set_representation(Representation::representation()); \
7765 set_type(HType::TypeFromRepresentation(representation_)); \
7767 SIMD_BINARY_OPERATIONS(SIMD_BINARY_OPERATION_CASE_ITEM)
7768 #undef SIMD_BINARY_OPERATION_CASE_ITEM
7775 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7777 BuiltinFunctionId op_;
7781 class HTernarySIMDOperation V8_FINAL : public HTemplateInstruction<4> {
7783 static HInstruction* New(Zone* zone,
7788 BuiltinFunctionId op);
7790 HValue* context() { return OperandAt(0); }
7791 HValue* first() { return OperandAt(1); }
7792 HValue* second() { return OperandAt(2); }
7793 HValue* third() { return OperandAt(3); }
7795 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7797 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7799 return Representation::Tagged();
7802 #define SIMD_TERNARY_OPERATION_CASE_ITEM(p1, p2, name, p4, \
7803 first_representation, second_representation, third_representation) \
7806 case 1: return Representation::first_representation(); \
7807 case 2: return Representation::second_representation(); \
7808 case 3: return Representation::third_representation(); \
7811 return Representation::None(); \
7813 SIMD_TERNARY_OPERATIONS(SIMD_TERNARY_OPERATION_CASE_ITEM)
7814 #undef SIMD_TERNARY_OPERATION_CASE_ITEM
7817 return Representation::None();
7822 BuiltinFunctionId op() const { return op_; }
7823 const char* OpName() const;
7825 DECLARE_CONCRETE_INSTRUCTION(TernarySIMDOperation)
7828 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7829 HTernarySIMDOperation* b = HTernarySIMDOperation::cast(other);
7830 return op_ == b->op();
7834 HTernarySIMDOperation(HValue* context, HValue* first, HValue* second,
7835 HValue* third, BuiltinFunctionId op)
7836 : HTemplateInstruction<4>(HType::None()), op_(op) {
7837 SetOperandAt(0, context);
7838 SetOperandAt(1, first);
7839 SetOperandAt(2, second);
7840 SetOperandAt(3, third);
7842 #define SIMD_TERNARY_OPERATION_CASE_ITEM(p1, p2, name, representation, p5, \
7845 set_representation(Representation::representation()); \
7846 set_type(HType::TypeFromRepresentation(representation_)); \
7848 SIMD_TERNARY_OPERATIONS(SIMD_TERNARY_OPERATION_CASE_ITEM)
7849 #undef SIMD_TERNARY_OPERATION_CASE_ITEM
7856 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7858 BuiltinFunctionId op_;
7862 class HQuarternarySIMDOperation V8_FINAL : public HTemplateInstruction<5> {
7864 static HInstruction* New(Zone* zone,
7870 BuiltinFunctionId op);
7872 HValue* context() { return OperandAt(0); }
7873 HValue* x() { return OperandAt(1); }
7874 HValue* y() { return OperandAt(2); }
7875 HValue* z() { return OperandAt(3); }
7876 HValue* w() { return OperandAt(4); }
7878 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7880 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7882 return Representation::Tagged();
7885 #define SIMD_QUARTERNARY_OPERATION_CASE_ITEM(p1, p2, name, p4, \
7886 first_representation, second_representation, third_representation, \
7887 fourth_representation) \
7890 case 1: return Representation::first_representation(); \
7891 case 2: return Representation::second_representation(); \
7892 case 3: return Representation::third_representation(); \
7893 case 4: return Representation::fourth_representation(); \
7896 return Representation::None(); \
7898 SIMD_QUARTERNARY_OPERATIONS(SIMD_QUARTERNARY_OPERATION_CASE_ITEM)
7899 #undef SIMD_QUARTERNARY_OPERATION_CASE_ITEM
7902 return Representation::None();
7907 BuiltinFunctionId op() const { return op_; }
7908 const char* OpName() const;
7910 DECLARE_CONCRETE_INSTRUCTION(QuarternarySIMDOperation)
7913 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7914 HQuarternarySIMDOperation* b = HQuarternarySIMDOperation::cast(other);
7915 return op_ == b->op();
7919 HQuarternarySIMDOperation(HValue* context, HValue* x, HValue* y, HValue* z,
7920 HValue* w, BuiltinFunctionId op)
7921 : HTemplateInstruction<5>(HType::None()), op_(op) {
7922 SetOperandAt(0, context);
7928 #define SIMD_QUARTERNARY_OPERATION_CASE_ITEM(p1, p2, name, representation, p5, \
7931 set_representation(Representation::representation()); \
7932 set_type(HType::TypeFromRepresentation(representation_)); \
7934 SIMD_QUARTERNARY_OPERATIONS(SIMD_QUARTERNARY_OPERATION_CASE_ITEM)
7935 #undef SIMD_QUARTERNARY_OPERATION_CASE_ITEM
7942 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7944 BuiltinFunctionId op_;
7948 #undef DECLARE_INSTRUCTION
7949 #undef DECLARE_CONCRETE_INSTRUCTION
7951 } } // namespace v8::internal
7953 #endif // V8_HYDROGEN_INSTRUCTIONS_H_