1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef V8_HYDROGEN_INSTRUCTIONS_H_
6 #define V8_HYDROGEN_INSTRUCTIONS_H_
10 #include "src/allocation.h"
11 #include "src/code-stubs.h"
12 #include "src/conversions.h"
13 #include "src/data-flow.h"
14 #include "src/deoptimizer.h"
15 #include "src/hydrogen-types.h"
16 #include "src/small-pointer-list.h"
17 #include "src/string-stream.h"
18 #include "src/unique.h"
19 #include "src/utils.h"
25 // Forward declarations.
29 class HInferRepresentationPhase;
31 class HLoopInformation;
32 class HStoreNamedField;
37 #define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V) \
38 V(ArithmeticBinaryOperation) \
40 V(BitwiseBinaryOperation) \
41 V(ControlInstruction) \
45 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
47 V(AccessArgumentsAt) \
49 V(AllocateBlockContext) \
52 V(ArgumentsElements) \
58 V(BoundsCheckBaseIndexInformation) \
60 V(CallWithDescriptor) \
70 V(CheckInstanceType) \
76 V(ClassOfTestAndBranch) \
77 V(CompareNumericAndBranch) \
78 V(CompareHoleAndBranch) \
80 V(CompareMinusZeroAndBranch) \
81 V(CompareObjectEqAndBranch) \
94 V(EnvironmentMarker) \
95 V(ForceRepresentation) \
99 V(GetCachedArrayIndex) \
101 V(HasCachedArrayIndexAndBranch) \
102 V(HasInstanceTypeAndBranch) \
103 V(InnerAllocatedObject) \
105 V(InstanceOfKnownGlobal) \
107 V(IsConstructCallAndBranch) \
108 V(IsObjectAndBranch) \
109 V(IsStringAndBranch) \
111 V(IsUndetectableAndBranch) \
114 V(LoadFieldByIndex) \
115 V(LoadFunctionPrototype) \
117 V(LoadGlobalGeneric) \
119 V(LoadKeyedGeneric) \
121 V(LoadNamedGeneric) \
136 V(SeqStringGetChar) \
137 V(SeqStringSetChar) \
143 V(StoreContextSlot) \
144 V(StoreFrameContext) \
147 V(StoreKeyedGeneric) \
149 V(StoreNamedGeneric) \
151 V(StringCharCodeAt) \
152 V(StringCharFromCode) \
153 V(StringCompareAndBranch) \
156 V(ToFastProperties) \
157 V(TransitionElementsKind) \
158 V(TrapAllocationMemento) \
160 V(TypeofIsAndBranch) \
161 V(UnaryMathOperation) \
166 #define GVN_TRACKED_FLAG_LIST(V) \
169 #define GVN_UNTRACKED_FLAG_LIST(V) \
173 V(BackingStoreFields) \
176 V(DoubleArrayElements) \
186 V(TypedArrayElements)
189 #define DECLARE_ABSTRACT_INSTRUCTION(type) \
190 virtual bool Is##type() const V8_FINAL V8_OVERRIDE { return true; } \
191 static H##type* cast(HValue* value) { \
192 ASSERT(value->Is##type()); \
193 return reinterpret_cast<H##type*>(value); \
197 #define DECLARE_CONCRETE_INSTRUCTION(type) \
198 virtual LInstruction* CompileToLithium( \
199 LChunkBuilder* builder) V8_FINAL V8_OVERRIDE; \
200 static H##type* cast(HValue* value) { \
201 ASSERT(value->Is##type()); \
202 return reinterpret_cast<H##type*>(value); \
204 virtual Opcode opcode() const V8_FINAL V8_OVERRIDE { \
205 return HValue::k##type; \
209 enum PropertyAccessType { LOAD, STORE };
212 class Range V8_FINAL : public ZoneObject {
218 can_be_minus_zero_(false) { }
220 Range(int32_t lower, int32_t upper)
224 can_be_minus_zero_(false) { }
226 int32_t upper() const { return upper_; }
227 int32_t lower() const { return lower_; }
228 Range* next() const { return next_; }
229 Range* CopyClearLower(Zone* zone) const {
230 return new(zone) Range(kMinInt, upper_);
232 Range* CopyClearUpper(Zone* zone) const {
233 return new(zone) Range(lower_, kMaxInt);
235 Range* Copy(Zone* zone) const {
236 Range* result = new(zone) Range(lower_, upper_);
237 result->set_can_be_minus_zero(CanBeMinusZero());
240 int32_t Mask() const;
241 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
242 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
243 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
244 bool CanBeNegative() const { return lower_ < 0; }
245 bool CanBePositive() const { return upper_ > 0; }
246 bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
247 bool IsMostGeneric() const {
248 return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
250 bool IsInSmiRange() const {
251 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
254 lower_ = Max(lower_, Smi::kMinValue);
255 upper_ = Min(upper_, Smi::kMaxValue);
262 void StackUpon(Range* other) {
267 void Intersect(Range* other);
268 void Union(Range* other);
269 void CombinedMax(Range* other);
270 void CombinedMin(Range* other);
272 void AddConstant(int32_t value);
273 void Sar(int32_t value);
274 void Shl(int32_t value);
275 bool AddAndCheckOverflow(const Representation& r, Range* other);
276 bool SubAndCheckOverflow(const Representation& r, Range* other);
277 bool MulAndCheckOverflow(const Representation& r, Range* other);
283 bool can_be_minus_zero_;
287 class HUseListNode: public ZoneObject {
289 HUseListNode(HValue* value, int index, HUseListNode* tail)
290 : tail_(tail), value_(value), index_(index) {
293 HUseListNode* tail();
294 HValue* value() const { return value_; }
295 int index() const { return index_; }
297 void set_tail(HUseListNode* list) { tail_ = list; }
301 tail_ = reinterpret_cast<HUseListNode*>(1);
314 // We reuse use list nodes behind the scenes as uses are added and deleted.
315 // This class is the safe way to iterate uses while deleting them.
316 class HUseIterator V8_FINAL BASE_EMBEDDED {
318 bool Done() { return current_ == NULL; }
332 explicit HUseIterator(HUseListNode* head);
334 HUseListNode* current_;
343 // All tracked flags should appear before untracked ones.
345 // Declare global value numbering flags.
346 #define DECLARE_FLAG(Type) k##Type,
347 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
348 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
350 #define COUNT_FLAG(Type) + 1
351 kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG),
352 kNumberOfUntrackedSideEffects = 0 GVN_UNTRACKED_FLAG_LIST(COUNT_FLAG),
354 kNumberOfFlags = kNumberOfTrackedSideEffects + kNumberOfUntrackedSideEffects
358 static inline GVNFlag GVNFlagFromInt(int i) {
360 ASSERT(i < kNumberOfFlags);
361 return static_cast<GVNFlag>(i);
365 class DecompositionResult V8_FINAL BASE_EMBEDDED {
367 DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
369 HValue* base() { return base_; }
370 int offset() { return offset_; }
371 int scale() { return scale_; }
373 bool Apply(HValue* other_base, int other_offset, int other_scale = 0) {
376 offset_ = other_offset;
377 scale_ = other_scale;
382 offset_ += other_offset;
383 scale_ = other_scale;
391 void SwapValues(HValue** other_base, int* other_offset, int* other_scale) {
392 swap(&base_, other_base);
393 swap(&offset_, other_offset);
394 swap(&scale_, other_scale);
398 template <class T> void swap(T* a, T* b) {
410 typedef EnumSet<GVNFlag, int32_t> GVNFlagSet;
413 // This class encapsulates encoding and decoding of sources positions from
414 // which hydrogen values originated.
415 // When FLAG_track_hydrogen_positions is set this object encodes the
416 // identifier of the inlining and absolute offset from the start of the
418 // When the flag is not set we simply track absolute offset from the
420 class HSourcePosition {
422 HSourcePosition(const HSourcePosition& other) : value_(other.value_) { }
424 static HSourcePosition Unknown() {
425 return HSourcePosition(RelocInfo::kNoPosition);
428 bool IsUnknown() const { return value_ == RelocInfo::kNoPosition; }
430 int position() const { return PositionField::decode(value_); }
431 void set_position(int position) {
432 if (FLAG_hydrogen_track_positions) {
433 value_ = static_cast<int>(PositionField::update(value_, position));
439 int inlining_id() const { return InliningIdField::decode(value_); }
440 void set_inlining_id(int inlining_id) {
441 if (FLAG_hydrogen_track_positions) {
442 value_ = static_cast<int>(InliningIdField::update(value_, inlining_id));
446 int raw() const { return value_; }
448 void PrintTo(FILE* f);
451 typedef BitField<int, 0, 9> InliningIdField;
453 // Offset from the start of the inlined function.
454 typedef BitField<int, 9, 22> PositionField;
456 // On HPositionInfo can use this constructor.
457 explicit HSourcePosition(int value) : value_(value) { }
459 friend class HPositionInfo;
461 // If FLAG_hydrogen_track_positions is set contains bitfields InliningIdField
462 // and PositionField.
463 // Otherwise contains absolute offset from the script start.
468 class HValue : public ZoneObject {
470 static const int kNoNumber = -1;
473 kFlexibleRepresentation,
475 // Participate in Global Value Numbering, i.e. elimination of
476 // unnecessary recomputations. If an instruction sets this flag, it must
477 // implement DataEquals(), which will be used to determine if other
478 // occurrences of the instruction are indeed the same.
480 // Track instructions that are dominating side effects. If an instruction
481 // sets this flag, it must implement HandleSideEffectDominator() and should
482 // indicate which side effects to track by setting GVN flags.
483 kTrackSideEffectDominators,
490 kAllowUndefinedAsNaN,
493 kAllUsesTruncatingToInt32,
495 kAllUsesTruncatingToSmi,
496 // Set after an instruction is killed.
498 // Instructions that are allowed to produce full range unsigned integer
499 // values are marked with kUint32 flag. If arithmetic shift or a load from
500 // EXTERNAL_UINT32_ELEMENTS array is not marked with this flag
501 // it will deoptimize if result does not fit into signed integer range.
502 // HGraph::ComputeSafeUint32Operations is responsible for setting this
505 kHasNoObservableSideEffects,
506 // Indicates an instruction shouldn't be replaced by optimization, this flag
507 // is useful to set in cases where recomputing a value is cheaper than
508 // extending the value's live range and spilling it.
510 // Indicates the instruction is live during dead code elimination.
513 // HEnvironmentMarkers are deleted before dead code
514 // elimination takes place, so they can repurpose the kIsLive flag:
515 kEndsLiveRange = kIsLive,
517 // TODO(everyone): Don't forget to update this!
521 STATIC_ASSERT(kLastFlag < kBitsPerInt);
523 static HValue* cast(HValue* value) { return value; }
526 // Declare a unique enum value for each hydrogen instruction.
527 #define DECLARE_OPCODE(type) k##type,
528 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
530 #undef DECLARE_OPCODE
532 virtual Opcode opcode() const = 0;
534 // Declare a non-virtual predicates for each concrete HInstruction or HValue.
535 #define DECLARE_PREDICATE(type) \
536 bool Is##type() const { return opcode() == k##type; }
537 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
538 #undef DECLARE_PREDICATE
539 bool IsPhi() const { return opcode() == kPhi; }
541 // Declare virtual predicates for abstract HInstruction or HValue
542 #define DECLARE_PREDICATE(type) \
543 virtual bool Is##type() const { return false; }
544 HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
545 #undef DECLARE_PREDICATE
547 bool IsBitwiseBinaryShift() {
548 return IsShl() || IsShr() || IsSar();
551 HValue(HType type = HType::Tagged())
558 range_poisoned_(false),
563 virtual HSourcePosition position() const {
564 return HSourcePosition::Unknown();
566 virtual HSourcePosition operand_position(int index) const {
570 HBasicBlock* block() const { return block_; }
571 void SetBlock(HBasicBlock* block);
573 // Note: Never call this method for an unlinked value.
574 Isolate* isolate() const;
576 int id() const { return id_; }
577 void set_id(int id) { id_ = id; }
579 HUseIterator uses() const { return HUseIterator(use_list_); }
581 virtual bool EmitAtUses() { return false; }
583 Representation representation() const { return representation_; }
584 void ChangeRepresentation(Representation r) {
585 ASSERT(CheckFlag(kFlexibleRepresentation));
586 ASSERT(!CheckFlag(kCannotBeTagged) || !r.IsTagged());
587 RepresentationChanged(r);
590 // Tagged is the bottom of the lattice, don't go any further.
591 ClearFlag(kFlexibleRepresentation);
594 virtual void AssumeRepresentation(Representation r);
596 virtual Representation KnownOptimalRepresentation() {
597 Representation r = representation();
600 if (t.IsSmi()) return Representation::Smi();
601 if (t.IsHeapNumber()) return Representation::Double();
602 if (t.IsHeapObject()) return r;
603 return Representation::None();
608 HType type() const { return type_; }
609 void set_type(HType new_type) {
610 ASSERT(new_type.IsSubtypeOf(type_));
614 // There are HInstructions that do not really change a value, they
615 // only add pieces of information to it (like bounds checks, map checks,
617 // We call these instructions "informative definitions", or "iDef".
618 // One of the iDef operands is special because it is the value that is
619 // "transferred" to the output, we call it the "redefined operand".
620 // If an HValue is an iDef it must override RedefinedOperandIndex() so that
621 // it does not return kNoRedefinedOperand;
622 static const int kNoRedefinedOperand = -1;
623 virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
624 bool IsInformativeDefinition() {
625 return RedefinedOperandIndex() != kNoRedefinedOperand;
627 HValue* RedefinedOperand() {
628 int index = RedefinedOperandIndex();
629 return index == kNoRedefinedOperand ? NULL : OperandAt(index);
632 bool CanReplaceWithDummyUses();
634 virtual int argument_delta() const { return 0; }
636 // A purely informative definition is an idef that will not emit code and
637 // should therefore be removed from the graph in the RestoreActualValues
638 // phase (so that live ranges will be shorter).
639 virtual bool IsPurelyInformativeDefinition() { return false; }
641 // This method must always return the original HValue SSA definition,
642 // regardless of any chain of iDefs of this value.
643 HValue* ActualValue() {
644 HValue* value = this;
646 while ((index = value->RedefinedOperandIndex()) != kNoRedefinedOperand) {
647 value = value->OperandAt(index);
652 bool IsInteger32Constant();
653 int32_t GetInteger32Constant();
654 bool EqualsInteger32Constant(int32_t value);
656 bool IsDefinedAfter(HBasicBlock* other) const;
659 virtual int OperandCount() = 0;
660 virtual HValue* OperandAt(int index) const = 0;
661 void SetOperandAt(int index, HValue* value);
663 void DeleteAndReplaceWith(HValue* other);
664 void ReplaceAllUsesWith(HValue* other);
665 bool HasNoUses() const { return use_list_ == NULL; }
666 bool HasMultipleUses() const {
667 return use_list_ != NULL && use_list_->tail() != NULL;
669 int UseCount() const;
671 // Mark this HValue as dead and to be removed from other HValues' use lists.
674 int flags() const { return flags_; }
675 void SetFlag(Flag f) { flags_ |= (1 << f); }
676 void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
677 bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
678 void CopyFlag(Flag f, HValue* other) {
679 if (other->CheckFlag(f)) SetFlag(f);
682 // Returns true if the flag specified is set for all uses, false otherwise.
683 bool CheckUsesForFlag(Flag f) const;
684 // Same as before and the first one without the flag is returned in value.
685 bool CheckUsesForFlag(Flag f, HValue** value) const;
686 // Returns true if the flag specified is set for all uses, and this set
687 // of uses is non-empty.
688 bool HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const;
690 GVNFlagSet ChangesFlags() const { return changes_flags_; }
691 GVNFlagSet DependsOnFlags() const { return depends_on_flags_; }
692 void SetChangesFlag(GVNFlag f) { changes_flags_.Add(f); }
693 void SetDependsOnFlag(GVNFlag f) { depends_on_flags_.Add(f); }
694 void ClearChangesFlag(GVNFlag f) { changes_flags_.Remove(f); }
695 void ClearDependsOnFlag(GVNFlag f) { depends_on_flags_.Remove(f); }
696 bool CheckChangesFlag(GVNFlag f) const {
697 return changes_flags_.Contains(f);
699 bool CheckDependsOnFlag(GVNFlag f) const {
700 return depends_on_flags_.Contains(f);
702 void SetAllSideEffects() { changes_flags_.Add(AllSideEffectsFlagSet()); }
703 void ClearAllSideEffects() {
704 changes_flags_.Remove(AllSideEffectsFlagSet());
706 bool HasSideEffects() const {
707 return changes_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
709 bool HasObservableSideEffects() const {
710 return !CheckFlag(kHasNoObservableSideEffects) &&
711 changes_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
714 GVNFlagSet SideEffectFlags() const {
715 GVNFlagSet result = ChangesFlags();
716 result.Intersect(AllSideEffectsFlagSet());
720 GVNFlagSet ObservableChangesFlags() const {
721 GVNFlagSet result = ChangesFlags();
722 result.Intersect(AllObservableSideEffectsFlagSet());
726 Range* range() const {
727 ASSERT(!range_poisoned_);
730 bool HasRange() const {
731 ASSERT(!range_poisoned_);
732 return range_ != NULL;
735 void PoisonRange() { range_poisoned_ = true; }
737 void AddNewRange(Range* r, Zone* zone);
738 void RemoveLastAddedRange();
739 void ComputeInitialRange(Zone* zone);
741 // Escape analysis helpers.
742 virtual bool HasEscapingOperandAt(int index) { return true; }
743 virtual bool HasOutOfBoundsAccess(int size) { return false; }
745 // Representation helpers.
746 virtual Representation observed_input_representation(int index) {
747 return Representation::None();
749 virtual Representation RequiredInputRepresentation(int index) = 0;
750 virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
752 // This gives the instruction an opportunity to replace itself with an
753 // instruction that does the same in some better way. To replace an
754 // instruction with a new one, first add the new instruction to the graph,
755 // then return it. Return NULL to have the instruction deleted.
756 virtual HValue* Canonicalize() { return this; }
758 bool Equals(HValue* other);
759 virtual intptr_t Hashcode();
761 // Compute unique ids upfront that is safe wrt GC and concurrent compilation.
762 virtual void FinalizeUniqueness() { }
765 virtual void PrintTo(StringStream* stream) = 0;
766 void PrintNameTo(StringStream* stream);
767 void PrintTypeTo(StringStream* stream);
768 void PrintChangesTo(StringStream* stream);
770 const char* Mnemonic() const;
772 // Type information helpers.
773 bool HasMonomorphicJSObjectType();
775 // TODO(mstarzinger): For now instructions can override this function to
776 // specify statically known types, once HType can convey more information
777 // it should be based on the HType.
778 virtual Handle<Map> GetMonomorphicJSObjectMap() { return Handle<Map>(); }
780 // Updated the inferred type of this instruction and returns true if
782 bool UpdateInferredType();
784 virtual HType CalculateInferredType();
786 // This function must be overridden for instructions which have the
787 // kTrackSideEffectDominators flag set, to track instructions that are
788 // dominating side effects.
789 // It returns true if it removed an instruction which had side effects.
790 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
796 // Check if this instruction has some reason that prevents elimination.
797 bool CannotBeEliminated() const {
798 return HasObservableSideEffects() || !IsDeletable();
802 virtual void Verify() = 0;
805 virtual bool TryDecompose(DecompositionResult* decomposition) {
806 if (RedefinedOperand() != NULL) {
807 return RedefinedOperand()->TryDecompose(decomposition);
813 // Returns true conservatively if the program might be able to observe a
814 // ToString() operation on this value.
815 bool ToStringCanBeObserved() const {
816 return ToStringOrToNumberCanBeObserved();
819 // Returns true conservatively if the program might be able to observe a
820 // ToNumber() operation on this value.
821 bool ToNumberCanBeObserved() const {
822 return ToStringOrToNumberCanBeObserved();
825 MinusZeroMode GetMinusZeroMode() {
826 return CheckFlag(kBailoutOnMinusZero)
827 ? FAIL_ON_MINUS_ZERO : TREAT_MINUS_ZERO_AS_ZERO;
831 // This function must be overridden for instructions with flag kUseGVN, to
832 // compare the non-Operand parts of the instruction.
833 virtual bool DataEquals(HValue* other) {
838 bool ToStringOrToNumberCanBeObserved() const {
839 if (type().IsTaggedPrimitive()) return false;
840 if (type().IsJSObject()) return true;
841 return !representation().IsSmiOrInteger32() && !representation().IsDouble();
844 virtual Representation RepresentationFromInputs() {
845 return representation();
847 virtual Representation RepresentationFromUses();
848 Representation RepresentationFromUseRequirements();
850 virtual void UpdateRepresentation(Representation new_rep,
851 HInferRepresentationPhase* h_infer,
853 void AddDependantsToWorklist(HInferRepresentationPhase* h_infer);
855 virtual void RepresentationChanged(Representation to) { }
857 virtual Range* InferRange(Zone* zone);
858 virtual void DeleteFromGraph() = 0;
859 virtual void InternalSetOperandAt(int index, HValue* value) = 0;
861 ASSERT(block_ != NULL);
865 void set_representation(Representation r) {
866 ASSERT(representation_.IsNone() && !r.IsNone());
870 static GVNFlagSet AllFlagSet() {
872 #define ADD_FLAG(Type) result.Add(k##Type);
873 GVN_TRACKED_FLAG_LIST(ADD_FLAG)
874 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
879 // A flag mask to mark an instruction as having arbitrary side effects.
880 static GVNFlagSet AllSideEffectsFlagSet() {
881 GVNFlagSet result = AllFlagSet();
882 result.Remove(kOsrEntries);
886 // A flag mask of all side effects that can make observable changes in
887 // an executing program (i.e. are not safe to repeat, move or remove);
888 static GVNFlagSet AllObservableSideEffectsFlagSet() {
889 GVNFlagSet result = AllFlagSet();
890 result.Remove(kNewSpacePromotion);
891 result.Remove(kElementsKind);
892 result.Remove(kElementsPointer);
893 result.Remove(kMaps);
897 // Remove the matching use from the use list if present. Returns the
898 // removed list node or NULL.
899 HUseListNode* RemoveUse(HValue* value, int index);
901 void RegisterUse(int index, HValue* new_value);
905 // The id of this instruction in the hydrogen graph, assigned when first
906 // added to the graph. Reflects creation order.
909 Representation representation_;
911 HUseListNode* use_list_;
914 bool range_poisoned_;
917 GVNFlagSet changes_flags_;
918 GVNFlagSet depends_on_flags_;
921 virtual bool IsDeletable() const { return false; }
923 DISALLOW_COPY_AND_ASSIGN(HValue);
927 #define DECLARE_INSTRUCTION_FACTORY_P0(I) \
928 static I* New(Zone* zone, HValue* context) { \
929 return new(zone) I(); \
932 #define DECLARE_INSTRUCTION_FACTORY_P1(I, P1) \
933 static I* New(Zone* zone, HValue* context, P1 p1) { \
934 return new(zone) I(p1); \
937 #define DECLARE_INSTRUCTION_FACTORY_P2(I, P1, P2) \
938 static I* New(Zone* zone, HValue* context, P1 p1, P2 p2) { \
939 return new(zone) I(p1, p2); \
942 #define DECLARE_INSTRUCTION_FACTORY_P3(I, P1, P2, P3) \
943 static I* New(Zone* zone, HValue* context, P1 p1, P2 p2, P3 p3) { \
944 return new(zone) I(p1, p2, p3); \
947 #define DECLARE_INSTRUCTION_FACTORY_P4(I, P1, P2, P3, P4) \
948 static I* New(Zone* zone, \
954 return new(zone) I(p1, p2, p3, p4); \
957 #define DECLARE_INSTRUCTION_FACTORY_P5(I, P1, P2, P3, P4, P5) \
958 static I* New(Zone* zone, \
965 return new(zone) I(p1, p2, p3, p4, p5); \
968 #define DECLARE_INSTRUCTION_FACTORY_P6(I, P1, P2, P3, P4, P5, P6) \
969 static I* New(Zone* zone, \
977 return new(zone) I(p1, p2, p3, p4, p5, p6); \
980 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(I) \
981 static I* New(Zone* zone, HValue* context) { \
982 return new(zone) I(context); \
985 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(I, P1) \
986 static I* New(Zone* zone, HValue* context, P1 p1) { \
987 return new(zone) I(context, p1); \
990 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(I, P1, P2) \
991 static I* New(Zone* zone, HValue* context, P1 p1, P2 p2) { \
992 return new(zone) I(context, p1, p2); \
995 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(I, P1, P2, P3) \
996 static I* New(Zone* zone, HValue* context, P1 p1, P2 p2, P3 p3) { \
997 return new(zone) I(context, p1, p2, p3); \
1000 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(I, P1, P2, P3, P4) \
1001 static I* New(Zone* zone, \
1007 return new(zone) I(context, p1, p2, p3, p4); \
1010 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(I, P1, P2, P3, P4, P5) \
1011 static I* New(Zone* zone, \
1018 return new(zone) I(context, p1, p2, p3, p4, p5); \
1022 // A helper class to represent per-operand position information attached to
1023 // the HInstruction in the compact form. Uses tagging to distinguish between
1024 // case when only instruction's position is available and case when operands'
1025 // positions are also available.
1026 // In the first case it contains intruction's position as a tagged value.
1027 // In the second case it points to an array which contains instruction's
1028 // position and operands' positions.
1029 class HPositionInfo {
1031 explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { }
1033 HSourcePosition position() const {
1034 if (has_operand_positions()) {
1035 return operand_positions()[kInstructionPosIndex];
1037 return HSourcePosition(static_cast<int>(UntagPosition(data_)));
1040 void set_position(HSourcePosition pos) {
1041 if (has_operand_positions()) {
1042 operand_positions()[kInstructionPosIndex] = pos;
1044 data_ = TagPosition(pos.raw());
1048 void ensure_storage_for_operand_positions(Zone* zone, int operand_count) {
1049 if (has_operand_positions()) {
1053 const int length = kFirstOperandPosIndex + operand_count;
1054 HSourcePosition* positions =
1055 zone->NewArray<HSourcePosition>(length);
1056 for (int i = 0; i < length; i++) {
1057 positions[i] = HSourcePosition::Unknown();
1060 const HSourcePosition pos = position();
1061 data_ = reinterpret_cast<intptr_t>(positions);
1064 ASSERT(has_operand_positions());
1067 HSourcePosition operand_position(int idx) const {
1068 if (!has_operand_positions()) {
1071 return *operand_position_slot(idx);
1074 void set_operand_position(int idx, HSourcePosition pos) {
1075 *operand_position_slot(idx) = pos;
1079 static const intptr_t kInstructionPosIndex = 0;
1080 static const intptr_t kFirstOperandPosIndex = 1;
1082 HSourcePosition* operand_position_slot(int idx) const {
1083 ASSERT(has_operand_positions());
1084 return &(operand_positions()[kFirstOperandPosIndex + idx]);
1087 bool has_operand_positions() const {
1088 return !IsTaggedPosition(data_);
1091 HSourcePosition* operand_positions() const {
1092 ASSERT(has_operand_positions());
1093 return reinterpret_cast<HSourcePosition*>(data_);
1096 static const intptr_t kPositionTag = 1;
1097 static const intptr_t kPositionShift = 1;
1098 static bool IsTaggedPosition(intptr_t val) {
1099 return (val & kPositionTag) != 0;
1101 static intptr_t UntagPosition(intptr_t val) {
1102 ASSERT(IsTaggedPosition(val));
1103 return val >> kPositionShift;
1105 static intptr_t TagPosition(intptr_t val) {
1106 const intptr_t result = (val << kPositionShift) | kPositionTag;
1107 ASSERT(UntagPosition(result) == val);
1115 class HInstruction : public HValue {
1117 HInstruction* next() const { return next_; }
1118 HInstruction* previous() const { return previous_; }
1120 virtual void PrintTo(StringStream* stream) V8_OVERRIDE;
1121 virtual void PrintDataTo(StringStream* stream);
1123 bool IsLinked() const { return block() != NULL; }
1126 void InsertBefore(HInstruction* next);
1128 template<class T> T* Prepend(T* instr) {
1129 instr->InsertBefore(this);
1133 void InsertAfter(HInstruction* previous);
1135 template<class T> T* Append(T* instr) {
1136 instr->InsertAfter(this);
1140 // The position is a write-once variable.
1141 virtual HSourcePosition position() const V8_OVERRIDE {
1142 return HSourcePosition(position_.position());
1144 bool has_position() const {
1145 return !position().IsUnknown();
1147 void set_position(HSourcePosition position) {
1148 ASSERT(!has_position());
1149 ASSERT(!position.IsUnknown());
1150 position_.set_position(position);
1153 virtual HSourcePosition operand_position(int index) const V8_OVERRIDE {
1154 const HSourcePosition pos = position_.operand_position(index);
1155 return pos.IsUnknown() ? position() : pos;
1157 void set_operand_position(Zone* zone, int index, HSourcePosition pos) {
1158 ASSERT(0 <= index && index < OperandCount());
1159 position_.ensure_storage_for_operand_positions(zone, OperandCount());
1160 position_.set_operand_position(index, pos);
1163 bool Dominates(HInstruction* other);
1164 bool CanTruncateToSmi() const { return CheckFlag(kTruncatingToSmi); }
1165 bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
1167 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
1170 virtual void Verify() V8_OVERRIDE;
1173 bool CanDeoptimize();
1175 virtual bool HasStackCheck() { return false; }
1177 DECLARE_ABSTRACT_INSTRUCTION(Instruction)
1180 HInstruction(HType type = HType::Tagged())
1184 position_(RelocInfo::kNoPosition) {
1185 SetDependsOnFlag(kOsrEntries);
1188 virtual void DeleteFromGraph() V8_OVERRIDE { Unlink(); }
1191 void InitializeAsFirst(HBasicBlock* block) {
1192 ASSERT(!IsLinked());
1196 void PrintMnemonicTo(StringStream* stream);
1198 HInstruction* next_;
1199 HInstruction* previous_;
1200 HPositionInfo position_;
1202 friend class HBasicBlock;
1207 class HTemplateInstruction : public HInstruction {
1209 virtual int OperandCount() V8_FINAL V8_OVERRIDE { return V; }
1210 virtual HValue* OperandAt(int i) const V8_FINAL V8_OVERRIDE {
1215 HTemplateInstruction(HType type = HType::Tagged()) : HInstruction(type) {}
1217 virtual void InternalSetOperandAt(int i, HValue* value) V8_FINAL V8_OVERRIDE {
1222 EmbeddedContainer<HValue*, V> inputs_;
1226 class HControlInstruction : public HInstruction {
1228 virtual HBasicBlock* SuccessorAt(int i) = 0;
1229 virtual int SuccessorCount() = 0;
1230 virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
1232 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1234 virtual bool KnownSuccessorBlock(HBasicBlock** block) {
1239 HBasicBlock* FirstSuccessor() {
1240 return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
1242 HBasicBlock* SecondSuccessor() {
1243 return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
1247 HBasicBlock* swap = SuccessorAt(0);
1248 SetSuccessorAt(0, SuccessorAt(1));
1249 SetSuccessorAt(1, swap);
1252 DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
1256 class HSuccessorIterator V8_FINAL BASE_EMBEDDED {
1258 explicit HSuccessorIterator(HControlInstruction* instr)
1259 : instr_(instr), current_(0) { }
1261 bool Done() { return current_ >= instr_->SuccessorCount(); }
1262 HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
1263 void Advance() { current_++; }
1266 HControlInstruction* instr_;
1271 template<int S, int V>
1272 class HTemplateControlInstruction : public HControlInstruction {
1274 int SuccessorCount() V8_OVERRIDE { return S; }
1275 HBasicBlock* SuccessorAt(int i) V8_OVERRIDE { return successors_[i]; }
1276 void SetSuccessorAt(int i, HBasicBlock* block) V8_OVERRIDE {
1277 successors_[i] = block;
1280 int OperandCount() V8_OVERRIDE { return V; }
1281 HValue* OperandAt(int i) const V8_OVERRIDE { return inputs_[i]; }
1285 void InternalSetOperandAt(int i, HValue* value) V8_OVERRIDE {
1290 EmbeddedContainer<HBasicBlock*, S> successors_;
1291 EmbeddedContainer<HValue*, V> inputs_;
1295 class HBlockEntry V8_FINAL : public HTemplateInstruction<0> {
1297 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1298 return Representation::None();
1301 DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
1305 class HDummyUse V8_FINAL : public HTemplateInstruction<1> {
1307 explicit HDummyUse(HValue* value)
1308 : HTemplateInstruction<1>(HType::Smi()) {
1309 SetOperandAt(0, value);
1310 // Pretend to be a Smi so that the HChange instructions inserted
1311 // before any use generate as little code as possible.
1312 set_representation(Representation::Tagged());
1315 HValue* value() { return OperandAt(0); }
1317 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
1318 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1319 return Representation::None();
1322 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1324 DECLARE_CONCRETE_INSTRUCTION(DummyUse);
1328 // Inserts an int3/stop break instruction for debugging purposes.
1329 class HDebugBreak V8_FINAL : public HTemplateInstruction<0> {
1331 DECLARE_INSTRUCTION_FACTORY_P0(HDebugBreak);
1333 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1334 return Representation::None();
1337 DECLARE_CONCRETE_INSTRUCTION(DebugBreak)
1341 class HGoto V8_FINAL : public HTemplateControlInstruction<1, 0> {
1343 explicit HGoto(HBasicBlock* target) {
1344 SetSuccessorAt(0, target);
1347 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE {
1348 *block = FirstSuccessor();
1352 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1353 return Representation::None();
1356 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1358 DECLARE_CONCRETE_INSTRUCTION(Goto)
1362 class HDeoptimize V8_FINAL : public HTemplateControlInstruction<1, 0> {
1364 static HDeoptimize* New(Zone* zone,
1367 Deoptimizer::BailoutType type,
1368 HBasicBlock* unreachable_continuation) {
1369 return new(zone) HDeoptimize(reason, type, unreachable_continuation);
1372 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE {
1377 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1378 return Representation::None();
1381 const char* reason() const { return reason_; }
1382 Deoptimizer::BailoutType type() { return type_; }
1384 DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
1387 explicit HDeoptimize(const char* reason,
1388 Deoptimizer::BailoutType type,
1389 HBasicBlock* unreachable_continuation)
1390 : reason_(reason), type_(type) {
1391 SetSuccessorAt(0, unreachable_continuation);
1394 const char* reason_;
1395 Deoptimizer::BailoutType type_;
1399 class HUnaryControlInstruction : public HTemplateControlInstruction<2, 1> {
1401 HUnaryControlInstruction(HValue* value,
1402 HBasicBlock* true_target,
1403 HBasicBlock* false_target) {
1404 SetOperandAt(0, value);
1405 SetSuccessorAt(0, true_target);
1406 SetSuccessorAt(1, false_target);
1409 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1411 HValue* value() { return OperandAt(0); }
1415 class HBranch V8_FINAL : public HUnaryControlInstruction {
1417 DECLARE_INSTRUCTION_FACTORY_P1(HBranch, HValue*);
1418 DECLARE_INSTRUCTION_FACTORY_P2(HBranch, HValue*,
1419 ToBooleanStub::Types);
1420 DECLARE_INSTRUCTION_FACTORY_P4(HBranch, HValue*,
1421 ToBooleanStub::Types,
1422 HBasicBlock*, HBasicBlock*);
1424 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1425 return Representation::None();
1427 virtual Representation observed_input_representation(int index) V8_OVERRIDE;
1429 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
1431 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1433 ToBooleanStub::Types expected_input_types() const {
1434 return expected_input_types_;
1437 DECLARE_CONCRETE_INSTRUCTION(Branch)
1440 HBranch(HValue* value,
1441 ToBooleanStub::Types expected_input_types = ToBooleanStub::Types(),
1442 HBasicBlock* true_target = NULL,
1443 HBasicBlock* false_target = NULL)
1444 : HUnaryControlInstruction(value, true_target, false_target),
1445 expected_input_types_(expected_input_types) {
1446 SetFlag(kAllowUndefinedAsNaN);
1449 ToBooleanStub::Types expected_input_types_;
1453 class HCompareMap V8_FINAL : public HUnaryControlInstruction {
1455 DECLARE_INSTRUCTION_FACTORY_P2(HCompareMap, HValue*, Handle<Map>);
1456 DECLARE_INSTRUCTION_FACTORY_P4(HCompareMap, HValue*, Handle<Map>,
1457 HBasicBlock*, HBasicBlock*);
1459 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE {
1460 if (known_successor_index() != kNoKnownSuccessorIndex) {
1461 *block = SuccessorAt(known_successor_index());
1468 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1470 static const int kNoKnownSuccessorIndex = -1;
1471 int known_successor_index() const { return known_successor_index_; }
1472 void set_known_successor_index(int known_successor_index) {
1473 known_successor_index_ = known_successor_index;
1476 Unique<Map> map() const { return map_; }
1477 bool map_is_stable() const { return map_is_stable_; }
1479 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1480 return Representation::Tagged();
1483 DECLARE_CONCRETE_INSTRUCTION(CompareMap)
1486 virtual int RedefinedOperandIndex() { return 0; }
1489 HCompareMap(HValue* value,
1491 HBasicBlock* true_target = NULL,
1492 HBasicBlock* false_target = NULL)
1493 : HUnaryControlInstruction(value, true_target, false_target),
1494 known_successor_index_(kNoKnownSuccessorIndex),
1495 map_is_stable_(map->is_stable()),
1496 map_(Unique<Map>::CreateImmovable(map)) {
1497 set_representation(Representation::Tagged());
1500 int known_successor_index_ : 31;
1501 bool map_is_stable_ : 1;
1506 class HContext V8_FINAL : public HTemplateInstruction<0> {
1508 static HContext* New(Zone* zone) {
1509 return new(zone) HContext();
1512 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1513 return Representation::None();
1516 DECLARE_CONCRETE_INSTRUCTION(Context)
1519 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1523 set_representation(Representation::Tagged());
1527 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1531 class HReturn V8_FINAL : public HTemplateControlInstruction<0, 3> {
1533 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HReturn, HValue*, HValue*);
1534 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HReturn, HValue*);
1536 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1537 // TODO(titzer): require an Int32 input for faster returns.
1538 if (index == 2) return Representation::Smi();
1539 return Representation::Tagged();
1542 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1544 HValue* value() { return OperandAt(0); }
1545 HValue* context() { return OperandAt(1); }
1546 HValue* parameter_count() { return OperandAt(2); }
1548 DECLARE_CONCRETE_INSTRUCTION(Return)
1551 HReturn(HValue* context, HValue* value, HValue* parameter_count = 0) {
1552 SetOperandAt(0, value);
1553 SetOperandAt(1, context);
1554 SetOperandAt(2, parameter_count);
1559 class HAbnormalExit V8_FINAL : public HTemplateControlInstruction<0, 0> {
1561 DECLARE_INSTRUCTION_FACTORY_P0(HAbnormalExit);
1563 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1564 return Representation::None();
1567 DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
1573 class HUnaryOperation : public HTemplateInstruction<1> {
1575 HUnaryOperation(HValue* value, HType type = HType::Tagged())
1576 : HTemplateInstruction<1>(type) {
1577 SetOperandAt(0, value);
1580 static HUnaryOperation* cast(HValue* value) {
1581 return reinterpret_cast<HUnaryOperation*>(value);
1584 HValue* value() const { return OperandAt(0); }
1585 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1589 class HUseConst V8_FINAL : public HUnaryOperation {
1591 DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue*);
1593 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1594 return Representation::None();
1597 DECLARE_CONCRETE_INSTRUCTION(UseConst)
1600 explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
1604 class HForceRepresentation V8_FINAL : public HTemplateInstruction<1> {
1606 static HInstruction* New(Zone* zone, HValue* context, HValue* value,
1607 Representation required_representation);
1609 HValue* value() { return OperandAt(0); }
1611 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1612 return representation(); // Same as the output representation.
1615 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1617 DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
1620 HForceRepresentation(HValue* value, Representation required_representation) {
1621 SetOperandAt(0, value);
1622 set_representation(required_representation);
1627 class HChange V8_FINAL : public HUnaryOperation {
1629 HChange(HValue* value,
1631 bool is_truncating_to_smi,
1632 bool is_truncating_to_int32)
1633 : HUnaryOperation(value) {
1634 ASSERT(!value->representation().IsNone());
1635 ASSERT(!to.IsNone());
1636 ASSERT(!value->representation().Equals(to));
1637 set_representation(to);
1639 SetFlag(kCanOverflow);
1640 if (is_truncating_to_smi && to.IsSmi()) {
1641 SetFlag(kTruncatingToSmi);
1642 SetFlag(kTruncatingToInt32);
1644 if (is_truncating_to_int32) SetFlag(kTruncatingToInt32);
1645 if (value->representation().IsSmi() || value->type().IsSmi()) {
1646 set_type(HType::Smi());
1648 set_type(HType::TaggedNumber());
1649 if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
1653 bool can_convert_undefined_to_nan() {
1654 return CheckUsesForFlag(kAllowUndefinedAsNaN);
1657 virtual HType CalculateInferredType() V8_OVERRIDE;
1658 virtual HValue* Canonicalize() V8_OVERRIDE;
1660 Representation from() const { return value()->representation(); }
1661 Representation to() const { return representation(); }
1662 bool deoptimize_on_minus_zero() const {
1663 return CheckFlag(kBailoutOnMinusZero);
1665 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1669 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
1671 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1673 DECLARE_CONCRETE_INSTRUCTION(Change)
1676 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1679 virtual bool IsDeletable() const V8_OVERRIDE {
1680 return !from().IsTagged() || value()->type().IsSmi();
1685 class HClampToUint8 V8_FINAL : public HUnaryOperation {
1687 DECLARE_INSTRUCTION_FACTORY_P1(HClampToUint8, HValue*);
1689 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1690 return Representation::None();
1693 DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
1696 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1699 explicit HClampToUint8(HValue* value)
1700 : HUnaryOperation(value) {
1701 set_representation(Representation::Integer32());
1702 SetFlag(kAllowUndefinedAsNaN);
1706 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1710 class HDoubleBits V8_FINAL : public HUnaryOperation {
1712 enum Bits { HIGH, LOW };
1713 DECLARE_INSTRUCTION_FACTORY_P2(HDoubleBits, HValue*, Bits);
1715 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1716 return Representation::Double();
1719 DECLARE_CONCRETE_INSTRUCTION(DoubleBits)
1721 Bits bits() { return bits_; }
1724 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
1725 return other->IsDoubleBits() && HDoubleBits::cast(other)->bits() == bits();
1729 HDoubleBits(HValue* value, Bits bits)
1730 : HUnaryOperation(value), bits_(bits) {
1731 set_representation(Representation::Integer32());
1735 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1741 class HConstructDouble V8_FINAL : public HTemplateInstruction<2> {
1743 DECLARE_INSTRUCTION_FACTORY_P2(HConstructDouble, HValue*, HValue*);
1745 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1746 return Representation::Integer32();
1749 DECLARE_CONCRETE_INSTRUCTION(ConstructDouble)
1751 HValue* hi() { return OperandAt(0); }
1752 HValue* lo() { return OperandAt(1); }
1755 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1758 explicit HConstructDouble(HValue* hi, HValue* lo) {
1759 set_representation(Representation::Double());
1761 SetOperandAt(0, hi);
1762 SetOperandAt(1, lo);
1765 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1769 enum RemovableSimulate {
1775 class HSimulate V8_FINAL : public HInstruction {
1777 HSimulate(BailoutId ast_id,
1780 RemovableSimulate removable)
1782 pop_count_(pop_count),
1784 assigned_indexes_(2, zone),
1786 removable_(removable),
1787 done_with_replay_(false) {}
1790 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1792 bool HasAstId() const { return !ast_id_.IsNone(); }
1793 BailoutId ast_id() const { return ast_id_; }
1794 void set_ast_id(BailoutId id) {
1795 ASSERT(!HasAstId());
1799 int pop_count() const { return pop_count_; }
1800 const ZoneList<HValue*>* values() const { return &values_; }
1801 int GetAssignedIndexAt(int index) const {
1802 ASSERT(HasAssignedIndexAt(index));
1803 return assigned_indexes_[index];
1805 bool HasAssignedIndexAt(int index) const {
1806 return assigned_indexes_[index] != kNoIndex;
1808 void AddAssignedValue(int index, HValue* value) {
1809 AddValue(index, value);
1811 void AddPushedValue(HValue* value) {
1812 AddValue(kNoIndex, value);
1814 int ToOperandIndex(int environment_index) {
1815 for (int i = 0; i < assigned_indexes_.length(); ++i) {
1816 if (assigned_indexes_[i] == environment_index) return i;
1820 virtual int OperandCount() V8_OVERRIDE { return values_.length(); }
1821 virtual HValue* OperandAt(int index) const V8_OVERRIDE {
1822 return values_[index];
1825 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
1826 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1827 return Representation::None();
1830 void MergeWith(ZoneList<HSimulate*>* list);
1831 bool is_candidate_for_removal() { return removable_ == REMOVABLE_SIMULATE; }
1833 // Replay effects of this instruction on the given environment.
1834 void ReplayEnvironment(HEnvironment* env);
1836 DECLARE_CONCRETE_INSTRUCTION(Simulate)
1839 virtual void Verify() V8_OVERRIDE;
1840 void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
1841 Handle<JSFunction> closure() const { return closure_; }
1845 virtual void InternalSetOperandAt(int index, HValue* value) V8_OVERRIDE {
1846 values_[index] = value;
1850 static const int kNoIndex = -1;
1851 void AddValue(int index, HValue* value) {
1852 assigned_indexes_.Add(index, zone_);
1853 // Resize the list of pushed values.
1854 values_.Add(NULL, zone_);
1855 // Set the operand through the base method in HValue to make sure that the
1856 // use lists are correctly updated.
1857 SetOperandAt(values_.length() - 1, value);
1859 bool HasValueForIndex(int index) {
1860 for (int i = 0; i < assigned_indexes_.length(); ++i) {
1861 if (assigned_indexes_[i] == index) return true;
1867 ZoneList<HValue*> values_;
1868 ZoneList<int> assigned_indexes_;
1870 RemovableSimulate removable_ : 2;
1871 bool done_with_replay_ : 1;
1874 Handle<JSFunction> closure_;
1879 class HEnvironmentMarker V8_FINAL : public HTemplateInstruction<1> {
1881 enum Kind { BIND, LOOKUP };
1883 DECLARE_INSTRUCTION_FACTORY_P2(HEnvironmentMarker, Kind, int);
1885 Kind kind() { return kind_; }
1886 int index() { return index_; }
1887 HSimulate* next_simulate() { return next_simulate_; }
1888 void set_next_simulate(HSimulate* simulate) {
1889 next_simulate_ = simulate;
1892 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1893 return Representation::None();
1896 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1899 void set_closure(Handle<JSFunction> closure) {
1900 ASSERT(closure_.is_null());
1901 ASSERT(!closure.is_null());
1904 Handle<JSFunction> closure() const { return closure_; }
1907 DECLARE_CONCRETE_INSTRUCTION(EnvironmentMarker);
1910 HEnvironmentMarker(Kind kind, int index)
1911 : kind_(kind), index_(index), next_simulate_(NULL) { }
1915 HSimulate* next_simulate_;
1918 Handle<JSFunction> closure_;
1923 class HStackCheck V8_FINAL : public HTemplateInstruction<1> {
1930 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HStackCheck, Type);
1932 HValue* context() { return OperandAt(0); }
1934 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1935 return Representation::Tagged();
1939 // The stack check eliminator might try to eliminate the same stack
1940 // check instruction multiple times.
1942 DeleteAndReplaceWith(NULL);
1946 bool is_function_entry() { return type_ == kFunctionEntry; }
1947 bool is_backwards_branch() { return type_ == kBackwardsBranch; }
1949 DECLARE_CONCRETE_INSTRUCTION(StackCheck)
1952 HStackCheck(HValue* context, Type type) : type_(type) {
1953 SetOperandAt(0, context);
1954 SetChangesFlag(kNewSpacePromotion);
1962 NORMAL_RETURN, // Drop the function from the environment on return.
1963 CONSTRUCT_CALL_RETURN, // Either use allocated receiver or return value.
1964 GETTER_CALL_RETURN, // Returning from a getter, need to restore context.
1965 SETTER_CALL_RETURN // Use the RHS of the assignment as the return value.
1969 class HArgumentsObject;
1972 class HEnterInlined V8_FINAL : public HTemplateInstruction<0> {
1974 static HEnterInlined* New(Zone* zone,
1976 BailoutId return_id,
1977 Handle<JSFunction> closure,
1978 int arguments_count,
1979 FunctionLiteral* function,
1980 InliningKind inlining_kind,
1981 Variable* arguments_var,
1982 HArgumentsObject* arguments_object) {
1983 return new(zone) HEnterInlined(return_id, closure, arguments_count,
1984 function, inlining_kind, arguments_var,
1985 arguments_object, zone);
1988 void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
1989 ZoneList<HBasicBlock*>* return_targets() { return &return_targets_; }
1991 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1993 Handle<JSFunction> closure() const { return closure_; }
1994 int arguments_count() const { return arguments_count_; }
1995 bool arguments_pushed() const { return arguments_pushed_; }
1996 void set_arguments_pushed() { arguments_pushed_ = true; }
1997 FunctionLiteral* function() const { return function_; }
1998 InliningKind inlining_kind() const { return inlining_kind_; }
1999 BailoutId ReturnId() const { return return_id_; }
2001 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2002 return Representation::None();
2005 Variable* arguments_var() { return arguments_var_; }
2006 HArgumentsObject* arguments_object() { return arguments_object_; }
2008 DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
2011 HEnterInlined(BailoutId return_id,
2012 Handle<JSFunction> closure,
2013 int arguments_count,
2014 FunctionLiteral* function,
2015 InliningKind inlining_kind,
2016 Variable* arguments_var,
2017 HArgumentsObject* arguments_object,
2019 : return_id_(return_id),
2021 arguments_count_(arguments_count),
2022 arguments_pushed_(false),
2023 function_(function),
2024 inlining_kind_(inlining_kind),
2025 arguments_var_(arguments_var),
2026 arguments_object_(arguments_object),
2027 return_targets_(2, zone) {
2030 BailoutId return_id_;
2031 Handle<JSFunction> closure_;
2032 int arguments_count_;
2033 bool arguments_pushed_;
2034 FunctionLiteral* function_;
2035 InliningKind inlining_kind_;
2036 Variable* arguments_var_;
2037 HArgumentsObject* arguments_object_;
2038 ZoneList<HBasicBlock*> return_targets_;
2042 class HLeaveInlined V8_FINAL : public HTemplateInstruction<0> {
2044 HLeaveInlined(HEnterInlined* entry,
2047 drop_count_(drop_count) { }
2049 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2050 return Representation::None();
2053 virtual int argument_delta() const V8_OVERRIDE {
2054 return entry_->arguments_pushed() ? -drop_count_ : 0;
2057 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
2060 HEnterInlined* entry_;
2065 class HPushArguments V8_FINAL : public HInstruction {
2067 static HPushArguments* New(Zone* zone, HValue* context) {
2068 return new(zone) HPushArguments(zone);
2070 static HPushArguments* New(Zone* zone, HValue* context, HValue* arg1) {
2071 HPushArguments* instr = new(zone) HPushArguments(zone);
2072 instr->AddInput(arg1);
2075 static HPushArguments* New(Zone* zone, HValue* context, HValue* arg1,
2077 HPushArguments* instr = new(zone) HPushArguments(zone);
2078 instr->AddInput(arg1);
2079 instr->AddInput(arg2);
2082 static HPushArguments* New(Zone* zone, HValue* context, HValue* arg1,
2083 HValue* arg2, HValue* arg3) {
2084 HPushArguments* instr = new(zone) HPushArguments(zone);
2085 instr->AddInput(arg1);
2086 instr->AddInput(arg2);
2087 instr->AddInput(arg3);
2090 static HPushArguments* New(Zone* zone, HValue* context, HValue* arg1,
2091 HValue* arg2, HValue* arg3, HValue* arg4) {
2092 HPushArguments* instr = new(zone) HPushArguments(zone);
2093 instr->AddInput(arg1);
2094 instr->AddInput(arg2);
2095 instr->AddInput(arg3);
2096 instr->AddInput(arg4);
2100 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2101 return Representation::Tagged();
2104 virtual int argument_delta() const V8_OVERRIDE { return inputs_.length(); }
2105 HValue* argument(int i) { return OperandAt(i); }
2107 virtual int OperandCount() V8_FINAL V8_OVERRIDE { return inputs_.length(); }
2108 virtual HValue* OperandAt(int i) const V8_FINAL V8_OVERRIDE {
2112 void AddInput(HValue* value);
2114 DECLARE_CONCRETE_INSTRUCTION(PushArguments)
2117 virtual void InternalSetOperandAt(int i, HValue* value) V8_FINAL V8_OVERRIDE {
2122 explicit HPushArguments(Zone* zone)
2123 : HInstruction(HType::Tagged()), inputs_(4, zone) {
2124 set_representation(Representation::Tagged());
2127 ZoneList<HValue*> inputs_;
2131 class HThisFunction V8_FINAL : public HTemplateInstruction<0> {
2133 DECLARE_INSTRUCTION_FACTORY_P0(HThisFunction);
2135 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2136 return Representation::None();
2139 DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
2142 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2146 set_representation(Representation::Tagged());
2150 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2154 class HDeclareGlobals V8_FINAL : public HUnaryOperation {
2156 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HDeclareGlobals,
2160 HValue* context() { return OperandAt(0); }
2161 Handle<FixedArray> pairs() const { return pairs_; }
2162 int flags() const { return flags_; }
2164 DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
2166 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2167 return Representation::Tagged();
2171 HDeclareGlobals(HValue* context,
2172 Handle<FixedArray> pairs,
2174 : HUnaryOperation(context),
2177 set_representation(Representation::Tagged());
2178 SetAllSideEffects();
2181 Handle<FixedArray> pairs_;
2187 class HCall : public HTemplateInstruction<V> {
2189 // The argument count includes the receiver.
2190 explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
2191 this->set_representation(Representation::Tagged());
2192 this->SetAllSideEffects();
2195 virtual HType CalculateInferredType() V8_FINAL V8_OVERRIDE {
2196 return HType::Tagged();
2199 virtual int argument_count() const {
2200 return argument_count_;
2203 virtual int argument_delta() const V8_OVERRIDE {
2204 return -argument_count();
2208 int argument_count_;
2212 class HUnaryCall : public HCall<1> {
2214 HUnaryCall(HValue* value, int argument_count)
2215 : HCall<1>(argument_count) {
2216 SetOperandAt(0, value);
2219 virtual Representation RequiredInputRepresentation(
2220 int index) V8_FINAL V8_OVERRIDE {
2221 return Representation::Tagged();
2224 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2226 HValue* value() { return OperandAt(0); }
2230 class HBinaryCall : public HCall<2> {
2232 HBinaryCall(HValue* first, HValue* second, int argument_count)
2233 : HCall<2>(argument_count) {
2234 SetOperandAt(0, first);
2235 SetOperandAt(1, second);
2238 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2240 virtual Representation RequiredInputRepresentation(
2241 int index) V8_FINAL V8_OVERRIDE {
2242 return Representation::Tagged();
2245 HValue* first() { return OperandAt(0); }
2246 HValue* second() { return OperandAt(1); }
2250 class HCallJSFunction V8_FINAL : public HCall<1> {
2252 static HCallJSFunction* New(Zone* zone,
2256 bool pass_argument_count);
2258 HValue* function() { return OperandAt(0); }
2260 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2262 virtual Representation RequiredInputRepresentation(
2263 int index) V8_FINAL V8_OVERRIDE {
2265 return Representation::Tagged();
2268 bool pass_argument_count() const { return pass_argument_count_; }
2270 virtual bool HasStackCheck() V8_FINAL V8_OVERRIDE {
2271 return has_stack_check_;
2274 DECLARE_CONCRETE_INSTRUCTION(CallJSFunction)
2277 // The argument count includes the receiver.
2278 HCallJSFunction(HValue* function,
2280 bool pass_argument_count,
2281 bool has_stack_check)
2282 : HCall<1>(argument_count),
2283 pass_argument_count_(pass_argument_count),
2284 has_stack_check_(has_stack_check) {
2285 SetOperandAt(0, function);
2288 bool pass_argument_count_;
2289 bool has_stack_check_;
2293 class HCallWithDescriptor V8_FINAL : public HInstruction {
2295 static HCallWithDescriptor* New(Zone* zone, HValue* context,
2298 const CallInterfaceDescriptor* descriptor,
2299 const Vector<HValue*>& operands) {
2300 ASSERT(operands.length() == descriptor->environment_length());
2301 HCallWithDescriptor* res =
2302 new(zone) HCallWithDescriptor(target, argument_count,
2303 descriptor, operands, zone);
2307 virtual int OperandCount() V8_FINAL V8_OVERRIDE { return values_.length(); }
2308 virtual HValue* OperandAt(int index) const V8_FINAL V8_OVERRIDE {
2309 return values_[index];
2312 virtual Representation RequiredInputRepresentation(
2313 int index) V8_FINAL V8_OVERRIDE {
2315 return Representation::Tagged();
2317 int par_index = index - 1;
2318 ASSERT(par_index < descriptor_->environment_length());
2319 return descriptor_->GetParameterRepresentation(par_index);
2323 DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor)
2325 virtual HType CalculateInferredType() V8_FINAL V8_OVERRIDE {
2326 return HType::Tagged();
2329 virtual int argument_count() const {
2330 return argument_count_;
2333 virtual int argument_delta() const V8_OVERRIDE {
2334 return -argument_count_;
2337 const CallInterfaceDescriptor* descriptor() const {
2342 return OperandAt(0);
2345 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2348 // The argument count includes the receiver.
2349 HCallWithDescriptor(HValue* target,
2351 const CallInterfaceDescriptor* descriptor,
2352 const Vector<HValue*>& operands,
2354 : descriptor_(descriptor),
2355 values_(descriptor->environment_length() + 1, zone) {
2356 argument_count_ = argument_count;
2357 AddOperand(target, zone);
2358 for (int i = 0; i < operands.length(); i++) {
2359 AddOperand(operands[i], zone);
2361 this->set_representation(Representation::Tagged());
2362 this->SetAllSideEffects();
2365 void AddOperand(HValue* v, Zone* zone) {
2366 values_.Add(NULL, zone);
2367 SetOperandAt(values_.length() - 1, v);
2370 void InternalSetOperandAt(int index,
2371 HValue* value) V8_FINAL V8_OVERRIDE {
2372 values_[index] = value;
2375 const CallInterfaceDescriptor* descriptor_;
2376 ZoneList<HValue*> values_;
2377 int argument_count_;
2381 class HInvokeFunction V8_FINAL : public HBinaryCall {
2383 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInvokeFunction, HValue*, int);
2385 HInvokeFunction(HValue* context,
2387 Handle<JSFunction> known_function,
2389 : HBinaryCall(context, function, argument_count),
2390 known_function_(known_function) {
2391 formal_parameter_count_ = known_function.is_null()
2392 ? 0 : known_function->shared()->formal_parameter_count();
2393 has_stack_check_ = !known_function.is_null() &&
2394 (known_function->code()->kind() == Code::FUNCTION ||
2395 known_function->code()->kind() == Code::OPTIMIZED_FUNCTION);
2398 static HInvokeFunction* New(Zone* zone,
2401 Handle<JSFunction> known_function,
2402 int argument_count) {
2403 return new(zone) HInvokeFunction(context, function,
2404 known_function, argument_count);
2407 HValue* context() { return first(); }
2408 HValue* function() { return second(); }
2409 Handle<JSFunction> known_function() { return known_function_; }
2410 int formal_parameter_count() const { return formal_parameter_count_; }
2412 virtual bool HasStackCheck() V8_FINAL V8_OVERRIDE {
2413 return has_stack_check_;
2416 DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
2419 HInvokeFunction(HValue* context, HValue* function, int argument_count)
2420 : HBinaryCall(context, function, argument_count),
2421 has_stack_check_(false) {
2424 Handle<JSFunction> known_function_;
2425 int formal_parameter_count_;
2426 bool has_stack_check_;
2430 class HCallFunction V8_FINAL : public HBinaryCall {
2432 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallFunction, HValue*, int);
2433 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(
2434 HCallFunction, HValue*, int, CallFunctionFlags);
2436 HValue* context() { return first(); }
2437 HValue* function() { return second(); }
2438 CallFunctionFlags function_flags() const { return function_flags_; }
2440 DECLARE_CONCRETE_INSTRUCTION(CallFunction)
2442 virtual int argument_delta() const V8_OVERRIDE { return -argument_count(); }
2445 HCallFunction(HValue* context,
2448 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS)
2449 : HBinaryCall(context, function, argument_count), function_flags_(flags) {
2451 CallFunctionFlags function_flags_;
2455 class HCallNew V8_FINAL : public HBinaryCall {
2457 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallNew, HValue*, int);
2459 HValue* context() { return first(); }
2460 HValue* constructor() { return second(); }
2462 DECLARE_CONCRETE_INSTRUCTION(CallNew)
2465 HCallNew(HValue* context, HValue* constructor, int argument_count)
2466 : HBinaryCall(context, constructor, argument_count) {}
2470 class HCallNewArray V8_FINAL : public HBinaryCall {
2472 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCallNewArray,
2477 HValue* context() { return first(); }
2478 HValue* constructor() { return second(); }
2480 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2482 ElementsKind elements_kind() const { return elements_kind_; }
2484 DECLARE_CONCRETE_INSTRUCTION(CallNewArray)
2487 HCallNewArray(HValue* context, HValue* constructor, int argument_count,
2488 ElementsKind elements_kind)
2489 : HBinaryCall(context, constructor, argument_count),
2490 elements_kind_(elements_kind) {}
2492 ElementsKind elements_kind_;
2496 class HCallRuntime V8_FINAL : public HCall<1> {
2498 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCallRuntime,
2500 const Runtime::Function*,
2503 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2505 HValue* context() { return OperandAt(0); }
2506 const Runtime::Function* function() const { return c_function_; }
2507 Handle<String> name() const { return name_; }
2508 SaveFPRegsMode save_doubles() const { return save_doubles_; }
2509 void set_save_doubles(SaveFPRegsMode save_doubles) {
2510 save_doubles_ = save_doubles;
2513 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2514 return Representation::Tagged();
2517 DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
2520 HCallRuntime(HValue* context,
2521 Handle<String> name,
2522 const Runtime::Function* c_function,
2524 : HCall<1>(argument_count), c_function_(c_function), name_(name),
2525 save_doubles_(kDontSaveFPRegs) {
2526 SetOperandAt(0, context);
2529 const Runtime::Function* c_function_;
2530 Handle<String> name_;
2531 SaveFPRegsMode save_doubles_;
2535 class HMapEnumLength V8_FINAL : public HUnaryOperation {
2537 DECLARE_INSTRUCTION_FACTORY_P1(HMapEnumLength, HValue*);
2539 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2540 return Representation::Tagged();
2543 DECLARE_CONCRETE_INSTRUCTION(MapEnumLength)
2546 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2549 explicit HMapEnumLength(HValue* value)
2550 : HUnaryOperation(value, HType::Smi()) {
2551 set_representation(Representation::Smi());
2553 SetDependsOnFlag(kMaps);
2556 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2560 class HUnaryMathOperation V8_FINAL : public HTemplateInstruction<2> {
2562 static HInstruction* New(Zone* zone,
2565 BuiltinFunctionId op);
2567 HValue* context() { return OperandAt(0); }
2568 HValue* value() { return OperandAt(1); }
2570 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2572 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2574 return Representation::Tagged();
2583 return Representation::Double();
2585 return representation();
2587 return Representation::Integer32();
2590 return Representation::None();
2595 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
2597 virtual HValue* Canonicalize() V8_OVERRIDE;
2598 virtual Representation RepresentationFromUses() V8_OVERRIDE;
2599 virtual Representation RepresentationFromInputs() V8_OVERRIDE;
2601 BuiltinFunctionId op() const { return op_; }
2602 const char* OpName() const;
2604 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
2607 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2608 HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
2609 return op_ == b->op();
2613 // Indicates if we support a double (and int32) output for Math.floor and
2615 bool SupportsFlexibleFloorAndRound() const {
2616 #ifdef V8_TARGET_ARCH_ARM64
2622 HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
2623 : HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
2624 SetOperandAt(0, context);
2625 SetOperandAt(1, value);
2629 if (SupportsFlexibleFloorAndRound()) {
2630 SetFlag(kFlexibleRepresentation);
2632 set_representation(Representation::Integer32());
2636 set_representation(Representation::Integer32());
2639 // Not setting representation here: it is None intentionally.
2640 SetFlag(kFlexibleRepresentation);
2641 // TODO(svenpanne) This flag is actually only needed if representation()
2642 // is tagged, and not when it is an unboxed double or unboxed integer.
2643 SetChangesFlag(kNewSpacePromotion);
2649 set_representation(Representation::Double());
2655 SetFlag(kAllowUndefinedAsNaN);
2658 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2660 HValue* SimplifiedDividendForMathFloorOfDiv(HDiv* hdiv);
2661 HValue* SimplifiedDivisorForMathFloorOfDiv(HDiv* hdiv);
2663 BuiltinFunctionId op_;
2667 class HLoadRoot V8_FINAL : public HTemplateInstruction<0> {
2669 DECLARE_INSTRUCTION_FACTORY_P1(HLoadRoot, Heap::RootListIndex);
2670 DECLARE_INSTRUCTION_FACTORY_P2(HLoadRoot, Heap::RootListIndex, HType);
2672 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2673 return Representation::None();
2676 Heap::RootListIndex index() const { return index_; }
2678 DECLARE_CONCRETE_INSTRUCTION(LoadRoot)
2681 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2682 HLoadRoot* b = HLoadRoot::cast(other);
2683 return index_ == b->index_;
2687 HLoadRoot(Heap::RootListIndex index, HType type = HType::Tagged())
2688 : HTemplateInstruction<0>(type), index_(index) {
2690 // TODO(bmeurer): We'll need kDependsOnRoots once we add the
2691 // corresponding HStoreRoot instruction.
2692 SetDependsOnFlag(kCalls);
2695 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2697 const Heap::RootListIndex index_;
2701 class HCheckMaps V8_FINAL : public HTemplateInstruction<2> {
2703 static HCheckMaps* New(Zone* zone, HValue* context, HValue* value,
2704 Handle<Map> map, HValue* typecheck = NULL) {
2705 return new(zone) HCheckMaps(value, new(zone) UniqueSet<Map>(
2706 Unique<Map>::CreateImmovable(map), zone), typecheck);
2708 static HCheckMaps* New(Zone* zone, HValue* context,
2709 HValue* value, SmallMapList* map_list,
2710 HValue* typecheck = NULL) {
2711 UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone);
2712 for (int i = 0; i < map_list->length(); ++i) {
2713 maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone);
2715 return new(zone) HCheckMaps(value, maps, typecheck);
2718 bool IsStabilityCheck() const { return is_stability_check_; }
2719 void MarkAsStabilityCheck() {
2720 maps_are_stable_ = true;
2721 has_migration_target_ = false;
2722 is_stability_check_ = true;
2723 ClearChangesFlag(kNewSpacePromotion);
2724 ClearDependsOnFlag(kElementsKind);
2725 ClearDependsOnFlag(kMaps);
2728 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
2729 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2730 return Representation::Tagged();
2733 virtual HType CalculateInferredType() V8_OVERRIDE {
2734 if (value()->type().IsHeapObject()) return value()->type();
2735 return HType::HeapObject();
2738 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2740 HValue* value() const { return OperandAt(0); }
2741 HValue* typecheck() const { return OperandAt(1); }
2743 const UniqueSet<Map>* maps() const { return maps_; }
2744 void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; }
2746 bool maps_are_stable() const { return maps_are_stable_; }
2748 bool HasMigrationTarget() const { return has_migration_target_; }
2750 virtual HValue* Canonicalize() V8_OVERRIDE;
2752 static HCheckMaps* CreateAndInsertAfter(Zone* zone,
2756 HInstruction* instr) {
2757 return instr->Append(new(zone) HCheckMaps(
2758 value, new(zone) UniqueSet<Map>(map, zone), map_is_stable));
2761 static HCheckMaps* CreateAndInsertBefore(Zone* zone,
2763 const UniqueSet<Map>* maps,
2764 bool maps_are_stable,
2765 HInstruction* instr) {
2766 return instr->Prepend(new(zone) HCheckMaps(value, maps, maps_are_stable));
2769 DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
2772 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2773 return this->maps()->Equals(HCheckMaps::cast(other)->maps());
2776 virtual int RedefinedOperandIndex() { return 0; }
2779 HCheckMaps(HValue* value, const UniqueSet<Map>* maps, bool maps_are_stable)
2780 : HTemplateInstruction<2>(HType::HeapObject()), maps_(maps),
2781 has_migration_target_(false), is_stability_check_(false),
2782 maps_are_stable_(maps_are_stable) {
2783 ASSERT_NE(0, maps->size());
2784 SetOperandAt(0, value);
2785 // Use the object value for the dependency.
2786 SetOperandAt(1, value);
2787 set_representation(Representation::Tagged());
2789 SetDependsOnFlag(kMaps);
2790 SetDependsOnFlag(kElementsKind);
2793 HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck)
2794 : HTemplateInstruction<2>(HType::HeapObject()), maps_(maps),
2795 has_migration_target_(false), is_stability_check_(false),
2796 maps_are_stable_(true) {
2797 ASSERT_NE(0, maps->size());
2798 SetOperandAt(0, value);
2799 // Use the object value for the dependency if NULL is passed.
2800 SetOperandAt(1, typecheck ? typecheck : value);
2801 set_representation(Representation::Tagged());
2803 SetDependsOnFlag(kMaps);
2804 SetDependsOnFlag(kElementsKind);
2805 for (int i = 0; i < maps->size(); ++i) {
2806 Handle<Map> map = maps->at(i).handle();
2807 if (map->is_migration_target()) has_migration_target_ = true;
2808 if (!map->is_stable()) maps_are_stable_ = false;
2810 if (has_migration_target_) SetChangesFlag(kNewSpacePromotion);
2813 const UniqueSet<Map>* maps_;
2814 bool has_migration_target_ : 1;
2815 bool is_stability_check_ : 1;
2816 bool maps_are_stable_ : 1;
2820 class HCheckValue V8_FINAL : public HUnaryOperation {
2822 static HCheckValue* New(Zone* zone, HValue* context,
2823 HValue* value, Handle<JSFunction> func) {
2824 bool in_new_space = zone->isolate()->heap()->InNewSpace(*func);
2825 // NOTE: We create an uninitialized Unique and initialize it later.
2826 // This is because a JSFunction can move due to GC during graph creation.
2827 // TODO(titzer): This is a migration crutch. Replace with some kind of
2828 // Uniqueness scope later.
2829 Unique<JSFunction> target = Unique<JSFunction>::CreateUninitialized(func);
2830 HCheckValue* check = new(zone) HCheckValue(value, target, in_new_space);
2833 static HCheckValue* New(Zone* zone, HValue* context,
2834 HValue* value, Unique<HeapObject> target,
2835 bool object_in_new_space) {
2836 return new(zone) HCheckValue(value, target, object_in_new_space);
2839 virtual void FinalizeUniqueness() V8_OVERRIDE {
2840 object_ = Unique<HeapObject>(object_.handle());
2843 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2844 return Representation::Tagged();
2846 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2848 virtual HValue* Canonicalize() V8_OVERRIDE;
2851 virtual void Verify() V8_OVERRIDE;
2854 Unique<HeapObject> object() const { return object_; }
2855 bool object_in_new_space() const { return object_in_new_space_; }
2857 DECLARE_CONCRETE_INSTRUCTION(CheckValue)
2860 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2861 HCheckValue* b = HCheckValue::cast(other);
2862 return object_ == b->object_;
2866 HCheckValue(HValue* value, Unique<HeapObject> object,
2867 bool object_in_new_space)
2868 : HUnaryOperation(value, value->type()),
2870 object_in_new_space_(object_in_new_space) {
2871 set_representation(Representation::Tagged());
2875 Unique<HeapObject> object_;
2876 bool object_in_new_space_;
2880 class HCheckInstanceType V8_FINAL : public HUnaryOperation {
2886 IS_INTERNALIZED_STRING,
2887 LAST_INTERVAL_CHECK = IS_JS_ARRAY
2890 DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue*, Check);
2892 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2894 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2895 return Representation::Tagged();
2898 virtual HType CalculateInferredType() V8_OVERRIDE {
2900 case IS_SPEC_OBJECT: return HType::JSObject();
2901 case IS_JS_ARRAY: return HType::JSArray();
2902 case IS_STRING: return HType::String();
2903 case IS_INTERNALIZED_STRING: return HType::String();
2906 return HType::Tagged();
2909 virtual HValue* Canonicalize() V8_OVERRIDE;
2911 bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
2912 void GetCheckInterval(InstanceType* first, InstanceType* last);
2913 void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
2915 Check check() const { return check_; }
2917 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
2920 // TODO(ager): It could be nice to allow the ommision of instance
2921 // type checks if we have already performed an instance type check
2922 // with a larger range.
2923 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2924 HCheckInstanceType* b = HCheckInstanceType::cast(other);
2925 return check_ == b->check_;
2928 virtual int RedefinedOperandIndex() { return 0; }
2931 const char* GetCheckName();
2933 HCheckInstanceType(HValue* value, Check check)
2934 : HUnaryOperation(value, HType::HeapObject()), check_(check) {
2935 set_representation(Representation::Tagged());
2943 class HCheckSmi V8_FINAL : public HUnaryOperation {
2945 DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue*);
2947 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2948 return Representation::Tagged();
2951 virtual HValue* Canonicalize() V8_OVERRIDE {
2952 HType value_type = value()->type();
2953 if (value_type.IsSmi()) {
2959 DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
2962 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2965 explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
2966 set_representation(Representation::Smi());
2972 class HCheckHeapObject V8_FINAL : public HUnaryOperation {
2974 DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
2976 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
2977 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2978 return Representation::Tagged();
2981 virtual HType CalculateInferredType() V8_OVERRIDE {
2982 if (value()->type().IsHeapObject()) return value()->type();
2983 return HType::HeapObject();
2987 virtual void Verify() V8_OVERRIDE;
2990 virtual HValue* Canonicalize() V8_OVERRIDE {
2991 return value()->type().IsHeapObject() ? NULL : this;
2994 DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
2997 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3000 explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) {
3001 set_representation(Representation::Tagged());
3007 class InductionVariableData;
3010 struct InductionVariableLimitUpdate {
3011 InductionVariableData* updated_variable;
3013 bool limit_is_upper;
3014 bool limit_is_included;
3016 InductionVariableLimitUpdate()
3017 : updated_variable(NULL), limit(NULL),
3018 limit_is_upper(false), limit_is_included(false) {}
3028 class InductionVariableData V8_FINAL : public ZoneObject {
3030 class InductionVariableCheck : public ZoneObject {
3032 HBoundsCheck* check() { return check_; }
3033 InductionVariableCheck* next() { return next_; }
3034 bool HasUpperLimit() { return upper_limit_ >= 0; }
3035 int32_t upper_limit() {
3036 ASSERT(HasUpperLimit());
3037 return upper_limit_;
3039 void set_upper_limit(int32_t upper_limit) {
3040 upper_limit_ = upper_limit;
3043 bool processed() { return processed_; }
3044 void set_processed() { processed_ = true; }
3046 InductionVariableCheck(HBoundsCheck* check,
3047 InductionVariableCheck* next,
3048 int32_t upper_limit = kNoLimit)
3049 : check_(check), next_(next), upper_limit_(upper_limit),
3050 processed_(false) {}
3053 HBoundsCheck* check_;
3054 InductionVariableCheck* next_;
3055 int32_t upper_limit_;
3059 class ChecksRelatedToLength : public ZoneObject {
3061 HValue* length() { return length_; }
3062 ChecksRelatedToLength* next() { return next_; }
3063 InductionVariableCheck* checks() { return checks_; }
3065 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3066 void CloseCurrentBlock();
3068 ChecksRelatedToLength(HValue* length, ChecksRelatedToLength* next)
3069 : length_(length), next_(next), checks_(NULL),
3070 first_check_in_block_(NULL),
3072 added_constant_(NULL),
3073 current_and_mask_in_block_(0),
3074 current_or_mask_in_block_(0) {}
3077 void UseNewIndexInCurrentBlock(Token::Value token,
3082 HBoundsCheck* first_check_in_block() { return first_check_in_block_; }
3083 HBitwise* added_index() { return added_index_; }
3084 void set_added_index(HBitwise* index) { added_index_ = index; }
3085 HConstant* added_constant() { return added_constant_; }
3086 void set_added_constant(HConstant* constant) { added_constant_ = constant; }
3087 int32_t current_and_mask_in_block() { return current_and_mask_in_block_; }
3088 int32_t current_or_mask_in_block() { return current_or_mask_in_block_; }
3089 int32_t current_upper_limit() { return current_upper_limit_; }
3092 ChecksRelatedToLength* next_;
3093 InductionVariableCheck* checks_;
3095 HBoundsCheck* first_check_in_block_;
3096 HBitwise* added_index_;
3097 HConstant* added_constant_;
3098 int32_t current_and_mask_in_block_;
3099 int32_t current_or_mask_in_block_;
3100 int32_t current_upper_limit_;
3103 struct LimitFromPredecessorBlock {
3104 InductionVariableData* variable;
3107 HBasicBlock* other_target;
3109 bool LimitIsValid() { return token != Token::ILLEGAL; }
3111 bool LimitIsIncluded() {
3112 return Token::IsEqualityOp(token) ||
3113 token == Token::GTE || token == Token::LTE;
3115 bool LimitIsUpper() {
3116 return token == Token::LTE || token == Token::LT || token == Token::NE;
3119 LimitFromPredecessorBlock()
3121 token(Token::ILLEGAL),
3123 other_target(NULL) {}
3126 static const int32_t kNoLimit = -1;
3128 static InductionVariableData* ExaminePhi(HPhi* phi);
3129 static void ComputeLimitFromPredecessorBlock(
3131 LimitFromPredecessorBlock* result);
3132 static bool ComputeInductionVariableLimit(
3134 InductionVariableLimitUpdate* additional_limit);
3136 struct BitwiseDecompositionResult {
3142 BitwiseDecompositionResult()
3143 : base(NULL), and_mask(0), or_mask(0), context(NULL) {}
3145 static void DecomposeBitwise(HValue* value,
3146 BitwiseDecompositionResult* result);
3148 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3150 bool CheckIfBranchIsLoopGuard(Token::Value token,
3151 HBasicBlock* current_branch,
3152 HBasicBlock* other_branch);
3154 void UpdateAdditionalLimit(InductionVariableLimitUpdate* update);
3156 HPhi* phi() { return phi_; }
3157 HValue* base() { return base_; }
3158 int32_t increment() { return increment_; }
3159 HValue* limit() { return limit_; }
3160 bool limit_included() { return limit_included_; }
3161 HBasicBlock* limit_validity() { return limit_validity_; }
3162 HBasicBlock* induction_exit_block() { return induction_exit_block_; }
3163 HBasicBlock* induction_exit_target() { return induction_exit_target_; }
3164 ChecksRelatedToLength* checks() { return checks_; }
3165 HValue* additional_upper_limit() { return additional_upper_limit_; }
3166 bool additional_upper_limit_is_included() {
3167 return additional_upper_limit_is_included_;
3169 HValue* additional_lower_limit() { return additional_lower_limit_; }
3170 bool additional_lower_limit_is_included() {
3171 return additional_lower_limit_is_included_;
3174 bool LowerLimitIsNonNegativeConstant() {
3175 if (base()->IsInteger32Constant() && base()->GetInteger32Constant() >= 0) {
3178 if (additional_lower_limit() != NULL &&
3179 additional_lower_limit()->IsInteger32Constant() &&
3180 additional_lower_limit()->GetInteger32Constant() >= 0) {
3181 // Ignoring the corner case of !additional_lower_limit_is_included()
3182 // is safe, handling it adds unneeded complexity.
3188 int32_t ComputeUpperLimit(int32_t and_mask, int32_t or_mask);
3191 template <class T> void swap(T* a, T* b) {
3197 InductionVariableData(HPhi* phi, HValue* base, int32_t increment)
3198 : phi_(phi), base_(IgnoreOsrValue(base)), increment_(increment),
3199 limit_(NULL), limit_included_(false), limit_validity_(NULL),
3200 induction_exit_block_(NULL), induction_exit_target_(NULL),
3202 additional_upper_limit_(NULL),
3203 additional_upper_limit_is_included_(false),
3204 additional_lower_limit_(NULL),
3205 additional_lower_limit_is_included_(false) {}
3207 static int32_t ComputeIncrement(HPhi* phi, HValue* phi_operand);
3209 static HValue* IgnoreOsrValue(HValue* v);
3210 static InductionVariableData* GetInductionVariableData(HValue* v);
3216 bool limit_included_;
3217 HBasicBlock* limit_validity_;
3218 HBasicBlock* induction_exit_block_;
3219 HBasicBlock* induction_exit_target_;
3220 ChecksRelatedToLength* checks_;
3221 HValue* additional_upper_limit_;
3222 bool additional_upper_limit_is_included_;
3223 HValue* additional_lower_limit_;
3224 bool additional_lower_limit_is_included_;
3228 class HPhi V8_FINAL : public HValue {
3230 HPhi(int merged_index, Zone* zone)
3232 merged_index_(merged_index),
3234 induction_variable_data_(NULL) {
3235 for (int i = 0; i < Representation::kNumRepresentations; i++) {
3236 non_phi_uses_[i] = 0;
3237 indirect_uses_[i] = 0;
3239 ASSERT(merged_index >= 0 || merged_index == kInvalidMergedIndex);
3240 SetFlag(kFlexibleRepresentation);
3241 SetFlag(kAllowUndefinedAsNaN);
3244 virtual Representation RepresentationFromInputs() V8_OVERRIDE;
3246 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
3247 virtual void InferRepresentation(
3248 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
3249 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3250 return representation();
3252 virtual Representation KnownOptimalRepresentation() V8_OVERRIDE {
3253 return representation();
3255 virtual HType CalculateInferredType() V8_OVERRIDE;
3256 virtual int OperandCount() V8_OVERRIDE { return inputs_.length(); }
3257 virtual HValue* OperandAt(int index) const V8_OVERRIDE {
3258 return inputs_[index];
3260 HValue* GetRedundantReplacement();
3261 void AddInput(HValue* value);
3264 bool IsReceiver() const { return merged_index_ == 0; }
3265 bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
3267 virtual HSourcePosition position() const V8_OVERRIDE;
3269 int merged_index() const { return merged_index_; }
3271 InductionVariableData* induction_variable_data() {
3272 return induction_variable_data_;
3274 bool IsInductionVariable() {
3275 return induction_variable_data_ != NULL;
3277 bool IsLimitedInductionVariable() {
3278 return IsInductionVariable() &&
3279 induction_variable_data_->limit() != NULL;
3281 void DetectInductionVariable() {
3282 ASSERT(induction_variable_data_ == NULL);
3283 induction_variable_data_ = InductionVariableData::ExaminePhi(this);
3286 virtual void PrintTo(StringStream* stream) V8_OVERRIDE;
3289 virtual void Verify() V8_OVERRIDE;
3292 void InitRealUses(int id);
3293 void AddNonPhiUsesFrom(HPhi* other);
3294 void AddIndirectUsesTo(int* use_count);
3296 int tagged_non_phi_uses() const {
3297 return non_phi_uses_[Representation::kTagged];
3299 int smi_non_phi_uses() const {
3300 return non_phi_uses_[Representation::kSmi];
3302 int int32_non_phi_uses() const {
3303 return non_phi_uses_[Representation::kInteger32];
3305 int double_non_phi_uses() const {
3306 return non_phi_uses_[Representation::kDouble];
3308 int tagged_indirect_uses() const {
3309 return indirect_uses_[Representation::kTagged];
3311 int smi_indirect_uses() const {
3312 return indirect_uses_[Representation::kSmi];
3314 int int32_indirect_uses() const {
3315 return indirect_uses_[Representation::kInteger32];
3317 int double_indirect_uses() const {
3318 return indirect_uses_[Representation::kDouble];
3320 int phi_id() { return phi_id_; }
3322 static HPhi* cast(HValue* value) {
3323 ASSERT(value->IsPhi());
3324 return reinterpret_cast<HPhi*>(value);
3326 virtual Opcode opcode() const V8_OVERRIDE { return HValue::kPhi; }
3328 void SimplifyConstantInputs();
3330 // Marker value representing an invalid merge index.
3331 static const int kInvalidMergedIndex = -1;
3334 virtual void DeleteFromGraph() V8_OVERRIDE;
3335 virtual void InternalSetOperandAt(int index, HValue* value) V8_OVERRIDE {
3336 inputs_[index] = value;
3340 ZoneList<HValue*> inputs_;
3343 int non_phi_uses_[Representation::kNumRepresentations];
3344 int indirect_uses_[Representation::kNumRepresentations];
3346 InductionVariableData* induction_variable_data_;
3348 // TODO(titzer): we can't eliminate the receiver for generating backtraces
3349 virtual bool IsDeletable() const V8_OVERRIDE { return !IsReceiver(); }
3353 // Common base class for HArgumentsObject and HCapturedObject.
3354 class HDematerializedObject : public HInstruction {
3356 HDematerializedObject(int count, Zone* zone) : values_(count, zone) {}
3358 virtual int OperandCount() V8_FINAL V8_OVERRIDE { return values_.length(); }
3359 virtual HValue* OperandAt(int index) const V8_FINAL V8_OVERRIDE {
3360 return values_[index];
3363 virtual bool HasEscapingOperandAt(int index) V8_FINAL V8_OVERRIDE {
3366 virtual Representation RequiredInputRepresentation(
3367 int index) V8_FINAL V8_OVERRIDE {
3368 return Representation::None();
3372 virtual void InternalSetOperandAt(int index,
3373 HValue* value) V8_FINAL V8_OVERRIDE {
3374 values_[index] = value;
3377 // List of values tracked by this marker.
3378 ZoneList<HValue*> values_;
3382 class HArgumentsObject V8_FINAL : public HDematerializedObject {
3384 static HArgumentsObject* New(Zone* zone, HValue* context, int count) {
3385 return new(zone) HArgumentsObject(count, zone);
3388 // The values contain a list of all elements in the arguments object
3389 // including the receiver object, which is skipped when materializing.
3390 const ZoneList<HValue*>* arguments_values() const { return &values_; }
3391 int arguments_count() const { return values_.length(); }
3393 void AddArgument(HValue* argument, Zone* zone) {
3394 values_.Add(NULL, zone); // Resize list.
3395 SetOperandAt(values_.length() - 1, argument);
3398 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
3401 HArgumentsObject(int count, Zone* zone)
3402 : HDematerializedObject(count, zone) {
3403 set_representation(Representation::Tagged());
3404 SetFlag(kIsArguments);
3409 class HCapturedObject V8_FINAL : public HDematerializedObject {
3411 HCapturedObject(int length, int id, Zone* zone)
3412 : HDematerializedObject(length, zone), capture_id_(id) {
3413 set_representation(Representation::Tagged());
3414 values_.AddBlock(NULL, length, zone); // Resize list.
3417 // The values contain a list of all in-object properties inside the
3418 // captured object and is index by field index. Properties in the
3419 // properties or elements backing store are not tracked here.
3420 const ZoneList<HValue*>* values() const { return &values_; }
3421 int length() const { return values_.length(); }
3422 int capture_id() const { return capture_id_; }
3424 // Shortcut for the map value of this captured object.
3425 HValue* map_value() const { return values()->first(); }
3427 void ReuseSideEffectsFromStore(HInstruction* store) {
3428 ASSERT(store->HasObservableSideEffects());
3429 ASSERT(store->IsStoreNamedField());
3430 changes_flags_.Add(store->ChangesFlags());
3433 // Replay effects of this instruction on the given environment.
3434 void ReplayEnvironment(HEnvironment* env);
3436 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3438 DECLARE_CONCRETE_INSTRUCTION(CapturedObject)
3443 // Note that we cannot DCE captured objects as they are used to replay
3444 // the environment. This method is here as an explicit reminder.
3445 // TODO(mstarzinger): Turn HSimulates into full snapshots maybe?
3446 virtual bool IsDeletable() const V8_FINAL V8_OVERRIDE { return false; }
3450 class HConstant V8_FINAL : public HTemplateInstruction<0> {
3452 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, int32_t);
3453 DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation);
3454 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double);
3455 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle<Object>);
3456 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);
3458 static HConstant* CreateAndInsertAfter(Zone* zone,
3461 Representation representation,
3462 HInstruction* instruction) {
3463 return instruction->Append(HConstant::New(
3464 zone, context, value, representation));
3467 static HConstant* CreateAndInsertBefore(Zone* zone,
3470 Representation representation,
3471 HInstruction* instruction) {
3472 return instruction->Prepend(HConstant::New(
3473 zone, context, value, representation));
3476 static HConstant* CreateAndInsertBefore(Zone* zone,
3479 HInstruction* instruction) {
3480 return instruction->Prepend(new(zone) HConstant(
3481 map, Unique<Map>(Handle<Map>::null()), map_is_stable,
3482 Representation::Tagged(), HType::HeapObject(), true,
3483 false, false, MAP_TYPE));
3486 static HConstant* CreateAndInsertAfter(Zone* zone,
3489 HInstruction* instruction) {
3490 return instruction->Append(new(zone) HConstant(
3491 map, Unique<Map>(Handle<Map>::null()), map_is_stable,
3492 Representation::Tagged(), HType::HeapObject(), true,
3493 false, false, MAP_TYPE));
3496 Handle<Object> handle(Isolate* isolate) {
3497 if (object_.handle().is_null()) {
3498 // Default arguments to is_not_in_new_space depend on this heap number
3499 // to be tenured so that it's guaranteed not to be located in new space.
3500 object_ = Unique<Object>::CreateUninitialized(
3501 isolate->factory()->NewNumber(double_value_, TENURED));
3503 AllowDeferredHandleDereference smi_check;
3504 ASSERT(has_int32_value_ || !object_.handle()->IsSmi());
3505 return object_.handle();
3508 bool IsSpecialDouble() const {
3509 return has_double_value_ &&
3510 (BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) ||
3511 FixedDoubleArray::is_the_hole_nan(double_value_) ||
3512 std::isnan(double_value_));
3515 bool NotInNewSpace() const {
3516 return is_not_in_new_space_;
3519 bool ImmortalImmovable() const;
3521 bool IsCell() const {
3522 return instance_type_ == CELL_TYPE || instance_type_ == PROPERTY_CELL_TYPE;
3525 bool IsMap() const {
3526 return instance_type_ == MAP_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 bool HasMapValue() const { return instance_type_ == MAP_TYPE; }
3597 Unique<Map> MapValue() const {
3598 ASSERT(HasMapValue());
3599 return Unique<Map>::cast(GetUnique());
3601 bool HasStableMapValue() const {
3602 ASSERT(HasMapValue() || !has_stable_map_value_);
3603 return has_stable_map_value_;
3606 bool HasObjectMap() const { return !object_map_.IsNull(); }
3607 Unique<Map> ObjectMap() const {
3608 ASSERT(HasObjectMap());
3612 virtual intptr_t Hashcode() V8_OVERRIDE {
3613 if (has_int32_value_) {
3614 return static_cast<intptr_t>(int32_value_);
3615 } else if (has_double_value_) {
3616 return static_cast<intptr_t>(BitCast<int64_t>(double_value_));
3617 } else if (has_external_reference_value_) {
3618 return reinterpret_cast<intptr_t>(external_reference_value_.address());
3620 ASSERT(!object_.handle().is_null());
3621 return object_.Hashcode();
3625 virtual void FinalizeUniqueness() V8_OVERRIDE {
3626 if (!has_double_value_ && !has_external_reference_value_) {
3627 ASSERT(!object_.handle().is_null());
3628 object_ = Unique<Object>(object_.handle());
3632 Unique<Object> GetUnique() const {
3636 bool EqualsUnique(Unique<Object> other) const {
3637 return object_.IsInitialized() && object_ == other;
3640 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
3641 HConstant* other_constant = HConstant::cast(other);
3642 if (has_int32_value_) {
3643 return other_constant->has_int32_value_ &&
3644 int32_value_ == other_constant->int32_value_;
3645 } else if (has_double_value_) {
3646 return other_constant->has_double_value_ &&
3647 BitCast<int64_t>(double_value_) ==
3648 BitCast<int64_t>(other_constant->double_value_);
3649 } else if (has_external_reference_value_) {
3650 return other_constant->has_external_reference_value_ &&
3651 external_reference_value_ ==
3652 other_constant->external_reference_value_;
3654 if (other_constant->has_int32_value_ ||
3655 other_constant->has_double_value_ ||
3656 other_constant->has_external_reference_value_) {
3659 ASSERT(!object_.handle().is_null());
3660 return other_constant->object_ == object_;
3665 virtual void Verify() V8_OVERRIDE { }
3668 DECLARE_CONCRETE_INSTRUCTION(Constant)
3671 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
3674 friend class HGraph;
3675 HConstant(Handle<Object> handle, Representation r = Representation::None());
3676 HConstant(int32_t value,
3677 Representation r = Representation::None(),
3678 bool is_not_in_new_space = true,
3679 Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3680 HConstant(double value,
3681 Representation r = Representation::None(),
3682 bool is_not_in_new_space = true,
3683 Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3684 HConstant(Unique<Object> object,
3685 Unique<Map> object_map,
3686 bool has_stable_map_value,
3689 bool is_not_in_new_space,
3691 bool is_undetectable,
3692 InstanceType instance_type);
3694 explicit HConstant(ExternalReference reference);
3696 void Initialize(Representation r);
3698 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
3700 // If this is a numerical constant, object_ either points to the
3701 // HeapObject the constant originated from or is null. If the
3702 // constant is non-numeric, object_ always points to a valid
3703 // constant HeapObject.
3704 Unique<Object> object_;
3706 // If object_ is a heap object, this points to the stable map of the object.
3707 Unique<Map> object_map_;
3709 // If object_ is a map, this indicates whether the map is stable.
3710 bool has_stable_map_value_ : 1;
3712 // We store the HConstant in the most specific form safely possible.
3713 // The two flags, has_int32_value_ and has_double_value_ tell us if
3714 // int32_value_ and double_value_ hold valid, safe representations
3715 // of the constant. has_int32_value_ implies has_double_value_ but
3716 // not the converse.
3717 bool has_smi_value_ : 1;
3718 bool has_int32_value_ : 1;
3719 bool has_double_value_ : 1;
3720 bool has_external_reference_value_ : 1;
3721 bool is_not_in_new_space_ : 1;
3722 bool boolean_value_ : 1;
3723 bool is_undetectable_: 1;
3724 int32_t int32_value_;
3725 double double_value_;
3726 ExternalReference external_reference_value_;
3728 static const InstanceType kUnknownInstanceType = FILLER_TYPE;
3729 InstanceType instance_type_;
3733 class HBinaryOperation : public HTemplateInstruction<3> {
3735 HBinaryOperation(HValue* context, HValue* left, HValue* right,
3736 HType type = HType::Tagged())
3737 : HTemplateInstruction<3>(type),
3738 observed_output_representation_(Representation::None()) {
3739 ASSERT(left != NULL && right != NULL);
3740 SetOperandAt(0, context);
3741 SetOperandAt(1, left);
3742 SetOperandAt(2, right);
3743 observed_input_representation_[0] = Representation::None();
3744 observed_input_representation_[1] = Representation::None();
3747 HValue* context() const { return OperandAt(0); }
3748 HValue* left() const { return OperandAt(1); }
3749 HValue* right() const { return OperandAt(2); }
3751 // True if switching left and right operands likely generates better code.
3752 bool AreOperandsBetterSwitched() {
3753 if (!IsCommutative()) return false;
3755 // Constant operands are better off on the right, they can be inlined in
3756 // many situations on most platforms.
3757 if (left()->IsConstant()) return true;
3758 if (right()->IsConstant()) return false;
3760 // Otherwise, if there is only one use of the right operand, it would be
3761 // better off on the left for platforms that only have 2-arg arithmetic
3762 // ops (e.g ia32, x64) that clobber the left operand.
3763 return right()->UseCount() == 1;
3766 HValue* BetterLeftOperand() {
3767 return AreOperandsBetterSwitched() ? right() : left();
3770 HValue* BetterRightOperand() {
3771 return AreOperandsBetterSwitched() ? left() : right();
3774 void set_observed_input_representation(int index, Representation rep) {
3775 ASSERT(index >= 1 && index <= 2);
3776 observed_input_representation_[index - 1] = rep;
3779 virtual void initialize_output_representation(Representation observed) {
3780 observed_output_representation_ = observed;
3783 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
3784 if (index == 0) return Representation::Tagged();
3785 return observed_input_representation_[index - 1];
3788 virtual void UpdateRepresentation(Representation new_rep,
3789 HInferRepresentationPhase* h_infer,
3790 const char* reason) V8_OVERRIDE {
3791 Representation rep = !FLAG_smi_binop && new_rep.IsSmi()
3792 ? Representation::Integer32() : new_rep;
3793 HValue::UpdateRepresentation(rep, h_infer, reason);
3796 virtual void InferRepresentation(
3797 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
3798 virtual Representation RepresentationFromInputs() V8_OVERRIDE;
3799 Representation RepresentationFromOutput();
3800 virtual void AssumeRepresentation(Representation r) V8_OVERRIDE;
3802 virtual bool IsCommutative() const { return false; }
3804 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3806 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3807 if (index == 0) return Representation::Tagged();
3808 return representation();
3811 void SetOperandPositions(Zone* zone,
3812 HSourcePosition left_pos,
3813 HSourcePosition right_pos) {
3814 set_operand_position(zone, 1, left_pos);
3815 set_operand_position(zone, 2, right_pos);
3818 bool RightIsPowerOf2() {
3819 if (!right()->IsInteger32Constant()) return false;
3820 int32_t value = right()->GetInteger32Constant();
3821 return IsPowerOf2(value) || IsPowerOf2(-value);
3824 DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
3827 bool IgnoreObservedOutputRepresentation(Representation current_rep);
3829 Representation observed_input_representation_[2];
3830 Representation observed_output_representation_;
3834 class HWrapReceiver V8_FINAL : public HTemplateInstruction<2> {
3836 DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
3838 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3840 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3841 return Representation::Tagged();
3844 HValue* receiver() { return OperandAt(0); }
3845 HValue* function() { return OperandAt(1); }
3847 virtual HValue* Canonicalize() V8_OVERRIDE;
3849 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3850 bool known_function() const { return known_function_; }
3852 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
3855 HWrapReceiver(HValue* receiver, HValue* function) {
3856 known_function_ = function->IsConstant() &&
3857 HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
3858 set_representation(Representation::Tagged());
3859 SetOperandAt(0, receiver);
3860 SetOperandAt(1, function);
3864 bool known_function_;
3868 class HApplyArguments V8_FINAL : public HTemplateInstruction<4> {
3870 DECLARE_INSTRUCTION_FACTORY_P4(HApplyArguments, HValue*, HValue*, HValue*,
3873 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3874 // The length is untagged, all other inputs are tagged.
3876 ? Representation::Integer32()
3877 : Representation::Tagged();
3880 HValue* function() { return OperandAt(0); }
3881 HValue* receiver() { return OperandAt(1); }
3882 HValue* length() { return OperandAt(2); }
3883 HValue* elements() { return OperandAt(3); }
3885 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
3888 HApplyArguments(HValue* function,
3892 set_representation(Representation::Tagged());
3893 SetOperandAt(0, function);
3894 SetOperandAt(1, receiver);
3895 SetOperandAt(2, length);
3896 SetOperandAt(3, elements);
3897 SetAllSideEffects();
3902 class HArgumentsElements V8_FINAL : public HTemplateInstruction<0> {
3904 DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
3906 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
3908 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3909 return Representation::None();
3912 bool from_inlined() const { return from_inlined_; }
3915 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3918 explicit HArgumentsElements(bool from_inlined) : from_inlined_(from_inlined) {
3919 // The value produced by this instruction is a pointer into the stack
3920 // that looks as if it was a smi because of alignment.
3921 set_representation(Representation::Tagged());
3925 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
3931 class HArgumentsLength V8_FINAL : public HUnaryOperation {
3933 DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue*);
3935 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3936 return Representation::Tagged();
3939 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
3942 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3945 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
3946 set_representation(Representation::Integer32());
3950 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
3954 class HAccessArgumentsAt V8_FINAL : public HTemplateInstruction<3> {
3956 DECLARE_INSTRUCTION_FACTORY_P3(HAccessArgumentsAt, HValue*, HValue*, HValue*);
3958 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3960 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3961 // The arguments elements is considered tagged.
3963 ? Representation::Tagged()
3964 : Representation::Integer32();
3967 HValue* arguments() { return OperandAt(0); }
3968 HValue* length() { return OperandAt(1); }
3969 HValue* index() { return OperandAt(2); }
3971 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
3974 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
3975 set_representation(Representation::Tagged());
3977 SetOperandAt(0, arguments);
3978 SetOperandAt(1, length);
3979 SetOperandAt(2, index);
3982 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3986 class HBoundsCheckBaseIndexInformation;
3989 class HBoundsCheck V8_FINAL : public HTemplateInstruction<2> {
3991 DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
3993 bool skip_check() const { return skip_check_; }
3994 void set_skip_check() { skip_check_ = true; }
3996 HValue* base() { return base_; }
3997 int offset() { return offset_; }
3998 int scale() { return scale_; }
4000 void ApplyIndexChange();
4001 bool DetectCompoundIndex() {
4002 ASSERT(base() == NULL);
4004 DecompositionResult decomposition;
4005 if (index()->TryDecompose(&decomposition)) {
4006 base_ = decomposition.base();
4007 offset_ = decomposition.offset();
4008 scale_ = decomposition.scale();
4018 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4019 return representation();
4022 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4023 virtual void InferRepresentation(
4024 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4026 HValue* index() { return OperandAt(0); }
4027 HValue* length() { return OperandAt(1); }
4028 bool allow_equality() { return allow_equality_; }
4029 void set_allow_equality(bool v) { allow_equality_ = v; }
4031 virtual int RedefinedOperandIndex() V8_OVERRIDE { return 0; }
4032 virtual bool IsPurelyInformativeDefinition() V8_OVERRIDE {
4033 return skip_check();
4036 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
4039 friend class HBoundsCheckBaseIndexInformation;
4041 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4043 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4048 bool allow_equality_;
4051 // Normally HBoundsCheck should be created using the
4052 // HGraphBuilder::AddBoundsCheck() helper.
4053 // However when building stubs, where we know that the arguments are Int32,
4054 // it makes sense to invoke this constructor directly.
4055 HBoundsCheck(HValue* index, HValue* length)
4056 : skip_check_(false),
4057 base_(NULL), offset_(0), scale_(0),
4058 allow_equality_(false) {
4059 SetOperandAt(0, index);
4060 SetOperandAt(1, length);
4061 SetFlag(kFlexibleRepresentation);
4065 virtual bool IsDeletable() const V8_OVERRIDE {
4066 return skip_check() && !FLAG_debug_code;
4071 class HBoundsCheckBaseIndexInformation V8_FINAL
4072 : public HTemplateInstruction<2> {
4074 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) {
4075 DecompositionResult decomposition;
4076 if (check->index()->TryDecompose(&decomposition)) {
4077 SetOperandAt(0, decomposition.base());
4078 SetOperandAt(1, check);
4084 HValue* base_index() { return OperandAt(0); }
4085 HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); }
4087 DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation)
4089 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4090 return representation();
4093 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4095 virtual int RedefinedOperandIndex() V8_OVERRIDE { return 0; }
4096 virtual bool IsPurelyInformativeDefinition() V8_OVERRIDE { return true; }
4100 class HBitwiseBinaryOperation : public HBinaryOperation {
4102 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
4103 HType type = HType::TaggedNumber())
4104 : HBinaryOperation(context, left, right, type) {
4105 SetFlag(kFlexibleRepresentation);
4106 SetFlag(kTruncatingToInt32);
4107 SetFlag(kAllowUndefinedAsNaN);
4108 SetAllSideEffects();
4111 virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
4112 if (to.IsTagged() &&
4113 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
4114 SetAllSideEffects();
4117 ClearAllSideEffects();
4120 if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
4123 virtual void UpdateRepresentation(Representation new_rep,
4124 HInferRepresentationPhase* h_infer,
4125 const char* reason) V8_OVERRIDE {
4126 // We only generate either int32 or generic tagged bitwise operations.
4127 if (new_rep.IsDouble()) new_rep = Representation::Integer32();
4128 HBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4131 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4132 Representation r = HBinaryOperation::observed_input_representation(index);
4133 if (r.IsDouble()) return Representation::Integer32();
4137 virtual void initialize_output_representation(Representation observed) {
4138 if (observed.IsDouble()) observed = Representation::Integer32();
4139 HBinaryOperation::initialize_output_representation(observed);
4142 DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
4145 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4149 class HMathFloorOfDiv V8_FINAL : public HBinaryOperation {
4151 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HMathFloorOfDiv,
4155 DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
4158 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4161 HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
4162 : HBinaryOperation(context, left, right) {
4163 set_representation(Representation::Integer32());
4165 SetFlag(kCanOverflow);
4166 SetFlag(kCanBeDivByZero);
4167 SetFlag(kLeftCanBeMinInt);
4168 SetFlag(kLeftCanBeNegative);
4169 SetFlag(kLeftCanBePositive);
4170 SetFlag(kAllowUndefinedAsNaN);
4173 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4175 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4179 class HArithmeticBinaryOperation : public HBinaryOperation {
4181 HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right)
4182 : HBinaryOperation(context, left, right, HType::TaggedNumber()) {
4183 SetAllSideEffects();
4184 SetFlag(kFlexibleRepresentation);
4185 SetFlag(kAllowUndefinedAsNaN);
4188 virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
4189 if (to.IsTagged() &&
4190 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
4191 SetAllSideEffects();
4194 ClearAllSideEffects();
4197 if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
4200 DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
4203 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4207 class HCompareGeneric V8_FINAL : public HBinaryOperation {
4209 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCompareGeneric, HValue*,
4210 HValue*, Token::Value);
4212 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4214 ? Representation::Tagged()
4218 Token::Value token() const { return token_; }
4219 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4221 DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
4224 HCompareGeneric(HValue* context,
4228 : HBinaryOperation(context, left, right, HType::Boolean()),
4230 ASSERT(Token::IsCompareOp(token));
4231 set_representation(Representation::Tagged());
4232 SetAllSideEffects();
4235 Token::Value token_;
4239 class HCompareNumericAndBranch : public HTemplateControlInstruction<2, 2> {
4241 DECLARE_INSTRUCTION_FACTORY_P3(HCompareNumericAndBranch,
4242 HValue*, HValue*, Token::Value);
4243 DECLARE_INSTRUCTION_FACTORY_P5(HCompareNumericAndBranch,
4244 HValue*, HValue*, Token::Value,
4245 HBasicBlock*, HBasicBlock*);
4247 HValue* left() { return OperandAt(0); }
4248 HValue* right() { return OperandAt(1); }
4249 Token::Value token() const { return token_; }
4251 void set_observed_input_representation(Representation left,
4252 Representation right) {
4253 observed_input_representation_[0] = left;
4254 observed_input_representation_[1] = right;
4257 virtual void InferRepresentation(
4258 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4260 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4261 return representation();
4263 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4264 return observed_input_representation_[index];
4267 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4269 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4271 void SetOperandPositions(Zone* zone,
4272 HSourcePosition left_pos,
4273 HSourcePosition right_pos) {
4274 set_operand_position(zone, 0, left_pos);
4275 set_operand_position(zone, 1, right_pos);
4278 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
4281 HCompareNumericAndBranch(HValue* left,
4284 HBasicBlock* true_target = NULL,
4285 HBasicBlock* false_target = NULL)
4287 SetFlag(kFlexibleRepresentation);
4288 ASSERT(Token::IsCompareOp(token));
4289 SetOperandAt(0, left);
4290 SetOperandAt(1, right);
4291 SetSuccessorAt(0, true_target);
4292 SetSuccessorAt(1, false_target);
4295 Representation observed_input_representation_[2];
4296 Token::Value token_;
4300 class HCompareHoleAndBranch V8_FINAL : public HUnaryControlInstruction {
4302 DECLARE_INSTRUCTION_FACTORY_P1(HCompareHoleAndBranch, HValue*);
4303 DECLARE_INSTRUCTION_FACTORY_P3(HCompareHoleAndBranch, HValue*,
4304 HBasicBlock*, HBasicBlock*);
4306 virtual void InferRepresentation(
4307 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4309 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4310 return representation();
4313 DECLARE_CONCRETE_INSTRUCTION(CompareHoleAndBranch)
4316 HCompareHoleAndBranch(HValue* value,
4317 HBasicBlock* true_target = NULL,
4318 HBasicBlock* false_target = NULL)
4319 : HUnaryControlInstruction(value, true_target, false_target) {
4320 SetFlag(kFlexibleRepresentation);
4321 SetFlag(kAllowUndefinedAsNaN);
4326 class HCompareMinusZeroAndBranch V8_FINAL : public HUnaryControlInstruction {
4328 DECLARE_INSTRUCTION_FACTORY_P1(HCompareMinusZeroAndBranch, HValue*);
4330 virtual void InferRepresentation(
4331 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4333 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4334 return representation();
4337 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4339 DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch)
4342 explicit HCompareMinusZeroAndBranch(HValue* value)
4343 : HUnaryControlInstruction(value, NULL, NULL) {
4348 class HCompareObjectEqAndBranch : public HTemplateControlInstruction<2, 2> {
4350 DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue*, HValue*);
4351 DECLARE_INSTRUCTION_FACTORY_P4(HCompareObjectEqAndBranch, HValue*, HValue*,
4352 HBasicBlock*, HBasicBlock*);
4354 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4356 static const int kNoKnownSuccessorIndex = -1;
4357 int known_successor_index() const { return known_successor_index_; }
4358 void set_known_successor_index(int known_successor_index) {
4359 known_successor_index_ = known_successor_index;
4362 HValue* left() { return OperandAt(0); }
4363 HValue* right() { return OperandAt(1); }
4365 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4367 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4368 return Representation::Tagged();
4371 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4372 return Representation::Tagged();
4375 DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
4378 HCompareObjectEqAndBranch(HValue* left,
4380 HBasicBlock* true_target = NULL,
4381 HBasicBlock* false_target = NULL)
4382 : known_successor_index_(kNoKnownSuccessorIndex) {
4383 ASSERT(!left->IsConstant() ||
4384 (!HConstant::cast(left)->HasInteger32Value() ||
4385 HConstant::cast(left)->HasSmiValue()));
4386 ASSERT(!right->IsConstant() ||
4387 (!HConstant::cast(right)->HasInteger32Value() ||
4388 HConstant::cast(right)->HasSmiValue()));
4389 SetOperandAt(0, left);
4390 SetOperandAt(1, right);
4391 SetSuccessorAt(0, true_target);
4392 SetSuccessorAt(1, false_target);
4395 int known_successor_index_;
4399 class HIsObjectAndBranch V8_FINAL : public HUnaryControlInstruction {
4401 DECLARE_INSTRUCTION_FACTORY_P1(HIsObjectAndBranch, HValue*);
4402 DECLARE_INSTRUCTION_FACTORY_P3(HIsObjectAndBranch, HValue*,
4403 HBasicBlock*, HBasicBlock*);
4405 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4406 return Representation::Tagged();
4409 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4411 DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch)
4414 HIsObjectAndBranch(HValue* value,
4415 HBasicBlock* true_target = NULL,
4416 HBasicBlock* false_target = NULL)
4417 : HUnaryControlInstruction(value, true_target, false_target) {}
4421 class HIsStringAndBranch V8_FINAL : public HUnaryControlInstruction {
4423 DECLARE_INSTRUCTION_FACTORY_P1(HIsStringAndBranch, HValue*);
4424 DECLARE_INSTRUCTION_FACTORY_P3(HIsStringAndBranch, HValue*,
4425 HBasicBlock*, HBasicBlock*);
4427 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4428 return Representation::Tagged();
4431 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4433 static const int kNoKnownSuccessorIndex = -1;
4434 int known_successor_index() const { return known_successor_index_; }
4435 void set_known_successor_index(int known_successor_index) {
4436 known_successor_index_ = known_successor_index;
4439 DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
4442 virtual int RedefinedOperandIndex() { return 0; }
4445 HIsStringAndBranch(HValue* value,
4446 HBasicBlock* true_target = NULL,
4447 HBasicBlock* false_target = NULL)
4448 : HUnaryControlInstruction(value, true_target, false_target),
4449 known_successor_index_(kNoKnownSuccessorIndex) { }
4451 int known_successor_index_;
4455 class HIsSmiAndBranch V8_FINAL : public HUnaryControlInstruction {
4457 DECLARE_INSTRUCTION_FACTORY_P1(HIsSmiAndBranch, HValue*);
4458 DECLARE_INSTRUCTION_FACTORY_P3(HIsSmiAndBranch, HValue*,
4459 HBasicBlock*, HBasicBlock*);
4461 DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
4463 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4464 return Representation::Tagged();
4468 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4469 virtual int RedefinedOperandIndex() { return 0; }
4472 HIsSmiAndBranch(HValue* value,
4473 HBasicBlock* true_target = NULL,
4474 HBasicBlock* false_target = NULL)
4475 : HUnaryControlInstruction(value, true_target, false_target) {
4476 set_representation(Representation::Tagged());
4481 class HIsUndetectableAndBranch V8_FINAL : public HUnaryControlInstruction {
4483 DECLARE_INSTRUCTION_FACTORY_P1(HIsUndetectableAndBranch, HValue*);
4484 DECLARE_INSTRUCTION_FACTORY_P3(HIsUndetectableAndBranch, HValue*,
4485 HBasicBlock*, HBasicBlock*);
4487 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4488 return Representation::Tagged();
4491 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4493 DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
4496 HIsUndetectableAndBranch(HValue* value,
4497 HBasicBlock* true_target = NULL,
4498 HBasicBlock* false_target = NULL)
4499 : HUnaryControlInstruction(value, true_target, false_target) {}
4503 class HStringCompareAndBranch : public HTemplateControlInstruction<2, 3> {
4505 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HStringCompareAndBranch,
4510 HValue* context() { return OperandAt(0); }
4511 HValue* left() { return OperandAt(1); }
4512 HValue* right() { return OperandAt(2); }
4513 Token::Value token() const { return token_; }
4515 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4517 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4518 return Representation::Tagged();
4521 Representation GetInputRepresentation() const {
4522 return Representation::Tagged();
4525 DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
4528 HStringCompareAndBranch(HValue* context,
4533 ASSERT(Token::IsCompareOp(token));
4534 SetOperandAt(0, context);
4535 SetOperandAt(1, left);
4536 SetOperandAt(2, right);
4537 set_representation(Representation::Tagged());
4538 SetChangesFlag(kNewSpacePromotion);
4541 Token::Value token_;
4545 class HIsConstructCallAndBranch : public HTemplateControlInstruction<2, 0> {
4547 DECLARE_INSTRUCTION_FACTORY_P0(HIsConstructCallAndBranch);
4549 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4550 return Representation::None();
4553 DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch)
4555 HIsConstructCallAndBranch() {}
4559 class HHasInstanceTypeAndBranch V8_FINAL : public HUnaryControlInstruction {
4561 DECLARE_INSTRUCTION_FACTORY_P2(
4562 HHasInstanceTypeAndBranch, HValue*, InstanceType);
4563 DECLARE_INSTRUCTION_FACTORY_P3(
4564 HHasInstanceTypeAndBranch, HValue*, InstanceType, InstanceType);
4566 InstanceType from() { return from_; }
4567 InstanceType to() { return to_; }
4569 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4571 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4572 return Representation::Tagged();
4575 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4577 DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
4580 HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
4581 : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
4582 HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
4583 : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
4584 ASSERT(to == LAST_TYPE); // Others not implemented yet in backend.
4588 InstanceType to_; // Inclusive range, not all combinations work.
4592 class HHasCachedArrayIndexAndBranch V8_FINAL : public HUnaryControlInstruction {
4594 DECLARE_INSTRUCTION_FACTORY_P1(HHasCachedArrayIndexAndBranch, HValue*);
4596 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4597 return Representation::Tagged();
4600 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
4602 explicit HHasCachedArrayIndexAndBranch(HValue* value)
4603 : HUnaryControlInstruction(value, NULL, NULL) { }
4607 class HGetCachedArrayIndex V8_FINAL : public HUnaryOperation {
4609 DECLARE_INSTRUCTION_FACTORY_P1(HGetCachedArrayIndex, HValue*);
4611 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4612 return Representation::Tagged();
4615 DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
4618 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4621 explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
4622 set_representation(Representation::Tagged());
4626 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4630 class HClassOfTestAndBranch V8_FINAL : public HUnaryControlInstruction {
4632 DECLARE_INSTRUCTION_FACTORY_P2(HClassOfTestAndBranch, HValue*,
4635 DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
4637 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4638 return Representation::Tagged();
4641 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4643 Handle<String> class_name() const { return class_name_; }
4646 HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
4647 : HUnaryControlInstruction(value, NULL, NULL),
4648 class_name_(class_name) { }
4650 Handle<String> class_name_;
4654 class HTypeofIsAndBranch V8_FINAL : public HUnaryControlInstruction {
4656 DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle<String>);
4658 Handle<String> type_literal() { return type_literal_.handle(); }
4659 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4661 DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
4663 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4664 return Representation::None();
4667 virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4669 virtual void FinalizeUniqueness() V8_OVERRIDE {
4670 type_literal_ = Unique<String>(type_literal_.handle());
4674 HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
4675 : HUnaryControlInstruction(value, NULL, NULL),
4676 type_literal_(Unique<String>::CreateUninitialized(type_literal)) { }
4678 Unique<String> type_literal_;
4682 class HInstanceOf V8_FINAL : public HBinaryOperation {
4684 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOf, HValue*, HValue*);
4686 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4687 return Representation::Tagged();
4690 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4692 DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
4695 HInstanceOf(HValue* context, HValue* left, HValue* right)
4696 : HBinaryOperation(context, left, right, HType::Boolean()) {
4697 set_representation(Representation::Tagged());
4698 SetAllSideEffects();
4703 class HInstanceOfKnownGlobal V8_FINAL : public HTemplateInstruction<2> {
4705 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOfKnownGlobal,
4707 Handle<JSFunction>);
4709 HValue* context() { return OperandAt(0); }
4710 HValue* left() { return OperandAt(1); }
4711 Handle<JSFunction> function() { return function_; }
4713 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4714 return Representation::Tagged();
4717 DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal)
4720 HInstanceOfKnownGlobal(HValue* context,
4722 Handle<JSFunction> right)
4723 : HTemplateInstruction<2>(HType::Boolean()), function_(right) {
4724 SetOperandAt(0, context);
4725 SetOperandAt(1, left);
4726 set_representation(Representation::Tagged());
4727 SetAllSideEffects();
4730 Handle<JSFunction> function_;
4734 class HPower V8_FINAL : public HTemplateInstruction<2> {
4736 static HInstruction* New(Zone* zone,
4741 HValue* left() { return OperandAt(0); }
4742 HValue* right() const { return OperandAt(1); }
4744 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4746 ? Representation::Double()
4747 : Representation::None();
4749 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4750 return RequiredInputRepresentation(index);
4753 DECLARE_CONCRETE_INSTRUCTION(Power)
4756 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4759 HPower(HValue* left, HValue* right) {
4760 SetOperandAt(0, left);
4761 SetOperandAt(1, right);
4762 set_representation(Representation::Double());
4764 SetChangesFlag(kNewSpacePromotion);
4767 virtual bool IsDeletable() const V8_OVERRIDE {
4768 return !right()->representation().IsTagged();
4773 class HAdd V8_FINAL : public HArithmeticBinaryOperation {
4775 static HInstruction* New(Zone* zone,
4780 // Add is only commutative if two integer values are added and not if two
4781 // tagged values are added (because it might be a String concatenation).
4782 // We also do not commute (pointer + offset).
4783 virtual bool IsCommutative() const V8_OVERRIDE {
4784 return !representation().IsTagged() && !representation().IsExternal();
4787 virtual HValue* Canonicalize() V8_OVERRIDE;
4789 virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
4790 if (left()->IsInteger32Constant()) {
4791 decomposition->Apply(right(), left()->GetInteger32Constant());
4793 } else if (right()->IsInteger32Constant()) {
4794 decomposition->Apply(left(), right()->GetInteger32Constant());
4801 virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
4802 if (to.IsTagged() &&
4803 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() ||
4804 left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) {
4805 SetAllSideEffects();
4808 ClearAllSideEffects();
4811 if (to.IsTagged()) {
4812 SetChangesFlag(kNewSpacePromotion);
4813 ClearFlag(kAllowUndefinedAsNaN);
4817 virtual Representation RepresentationFromInputs() V8_OVERRIDE;
4819 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE;
4821 DECLARE_CONCRETE_INSTRUCTION(Add)
4824 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4826 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4829 HAdd(HValue* context, HValue* left, HValue* right)
4830 : HArithmeticBinaryOperation(context, left, right) {
4831 SetFlag(kCanOverflow);
4836 class HSub V8_FINAL : public HArithmeticBinaryOperation {
4838 static HInstruction* New(Zone* zone,
4843 virtual HValue* Canonicalize() V8_OVERRIDE;
4845 virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
4846 if (right()->IsInteger32Constant()) {
4847 decomposition->Apply(left(), -right()->GetInteger32Constant());
4854 DECLARE_CONCRETE_INSTRUCTION(Sub)
4857 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4859 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4862 HSub(HValue* context, HValue* left, HValue* right)
4863 : HArithmeticBinaryOperation(context, left, right) {
4864 SetFlag(kCanOverflow);
4869 class HMul V8_FINAL : public HArithmeticBinaryOperation {
4871 static HInstruction* New(Zone* zone,
4876 static HInstruction* NewImul(Zone* zone,
4880 HInstruction* instr = HMul::New(zone, context, left, right);
4881 if (!instr->IsMul()) return instr;
4882 HMul* mul = HMul::cast(instr);
4883 // TODO(mstarzinger): Prevent bailout on minus zero for imul.
4884 mul->AssumeRepresentation(Representation::Integer32());
4885 mul->ClearFlag(HValue::kCanOverflow);
4889 virtual HValue* Canonicalize() V8_OVERRIDE;
4891 // Only commutative if it is certain that not two objects are multiplicated.
4892 virtual bool IsCommutative() const V8_OVERRIDE {
4893 return !representation().IsTagged();
4896 virtual void UpdateRepresentation(Representation new_rep,
4897 HInferRepresentationPhase* h_infer,
4898 const char* reason) V8_OVERRIDE {
4899 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4904 DECLARE_CONCRETE_INSTRUCTION(Mul)
4907 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4909 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4912 HMul(HValue* context, HValue* left, HValue* right)
4913 : HArithmeticBinaryOperation(context, left, right) {
4914 SetFlag(kCanOverflow);
4919 class HMod V8_FINAL : public HArithmeticBinaryOperation {
4921 static HInstruction* New(Zone* zone,
4926 virtual HValue* Canonicalize() V8_OVERRIDE;
4928 virtual void UpdateRepresentation(Representation new_rep,
4929 HInferRepresentationPhase* h_infer,
4930 const char* reason) V8_OVERRIDE {
4931 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4932 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4935 DECLARE_CONCRETE_INSTRUCTION(Mod)
4938 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4940 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4943 HMod(HValue* context,
4945 HValue* right) : HArithmeticBinaryOperation(context, left, right) {
4946 SetFlag(kCanBeDivByZero);
4947 SetFlag(kCanOverflow);
4948 SetFlag(kLeftCanBeNegative);
4953 class HDiv V8_FINAL : public HArithmeticBinaryOperation {
4955 static HInstruction* New(Zone* zone,
4960 virtual HValue* Canonicalize() V8_OVERRIDE;
4962 virtual void UpdateRepresentation(Representation new_rep,
4963 HInferRepresentationPhase* h_infer,
4964 const char* reason) V8_OVERRIDE {
4965 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4966 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4969 DECLARE_CONCRETE_INSTRUCTION(Div)
4972 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4974 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4977 HDiv(HValue* context, HValue* left, HValue* right)
4978 : HArithmeticBinaryOperation(context, left, right) {
4979 SetFlag(kCanBeDivByZero);
4980 SetFlag(kCanOverflow);
4985 class HMathMinMax V8_FINAL : public HArithmeticBinaryOperation {
4987 enum Operation { kMathMin, kMathMax };
4989 static HInstruction* New(Zone* zone,
4995 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4996 return RequiredInputRepresentation(index);
4999 virtual void InferRepresentation(
5000 HInferRepresentationPhase* h_infer) V8_OVERRIDE;
5002 virtual Representation RepresentationFromInputs() V8_OVERRIDE {
5003 Representation left_rep = left()->representation();
5004 Representation right_rep = right()->representation();
5005 Representation result = Representation::Smi();
5006 result = result.generalize(left_rep);
5007 result = result.generalize(right_rep);
5008 if (result.IsTagged()) return Representation::Double();
5012 virtual bool IsCommutative() const V8_OVERRIDE { return true; }
5014 Operation operation() { return operation_; }
5016 DECLARE_CONCRETE_INSTRUCTION(MathMinMax)
5019 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
5020 return other->IsMathMinMax() &&
5021 HMathMinMax::cast(other)->operation_ == operation_;
5024 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5027 HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
5028 : HArithmeticBinaryOperation(context, left, right),
5031 Operation operation_;
5035 class HBitwise V8_FINAL : public HBitwiseBinaryOperation {
5037 static HInstruction* New(Zone* zone,
5043 Token::Value op() const { return op_; }
5045 virtual bool IsCommutative() const V8_OVERRIDE { return true; }
5047 virtual HValue* Canonicalize() V8_OVERRIDE;
5049 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5051 DECLARE_CONCRETE_INSTRUCTION(Bitwise)
5054 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
5055 return op() == HBitwise::cast(other)->op();
5058 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5061 HBitwise(HValue* context,
5065 : HBitwiseBinaryOperation(context, left, right),
5067 ASSERT(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
5068 // BIT_AND with a smi-range positive value will always unset the
5069 // entire sign-extension of the smi-sign.
5070 if (op == Token::BIT_AND &&
5071 ((left->IsConstant() &&
5072 left->representation().IsSmi() &&
5073 HConstant::cast(left)->Integer32Value() >= 0) ||
5074 (right->IsConstant() &&
5075 right->representation().IsSmi() &&
5076 HConstant::cast(right)->Integer32Value() >= 0))) {
5077 SetFlag(kTruncatingToSmi);
5078 SetFlag(kTruncatingToInt32);
5079 // BIT_OR with a smi-range negative value will always set the entire
5080 // sign-extension of the smi-sign.
5081 } else if (op == Token::BIT_OR &&
5082 ((left->IsConstant() &&
5083 left->representation().IsSmi() &&
5084 HConstant::cast(left)->Integer32Value() < 0) ||
5085 (right->IsConstant() &&
5086 right->representation().IsSmi() &&
5087 HConstant::cast(right)->Integer32Value() < 0))) {
5088 SetFlag(kTruncatingToSmi);
5089 SetFlag(kTruncatingToInt32);
5097 class HShl V8_FINAL : public HBitwiseBinaryOperation {
5099 static HInstruction* New(Zone* zone,
5104 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5106 virtual void UpdateRepresentation(Representation new_rep,
5107 HInferRepresentationPhase* h_infer,
5108 const char* reason) V8_OVERRIDE {
5109 if (new_rep.IsSmi() &&
5110 !(right()->IsInteger32Constant() &&
5111 right()->GetInteger32Constant() >= 0)) {
5112 new_rep = Representation::Integer32();
5114 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5117 DECLARE_CONCRETE_INSTRUCTION(Shl)
5120 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5123 HShl(HValue* context, HValue* left, HValue* right)
5124 : HBitwiseBinaryOperation(context, left, right) { }
5128 class HShr V8_FINAL : public HBitwiseBinaryOperation {
5130 static HInstruction* New(Zone* zone,
5135 virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
5136 if (right()->IsInteger32Constant()) {
5137 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
5138 // This is intended to look for HAdd and HSub, to handle compounds
5139 // like ((base + offset) >> scale) with one single decomposition.
5140 left()->TryDecompose(decomposition);
5147 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5149 virtual void UpdateRepresentation(Representation new_rep,
5150 HInferRepresentationPhase* h_infer,
5151 const char* reason) V8_OVERRIDE {
5152 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5153 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5156 DECLARE_CONCRETE_INSTRUCTION(Shr)
5159 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5162 HShr(HValue* context, HValue* left, HValue* right)
5163 : HBitwiseBinaryOperation(context, left, right) { }
5167 class HSar V8_FINAL : public HBitwiseBinaryOperation {
5169 static HInstruction* New(Zone* zone,
5174 virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
5175 if (right()->IsInteger32Constant()) {
5176 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
5177 // This is intended to look for HAdd and HSub, to handle compounds
5178 // like ((base + offset) >> scale) with one single decomposition.
5179 left()->TryDecompose(decomposition);
5186 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5188 virtual void UpdateRepresentation(Representation new_rep,
5189 HInferRepresentationPhase* h_infer,
5190 const char* reason) V8_OVERRIDE {
5191 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5192 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5195 DECLARE_CONCRETE_INSTRUCTION(Sar)
5198 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5201 HSar(HValue* context, HValue* left, HValue* right)
5202 : HBitwiseBinaryOperation(context, left, right) { }
5206 class HRor V8_FINAL : public HBitwiseBinaryOperation {
5208 static HInstruction* New(Zone* zone,
5212 return new(zone) HRor(context, left, right);
5215 virtual void UpdateRepresentation(Representation new_rep,
5216 HInferRepresentationPhase* h_infer,
5217 const char* reason) V8_OVERRIDE {
5218 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5219 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5222 DECLARE_CONCRETE_INSTRUCTION(Ror)
5225 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5228 HRor(HValue* context, HValue* left, HValue* right)
5229 : HBitwiseBinaryOperation(context, left, right) {
5230 ChangeRepresentation(Representation::Integer32());
5235 class HOsrEntry V8_FINAL : public HTemplateInstruction<0> {
5237 DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId);
5239 BailoutId ast_id() const { return ast_id_; }
5241 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5242 return Representation::None();
5245 DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
5248 explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
5249 SetChangesFlag(kOsrEntries);
5250 SetChangesFlag(kNewSpacePromotion);
5257 class HParameter V8_FINAL : public HTemplateInstruction<0> {
5259 enum ParameterKind {
5264 DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned);
5265 DECLARE_INSTRUCTION_FACTORY_P2(HParameter, unsigned, ParameterKind);
5266 DECLARE_INSTRUCTION_FACTORY_P3(HParameter, unsigned, ParameterKind,
5269 unsigned index() const { return index_; }
5270 ParameterKind kind() const { return kind_; }
5272 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5274 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5275 return Representation::None();
5278 DECLARE_CONCRETE_INSTRUCTION(Parameter)
5281 explicit HParameter(unsigned index,
5282 ParameterKind kind = STACK_PARAMETER)
5285 set_representation(Representation::Tagged());
5288 explicit HParameter(unsigned index,
5293 set_representation(r);
5297 ParameterKind kind_;
5301 class HCallStub V8_FINAL : public HUnaryCall {
5303 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallStub, CodeStub::Major, int);
5304 CodeStub::Major major_key() { return major_key_; }
5306 HValue* context() { return value(); }
5308 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5310 DECLARE_CONCRETE_INSTRUCTION(CallStub)
5313 HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
5314 : HUnaryCall(context, argument_count),
5315 major_key_(major_key) {
5318 CodeStub::Major major_key_;
5322 class HUnknownOSRValue V8_FINAL : public HTemplateInstruction<0> {
5324 DECLARE_INSTRUCTION_FACTORY_P2(HUnknownOSRValue, HEnvironment*, int);
5326 virtual void PrintDataTo(StringStream* stream);
5328 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5329 return Representation::None();
5332 void set_incoming_value(HPhi* value) { incoming_value_ = value; }
5333 HPhi* incoming_value() { return incoming_value_; }
5334 HEnvironment *environment() { return environment_; }
5335 int index() { return index_; }
5337 virtual Representation KnownOptimalRepresentation() V8_OVERRIDE {
5338 if (incoming_value_ == NULL) return Representation::None();
5339 return incoming_value_->KnownOptimalRepresentation();
5342 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
5345 HUnknownOSRValue(HEnvironment* environment, int index)
5346 : environment_(environment),
5348 incoming_value_(NULL) {
5349 set_representation(Representation::Tagged());
5352 HEnvironment* environment_;
5354 HPhi* incoming_value_;
5358 class HLoadGlobalCell V8_FINAL : public HTemplateInstruction<0> {
5360 DECLARE_INSTRUCTION_FACTORY_P2(HLoadGlobalCell, Handle<Cell>,
5363 Unique<Cell> cell() const { return cell_; }
5364 bool RequiresHoleCheck() const;
5366 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5368 virtual intptr_t Hashcode() V8_OVERRIDE {
5369 return cell_.Hashcode();
5372 virtual void FinalizeUniqueness() V8_OVERRIDE {
5373 cell_ = Unique<Cell>(cell_.handle());
5376 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5377 return Representation::None();
5380 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell)
5383 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
5384 return cell_ == HLoadGlobalCell::cast(other)->cell_;
5388 HLoadGlobalCell(Handle<Cell> cell, PropertyDetails details)
5389 : cell_(Unique<Cell>::CreateUninitialized(cell)), details_(details) {
5390 set_representation(Representation::Tagged());
5392 SetDependsOnFlag(kGlobalVars);
5395 virtual bool IsDeletable() const V8_OVERRIDE { return !RequiresHoleCheck(); }
5398 PropertyDetails details_;
5402 class HLoadGlobalGeneric V8_FINAL : public HTemplateInstruction<2> {
5404 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadGlobalGeneric, HValue*,
5405 Handle<Object>, bool);
5407 HValue* context() { return OperandAt(0); }
5408 HValue* global_object() { return OperandAt(1); }
5409 Handle<Object> name() const { return name_; }
5410 bool for_typeof() const { return for_typeof_; }
5412 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5414 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5415 return Representation::Tagged();
5418 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
5421 HLoadGlobalGeneric(HValue* context,
5422 HValue* global_object,
5423 Handle<Object> name,
5426 for_typeof_(for_typeof) {
5427 SetOperandAt(0, context);
5428 SetOperandAt(1, global_object);
5429 set_representation(Representation::Tagged());
5430 SetAllSideEffects();
5433 Handle<Object> name_;
5438 class HAllocate V8_FINAL : public HTemplateInstruction<2> {
5440 static bool CompatibleInstanceTypes(InstanceType type1,
5441 InstanceType type2) {
5442 return ComputeFlags(TENURED, type1) == ComputeFlags(TENURED, type2) &&
5443 ComputeFlags(NOT_TENURED, type1) == ComputeFlags(NOT_TENURED, type2);
5446 static HAllocate* New(Zone* zone,
5450 PretenureFlag pretenure_flag,
5451 InstanceType instance_type,
5452 Handle<AllocationSite> allocation_site =
5453 Handle<AllocationSite>::null()) {
5454 return new(zone) HAllocate(context, size, type, pretenure_flag,
5455 instance_type, allocation_site);
5458 // Maximum instance size for which allocations will be inlined.
5459 static const int kMaxInlineSize = 64 * kPointerSize;
5461 HValue* context() { return OperandAt(0); }
5462 HValue* size() { return OperandAt(1); }
5464 bool has_size_upper_bound() { return size_upper_bound_ != NULL; }
5465 HConstant* size_upper_bound() { return size_upper_bound_; }
5466 void set_size_upper_bound(HConstant* value) {
5467 ASSERT(size_upper_bound_ == NULL);
5468 size_upper_bound_ = value;
5471 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5473 return Representation::Tagged();
5475 return Representation::Integer32();
5479 virtual Handle<Map> GetMonomorphicJSObjectMap() {
5480 return known_initial_map_;
5483 void set_known_initial_map(Handle<Map> known_initial_map) {
5484 known_initial_map_ = known_initial_map;
5487 bool IsNewSpaceAllocation() const {
5488 return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
5491 bool IsOldDataSpaceAllocation() const {
5492 return (flags_ & ALLOCATE_IN_OLD_DATA_SPACE) != 0;
5495 bool IsOldPointerSpaceAllocation() const {
5496 return (flags_ & ALLOCATE_IN_OLD_POINTER_SPACE) != 0;
5499 bool MustAllocateDoubleAligned() const {
5500 return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
5503 bool MustPrefillWithFiller() const {
5504 return (flags_ & PREFILL_WITH_FILLER) != 0;
5507 void MakePrefillWithFiller() {
5508 flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
5511 bool MustClearNextMapWord() const {
5512 return (flags_ & CLEAR_NEXT_MAP_WORD) != 0;
5515 void MakeDoubleAligned() {
5516 flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
5519 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
5520 HValue* dominator) V8_OVERRIDE;
5522 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5524 DECLARE_CONCRETE_INSTRUCTION(Allocate)
5528 ALLOCATE_IN_NEW_SPACE = 1 << 0,
5529 ALLOCATE_IN_OLD_DATA_SPACE = 1 << 1,
5530 ALLOCATE_IN_OLD_POINTER_SPACE = 1 << 2,
5531 ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
5532 PREFILL_WITH_FILLER = 1 << 4,
5533 CLEAR_NEXT_MAP_WORD = 1 << 5
5536 HAllocate(HValue* context,
5539 PretenureFlag pretenure_flag,
5540 InstanceType instance_type,
5541 Handle<AllocationSite> allocation_site =
5542 Handle<AllocationSite>::null())
5543 : HTemplateInstruction<2>(type),
5544 flags_(ComputeFlags(pretenure_flag, instance_type)),
5545 dominating_allocate_(NULL),
5546 filler_free_space_size_(NULL),
5547 size_upper_bound_(NULL) {
5548 SetOperandAt(0, context);
5550 set_representation(Representation::Tagged());
5551 SetFlag(kTrackSideEffectDominators);
5552 SetChangesFlag(kNewSpacePromotion);
5553 SetDependsOnFlag(kNewSpacePromotion);
5555 if (FLAG_trace_pretenuring) {
5556 PrintF("HAllocate with AllocationSite %p %s\n",
5557 allocation_site.is_null()
5558 ? static_cast<void*>(NULL)
5559 : static_cast<void*>(*allocation_site),
5560 pretenure_flag == TENURED ? "tenured" : "not tenured");
5564 static Flags ComputeFlags(PretenureFlag pretenure_flag,
5565 InstanceType instance_type) {
5566 Flags flags = pretenure_flag == TENURED
5567 ? (Heap::TargetSpaceId(instance_type) == OLD_POINTER_SPACE
5568 ? ALLOCATE_IN_OLD_POINTER_SPACE : ALLOCATE_IN_OLD_DATA_SPACE)
5569 : ALLOCATE_IN_NEW_SPACE;
5570 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
5571 flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED);
5573 // We have to fill the allocated object with one word fillers if we do
5574 // not use allocation folding since some allocations may depend on each
5575 // other, i.e., have a pointer to each other. A GC in between these
5576 // allocations may leave such objects behind in a not completely initialized
5578 if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
5579 flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER);
5581 if (pretenure_flag == NOT_TENURED &&
5582 AllocationSite::CanTrack(instance_type)) {
5583 flags = static_cast<Flags>(flags | CLEAR_NEXT_MAP_WORD);
5588 void UpdateClearNextMapWord(bool clear_next_map_word) {
5589 flags_ = static_cast<Flags>(clear_next_map_word
5590 ? flags_ | CLEAR_NEXT_MAP_WORD
5591 : flags_ & ~CLEAR_NEXT_MAP_WORD);
5594 void UpdateSize(HValue* size) {
5595 SetOperandAt(1, size);
5596 if (size->IsInteger32Constant()) {
5597 size_upper_bound_ = HConstant::cast(size);
5599 size_upper_bound_ = NULL;
5603 HAllocate* GetFoldableDominator(HAllocate* dominator);
5605 void UpdateFreeSpaceFiller(int32_t filler_size);
5607 void CreateFreeSpaceFiller(int32_t filler_size);
5609 bool IsFoldable(HAllocate* allocate) {
5610 return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) ||
5611 (IsOldDataSpaceAllocation() && allocate->IsOldDataSpaceAllocation()) ||
5612 (IsOldPointerSpaceAllocation() &&
5613 allocate->IsOldPointerSpaceAllocation());
5616 void ClearNextMapWord(int offset);
5619 Handle<Map> known_initial_map_;
5620 HAllocate* dominating_allocate_;
5621 HStoreNamedField* filler_free_space_size_;
5622 HConstant* size_upper_bound_;
5626 class HStoreCodeEntry V8_FINAL: public HTemplateInstruction<2> {
5628 static HStoreCodeEntry* New(Zone* zone,
5632 return new(zone) HStoreCodeEntry(function, code);
5635 virtual Representation RequiredInputRepresentation(int index) {
5636 return Representation::Tagged();
5639 HValue* function() { return OperandAt(0); }
5640 HValue* code_object() { return OperandAt(1); }
5642 DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry)
5645 HStoreCodeEntry(HValue* function, HValue* code) {
5646 SetOperandAt(0, function);
5647 SetOperandAt(1, code);
5652 class HInnerAllocatedObject V8_FINAL : public HTemplateInstruction<2> {
5654 static HInnerAllocatedObject* New(Zone* zone,
5659 return new(zone) HInnerAllocatedObject(value, offset, type);
5662 HValue* base_object() { return OperandAt(0); }
5663 HValue* offset() { return OperandAt(1); }
5665 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5666 return index == 0 ? Representation::Tagged() : Representation::Integer32();
5669 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5671 DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
5674 HInnerAllocatedObject(HValue* value,
5676 HType type) : HTemplateInstruction<2>(type) {
5677 ASSERT(value->IsAllocate());
5678 ASSERT(type.IsHeapObject());
5679 SetOperandAt(0, value);
5680 SetOperandAt(1, offset);
5681 set_representation(Representation::Tagged());
5686 inline bool StoringValueNeedsWriteBarrier(HValue* value) {
5687 return !value->type().IsSmi()
5688 && !value->type().IsNull()
5689 && !value->type().IsBoolean()
5690 && !value->type().IsUndefined()
5691 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
5695 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
5697 HValue* dominator) {
5698 while (object->IsInnerAllocatedObject()) {
5699 object = HInnerAllocatedObject::cast(object)->base_object();
5701 if (object->IsConstant() && HConstant::cast(object)->IsCell()) {
5704 if (object->IsConstant() &&
5705 HConstant::cast(object)->HasExternalReferenceValue()) {
5706 // Stores to external references require no write barriers
5709 // We definitely need a write barrier unless the object is the allocation
5711 if (object == dominator && object->IsAllocate()) {
5712 // Stores to new space allocations require no write barriers.
5713 if (HAllocate::cast(object)->IsNewSpaceAllocation()) {
5716 // Stores to old space allocations require no write barriers if the value is
5717 // a constant provably not in new space.
5718 if (value->IsConstant() && HConstant::cast(value)->NotInNewSpace()) {
5721 // Stores to old space allocations require no write barriers if the value is
5722 // an old space allocation.
5723 while (value->IsInnerAllocatedObject()) {
5724 value = HInnerAllocatedObject::cast(value)->base_object();
5726 if (value->IsAllocate() &&
5727 !HAllocate::cast(value)->IsNewSpaceAllocation()) {
5735 inline PointersToHereCheck PointersToHereCheckForObject(HValue* object,
5736 HValue* dominator) {
5737 while (object->IsInnerAllocatedObject()) {
5738 object = HInnerAllocatedObject::cast(object)->base_object();
5740 if (object == dominator &&
5741 object->IsAllocate() &&
5742 HAllocate::cast(object)->IsNewSpaceAllocation()) {
5743 return kPointersToHereAreAlwaysInteresting;
5745 return kPointersToHereMaybeInteresting;
5749 class HStoreGlobalCell V8_FINAL : public HUnaryOperation {
5751 DECLARE_INSTRUCTION_FACTORY_P3(HStoreGlobalCell, HValue*,
5752 Handle<PropertyCell>, PropertyDetails);
5754 Unique<PropertyCell> cell() const { return cell_; }
5755 bool RequiresHoleCheck() {
5756 return !details_.IsDontDelete() || details_.IsReadOnly();
5758 bool NeedsWriteBarrier() {
5759 return StoringValueNeedsWriteBarrier(value());
5762 virtual void FinalizeUniqueness() V8_OVERRIDE {
5763 cell_ = Unique<PropertyCell>(cell_.handle());
5766 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5767 return Representation::Tagged();
5769 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5771 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell)
5774 HStoreGlobalCell(HValue* value,
5775 Handle<PropertyCell> cell,
5776 PropertyDetails details)
5777 : HUnaryOperation(value),
5778 cell_(Unique<PropertyCell>::CreateUninitialized(cell)),
5780 SetChangesFlag(kGlobalVars);
5783 Unique<PropertyCell> cell_;
5784 PropertyDetails details_;
5788 class HLoadContextSlot V8_FINAL : public HUnaryOperation {
5791 // Perform a normal load of the context slot without checking its value.
5793 // Load and check the value of the context slot. Deoptimize if it's the
5794 // hole value. This is used for checking for loading of uninitialized
5795 // harmony bindings where we deoptimize into full-codegen generated code
5796 // which will subsequently throw a reference error.
5798 // Load and check the value of the context slot. Return undefined if it's
5799 // the hole value. This is used for non-harmony const assignments
5800 kCheckReturnUndefined
5803 HLoadContextSlot(HValue* context, int slot_index, Mode mode)
5804 : HUnaryOperation(context), slot_index_(slot_index), mode_(mode) {
5805 set_representation(Representation::Tagged());
5807 SetDependsOnFlag(kContextSlots);
5810 int slot_index() const { return slot_index_; }
5811 Mode mode() const { return mode_; }
5813 bool DeoptimizesOnHole() {
5814 return mode_ == kCheckDeoptimize;
5817 bool RequiresHoleCheck() const {
5818 return mode_ != kNoCheck;
5821 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5822 return Representation::Tagged();
5825 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5827 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
5830 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
5831 HLoadContextSlot* b = HLoadContextSlot::cast(other);
5832 return (slot_index() == b->slot_index());
5836 virtual bool IsDeletable() const V8_OVERRIDE { return !RequiresHoleCheck(); }
5843 class HStoreContextSlot V8_FINAL : public HTemplateInstruction<2> {
5846 // Perform a normal store to the context slot without checking its previous
5849 // Check the previous value of the context slot and deoptimize if it's the
5850 // hole value. This is used for checking for assignments to uninitialized
5851 // harmony bindings where we deoptimize into full-codegen generated code
5852 // which will subsequently throw a reference error.
5854 // Check the previous value and ignore assignment if it isn't a hole value
5855 kCheckIgnoreAssignment
5858 DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
5861 HValue* context() { return OperandAt(0); }
5862 HValue* value() { return OperandAt(1); }
5863 int slot_index() const { return slot_index_; }
5864 Mode mode() const { return mode_; }
5866 bool NeedsWriteBarrier() {
5867 return StoringValueNeedsWriteBarrier(value());
5870 bool DeoptimizesOnHole() {
5871 return mode_ == kCheckDeoptimize;
5874 bool RequiresHoleCheck() {
5875 return mode_ != kNoCheck;
5878 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5879 return Representation::Tagged();
5882 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5884 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
5887 HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
5888 : slot_index_(slot_index), mode_(mode) {
5889 SetOperandAt(0, context);
5890 SetOperandAt(1, value);
5891 SetChangesFlag(kContextSlots);
5899 // Represents an access to a portion of an object, such as the map pointer,
5900 // array elements pointer, etc, but not accesses to array elements themselves.
5901 class HObjectAccess V8_FINAL {
5903 inline bool IsInobject() const {
5904 return portion() != kBackingStore && portion() != kExternalMemory;
5907 inline bool IsExternalMemory() const {
5908 return portion() == kExternalMemory;
5911 inline bool IsStringLength() const {
5912 return portion() == kStringLengths;
5915 inline bool IsMap() const {
5916 return portion() == kMaps;
5919 inline int offset() const {
5920 return OffsetField::decode(value_);
5923 inline Representation representation() const {
5924 return Representation::FromKind(RepresentationField::decode(value_));
5927 inline Handle<String> name() const {
5931 inline bool immutable() const {
5932 return ImmutableField::decode(value_);
5935 // Returns true if access is being made to an in-object property that
5936 // was already added to the object.
5937 inline bool existing_inobject_property() const {
5938 return ExistingInobjectPropertyField::decode(value_);
5941 inline HObjectAccess WithRepresentation(Representation representation) {
5942 return HObjectAccess(portion(), offset(), representation, name(),
5943 immutable(), existing_inobject_property());
5946 static HObjectAccess ForHeapNumberValue() {
5947 return HObjectAccess(
5948 kDouble, HeapNumber::kValueOffset, Representation::Double());
5951 static HObjectAccess ForHeapNumberValueLowestBits() {
5952 return HObjectAccess(kDouble,
5953 HeapNumber::kValueOffset,
5954 Representation::Integer32());
5957 static HObjectAccess ForHeapNumberValueHighestBits() {
5958 return HObjectAccess(kDouble,
5959 HeapNumber::kValueOffset + kIntSize,
5960 Representation::Integer32());
5963 static HObjectAccess ForElementsPointer() {
5964 return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
5967 static HObjectAccess ForLiteralsPointer() {
5968 return HObjectAccess(kInobject, JSFunction::kLiteralsOffset);
5971 static HObjectAccess ForNextFunctionLinkPointer() {
5972 return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
5975 static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
5976 return HObjectAccess(
5978 JSArray::kLengthOffset,
5979 IsFastElementsKind(elements_kind)
5980 ? Representation::Smi() : Representation::Tagged());
5983 static HObjectAccess ForAllocationSiteOffset(int offset);
5985 static HObjectAccess ForAllocationSiteList() {
5986 return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
5987 Handle<String>::null(), false, false);
5990 static HObjectAccess ForFixedArrayLength() {
5991 return HObjectAccess(
5993 FixedArray::kLengthOffset,
5994 Representation::Smi());
5997 static HObjectAccess ForStringHashField() {
5998 return HObjectAccess(kInobject,
5999 String::kHashFieldOffset,
6000 Representation::Integer32());
6003 static HObjectAccess ForStringLength() {
6004 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
6005 return HObjectAccess(
6007 String::kLengthOffset,
6008 Representation::Smi());
6011 static HObjectAccess ForConsStringFirst() {
6012 return HObjectAccess(kInobject, ConsString::kFirstOffset);
6015 static HObjectAccess ForConsStringSecond() {
6016 return HObjectAccess(kInobject, ConsString::kSecondOffset);
6019 static HObjectAccess ForPropertiesPointer() {
6020 return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
6023 static HObjectAccess ForPrototypeOrInitialMap() {
6024 return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
6027 static HObjectAccess ForSharedFunctionInfoPointer() {
6028 return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
6031 static HObjectAccess ForCodeEntryPointer() {
6032 return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
6035 static HObjectAccess ForCodeOffset() {
6036 return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
6039 static HObjectAccess ForOptimizedCodeMap() {
6040 return HObjectAccess(kInobject,
6041 SharedFunctionInfo::kOptimizedCodeMapOffset);
6044 static HObjectAccess ForFunctionContextPointer() {
6045 return HObjectAccess(kInobject, JSFunction::kContextOffset);
6048 static HObjectAccess ForMap() {
6049 return HObjectAccess(kMaps, JSObject::kMapOffset);
6052 static HObjectAccess ForMapAsInteger32() {
6053 return HObjectAccess(kMaps, JSObject::kMapOffset,
6054 Representation::Integer32());
6057 static HObjectAccess ForMapInObjectProperties() {
6058 return HObjectAccess(kInobject,
6059 Map::kInObjectPropertiesOffset,
6060 Representation::UInteger8());
6063 static HObjectAccess ForMapInstanceType() {
6064 return HObjectAccess(kInobject,
6065 Map::kInstanceTypeOffset,
6066 Representation::UInteger8());
6069 static HObjectAccess ForMapInstanceSize() {
6070 return HObjectAccess(kInobject,
6071 Map::kInstanceSizeOffset,
6072 Representation::UInteger8());
6075 static HObjectAccess ForMapBitField() {
6076 return HObjectAccess(kInobject,
6077 Map::kBitFieldOffset,
6078 Representation::UInteger8());
6081 static HObjectAccess ForMapBitField2() {
6082 return HObjectAccess(kInobject,
6083 Map::kBitField2Offset,
6084 Representation::UInteger8());
6087 static HObjectAccess ForNameHashField() {
6088 return HObjectAccess(kInobject,
6089 Name::kHashFieldOffset,
6090 Representation::Integer32());
6093 static HObjectAccess ForMapInstanceTypeAndBitField() {
6094 STATIC_ASSERT((Map::kInstanceTypeOffset & 1) == 0);
6095 STATIC_ASSERT(Map::kBitFieldOffset == Map::kInstanceTypeOffset + 1);
6096 return HObjectAccess(kInobject,
6097 Map::kInstanceTypeOffset,
6098 Representation::UInteger16());
6101 static HObjectAccess ForPropertyCellValue() {
6102 return HObjectAccess(kInobject, PropertyCell::kValueOffset);
6105 static HObjectAccess ForCellValue() {
6106 return HObjectAccess(kInobject, Cell::kValueOffset);
6109 static HObjectAccess ForAllocationMementoSite() {
6110 return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
6113 static HObjectAccess ForCounter() {
6114 return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
6115 Handle<String>::null(), false, false);
6118 // Create an access to an offset in a fixed array header.
6119 static HObjectAccess ForFixedArrayHeader(int offset);
6121 // Create an access to an in-object property in a JSObject.
6122 // This kind of access must be used when the object |map| is known and
6123 // in-object properties are being accessed. Accesses of the in-object
6124 // properties can have different semantics depending on whether corresponding
6125 // property was added to the map or not.
6126 static HObjectAccess ForMapAndOffset(Handle<Map> map, int offset,
6127 Representation representation = Representation::Tagged());
6129 // Create an access to an in-object property in a JSObject.
6130 // This kind of access can be used for accessing object header fields or
6131 // in-object properties if the map of the object is not known.
6132 static HObjectAccess ForObservableJSObjectOffset(int offset,
6133 Representation representation = Representation::Tagged()) {
6134 return ForMapAndOffset(Handle<Map>::null(), offset, representation);
6137 // Create an access to an in-object property in a JSArray.
6138 static HObjectAccess ForJSArrayOffset(int offset);
6140 static HObjectAccess ForContextSlot(int index);
6142 // Create an access to the backing store of an object.
6143 static HObjectAccess ForBackingStoreOffset(int offset,
6144 Representation representation = Representation::Tagged());
6146 // Create an access to a resolved field (in-object or backing store).
6147 static HObjectAccess ForField(Handle<Map> map,
6148 LookupResult *lookup, Handle<String> name = Handle<String>::null());
6150 // Create an access for the payload of a Cell or JSGlobalPropertyCell.
6151 static HObjectAccess ForCellPayload(Isolate* isolate);
6153 static HObjectAccess ForJSTypedArrayLength() {
6154 return HObjectAccess::ForObservableJSObjectOffset(
6155 JSTypedArray::kLengthOffset);
6158 static HObjectAccess ForJSArrayBufferBackingStore() {
6159 return HObjectAccess::ForObservableJSObjectOffset(
6160 JSArrayBuffer::kBackingStoreOffset, Representation::External());
6163 static HObjectAccess ForJSArrayBufferByteLength() {
6164 return HObjectAccess::ForObservableJSObjectOffset(
6165 JSArrayBuffer::kByteLengthOffset, Representation::Tagged());
6168 static HObjectAccess ForExternalArrayExternalPointer() {
6169 return HObjectAccess::ForObservableJSObjectOffset(
6170 ExternalArray::kExternalPointerOffset, Representation::External());
6173 static HObjectAccess ForJSArrayBufferViewWeakNext() {
6174 return HObjectAccess::ForObservableJSObjectOffset(
6175 JSArrayBufferView::kWeakNextOffset);
6178 static HObjectAccess ForJSArrayBufferWeakFirstView() {
6179 return HObjectAccess::ForObservableJSObjectOffset(
6180 JSArrayBuffer::kWeakFirstViewOffset);
6183 static HObjectAccess ForJSArrayBufferViewBuffer() {
6184 return HObjectAccess::ForObservableJSObjectOffset(
6185 JSArrayBufferView::kBufferOffset);
6188 static HObjectAccess ForJSArrayBufferViewByteOffset() {
6189 return HObjectAccess::ForObservableJSObjectOffset(
6190 JSArrayBufferView::kByteOffsetOffset);
6193 static HObjectAccess ForJSArrayBufferViewByteLength() {
6194 return HObjectAccess::ForObservableJSObjectOffset(
6195 JSArrayBufferView::kByteLengthOffset);
6198 static HObjectAccess ForGlobalObjectNativeContext() {
6199 return HObjectAccess(kInobject, GlobalObject::kNativeContextOffset);
6202 void PrintTo(StringStream* stream) const;
6204 inline bool Equals(HObjectAccess that) const {
6205 return value_ == that.value_; // portion and offset must match
6209 void SetGVNFlags(HValue *instr, PropertyAccessType access_type);
6212 // internal use only; different parts of an object or array
6214 kMaps, // map of an object
6215 kArrayLengths, // the length of an array
6216 kStringLengths, // the length of a string
6217 kElementsPointer, // elements pointer
6218 kBackingStore, // some field in the backing store
6219 kDouble, // some double field
6220 kInobject, // some other in-object field
6221 kExternalMemory // some field in external memory
6224 HObjectAccess() : value_(0) {}
6226 HObjectAccess(Portion portion, int offset,
6227 Representation representation = Representation::Tagged(),
6228 Handle<String> name = Handle<String>::null(),
6229 bool immutable = false,
6230 bool existing_inobject_property = true)
6231 : value_(PortionField::encode(portion) |
6232 RepresentationField::encode(representation.kind()) |
6233 ImmutableField::encode(immutable ? 1 : 0) |
6234 ExistingInobjectPropertyField::encode(
6235 existing_inobject_property ? 1 : 0) |
6236 OffsetField::encode(offset)),
6238 // assert that the fields decode correctly
6239 ASSERT(this->offset() == offset);
6240 ASSERT(this->portion() == portion);
6241 ASSERT(this->immutable() == immutable);
6242 ASSERT(this->existing_inobject_property() == existing_inobject_property);
6243 ASSERT(RepresentationField::decode(value_) == representation.kind());
6244 ASSERT(!this->existing_inobject_property() || IsInobject());
6247 class PortionField : public BitField<Portion, 0, 3> {};
6248 class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
6249 class ImmutableField : public BitField<bool, 7, 1> {};
6250 class ExistingInobjectPropertyField : public BitField<bool, 8, 1> {};
6251 class OffsetField : public BitField<int, 9, 23> {};
6253 uint32_t value_; // encodes portion, representation, immutable, and offset
6254 Handle<String> name_;
6256 friend class HLoadNamedField;
6257 friend class HStoreNamedField;
6258 friend class SideEffectsTracker;
6260 inline Portion portion() const {
6261 return PortionField::decode(value_);
6266 class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> {
6268 DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*,
6269 HValue*, HObjectAccess);
6270 DECLARE_INSTRUCTION_FACTORY_P5(HLoadNamedField, HValue*, HValue*,
6271 HObjectAccess, const UniqueSet<Map>*, HType);
6273 HValue* object() { return OperandAt(0); }
6274 HValue* dependency() {
6275 ASSERT(HasDependency());
6276 return OperandAt(1);
6278 bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
6279 HObjectAccess access() const { return access_; }
6280 Representation field_representation() const {
6281 return access_.representation();
6284 const UniqueSet<Map>* maps() const { return maps_; }
6286 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
6287 virtual bool HasOutOfBoundsAccess(int size) V8_OVERRIDE {
6288 return !access().IsInobject() || access().offset() >= size;
6290 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6291 if (index == 0 && access().IsExternalMemory()) {
6292 // object must be external in case of external memory access
6293 return Representation::External();
6295 return Representation::Tagged();
6297 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
6298 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6300 bool CanBeReplacedWith(HValue* other) const {
6301 if (!CheckFlag(HValue::kCantBeReplaced)) return false;
6302 if (!type().Equals(other->type())) return false;
6303 if (!representation().Equals(other->representation())) return false;
6304 if (!other->IsLoadNamedField()) return true;
6305 HLoadNamedField* that = HLoadNamedField::cast(other);
6306 if (this->maps_ == that->maps_) return true;
6307 if (this->maps_ == NULL || that->maps_ == NULL) return false;
6308 return this->maps_->IsSubset(that->maps_);
6311 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
6314 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
6315 HLoadNamedField* that = HLoadNamedField::cast(other);
6316 if (!this->access_.Equals(that->access_)) return false;
6317 if (this->maps_ == that->maps_) return true;
6318 return (this->maps_ != NULL &&
6319 that->maps_ != NULL &&
6320 this->maps_->Equals(that->maps_));
6324 HLoadNamedField(HValue* object,
6326 HObjectAccess access)
6327 : access_(access), maps_(NULL) {
6328 ASSERT_NOT_NULL(object);
6329 SetOperandAt(0, object);
6330 SetOperandAt(1, dependency ? dependency : object);
6332 Representation representation = access.representation();
6333 if (representation.IsInteger8() ||
6334 representation.IsUInteger8() ||
6335 representation.IsInteger16() ||
6336 representation.IsUInteger16()) {
6337 set_representation(Representation::Integer32());
6338 } else if (representation.IsSmi()) {
6339 set_type(HType::Smi());
6340 if (SmiValuesAre32Bits()) {
6341 set_representation(Representation::Integer32());
6343 set_representation(representation);
6345 } else if (representation.IsDouble() ||
6346 representation.IsExternal() ||
6347 representation.IsInteger32()) {
6348 set_representation(representation);
6349 } else if (representation.IsHeapObject()) {
6350 set_type(HType::HeapObject());
6351 set_representation(Representation::Tagged());
6353 set_representation(Representation::Tagged());
6355 access.SetGVNFlags(this, LOAD);
6358 HLoadNamedField(HValue* object,
6360 HObjectAccess access,
6361 const UniqueSet<Map>* maps,
6363 : HTemplateInstruction<2>(type), access_(access), maps_(maps) {
6364 ASSERT_NOT_NULL(maps);
6365 ASSERT_NE(0, maps->size());
6367 ASSERT_NOT_NULL(object);
6368 SetOperandAt(0, object);
6369 SetOperandAt(1, dependency ? dependency : object);
6371 ASSERT(access.representation().IsHeapObject());
6372 ASSERT(type.IsHeapObject());
6373 set_representation(Representation::Tagged());
6375 access.SetGVNFlags(this, LOAD);
6378 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
6380 HObjectAccess access_;
6381 const UniqueSet<Map>* maps_;
6385 class HLoadNamedGeneric V8_FINAL : public HTemplateInstruction<2> {
6387 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadNamedGeneric, HValue*,
6390 HValue* context() { return OperandAt(0); }
6391 HValue* object() { return OperandAt(1); }
6392 Handle<Object> name() const { return name_; }
6394 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6395 return Representation::Tagged();
6398 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6400 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
6403 HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
6405 SetOperandAt(0, context);
6406 SetOperandAt(1, object);
6407 set_representation(Representation::Tagged());
6408 SetAllSideEffects();
6411 Handle<Object> name_;
6415 class HLoadFunctionPrototype V8_FINAL : public HUnaryOperation {
6417 DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);
6419 HValue* function() { return OperandAt(0); }
6421 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6422 return Representation::Tagged();
6425 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
6428 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
6431 explicit HLoadFunctionPrototype(HValue* function)
6432 : HUnaryOperation(function) {
6433 set_representation(Representation::Tagged());
6435 SetDependsOnFlag(kCalls);
6439 class ArrayInstructionInterface {
6441 virtual HValue* GetKey() = 0;
6442 virtual void SetKey(HValue* key) = 0;
6443 virtual ElementsKind elements_kind() const = 0;
6444 virtual void IncreaseBaseOffset(uint32_t base_offset) = 0;
6445 virtual int MaxBaseOffsetBits() = 0;
6446 virtual bool IsDehoisted() = 0;
6447 virtual void SetDehoisted(bool is_dehoisted) = 0;
6448 virtual ~ArrayInstructionInterface() { }
6450 static Representation KeyedAccessIndexRequirement(Representation r) {
6451 return r.IsInteger32() || SmiValuesAre32Bits()
6452 ? Representation::Integer32() : Representation::Smi();
6457 static const int kDefaultKeyedHeaderOffsetSentinel = -1;
6459 enum LoadKeyedHoleMode {
6465 class HLoadKeyed V8_FINAL
6466 : public HTemplateInstruction<3>, public ArrayInstructionInterface {
6468 DECLARE_INSTRUCTION_FACTORY_P4(HLoadKeyed, HValue*, HValue*, HValue*,
6470 DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*,
6471 ElementsKind, LoadKeyedHoleMode);
6472 DECLARE_INSTRUCTION_FACTORY_P6(HLoadKeyed, HValue*, HValue*, HValue*,
6473 ElementsKind, LoadKeyedHoleMode, int);
6475 bool is_external() const {
6476 return IsExternalArrayElementsKind(elements_kind());
6478 bool is_fixed_typed_array() const {
6479 return IsFixedTypedArrayElementsKind(elements_kind());
6481 bool is_typed_elements() const {
6482 return is_external() || is_fixed_typed_array();
6484 HValue* elements() { return OperandAt(0); }
6485 HValue* key() { return OperandAt(1); }
6486 HValue* dependency() {
6487 ASSERT(HasDependency());
6488 return OperandAt(2);
6490 bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
6491 uint32_t base_offset() { return BaseOffsetField::decode(bit_field_); }
6492 void IncreaseBaseOffset(uint32_t base_offset) {
6493 // The base offset is usually simply the size of the array header, except
6494 // with dehoisting adds an addition offset due to a array index key
6495 // manipulation, in which case it becomes (array header size +
6496 // constant-offset-from-key * kPointerSize)
6497 base_offset += BaseOffsetField::decode(bit_field_);
6498 bit_field_ = BaseOffsetField::update(bit_field_, base_offset);
6500 virtual int MaxBaseOffsetBits() {
6501 return kBitsForBaseOffset;
6503 HValue* GetKey() { return key(); }
6504 void SetKey(HValue* key) { SetOperandAt(1, key); }
6505 bool IsDehoisted() { return IsDehoistedField::decode(bit_field_); }
6506 void SetDehoisted(bool is_dehoisted) {
6507 bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
6509 virtual ElementsKind elements_kind() const V8_OVERRIDE {
6510 return ElementsKindField::decode(bit_field_);
6512 LoadKeyedHoleMode hole_mode() const {
6513 return HoleModeField::decode(bit_field_);
6516 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6517 // kind_fast: tagged[int32] (none)
6518 // kind_double: tagged[int32] (none)
6519 // kind_fixed_typed_array: tagged[int32] (none)
6520 // kind_external: external[int32] (none)
6522 return is_external() ? Representation::External()
6523 : Representation::Tagged();
6526 return ArrayInstructionInterface::KeyedAccessIndexRequirement(
6527 OperandAt(1)->representation());
6529 return Representation::None();
6532 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
6533 return RequiredInputRepresentation(index);
6536 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6538 bool UsesMustHandleHole() const;
6539 bool AllUsesCanTreatHoleAsNaN() const;
6540 bool RequiresHoleCheck() const;
6542 virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
6544 DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)
6547 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
6548 if (!other->IsLoadKeyed()) return false;
6549 HLoadKeyed* other_load = HLoadKeyed::cast(other);
6551 if (IsDehoisted() && base_offset() != other_load->base_offset())
6553 return elements_kind() == other_load->elements_kind();
6557 HLoadKeyed(HValue* obj,
6560 ElementsKind elements_kind,
6561 LoadKeyedHoleMode mode = NEVER_RETURN_HOLE,
6562 int offset = kDefaultKeyedHeaderOffsetSentinel)
6564 offset = offset == kDefaultKeyedHeaderOffsetSentinel
6565 ? GetDefaultHeaderSizeForElementsKind(elements_kind)
6567 bit_field_ = ElementsKindField::encode(elements_kind) |
6568 HoleModeField::encode(mode) |
6569 BaseOffsetField::encode(offset);
6571 SetOperandAt(0, obj);
6572 SetOperandAt(1, key);
6573 SetOperandAt(2, dependency != NULL ? dependency : obj);
6575 if (!is_typed_elements()) {
6576 // I can detect the case between storing double (holey and fast) and
6577 // smi/object by looking at elements_kind_.
6578 ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
6579 IsFastDoubleElementsKind(elements_kind));
6581 if (IsFastSmiOrObjectElementsKind(elements_kind)) {
6582 if (IsFastSmiElementsKind(elements_kind) &&
6583 (!IsHoleyElementsKind(elements_kind) ||
6584 mode == NEVER_RETURN_HOLE)) {
6585 set_type(HType::Smi());
6586 if (SmiValuesAre32Bits() && !RequiresHoleCheck()) {
6587 set_representation(Representation::Integer32());
6589 set_representation(Representation::Smi());
6592 set_representation(Representation::Tagged());
6595 SetDependsOnFlag(kArrayElements);
6597 set_representation(Representation::Double());
6598 SetDependsOnFlag(kDoubleArrayElements);
6601 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
6602 elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
6603 elements_kind == FLOAT32_ELEMENTS ||
6604 elements_kind == FLOAT64_ELEMENTS) {
6605 set_representation(Representation::Double());
6607 set_representation(Representation::Integer32());
6610 if (is_external()) {
6611 SetDependsOnFlag(kExternalMemory);
6612 } else if (is_fixed_typed_array()) {
6613 SetDependsOnFlag(kTypedArrayElements);
6617 // Native code could change the specialized array.
6618 SetDependsOnFlag(kCalls);
6624 virtual bool IsDeletable() const V8_OVERRIDE {
6625 return !RequiresHoleCheck();
6628 // Establish some checks around our packed fields
6629 enum LoadKeyedBits {
6630 kBitsForElementsKind = 5,
6631 kBitsForHoleMode = 1,
6632 kBitsForBaseOffset = 25,
6633 kBitsForIsDehoisted = 1,
6635 kStartElementsKind = 0,
6636 kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
6637 kStartBaseOffset = kStartHoleMode + kBitsForHoleMode,
6638 kStartIsDehoisted = kStartBaseOffset + kBitsForBaseOffset
6641 STATIC_ASSERT((kBitsForElementsKind + kBitsForBaseOffset +
6642 kBitsForIsDehoisted) <= sizeof(uint32_t)*8);
6643 STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
6644 class ElementsKindField:
6645 public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
6647 class HoleModeField:
6648 public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
6650 class BaseOffsetField:
6651 public BitField<uint32_t, kStartBaseOffset, kBitsForBaseOffset>
6653 class IsDehoistedField:
6654 public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
6656 uint32_t bit_field_;
6660 class HLoadKeyedGeneric V8_FINAL : public HTemplateInstruction<3> {
6662 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadKeyedGeneric, HValue*,
6664 HValue* object() { return OperandAt(0); }
6665 HValue* key() { return OperandAt(1); }
6666 HValue* context() { return OperandAt(2); }
6668 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6670 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6672 return Representation::Tagged();
6675 virtual HValue* Canonicalize() V8_OVERRIDE;
6677 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
6680 HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key) {
6681 set_representation(Representation::Tagged());
6682 SetOperandAt(0, obj);
6683 SetOperandAt(1, key);
6684 SetOperandAt(2, context);
6685 SetAllSideEffects();
6690 // Indicates whether the store is a store to an entry that was previously
6691 // initialized or not.
6692 enum StoreFieldOrKeyedMode {
6693 // The entry could be either previously initialized or not.
6695 // At the time of this store it is guaranteed that the entry is already
6697 STORE_TO_INITIALIZED_ENTRY
6701 class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> {
6703 DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
6704 HObjectAccess, HValue*);
6705 DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue*,
6706 HObjectAccess, HValue*, StoreFieldOrKeyedMode);
6708 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
6710 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE {
6713 virtual bool HasOutOfBoundsAccess(int size) V8_OVERRIDE {
6714 return !access().IsInobject() || access().offset() >= size;
6716 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6717 if (index == 0 && access().IsExternalMemory()) {
6718 // object must be external in case of external memory access
6719 return Representation::External();
6720 } else if (index == 1) {
6721 if (field_representation().IsInteger8() ||
6722 field_representation().IsUInteger8() ||
6723 field_representation().IsInteger16() ||
6724 field_representation().IsUInteger16() ||
6725 field_representation().IsInteger32()) {
6726 return Representation::Integer32();
6727 } else if (field_representation().IsDouble()) {
6728 return field_representation();
6729 } else if (field_representation().IsSmi()) {
6730 if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
6731 return Representation::Integer32();
6733 return field_representation();
6734 } else if (field_representation().IsExternal()) {
6735 return Representation::External();
6738 return Representation::Tagged();
6740 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
6741 HValue* dominator) V8_OVERRIDE {
6742 ASSERT(side_effect == kNewSpacePromotion);
6743 if (!FLAG_use_write_barrier_elimination) return false;
6744 dominator_ = dominator;
6747 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6749 HValue* object() const { return OperandAt(0); }
6750 HValue* value() const { return OperandAt(1); }
6751 HValue* transition() const { return OperandAt(2); }
6753 HObjectAccess access() const { return access_; }
6754 HValue* dominator() const { return dominator_; }
6755 bool has_transition() const { return has_transition_; }
6756 StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
6758 Handle<Map> transition_map() const {
6759 if (has_transition()) {
6760 return Handle<Map>::cast(
6761 HConstant::cast(transition())->handle(Isolate::Current()));
6763 return Handle<Map>();
6767 void SetTransition(HConstant* transition) {
6768 ASSERT(!has_transition()); // Only set once.
6769 SetOperandAt(2, transition);
6770 has_transition_ = true;
6771 SetChangesFlag(kMaps);
6774 bool NeedsWriteBarrier() {
6775 ASSERT(!field_representation().IsDouble() || !has_transition());
6776 if (field_representation().IsDouble()) return false;
6777 if (field_representation().IsSmi()) return false;
6778 if (field_representation().IsInteger32()) return false;
6779 if (field_representation().IsExternal()) return false;
6780 return StoringValueNeedsWriteBarrier(value()) &&
6781 ReceiverObjectNeedsWriteBarrier(object(), value(), dominator());
6784 bool NeedsWriteBarrierForMap() {
6785 return ReceiverObjectNeedsWriteBarrier(object(), transition(),
6789 SmiCheck SmiCheckForWriteBarrier() const {
6790 if (field_representation().IsHeapObject()) return OMIT_SMI_CHECK;
6791 if (value()->type().IsHeapObject()) return OMIT_SMI_CHECK;
6792 return INLINE_SMI_CHECK;
6795 PointersToHereCheck PointersToHereCheckForValue() const {
6796 return PointersToHereCheckForObject(value(), dominator());
6799 Representation field_representation() const {
6800 return access_.representation();
6803 void UpdateValue(HValue* value) {
6804 SetOperandAt(1, value);
6807 bool CanBeReplacedWith(HStoreNamedField* that) const {
6808 if (!this->access().Equals(that->access())) return false;
6809 if (SmiValuesAre32Bits() &&
6810 this->field_representation().IsSmi() &&
6811 this->store_mode() == INITIALIZING_STORE &&
6812 that->store_mode() == STORE_TO_INITIALIZED_ENTRY) {
6813 // We cannot replace an initializing store to a smi field with a store to
6814 // an initialized entry on 64-bit architectures (with 32-bit smis).
6821 HStoreNamedField(HValue* obj,
6822 HObjectAccess access,
6824 StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
6827 has_transition_(false),
6828 store_mode_(store_mode) {
6829 // Stores to a non existing in-object property are allowed only to the
6830 // newly allocated objects (via HAllocate or HInnerAllocatedObject).
6831 ASSERT(!access.IsInobject() || access.existing_inobject_property() ||
6832 obj->IsAllocate() || obj->IsInnerAllocatedObject());
6833 SetOperandAt(0, obj);
6834 SetOperandAt(1, val);
6835 SetOperandAt(2, obj);
6836 access.SetGVNFlags(this, STORE);
6839 HObjectAccess access_;
6841 bool has_transition_ : 1;
6842 StoreFieldOrKeyedMode store_mode_ : 1;
6846 class HStoreNamedGeneric V8_FINAL : public HTemplateInstruction<3> {
6848 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreNamedGeneric, HValue*,
6849 Handle<String>, HValue*,
6851 HValue* object() { return OperandAt(0); }
6852 HValue* value() { return OperandAt(1); }
6853 HValue* context() { return OperandAt(2); }
6854 Handle<String> name() { return name_; }
6855 StrictMode strict_mode() { return strict_mode_; }
6857 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6859 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6860 return Representation::Tagged();
6863 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
6866 HStoreNamedGeneric(HValue* context,
6868 Handle<String> name,
6870 StrictMode strict_mode)
6872 strict_mode_(strict_mode) {
6873 SetOperandAt(0, object);
6874 SetOperandAt(1, value);
6875 SetOperandAt(2, context);
6876 SetAllSideEffects();
6879 Handle<String> name_;
6880 StrictMode strict_mode_;
6884 class HStoreKeyed V8_FINAL
6885 : public HTemplateInstruction<3>, public ArrayInstructionInterface {
6887 DECLARE_INSTRUCTION_FACTORY_P4(HStoreKeyed, HValue*, HValue*, HValue*,
6889 DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*,
6890 ElementsKind, StoreFieldOrKeyedMode);
6891 DECLARE_INSTRUCTION_FACTORY_P6(HStoreKeyed, HValue*, HValue*, HValue*,
6892 ElementsKind, StoreFieldOrKeyedMode, int);
6894 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6895 // kind_fast: tagged[int32] = tagged
6896 // kind_double: tagged[int32] = double
6897 // kind_smi : tagged[int32] = smi
6898 // kind_fixed_typed_array: tagged[int32] = (double | int32)
6899 // kind_external: external[int32] = (double | int32)
6901 return is_external() ? Representation::External()
6902 : Representation::Tagged();
6903 } else if (index == 1) {
6904 return ArrayInstructionInterface::KeyedAccessIndexRequirement(
6905 OperandAt(1)->representation());
6908 ASSERT_EQ(index, 2);
6909 if (IsDoubleOrFloatElementsKind(elements_kind())) {
6910 return Representation::Double();
6912 if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
6913 return Representation::Integer32();
6915 if (IsFastSmiElementsKind(elements_kind())) {
6916 return Representation::Smi();
6919 return is_external() || is_fixed_typed_array()
6920 ? Representation::Integer32()
6921 : Representation::Tagged();
6924 bool is_external() const {
6925 return IsExternalArrayElementsKind(elements_kind());
6928 bool is_fixed_typed_array() const {
6929 return IsFixedTypedArrayElementsKind(elements_kind());
6932 bool is_typed_elements() const {
6933 return is_external() || is_fixed_typed_array();
6936 virtual Representation observed_input_representation(int index) V8_OVERRIDE {
6937 if (index < 2) return RequiredInputRepresentation(index);
6938 if (IsUninitialized()) {
6939 return Representation::None();
6941 if (IsDoubleOrFloatElementsKind(elements_kind())) {
6942 return Representation::Double();
6944 if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
6945 return Representation::Integer32();
6947 if (IsFastSmiElementsKind(elements_kind())) {
6948 return Representation::Smi();
6950 if (is_typed_elements()) {
6951 return Representation::Integer32();
6953 // For fast object elements kinds, don't assume anything.
6954 return Representation::None();
6957 HValue* elements() const { return OperandAt(0); }
6958 HValue* key() const { return OperandAt(1); }
6959 HValue* value() const { return OperandAt(2); }
6960 bool value_is_smi() const {
6961 return IsFastSmiElementsKind(elements_kind_);
6963 StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
6964 ElementsKind elements_kind() const { return elements_kind_; }
6965 uint32_t base_offset() { return base_offset_; }
6966 void IncreaseBaseOffset(uint32_t base_offset) {
6967 // The base offset is usually simply the size of the array header, except
6968 // with dehoisting adds an addition offset due to a array index key
6969 // manipulation, in which case it becomes (array header size +
6970 // constant-offset-from-key * kPointerSize)
6971 base_offset_ += base_offset;
6973 virtual int MaxBaseOffsetBits() {
6974 return 31 - ElementsKindToShiftSize(elements_kind_);
6976 HValue* GetKey() { return key(); }
6977 void SetKey(HValue* key) { SetOperandAt(1, key); }
6978 bool IsDehoisted() { return is_dehoisted_; }
6979 void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
6980 bool IsUninitialized() { return is_uninitialized_; }
6981 void SetUninitialized(bool is_uninitialized) {
6982 is_uninitialized_ = is_uninitialized;
6985 bool IsConstantHoleStore() {
6986 return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
6989 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
6990 HValue* dominator) V8_OVERRIDE {
6991 ASSERT(side_effect == kNewSpacePromotion);
6992 dominator_ = dominator;
6996 HValue* dominator() const { return dominator_; }
6998 bool NeedsWriteBarrier() {
6999 if (value_is_smi()) {
7002 return StoringValueNeedsWriteBarrier(value()) &&
7003 ReceiverObjectNeedsWriteBarrier(elements(), value(), dominator());
7007 PointersToHereCheck PointersToHereCheckForValue() const {
7008 return PointersToHereCheckForObject(value(), dominator());
7011 bool NeedsCanonicalization();
7013 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7015 DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
7018 HStoreKeyed(HValue* obj, HValue* key, HValue* val,
7019 ElementsKind elements_kind,
7020 StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE,
7021 int offset = kDefaultKeyedHeaderOffsetSentinel)
7022 : elements_kind_(elements_kind),
7023 base_offset_(offset == kDefaultKeyedHeaderOffsetSentinel
7024 ? GetDefaultHeaderSizeForElementsKind(elements_kind)
7026 is_dehoisted_(false),
7027 is_uninitialized_(false),
7028 store_mode_(store_mode),
7030 SetOperandAt(0, obj);
7031 SetOperandAt(1, key);
7032 SetOperandAt(2, val);
7034 ASSERT(store_mode != STORE_TO_INITIALIZED_ENTRY ||
7035 elements_kind == FAST_SMI_ELEMENTS);
7037 if (IsFastObjectElementsKind(elements_kind)) {
7038 SetFlag(kTrackSideEffectDominators);
7039 SetDependsOnFlag(kNewSpacePromotion);
7041 if (is_external()) {
7042 SetChangesFlag(kExternalMemory);
7043 SetFlag(kAllowUndefinedAsNaN);
7044 } else if (IsFastDoubleElementsKind(elements_kind)) {
7045 SetChangesFlag(kDoubleArrayElements);
7046 } else if (IsFastSmiElementsKind(elements_kind)) {
7047 SetChangesFlag(kArrayElements);
7048 } else if (is_fixed_typed_array()) {
7049 SetChangesFlag(kTypedArrayElements);
7050 SetFlag(kAllowUndefinedAsNaN);
7052 SetChangesFlag(kArrayElements);
7055 // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
7056 if ((elements_kind >= EXTERNAL_INT8_ELEMENTS &&
7057 elements_kind <= EXTERNAL_UINT32_ELEMENTS) ||
7058 (elements_kind >= UINT8_ELEMENTS &&
7059 elements_kind <= INT32_ELEMENTS)) {
7060 SetFlag(kTruncatingToInt32);
7064 ElementsKind elements_kind_;
7065 uint32_t base_offset_;
7066 bool is_dehoisted_ : 1;
7067 bool is_uninitialized_ : 1;
7068 StoreFieldOrKeyedMode store_mode_: 1;
7073 class HStoreKeyedGeneric V8_FINAL : public HTemplateInstruction<4> {
7075 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreKeyedGeneric, HValue*,
7076 HValue*, HValue*, StrictMode);
7078 HValue* object() { return OperandAt(0); }
7079 HValue* key() { return OperandAt(1); }
7080 HValue* value() { return OperandAt(2); }
7081 HValue* context() { return OperandAt(3); }
7082 StrictMode strict_mode() { return strict_mode_; }
7084 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7085 // tagged[tagged] = tagged
7086 return Representation::Tagged();
7089 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7091 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
7094 HStoreKeyedGeneric(HValue* context,
7098 StrictMode strict_mode)
7099 : strict_mode_(strict_mode) {
7100 SetOperandAt(0, object);
7101 SetOperandAt(1, key);
7102 SetOperandAt(2, value);
7103 SetOperandAt(3, context);
7104 SetAllSideEffects();
7107 StrictMode strict_mode_;
7111 class HTransitionElementsKind V8_FINAL : public HTemplateInstruction<2> {
7113 inline static HTransitionElementsKind* New(Zone* zone,
7116 Handle<Map> original_map,
7117 Handle<Map> transitioned_map) {
7118 return new(zone) HTransitionElementsKind(context, object,
7119 original_map, transitioned_map);
7122 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7123 return Representation::Tagged();
7126 HValue* object() { return OperandAt(0); }
7127 HValue* context() { return OperandAt(1); }
7128 Unique<Map> original_map() { return original_map_; }
7129 Unique<Map> transitioned_map() { return transitioned_map_; }
7130 ElementsKind from_kind() { return from_kind_; }
7131 ElementsKind to_kind() { return to_kind_; }
7133 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7135 DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
7138 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7139 HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
7140 return original_map_ == instr->original_map_ &&
7141 transitioned_map_ == instr->transitioned_map_;
7144 virtual int RedefinedOperandIndex() { return 0; }
7147 HTransitionElementsKind(HValue* context,
7149 Handle<Map> original_map,
7150 Handle<Map> transitioned_map)
7151 : original_map_(Unique<Map>(original_map)),
7152 transitioned_map_(Unique<Map>(transitioned_map)),
7153 from_kind_(original_map->elements_kind()),
7154 to_kind_(transitioned_map->elements_kind()) {
7155 SetOperandAt(0, object);
7156 SetOperandAt(1, context);
7158 SetChangesFlag(kElementsKind);
7159 if (!IsSimpleMapChangeTransition(from_kind_, to_kind_)) {
7160 SetChangesFlag(kElementsPointer);
7161 SetChangesFlag(kNewSpacePromotion);
7163 set_representation(Representation::Tagged());
7166 Unique<Map> original_map_;
7167 Unique<Map> transitioned_map_;
7168 ElementsKind from_kind_;
7169 ElementsKind to_kind_;
7173 class HStringAdd V8_FINAL : public HBinaryOperation {
7175 static HInstruction* New(Zone* zone,
7179 PretenureFlag pretenure_flag = NOT_TENURED,
7180 StringAddFlags flags = STRING_ADD_CHECK_BOTH,
7181 Handle<AllocationSite> allocation_site =
7182 Handle<AllocationSite>::null());
7184 StringAddFlags flags() const { return flags_; }
7185 PretenureFlag pretenure_flag() const { return pretenure_flag_; }
7187 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7188 return Representation::Tagged();
7191 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7193 DECLARE_CONCRETE_INSTRUCTION(StringAdd)
7196 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7197 return flags_ == HStringAdd::cast(other)->flags_ &&
7198 pretenure_flag_ == HStringAdd::cast(other)->pretenure_flag_;
7202 HStringAdd(HValue* context,
7205 PretenureFlag pretenure_flag,
7206 StringAddFlags flags,
7207 Handle<AllocationSite> allocation_site)
7208 : HBinaryOperation(context, left, right, HType::String()),
7209 flags_(flags), pretenure_flag_(pretenure_flag) {
7210 set_representation(Representation::Tagged());
7212 SetDependsOnFlag(kMaps);
7213 SetChangesFlag(kNewSpacePromotion);
7214 if (FLAG_trace_pretenuring) {
7215 PrintF("HStringAdd with AllocationSite %p %s\n",
7216 allocation_site.is_null()
7217 ? static_cast<void*>(NULL)
7218 : static_cast<void*>(*allocation_site),
7219 pretenure_flag == TENURED ? "tenured" : "not tenured");
7223 // No side-effects except possible allocation:
7224 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7226 const StringAddFlags flags_;
7227 const PretenureFlag pretenure_flag_;
7231 class HStringCharCodeAt V8_FINAL : public HTemplateInstruction<3> {
7233 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HStringCharCodeAt,
7237 virtual Representation RequiredInputRepresentation(int index) {
7238 // The index is supposed to be Integer32.
7240 ? Representation::Integer32()
7241 : Representation::Tagged();
7244 HValue* context() const { return OperandAt(0); }
7245 HValue* string() const { return OperandAt(1); }
7246 HValue* index() const { return OperandAt(2); }
7248 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
7251 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
7253 virtual Range* InferRange(Zone* zone) V8_OVERRIDE {
7254 return new(zone) Range(0, String::kMaxUtf16CodeUnit);
7258 HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
7259 SetOperandAt(0, context);
7260 SetOperandAt(1, string);
7261 SetOperandAt(2, index);
7262 set_representation(Representation::Integer32());
7264 SetDependsOnFlag(kMaps);
7265 SetDependsOnFlag(kStringChars);
7266 SetChangesFlag(kNewSpacePromotion);
7269 // No side effects: runtime function assumes string + number inputs.
7270 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7274 class HStringCharFromCode V8_FINAL : public HTemplateInstruction<2> {
7276 static HInstruction* New(Zone* zone,
7280 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7282 ? Representation::Tagged()
7283 : Representation::Integer32();
7286 HValue* context() const { return OperandAt(0); }
7287 HValue* value() const { return OperandAt(1); }
7289 virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
7291 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
7294 HStringCharFromCode(HValue* context, HValue* char_code)
7295 : HTemplateInstruction<2>(HType::String()) {
7296 SetOperandAt(0, context);
7297 SetOperandAt(1, char_code);
7298 set_representation(Representation::Tagged());
7300 SetChangesFlag(kNewSpacePromotion);
7303 virtual bool IsDeletable() const V8_OVERRIDE {
7304 return !value()->ToNumberCanBeObserved();
7310 class HMaterializedLiteral : public HTemplateInstruction<V> {
7312 HMaterializedLiteral<V>(int index, int depth, AllocationSiteMode mode)
7313 : literal_index_(index), depth_(depth), allocation_site_mode_(mode) {
7314 this->set_representation(Representation::Tagged());
7317 HMaterializedLiteral<V>(int index, int depth)
7318 : literal_index_(index), depth_(depth),
7319 allocation_site_mode_(DONT_TRACK_ALLOCATION_SITE) {
7320 this->set_representation(Representation::Tagged());
7323 int literal_index() const { return literal_index_; }
7324 int depth() const { return depth_; }
7325 AllocationSiteMode allocation_site_mode() const {
7326 return allocation_site_mode_;
7330 virtual bool IsDeletable() const V8_FINAL V8_OVERRIDE { return true; }
7334 AllocationSiteMode allocation_site_mode_;
7338 class HRegExpLiteral V8_FINAL : public HMaterializedLiteral<1> {
7340 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HRegExpLiteral,
7346 HValue* context() { return OperandAt(0); }
7347 Handle<FixedArray> literals() { return literals_; }
7348 Handle<String> pattern() { return pattern_; }
7349 Handle<String> flags() { return flags_; }
7351 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7352 return Representation::Tagged();
7355 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
7358 HRegExpLiteral(HValue* context,
7359 Handle<FixedArray> literals,
7360 Handle<String> pattern,
7361 Handle<String> flags,
7363 : HMaterializedLiteral<1>(literal_index, 0),
7364 literals_(literals),
7367 SetOperandAt(0, context);
7368 SetAllSideEffects();
7369 set_type(HType::JSObject());
7372 Handle<FixedArray> literals_;
7373 Handle<String> pattern_;
7374 Handle<String> flags_;
7378 class HFunctionLiteral V8_FINAL : public HTemplateInstruction<1> {
7380 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HFunctionLiteral,
7381 Handle<SharedFunctionInfo>,
7383 HValue* context() { return OperandAt(0); }
7385 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7386 return Representation::Tagged();
7389 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral)
7391 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
7392 bool pretenure() const { return pretenure_; }
7393 bool has_no_literals() const { return has_no_literals_; }
7394 bool is_generator() const { return is_generator_; }
7395 StrictMode strict_mode() const { return strict_mode_; }
7398 HFunctionLiteral(HValue* context,
7399 Handle<SharedFunctionInfo> shared,
7401 : HTemplateInstruction<1>(HType::JSObject()),
7402 shared_info_(shared),
7403 pretenure_(pretenure),
7404 has_no_literals_(shared->num_literals() == 0),
7405 is_generator_(shared->is_generator()),
7406 strict_mode_(shared->strict_mode()) {
7407 SetOperandAt(0, context);
7408 set_representation(Representation::Tagged());
7409 SetChangesFlag(kNewSpacePromotion);
7412 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7414 Handle<SharedFunctionInfo> shared_info_;
7415 bool pretenure_ : 1;
7416 bool has_no_literals_ : 1;
7417 bool is_generator_ : 1;
7418 StrictMode strict_mode_;
7422 class HTypeof V8_FINAL : public HTemplateInstruction<2> {
7424 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HTypeof, HValue*);
7426 HValue* context() { return OperandAt(0); }
7427 HValue* value() { return OperandAt(1); }
7429 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7431 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7432 return Representation::Tagged();
7435 DECLARE_CONCRETE_INSTRUCTION(Typeof)
7438 explicit HTypeof(HValue* context, HValue* value) {
7439 SetOperandAt(0, context);
7440 SetOperandAt(1, value);
7441 set_representation(Representation::Tagged());
7444 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7448 class HTrapAllocationMemento V8_FINAL : public HTemplateInstruction<1> {
7450 DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
7452 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7453 return Representation::Tagged();
7456 HValue* object() { return OperandAt(0); }
7458 DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
7461 explicit HTrapAllocationMemento(HValue* obj) {
7462 SetOperandAt(0, obj);
7467 class HToFastProperties V8_FINAL : public HUnaryOperation {
7469 DECLARE_INSTRUCTION_FACTORY_P1(HToFastProperties, HValue*);
7471 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7472 return Representation::Tagged();
7475 DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
7478 explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
7479 set_representation(Representation::Tagged());
7480 SetChangesFlag(kNewSpacePromotion);
7482 // This instruction is not marked as kChangesMaps, but does
7483 // change the map of the input operand. Use it only when creating
7484 // object literals via a runtime call.
7485 ASSERT(value->IsCallRuntime());
7487 const Runtime::Function* function = HCallRuntime::cast(value)->function();
7488 ASSERT(function->function_id == Runtime::kHiddenCreateObjectLiteral);
7492 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7496 class HDateField V8_FINAL : public HUnaryOperation {
7498 DECLARE_INSTRUCTION_FACTORY_P2(HDateField, HValue*, Smi*);
7500 Smi* index() const { return index_; }
7502 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7503 return Representation::Tagged();
7506 DECLARE_CONCRETE_INSTRUCTION(DateField)
7509 HDateField(HValue* date, Smi* index)
7510 : HUnaryOperation(date), index_(index) {
7511 set_representation(Representation::Tagged());
7518 class HSeqStringGetChar V8_FINAL : public HTemplateInstruction<2> {
7520 static HInstruction* New(Zone* zone,
7522 String::Encoding encoding,
7526 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7527 return (index == 0) ? Representation::Tagged()
7528 : Representation::Integer32();
7531 String::Encoding encoding() const { return encoding_; }
7532 HValue* string() const { return OperandAt(0); }
7533 HValue* index() const { return OperandAt(1); }
7535 DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)
7538 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7539 return encoding() == HSeqStringGetChar::cast(other)->encoding();
7542 virtual Range* InferRange(Zone* zone) V8_OVERRIDE {
7543 if (encoding() == String::ONE_BYTE_ENCODING) {
7544 return new(zone) Range(0, String::kMaxOneByteCharCode);
7546 ASSERT_EQ(String::TWO_BYTE_ENCODING, encoding());
7547 return new(zone) Range(0, String::kMaxUtf16CodeUnit);
7552 HSeqStringGetChar(String::Encoding encoding,
7554 HValue* index) : encoding_(encoding) {
7555 SetOperandAt(0, string);
7556 SetOperandAt(1, index);
7557 set_representation(Representation::Integer32());
7559 SetDependsOnFlag(kStringChars);
7562 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7564 String::Encoding encoding_;
7568 class HSeqStringSetChar V8_FINAL : public HTemplateInstruction<4> {
7570 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(
7571 HSeqStringSetChar, String::Encoding,
7572 HValue*, HValue*, HValue*);
7574 String::Encoding encoding() { return encoding_; }
7575 HValue* context() { return OperandAt(0); }
7576 HValue* string() { return OperandAt(1); }
7577 HValue* index() { return OperandAt(2); }
7578 HValue* value() { return OperandAt(3); }
7580 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7581 return (index <= 1) ? Representation::Tagged()
7582 : Representation::Integer32();
7585 DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
7588 HSeqStringSetChar(HValue* context,
7589 String::Encoding encoding,
7592 HValue* value) : encoding_(encoding) {
7593 SetOperandAt(0, context);
7594 SetOperandAt(1, string);
7595 SetOperandAt(2, index);
7596 SetOperandAt(3, value);
7597 set_representation(Representation::Tagged());
7598 SetChangesFlag(kStringChars);
7601 String::Encoding encoding_;
7605 class HCheckMapValue V8_FINAL : public HTemplateInstruction<2> {
7607 DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);
7609 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7610 return Representation::Tagged();
7613 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7615 virtual HType CalculateInferredType() V8_OVERRIDE {
7616 if (value()->type().IsHeapObject()) return value()->type();
7617 return HType::HeapObject();
7620 HValue* value() const { return OperandAt(0); }
7621 HValue* map() const { return OperandAt(1); }
7623 virtual HValue* Canonicalize() V8_OVERRIDE;
7625 DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
7628 virtual int RedefinedOperandIndex() { return 0; }
7630 virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7635 HCheckMapValue(HValue* value, HValue* map)
7636 : HTemplateInstruction<2>(HType::HeapObject()) {
7637 SetOperandAt(0, value);
7638 SetOperandAt(1, map);
7639 set_representation(Representation::Tagged());
7641 SetDependsOnFlag(kMaps);
7642 SetDependsOnFlag(kElementsKind);
7647 class HForInPrepareMap V8_FINAL : public HTemplateInstruction<2> {
7649 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HForInPrepareMap, HValue*);
7651 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7652 return Representation::Tagged();
7655 HValue* context() { return OperandAt(0); }
7656 HValue* enumerable() { return OperandAt(1); }
7658 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7660 virtual HType CalculateInferredType() V8_OVERRIDE {
7661 return HType::Tagged();
7664 DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
7667 HForInPrepareMap(HValue* context,
7669 SetOperandAt(0, context);
7670 SetOperandAt(1, object);
7671 set_representation(Representation::Tagged());
7672 SetAllSideEffects();
7677 class HForInCacheArray V8_FINAL : public HTemplateInstruction<2> {
7679 DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
7681 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7682 return Representation::Tagged();
7685 HValue* enumerable() { return OperandAt(0); }
7686 HValue* map() { return OperandAt(1); }
7687 int idx() { return idx_; }
7689 HForInCacheArray* index_cache() {
7690 return index_cache_;
7693 void set_index_cache(HForInCacheArray* index_cache) {
7694 index_cache_ = index_cache;
7697 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7699 virtual HType CalculateInferredType() V8_OVERRIDE {
7700 return HType::Tagged();
7703 DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
7706 HForInCacheArray(HValue* enumerable,
7708 int idx) : idx_(idx) {
7709 SetOperandAt(0, enumerable);
7710 SetOperandAt(1, keys);
7711 set_representation(Representation::Tagged());
7715 HForInCacheArray* index_cache_;
7719 class HLoadFieldByIndex V8_FINAL : public HTemplateInstruction<2> {
7721 DECLARE_INSTRUCTION_FACTORY_P2(HLoadFieldByIndex, HValue*, HValue*);
7723 HLoadFieldByIndex(HValue* object,
7725 SetOperandAt(0, object);
7726 SetOperandAt(1, index);
7727 SetChangesFlag(kNewSpacePromotion);
7728 set_representation(Representation::Tagged());
7731 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7733 return Representation::Smi();
7735 return Representation::Tagged();
7739 HValue* object() { return OperandAt(0); }
7740 HValue* index() { return OperandAt(1); }
7742 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7744 virtual HType CalculateInferredType() V8_OVERRIDE {
7745 return HType::Tagged();
7748 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
7751 virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7755 class HStoreFrameContext: public HUnaryOperation {
7757 DECLARE_INSTRUCTION_FACTORY_P1(HStoreFrameContext, HValue*);
7759 HValue* context() { return OperandAt(0); }
7761 virtual Representation RequiredInputRepresentation(int index) {
7762 return Representation::Tagged();
7765 DECLARE_CONCRETE_INSTRUCTION(StoreFrameContext)
7767 explicit HStoreFrameContext(HValue* context)
7768 : HUnaryOperation(context) {
7769 set_representation(Representation::Tagged());
7770 SetChangesFlag(kContextSlots);
7775 class HAllocateBlockContext: public HTemplateInstruction<2> {
7777 DECLARE_INSTRUCTION_FACTORY_P3(HAllocateBlockContext, HValue*,
7778 HValue*, Handle<ScopeInfo>);
7779 HValue* context() { return OperandAt(0); }
7780 HValue* function() { return OperandAt(1); }
7781 Handle<ScopeInfo> scope_info() { return scope_info_; }
7783 virtual Representation RequiredInputRepresentation(int index) {
7784 return Representation::Tagged();
7787 virtual void PrintDataTo(StringStream* stream);
7789 DECLARE_CONCRETE_INSTRUCTION(AllocateBlockContext)
7792 HAllocateBlockContext(HValue* context,
7794 Handle<ScopeInfo> scope_info)
7795 : scope_info_(scope_info) {
7796 SetOperandAt(0, context);
7797 SetOperandAt(1, function);
7798 set_representation(Representation::Tagged());
7801 Handle<ScopeInfo> scope_info_;
7806 #undef DECLARE_INSTRUCTION
7807 #undef DECLARE_CONCRETE_INSTRUCTION
7809 } } // namespace v8::internal
7811 #endif // V8_HYDROGEN_INSTRUCTIONS_H_