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/base/bits.h"
12 #include "src/code-stubs.h"
13 #include "src/conversions.h"
14 #include "src/data-flow.h"
15 #include "src/deoptimizer.h"
16 #include "src/feedback-slots.h"
17 #include "src/hydrogen-types.h"
18 #include "src/small-pointer-list.h"
19 #include "src/unique.h"
20 #include "src/utils.h"
26 // Forward declarations.
31 class HInferRepresentationPhase;
33 class HLoopInformation;
34 class HStoreNamedField;
40 #define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V) \
41 V(ArithmeticBinaryOperation) \
43 V(BitwiseBinaryOperation) \
44 V(ControlInstruction) \
48 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
50 V(AccessArgumentsAt) \
52 V(AllocateBlockContext) \
55 V(ArgumentsElements) \
61 V(BoundsCheckBaseIndexInformation) \
63 V(CallWithDescriptor) \
73 V(CheckInstanceType) \
79 V(ClassOfTestAndBranch) \
80 V(CompareNumericAndBranch) \
81 V(CompareHoleAndBranch) \
83 V(CompareMinusZeroAndBranch) \
84 V(CompareObjectEqAndBranch) \
97 V(EnvironmentMarker) \
98 V(ForceRepresentation) \
102 V(GetCachedArrayIndex) \
104 V(HasCachedArrayIndexAndBranch) \
105 V(HasInstanceTypeAndBranch) \
106 V(InnerAllocatedObject) \
108 V(InstanceOfKnownGlobal) \
110 V(IsConstructCallAndBranch) \
111 V(IsObjectAndBranch) \
112 V(IsStringAndBranch) \
114 V(IsUndetectableAndBranch) \
117 V(LoadFieldByIndex) \
118 V(LoadFunctionPrototype) \
120 V(LoadGlobalGeneric) \
122 V(LoadKeyedGeneric) \
124 V(LoadNamedGeneric) \
139 V(SeqStringGetChar) \
140 V(SeqStringSetChar) \
146 V(StoreContextSlot) \
147 V(StoreFrameContext) \
150 V(StoreKeyedGeneric) \
152 V(StoreNamedGeneric) \
154 V(StringCharCodeAt) \
155 V(StringCharFromCode) \
156 V(StringCompareAndBranch) \
158 V(TailCallThroughMegamorphicCache) \
160 V(ToFastProperties) \
161 V(TransitionElementsKind) \
162 V(TrapAllocationMemento) \
164 V(TypeofIsAndBranch) \
165 V(UnaryMathOperation) \
170 #define GVN_TRACKED_FLAG_LIST(V) \
173 #define GVN_UNTRACKED_FLAG_LIST(V) \
177 V(BackingStoreFields) \
180 V(DoubleArrayElements) \
190 V(TypedArrayElements)
193 #define DECLARE_ABSTRACT_INSTRUCTION(type) \
194 virtual bool Is##type() const FINAL OVERRIDE { return true; } \
195 static H##type* cast(HValue* value) { \
196 DCHECK(value->Is##type()); \
197 return reinterpret_cast<H##type*>(value); \
201 #define DECLARE_CONCRETE_INSTRUCTION(type) \
202 virtual LInstruction* CompileToLithium( \
203 LChunkBuilder* builder) FINAL OVERRIDE; \
204 static H##type* cast(HValue* value) { \
205 DCHECK(value->Is##type()); \
206 return reinterpret_cast<H##type*>(value); \
208 virtual Opcode opcode() const FINAL OVERRIDE { \
209 return HValue::k##type; \
213 enum PropertyAccessType { LOAD, STORE };
216 class Range FINAL : public ZoneObject {
222 can_be_minus_zero_(false) { }
224 Range(int32_t lower, int32_t upper)
228 can_be_minus_zero_(false) { }
230 int32_t upper() const { return upper_; }
231 int32_t lower() const { return lower_; }
232 Range* next() const { return next_; }
233 Range* CopyClearLower(Zone* zone) const {
234 return new(zone) Range(kMinInt, upper_);
236 Range* CopyClearUpper(Zone* zone) const {
237 return new(zone) Range(lower_, kMaxInt);
239 Range* Copy(Zone* zone) const {
240 Range* result = new(zone) Range(lower_, upper_);
241 result->set_can_be_minus_zero(CanBeMinusZero());
244 int32_t Mask() const;
245 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
246 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
247 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
248 bool CanBeNegative() const { return lower_ < 0; }
249 bool CanBePositive() const { return upper_ > 0; }
250 bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
251 bool IsMostGeneric() const {
252 return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
254 bool IsInSmiRange() const {
255 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
258 lower_ = Max(lower_, Smi::kMinValue);
259 upper_ = Min(upper_, Smi::kMaxValue);
266 void StackUpon(Range* other) {
271 void Intersect(Range* other);
272 void Union(Range* other);
273 void CombinedMax(Range* other);
274 void CombinedMin(Range* other);
276 void AddConstant(int32_t value);
277 void Sar(int32_t value);
278 void Shl(int32_t value);
279 bool AddAndCheckOverflow(const Representation& r, Range* other);
280 bool SubAndCheckOverflow(const Representation& r, Range* other);
281 bool MulAndCheckOverflow(const Representation& r, Range* other);
287 bool can_be_minus_zero_;
291 class HUseListNode: public ZoneObject {
293 HUseListNode(HValue* value, int index, HUseListNode* tail)
294 : tail_(tail), value_(value), index_(index) {
297 HUseListNode* tail();
298 HValue* value() const { return value_; }
299 int index() const { return index_; }
301 void set_tail(HUseListNode* list) { tail_ = list; }
305 tail_ = reinterpret_cast<HUseListNode*>(1);
318 // We reuse use list nodes behind the scenes as uses are added and deleted.
319 // This class is the safe way to iterate uses while deleting them.
320 class HUseIterator FINAL BASE_EMBEDDED {
322 bool Done() { return current_ == NULL; }
336 explicit HUseIterator(HUseListNode* head);
338 HUseListNode* current_;
347 // All tracked flags should appear before untracked ones.
349 // Declare global value numbering flags.
350 #define DECLARE_FLAG(Type) k##Type,
351 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
352 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
354 #define COUNT_FLAG(Type) + 1
355 kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG),
356 kNumberOfUntrackedSideEffects = 0 GVN_UNTRACKED_FLAG_LIST(COUNT_FLAG),
358 kNumberOfFlags = kNumberOfTrackedSideEffects + kNumberOfUntrackedSideEffects
362 static inline GVNFlag GVNFlagFromInt(int i) {
364 DCHECK(i < kNumberOfFlags);
365 return static_cast<GVNFlag>(i);
369 class DecompositionResult FINAL BASE_EMBEDDED {
371 DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
373 HValue* base() { return base_; }
374 int offset() { return offset_; }
375 int scale() { return scale_; }
377 bool Apply(HValue* other_base, int other_offset, int other_scale = 0) {
380 offset_ = other_offset;
381 scale_ = other_scale;
386 offset_ += other_offset;
387 scale_ = other_scale;
395 void SwapValues(HValue** other_base, int* other_offset, int* other_scale) {
396 swap(&base_, other_base);
397 swap(&offset_, other_offset);
398 swap(&scale_, other_scale);
402 template <class T> void swap(T* a, T* b) {
414 typedef EnumSet<GVNFlag, int32_t> GVNFlagSet;
417 // This class encapsulates encoding and decoding of sources positions from
418 // which hydrogen values originated.
419 // When FLAG_track_hydrogen_positions is set this object encodes the
420 // identifier of the inlining and absolute offset from the start of the
422 // When the flag is not set we simply track absolute offset from the
424 class HSourcePosition {
426 HSourcePosition(const HSourcePosition& other) : value_(other.value_) { }
428 static HSourcePosition Unknown() {
429 return HSourcePosition(RelocInfo::kNoPosition);
432 bool IsUnknown() const { return value_ == RelocInfo::kNoPosition; }
434 int position() const { return PositionField::decode(value_); }
435 void set_position(int position) {
436 if (FLAG_hydrogen_track_positions) {
437 value_ = static_cast<int>(PositionField::update(value_, position));
443 int inlining_id() const { return InliningIdField::decode(value_); }
444 void set_inlining_id(int inlining_id) {
445 if (FLAG_hydrogen_track_positions) {
446 value_ = static_cast<int>(InliningIdField::update(value_, inlining_id));
450 int raw() const { return value_; }
453 typedef BitField<int, 0, 9> InliningIdField;
455 // Offset from the start of the inlined function.
456 typedef BitField<int, 9, 23> PositionField;
458 explicit HSourcePosition(int value) : value_(value) { }
460 friend class HPositionInfo;
461 friend class LCodeGenBase;
463 // If FLAG_hydrogen_track_positions is set contains bitfields InliningIdField
464 // and PositionField.
465 // Otherwise contains absolute offset from the script start.
470 OStream& operator<<(OStream& os, const HSourcePosition& p);
473 class HValue : public ZoneObject {
475 static const int kNoNumber = -1;
478 kFlexibleRepresentation,
480 // Participate in Global Value Numbering, i.e. elimination of
481 // unnecessary recomputations. If an instruction sets this flag, it must
482 // implement DataEquals(), which will be used to determine if other
483 // occurrences of the instruction are indeed the same.
485 // Track instructions that are dominating side effects. If an instruction
486 // sets this flag, it must implement HandleSideEffectDominator() and should
487 // indicate which side effects to track by setting GVN flags.
488 kTrackSideEffectDominators,
495 kAllowUndefinedAsNaN,
498 kAllUsesTruncatingToInt32,
500 kAllUsesTruncatingToSmi,
501 // Set after an instruction is killed.
503 // Instructions that are allowed to produce full range unsigned integer
504 // values are marked with kUint32 flag. If arithmetic shift or a load from
505 // EXTERNAL_UINT32_ELEMENTS array is not marked with this flag
506 // it will deoptimize if result does not fit into signed integer range.
507 // HGraph::ComputeSafeUint32Operations is responsible for setting this
510 kHasNoObservableSideEffects,
511 // Indicates an instruction shouldn't be replaced by optimization, this flag
512 // is useful to set in cases where recomputing a value is cheaper than
513 // extending the value's live range and spilling it.
515 // Indicates the instruction is live during dead code elimination.
518 // HEnvironmentMarkers are deleted before dead code
519 // elimination takes place, so they can repurpose the kIsLive flag:
520 kEndsLiveRange = kIsLive,
522 // TODO(everyone): Don't forget to update this!
526 STATIC_ASSERT(kLastFlag < kBitsPerInt);
528 static HValue* cast(HValue* value) { return value; }
531 // Declare a unique enum value for each hydrogen instruction.
532 #define DECLARE_OPCODE(type) k##type,
533 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
535 #undef DECLARE_OPCODE
537 virtual Opcode opcode() const = 0;
539 // Declare a non-virtual predicates for each concrete HInstruction or HValue.
540 #define DECLARE_PREDICATE(type) \
541 bool Is##type() const { return opcode() == k##type; }
542 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
543 #undef DECLARE_PREDICATE
544 bool IsPhi() const { return opcode() == kPhi; }
546 // Declare virtual predicates for abstract HInstruction or HValue
547 #define DECLARE_PREDICATE(type) \
548 virtual bool Is##type() const { return false; }
549 HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
550 #undef DECLARE_PREDICATE
552 bool IsBitwiseBinaryShift() {
553 return IsShl() || IsShr() || IsSar();
556 explicit HValue(HType type = HType::Tagged())
563 range_poisoned_(false),
568 virtual HSourcePosition position() const {
569 return HSourcePosition::Unknown();
571 virtual HSourcePosition operand_position(int index) const {
575 HBasicBlock* block() const { return block_; }
576 void SetBlock(HBasicBlock* block);
578 // Note: Never call this method for an unlinked value.
579 Isolate* isolate() const;
581 int id() const { return id_; }
582 void set_id(int id) { id_ = id; }
584 HUseIterator uses() const { return HUseIterator(use_list_); }
586 virtual bool EmitAtUses() { return false; }
588 Representation representation() const { return representation_; }
589 void ChangeRepresentation(Representation r) {
590 DCHECK(CheckFlag(kFlexibleRepresentation));
591 DCHECK(!CheckFlag(kCannotBeTagged) || !r.IsTagged());
592 RepresentationChanged(r);
595 // Tagged is the bottom of the lattice, don't go any further.
596 ClearFlag(kFlexibleRepresentation);
599 virtual void AssumeRepresentation(Representation r);
601 virtual Representation KnownOptimalRepresentation() {
602 Representation r = representation();
605 if (t.IsSmi()) return Representation::Smi();
606 if (t.IsHeapNumber()) return Representation::Double();
607 if (t.IsHeapObject()) return r;
608 return Representation::None();
613 HType type() const { return type_; }
614 void set_type(HType new_type) {
615 DCHECK(new_type.IsSubtypeOf(type_));
619 // There are HInstructions that do not really change a value, they
620 // only add pieces of information to it (like bounds checks, map checks,
622 // We call these instructions "informative definitions", or "iDef".
623 // One of the iDef operands is special because it is the value that is
624 // "transferred" to the output, we call it the "redefined operand".
625 // If an HValue is an iDef it must override RedefinedOperandIndex() so that
626 // it does not return kNoRedefinedOperand;
627 static const int kNoRedefinedOperand = -1;
628 virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
629 bool IsInformativeDefinition() {
630 return RedefinedOperandIndex() != kNoRedefinedOperand;
632 HValue* RedefinedOperand() {
633 int index = RedefinedOperandIndex();
634 return index == kNoRedefinedOperand ? NULL : OperandAt(index);
637 bool CanReplaceWithDummyUses();
639 virtual int argument_delta() const { return 0; }
641 // A purely informative definition is an idef that will not emit code and
642 // should therefore be removed from the graph in the RestoreActualValues
643 // phase (so that live ranges will be shorter).
644 virtual bool IsPurelyInformativeDefinition() { return false; }
646 // This method must always return the original HValue SSA definition,
647 // regardless of any chain of iDefs of this value.
648 HValue* ActualValue() {
649 HValue* value = this;
651 while ((index = value->RedefinedOperandIndex()) != kNoRedefinedOperand) {
652 value = value->OperandAt(index);
657 bool IsInteger32Constant();
658 int32_t GetInteger32Constant();
659 bool EqualsInteger32Constant(int32_t value);
661 bool IsDefinedAfter(HBasicBlock* other) const;
664 virtual int OperandCount() const = 0;
665 virtual HValue* OperandAt(int index) const = 0;
666 void SetOperandAt(int index, HValue* value);
668 void DeleteAndReplaceWith(HValue* other);
669 void ReplaceAllUsesWith(HValue* other);
670 bool HasNoUses() const { return use_list_ == NULL; }
671 bool HasOneUse() const {
672 return use_list_ != NULL && use_list_->tail() == NULL;
674 bool HasMultipleUses() const {
675 return use_list_ != NULL && use_list_->tail() != NULL;
677 int UseCount() const;
679 // Mark this HValue as dead and to be removed from other HValues' use lists.
682 int flags() const { return flags_; }
683 void SetFlag(Flag f) { flags_ |= (1 << f); }
684 void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
685 bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
686 void CopyFlag(Flag f, HValue* other) {
687 if (other->CheckFlag(f)) SetFlag(f);
690 // Returns true if the flag specified is set for all uses, false otherwise.
691 bool CheckUsesForFlag(Flag f) const;
692 // Same as before and the first one without the flag is returned in value.
693 bool CheckUsesForFlag(Flag f, HValue** value) const;
694 // Returns true if the flag specified is set for all uses, and this set
695 // of uses is non-empty.
696 bool HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const;
698 GVNFlagSet ChangesFlags() const { return changes_flags_; }
699 GVNFlagSet DependsOnFlags() const { return depends_on_flags_; }
700 void SetChangesFlag(GVNFlag f) { changes_flags_.Add(f); }
701 void SetDependsOnFlag(GVNFlag f) { depends_on_flags_.Add(f); }
702 void ClearChangesFlag(GVNFlag f) { changes_flags_.Remove(f); }
703 void ClearDependsOnFlag(GVNFlag f) { depends_on_flags_.Remove(f); }
704 bool CheckChangesFlag(GVNFlag f) const {
705 return changes_flags_.Contains(f);
707 bool CheckDependsOnFlag(GVNFlag f) const {
708 return depends_on_flags_.Contains(f);
710 void SetAllSideEffects() { changes_flags_.Add(AllSideEffectsFlagSet()); }
711 void ClearAllSideEffects() {
712 changes_flags_.Remove(AllSideEffectsFlagSet());
714 bool HasSideEffects() const {
715 return changes_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
717 bool HasObservableSideEffects() const {
718 return !CheckFlag(kHasNoObservableSideEffects) &&
719 changes_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
722 GVNFlagSet SideEffectFlags() const {
723 GVNFlagSet result = ChangesFlags();
724 result.Intersect(AllSideEffectsFlagSet());
728 GVNFlagSet ObservableChangesFlags() const {
729 GVNFlagSet result = ChangesFlags();
730 result.Intersect(AllObservableSideEffectsFlagSet());
734 Range* range() const {
735 DCHECK(!range_poisoned_);
738 bool HasRange() const {
739 DCHECK(!range_poisoned_);
740 return range_ != NULL;
743 void PoisonRange() { range_poisoned_ = true; }
745 void AddNewRange(Range* r, Zone* zone);
746 void RemoveLastAddedRange();
747 void ComputeInitialRange(Zone* zone);
749 // Escape analysis helpers.
750 virtual bool HasEscapingOperandAt(int index) { return true; }
751 virtual bool HasOutOfBoundsAccess(int size) { return false; }
753 // Representation helpers.
754 virtual Representation observed_input_representation(int index) {
755 return Representation::None();
757 virtual Representation RequiredInputRepresentation(int index) = 0;
758 virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
760 // This gives the instruction an opportunity to replace itself with an
761 // instruction that does the same in some better way. To replace an
762 // instruction with a new one, first add the new instruction to the graph,
763 // then return it. Return NULL to have the instruction deleted.
764 virtual HValue* Canonicalize() { return this; }
766 bool Equals(HValue* other);
767 virtual intptr_t Hashcode();
769 // Compute unique ids upfront that is safe wrt GC and concurrent compilation.
770 virtual void FinalizeUniqueness() { }
773 virtual OStream& PrintTo(OStream& os) const = 0; // NOLINT
775 const char* Mnemonic() const;
777 // Type information helpers.
778 bool HasMonomorphicJSObjectType();
780 // TODO(mstarzinger): For now instructions can override this function to
781 // specify statically known types, once HType can convey more information
782 // it should be based on the HType.
783 virtual Handle<Map> GetMonomorphicJSObjectMap() { return Handle<Map>(); }
785 // Updated the inferred type of this instruction and returns true if
787 bool UpdateInferredType();
789 virtual HType CalculateInferredType();
791 // This function must be overridden for instructions which have the
792 // kTrackSideEffectDominators flag set, to track instructions that are
793 // dominating side effects.
794 // It returns true if it removed an instruction which had side effects.
795 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
801 // Check if this instruction has some reason that prevents elimination.
802 bool CannotBeEliminated() const {
803 return HasObservableSideEffects() || !IsDeletable();
807 virtual void Verify() = 0;
810 virtual bool TryDecompose(DecompositionResult* decomposition) {
811 if (RedefinedOperand() != NULL) {
812 return RedefinedOperand()->TryDecompose(decomposition);
818 // Returns true conservatively if the program might be able to observe a
819 // ToString() operation on this value.
820 bool ToStringCanBeObserved() const {
821 return ToStringOrToNumberCanBeObserved();
824 // Returns true conservatively if the program might be able to observe a
825 // ToNumber() operation on this value.
826 bool ToNumberCanBeObserved() const {
827 return ToStringOrToNumberCanBeObserved();
830 MinusZeroMode GetMinusZeroMode() {
831 return CheckFlag(kBailoutOnMinusZero)
832 ? FAIL_ON_MINUS_ZERO : TREAT_MINUS_ZERO_AS_ZERO;
836 // This function must be overridden for instructions with flag kUseGVN, to
837 // compare the non-Operand parts of the instruction.
838 virtual bool DataEquals(HValue* other) {
843 bool ToStringOrToNumberCanBeObserved() const {
844 if (type().IsTaggedPrimitive()) return false;
845 if (type().IsJSObject()) return true;
846 return !representation().IsSmiOrInteger32() && !representation().IsDouble();
849 virtual Representation RepresentationFromInputs() {
850 return representation();
852 virtual Representation RepresentationFromUses();
853 Representation RepresentationFromUseRequirements();
855 virtual void UpdateRepresentation(Representation new_rep,
856 HInferRepresentationPhase* h_infer,
858 void AddDependantsToWorklist(HInferRepresentationPhase* h_infer);
860 virtual void RepresentationChanged(Representation to) { }
862 virtual Range* InferRange(Zone* zone);
863 virtual void DeleteFromGraph() = 0;
864 virtual void InternalSetOperandAt(int index, HValue* value) = 0;
866 DCHECK(block_ != NULL);
870 void set_representation(Representation r) {
871 DCHECK(representation_.IsNone() && !r.IsNone());
875 static GVNFlagSet AllFlagSet() {
877 #define ADD_FLAG(Type) result.Add(k##Type);
878 GVN_TRACKED_FLAG_LIST(ADD_FLAG)
879 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
884 // A flag mask to mark an instruction as having arbitrary side effects.
885 static GVNFlagSet AllSideEffectsFlagSet() {
886 GVNFlagSet result = AllFlagSet();
887 result.Remove(kOsrEntries);
890 friend OStream& operator<<(OStream& os, const ChangesOf& v);
892 // A flag mask of all side effects that can make observable changes in
893 // an executing program (i.e. are not safe to repeat, move or remove);
894 static GVNFlagSet AllObservableSideEffectsFlagSet() {
895 GVNFlagSet result = AllFlagSet();
896 result.Remove(kNewSpacePromotion);
897 result.Remove(kElementsKind);
898 result.Remove(kElementsPointer);
899 result.Remove(kMaps);
903 // Remove the matching use from the use list if present. Returns the
904 // removed list node or NULL.
905 HUseListNode* RemoveUse(HValue* value, int index);
907 void RegisterUse(int index, HValue* new_value);
911 // The id of this instruction in the hydrogen graph, assigned when first
912 // added to the graph. Reflects creation order.
915 Representation representation_;
917 HUseListNode* use_list_;
920 bool range_poisoned_;
923 GVNFlagSet changes_flags_;
924 GVNFlagSet depends_on_flags_;
927 virtual bool IsDeletable() const { return false; }
929 DISALLOW_COPY_AND_ASSIGN(HValue);
932 // Support for printing various aspects of an HValue.
934 explicit NameOf(const HValue* const v) : value(v) {}
940 explicit TypeOf(const HValue* const v) : value(v) {}
946 explicit ChangesOf(const HValue* const v) : value(v) {}
951 OStream& operator<<(OStream& os, const HValue& v);
952 OStream& operator<<(OStream& os, const NameOf& v);
953 OStream& operator<<(OStream& os, const TypeOf& v);
954 OStream& operator<<(OStream& os, const ChangesOf& v);
957 #define DECLARE_INSTRUCTION_FACTORY_P0(I) \
958 static I* New(Zone* zone, HValue* context) { \
959 return new(zone) I(); \
962 #define DECLARE_INSTRUCTION_FACTORY_P1(I, P1) \
963 static I* New(Zone* zone, HValue* context, P1 p1) { \
964 return new(zone) I(p1); \
967 #define DECLARE_INSTRUCTION_FACTORY_P2(I, P1, P2) \
968 static I* New(Zone* zone, HValue* context, P1 p1, P2 p2) { \
969 return new(zone) I(p1, p2); \
972 #define DECLARE_INSTRUCTION_FACTORY_P3(I, P1, P2, P3) \
973 static I* New(Zone* zone, HValue* context, P1 p1, P2 p2, P3 p3) { \
974 return new(zone) I(p1, p2, p3); \
977 #define DECLARE_INSTRUCTION_FACTORY_P4(I, P1, P2, P3, P4) \
978 static I* New(Zone* zone, \
984 return new(zone) I(p1, p2, p3, p4); \
987 #define DECLARE_INSTRUCTION_FACTORY_P5(I, P1, P2, P3, P4, P5) \
988 static I* New(Zone* zone, \
995 return new(zone) I(p1, p2, p3, p4, p5); \
998 #define DECLARE_INSTRUCTION_FACTORY_P6(I, P1, P2, P3, P4, P5, P6) \
999 static I* New(Zone* zone, \
1007 return new(zone) I(p1, p2, p3, p4, p5, p6); \
1010 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(I) \
1011 static I* New(Zone* zone, HValue* context) { \
1012 return new(zone) I(context); \
1015 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(I, P1) \
1016 static I* New(Zone* zone, HValue* context, P1 p1) { \
1017 return new(zone) I(context, p1); \
1020 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(I, P1, P2) \
1021 static I* New(Zone* zone, HValue* context, P1 p1, P2 p2) { \
1022 return new(zone) I(context, p1, p2); \
1025 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(I, P1, P2, P3) \
1026 static I* New(Zone* zone, HValue* context, P1 p1, P2 p2, P3 p3) { \
1027 return new(zone) I(context, p1, p2, p3); \
1030 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(I, P1, P2, P3, P4) \
1031 static I* New(Zone* zone, \
1037 return new(zone) I(context, p1, p2, p3, p4); \
1040 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(I, P1, P2, P3, P4, P5) \
1041 static I* New(Zone* zone, \
1048 return new(zone) I(context, p1, p2, p3, p4, p5); \
1052 // A helper class to represent per-operand position information attached to
1053 // the HInstruction in the compact form. Uses tagging to distinguish between
1054 // case when only instruction's position is available and case when operands'
1055 // positions are also available.
1056 // In the first case it contains intruction's position as a tagged value.
1057 // In the second case it points to an array which contains instruction's
1058 // position and operands' positions.
1059 class HPositionInfo {
1061 explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { }
1063 HSourcePosition position() const {
1064 if (has_operand_positions()) {
1065 return operand_positions()[kInstructionPosIndex];
1067 return HSourcePosition(static_cast<int>(UntagPosition(data_)));
1070 void set_position(HSourcePosition pos) {
1071 if (has_operand_positions()) {
1072 operand_positions()[kInstructionPosIndex] = pos;
1074 data_ = TagPosition(pos.raw());
1078 void ensure_storage_for_operand_positions(Zone* zone, int operand_count) {
1079 if (has_operand_positions()) {
1083 const int length = kFirstOperandPosIndex + operand_count;
1084 HSourcePosition* positions =
1085 zone->NewArray<HSourcePosition>(length);
1086 for (int i = 0; i < length; i++) {
1087 positions[i] = HSourcePosition::Unknown();
1090 const HSourcePosition pos = position();
1091 data_ = reinterpret_cast<intptr_t>(positions);
1094 DCHECK(has_operand_positions());
1097 HSourcePosition operand_position(int idx) const {
1098 if (!has_operand_positions()) {
1101 return *operand_position_slot(idx);
1104 void set_operand_position(int idx, HSourcePosition pos) {
1105 *operand_position_slot(idx) = pos;
1109 static const intptr_t kInstructionPosIndex = 0;
1110 static const intptr_t kFirstOperandPosIndex = 1;
1112 HSourcePosition* operand_position_slot(int idx) const {
1113 DCHECK(has_operand_positions());
1114 return &(operand_positions()[kFirstOperandPosIndex + idx]);
1117 bool has_operand_positions() const {
1118 return !IsTaggedPosition(data_);
1121 HSourcePosition* operand_positions() const {
1122 DCHECK(has_operand_positions());
1123 return reinterpret_cast<HSourcePosition*>(data_);
1126 static const intptr_t kPositionTag = 1;
1127 static const intptr_t kPositionShift = 1;
1128 static bool IsTaggedPosition(intptr_t val) {
1129 return (val & kPositionTag) != 0;
1131 static intptr_t UntagPosition(intptr_t val) {
1132 DCHECK(IsTaggedPosition(val));
1133 return val >> kPositionShift;
1135 static intptr_t TagPosition(intptr_t val) {
1136 const intptr_t result = (val << kPositionShift) | kPositionTag;
1137 DCHECK(UntagPosition(result) == val);
1145 class HInstruction : public HValue {
1147 HInstruction* next() const { return next_; }
1148 HInstruction* previous() const { return previous_; }
1150 virtual OStream& PrintTo(OStream& os) const OVERRIDE; // NOLINT
1151 virtual OStream& PrintDataTo(OStream& os) const; // NOLINT
1153 bool IsLinked() const { return block() != NULL; }
1156 void InsertBefore(HInstruction* next);
1158 template<class T> T* Prepend(T* instr) {
1159 instr->InsertBefore(this);
1163 void InsertAfter(HInstruction* previous);
1165 template<class T> T* Append(T* instr) {
1166 instr->InsertAfter(this);
1170 // The position is a write-once variable.
1171 virtual HSourcePosition position() const OVERRIDE {
1172 return HSourcePosition(position_.position());
1174 bool has_position() const {
1175 return !position().IsUnknown();
1177 void set_position(HSourcePosition position) {
1178 DCHECK(!has_position());
1179 DCHECK(!position.IsUnknown());
1180 position_.set_position(position);
1183 virtual HSourcePosition operand_position(int index) const OVERRIDE {
1184 const HSourcePosition pos = position_.operand_position(index);
1185 return pos.IsUnknown() ? position() : pos;
1187 void set_operand_position(Zone* zone, int index, HSourcePosition pos) {
1188 DCHECK(0 <= index && index < OperandCount());
1189 position_.ensure_storage_for_operand_positions(zone, OperandCount());
1190 position_.set_operand_position(index, pos);
1193 bool Dominates(HInstruction* other);
1194 bool CanTruncateToSmi() const { return CheckFlag(kTruncatingToSmi); }
1195 bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
1197 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
1200 virtual void Verify() OVERRIDE;
1203 bool CanDeoptimize();
1205 virtual bool HasStackCheck() { return false; }
1207 DECLARE_ABSTRACT_INSTRUCTION(Instruction)
1210 explicit HInstruction(HType type = HType::Tagged())
1214 position_(RelocInfo::kNoPosition) {
1215 SetDependsOnFlag(kOsrEntries);
1218 virtual void DeleteFromGraph() OVERRIDE { Unlink(); }
1221 void InitializeAsFirst(HBasicBlock* block) {
1222 DCHECK(!IsLinked());
1226 HInstruction* next_;
1227 HInstruction* previous_;
1228 HPositionInfo position_;
1230 friend class HBasicBlock;
1235 class HTemplateInstruction : public HInstruction {
1237 virtual int OperandCount() const FINAL OVERRIDE { return V; }
1238 virtual HValue* OperandAt(int i) const FINAL OVERRIDE {
1243 explicit HTemplateInstruction(HType type = HType::Tagged())
1244 : HInstruction(type) {}
1246 virtual void InternalSetOperandAt(int i, HValue* value) FINAL OVERRIDE {
1251 EmbeddedContainer<HValue*, V> inputs_;
1255 class HControlInstruction : public HInstruction {
1257 virtual HBasicBlock* SuccessorAt(int i) const = 0;
1258 virtual int SuccessorCount() const = 0;
1259 virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
1261 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1263 virtual bool KnownSuccessorBlock(HBasicBlock** block) {
1268 HBasicBlock* FirstSuccessor() {
1269 return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
1271 HBasicBlock* SecondSuccessor() {
1272 return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
1276 HBasicBlock* swap = SuccessorAt(0);
1277 SetSuccessorAt(0, SuccessorAt(1));
1278 SetSuccessorAt(1, swap);
1281 DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
1285 class HSuccessorIterator FINAL BASE_EMBEDDED {
1287 explicit HSuccessorIterator(const HControlInstruction* instr)
1288 : instr_(instr), current_(0) {}
1290 bool Done() { return current_ >= instr_->SuccessorCount(); }
1291 HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
1292 void Advance() { current_++; }
1295 const HControlInstruction* instr_;
1300 template<int S, int V>
1301 class HTemplateControlInstruction : public HControlInstruction {
1303 int SuccessorCount() const OVERRIDE { return S; }
1304 HBasicBlock* SuccessorAt(int i) const OVERRIDE { return successors_[i]; }
1305 void SetSuccessorAt(int i, HBasicBlock* block) OVERRIDE {
1306 successors_[i] = block;
1309 int OperandCount() const OVERRIDE { return V; }
1310 HValue* OperandAt(int i) const OVERRIDE { return inputs_[i]; }
1314 void InternalSetOperandAt(int i, HValue* value) OVERRIDE {
1319 EmbeddedContainer<HBasicBlock*, S> successors_;
1320 EmbeddedContainer<HValue*, V> inputs_;
1324 class HBlockEntry FINAL : public HTemplateInstruction<0> {
1326 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1327 return Representation::None();
1330 DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
1334 class HDummyUse FINAL : public HTemplateInstruction<1> {
1336 explicit HDummyUse(HValue* value)
1337 : HTemplateInstruction<1>(HType::Smi()) {
1338 SetOperandAt(0, value);
1339 // Pretend to be a Smi so that the HChange instructions inserted
1340 // before any use generate as little code as possible.
1341 set_representation(Representation::Tagged());
1344 HValue* value() const { return OperandAt(0); }
1346 virtual bool HasEscapingOperandAt(int index) OVERRIDE { return false; }
1347 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1348 return Representation::None();
1351 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1353 DECLARE_CONCRETE_INSTRUCTION(DummyUse);
1357 // Inserts an int3/stop break instruction for debugging purposes.
1358 class HDebugBreak FINAL : public HTemplateInstruction<0> {
1360 DECLARE_INSTRUCTION_FACTORY_P0(HDebugBreak);
1362 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1363 return Representation::None();
1366 DECLARE_CONCRETE_INSTRUCTION(DebugBreak)
1370 class HGoto FINAL : public HTemplateControlInstruction<1, 0> {
1372 explicit HGoto(HBasicBlock* target) {
1373 SetSuccessorAt(0, target);
1376 virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE {
1377 *block = FirstSuccessor();
1381 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1382 return Representation::None();
1385 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1387 DECLARE_CONCRETE_INSTRUCTION(Goto)
1391 class HDeoptimize FINAL : public HTemplateControlInstruction<1, 0> {
1393 static HDeoptimize* New(Zone* zone,
1396 Deoptimizer::BailoutType type,
1397 HBasicBlock* unreachable_continuation) {
1398 return new(zone) HDeoptimize(reason, type, unreachable_continuation);
1401 virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE {
1406 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1407 return Representation::None();
1410 const char* reason() const { return reason_; }
1411 Deoptimizer::BailoutType type() { return type_; }
1413 DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
1416 explicit HDeoptimize(const char* reason,
1417 Deoptimizer::BailoutType type,
1418 HBasicBlock* unreachable_continuation)
1419 : reason_(reason), type_(type) {
1420 SetSuccessorAt(0, unreachable_continuation);
1423 const char* reason_;
1424 Deoptimizer::BailoutType type_;
1428 class HUnaryControlInstruction : public HTemplateControlInstruction<2, 1> {
1430 HUnaryControlInstruction(HValue* value,
1431 HBasicBlock* true_target,
1432 HBasicBlock* false_target) {
1433 SetOperandAt(0, value);
1434 SetSuccessorAt(0, true_target);
1435 SetSuccessorAt(1, false_target);
1438 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1440 HValue* value() const { return OperandAt(0); }
1444 class HBranch FINAL : public HUnaryControlInstruction {
1446 DECLARE_INSTRUCTION_FACTORY_P1(HBranch, HValue*);
1447 DECLARE_INSTRUCTION_FACTORY_P2(HBranch, HValue*,
1448 ToBooleanStub::Types);
1449 DECLARE_INSTRUCTION_FACTORY_P4(HBranch, HValue*,
1450 ToBooleanStub::Types,
1451 HBasicBlock*, HBasicBlock*);
1453 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1454 return Representation::None();
1456 virtual Representation observed_input_representation(int index) OVERRIDE;
1458 virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE;
1460 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1462 ToBooleanStub::Types expected_input_types() const {
1463 return expected_input_types_;
1466 DECLARE_CONCRETE_INSTRUCTION(Branch)
1469 HBranch(HValue* value,
1470 ToBooleanStub::Types expected_input_types = ToBooleanStub::Types(),
1471 HBasicBlock* true_target = NULL,
1472 HBasicBlock* false_target = NULL)
1473 : HUnaryControlInstruction(value, true_target, false_target),
1474 expected_input_types_(expected_input_types) {
1475 SetFlag(kAllowUndefinedAsNaN);
1478 ToBooleanStub::Types expected_input_types_;
1482 class HCompareMap FINAL : public HUnaryControlInstruction {
1484 DECLARE_INSTRUCTION_FACTORY_P2(HCompareMap, HValue*, Handle<Map>);
1485 DECLARE_INSTRUCTION_FACTORY_P4(HCompareMap, HValue*, Handle<Map>,
1486 HBasicBlock*, HBasicBlock*);
1488 virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE {
1489 if (known_successor_index() != kNoKnownSuccessorIndex) {
1490 *block = SuccessorAt(known_successor_index());
1497 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1499 static const int kNoKnownSuccessorIndex = -1;
1500 int known_successor_index() const { return known_successor_index_; }
1501 void set_known_successor_index(int known_successor_index) {
1502 known_successor_index_ = known_successor_index;
1505 Unique<Map> map() const { return map_; }
1506 bool map_is_stable() const { return map_is_stable_; }
1508 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1509 return Representation::Tagged();
1512 DECLARE_CONCRETE_INSTRUCTION(CompareMap)
1515 virtual int RedefinedOperandIndex() { return 0; }
1518 HCompareMap(HValue* value,
1520 HBasicBlock* true_target = NULL,
1521 HBasicBlock* false_target = NULL)
1522 : HUnaryControlInstruction(value, true_target, false_target),
1523 known_successor_index_(kNoKnownSuccessorIndex),
1524 map_is_stable_(map->is_stable()),
1525 map_(Unique<Map>::CreateImmovable(map)) {
1526 set_representation(Representation::Tagged());
1529 int known_successor_index_ : 31;
1530 bool map_is_stable_ : 1;
1535 class HContext FINAL : public HTemplateInstruction<0> {
1537 static HContext* New(Zone* zone) {
1538 return new(zone) HContext();
1541 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1542 return Representation::None();
1545 DECLARE_CONCRETE_INSTRUCTION(Context)
1548 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
1552 set_representation(Representation::Tagged());
1556 virtual bool IsDeletable() const OVERRIDE { return true; }
1560 class HReturn FINAL : public HTemplateControlInstruction<0, 3> {
1562 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HReturn, HValue*, HValue*);
1563 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HReturn, HValue*);
1565 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1566 // TODO(titzer): require an Int32 input for faster returns.
1567 if (index == 2) return Representation::Smi();
1568 return Representation::Tagged();
1571 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1573 HValue* value() const { return OperandAt(0); }
1574 HValue* context() const { return OperandAt(1); }
1575 HValue* parameter_count() const { return OperandAt(2); }
1577 DECLARE_CONCRETE_INSTRUCTION(Return)
1580 HReturn(HValue* context, HValue* value, HValue* parameter_count = 0) {
1581 SetOperandAt(0, value);
1582 SetOperandAt(1, context);
1583 SetOperandAt(2, parameter_count);
1588 class HAbnormalExit FINAL : public HTemplateControlInstruction<0, 0> {
1590 DECLARE_INSTRUCTION_FACTORY_P0(HAbnormalExit);
1592 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1593 return Representation::None();
1596 DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
1602 class HUnaryOperation : public HTemplateInstruction<1> {
1604 explicit HUnaryOperation(HValue* value, HType type = HType::Tagged())
1605 : HTemplateInstruction<1>(type) {
1606 SetOperandAt(0, value);
1609 static HUnaryOperation* cast(HValue* value) {
1610 return reinterpret_cast<HUnaryOperation*>(value);
1613 HValue* value() const { return OperandAt(0); }
1614 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1618 class HUseConst FINAL : public HUnaryOperation {
1620 DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue*);
1622 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1623 return Representation::None();
1626 DECLARE_CONCRETE_INSTRUCTION(UseConst)
1629 explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
1633 class HForceRepresentation FINAL : public HTemplateInstruction<1> {
1635 static HInstruction* New(Zone* zone, HValue* context, HValue* value,
1636 Representation required_representation);
1638 HValue* value() const { return OperandAt(0); }
1640 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1641 return representation(); // Same as the output representation.
1644 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1646 DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
1649 HForceRepresentation(HValue* value, Representation required_representation) {
1650 SetOperandAt(0, value);
1651 set_representation(required_representation);
1656 class HChange FINAL : public HUnaryOperation {
1658 HChange(HValue* value,
1660 bool is_truncating_to_smi,
1661 bool is_truncating_to_int32)
1662 : HUnaryOperation(value) {
1663 DCHECK(!value->representation().IsNone());
1664 DCHECK(!to.IsNone());
1665 DCHECK(!value->representation().Equals(to));
1666 set_representation(to);
1668 SetFlag(kCanOverflow);
1669 if (is_truncating_to_smi && to.IsSmi()) {
1670 SetFlag(kTruncatingToSmi);
1671 SetFlag(kTruncatingToInt32);
1673 if (is_truncating_to_int32) SetFlag(kTruncatingToInt32);
1674 if (value->representation().IsSmi() || value->type().IsSmi()) {
1675 set_type(HType::Smi());
1677 set_type(HType::TaggedNumber());
1678 if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
1682 bool can_convert_undefined_to_nan() {
1683 return CheckUsesForFlag(kAllowUndefinedAsNaN);
1686 virtual HType CalculateInferredType() OVERRIDE;
1687 virtual HValue* Canonicalize() OVERRIDE;
1689 Representation from() const { return value()->representation(); }
1690 Representation to() const { return representation(); }
1691 bool deoptimize_on_minus_zero() const {
1692 return CheckFlag(kBailoutOnMinusZero);
1694 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1698 virtual Range* InferRange(Zone* zone) OVERRIDE;
1700 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1702 DECLARE_CONCRETE_INSTRUCTION(Change)
1705 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
1708 virtual bool IsDeletable() const OVERRIDE {
1709 return !from().IsTagged() || value()->type().IsSmi();
1714 class HClampToUint8 FINAL : public HUnaryOperation {
1716 DECLARE_INSTRUCTION_FACTORY_P1(HClampToUint8, HValue*);
1718 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1719 return Representation::None();
1722 DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
1725 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
1728 explicit HClampToUint8(HValue* value)
1729 : HUnaryOperation(value) {
1730 set_representation(Representation::Integer32());
1731 SetFlag(kAllowUndefinedAsNaN);
1735 virtual bool IsDeletable() const OVERRIDE { return true; }
1739 class HDoubleBits FINAL : public HUnaryOperation {
1741 enum Bits { HIGH, LOW };
1742 DECLARE_INSTRUCTION_FACTORY_P2(HDoubleBits, HValue*, Bits);
1744 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1745 return Representation::Double();
1748 DECLARE_CONCRETE_INSTRUCTION(DoubleBits)
1750 Bits bits() { return bits_; }
1753 virtual bool DataEquals(HValue* other) OVERRIDE {
1754 return other->IsDoubleBits() && HDoubleBits::cast(other)->bits() == bits();
1758 HDoubleBits(HValue* value, Bits bits)
1759 : HUnaryOperation(value), bits_(bits) {
1760 set_representation(Representation::Integer32());
1764 virtual bool IsDeletable() const OVERRIDE { return true; }
1770 class HConstructDouble FINAL : public HTemplateInstruction<2> {
1772 DECLARE_INSTRUCTION_FACTORY_P2(HConstructDouble, HValue*, HValue*);
1774 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1775 return Representation::Integer32();
1778 DECLARE_CONCRETE_INSTRUCTION(ConstructDouble)
1780 HValue* hi() { return OperandAt(0); }
1781 HValue* lo() { return OperandAt(1); }
1784 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
1787 explicit HConstructDouble(HValue* hi, HValue* lo) {
1788 set_representation(Representation::Double());
1790 SetOperandAt(0, hi);
1791 SetOperandAt(1, lo);
1794 virtual bool IsDeletable() const OVERRIDE { return true; }
1798 enum RemovableSimulate {
1804 class HSimulate FINAL : public HInstruction {
1806 HSimulate(BailoutId ast_id,
1809 RemovableSimulate removable)
1811 pop_count_(pop_count),
1813 assigned_indexes_(2, zone),
1815 removable_(removable),
1816 done_with_replay_(false) {}
1819 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1821 bool HasAstId() const { return !ast_id_.IsNone(); }
1822 BailoutId ast_id() const { return ast_id_; }
1823 void set_ast_id(BailoutId id) {
1824 DCHECK(!HasAstId());
1828 int pop_count() const { return pop_count_; }
1829 const ZoneList<HValue*>* values() const { return &values_; }
1830 int GetAssignedIndexAt(int index) const {
1831 DCHECK(HasAssignedIndexAt(index));
1832 return assigned_indexes_[index];
1834 bool HasAssignedIndexAt(int index) const {
1835 return assigned_indexes_[index] != kNoIndex;
1837 void AddAssignedValue(int index, HValue* value) {
1838 AddValue(index, value);
1840 void AddPushedValue(HValue* value) {
1841 AddValue(kNoIndex, value);
1843 int ToOperandIndex(int environment_index) {
1844 for (int i = 0; i < assigned_indexes_.length(); ++i) {
1845 if (assigned_indexes_[i] == environment_index) return i;
1849 virtual int OperandCount() const OVERRIDE { return values_.length(); }
1850 virtual HValue* OperandAt(int index) const OVERRIDE {
1851 return values_[index];
1854 virtual bool HasEscapingOperandAt(int index) OVERRIDE { return false; }
1855 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1856 return Representation::None();
1859 void MergeWith(ZoneList<HSimulate*>* list);
1860 bool is_candidate_for_removal() { return removable_ == REMOVABLE_SIMULATE; }
1862 // Replay effects of this instruction on the given environment.
1863 void ReplayEnvironment(HEnvironment* env);
1865 DECLARE_CONCRETE_INSTRUCTION(Simulate)
1868 virtual void Verify() OVERRIDE;
1869 void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
1870 Handle<JSFunction> closure() const { return closure_; }
1874 virtual void InternalSetOperandAt(int index, HValue* value) OVERRIDE {
1875 values_[index] = value;
1879 static const int kNoIndex = -1;
1880 void AddValue(int index, HValue* value) {
1881 assigned_indexes_.Add(index, zone_);
1882 // Resize the list of pushed values.
1883 values_.Add(NULL, zone_);
1884 // Set the operand through the base method in HValue to make sure that the
1885 // use lists are correctly updated.
1886 SetOperandAt(values_.length() - 1, value);
1888 bool HasValueForIndex(int index) {
1889 for (int i = 0; i < assigned_indexes_.length(); ++i) {
1890 if (assigned_indexes_[i] == index) return true;
1896 ZoneList<HValue*> values_;
1897 ZoneList<int> assigned_indexes_;
1899 RemovableSimulate removable_ : 2;
1900 bool done_with_replay_ : 1;
1903 Handle<JSFunction> closure_;
1908 class HEnvironmentMarker FINAL : public HTemplateInstruction<1> {
1910 enum Kind { BIND, LOOKUP };
1912 DECLARE_INSTRUCTION_FACTORY_P2(HEnvironmentMarker, Kind, int);
1914 Kind kind() const { return kind_; }
1915 int index() const { return index_; }
1916 HSimulate* next_simulate() { return next_simulate_; }
1917 void set_next_simulate(HSimulate* simulate) {
1918 next_simulate_ = simulate;
1921 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1922 return Representation::None();
1925 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
1928 void set_closure(Handle<JSFunction> closure) {
1929 DCHECK(closure_.is_null());
1930 DCHECK(!closure.is_null());
1933 Handle<JSFunction> closure() const { return closure_; }
1936 DECLARE_CONCRETE_INSTRUCTION(EnvironmentMarker);
1939 HEnvironmentMarker(Kind kind, int index)
1940 : kind_(kind), index_(index), next_simulate_(NULL) { }
1944 HSimulate* next_simulate_;
1947 Handle<JSFunction> closure_;
1952 class HStackCheck FINAL : public HTemplateInstruction<1> {
1959 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HStackCheck, Type);
1961 HValue* context() { return OperandAt(0); }
1963 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
1964 return Representation::Tagged();
1968 // The stack check eliminator might try to eliminate the same stack
1969 // check instruction multiple times.
1971 DeleteAndReplaceWith(NULL);
1975 bool is_function_entry() { return type_ == kFunctionEntry; }
1976 bool is_backwards_branch() { return type_ == kBackwardsBranch; }
1978 DECLARE_CONCRETE_INSTRUCTION(StackCheck)
1981 HStackCheck(HValue* context, Type type) : type_(type) {
1982 SetOperandAt(0, context);
1983 SetChangesFlag(kNewSpacePromotion);
1991 NORMAL_RETURN, // Drop the function from the environment on return.
1992 CONSTRUCT_CALL_RETURN, // Either use allocated receiver or return value.
1993 GETTER_CALL_RETURN, // Returning from a getter, need to restore context.
1994 SETTER_CALL_RETURN // Use the RHS of the assignment as the return value.
1998 class HArgumentsObject;
2002 class HEnterInlined FINAL : public HTemplateInstruction<0> {
2004 static HEnterInlined* New(Zone* zone, HValue* context, BailoutId return_id,
2005 Handle<JSFunction> closure,
2006 HConstant* closure_context, int arguments_count,
2007 FunctionLiteral* function,
2008 InliningKind inlining_kind, Variable* arguments_var,
2009 HArgumentsObject* arguments_object) {
2010 return new (zone) HEnterInlined(return_id, closure, closure_context,
2011 arguments_count, function, inlining_kind,
2012 arguments_var, arguments_object, zone);
2015 void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
2016 ZoneList<HBasicBlock*>* return_targets() { return &return_targets_; }
2018 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2020 Handle<JSFunction> closure() const { return closure_; }
2021 HConstant* closure_context() const { return closure_context_; }
2022 int arguments_count() const { return arguments_count_; }
2023 bool arguments_pushed() const { return arguments_pushed_; }
2024 void set_arguments_pushed() { arguments_pushed_ = true; }
2025 FunctionLiteral* function() const { return function_; }
2026 InliningKind inlining_kind() const { return inlining_kind_; }
2027 BailoutId ReturnId() const { return return_id_; }
2029 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
2030 return Representation::None();
2033 Variable* arguments_var() { return arguments_var_; }
2034 HArgumentsObject* arguments_object() { return arguments_object_; }
2036 DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
2039 HEnterInlined(BailoutId return_id, Handle<JSFunction> closure,
2040 HConstant* closure_context, int arguments_count,
2041 FunctionLiteral* function, InliningKind inlining_kind,
2042 Variable* arguments_var, HArgumentsObject* arguments_object,
2044 : return_id_(return_id),
2046 closure_context_(closure_context),
2047 arguments_count_(arguments_count),
2048 arguments_pushed_(false),
2049 function_(function),
2050 inlining_kind_(inlining_kind),
2051 arguments_var_(arguments_var),
2052 arguments_object_(arguments_object),
2053 return_targets_(2, zone) {}
2055 BailoutId return_id_;
2056 Handle<JSFunction> closure_;
2057 HConstant* closure_context_;
2058 int arguments_count_;
2059 bool arguments_pushed_;
2060 FunctionLiteral* function_;
2061 InliningKind inlining_kind_;
2062 Variable* arguments_var_;
2063 HArgumentsObject* arguments_object_;
2064 ZoneList<HBasicBlock*> return_targets_;
2068 class HLeaveInlined FINAL : public HTemplateInstruction<0> {
2070 HLeaveInlined(HEnterInlined* entry,
2073 drop_count_(drop_count) { }
2075 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
2076 return Representation::None();
2079 virtual int argument_delta() const OVERRIDE {
2080 return entry_->arguments_pushed() ? -drop_count_ : 0;
2083 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
2086 HEnterInlined* entry_;
2091 class HPushArguments FINAL : public HInstruction {
2093 static HPushArguments* New(Zone* zone, HValue* context) {
2094 return new(zone) HPushArguments(zone);
2096 static HPushArguments* New(Zone* zone, HValue* context, HValue* arg1) {
2097 HPushArguments* instr = new(zone) HPushArguments(zone);
2098 instr->AddInput(arg1);
2101 static HPushArguments* New(Zone* zone, HValue* context, HValue* arg1,
2103 HPushArguments* instr = new(zone) HPushArguments(zone);
2104 instr->AddInput(arg1);
2105 instr->AddInput(arg2);
2108 static HPushArguments* New(Zone* zone, HValue* context, HValue* arg1,
2109 HValue* arg2, HValue* arg3) {
2110 HPushArguments* instr = new(zone) HPushArguments(zone);
2111 instr->AddInput(arg1);
2112 instr->AddInput(arg2);
2113 instr->AddInput(arg3);
2116 static HPushArguments* New(Zone* zone, HValue* context, HValue* arg1,
2117 HValue* arg2, HValue* arg3, HValue* arg4) {
2118 HPushArguments* instr = new(zone) HPushArguments(zone);
2119 instr->AddInput(arg1);
2120 instr->AddInput(arg2);
2121 instr->AddInput(arg3);
2122 instr->AddInput(arg4);
2126 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
2127 return Representation::Tagged();
2130 virtual int argument_delta() const OVERRIDE { return inputs_.length(); }
2131 HValue* argument(int i) { return OperandAt(i); }
2133 virtual int OperandCount() const FINAL OVERRIDE {
2134 return inputs_.length();
2136 virtual HValue* OperandAt(int i) const FINAL OVERRIDE {
2140 void AddInput(HValue* value);
2142 DECLARE_CONCRETE_INSTRUCTION(PushArguments)
2145 virtual void InternalSetOperandAt(int i, HValue* value) FINAL OVERRIDE {
2150 explicit HPushArguments(Zone* zone)
2151 : HInstruction(HType::Tagged()), inputs_(4, zone) {
2152 set_representation(Representation::Tagged());
2155 ZoneList<HValue*> inputs_;
2159 class HThisFunction FINAL : public HTemplateInstruction<0> {
2161 DECLARE_INSTRUCTION_FACTORY_P0(HThisFunction);
2163 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
2164 return Representation::None();
2167 DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
2170 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
2174 set_representation(Representation::Tagged());
2178 virtual bool IsDeletable() const OVERRIDE { return true; }
2182 class HDeclareGlobals FINAL : public HUnaryOperation {
2184 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HDeclareGlobals,
2188 HValue* context() { return OperandAt(0); }
2189 Handle<FixedArray> pairs() const { return pairs_; }
2190 int flags() const { return flags_; }
2192 DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
2194 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
2195 return Representation::Tagged();
2199 HDeclareGlobals(HValue* context,
2200 Handle<FixedArray> pairs,
2202 : HUnaryOperation(context),
2205 set_representation(Representation::Tagged());
2206 SetAllSideEffects();
2209 Handle<FixedArray> pairs_;
2215 class HCall : public HTemplateInstruction<V> {
2217 // The argument count includes the receiver.
2218 explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
2219 this->set_representation(Representation::Tagged());
2220 this->SetAllSideEffects();
2223 virtual HType CalculateInferredType() FINAL OVERRIDE {
2224 return HType::Tagged();
2227 virtual int argument_count() const {
2228 return argument_count_;
2231 virtual int argument_delta() const OVERRIDE {
2232 return -argument_count();
2236 int argument_count_;
2240 class HUnaryCall : public HCall<1> {
2242 HUnaryCall(HValue* value, int argument_count)
2243 : HCall<1>(argument_count) {
2244 SetOperandAt(0, value);
2247 virtual Representation RequiredInputRepresentation(
2248 int index) FINAL OVERRIDE {
2249 return Representation::Tagged();
2252 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2254 HValue* value() const { return OperandAt(0); }
2258 class HBinaryCall : public HCall<2> {
2260 HBinaryCall(HValue* first, HValue* second, int argument_count)
2261 : HCall<2>(argument_count) {
2262 SetOperandAt(0, first);
2263 SetOperandAt(1, second);
2266 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2268 virtual Representation RequiredInputRepresentation(
2269 int index) FINAL OVERRIDE {
2270 return Representation::Tagged();
2273 HValue* first() const { return OperandAt(0); }
2274 HValue* second() const { return OperandAt(1); }
2278 class HCallJSFunction FINAL : public HCall<1> {
2280 static HCallJSFunction* New(Zone* zone,
2284 bool pass_argument_count);
2286 HValue* function() const { return OperandAt(0); }
2288 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2290 virtual Representation RequiredInputRepresentation(
2291 int index) FINAL OVERRIDE {
2293 return Representation::Tagged();
2296 bool pass_argument_count() const { return pass_argument_count_; }
2298 virtual bool HasStackCheck() FINAL OVERRIDE {
2299 return has_stack_check_;
2302 DECLARE_CONCRETE_INSTRUCTION(CallJSFunction)
2305 // The argument count includes the receiver.
2306 HCallJSFunction(HValue* function,
2308 bool pass_argument_count,
2309 bool has_stack_check)
2310 : HCall<1>(argument_count),
2311 pass_argument_count_(pass_argument_count),
2312 has_stack_check_(has_stack_check) {
2313 SetOperandAt(0, function);
2316 bool pass_argument_count_;
2317 bool has_stack_check_;
2321 class HCallWithDescriptor FINAL : public HInstruction {
2323 static HCallWithDescriptor* New(Zone* zone, HValue* context, HValue* target,
2325 CallInterfaceDescriptor descriptor,
2326 const Vector<HValue*>& operands) {
2327 DCHECK(operands.length() == descriptor.GetEnvironmentLength());
2328 HCallWithDescriptor* res = new (zone)
2329 HCallWithDescriptor(target, argument_count, descriptor, operands, zone);
2333 virtual int OperandCount() const FINAL OVERRIDE {
2334 return values_.length();
2336 virtual HValue* OperandAt(int index) const FINAL OVERRIDE {
2337 return values_[index];
2340 virtual Representation RequiredInputRepresentation(
2341 int index) FINAL OVERRIDE {
2343 return Representation::Tagged();
2345 int par_index = index - 1;
2346 DCHECK(par_index < descriptor_.GetEnvironmentLength());
2347 return descriptor_.GetParameterRepresentation(par_index);
2351 DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor)
2353 virtual HType CalculateInferredType() FINAL OVERRIDE {
2354 return HType::Tagged();
2357 virtual int argument_count() const {
2358 return argument_count_;
2361 virtual int argument_delta() const OVERRIDE {
2362 return -argument_count_;
2365 CallInterfaceDescriptor descriptor() const { return descriptor_; }
2368 return OperandAt(0);
2371 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2374 // The argument count includes the receiver.
2375 HCallWithDescriptor(HValue* target, int argument_count,
2376 CallInterfaceDescriptor descriptor,
2377 const Vector<HValue*>& operands, Zone* zone)
2378 : descriptor_(descriptor),
2379 values_(descriptor.GetEnvironmentLength() + 1, zone) {
2380 argument_count_ = argument_count;
2381 AddOperand(target, zone);
2382 for (int i = 0; i < operands.length(); i++) {
2383 AddOperand(operands[i], zone);
2385 this->set_representation(Representation::Tagged());
2386 this->SetAllSideEffects();
2389 void AddOperand(HValue* v, Zone* zone) {
2390 values_.Add(NULL, zone);
2391 SetOperandAt(values_.length() - 1, v);
2394 void InternalSetOperandAt(int index,
2395 HValue* value) FINAL OVERRIDE {
2396 values_[index] = value;
2399 CallInterfaceDescriptor descriptor_;
2400 ZoneList<HValue*> values_;
2401 int argument_count_;
2405 class HInvokeFunction FINAL : public HBinaryCall {
2407 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInvokeFunction, HValue*, int);
2409 HInvokeFunction(HValue* context,
2411 Handle<JSFunction> known_function,
2413 : HBinaryCall(context, function, argument_count),
2414 known_function_(known_function) {
2415 formal_parameter_count_ = known_function.is_null()
2416 ? 0 : known_function->shared()->formal_parameter_count();
2417 has_stack_check_ = !known_function.is_null() &&
2418 (known_function->code()->kind() == Code::FUNCTION ||
2419 known_function->code()->kind() == Code::OPTIMIZED_FUNCTION);
2422 static HInvokeFunction* New(Zone* zone,
2425 Handle<JSFunction> known_function,
2426 int argument_count) {
2427 return new(zone) HInvokeFunction(context, function,
2428 known_function, argument_count);
2431 HValue* context() { return first(); }
2432 HValue* function() { return second(); }
2433 Handle<JSFunction> known_function() { return known_function_; }
2434 int formal_parameter_count() const { return formal_parameter_count_; }
2436 virtual bool HasStackCheck() FINAL OVERRIDE {
2437 return has_stack_check_;
2440 DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
2443 HInvokeFunction(HValue* context, HValue* function, int argument_count)
2444 : HBinaryCall(context, function, argument_count),
2445 has_stack_check_(false) {
2448 Handle<JSFunction> known_function_;
2449 int formal_parameter_count_;
2450 bool has_stack_check_;
2454 class HCallFunction FINAL : public HBinaryCall {
2456 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallFunction, HValue*, int);
2457 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(
2458 HCallFunction, HValue*, int, CallFunctionFlags);
2460 HValue* context() { return first(); }
2461 HValue* function() { return second(); }
2462 CallFunctionFlags function_flags() const { return function_flags_; }
2464 DECLARE_CONCRETE_INSTRUCTION(CallFunction)
2466 virtual int argument_delta() const OVERRIDE { return -argument_count(); }
2469 HCallFunction(HValue* context,
2472 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS)
2473 : HBinaryCall(context, function, argument_count), function_flags_(flags) {
2475 CallFunctionFlags function_flags_;
2479 class HCallNew FINAL : public HBinaryCall {
2481 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallNew, HValue*, int);
2483 HValue* context() { return first(); }
2484 HValue* constructor() { return second(); }
2486 DECLARE_CONCRETE_INSTRUCTION(CallNew)
2489 HCallNew(HValue* context, HValue* constructor, int argument_count)
2490 : HBinaryCall(context, constructor, argument_count) {}
2494 class HCallNewArray FINAL : public HBinaryCall {
2496 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCallNewArray,
2501 HValue* context() { return first(); }
2502 HValue* constructor() { return second(); }
2504 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2506 ElementsKind elements_kind() const { return elements_kind_; }
2508 DECLARE_CONCRETE_INSTRUCTION(CallNewArray)
2511 HCallNewArray(HValue* context, HValue* constructor, int argument_count,
2512 ElementsKind elements_kind)
2513 : HBinaryCall(context, constructor, argument_count),
2514 elements_kind_(elements_kind) {}
2516 ElementsKind elements_kind_;
2520 class HCallRuntime FINAL : public HCall<1> {
2522 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCallRuntime,
2524 const Runtime::Function*,
2527 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2529 HValue* context() { return OperandAt(0); }
2530 const Runtime::Function* function() const { return c_function_; }
2531 Handle<String> name() const { return name_; }
2532 SaveFPRegsMode save_doubles() const { return save_doubles_; }
2533 void set_save_doubles(SaveFPRegsMode save_doubles) {
2534 save_doubles_ = save_doubles;
2537 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
2538 return Representation::Tagged();
2541 DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
2544 HCallRuntime(HValue* context,
2545 Handle<String> name,
2546 const Runtime::Function* c_function,
2548 : HCall<1>(argument_count), c_function_(c_function), name_(name),
2549 save_doubles_(kDontSaveFPRegs) {
2550 SetOperandAt(0, context);
2553 const Runtime::Function* c_function_;
2554 Handle<String> name_;
2555 SaveFPRegsMode save_doubles_;
2559 class HMapEnumLength FINAL : public HUnaryOperation {
2561 DECLARE_INSTRUCTION_FACTORY_P1(HMapEnumLength, HValue*);
2563 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
2564 return Representation::Tagged();
2567 DECLARE_CONCRETE_INSTRUCTION(MapEnumLength)
2570 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
2573 explicit HMapEnumLength(HValue* value)
2574 : HUnaryOperation(value, HType::Smi()) {
2575 set_representation(Representation::Smi());
2577 SetDependsOnFlag(kMaps);
2580 virtual bool IsDeletable() const OVERRIDE { return true; }
2584 class HUnaryMathOperation FINAL : public HTemplateInstruction<2> {
2586 static HInstruction* New(Zone* zone,
2589 BuiltinFunctionId op);
2591 HValue* context() const { return OperandAt(0); }
2592 HValue* value() const { return OperandAt(1); }
2594 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2596 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
2598 return Representation::Tagged();
2608 return Representation::Double();
2610 return representation();
2612 return Representation::Integer32();
2615 return Representation::None();
2620 virtual Range* InferRange(Zone* zone) OVERRIDE;
2622 virtual HValue* Canonicalize() OVERRIDE;
2623 virtual Representation RepresentationFromUses() OVERRIDE;
2624 virtual Representation RepresentationFromInputs() OVERRIDE;
2626 BuiltinFunctionId op() const { return op_; }
2627 const char* OpName() const;
2629 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
2632 virtual bool DataEquals(HValue* other) OVERRIDE {
2633 HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
2634 return op_ == b->op();
2638 // Indicates if we support a double (and int32) output for Math.floor and
2640 bool SupportsFlexibleFloorAndRound() const {
2641 #ifdef V8_TARGET_ARCH_ARM64
2647 HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
2648 : HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
2649 SetOperandAt(0, context);
2650 SetOperandAt(1, value);
2654 if (SupportsFlexibleFloorAndRound()) {
2655 SetFlag(kFlexibleRepresentation);
2657 set_representation(Representation::Integer32());
2661 set_representation(Representation::Integer32());
2664 // Not setting representation here: it is None intentionally.
2665 SetFlag(kFlexibleRepresentation);
2666 // TODO(svenpanne) This flag is actually only needed if representation()
2667 // is tagged, and not when it is an unboxed double or unboxed integer.
2668 SetChangesFlag(kNewSpacePromotion);
2675 set_representation(Representation::Double());
2681 SetFlag(kAllowUndefinedAsNaN);
2684 virtual bool IsDeletable() const OVERRIDE { return true; }
2686 HValue* SimplifiedDividendForMathFloorOfDiv(HDiv* hdiv);
2687 HValue* SimplifiedDivisorForMathFloorOfDiv(HDiv* hdiv);
2689 BuiltinFunctionId op_;
2693 class HLoadRoot FINAL : public HTemplateInstruction<0> {
2695 DECLARE_INSTRUCTION_FACTORY_P1(HLoadRoot, Heap::RootListIndex);
2696 DECLARE_INSTRUCTION_FACTORY_P2(HLoadRoot, Heap::RootListIndex, HType);
2698 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
2699 return Representation::None();
2702 Heap::RootListIndex index() const { return index_; }
2704 DECLARE_CONCRETE_INSTRUCTION(LoadRoot)
2707 virtual bool DataEquals(HValue* other) OVERRIDE {
2708 HLoadRoot* b = HLoadRoot::cast(other);
2709 return index_ == b->index_;
2713 explicit HLoadRoot(Heap::RootListIndex index, HType type = HType::Tagged())
2714 : HTemplateInstruction<0>(type), index_(index) {
2716 // TODO(bmeurer): We'll need kDependsOnRoots once we add the
2717 // corresponding HStoreRoot instruction.
2718 SetDependsOnFlag(kCalls);
2721 virtual bool IsDeletable() const OVERRIDE { return true; }
2723 const Heap::RootListIndex index_;
2727 class HCheckMaps FINAL : public HTemplateInstruction<2> {
2729 static HCheckMaps* New(Zone* zone, HValue* context, HValue* value,
2730 Handle<Map> map, HValue* typecheck = NULL) {
2731 return new(zone) HCheckMaps(value, new(zone) UniqueSet<Map>(
2732 Unique<Map>::CreateImmovable(map), zone), typecheck);
2734 static HCheckMaps* New(Zone* zone, HValue* context,
2735 HValue* value, SmallMapList* map_list,
2736 HValue* typecheck = NULL) {
2737 UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone);
2738 for (int i = 0; i < map_list->length(); ++i) {
2739 maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone);
2741 return new(zone) HCheckMaps(value, maps, typecheck);
2744 bool IsStabilityCheck() const { return is_stability_check_; }
2745 void MarkAsStabilityCheck() {
2746 maps_are_stable_ = true;
2747 has_migration_target_ = false;
2748 is_stability_check_ = true;
2749 ClearChangesFlag(kNewSpacePromotion);
2750 ClearDependsOnFlag(kElementsKind);
2751 ClearDependsOnFlag(kMaps);
2754 virtual bool HasEscapingOperandAt(int index) OVERRIDE { return false; }
2755 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
2756 return Representation::Tagged();
2759 virtual HType CalculateInferredType() OVERRIDE {
2760 if (value()->type().IsHeapObject()) return value()->type();
2761 return HType::HeapObject();
2764 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2766 HValue* value() const { return OperandAt(0); }
2767 HValue* typecheck() const { return OperandAt(1); }
2769 const UniqueSet<Map>* maps() const { return maps_; }
2770 void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; }
2772 bool maps_are_stable() const { return maps_are_stable_; }
2774 bool HasMigrationTarget() const { return has_migration_target_; }
2776 virtual HValue* Canonicalize() OVERRIDE;
2778 static HCheckMaps* CreateAndInsertAfter(Zone* zone,
2782 HInstruction* instr) {
2783 return instr->Append(new(zone) HCheckMaps(
2784 value, new(zone) UniqueSet<Map>(map, zone), map_is_stable));
2787 static HCheckMaps* CreateAndInsertBefore(Zone* zone,
2789 const UniqueSet<Map>* maps,
2790 bool maps_are_stable,
2791 HInstruction* instr) {
2792 return instr->Prepend(new(zone) HCheckMaps(value, maps, maps_are_stable));
2795 DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
2798 virtual bool DataEquals(HValue* other) OVERRIDE {
2799 return this->maps()->Equals(HCheckMaps::cast(other)->maps());
2802 virtual int RedefinedOperandIndex() { return 0; }
2805 HCheckMaps(HValue* value, const UniqueSet<Map>* maps, bool maps_are_stable)
2806 : HTemplateInstruction<2>(HType::HeapObject()), maps_(maps),
2807 has_migration_target_(false), is_stability_check_(false),
2808 maps_are_stable_(maps_are_stable) {
2809 DCHECK_NE(0, maps->size());
2810 SetOperandAt(0, value);
2811 // Use the object value for the dependency.
2812 SetOperandAt(1, value);
2813 set_representation(Representation::Tagged());
2815 SetDependsOnFlag(kMaps);
2816 SetDependsOnFlag(kElementsKind);
2819 HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck)
2820 : HTemplateInstruction<2>(HType::HeapObject()), maps_(maps),
2821 has_migration_target_(false), is_stability_check_(false),
2822 maps_are_stable_(true) {
2823 DCHECK_NE(0, maps->size());
2824 SetOperandAt(0, value);
2825 // Use the object value for the dependency if NULL is passed.
2826 SetOperandAt(1, typecheck ? typecheck : value);
2827 set_representation(Representation::Tagged());
2829 SetDependsOnFlag(kMaps);
2830 SetDependsOnFlag(kElementsKind);
2831 for (int i = 0; i < maps->size(); ++i) {
2832 Handle<Map> map = maps->at(i).handle();
2833 if (map->is_migration_target()) has_migration_target_ = true;
2834 if (!map->is_stable()) maps_are_stable_ = false;
2836 if (has_migration_target_) SetChangesFlag(kNewSpacePromotion);
2839 const UniqueSet<Map>* maps_;
2840 bool has_migration_target_ : 1;
2841 bool is_stability_check_ : 1;
2842 bool maps_are_stable_ : 1;
2846 class HCheckValue FINAL : public HUnaryOperation {
2848 static HCheckValue* New(Zone* zone, HValue* context,
2849 HValue* value, Handle<JSFunction> func) {
2850 bool in_new_space = zone->isolate()->heap()->InNewSpace(*func);
2851 // NOTE: We create an uninitialized Unique and initialize it later.
2852 // This is because a JSFunction can move due to GC during graph creation.
2853 // TODO(titzer): This is a migration crutch. Replace with some kind of
2854 // Uniqueness scope later.
2855 Unique<JSFunction> target = Unique<JSFunction>::CreateUninitialized(func);
2856 HCheckValue* check = new(zone) HCheckValue(value, target, in_new_space);
2859 static HCheckValue* New(Zone* zone, HValue* context,
2860 HValue* value, Unique<HeapObject> target,
2861 bool object_in_new_space) {
2862 return new(zone) HCheckValue(value, target, object_in_new_space);
2865 virtual void FinalizeUniqueness() OVERRIDE {
2866 object_ = Unique<HeapObject>(object_.handle());
2869 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
2870 return Representation::Tagged();
2872 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2874 virtual HValue* Canonicalize() OVERRIDE;
2877 virtual void Verify() OVERRIDE;
2880 Unique<HeapObject> object() const { return object_; }
2881 bool object_in_new_space() const { return object_in_new_space_; }
2883 DECLARE_CONCRETE_INSTRUCTION(CheckValue)
2886 virtual bool DataEquals(HValue* other) OVERRIDE {
2887 HCheckValue* b = HCheckValue::cast(other);
2888 return object_ == b->object_;
2892 HCheckValue(HValue* value, Unique<HeapObject> object,
2893 bool object_in_new_space)
2894 : HUnaryOperation(value, value->type()),
2896 object_in_new_space_(object_in_new_space) {
2897 set_representation(Representation::Tagged());
2901 Unique<HeapObject> object_;
2902 bool object_in_new_space_;
2906 class HCheckInstanceType FINAL : public HUnaryOperation {
2912 IS_INTERNALIZED_STRING,
2913 LAST_INTERVAL_CHECK = IS_JS_ARRAY
2916 DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue*, Check);
2918 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
2920 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
2921 return Representation::Tagged();
2924 virtual HType CalculateInferredType() OVERRIDE {
2926 case IS_SPEC_OBJECT: return HType::JSObject();
2927 case IS_JS_ARRAY: return HType::JSArray();
2928 case IS_STRING: return HType::String();
2929 case IS_INTERNALIZED_STRING: return HType::String();
2932 return HType::Tagged();
2935 virtual HValue* Canonicalize() OVERRIDE;
2937 bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
2938 void GetCheckInterval(InstanceType* first, InstanceType* last);
2939 void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
2941 Check check() const { return check_; }
2943 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
2946 // TODO(ager): It could be nice to allow the ommision of instance
2947 // type checks if we have already performed an instance type check
2948 // with a larger range.
2949 virtual bool DataEquals(HValue* other) OVERRIDE {
2950 HCheckInstanceType* b = HCheckInstanceType::cast(other);
2951 return check_ == b->check_;
2954 virtual int RedefinedOperandIndex() { return 0; }
2957 const char* GetCheckName() const;
2959 HCheckInstanceType(HValue* value, Check check)
2960 : HUnaryOperation(value, HType::HeapObject()), check_(check) {
2961 set_representation(Representation::Tagged());
2969 class HCheckSmi FINAL : public HUnaryOperation {
2971 DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue*);
2973 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
2974 return Representation::Tagged();
2977 virtual HValue* Canonicalize() OVERRIDE {
2978 HType value_type = value()->type();
2979 if (value_type.IsSmi()) {
2985 DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
2988 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
2991 explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
2992 set_representation(Representation::Smi());
2998 class HCheckHeapObject FINAL : public HUnaryOperation {
3000 DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
3002 virtual bool HasEscapingOperandAt(int index) OVERRIDE { return false; }
3003 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
3004 return Representation::Tagged();
3007 virtual HType CalculateInferredType() OVERRIDE {
3008 if (value()->type().IsHeapObject()) return value()->type();
3009 return HType::HeapObject();
3013 virtual void Verify() OVERRIDE;
3016 virtual HValue* Canonicalize() OVERRIDE {
3017 return value()->type().IsHeapObject() ? NULL : this;
3020 DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
3023 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
3026 explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) {
3027 set_representation(Representation::Tagged());
3033 class InductionVariableData;
3036 struct InductionVariableLimitUpdate {
3037 InductionVariableData* updated_variable;
3039 bool limit_is_upper;
3040 bool limit_is_included;
3042 InductionVariableLimitUpdate()
3043 : updated_variable(NULL), limit(NULL),
3044 limit_is_upper(false), limit_is_included(false) {}
3053 class InductionVariableData FINAL : public ZoneObject {
3055 class InductionVariableCheck : public ZoneObject {
3057 HBoundsCheck* check() { return check_; }
3058 InductionVariableCheck* next() { return next_; }
3059 bool HasUpperLimit() { return upper_limit_ >= 0; }
3060 int32_t upper_limit() {
3061 DCHECK(HasUpperLimit());
3062 return upper_limit_;
3064 void set_upper_limit(int32_t upper_limit) {
3065 upper_limit_ = upper_limit;
3068 bool processed() { return processed_; }
3069 void set_processed() { processed_ = true; }
3071 InductionVariableCheck(HBoundsCheck* check,
3072 InductionVariableCheck* next,
3073 int32_t upper_limit = kNoLimit)
3074 : check_(check), next_(next), upper_limit_(upper_limit),
3075 processed_(false) {}
3078 HBoundsCheck* check_;
3079 InductionVariableCheck* next_;
3080 int32_t upper_limit_;
3084 class ChecksRelatedToLength : public ZoneObject {
3086 HValue* length() { return length_; }
3087 ChecksRelatedToLength* next() { return next_; }
3088 InductionVariableCheck* checks() { return checks_; }
3090 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3091 void CloseCurrentBlock();
3093 ChecksRelatedToLength(HValue* length, ChecksRelatedToLength* next)
3094 : length_(length), next_(next), checks_(NULL),
3095 first_check_in_block_(NULL),
3097 added_constant_(NULL),
3098 current_and_mask_in_block_(0),
3099 current_or_mask_in_block_(0) {}
3102 void UseNewIndexInCurrentBlock(Token::Value token,
3107 HBoundsCheck* first_check_in_block() { return first_check_in_block_; }
3108 HBitwise* added_index() { return added_index_; }
3109 void set_added_index(HBitwise* index) { added_index_ = index; }
3110 HConstant* added_constant() { return added_constant_; }
3111 void set_added_constant(HConstant* constant) { added_constant_ = constant; }
3112 int32_t current_and_mask_in_block() { return current_and_mask_in_block_; }
3113 int32_t current_or_mask_in_block() { return current_or_mask_in_block_; }
3114 int32_t current_upper_limit() { return current_upper_limit_; }
3117 ChecksRelatedToLength* next_;
3118 InductionVariableCheck* checks_;
3120 HBoundsCheck* first_check_in_block_;
3121 HBitwise* added_index_;
3122 HConstant* added_constant_;
3123 int32_t current_and_mask_in_block_;
3124 int32_t current_or_mask_in_block_;
3125 int32_t current_upper_limit_;
3128 struct LimitFromPredecessorBlock {
3129 InductionVariableData* variable;
3132 HBasicBlock* other_target;
3134 bool LimitIsValid() { return token != Token::ILLEGAL; }
3136 bool LimitIsIncluded() {
3137 return Token::IsEqualityOp(token) ||
3138 token == Token::GTE || token == Token::LTE;
3140 bool LimitIsUpper() {
3141 return token == Token::LTE || token == Token::LT || token == Token::NE;
3144 LimitFromPredecessorBlock()
3146 token(Token::ILLEGAL),
3148 other_target(NULL) {}
3151 static const int32_t kNoLimit = -1;
3153 static InductionVariableData* ExaminePhi(HPhi* phi);
3154 static void ComputeLimitFromPredecessorBlock(
3156 LimitFromPredecessorBlock* result);
3157 static bool ComputeInductionVariableLimit(
3159 InductionVariableLimitUpdate* additional_limit);
3161 struct BitwiseDecompositionResult {
3167 BitwiseDecompositionResult()
3168 : base(NULL), and_mask(0), or_mask(0), context(NULL) {}
3170 static void DecomposeBitwise(HValue* value,
3171 BitwiseDecompositionResult* result);
3173 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3175 bool CheckIfBranchIsLoopGuard(Token::Value token,
3176 HBasicBlock* current_branch,
3177 HBasicBlock* other_branch);
3179 void UpdateAdditionalLimit(InductionVariableLimitUpdate* update);
3181 HPhi* phi() { return phi_; }
3182 HValue* base() { return base_; }
3183 int32_t increment() { return increment_; }
3184 HValue* limit() { return limit_; }
3185 bool limit_included() { return limit_included_; }
3186 HBasicBlock* limit_validity() { return limit_validity_; }
3187 HBasicBlock* induction_exit_block() { return induction_exit_block_; }
3188 HBasicBlock* induction_exit_target() { return induction_exit_target_; }
3189 ChecksRelatedToLength* checks() { return checks_; }
3190 HValue* additional_upper_limit() { return additional_upper_limit_; }
3191 bool additional_upper_limit_is_included() {
3192 return additional_upper_limit_is_included_;
3194 HValue* additional_lower_limit() { return additional_lower_limit_; }
3195 bool additional_lower_limit_is_included() {
3196 return additional_lower_limit_is_included_;
3199 bool LowerLimitIsNonNegativeConstant() {
3200 if (base()->IsInteger32Constant() && base()->GetInteger32Constant() >= 0) {
3203 if (additional_lower_limit() != NULL &&
3204 additional_lower_limit()->IsInteger32Constant() &&
3205 additional_lower_limit()->GetInteger32Constant() >= 0) {
3206 // Ignoring the corner case of !additional_lower_limit_is_included()
3207 // is safe, handling it adds unneeded complexity.
3213 int32_t ComputeUpperLimit(int32_t and_mask, int32_t or_mask);
3216 template <class T> void swap(T* a, T* b) {
3222 InductionVariableData(HPhi* phi, HValue* base, int32_t increment)
3223 : phi_(phi), base_(IgnoreOsrValue(base)), increment_(increment),
3224 limit_(NULL), limit_included_(false), limit_validity_(NULL),
3225 induction_exit_block_(NULL), induction_exit_target_(NULL),
3227 additional_upper_limit_(NULL),
3228 additional_upper_limit_is_included_(false),
3229 additional_lower_limit_(NULL),
3230 additional_lower_limit_is_included_(false) {}
3232 static int32_t ComputeIncrement(HPhi* phi, HValue* phi_operand);
3234 static HValue* IgnoreOsrValue(HValue* v);
3235 static InductionVariableData* GetInductionVariableData(HValue* v);
3241 bool limit_included_;
3242 HBasicBlock* limit_validity_;
3243 HBasicBlock* induction_exit_block_;
3244 HBasicBlock* induction_exit_target_;
3245 ChecksRelatedToLength* checks_;
3246 HValue* additional_upper_limit_;
3247 bool additional_upper_limit_is_included_;
3248 HValue* additional_lower_limit_;
3249 bool additional_lower_limit_is_included_;
3253 class HPhi FINAL : public HValue {
3255 HPhi(int merged_index, Zone* zone)
3257 merged_index_(merged_index),
3259 induction_variable_data_(NULL) {
3260 for (int i = 0; i < Representation::kNumRepresentations; i++) {
3261 non_phi_uses_[i] = 0;
3262 indirect_uses_[i] = 0;
3264 DCHECK(merged_index >= 0 || merged_index == kInvalidMergedIndex);
3265 SetFlag(kFlexibleRepresentation);
3266 SetFlag(kAllowUndefinedAsNaN);
3269 virtual Representation RepresentationFromInputs() OVERRIDE;
3271 virtual Range* InferRange(Zone* zone) OVERRIDE;
3272 virtual void InferRepresentation(
3273 HInferRepresentationPhase* h_infer) OVERRIDE;
3274 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
3275 return representation();
3277 virtual Representation KnownOptimalRepresentation() OVERRIDE {
3278 return representation();
3280 virtual HType CalculateInferredType() OVERRIDE;
3281 virtual int OperandCount() const OVERRIDE { return inputs_.length(); }
3282 virtual HValue* OperandAt(int index) const OVERRIDE {
3283 return inputs_[index];
3285 HValue* GetRedundantReplacement();
3286 void AddInput(HValue* value);
3289 bool IsReceiver() const { return merged_index_ == 0; }
3290 bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
3292 virtual HSourcePosition position() const OVERRIDE;
3294 int merged_index() const { return merged_index_; }
3296 InductionVariableData* induction_variable_data() {
3297 return induction_variable_data_;
3299 bool IsInductionVariable() {
3300 return induction_variable_data_ != NULL;
3302 bool IsLimitedInductionVariable() {
3303 return IsInductionVariable() &&
3304 induction_variable_data_->limit() != NULL;
3306 void DetectInductionVariable() {
3307 DCHECK(induction_variable_data_ == NULL);
3308 induction_variable_data_ = InductionVariableData::ExaminePhi(this);
3311 virtual OStream& PrintTo(OStream& os) const OVERRIDE; // NOLINT
3314 virtual void Verify() OVERRIDE;
3317 void InitRealUses(int id);
3318 void AddNonPhiUsesFrom(HPhi* other);
3319 void AddIndirectUsesTo(int* use_count);
3321 int tagged_non_phi_uses() const {
3322 return non_phi_uses_[Representation::kTagged];
3324 int smi_non_phi_uses() const {
3325 return non_phi_uses_[Representation::kSmi];
3327 int int32_non_phi_uses() const {
3328 return non_phi_uses_[Representation::kInteger32];
3330 int double_non_phi_uses() const {
3331 return non_phi_uses_[Representation::kDouble];
3333 int tagged_indirect_uses() const {
3334 return indirect_uses_[Representation::kTagged];
3336 int smi_indirect_uses() const {
3337 return indirect_uses_[Representation::kSmi];
3339 int int32_indirect_uses() const {
3340 return indirect_uses_[Representation::kInteger32];
3342 int double_indirect_uses() const {
3343 return indirect_uses_[Representation::kDouble];
3345 int phi_id() { return phi_id_; }
3347 static HPhi* cast(HValue* value) {
3348 DCHECK(value->IsPhi());
3349 return reinterpret_cast<HPhi*>(value);
3351 virtual Opcode opcode() const OVERRIDE { return HValue::kPhi; }
3353 void SimplifyConstantInputs();
3355 // Marker value representing an invalid merge index.
3356 static const int kInvalidMergedIndex = -1;
3359 virtual void DeleteFromGraph() OVERRIDE;
3360 virtual void InternalSetOperandAt(int index, HValue* value) OVERRIDE {
3361 inputs_[index] = value;
3365 ZoneList<HValue*> inputs_;
3368 int non_phi_uses_[Representation::kNumRepresentations];
3369 int indirect_uses_[Representation::kNumRepresentations];
3371 InductionVariableData* induction_variable_data_;
3373 // TODO(titzer): we can't eliminate the receiver for generating backtraces
3374 virtual bool IsDeletable() const OVERRIDE { return !IsReceiver(); }
3378 // Common base class for HArgumentsObject and HCapturedObject.
3379 class HDematerializedObject : public HInstruction {
3381 HDematerializedObject(int count, Zone* zone) : values_(count, zone) {}
3383 virtual int OperandCount() const FINAL OVERRIDE {
3384 return values_.length();
3386 virtual HValue* OperandAt(int index) const FINAL OVERRIDE {
3387 return values_[index];
3390 virtual bool HasEscapingOperandAt(int index) FINAL OVERRIDE {
3393 virtual Representation RequiredInputRepresentation(
3394 int index) FINAL OVERRIDE {
3395 return Representation::None();
3399 virtual void InternalSetOperandAt(int index,
3400 HValue* value) FINAL OVERRIDE {
3401 values_[index] = value;
3404 // List of values tracked by this marker.
3405 ZoneList<HValue*> values_;
3409 class HArgumentsObject FINAL : public HDematerializedObject {
3411 static HArgumentsObject* New(Zone* zone, HValue* context, int count) {
3412 return new(zone) HArgumentsObject(count, zone);
3415 // The values contain a list of all elements in the arguments object
3416 // including the receiver object, which is skipped when materializing.
3417 const ZoneList<HValue*>* arguments_values() const { return &values_; }
3418 int arguments_count() const { return values_.length(); }
3420 void AddArgument(HValue* argument, Zone* zone) {
3421 values_.Add(NULL, zone); // Resize list.
3422 SetOperandAt(values_.length() - 1, argument);
3425 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
3428 HArgumentsObject(int count, Zone* zone)
3429 : HDematerializedObject(count, zone) {
3430 set_representation(Representation::Tagged());
3431 SetFlag(kIsArguments);
3436 class HCapturedObject FINAL : public HDematerializedObject {
3438 HCapturedObject(int length, int id, Zone* zone)
3439 : HDematerializedObject(length, zone), capture_id_(id) {
3440 set_representation(Representation::Tagged());
3441 values_.AddBlock(NULL, length, zone); // Resize list.
3444 // The values contain a list of all in-object properties inside the
3445 // captured object and is index by field index. Properties in the
3446 // properties or elements backing store are not tracked here.
3447 const ZoneList<HValue*>* values() const { return &values_; }
3448 int length() const { return values_.length(); }
3449 int capture_id() const { return capture_id_; }
3451 // Shortcut for the map value of this captured object.
3452 HValue* map_value() const { return values()->first(); }
3454 void ReuseSideEffectsFromStore(HInstruction* store) {
3455 DCHECK(store->HasObservableSideEffects());
3456 DCHECK(store->IsStoreNamedField());
3457 changes_flags_.Add(store->ChangesFlags());
3460 // Replay effects of this instruction on the given environment.
3461 void ReplayEnvironment(HEnvironment* env);
3463 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
3465 DECLARE_CONCRETE_INSTRUCTION(CapturedObject)
3470 // Note that we cannot DCE captured objects as they are used to replay
3471 // the environment. This method is here as an explicit reminder.
3472 // TODO(mstarzinger): Turn HSimulates into full snapshots maybe?
3473 virtual bool IsDeletable() const FINAL OVERRIDE { return false; }
3477 class HConstant FINAL : public HTemplateInstruction<0> {
3479 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, int32_t);
3480 DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation);
3481 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double);
3482 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle<Object>);
3483 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);
3485 static HConstant* CreateAndInsertAfter(Zone* zone,
3488 Representation representation,
3489 HInstruction* instruction) {
3490 return instruction->Append(HConstant::New(
3491 zone, context, value, representation));
3494 virtual Handle<Map> GetMonomorphicJSObjectMap() OVERRIDE {
3495 Handle<Object> object = object_.handle();
3496 if (!object.is_null() && object->IsHeapObject()) {
3497 return v8::internal::handle(HeapObject::cast(*object)->map());
3499 return Handle<Map>();
3502 static HConstant* CreateAndInsertBefore(Zone* zone,
3505 Representation representation,
3506 HInstruction* instruction) {
3507 return instruction->Prepend(HConstant::New(
3508 zone, context, value, representation));
3511 static HConstant* CreateAndInsertBefore(Zone* zone,
3514 HInstruction* instruction) {
3515 return instruction->Prepend(new(zone) HConstant(
3516 map, Unique<Map>(Handle<Map>::null()), map_is_stable,
3517 Representation::Tagged(), HType::HeapObject(), true,
3518 false, false, MAP_TYPE));
3521 static HConstant* CreateAndInsertAfter(Zone* zone,
3524 HInstruction* instruction) {
3525 return instruction->Append(new(zone) HConstant(
3526 map, Unique<Map>(Handle<Map>::null()), map_is_stable,
3527 Representation::Tagged(), HType::HeapObject(), true,
3528 false, false, MAP_TYPE));
3531 Handle<Object> handle(Isolate* isolate) {
3532 if (object_.handle().is_null()) {
3533 // Default arguments to is_not_in_new_space depend on this heap number
3534 // to be tenured so that it's guaranteed not to be located in new space.
3535 object_ = Unique<Object>::CreateUninitialized(
3536 isolate->factory()->NewNumber(double_value_, TENURED));
3538 AllowDeferredHandleDereference smi_check;
3539 DCHECK(has_int32_value_ || !object_.handle()->IsSmi());
3540 return object_.handle();
3543 bool IsSpecialDouble() const {
3544 return has_double_value_ &&
3545 (bit_cast<int64_t>(double_value_) == bit_cast<int64_t>(-0.0) ||
3546 FixedDoubleArray::is_the_hole_nan(double_value_) ||
3547 std::isnan(double_value_));
3550 bool NotInNewSpace() const {
3551 return is_not_in_new_space_;
3554 bool ImmortalImmovable() const;
3556 bool IsCell() const {
3557 return instance_type_ == CELL_TYPE || instance_type_ == PROPERTY_CELL_TYPE;
3560 bool IsMap() const {
3561 return instance_type_ == MAP_TYPE;
3564 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
3565 return Representation::None();
3568 virtual Representation KnownOptimalRepresentation() OVERRIDE {
3569 if (HasSmiValue() && SmiValuesAre31Bits()) return Representation::Smi();
3570 if (HasInteger32Value()) return Representation::Integer32();
3571 if (HasNumberValue()) return Representation::Double();
3572 if (HasExternalReferenceValue()) return Representation::External();
3573 return Representation::Tagged();
3576 virtual bool EmitAtUses() OVERRIDE;
3577 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
3578 HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
3579 Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone);
3580 Maybe<HConstant*> CopyToTruncatedNumber(Zone* zone);
3581 bool HasInteger32Value() const { return has_int32_value_; }
3582 int32_t Integer32Value() const {
3583 DCHECK(HasInteger32Value());
3584 return int32_value_;
3586 bool HasSmiValue() const { return has_smi_value_; }
3587 bool HasDoubleValue() const { return has_double_value_; }
3588 double DoubleValue() const {
3589 DCHECK(HasDoubleValue());
3590 return double_value_;
3592 bool IsTheHole() const {
3593 if (HasDoubleValue() && FixedDoubleArray::is_the_hole_nan(double_value_)) {
3596 return object_.IsInitialized() &&
3597 object_.IsKnownGlobal(isolate()->heap()->the_hole_value());
3599 bool HasNumberValue() const { return has_double_value_; }
3600 int32_t NumberValueAsInteger32() const {
3601 DCHECK(HasNumberValue());
3602 // Irrespective of whether a numeric HConstant can be safely
3603 // represented as an int32, we store the (in some cases lossy)
3604 // representation of the number in int32_value_.
3605 return int32_value_;
3607 bool HasStringValue() const {
3608 if (has_double_value_ || has_int32_value_) return false;
3609 DCHECK(!object_.handle().is_null());
3610 return instance_type_ < FIRST_NONSTRING_TYPE;
3612 Handle<String> StringValue() const {
3613 DCHECK(HasStringValue());
3614 return Handle<String>::cast(object_.handle());
3616 bool HasInternalizedStringValue() const {
3617 return HasStringValue() && StringShape(instance_type_).IsInternalized();
3620 bool HasExternalReferenceValue() const {
3621 return has_external_reference_value_;
3623 ExternalReference ExternalReferenceValue() const {
3624 return external_reference_value_;
3627 bool HasBooleanValue() const { return type_.IsBoolean(); }
3628 bool BooleanValue() const { return boolean_value_; }
3629 bool IsUndetectable() const { return is_undetectable_; }
3630 InstanceType GetInstanceType() const { return instance_type_; }
3632 bool HasMapValue() const { return instance_type_ == MAP_TYPE; }
3633 Unique<Map> MapValue() const {
3634 DCHECK(HasMapValue());
3635 return Unique<Map>::cast(GetUnique());
3637 bool HasStableMapValue() const {
3638 DCHECK(HasMapValue() || !has_stable_map_value_);
3639 return has_stable_map_value_;
3642 bool HasObjectMap() const { return !object_map_.IsNull(); }
3643 Unique<Map> ObjectMap() const {
3644 DCHECK(HasObjectMap());
3648 virtual intptr_t Hashcode() OVERRIDE {
3649 if (has_int32_value_) {
3650 return static_cast<intptr_t>(int32_value_);
3651 } else if (has_double_value_) {
3652 return static_cast<intptr_t>(bit_cast<int64_t>(double_value_));
3653 } else if (has_external_reference_value_) {
3654 return reinterpret_cast<intptr_t>(external_reference_value_.address());
3656 DCHECK(!object_.handle().is_null());
3657 return object_.Hashcode();
3661 virtual void FinalizeUniqueness() OVERRIDE {
3662 if (!has_double_value_ && !has_external_reference_value_) {
3663 DCHECK(!object_.handle().is_null());
3664 object_ = Unique<Object>(object_.handle());
3668 Unique<Object> GetUnique() const {
3672 bool EqualsUnique(Unique<Object> other) const {
3673 return object_.IsInitialized() && object_ == other;
3676 virtual bool DataEquals(HValue* other) OVERRIDE {
3677 HConstant* other_constant = HConstant::cast(other);
3678 if (has_int32_value_) {
3679 return other_constant->has_int32_value_ &&
3680 int32_value_ == other_constant->int32_value_;
3681 } else if (has_double_value_) {
3682 return other_constant->has_double_value_ &&
3683 bit_cast<int64_t>(double_value_) ==
3684 bit_cast<int64_t>(other_constant->double_value_);
3685 } else if (has_external_reference_value_) {
3686 return other_constant->has_external_reference_value_ &&
3687 external_reference_value_ ==
3688 other_constant->external_reference_value_;
3690 if (other_constant->has_int32_value_ ||
3691 other_constant->has_double_value_ ||
3692 other_constant->has_external_reference_value_) {
3695 DCHECK(!object_.handle().is_null());
3696 return other_constant->object_ == object_;
3701 virtual void Verify() OVERRIDE { }
3704 DECLARE_CONCRETE_INSTRUCTION(Constant)
3707 virtual Range* InferRange(Zone* zone) OVERRIDE;
3710 friend class HGraph;
3711 explicit HConstant(Handle<Object> handle,
3712 Representation r = Representation::None());
3713 HConstant(int32_t value,
3714 Representation r = Representation::None(),
3715 bool is_not_in_new_space = true,
3716 Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3717 HConstant(double value,
3718 Representation r = Representation::None(),
3719 bool is_not_in_new_space = true,
3720 Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3721 HConstant(Unique<Object> object,
3722 Unique<Map> object_map,
3723 bool has_stable_map_value,
3726 bool is_not_in_new_space,
3728 bool is_undetectable,
3729 InstanceType instance_type);
3731 explicit HConstant(ExternalReference reference);
3733 void Initialize(Representation r);
3735 virtual bool IsDeletable() const OVERRIDE { return true; }
3737 // If this is a numerical constant, object_ either points to the
3738 // HeapObject the constant originated from or is null. If the
3739 // constant is non-numeric, object_ always points to a valid
3740 // constant HeapObject.
3741 Unique<Object> object_;
3743 // If object_ is a heap object, this points to the stable map of the object.
3744 Unique<Map> object_map_;
3746 // If object_ is a map, this indicates whether the map is stable.
3747 bool has_stable_map_value_ : 1;
3749 // We store the HConstant in the most specific form safely possible.
3750 // The two flags, has_int32_value_ and has_double_value_ tell us if
3751 // int32_value_ and double_value_ hold valid, safe representations
3752 // of the constant. has_int32_value_ implies has_double_value_ but
3753 // not the converse.
3754 bool has_smi_value_ : 1;
3755 bool has_int32_value_ : 1;
3756 bool has_double_value_ : 1;
3757 bool has_external_reference_value_ : 1;
3758 bool is_not_in_new_space_ : 1;
3759 bool boolean_value_ : 1;
3760 bool is_undetectable_: 1;
3761 int32_t int32_value_;
3762 double double_value_;
3763 ExternalReference external_reference_value_;
3765 static const InstanceType kUnknownInstanceType = FILLER_TYPE;
3766 InstanceType instance_type_;
3770 class HBinaryOperation : public HTemplateInstruction<3> {
3772 HBinaryOperation(HValue* context, HValue* left, HValue* right,
3773 HType type = HType::Tagged())
3774 : HTemplateInstruction<3>(type),
3775 observed_output_representation_(Representation::None()) {
3776 DCHECK(left != NULL && right != NULL);
3777 SetOperandAt(0, context);
3778 SetOperandAt(1, left);
3779 SetOperandAt(2, right);
3780 observed_input_representation_[0] = Representation::None();
3781 observed_input_representation_[1] = Representation::None();
3784 HValue* context() const { return OperandAt(0); }
3785 HValue* left() const { return OperandAt(1); }
3786 HValue* right() const { return OperandAt(2); }
3788 // True if switching left and right operands likely generates better code.
3789 bool AreOperandsBetterSwitched() {
3790 if (!IsCommutative()) return false;
3792 // Constant operands are better off on the right, they can be inlined in
3793 // many situations on most platforms.
3794 if (left()->IsConstant()) return true;
3795 if (right()->IsConstant()) return false;
3797 // Otherwise, if there is only one use of the right operand, it would be
3798 // better off on the left for platforms that only have 2-arg arithmetic
3799 // ops (e.g ia32, x64) that clobber the left operand.
3800 return right()->HasOneUse();
3803 HValue* BetterLeftOperand() {
3804 return AreOperandsBetterSwitched() ? right() : left();
3807 HValue* BetterRightOperand() {
3808 return AreOperandsBetterSwitched() ? left() : right();
3811 void set_observed_input_representation(int index, Representation rep) {
3812 DCHECK(index >= 1 && index <= 2);
3813 observed_input_representation_[index - 1] = rep;
3816 virtual void initialize_output_representation(Representation observed) {
3817 observed_output_representation_ = observed;
3820 virtual Representation observed_input_representation(int index) OVERRIDE {
3821 if (index == 0) return Representation::Tagged();
3822 return observed_input_representation_[index - 1];
3825 virtual void UpdateRepresentation(Representation new_rep,
3826 HInferRepresentationPhase* h_infer,
3827 const char* reason) OVERRIDE {
3828 Representation rep = !FLAG_smi_binop && new_rep.IsSmi()
3829 ? Representation::Integer32() : new_rep;
3830 HValue::UpdateRepresentation(rep, h_infer, reason);
3833 virtual void InferRepresentation(
3834 HInferRepresentationPhase* h_infer) OVERRIDE;
3835 virtual Representation RepresentationFromInputs() OVERRIDE;
3836 Representation RepresentationFromOutput();
3837 virtual void AssumeRepresentation(Representation r) OVERRIDE;
3839 virtual bool IsCommutative() const { return false; }
3841 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
3843 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
3844 if (index == 0) return Representation::Tagged();
3845 return representation();
3848 void SetOperandPositions(Zone* zone,
3849 HSourcePosition left_pos,
3850 HSourcePosition right_pos) {
3851 set_operand_position(zone, 1, left_pos);
3852 set_operand_position(zone, 2, right_pos);
3855 bool RightIsPowerOf2() {
3856 if (!right()->IsInteger32Constant()) return false;
3857 int32_t value = right()->GetInteger32Constant();
3859 return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(-value));
3861 return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(value));
3864 DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
3867 bool IgnoreObservedOutputRepresentation(Representation current_rep);
3869 Representation observed_input_representation_[2];
3870 Representation observed_output_representation_;
3874 class HWrapReceiver FINAL : public HTemplateInstruction<2> {
3876 DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
3878 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
3880 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
3881 return Representation::Tagged();
3884 HValue* receiver() const { return OperandAt(0); }
3885 HValue* function() const { return OperandAt(1); }
3887 virtual HValue* Canonicalize() OVERRIDE;
3889 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
3890 bool known_function() const { return known_function_; }
3892 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
3895 HWrapReceiver(HValue* receiver, HValue* function) {
3896 known_function_ = function->IsConstant() &&
3897 HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
3898 set_representation(Representation::Tagged());
3899 SetOperandAt(0, receiver);
3900 SetOperandAt(1, function);
3904 bool known_function_;
3908 class HApplyArguments FINAL : public HTemplateInstruction<4> {
3910 DECLARE_INSTRUCTION_FACTORY_P4(HApplyArguments, HValue*, HValue*, HValue*,
3913 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
3914 // The length is untagged, all other inputs are tagged.
3916 ? Representation::Integer32()
3917 : Representation::Tagged();
3920 HValue* function() { return OperandAt(0); }
3921 HValue* receiver() { return OperandAt(1); }
3922 HValue* length() { return OperandAt(2); }
3923 HValue* elements() { return OperandAt(3); }
3925 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
3928 HApplyArguments(HValue* function,
3932 set_representation(Representation::Tagged());
3933 SetOperandAt(0, function);
3934 SetOperandAt(1, receiver);
3935 SetOperandAt(2, length);
3936 SetOperandAt(3, elements);
3937 SetAllSideEffects();
3942 class HArgumentsElements FINAL : public HTemplateInstruction<0> {
3944 DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
3946 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
3948 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
3949 return Representation::None();
3952 bool from_inlined() const { return from_inlined_; }
3955 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
3958 explicit HArgumentsElements(bool from_inlined) : from_inlined_(from_inlined) {
3959 // The value produced by this instruction is a pointer into the stack
3960 // that looks as if it was a smi because of alignment.
3961 set_representation(Representation::Tagged());
3965 virtual bool IsDeletable() const OVERRIDE { return true; }
3971 class HArgumentsLength FINAL : public HUnaryOperation {
3973 DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue*);
3975 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
3976 return Representation::Tagged();
3979 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
3982 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
3985 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
3986 set_representation(Representation::Integer32());
3990 virtual bool IsDeletable() const OVERRIDE { return true; }
3994 class HAccessArgumentsAt FINAL : public HTemplateInstruction<3> {
3996 DECLARE_INSTRUCTION_FACTORY_P3(HAccessArgumentsAt, HValue*, HValue*, HValue*);
3998 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4000 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4001 // The arguments elements is considered tagged.
4003 ? Representation::Tagged()
4004 : Representation::Integer32();
4007 HValue* arguments() const { return OperandAt(0); }
4008 HValue* length() const { return OperandAt(1); }
4009 HValue* index() const { return OperandAt(2); }
4011 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
4014 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
4015 set_representation(Representation::Tagged());
4017 SetOperandAt(0, arguments);
4018 SetOperandAt(1, length);
4019 SetOperandAt(2, index);
4022 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4026 class HBoundsCheckBaseIndexInformation;
4029 class HBoundsCheck FINAL : public HTemplateInstruction<2> {
4031 DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
4033 bool skip_check() const { return skip_check_; }
4034 void set_skip_check() { skip_check_ = true; }
4036 HValue* base() const { return base_; }
4037 int offset() const { return offset_; }
4038 int scale() const { return scale_; }
4040 void ApplyIndexChange();
4041 bool DetectCompoundIndex() {
4042 DCHECK(base() == NULL);
4044 DecompositionResult decomposition;
4045 if (index()->TryDecompose(&decomposition)) {
4046 base_ = decomposition.base();
4047 offset_ = decomposition.offset();
4048 scale_ = decomposition.scale();
4058 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4059 return representation();
4062 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4063 virtual void InferRepresentation(
4064 HInferRepresentationPhase* h_infer) OVERRIDE;
4066 HValue* index() const { return OperandAt(0); }
4067 HValue* length() const { return OperandAt(1); }
4068 bool allow_equality() const { return allow_equality_; }
4069 void set_allow_equality(bool v) { allow_equality_ = v; }
4071 virtual int RedefinedOperandIndex() OVERRIDE { return 0; }
4072 virtual bool IsPurelyInformativeDefinition() OVERRIDE {
4073 return skip_check();
4076 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
4079 friend class HBoundsCheckBaseIndexInformation;
4081 virtual Range* InferRange(Zone* zone) OVERRIDE;
4083 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4088 bool allow_equality_;
4091 // Normally HBoundsCheck should be created using the
4092 // HGraphBuilder::AddBoundsCheck() helper.
4093 // However when building stubs, where we know that the arguments are Int32,
4094 // it makes sense to invoke this constructor directly.
4095 HBoundsCheck(HValue* index, HValue* length)
4096 : skip_check_(false),
4097 base_(NULL), offset_(0), scale_(0),
4098 allow_equality_(false) {
4099 SetOperandAt(0, index);
4100 SetOperandAt(1, length);
4101 SetFlag(kFlexibleRepresentation);
4105 virtual bool IsDeletable() const OVERRIDE {
4106 return skip_check() && !FLAG_debug_code;
4111 class HBoundsCheckBaseIndexInformation FINAL
4112 : public HTemplateInstruction<2> {
4114 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) {
4115 DecompositionResult decomposition;
4116 if (check->index()->TryDecompose(&decomposition)) {
4117 SetOperandAt(0, decomposition.base());
4118 SetOperandAt(1, check);
4124 HValue* base_index() const { return OperandAt(0); }
4125 HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); }
4127 DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation)
4129 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4130 return representation();
4133 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4135 virtual int RedefinedOperandIndex() OVERRIDE { return 0; }
4136 virtual bool IsPurelyInformativeDefinition() OVERRIDE { return true; }
4140 class HBitwiseBinaryOperation : public HBinaryOperation {
4142 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
4143 HType type = HType::TaggedNumber())
4144 : HBinaryOperation(context, left, right, type) {
4145 SetFlag(kFlexibleRepresentation);
4146 SetFlag(kTruncatingToInt32);
4147 SetFlag(kAllowUndefinedAsNaN);
4148 SetAllSideEffects();
4151 virtual void RepresentationChanged(Representation to) OVERRIDE {
4152 if (to.IsTagged() &&
4153 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
4154 SetAllSideEffects();
4157 ClearAllSideEffects();
4160 if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
4163 virtual void UpdateRepresentation(Representation new_rep,
4164 HInferRepresentationPhase* h_infer,
4165 const char* reason) OVERRIDE {
4166 // We only generate either int32 or generic tagged bitwise operations.
4167 if (new_rep.IsDouble()) new_rep = Representation::Integer32();
4168 HBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4171 virtual Representation observed_input_representation(int index) OVERRIDE {
4172 Representation r = HBinaryOperation::observed_input_representation(index);
4173 if (r.IsDouble()) return Representation::Integer32();
4177 virtual void initialize_output_representation(Representation observed) {
4178 if (observed.IsDouble()) observed = Representation::Integer32();
4179 HBinaryOperation::initialize_output_representation(observed);
4182 DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
4185 virtual bool IsDeletable() const OVERRIDE { return true; }
4189 class HMathFloorOfDiv FINAL : public HBinaryOperation {
4191 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HMathFloorOfDiv,
4195 DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
4198 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4201 HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
4202 : HBinaryOperation(context, left, right) {
4203 set_representation(Representation::Integer32());
4205 SetFlag(kCanOverflow);
4206 SetFlag(kCanBeDivByZero);
4207 SetFlag(kLeftCanBeMinInt);
4208 SetFlag(kLeftCanBeNegative);
4209 SetFlag(kLeftCanBePositive);
4210 SetFlag(kAllowUndefinedAsNaN);
4213 virtual Range* InferRange(Zone* zone) OVERRIDE;
4215 virtual bool IsDeletable() const OVERRIDE { return true; }
4219 class HArithmeticBinaryOperation : public HBinaryOperation {
4221 HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right)
4222 : HBinaryOperation(context, left, right, HType::TaggedNumber()) {
4223 SetAllSideEffects();
4224 SetFlag(kFlexibleRepresentation);
4225 SetFlag(kAllowUndefinedAsNaN);
4228 virtual void RepresentationChanged(Representation to) OVERRIDE {
4229 if (to.IsTagged() &&
4230 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
4231 SetAllSideEffects();
4234 ClearAllSideEffects();
4237 if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
4240 DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
4243 virtual bool IsDeletable() const OVERRIDE { return true; }
4247 class HCompareGeneric FINAL : public HBinaryOperation {
4249 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCompareGeneric, HValue*,
4250 HValue*, Token::Value);
4252 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4254 ? Representation::Tagged()
4258 Token::Value token() const { return token_; }
4259 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4261 DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
4264 HCompareGeneric(HValue* context,
4268 : HBinaryOperation(context, left, right, HType::Boolean()),
4270 DCHECK(Token::IsCompareOp(token));
4271 set_representation(Representation::Tagged());
4272 SetAllSideEffects();
4275 Token::Value token_;
4279 class HCompareNumericAndBranch : public HTemplateControlInstruction<2, 2> {
4281 DECLARE_INSTRUCTION_FACTORY_P3(HCompareNumericAndBranch,
4282 HValue*, HValue*, Token::Value);
4283 DECLARE_INSTRUCTION_FACTORY_P5(HCompareNumericAndBranch,
4284 HValue*, HValue*, Token::Value,
4285 HBasicBlock*, HBasicBlock*);
4287 HValue* left() const { return OperandAt(0); }
4288 HValue* right() const { return OperandAt(1); }
4289 Token::Value token() const { return token_; }
4291 void set_observed_input_representation(Representation left,
4292 Representation right) {
4293 observed_input_representation_[0] = left;
4294 observed_input_representation_[1] = right;
4297 virtual void InferRepresentation(
4298 HInferRepresentationPhase* h_infer) OVERRIDE;
4300 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4301 return representation();
4303 virtual Representation observed_input_representation(int index) OVERRIDE {
4304 return observed_input_representation_[index];
4307 virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE;
4309 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4311 void SetOperandPositions(Zone* zone,
4312 HSourcePosition left_pos,
4313 HSourcePosition right_pos) {
4314 set_operand_position(zone, 0, left_pos);
4315 set_operand_position(zone, 1, right_pos);
4318 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
4321 HCompareNumericAndBranch(HValue* left,
4324 HBasicBlock* true_target = NULL,
4325 HBasicBlock* false_target = NULL)
4327 SetFlag(kFlexibleRepresentation);
4328 DCHECK(Token::IsCompareOp(token));
4329 SetOperandAt(0, left);
4330 SetOperandAt(1, right);
4331 SetSuccessorAt(0, true_target);
4332 SetSuccessorAt(1, false_target);
4335 Representation observed_input_representation_[2];
4336 Token::Value token_;
4340 class HCompareHoleAndBranch FINAL : public HUnaryControlInstruction {
4342 DECLARE_INSTRUCTION_FACTORY_P1(HCompareHoleAndBranch, HValue*);
4343 DECLARE_INSTRUCTION_FACTORY_P3(HCompareHoleAndBranch, HValue*,
4344 HBasicBlock*, HBasicBlock*);
4346 virtual void InferRepresentation(
4347 HInferRepresentationPhase* h_infer) OVERRIDE;
4349 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4350 return representation();
4353 DECLARE_CONCRETE_INSTRUCTION(CompareHoleAndBranch)
4356 HCompareHoleAndBranch(HValue* value,
4357 HBasicBlock* true_target = NULL,
4358 HBasicBlock* false_target = NULL)
4359 : HUnaryControlInstruction(value, true_target, false_target) {
4360 SetFlag(kFlexibleRepresentation);
4361 SetFlag(kAllowUndefinedAsNaN);
4366 class HCompareMinusZeroAndBranch FINAL : public HUnaryControlInstruction {
4368 DECLARE_INSTRUCTION_FACTORY_P1(HCompareMinusZeroAndBranch, HValue*);
4370 virtual void InferRepresentation(
4371 HInferRepresentationPhase* h_infer) OVERRIDE;
4373 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4374 return representation();
4377 virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE;
4379 DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch)
4382 explicit HCompareMinusZeroAndBranch(HValue* value)
4383 : HUnaryControlInstruction(value, NULL, NULL) {
4388 class HCompareObjectEqAndBranch : public HTemplateControlInstruction<2, 2> {
4390 DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue*, HValue*);
4391 DECLARE_INSTRUCTION_FACTORY_P4(HCompareObjectEqAndBranch, HValue*, HValue*,
4392 HBasicBlock*, HBasicBlock*);
4394 virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE;
4396 static const int kNoKnownSuccessorIndex = -1;
4397 int known_successor_index() const { return known_successor_index_; }
4398 void set_known_successor_index(int known_successor_index) {
4399 known_successor_index_ = known_successor_index;
4402 HValue* left() const { return OperandAt(0); }
4403 HValue* right() const { return OperandAt(1); }
4405 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4407 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4408 return Representation::Tagged();
4411 virtual Representation observed_input_representation(int index) OVERRIDE {
4412 return Representation::Tagged();
4415 DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
4418 HCompareObjectEqAndBranch(HValue* left,
4420 HBasicBlock* true_target = NULL,
4421 HBasicBlock* false_target = NULL)
4422 : known_successor_index_(kNoKnownSuccessorIndex) {
4423 SetOperandAt(0, left);
4424 SetOperandAt(1, right);
4425 SetSuccessorAt(0, true_target);
4426 SetSuccessorAt(1, false_target);
4429 int known_successor_index_;
4433 class HIsObjectAndBranch FINAL : public HUnaryControlInstruction {
4435 DECLARE_INSTRUCTION_FACTORY_P1(HIsObjectAndBranch, HValue*);
4436 DECLARE_INSTRUCTION_FACTORY_P3(HIsObjectAndBranch, HValue*,
4437 HBasicBlock*, HBasicBlock*);
4439 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4440 return Representation::Tagged();
4443 virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE;
4445 DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch)
4448 HIsObjectAndBranch(HValue* value,
4449 HBasicBlock* true_target = NULL,
4450 HBasicBlock* false_target = NULL)
4451 : HUnaryControlInstruction(value, true_target, false_target) {}
4455 class HIsStringAndBranch FINAL : public HUnaryControlInstruction {
4457 DECLARE_INSTRUCTION_FACTORY_P1(HIsStringAndBranch, HValue*);
4458 DECLARE_INSTRUCTION_FACTORY_P3(HIsStringAndBranch, HValue*,
4459 HBasicBlock*, HBasicBlock*);
4461 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4462 return Representation::Tagged();
4465 virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE;
4467 static const int kNoKnownSuccessorIndex = -1;
4468 int known_successor_index() const { return known_successor_index_; }
4469 void set_known_successor_index(int known_successor_index) {
4470 known_successor_index_ = known_successor_index;
4473 DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
4476 virtual int RedefinedOperandIndex() { return 0; }
4479 HIsStringAndBranch(HValue* value,
4480 HBasicBlock* true_target = NULL,
4481 HBasicBlock* false_target = NULL)
4482 : HUnaryControlInstruction(value, true_target, false_target),
4483 known_successor_index_(kNoKnownSuccessorIndex) { }
4485 int known_successor_index_;
4489 class HIsSmiAndBranch FINAL : public HUnaryControlInstruction {
4491 DECLARE_INSTRUCTION_FACTORY_P1(HIsSmiAndBranch, HValue*);
4492 DECLARE_INSTRUCTION_FACTORY_P3(HIsSmiAndBranch, HValue*,
4493 HBasicBlock*, HBasicBlock*);
4495 DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
4497 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4498 return Representation::Tagged();
4502 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4503 virtual int RedefinedOperandIndex() { return 0; }
4506 HIsSmiAndBranch(HValue* value,
4507 HBasicBlock* true_target = NULL,
4508 HBasicBlock* false_target = NULL)
4509 : HUnaryControlInstruction(value, true_target, false_target) {
4510 set_representation(Representation::Tagged());
4515 class HIsUndetectableAndBranch FINAL : public HUnaryControlInstruction {
4517 DECLARE_INSTRUCTION_FACTORY_P1(HIsUndetectableAndBranch, HValue*);
4518 DECLARE_INSTRUCTION_FACTORY_P3(HIsUndetectableAndBranch, HValue*,
4519 HBasicBlock*, HBasicBlock*);
4521 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4522 return Representation::Tagged();
4525 virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE;
4527 DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
4530 HIsUndetectableAndBranch(HValue* value,
4531 HBasicBlock* true_target = NULL,
4532 HBasicBlock* false_target = NULL)
4533 : HUnaryControlInstruction(value, true_target, false_target) {}
4537 class HStringCompareAndBranch : public HTemplateControlInstruction<2, 3> {
4539 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HStringCompareAndBranch,
4544 HValue* context() { return OperandAt(0); }
4545 HValue* left() { return OperandAt(1); }
4546 HValue* right() { return OperandAt(2); }
4547 Token::Value token() const { return token_; }
4549 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4551 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4552 return Representation::Tagged();
4555 Representation GetInputRepresentation() const {
4556 return Representation::Tagged();
4559 DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
4562 HStringCompareAndBranch(HValue* context,
4567 DCHECK(Token::IsCompareOp(token));
4568 SetOperandAt(0, context);
4569 SetOperandAt(1, left);
4570 SetOperandAt(2, right);
4571 set_representation(Representation::Tagged());
4572 SetChangesFlag(kNewSpacePromotion);
4575 Token::Value token_;
4579 class HIsConstructCallAndBranch : public HTemplateControlInstruction<2, 0> {
4581 DECLARE_INSTRUCTION_FACTORY_P0(HIsConstructCallAndBranch);
4583 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4584 return Representation::None();
4587 DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch)
4589 HIsConstructCallAndBranch() {}
4593 class HHasInstanceTypeAndBranch FINAL : public HUnaryControlInstruction {
4595 DECLARE_INSTRUCTION_FACTORY_P2(
4596 HHasInstanceTypeAndBranch, HValue*, InstanceType);
4597 DECLARE_INSTRUCTION_FACTORY_P3(
4598 HHasInstanceTypeAndBranch, HValue*, InstanceType, InstanceType);
4600 InstanceType from() { return from_; }
4601 InstanceType to() { return to_; }
4603 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4605 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4606 return Representation::Tagged();
4609 virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE;
4611 DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
4614 HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
4615 : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
4616 HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
4617 : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
4618 DCHECK(to == LAST_TYPE); // Others not implemented yet in backend.
4622 InstanceType to_; // Inclusive range, not all combinations work.
4626 class HHasCachedArrayIndexAndBranch FINAL : public HUnaryControlInstruction {
4628 DECLARE_INSTRUCTION_FACTORY_P1(HHasCachedArrayIndexAndBranch, HValue*);
4630 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4631 return Representation::Tagged();
4634 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
4636 explicit HHasCachedArrayIndexAndBranch(HValue* value)
4637 : HUnaryControlInstruction(value, NULL, NULL) { }
4641 class HGetCachedArrayIndex FINAL : public HUnaryOperation {
4643 DECLARE_INSTRUCTION_FACTORY_P1(HGetCachedArrayIndex, HValue*);
4645 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4646 return Representation::Tagged();
4649 DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
4652 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4655 explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
4656 set_representation(Representation::Tagged());
4660 virtual bool IsDeletable() const OVERRIDE { return true; }
4664 class HClassOfTestAndBranch FINAL : public HUnaryControlInstruction {
4666 DECLARE_INSTRUCTION_FACTORY_P2(HClassOfTestAndBranch, HValue*,
4669 DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
4671 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4672 return Representation::Tagged();
4675 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4677 Handle<String> class_name() const { return class_name_; }
4680 HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
4681 : HUnaryControlInstruction(value, NULL, NULL),
4682 class_name_(class_name) { }
4684 Handle<String> class_name_;
4688 class HTypeofIsAndBranch FINAL : public HUnaryControlInstruction {
4690 DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle<String>);
4692 Handle<String> type_literal() const { return type_literal_.handle(); }
4693 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4695 DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
4697 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4698 return Representation::None();
4701 virtual bool KnownSuccessorBlock(HBasicBlock** block) OVERRIDE;
4703 virtual void FinalizeUniqueness() OVERRIDE {
4704 type_literal_ = Unique<String>(type_literal_.handle());
4708 HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
4709 : HUnaryControlInstruction(value, NULL, NULL),
4710 type_literal_(Unique<String>::CreateUninitialized(type_literal)) { }
4712 Unique<String> type_literal_;
4716 class HInstanceOf FINAL : public HBinaryOperation {
4718 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOf, HValue*, HValue*);
4720 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4721 return Representation::Tagged();
4724 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
4726 DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
4729 HInstanceOf(HValue* context, HValue* left, HValue* right)
4730 : HBinaryOperation(context, left, right, HType::Boolean()) {
4731 set_representation(Representation::Tagged());
4732 SetAllSideEffects();
4737 class HInstanceOfKnownGlobal FINAL : public HTemplateInstruction<2> {
4739 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOfKnownGlobal,
4741 Handle<JSFunction>);
4743 HValue* context() { return OperandAt(0); }
4744 HValue* left() { return OperandAt(1); }
4745 Handle<JSFunction> function() { return function_; }
4747 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4748 return Representation::Tagged();
4751 DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal)
4754 HInstanceOfKnownGlobal(HValue* context,
4756 Handle<JSFunction> right)
4757 : HTemplateInstruction<2>(HType::Boolean()), function_(right) {
4758 SetOperandAt(0, context);
4759 SetOperandAt(1, left);
4760 set_representation(Representation::Tagged());
4761 SetAllSideEffects();
4764 Handle<JSFunction> function_;
4768 class HPower FINAL : public HTemplateInstruction<2> {
4770 static HInstruction* New(Zone* zone,
4775 HValue* left() { return OperandAt(0); }
4776 HValue* right() const { return OperandAt(1); }
4778 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
4780 ? Representation::Double()
4781 : Representation::None();
4783 virtual Representation observed_input_representation(int index) OVERRIDE {
4784 return RequiredInputRepresentation(index);
4787 DECLARE_CONCRETE_INSTRUCTION(Power)
4790 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4793 HPower(HValue* left, HValue* right) {
4794 SetOperandAt(0, left);
4795 SetOperandAt(1, right);
4796 set_representation(Representation::Double());
4798 SetChangesFlag(kNewSpacePromotion);
4801 virtual bool IsDeletable() const OVERRIDE {
4802 return !right()->representation().IsTagged();
4807 class HAdd FINAL : public HArithmeticBinaryOperation {
4809 static HInstruction* New(Zone* zone,
4814 // Add is only commutative if two integer values are added and not if two
4815 // tagged values are added (because it might be a String concatenation).
4816 // We also do not commute (pointer + offset).
4817 virtual bool IsCommutative() const OVERRIDE {
4818 return !representation().IsTagged() && !representation().IsExternal();
4821 virtual HValue* Canonicalize() OVERRIDE;
4823 virtual bool TryDecompose(DecompositionResult* decomposition) OVERRIDE {
4824 if (left()->IsInteger32Constant()) {
4825 decomposition->Apply(right(), left()->GetInteger32Constant());
4827 } else if (right()->IsInteger32Constant()) {
4828 decomposition->Apply(left(), right()->GetInteger32Constant());
4835 virtual void RepresentationChanged(Representation to) OVERRIDE {
4836 if (to.IsTagged() &&
4837 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() ||
4838 left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) {
4839 SetAllSideEffects();
4842 ClearAllSideEffects();
4845 if (to.IsTagged()) {
4846 SetChangesFlag(kNewSpacePromotion);
4847 ClearFlag(kAllowUndefinedAsNaN);
4851 virtual Representation RepresentationFromInputs() OVERRIDE;
4853 virtual Representation RequiredInputRepresentation(int index) OVERRIDE;
4855 DECLARE_CONCRETE_INSTRUCTION(Add)
4858 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4860 virtual Range* InferRange(Zone* zone) OVERRIDE;
4863 HAdd(HValue* context, HValue* left, HValue* right)
4864 : HArithmeticBinaryOperation(context, left, right) {
4865 SetFlag(kCanOverflow);
4870 class HSub FINAL : public HArithmeticBinaryOperation {
4872 static HInstruction* New(Zone* zone,
4877 virtual HValue* Canonicalize() OVERRIDE;
4879 virtual bool TryDecompose(DecompositionResult* decomposition) OVERRIDE {
4880 if (right()->IsInteger32Constant()) {
4881 decomposition->Apply(left(), -right()->GetInteger32Constant());
4888 DECLARE_CONCRETE_INSTRUCTION(Sub)
4891 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4893 virtual Range* InferRange(Zone* zone) OVERRIDE;
4896 HSub(HValue* context, HValue* left, HValue* right)
4897 : HArithmeticBinaryOperation(context, left, right) {
4898 SetFlag(kCanOverflow);
4903 class HMul FINAL : public HArithmeticBinaryOperation {
4905 static HInstruction* New(Zone* zone,
4910 static HInstruction* NewImul(Zone* zone,
4914 HInstruction* instr = HMul::New(zone, context, left, right);
4915 if (!instr->IsMul()) return instr;
4916 HMul* mul = HMul::cast(instr);
4917 // TODO(mstarzinger): Prevent bailout on minus zero for imul.
4918 mul->AssumeRepresentation(Representation::Integer32());
4919 mul->ClearFlag(HValue::kCanOverflow);
4923 virtual HValue* Canonicalize() OVERRIDE;
4925 // Only commutative if it is certain that not two objects are multiplicated.
4926 virtual bool IsCommutative() const OVERRIDE {
4927 return !representation().IsTagged();
4930 virtual void UpdateRepresentation(Representation new_rep,
4931 HInferRepresentationPhase* h_infer,
4932 const char* reason) OVERRIDE {
4933 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4938 DECLARE_CONCRETE_INSTRUCTION(Mul)
4941 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4943 virtual Range* InferRange(Zone* zone) OVERRIDE;
4946 HMul(HValue* context, HValue* left, HValue* right)
4947 : HArithmeticBinaryOperation(context, left, right) {
4948 SetFlag(kCanOverflow);
4953 class HMod FINAL : public HArithmeticBinaryOperation {
4955 static HInstruction* New(Zone* zone,
4960 virtual HValue* Canonicalize() OVERRIDE;
4962 virtual void UpdateRepresentation(Representation new_rep,
4963 HInferRepresentationPhase* h_infer,
4964 const char* reason) OVERRIDE {
4965 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4966 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4969 DECLARE_CONCRETE_INSTRUCTION(Mod)
4972 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
4974 virtual Range* InferRange(Zone* zone) OVERRIDE;
4977 HMod(HValue* context,
4979 HValue* right) : HArithmeticBinaryOperation(context, left, right) {
4980 SetFlag(kCanBeDivByZero);
4981 SetFlag(kCanOverflow);
4982 SetFlag(kLeftCanBeNegative);
4987 class HDiv FINAL : public HArithmeticBinaryOperation {
4989 static HInstruction* New(Zone* zone,
4994 virtual HValue* Canonicalize() OVERRIDE;
4996 virtual void UpdateRepresentation(Representation new_rep,
4997 HInferRepresentationPhase* h_infer,
4998 const char* reason) OVERRIDE {
4999 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5000 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5003 DECLARE_CONCRETE_INSTRUCTION(Div)
5006 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
5008 virtual Range* InferRange(Zone* zone) OVERRIDE;
5011 HDiv(HValue* context, HValue* left, HValue* right)
5012 : HArithmeticBinaryOperation(context, left, right) {
5013 SetFlag(kCanBeDivByZero);
5014 SetFlag(kCanOverflow);
5019 class HMathMinMax FINAL : public HArithmeticBinaryOperation {
5021 enum Operation { kMathMin, kMathMax };
5023 static HInstruction* New(Zone* zone,
5029 virtual Representation observed_input_representation(int index) OVERRIDE {
5030 return RequiredInputRepresentation(index);
5033 virtual void InferRepresentation(
5034 HInferRepresentationPhase* h_infer) OVERRIDE;
5036 virtual Representation RepresentationFromInputs() OVERRIDE {
5037 Representation left_rep = left()->representation();
5038 Representation right_rep = right()->representation();
5039 Representation result = Representation::Smi();
5040 result = result.generalize(left_rep);
5041 result = result.generalize(right_rep);
5042 if (result.IsTagged()) return Representation::Double();
5046 virtual bool IsCommutative() const OVERRIDE { return true; }
5048 Operation operation() { return operation_; }
5050 DECLARE_CONCRETE_INSTRUCTION(MathMinMax)
5053 virtual bool DataEquals(HValue* other) OVERRIDE {
5054 return other->IsMathMinMax() &&
5055 HMathMinMax::cast(other)->operation_ == operation_;
5058 virtual Range* InferRange(Zone* zone) OVERRIDE;
5061 HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
5062 : HArithmeticBinaryOperation(context, left, right),
5065 Operation operation_;
5069 class HBitwise FINAL : public HBitwiseBinaryOperation {
5071 static HInstruction* New(Zone* zone,
5077 Token::Value op() const { return op_; }
5079 virtual bool IsCommutative() const OVERRIDE { return true; }
5081 virtual HValue* Canonicalize() OVERRIDE;
5083 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5085 DECLARE_CONCRETE_INSTRUCTION(Bitwise)
5088 virtual bool DataEquals(HValue* other) OVERRIDE {
5089 return op() == HBitwise::cast(other)->op();
5092 virtual Range* InferRange(Zone* zone) OVERRIDE;
5095 HBitwise(HValue* context,
5099 : HBitwiseBinaryOperation(context, left, right),
5101 DCHECK(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
5102 // BIT_AND with a smi-range positive value will always unset the
5103 // entire sign-extension of the smi-sign.
5104 if (op == Token::BIT_AND &&
5105 ((left->IsConstant() &&
5106 left->representation().IsSmi() &&
5107 HConstant::cast(left)->Integer32Value() >= 0) ||
5108 (right->IsConstant() &&
5109 right->representation().IsSmi() &&
5110 HConstant::cast(right)->Integer32Value() >= 0))) {
5111 SetFlag(kTruncatingToSmi);
5112 SetFlag(kTruncatingToInt32);
5113 // BIT_OR with a smi-range negative value will always set the entire
5114 // sign-extension of the smi-sign.
5115 } else if (op == Token::BIT_OR &&
5116 ((left->IsConstant() &&
5117 left->representation().IsSmi() &&
5118 HConstant::cast(left)->Integer32Value() < 0) ||
5119 (right->IsConstant() &&
5120 right->representation().IsSmi() &&
5121 HConstant::cast(right)->Integer32Value() < 0))) {
5122 SetFlag(kTruncatingToSmi);
5123 SetFlag(kTruncatingToInt32);
5131 class HShl FINAL : public HBitwiseBinaryOperation {
5133 static HInstruction* New(Zone* zone,
5138 virtual Range* InferRange(Zone* zone) OVERRIDE;
5140 virtual void UpdateRepresentation(Representation new_rep,
5141 HInferRepresentationPhase* h_infer,
5142 const char* reason) OVERRIDE {
5143 if (new_rep.IsSmi() &&
5144 !(right()->IsInteger32Constant() &&
5145 right()->GetInteger32Constant() >= 0)) {
5146 new_rep = Representation::Integer32();
5148 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5151 DECLARE_CONCRETE_INSTRUCTION(Shl)
5154 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
5157 HShl(HValue* context, HValue* left, HValue* right)
5158 : HBitwiseBinaryOperation(context, left, right) { }
5162 class HShr FINAL : public HBitwiseBinaryOperation {
5164 static HInstruction* New(Zone* zone,
5169 virtual bool TryDecompose(DecompositionResult* decomposition) OVERRIDE {
5170 if (right()->IsInteger32Constant()) {
5171 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
5172 // This is intended to look for HAdd and HSub, to handle compounds
5173 // like ((base + offset) >> scale) with one single decomposition.
5174 left()->TryDecompose(decomposition);
5181 virtual Range* InferRange(Zone* zone) OVERRIDE;
5183 virtual void UpdateRepresentation(Representation new_rep,
5184 HInferRepresentationPhase* h_infer,
5185 const char* reason) OVERRIDE {
5186 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5187 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5190 DECLARE_CONCRETE_INSTRUCTION(Shr)
5193 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
5196 HShr(HValue* context, HValue* left, HValue* right)
5197 : HBitwiseBinaryOperation(context, left, right) { }
5201 class HSar FINAL : public HBitwiseBinaryOperation {
5203 static HInstruction* New(Zone* zone,
5208 virtual bool TryDecompose(DecompositionResult* decomposition) OVERRIDE {
5209 if (right()->IsInteger32Constant()) {
5210 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
5211 // This is intended to look for HAdd and HSub, to handle compounds
5212 // like ((base + offset) >> scale) with one single decomposition.
5213 left()->TryDecompose(decomposition);
5220 virtual Range* InferRange(Zone* zone) OVERRIDE;
5222 virtual void UpdateRepresentation(Representation new_rep,
5223 HInferRepresentationPhase* h_infer,
5224 const char* reason) OVERRIDE {
5225 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5226 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5229 DECLARE_CONCRETE_INSTRUCTION(Sar)
5232 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
5235 HSar(HValue* context, HValue* left, HValue* right)
5236 : HBitwiseBinaryOperation(context, left, right) { }
5240 class HRor FINAL : public HBitwiseBinaryOperation {
5242 static HInstruction* New(Zone* zone,
5246 return new(zone) HRor(context, left, right);
5249 virtual void UpdateRepresentation(Representation new_rep,
5250 HInferRepresentationPhase* h_infer,
5251 const char* reason) OVERRIDE {
5252 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5253 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5256 DECLARE_CONCRETE_INSTRUCTION(Ror)
5259 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
5262 HRor(HValue* context, HValue* left, HValue* right)
5263 : HBitwiseBinaryOperation(context, left, right) {
5264 ChangeRepresentation(Representation::Integer32());
5269 class HOsrEntry FINAL : public HTemplateInstruction<0> {
5271 DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId);
5273 BailoutId ast_id() const { return ast_id_; }
5275 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
5276 return Representation::None();
5279 DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
5282 explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
5283 SetChangesFlag(kOsrEntries);
5284 SetChangesFlag(kNewSpacePromotion);
5291 class HParameter FINAL : public HTemplateInstruction<0> {
5293 enum ParameterKind {
5298 DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned);
5299 DECLARE_INSTRUCTION_FACTORY_P2(HParameter, unsigned, ParameterKind);
5300 DECLARE_INSTRUCTION_FACTORY_P3(HParameter, unsigned, ParameterKind,
5303 unsigned index() const { return index_; }
5304 ParameterKind kind() const { return kind_; }
5306 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5308 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
5309 return Representation::None();
5312 DECLARE_CONCRETE_INSTRUCTION(Parameter)
5315 explicit HParameter(unsigned index,
5316 ParameterKind kind = STACK_PARAMETER)
5319 set_representation(Representation::Tagged());
5322 explicit HParameter(unsigned index,
5327 set_representation(r);
5331 ParameterKind kind_;
5335 class HCallStub FINAL : public HUnaryCall {
5337 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallStub, CodeStub::Major, int);
5338 CodeStub::Major major_key() { return major_key_; }
5340 HValue* context() { return value(); }
5342 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5344 DECLARE_CONCRETE_INSTRUCTION(CallStub)
5347 HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
5348 : HUnaryCall(context, argument_count),
5349 major_key_(major_key) {
5352 CodeStub::Major major_key_;
5356 class HTailCallThroughMegamorphicCache FINAL : public HTemplateInstruction<3> {
5358 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HTailCallThroughMegamorphicCache,
5359 HValue*, HValue*, Code::Flags);
5361 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
5362 return Representation::Tagged();
5365 HValue* context() const { return OperandAt(0); }
5366 HValue* receiver() const { return OperandAt(1); }
5367 HValue* name() const { return OperandAt(2); }
5368 Code::Flags flags() const { return flags_; }
5370 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5372 DECLARE_CONCRETE_INSTRUCTION(TailCallThroughMegamorphicCache)
5375 HTailCallThroughMegamorphicCache(HValue* context, HValue* receiver,
5376 HValue* name, Code::Flags flags)
5378 SetOperandAt(0, context);
5379 SetOperandAt(1, receiver);
5380 SetOperandAt(2, name);
5387 class HUnknownOSRValue FINAL : public HTemplateInstruction<0> {
5389 DECLARE_INSTRUCTION_FACTORY_P2(HUnknownOSRValue, HEnvironment*, int);
5391 virtual OStream& PrintDataTo(OStream& os) const; // NOLINT
5393 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
5394 return Representation::None();
5397 void set_incoming_value(HPhi* value) { incoming_value_ = value; }
5398 HPhi* incoming_value() { return incoming_value_; }
5399 HEnvironment *environment() { return environment_; }
5400 int index() { return index_; }
5402 virtual Representation KnownOptimalRepresentation() OVERRIDE {
5403 if (incoming_value_ == NULL) return Representation::None();
5404 return incoming_value_->KnownOptimalRepresentation();
5407 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
5410 HUnknownOSRValue(HEnvironment* environment, int index)
5411 : environment_(environment),
5413 incoming_value_(NULL) {
5414 set_representation(Representation::Tagged());
5417 HEnvironment* environment_;
5419 HPhi* incoming_value_;
5423 class HLoadGlobalCell FINAL : public HTemplateInstruction<0> {
5425 DECLARE_INSTRUCTION_FACTORY_P2(HLoadGlobalCell, Handle<Cell>,
5428 Unique<Cell> cell() const { return cell_; }
5429 bool RequiresHoleCheck() const;
5431 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5433 virtual intptr_t Hashcode() OVERRIDE {
5434 return cell_.Hashcode();
5437 virtual void FinalizeUniqueness() OVERRIDE {
5438 cell_ = Unique<Cell>(cell_.handle());
5441 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
5442 return Representation::None();
5445 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell)
5448 virtual bool DataEquals(HValue* other) OVERRIDE {
5449 return cell_ == HLoadGlobalCell::cast(other)->cell_;
5453 HLoadGlobalCell(Handle<Cell> cell, PropertyDetails details)
5454 : cell_(Unique<Cell>::CreateUninitialized(cell)), details_(details) {
5455 set_representation(Representation::Tagged());
5457 SetDependsOnFlag(kGlobalVars);
5460 virtual bool IsDeletable() const OVERRIDE { return !RequiresHoleCheck(); }
5463 PropertyDetails details_;
5467 class HLoadGlobalGeneric FINAL : public HTemplateInstruction<2> {
5469 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadGlobalGeneric, HValue*,
5470 Handle<String>, bool);
5472 HValue* context() { return OperandAt(0); }
5473 HValue* global_object() { return OperandAt(1); }
5474 Handle<String> name() const { return name_; }
5475 bool for_typeof() const { return for_typeof_; }
5477 DCHECK(FLAG_vector_ics &&
5478 slot_ != FeedbackSlotInterface::kInvalidFeedbackSlot);
5481 Handle<FixedArray> feedback_vector() const { return feedback_vector_; }
5482 void SetVectorAndSlot(Handle<FixedArray> vector, int slot) {
5483 DCHECK(FLAG_vector_ics);
5484 feedback_vector_ = vector;
5488 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5490 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
5491 return Representation::Tagged();
5494 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
5497 HLoadGlobalGeneric(HValue* context, HValue* global_object,
5498 Handle<String> name, bool for_typeof)
5499 : name_(name), for_typeof_(for_typeof),
5500 slot_(FeedbackSlotInterface::kInvalidFeedbackSlot) {
5501 SetOperandAt(0, context);
5502 SetOperandAt(1, global_object);
5503 set_representation(Representation::Tagged());
5504 SetAllSideEffects();
5507 Handle<String> name_;
5509 Handle<FixedArray> feedback_vector_;
5514 class HAllocate FINAL : public HTemplateInstruction<2> {
5516 static bool CompatibleInstanceTypes(InstanceType type1,
5517 InstanceType type2) {
5518 return ComputeFlags(TENURED, type1) == ComputeFlags(TENURED, type2) &&
5519 ComputeFlags(NOT_TENURED, type1) == ComputeFlags(NOT_TENURED, type2);
5522 static HAllocate* New(Zone* zone,
5526 PretenureFlag pretenure_flag,
5527 InstanceType instance_type,
5528 Handle<AllocationSite> allocation_site =
5529 Handle<AllocationSite>::null()) {
5530 return new(zone) HAllocate(context, size, type, pretenure_flag,
5531 instance_type, allocation_site);
5534 // Maximum instance size for which allocations will be inlined.
5535 static const int kMaxInlineSize = 64 * kPointerSize;
5537 HValue* context() const { return OperandAt(0); }
5538 HValue* size() const { return OperandAt(1); }
5540 bool has_size_upper_bound() { return size_upper_bound_ != NULL; }
5541 HConstant* size_upper_bound() { return size_upper_bound_; }
5542 void set_size_upper_bound(HConstant* value) {
5543 DCHECK(size_upper_bound_ == NULL);
5544 size_upper_bound_ = value;
5547 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
5549 return Representation::Tagged();
5551 return Representation::Integer32();
5555 virtual Handle<Map> GetMonomorphicJSObjectMap() OVERRIDE {
5556 return known_initial_map_;
5559 void set_known_initial_map(Handle<Map> known_initial_map) {
5560 known_initial_map_ = known_initial_map;
5563 bool IsNewSpaceAllocation() const {
5564 return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
5567 bool IsOldDataSpaceAllocation() const {
5568 return (flags_ & ALLOCATE_IN_OLD_DATA_SPACE) != 0;
5571 bool IsOldPointerSpaceAllocation() const {
5572 return (flags_ & ALLOCATE_IN_OLD_POINTER_SPACE) != 0;
5575 bool MustAllocateDoubleAligned() const {
5576 return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
5579 bool MustPrefillWithFiller() const {
5580 return (flags_ & PREFILL_WITH_FILLER) != 0;
5583 void MakePrefillWithFiller() {
5584 flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
5587 bool MustClearNextMapWord() const {
5588 return (flags_ & CLEAR_NEXT_MAP_WORD) != 0;
5591 void MakeDoubleAligned() {
5592 flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
5595 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
5596 HValue* dominator) OVERRIDE;
5598 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5600 DECLARE_CONCRETE_INSTRUCTION(Allocate)
5604 ALLOCATE_IN_NEW_SPACE = 1 << 0,
5605 ALLOCATE_IN_OLD_DATA_SPACE = 1 << 1,
5606 ALLOCATE_IN_OLD_POINTER_SPACE = 1 << 2,
5607 ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
5608 PREFILL_WITH_FILLER = 1 << 4,
5609 CLEAR_NEXT_MAP_WORD = 1 << 5
5612 HAllocate(HValue* context,
5615 PretenureFlag pretenure_flag,
5616 InstanceType instance_type,
5617 Handle<AllocationSite> allocation_site =
5618 Handle<AllocationSite>::null())
5619 : HTemplateInstruction<2>(type),
5620 flags_(ComputeFlags(pretenure_flag, instance_type)),
5621 dominating_allocate_(NULL),
5622 filler_free_space_size_(NULL),
5623 size_upper_bound_(NULL) {
5624 SetOperandAt(0, context);
5626 set_representation(Representation::Tagged());
5627 SetFlag(kTrackSideEffectDominators);
5628 SetChangesFlag(kNewSpacePromotion);
5629 SetDependsOnFlag(kNewSpacePromotion);
5631 if (FLAG_trace_pretenuring) {
5632 PrintF("HAllocate with AllocationSite %p %s\n",
5633 allocation_site.is_null()
5634 ? static_cast<void*>(NULL)
5635 : static_cast<void*>(*allocation_site),
5636 pretenure_flag == TENURED ? "tenured" : "not tenured");
5640 static Flags ComputeFlags(PretenureFlag pretenure_flag,
5641 InstanceType instance_type) {
5642 Flags flags = pretenure_flag == TENURED
5643 ? (Heap::TargetSpaceId(instance_type) == OLD_POINTER_SPACE
5644 ? ALLOCATE_IN_OLD_POINTER_SPACE : ALLOCATE_IN_OLD_DATA_SPACE)
5645 : ALLOCATE_IN_NEW_SPACE;
5646 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
5647 flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED);
5649 // We have to fill the allocated object with one word fillers if we do
5650 // not use allocation folding since some allocations may depend on each
5651 // other, i.e., have a pointer to each other. A GC in between these
5652 // allocations may leave such objects behind in a not completely initialized
5654 if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
5655 flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER);
5657 if (pretenure_flag == NOT_TENURED &&
5658 AllocationSite::CanTrack(instance_type)) {
5659 flags = static_cast<Flags>(flags | CLEAR_NEXT_MAP_WORD);
5664 void UpdateClearNextMapWord(bool clear_next_map_word) {
5665 flags_ = static_cast<Flags>(clear_next_map_word
5666 ? flags_ | CLEAR_NEXT_MAP_WORD
5667 : flags_ & ~CLEAR_NEXT_MAP_WORD);
5670 void UpdateSize(HValue* size) {
5671 SetOperandAt(1, size);
5672 if (size->IsInteger32Constant()) {
5673 size_upper_bound_ = HConstant::cast(size);
5675 size_upper_bound_ = NULL;
5679 HAllocate* GetFoldableDominator(HAllocate* dominator);
5681 void UpdateFreeSpaceFiller(int32_t filler_size);
5683 void CreateFreeSpaceFiller(int32_t filler_size);
5685 bool IsFoldable(HAllocate* allocate) {
5686 return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) ||
5687 (IsOldDataSpaceAllocation() && allocate->IsOldDataSpaceAllocation()) ||
5688 (IsOldPointerSpaceAllocation() &&
5689 allocate->IsOldPointerSpaceAllocation());
5692 void ClearNextMapWord(int offset);
5695 Handle<Map> known_initial_map_;
5696 HAllocate* dominating_allocate_;
5697 HStoreNamedField* filler_free_space_size_;
5698 HConstant* size_upper_bound_;
5702 class HStoreCodeEntry FINAL: public HTemplateInstruction<2> {
5704 static HStoreCodeEntry* New(Zone* zone,
5708 return new(zone) HStoreCodeEntry(function, code);
5711 virtual Representation RequiredInputRepresentation(int index) {
5712 return Representation::Tagged();
5715 HValue* function() { return OperandAt(0); }
5716 HValue* code_object() { return OperandAt(1); }
5718 DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry)
5721 HStoreCodeEntry(HValue* function, HValue* code) {
5722 SetOperandAt(0, function);
5723 SetOperandAt(1, code);
5728 class HInnerAllocatedObject FINAL : public HTemplateInstruction<2> {
5730 static HInnerAllocatedObject* New(Zone* zone,
5735 return new(zone) HInnerAllocatedObject(value, offset, type);
5738 HValue* base_object() const { return OperandAt(0); }
5739 HValue* offset() const { return OperandAt(1); }
5741 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
5742 return index == 0 ? Representation::Tagged() : Representation::Integer32();
5745 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5747 DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
5750 HInnerAllocatedObject(HValue* value,
5752 HType type) : HTemplateInstruction<2>(type) {
5753 DCHECK(value->IsAllocate());
5754 DCHECK(type.IsHeapObject());
5755 SetOperandAt(0, value);
5756 SetOperandAt(1, offset);
5757 set_representation(Representation::Tagged());
5762 inline bool StoringValueNeedsWriteBarrier(HValue* value) {
5763 return !value->type().IsSmi()
5764 && !value->type().IsNull()
5765 && !value->type().IsBoolean()
5766 && !value->type().IsUndefined()
5767 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
5771 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
5773 HValue* dominator) {
5774 while (object->IsInnerAllocatedObject()) {
5775 object = HInnerAllocatedObject::cast(object)->base_object();
5777 if (object->IsConstant() && HConstant::cast(object)->IsCell()) {
5780 if (object->IsConstant() &&
5781 HConstant::cast(object)->HasExternalReferenceValue()) {
5782 // Stores to external references require no write barriers
5785 // We definitely need a write barrier unless the object is the allocation
5787 if (object == dominator && object->IsAllocate()) {
5788 // Stores to new space allocations require no write barriers.
5789 if (HAllocate::cast(object)->IsNewSpaceAllocation()) {
5792 // Stores to old space allocations require no write barriers if the value is
5793 // a constant provably not in new space.
5794 if (value->IsConstant() && HConstant::cast(value)->NotInNewSpace()) {
5797 // Stores to old space allocations require no write barriers if the value is
5798 // an old space allocation.
5799 while (value->IsInnerAllocatedObject()) {
5800 value = HInnerAllocatedObject::cast(value)->base_object();
5802 if (value->IsAllocate() &&
5803 !HAllocate::cast(value)->IsNewSpaceAllocation()) {
5811 inline PointersToHereCheck PointersToHereCheckForObject(HValue* object,
5812 HValue* dominator) {
5813 while (object->IsInnerAllocatedObject()) {
5814 object = HInnerAllocatedObject::cast(object)->base_object();
5816 if (object == dominator &&
5817 object->IsAllocate() &&
5818 HAllocate::cast(object)->IsNewSpaceAllocation()) {
5819 return kPointersToHereAreAlwaysInteresting;
5821 return kPointersToHereMaybeInteresting;
5825 class HStoreGlobalCell FINAL : public HUnaryOperation {
5827 DECLARE_INSTRUCTION_FACTORY_P3(HStoreGlobalCell, HValue*,
5828 Handle<PropertyCell>, PropertyDetails);
5830 Unique<PropertyCell> cell() const { return cell_; }
5831 bool RequiresHoleCheck() { return details_.IsConfigurable(); }
5832 bool NeedsWriteBarrier() {
5833 return StoringValueNeedsWriteBarrier(value());
5836 virtual void FinalizeUniqueness() OVERRIDE {
5837 cell_ = Unique<PropertyCell>(cell_.handle());
5840 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
5841 return Representation::Tagged();
5843 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5845 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell)
5848 HStoreGlobalCell(HValue* value,
5849 Handle<PropertyCell> cell,
5850 PropertyDetails details)
5851 : HUnaryOperation(value),
5852 cell_(Unique<PropertyCell>::CreateUninitialized(cell)),
5854 SetChangesFlag(kGlobalVars);
5857 Unique<PropertyCell> cell_;
5858 PropertyDetails details_;
5862 class HLoadContextSlot FINAL : public HUnaryOperation {
5865 // Perform a normal load of the context slot without checking its value.
5867 // Load and check the value of the context slot. Deoptimize if it's the
5868 // hole value. This is used for checking for loading of uninitialized
5869 // harmony bindings where we deoptimize into full-codegen generated code
5870 // which will subsequently throw a reference error.
5872 // Load and check the value of the context slot. Return undefined if it's
5873 // the hole value. This is used for non-harmony const assignments
5874 kCheckReturnUndefined
5877 HLoadContextSlot(HValue* context, int slot_index, Mode mode)
5878 : HUnaryOperation(context), slot_index_(slot_index), mode_(mode) {
5879 set_representation(Representation::Tagged());
5881 SetDependsOnFlag(kContextSlots);
5884 int slot_index() const { return slot_index_; }
5885 Mode mode() const { return mode_; }
5887 bool DeoptimizesOnHole() {
5888 return mode_ == kCheckDeoptimize;
5891 bool RequiresHoleCheck() const {
5892 return mode_ != kNoCheck;
5895 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
5896 return Representation::Tagged();
5899 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5901 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
5904 virtual bool DataEquals(HValue* other) OVERRIDE {
5905 HLoadContextSlot* b = HLoadContextSlot::cast(other);
5906 return (slot_index() == b->slot_index());
5910 virtual bool IsDeletable() const OVERRIDE { return !RequiresHoleCheck(); }
5917 class HStoreContextSlot FINAL : public HTemplateInstruction<2> {
5920 // Perform a normal store to the context slot without checking its previous
5923 // Check the previous value of the context slot and deoptimize if it's the
5924 // hole value. This is used for checking for assignments to uninitialized
5925 // harmony bindings where we deoptimize into full-codegen generated code
5926 // which will subsequently throw a reference error.
5928 // Check the previous value and ignore assignment if it isn't a hole value
5929 kCheckIgnoreAssignment
5932 DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
5935 HValue* context() const { return OperandAt(0); }
5936 HValue* value() const { return OperandAt(1); }
5937 int slot_index() const { return slot_index_; }
5938 Mode mode() const { return mode_; }
5940 bool NeedsWriteBarrier() {
5941 return StoringValueNeedsWriteBarrier(value());
5944 bool DeoptimizesOnHole() {
5945 return mode_ == kCheckDeoptimize;
5948 bool RequiresHoleCheck() {
5949 return mode_ != kNoCheck;
5952 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
5953 return Representation::Tagged();
5956 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
5958 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
5961 HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
5962 : slot_index_(slot_index), mode_(mode) {
5963 SetOperandAt(0, context);
5964 SetOperandAt(1, value);
5965 SetChangesFlag(kContextSlots);
5973 // Represents an access to a portion of an object, such as the map pointer,
5974 // array elements pointer, etc, but not accesses to array elements themselves.
5975 class HObjectAccess FINAL {
5977 inline bool IsInobject() const {
5978 return portion() != kBackingStore && portion() != kExternalMemory;
5981 inline bool IsExternalMemory() const {
5982 return portion() == kExternalMemory;
5985 inline bool IsStringLength() const {
5986 return portion() == kStringLengths;
5989 inline bool IsMap() const {
5990 return portion() == kMaps;
5993 inline int offset() const {
5994 return OffsetField::decode(value_);
5997 inline Representation representation() const {
5998 return Representation::FromKind(RepresentationField::decode(value_));
6001 inline Handle<String> name() const {
6005 inline bool immutable() const {
6006 return ImmutableField::decode(value_);
6009 // Returns true if access is being made to an in-object property that
6010 // was already added to the object.
6011 inline bool existing_inobject_property() const {
6012 return ExistingInobjectPropertyField::decode(value_);
6015 inline HObjectAccess WithRepresentation(Representation representation) {
6016 return HObjectAccess(portion(), offset(), representation, name(),
6017 immutable(), existing_inobject_property());
6020 static HObjectAccess ForHeapNumberValue() {
6021 return HObjectAccess(
6022 kDouble, HeapNumber::kValueOffset, Representation::Double());
6025 static HObjectAccess ForHeapNumberValueLowestBits() {
6026 return HObjectAccess(kDouble,
6027 HeapNumber::kValueOffset,
6028 Representation::Integer32());
6031 static HObjectAccess ForHeapNumberValueHighestBits() {
6032 return HObjectAccess(kDouble,
6033 HeapNumber::kValueOffset + kIntSize,
6034 Representation::Integer32());
6037 static HObjectAccess ForElementsPointer() {
6038 return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
6041 static HObjectAccess ForLiteralsPointer() {
6042 return HObjectAccess(kInobject, JSFunction::kLiteralsOffset);
6045 static HObjectAccess ForNextFunctionLinkPointer() {
6046 return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
6049 static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
6050 return HObjectAccess(
6052 JSArray::kLengthOffset,
6053 IsFastElementsKind(elements_kind)
6054 ? Representation::Smi() : Representation::Tagged());
6057 static HObjectAccess ForAllocationSiteOffset(int offset);
6059 static HObjectAccess ForAllocationSiteList() {
6060 return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
6061 Handle<String>::null(), false, false);
6064 static HObjectAccess ForFixedArrayLength() {
6065 return HObjectAccess(
6067 FixedArray::kLengthOffset,
6068 Representation::Smi());
6071 static HObjectAccess ForStringHashField() {
6072 return HObjectAccess(kInobject,
6073 String::kHashFieldOffset,
6074 Representation::Integer32());
6077 static HObjectAccess ForStringLength() {
6078 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
6079 return HObjectAccess(
6081 String::kLengthOffset,
6082 Representation::Smi());
6085 static HObjectAccess ForConsStringFirst() {
6086 return HObjectAccess(kInobject, ConsString::kFirstOffset);
6089 static HObjectAccess ForConsStringSecond() {
6090 return HObjectAccess(kInobject, ConsString::kSecondOffset);
6093 static HObjectAccess ForPropertiesPointer() {
6094 return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
6097 static HObjectAccess ForPrototypeOrInitialMap() {
6098 return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
6101 static HObjectAccess ForSharedFunctionInfoPointer() {
6102 return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
6105 static HObjectAccess ForCodeEntryPointer() {
6106 return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
6109 static HObjectAccess ForCodeOffset() {
6110 return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
6113 static HObjectAccess ForOptimizedCodeMap() {
6114 return HObjectAccess(kInobject,
6115 SharedFunctionInfo::kOptimizedCodeMapOffset);
6118 static HObjectAccess ForFunctionContextPointer() {
6119 return HObjectAccess(kInobject, JSFunction::kContextOffset);
6122 static HObjectAccess ForMap() {
6123 return HObjectAccess(kMaps, JSObject::kMapOffset);
6126 static HObjectAccess ForMapAsInteger32() {
6127 return HObjectAccess(kMaps, JSObject::kMapOffset,
6128 Representation::Integer32());
6131 static HObjectAccess ForMapInObjectProperties() {
6132 return HObjectAccess(kInobject,
6133 Map::kInObjectPropertiesOffset,
6134 Representation::UInteger8());
6137 static HObjectAccess ForMapInstanceType() {
6138 return HObjectAccess(kInobject,
6139 Map::kInstanceTypeOffset,
6140 Representation::UInteger8());
6143 static HObjectAccess ForMapInstanceSize() {
6144 return HObjectAccess(kInobject,
6145 Map::kInstanceSizeOffset,
6146 Representation::UInteger8());
6149 static HObjectAccess ForMapBitField() {
6150 return HObjectAccess(kInobject,
6151 Map::kBitFieldOffset,
6152 Representation::UInteger8());
6155 static HObjectAccess ForMapBitField2() {
6156 return HObjectAccess(kInobject,
6157 Map::kBitField2Offset,
6158 Representation::UInteger8());
6161 static HObjectAccess ForNameHashField() {
6162 return HObjectAccess(kInobject,
6163 Name::kHashFieldOffset,
6164 Representation::Integer32());
6167 static HObjectAccess ForMapInstanceTypeAndBitField() {
6168 STATIC_ASSERT((Map::kInstanceTypeAndBitFieldOffset & 1) == 0);
6169 // Ensure the two fields share one 16-bit word, endian-independent.
6170 STATIC_ASSERT((Map::kBitFieldOffset & ~1) ==
6171 (Map::kInstanceTypeOffset & ~1));
6172 return HObjectAccess(kInobject,
6173 Map::kInstanceTypeAndBitFieldOffset,
6174 Representation::UInteger16());
6177 static HObjectAccess ForPropertyCellValue() {
6178 return HObjectAccess(kInobject, PropertyCell::kValueOffset);
6181 static HObjectAccess ForCellValue() {
6182 return HObjectAccess(kInobject, Cell::kValueOffset);
6185 static HObjectAccess ForAllocationMementoSite() {
6186 return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
6189 static HObjectAccess ForCounter() {
6190 return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
6191 Handle<String>::null(), false, false);
6194 static HObjectAccess ForExternalUInteger8() {
6195 return HObjectAccess(kExternalMemory, 0, Representation::UInteger8(),
6196 Handle<String>::null(), false, false);
6199 // Create an access to an offset in a fixed array header.
6200 static HObjectAccess ForFixedArrayHeader(int offset);
6202 // Create an access to an in-object property in a JSObject.
6203 // This kind of access must be used when the object |map| is known and
6204 // in-object properties are being accessed. Accesses of the in-object
6205 // properties can have different semantics depending on whether corresponding
6206 // property was added to the map or not.
6207 static HObjectAccess ForMapAndOffset(Handle<Map> map, int offset,
6208 Representation representation = Representation::Tagged());
6210 // Create an access to an in-object property in a JSObject.
6211 // This kind of access can be used for accessing object header fields or
6212 // in-object properties if the map of the object is not known.
6213 static HObjectAccess ForObservableJSObjectOffset(int offset,
6214 Representation representation = Representation::Tagged()) {
6215 return ForMapAndOffset(Handle<Map>::null(), offset, representation);
6218 // Create an access to an in-object property in a JSArray.
6219 static HObjectAccess ForJSArrayOffset(int offset);
6221 static HObjectAccess ForContextSlot(int index);
6223 // Create an access to the backing store of an object.
6224 static HObjectAccess ForBackingStoreOffset(int offset,
6225 Representation representation = Representation::Tagged());
6227 // Create an access to a resolved field (in-object or backing store).
6228 static HObjectAccess ForField(Handle<Map> map, int index,
6229 Representation representation,
6230 Handle<String> name);
6232 // Create an access for the payload of a Cell or JSGlobalPropertyCell.
6233 static HObjectAccess ForCellPayload(Isolate* isolate);
6235 static HObjectAccess ForJSTypedArrayLength() {
6236 return HObjectAccess::ForObservableJSObjectOffset(
6237 JSTypedArray::kLengthOffset);
6240 static HObjectAccess ForJSArrayBufferBackingStore() {
6241 return HObjectAccess::ForObservableJSObjectOffset(
6242 JSArrayBuffer::kBackingStoreOffset, Representation::External());
6245 static HObjectAccess ForJSArrayBufferByteLength() {
6246 return HObjectAccess::ForObservableJSObjectOffset(
6247 JSArrayBuffer::kByteLengthOffset, Representation::Tagged());
6250 static HObjectAccess ForExternalArrayExternalPointer() {
6251 return HObjectAccess::ForObservableJSObjectOffset(
6252 ExternalArray::kExternalPointerOffset, Representation::External());
6255 static HObjectAccess ForJSArrayBufferViewWeakNext() {
6256 return HObjectAccess::ForObservableJSObjectOffset(
6257 JSArrayBufferView::kWeakNextOffset);
6260 static HObjectAccess ForJSArrayBufferWeakFirstView() {
6261 return HObjectAccess::ForObservableJSObjectOffset(
6262 JSArrayBuffer::kWeakFirstViewOffset);
6265 static HObjectAccess ForJSArrayBufferViewBuffer() {
6266 return HObjectAccess::ForObservableJSObjectOffset(
6267 JSArrayBufferView::kBufferOffset);
6270 static HObjectAccess ForJSArrayBufferViewByteOffset() {
6271 return HObjectAccess::ForObservableJSObjectOffset(
6272 JSArrayBufferView::kByteOffsetOffset);
6275 static HObjectAccess ForJSArrayBufferViewByteLength() {
6276 return HObjectAccess::ForObservableJSObjectOffset(
6277 JSArrayBufferView::kByteLengthOffset);
6280 static HObjectAccess ForGlobalObjectNativeContext() {
6281 return HObjectAccess(kInobject, GlobalObject::kNativeContextOffset);
6284 inline bool Equals(HObjectAccess that) const {
6285 return value_ == that.value_; // portion and offset must match
6289 void SetGVNFlags(HValue *instr, PropertyAccessType access_type);
6292 // internal use only; different parts of an object or array
6294 kMaps, // map of an object
6295 kArrayLengths, // the length of an array
6296 kStringLengths, // the length of a string
6297 kElementsPointer, // elements pointer
6298 kBackingStore, // some field in the backing store
6299 kDouble, // some double field
6300 kInobject, // some other in-object field
6301 kExternalMemory // some field in external memory
6304 HObjectAccess() : value_(0) {}
6306 HObjectAccess(Portion portion, int offset,
6307 Representation representation = Representation::Tagged(),
6308 Handle<String> name = Handle<String>::null(),
6309 bool immutable = false,
6310 bool existing_inobject_property = true)
6311 : value_(PortionField::encode(portion) |
6312 RepresentationField::encode(representation.kind()) |
6313 ImmutableField::encode(immutable ? 1 : 0) |
6314 ExistingInobjectPropertyField::encode(
6315 existing_inobject_property ? 1 : 0) |
6316 OffsetField::encode(offset)),
6318 // assert that the fields decode correctly
6319 DCHECK(this->offset() == offset);
6320 DCHECK(this->portion() == portion);
6321 DCHECK(this->immutable() == immutable);
6322 DCHECK(this->existing_inobject_property() == existing_inobject_property);
6323 DCHECK(RepresentationField::decode(value_) == representation.kind());
6324 DCHECK(!this->existing_inobject_property() || IsInobject());
6327 class PortionField : public BitField<Portion, 0, 3> {};
6328 class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
6329 class ImmutableField : public BitField<bool, 7, 1> {};
6330 class ExistingInobjectPropertyField : public BitField<bool, 8, 1> {};
6331 class OffsetField : public BitField<int, 9, 23> {};
6333 uint32_t value_; // encodes portion, representation, immutable, and offset
6334 Handle<String> name_;
6336 friend class HLoadNamedField;
6337 friend class HStoreNamedField;
6338 friend class SideEffectsTracker;
6339 friend OStream& operator<<(OStream& os, const HObjectAccess& access);
6341 inline Portion portion() const {
6342 return PortionField::decode(value_);
6347 OStream& operator<<(OStream& os, const HObjectAccess& access);
6350 class HLoadNamedField FINAL : public HTemplateInstruction<2> {
6352 DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*,
6353 HValue*, HObjectAccess);
6354 DECLARE_INSTRUCTION_FACTORY_P5(HLoadNamedField, HValue*, HValue*,
6355 HObjectAccess, const UniqueSet<Map>*, HType);
6357 HValue* object() const { return OperandAt(0); }
6358 HValue* dependency() const {
6359 DCHECK(HasDependency());
6360 return OperandAt(1);
6362 bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
6363 HObjectAccess access() const { return access_; }
6364 Representation field_representation() const {
6365 return access_.representation();
6368 const UniqueSet<Map>* maps() const { return maps_; }
6370 virtual bool HasEscapingOperandAt(int index) OVERRIDE { return false; }
6371 virtual bool HasOutOfBoundsAccess(int size) OVERRIDE {
6372 return !access().IsInobject() || access().offset() >= size;
6374 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
6375 if (index == 0 && access().IsExternalMemory()) {
6376 // object must be external in case of external memory access
6377 return Representation::External();
6379 return Representation::Tagged();
6381 virtual Range* InferRange(Zone* zone) OVERRIDE;
6382 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
6384 bool CanBeReplacedWith(HValue* other) const {
6385 if (!CheckFlag(HValue::kCantBeReplaced)) return false;
6386 if (!type().Equals(other->type())) return false;
6387 if (!representation().Equals(other->representation())) return false;
6388 if (!other->IsLoadNamedField()) return true;
6389 HLoadNamedField* that = HLoadNamedField::cast(other);
6390 if (this->maps_ == that->maps_) return true;
6391 if (this->maps_ == NULL || that->maps_ == NULL) return false;
6392 return this->maps_->IsSubset(that->maps_);
6395 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
6398 virtual bool DataEquals(HValue* other) OVERRIDE {
6399 HLoadNamedField* that = HLoadNamedField::cast(other);
6400 if (!this->access_.Equals(that->access_)) return false;
6401 if (this->maps_ == that->maps_) return true;
6402 return (this->maps_ != NULL &&
6403 that->maps_ != NULL &&
6404 this->maps_->Equals(that->maps_));
6408 HLoadNamedField(HValue* object,
6410 HObjectAccess access)
6411 : access_(access), maps_(NULL) {
6412 DCHECK_NOT_NULL(object);
6413 SetOperandAt(0, object);
6414 SetOperandAt(1, dependency ? dependency : object);
6416 Representation representation = access.representation();
6417 if (representation.IsInteger8() ||
6418 representation.IsUInteger8() ||
6419 representation.IsInteger16() ||
6420 representation.IsUInteger16()) {
6421 set_representation(Representation::Integer32());
6422 } else if (representation.IsSmi()) {
6423 set_type(HType::Smi());
6424 if (SmiValuesAre32Bits()) {
6425 set_representation(Representation::Integer32());
6427 set_representation(representation);
6429 } else if (representation.IsDouble() ||
6430 representation.IsExternal() ||
6431 representation.IsInteger32()) {
6432 set_representation(representation);
6433 } else if (representation.IsHeapObject()) {
6434 set_type(HType::HeapObject());
6435 set_representation(Representation::Tagged());
6437 set_representation(Representation::Tagged());
6439 access.SetGVNFlags(this, LOAD);
6442 HLoadNamedField(HValue* object,
6444 HObjectAccess access,
6445 const UniqueSet<Map>* maps,
6447 : HTemplateInstruction<2>(type), access_(access), maps_(maps) {
6448 DCHECK_NOT_NULL(maps);
6449 DCHECK_NE(0, maps->size());
6451 DCHECK_NOT_NULL(object);
6452 SetOperandAt(0, object);
6453 SetOperandAt(1, dependency ? dependency : object);
6455 DCHECK(access.representation().IsHeapObject());
6456 DCHECK(type.IsHeapObject());
6457 set_representation(Representation::Tagged());
6459 access.SetGVNFlags(this, LOAD);
6462 virtual bool IsDeletable() const OVERRIDE { return true; }
6464 HObjectAccess access_;
6465 const UniqueSet<Map>* maps_;
6469 class HLoadNamedGeneric FINAL : public HTemplateInstruction<2> {
6471 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadNamedGeneric, HValue*,
6474 HValue* context() const { return OperandAt(0); }
6475 HValue* object() const { return OperandAt(1); }
6476 Handle<Object> name() const { return name_; }
6479 DCHECK(FLAG_vector_ics &&
6480 slot_ != FeedbackSlotInterface::kInvalidFeedbackSlot);
6483 Handle<FixedArray> feedback_vector() const { return feedback_vector_; }
6484 void SetVectorAndSlot(Handle<FixedArray> vector, int slot) {
6485 DCHECK(FLAG_vector_ics);
6486 feedback_vector_ = vector;
6490 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
6491 return Representation::Tagged();
6494 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
6496 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
6499 HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
6501 slot_(FeedbackSlotInterface::kInvalidFeedbackSlot) {
6502 SetOperandAt(0, context);
6503 SetOperandAt(1, object);
6504 set_representation(Representation::Tagged());
6505 SetAllSideEffects();
6508 Handle<Object> name_;
6509 Handle<FixedArray> feedback_vector_;
6514 class HLoadFunctionPrototype FINAL : public HUnaryOperation {
6516 DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);
6518 HValue* function() { return OperandAt(0); }
6520 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
6521 return Representation::Tagged();
6524 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
6527 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
6530 explicit HLoadFunctionPrototype(HValue* function)
6531 : HUnaryOperation(function) {
6532 set_representation(Representation::Tagged());
6534 SetDependsOnFlag(kCalls);
6538 class ArrayInstructionInterface {
6540 virtual HValue* GetKey() = 0;
6541 virtual void SetKey(HValue* key) = 0;
6542 virtual ElementsKind elements_kind() const = 0;
6543 // TryIncreaseBaseOffset returns false if overflow would result.
6544 virtual bool TryIncreaseBaseOffset(uint32_t increase_by_value) = 0;
6545 virtual bool IsDehoisted() const = 0;
6546 virtual void SetDehoisted(bool is_dehoisted) = 0;
6547 virtual ~ArrayInstructionInterface() { }
6549 static Representation KeyedAccessIndexRequirement(Representation r) {
6550 return r.IsInteger32() || SmiValuesAre32Bits()
6551 ? Representation::Integer32() : Representation::Smi();
6556 static const int kDefaultKeyedHeaderOffsetSentinel = -1;
6558 enum LoadKeyedHoleMode {
6564 class HLoadKeyed FINAL
6565 : public HTemplateInstruction<3>, public ArrayInstructionInterface {
6567 DECLARE_INSTRUCTION_FACTORY_P4(HLoadKeyed, HValue*, HValue*, HValue*,
6569 DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*,
6570 ElementsKind, LoadKeyedHoleMode);
6571 DECLARE_INSTRUCTION_FACTORY_P6(HLoadKeyed, HValue*, HValue*, HValue*,
6572 ElementsKind, LoadKeyedHoleMode, int);
6574 bool is_external() const {
6575 return IsExternalArrayElementsKind(elements_kind());
6577 bool is_fixed_typed_array() const {
6578 return IsFixedTypedArrayElementsKind(elements_kind());
6580 bool is_typed_elements() const {
6581 return is_external() || is_fixed_typed_array();
6583 HValue* elements() const { return OperandAt(0); }
6584 HValue* key() const { return OperandAt(1); }
6585 HValue* dependency() const {
6586 DCHECK(HasDependency());
6587 return OperandAt(2);
6589 bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
6590 uint32_t base_offset() const { return BaseOffsetField::decode(bit_field_); }
6591 bool TryIncreaseBaseOffset(uint32_t increase_by_value);
6592 HValue* GetKey() { return key(); }
6593 void SetKey(HValue* key) { SetOperandAt(1, key); }
6594 bool IsDehoisted() const { return IsDehoistedField::decode(bit_field_); }
6595 void SetDehoisted(bool is_dehoisted) {
6596 bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
6598 virtual ElementsKind elements_kind() const OVERRIDE {
6599 return ElementsKindField::decode(bit_field_);
6601 LoadKeyedHoleMode hole_mode() const {
6602 return HoleModeField::decode(bit_field_);
6605 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
6606 // kind_fast: tagged[int32] (none)
6607 // kind_double: tagged[int32] (none)
6608 // kind_fixed_typed_array: tagged[int32] (none)
6609 // kind_external: external[int32] (none)
6611 return is_external() ? Representation::External()
6612 : Representation::Tagged();
6615 return ArrayInstructionInterface::KeyedAccessIndexRequirement(
6616 OperandAt(1)->representation());
6618 return Representation::None();
6621 virtual Representation observed_input_representation(int index) OVERRIDE {
6622 return RequiredInputRepresentation(index);
6625 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
6627 bool UsesMustHandleHole() const;
6628 bool AllUsesCanTreatHoleAsNaN() const;
6629 bool RequiresHoleCheck() const;
6631 virtual Range* InferRange(Zone* zone) OVERRIDE;
6633 DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)
6636 virtual bool DataEquals(HValue* other) OVERRIDE {
6637 if (!other->IsLoadKeyed()) return false;
6638 HLoadKeyed* other_load = HLoadKeyed::cast(other);
6640 if (IsDehoisted() && base_offset() != other_load->base_offset())
6642 return elements_kind() == other_load->elements_kind();
6646 HLoadKeyed(HValue* obj,
6649 ElementsKind elements_kind,
6650 LoadKeyedHoleMode mode = NEVER_RETURN_HOLE,
6651 int offset = kDefaultKeyedHeaderOffsetSentinel)
6653 offset = offset == kDefaultKeyedHeaderOffsetSentinel
6654 ? GetDefaultHeaderSizeForElementsKind(elements_kind)
6656 bit_field_ = ElementsKindField::encode(elements_kind) |
6657 HoleModeField::encode(mode) |
6658 BaseOffsetField::encode(offset);
6660 SetOperandAt(0, obj);
6661 SetOperandAt(1, key);
6662 SetOperandAt(2, dependency != NULL ? dependency : obj);
6664 if (!is_typed_elements()) {
6665 // I can detect the case between storing double (holey and fast) and
6666 // smi/object by looking at elements_kind_.
6667 DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
6668 IsFastDoubleElementsKind(elements_kind));
6670 if (IsFastSmiOrObjectElementsKind(elements_kind)) {
6671 if (IsFastSmiElementsKind(elements_kind) &&
6672 (!IsHoleyElementsKind(elements_kind) ||
6673 mode == NEVER_RETURN_HOLE)) {
6674 set_type(HType::Smi());
6675 if (SmiValuesAre32Bits() && !RequiresHoleCheck()) {
6676 set_representation(Representation::Integer32());
6678 set_representation(Representation::Smi());
6681 set_representation(Representation::Tagged());
6684 SetDependsOnFlag(kArrayElements);
6686 set_representation(Representation::Double());
6687 SetDependsOnFlag(kDoubleArrayElements);
6690 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
6691 elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
6692 elements_kind == FLOAT32_ELEMENTS ||
6693 elements_kind == FLOAT64_ELEMENTS) {
6694 set_representation(Representation::Double());
6696 set_representation(Representation::Integer32());
6699 if (is_external()) {
6700 SetDependsOnFlag(kExternalMemory);
6701 } else if (is_fixed_typed_array()) {
6702 SetDependsOnFlag(kTypedArrayElements);
6706 // Native code could change the specialized array.
6707 SetDependsOnFlag(kCalls);
6713 virtual bool IsDeletable() const OVERRIDE {
6714 return !RequiresHoleCheck();
6717 // Establish some checks around our packed fields
6718 enum LoadKeyedBits {
6719 kBitsForElementsKind = 5,
6720 kBitsForHoleMode = 1,
6721 kBitsForBaseOffset = 25,
6722 kBitsForIsDehoisted = 1,
6724 kStartElementsKind = 0,
6725 kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
6726 kStartBaseOffset = kStartHoleMode + kBitsForHoleMode,
6727 kStartIsDehoisted = kStartBaseOffset + kBitsForBaseOffset
6730 STATIC_ASSERT((kBitsForElementsKind + kBitsForBaseOffset +
6731 kBitsForIsDehoisted) <= sizeof(uint32_t)*8);
6732 STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
6733 class ElementsKindField:
6734 public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
6736 class HoleModeField:
6737 public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
6739 class BaseOffsetField:
6740 public BitField<uint32_t, kStartBaseOffset, kBitsForBaseOffset>
6742 class IsDehoistedField:
6743 public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
6745 uint32_t bit_field_;
6749 class HLoadKeyedGeneric FINAL : public HTemplateInstruction<3> {
6751 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadKeyedGeneric, HValue*,
6753 HValue* object() const { return OperandAt(0); }
6754 HValue* key() const { return OperandAt(1); }
6755 HValue* context() const { return OperandAt(2); }
6757 DCHECK(FLAG_vector_ics &&
6758 slot_ != FeedbackSlotInterface::kInvalidFeedbackSlot);
6761 Handle<FixedArray> feedback_vector() const { return feedback_vector_; }
6762 void SetVectorAndSlot(Handle<FixedArray> vector, int slot) {
6763 DCHECK(FLAG_vector_ics);
6764 feedback_vector_ = vector;
6768 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
6770 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
6772 return Representation::Tagged();
6775 virtual HValue* Canonicalize() OVERRIDE;
6777 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
6780 HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key)
6781 : slot_(FeedbackSlotInterface::kInvalidFeedbackSlot) {
6782 set_representation(Representation::Tagged());
6783 SetOperandAt(0, obj);
6784 SetOperandAt(1, key);
6785 SetOperandAt(2, context);
6786 SetAllSideEffects();
6789 Handle<FixedArray> feedback_vector_;
6794 // Indicates whether the store is a store to an entry that was previously
6795 // initialized or not.
6796 enum StoreFieldOrKeyedMode {
6797 // The entry could be either previously initialized or not.
6799 // At the time of this store it is guaranteed that the entry is already
6801 STORE_TO_INITIALIZED_ENTRY
6805 class HStoreNamedField FINAL : public HTemplateInstruction<3> {
6807 DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
6808 HObjectAccess, HValue*);
6809 DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue*,
6810 HObjectAccess, HValue*, StoreFieldOrKeyedMode);
6812 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
6814 virtual bool HasEscapingOperandAt(int index) OVERRIDE {
6817 virtual bool HasOutOfBoundsAccess(int size) OVERRIDE {
6818 return !access().IsInobject() || access().offset() >= size;
6820 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
6821 if (index == 0 && access().IsExternalMemory()) {
6822 // object must be external in case of external memory access
6823 return Representation::External();
6824 } else if (index == 1) {
6825 if (field_representation().IsInteger8() ||
6826 field_representation().IsUInteger8() ||
6827 field_representation().IsInteger16() ||
6828 field_representation().IsUInteger16() ||
6829 field_representation().IsInteger32()) {
6830 return Representation::Integer32();
6831 } else if (field_representation().IsDouble()) {
6832 return field_representation();
6833 } else if (field_representation().IsSmi()) {
6834 if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
6835 return Representation::Integer32();
6837 return field_representation();
6838 } else if (field_representation().IsExternal()) {
6839 return Representation::External();
6842 return Representation::Tagged();
6844 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
6845 HValue* dominator) OVERRIDE {
6846 DCHECK(side_effect == kNewSpacePromotion);
6847 if (!FLAG_use_write_barrier_elimination) return false;
6848 dominator_ = dominator;
6851 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
6853 HValue* object() const { return OperandAt(0); }
6854 HValue* value() const { return OperandAt(1); }
6855 HValue* transition() const { return OperandAt(2); }
6857 HObjectAccess access() const { return access_; }
6858 HValue* dominator() const { return dominator_; }
6859 bool has_transition() const { return has_transition_; }
6860 StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
6862 Handle<Map> transition_map() const {
6863 if (has_transition()) {
6864 return Handle<Map>::cast(
6865 HConstant::cast(transition())->handle(Isolate::Current()));
6867 return Handle<Map>();
6871 void SetTransition(HConstant* transition) {
6872 DCHECK(!has_transition()); // Only set once.
6873 SetOperandAt(2, transition);
6874 has_transition_ = true;
6875 SetChangesFlag(kMaps);
6878 bool NeedsWriteBarrier() const {
6879 DCHECK(!field_representation().IsDouble() || !has_transition());
6880 if (field_representation().IsDouble()) return false;
6881 if (field_representation().IsSmi()) return false;
6882 if (field_representation().IsInteger32()) return false;
6883 if (field_representation().IsExternal()) return false;
6884 return StoringValueNeedsWriteBarrier(value()) &&
6885 ReceiverObjectNeedsWriteBarrier(object(), value(), dominator());
6888 bool NeedsWriteBarrierForMap() {
6889 return ReceiverObjectNeedsWriteBarrier(object(), transition(),
6893 SmiCheck SmiCheckForWriteBarrier() const {
6894 if (field_representation().IsHeapObject()) return OMIT_SMI_CHECK;
6895 if (value()->type().IsHeapObject()) return OMIT_SMI_CHECK;
6896 return INLINE_SMI_CHECK;
6899 PointersToHereCheck PointersToHereCheckForValue() const {
6900 return PointersToHereCheckForObject(value(), dominator());
6903 Representation field_representation() const {
6904 return access_.representation();
6907 void UpdateValue(HValue* value) {
6908 SetOperandAt(1, value);
6911 bool CanBeReplacedWith(HStoreNamedField* that) const {
6912 if (!this->access().Equals(that->access())) return false;
6913 if (SmiValuesAre32Bits() &&
6914 this->field_representation().IsSmi() &&
6915 this->store_mode() == INITIALIZING_STORE &&
6916 that->store_mode() == STORE_TO_INITIALIZED_ENTRY) {
6917 // We cannot replace an initializing store to a smi field with a store to
6918 // an initialized entry on 64-bit architectures (with 32-bit smis).
6925 HStoreNamedField(HValue* obj,
6926 HObjectAccess access,
6928 StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
6931 has_transition_(false),
6932 store_mode_(store_mode) {
6933 // Stores to a non existing in-object property are allowed only to the
6934 // newly allocated objects (via HAllocate or HInnerAllocatedObject).
6935 DCHECK(!access.IsInobject() || access.existing_inobject_property() ||
6936 obj->IsAllocate() || obj->IsInnerAllocatedObject());
6937 SetOperandAt(0, obj);
6938 SetOperandAt(1, val);
6939 SetOperandAt(2, obj);
6940 access.SetGVNFlags(this, STORE);
6943 HObjectAccess access_;
6945 bool has_transition_ : 1;
6946 StoreFieldOrKeyedMode store_mode_ : 1;
6950 class HStoreNamedGeneric FINAL : public HTemplateInstruction<3> {
6952 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreNamedGeneric, HValue*,
6953 Handle<String>, HValue*,
6955 HValue* object() const { return OperandAt(0); }
6956 HValue* value() const { return OperandAt(1); }
6957 HValue* context() const { return OperandAt(2); }
6958 Handle<String> name() const { return name_; }
6959 StrictMode strict_mode() const { return strict_mode_; }
6961 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
6963 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
6964 return Representation::Tagged();
6967 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
6970 HStoreNamedGeneric(HValue* context,
6972 Handle<String> name,
6974 StrictMode strict_mode)
6976 strict_mode_(strict_mode) {
6977 SetOperandAt(0, object);
6978 SetOperandAt(1, value);
6979 SetOperandAt(2, context);
6980 SetAllSideEffects();
6983 Handle<String> name_;
6984 StrictMode strict_mode_;
6988 class HStoreKeyed FINAL
6989 : public HTemplateInstruction<3>, public ArrayInstructionInterface {
6991 DECLARE_INSTRUCTION_FACTORY_P4(HStoreKeyed, HValue*, HValue*, HValue*,
6993 DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*,
6994 ElementsKind, StoreFieldOrKeyedMode);
6995 DECLARE_INSTRUCTION_FACTORY_P6(HStoreKeyed, HValue*, HValue*, HValue*,
6996 ElementsKind, StoreFieldOrKeyedMode, int);
6998 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
6999 // kind_fast: tagged[int32] = tagged
7000 // kind_double: tagged[int32] = double
7001 // kind_smi : tagged[int32] = smi
7002 // kind_fixed_typed_array: tagged[int32] = (double | int32)
7003 // kind_external: external[int32] = (double | int32)
7005 return is_external() ? Representation::External()
7006 : Representation::Tagged();
7007 } else if (index == 1) {
7008 return ArrayInstructionInterface::KeyedAccessIndexRequirement(
7009 OperandAt(1)->representation());
7012 DCHECK_EQ(index, 2);
7013 return RequiredValueRepresentation(elements_kind_, store_mode_);
7016 static Representation RequiredValueRepresentation(
7017 ElementsKind kind, StoreFieldOrKeyedMode mode) {
7018 if (IsDoubleOrFloatElementsKind(kind)) {
7019 return Representation::Double();
7022 if (kind == FAST_SMI_ELEMENTS && SmiValuesAre32Bits() &&
7023 mode == STORE_TO_INITIALIZED_ENTRY) {
7024 return Representation::Integer32();
7027 if (IsFastSmiElementsKind(kind)) {
7028 return Representation::Smi();
7031 return IsExternalArrayElementsKind(kind) ||
7032 IsFixedTypedArrayElementsKind(kind)
7033 ? Representation::Integer32()
7034 : Representation::Tagged();
7037 bool is_external() const {
7038 return IsExternalArrayElementsKind(elements_kind());
7041 bool is_fixed_typed_array() const {
7042 return IsFixedTypedArrayElementsKind(elements_kind());
7045 bool is_typed_elements() const {
7046 return is_external() || is_fixed_typed_array();
7049 virtual Representation observed_input_representation(int index) OVERRIDE {
7050 if (index < 2) return RequiredInputRepresentation(index);
7051 if (IsUninitialized()) {
7052 return Representation::None();
7054 Representation r = RequiredValueRepresentation(elements_kind_, store_mode_);
7055 // For fast object elements kinds, don't assume anything.
7056 if (r.IsTagged()) return Representation::None();
7060 HValue* elements() const { return OperandAt(0); }
7061 HValue* key() const { return OperandAt(1); }
7062 HValue* value() const { return OperandAt(2); }
7063 bool value_is_smi() const {
7064 return IsFastSmiElementsKind(elements_kind_);
7066 StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
7067 ElementsKind elements_kind() const { return elements_kind_; }
7068 uint32_t base_offset() const { return base_offset_; }
7069 bool TryIncreaseBaseOffset(uint32_t increase_by_value);
7070 HValue* GetKey() { return key(); }
7071 void SetKey(HValue* key) { SetOperandAt(1, key); }
7072 bool IsDehoisted() const { return is_dehoisted_; }
7073 void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
7074 bool IsUninitialized() { return is_uninitialized_; }
7075 void SetUninitialized(bool is_uninitialized) {
7076 is_uninitialized_ = is_uninitialized;
7079 bool IsConstantHoleStore() {
7080 return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
7083 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
7084 HValue* dominator) OVERRIDE {
7085 DCHECK(side_effect == kNewSpacePromotion);
7086 dominator_ = dominator;
7090 HValue* dominator() const { return dominator_; }
7092 bool NeedsWriteBarrier() {
7093 if (value_is_smi()) {
7096 return StoringValueNeedsWriteBarrier(value()) &&
7097 ReceiverObjectNeedsWriteBarrier(elements(), value(), dominator());
7101 PointersToHereCheck PointersToHereCheckForValue() const {
7102 return PointersToHereCheckForObject(value(), dominator());
7105 bool NeedsCanonicalization();
7107 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7109 DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
7112 HStoreKeyed(HValue* obj, HValue* key, HValue* val,
7113 ElementsKind elements_kind,
7114 StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE,
7115 int offset = kDefaultKeyedHeaderOffsetSentinel)
7116 : elements_kind_(elements_kind),
7117 base_offset_(offset == kDefaultKeyedHeaderOffsetSentinel
7118 ? GetDefaultHeaderSizeForElementsKind(elements_kind)
7120 is_dehoisted_(false),
7121 is_uninitialized_(false),
7122 store_mode_(store_mode),
7124 SetOperandAt(0, obj);
7125 SetOperandAt(1, key);
7126 SetOperandAt(2, val);
7128 if (IsFastObjectElementsKind(elements_kind)) {
7129 SetFlag(kTrackSideEffectDominators);
7130 SetDependsOnFlag(kNewSpacePromotion);
7132 if (is_external()) {
7133 SetChangesFlag(kExternalMemory);
7134 SetFlag(kAllowUndefinedAsNaN);
7135 } else if (IsFastDoubleElementsKind(elements_kind)) {
7136 SetChangesFlag(kDoubleArrayElements);
7137 } else if (IsFastSmiElementsKind(elements_kind)) {
7138 SetChangesFlag(kArrayElements);
7139 } else if (is_fixed_typed_array()) {
7140 SetChangesFlag(kTypedArrayElements);
7141 SetFlag(kAllowUndefinedAsNaN);
7143 SetChangesFlag(kArrayElements);
7146 // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
7147 if ((elements_kind >= EXTERNAL_INT8_ELEMENTS &&
7148 elements_kind <= EXTERNAL_UINT32_ELEMENTS) ||
7149 (elements_kind >= UINT8_ELEMENTS &&
7150 elements_kind <= INT32_ELEMENTS)) {
7151 SetFlag(kTruncatingToInt32);
7155 ElementsKind elements_kind_;
7156 uint32_t base_offset_;
7157 bool is_dehoisted_ : 1;
7158 bool is_uninitialized_ : 1;
7159 StoreFieldOrKeyedMode store_mode_: 1;
7164 class HStoreKeyedGeneric FINAL : public HTemplateInstruction<4> {
7166 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreKeyedGeneric, HValue*,
7167 HValue*, HValue*, StrictMode);
7169 HValue* object() const { return OperandAt(0); }
7170 HValue* key() const { return OperandAt(1); }
7171 HValue* value() const { return OperandAt(2); }
7172 HValue* context() const { return OperandAt(3); }
7173 StrictMode strict_mode() const { return strict_mode_; }
7175 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
7176 // tagged[tagged] = tagged
7177 return Representation::Tagged();
7180 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7182 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
7185 HStoreKeyedGeneric(HValue* context,
7189 StrictMode strict_mode)
7190 : strict_mode_(strict_mode) {
7191 SetOperandAt(0, object);
7192 SetOperandAt(1, key);
7193 SetOperandAt(2, value);
7194 SetOperandAt(3, context);
7195 SetAllSideEffects();
7198 StrictMode strict_mode_;
7202 class HTransitionElementsKind FINAL : public HTemplateInstruction<2> {
7204 inline static HTransitionElementsKind* New(Zone* zone,
7207 Handle<Map> original_map,
7208 Handle<Map> transitioned_map) {
7209 return new(zone) HTransitionElementsKind(context, object,
7210 original_map, transitioned_map);
7213 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
7214 return Representation::Tagged();
7217 HValue* object() const { return OperandAt(0); }
7218 HValue* context() const { return OperandAt(1); }
7219 Unique<Map> original_map() const { return original_map_; }
7220 Unique<Map> transitioned_map() const { return transitioned_map_; }
7221 ElementsKind from_kind() const { return from_kind_; }
7222 ElementsKind to_kind() const { return to_kind_; }
7224 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7226 DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
7229 virtual bool DataEquals(HValue* other) OVERRIDE {
7230 HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
7231 return original_map_ == instr->original_map_ &&
7232 transitioned_map_ == instr->transitioned_map_;
7235 virtual int RedefinedOperandIndex() { return 0; }
7238 HTransitionElementsKind(HValue* context,
7240 Handle<Map> original_map,
7241 Handle<Map> transitioned_map)
7242 : original_map_(Unique<Map>(original_map)),
7243 transitioned_map_(Unique<Map>(transitioned_map)),
7244 from_kind_(original_map->elements_kind()),
7245 to_kind_(transitioned_map->elements_kind()) {
7246 SetOperandAt(0, object);
7247 SetOperandAt(1, context);
7249 SetChangesFlag(kElementsKind);
7250 if (!IsSimpleMapChangeTransition(from_kind_, to_kind_)) {
7251 SetChangesFlag(kElementsPointer);
7252 SetChangesFlag(kNewSpacePromotion);
7254 set_representation(Representation::Tagged());
7257 Unique<Map> original_map_;
7258 Unique<Map> transitioned_map_;
7259 ElementsKind from_kind_;
7260 ElementsKind to_kind_;
7264 class HStringAdd FINAL : public HBinaryOperation {
7266 static HInstruction* New(Zone* zone,
7270 PretenureFlag pretenure_flag = NOT_TENURED,
7271 StringAddFlags flags = STRING_ADD_CHECK_BOTH,
7272 Handle<AllocationSite> allocation_site =
7273 Handle<AllocationSite>::null());
7275 StringAddFlags flags() const { return flags_; }
7276 PretenureFlag pretenure_flag() const { return pretenure_flag_; }
7278 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
7279 return Representation::Tagged();
7282 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7284 DECLARE_CONCRETE_INSTRUCTION(StringAdd)
7287 virtual bool DataEquals(HValue* other) OVERRIDE {
7288 return flags_ == HStringAdd::cast(other)->flags_ &&
7289 pretenure_flag_ == HStringAdd::cast(other)->pretenure_flag_;
7293 HStringAdd(HValue* context,
7296 PretenureFlag pretenure_flag,
7297 StringAddFlags flags,
7298 Handle<AllocationSite> allocation_site)
7299 : HBinaryOperation(context, left, right, HType::String()),
7300 flags_(flags), pretenure_flag_(pretenure_flag) {
7301 set_representation(Representation::Tagged());
7303 SetDependsOnFlag(kMaps);
7304 SetChangesFlag(kNewSpacePromotion);
7305 if (FLAG_trace_pretenuring) {
7306 PrintF("HStringAdd with AllocationSite %p %s\n",
7307 allocation_site.is_null()
7308 ? static_cast<void*>(NULL)
7309 : static_cast<void*>(*allocation_site),
7310 pretenure_flag == TENURED ? "tenured" : "not tenured");
7314 // No side-effects except possible allocation:
7315 virtual bool IsDeletable() const OVERRIDE { return true; }
7317 const StringAddFlags flags_;
7318 const PretenureFlag pretenure_flag_;
7322 class HStringCharCodeAt FINAL : public HTemplateInstruction<3> {
7324 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HStringCharCodeAt,
7328 virtual Representation RequiredInputRepresentation(int index) {
7329 // The index is supposed to be Integer32.
7331 ? Representation::Integer32()
7332 : Representation::Tagged();
7335 HValue* context() const { return OperandAt(0); }
7336 HValue* string() const { return OperandAt(1); }
7337 HValue* index() const { return OperandAt(2); }
7339 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
7342 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
7344 virtual Range* InferRange(Zone* zone) OVERRIDE {
7345 return new(zone) Range(0, String::kMaxUtf16CodeUnit);
7349 HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
7350 SetOperandAt(0, context);
7351 SetOperandAt(1, string);
7352 SetOperandAt(2, index);
7353 set_representation(Representation::Integer32());
7355 SetDependsOnFlag(kMaps);
7356 SetDependsOnFlag(kStringChars);
7357 SetChangesFlag(kNewSpacePromotion);
7360 // No side effects: runtime function assumes string + number inputs.
7361 virtual bool IsDeletable() const OVERRIDE { return true; }
7365 class HStringCharFromCode FINAL : public HTemplateInstruction<2> {
7367 static HInstruction* New(Zone* zone,
7371 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
7373 ? Representation::Tagged()
7374 : Representation::Integer32();
7377 HValue* context() const { return OperandAt(0); }
7378 HValue* value() const { return OperandAt(1); }
7380 virtual bool DataEquals(HValue* other) OVERRIDE { return true; }
7382 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
7385 HStringCharFromCode(HValue* context, HValue* char_code)
7386 : HTemplateInstruction<2>(HType::String()) {
7387 SetOperandAt(0, context);
7388 SetOperandAt(1, char_code);
7389 set_representation(Representation::Tagged());
7391 SetChangesFlag(kNewSpacePromotion);
7394 virtual bool IsDeletable() const OVERRIDE {
7395 return !value()->ToNumberCanBeObserved();
7401 class HMaterializedLiteral : public HTemplateInstruction<V> {
7403 HMaterializedLiteral<V>(int index, int depth, AllocationSiteMode mode)
7404 : literal_index_(index), depth_(depth), allocation_site_mode_(mode) {
7405 this->set_representation(Representation::Tagged());
7408 HMaterializedLiteral<V>(int index, int depth)
7409 : literal_index_(index), depth_(depth),
7410 allocation_site_mode_(DONT_TRACK_ALLOCATION_SITE) {
7411 this->set_representation(Representation::Tagged());
7414 int literal_index() const { return literal_index_; }
7415 int depth() const { return depth_; }
7416 AllocationSiteMode allocation_site_mode() const {
7417 return allocation_site_mode_;
7421 virtual bool IsDeletable() const FINAL OVERRIDE { return true; }
7425 AllocationSiteMode allocation_site_mode_;
7429 class HRegExpLiteral FINAL : public HMaterializedLiteral<1> {
7431 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HRegExpLiteral,
7437 HValue* context() { return OperandAt(0); }
7438 Handle<FixedArray> literals() { return literals_; }
7439 Handle<String> pattern() { return pattern_; }
7440 Handle<String> flags() { return flags_; }
7442 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
7443 return Representation::Tagged();
7446 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
7449 HRegExpLiteral(HValue* context,
7450 Handle<FixedArray> literals,
7451 Handle<String> pattern,
7452 Handle<String> flags,
7454 : HMaterializedLiteral<1>(literal_index, 0),
7455 literals_(literals),
7458 SetOperandAt(0, context);
7459 SetAllSideEffects();
7460 set_type(HType::JSObject());
7463 Handle<FixedArray> literals_;
7464 Handle<String> pattern_;
7465 Handle<String> flags_;
7469 class HFunctionLiteral FINAL : public HTemplateInstruction<1> {
7471 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HFunctionLiteral,
7472 Handle<SharedFunctionInfo>,
7474 HValue* context() { return OperandAt(0); }
7476 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
7477 return Representation::Tagged();
7480 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral)
7482 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
7483 bool pretenure() const { return pretenure_; }
7484 bool has_no_literals() const { return has_no_literals_; }
7485 bool is_arrow() const { return IsArrowFunction(kind_); }
7486 bool is_generator() const { return IsGeneratorFunction(kind_); }
7487 bool is_concise_method() const { return IsConciseMethod(kind_); }
7488 FunctionKind kind() const { return kind_; }
7489 StrictMode strict_mode() const { return strict_mode_; }
7492 HFunctionLiteral(HValue* context, Handle<SharedFunctionInfo> shared,
7494 : HTemplateInstruction<1>(HType::JSObject()),
7495 shared_info_(shared),
7496 kind_(shared->kind()),
7497 pretenure_(pretenure),
7498 has_no_literals_(shared->num_literals() == 0),
7499 strict_mode_(shared->strict_mode()) {
7500 SetOperandAt(0, context);
7501 set_representation(Representation::Tagged());
7502 SetChangesFlag(kNewSpacePromotion);
7505 virtual bool IsDeletable() const OVERRIDE { return true; }
7507 Handle<SharedFunctionInfo> shared_info_;
7509 bool pretenure_ : 1;
7510 bool has_no_literals_ : 1;
7511 StrictMode strict_mode_;
7515 class HTypeof FINAL : public HTemplateInstruction<2> {
7517 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HTypeof, HValue*);
7519 HValue* context() const { return OperandAt(0); }
7520 HValue* value() const { return OperandAt(1); }
7522 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7524 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
7525 return Representation::Tagged();
7528 DECLARE_CONCRETE_INSTRUCTION(Typeof)
7531 explicit HTypeof(HValue* context, HValue* value) {
7532 SetOperandAt(0, context);
7533 SetOperandAt(1, value);
7534 set_representation(Representation::Tagged());
7537 virtual bool IsDeletable() const OVERRIDE { return true; }
7541 class HTrapAllocationMemento FINAL : public HTemplateInstruction<1> {
7543 DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
7545 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
7546 return Representation::Tagged();
7549 HValue* object() { return OperandAt(0); }
7551 DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
7554 explicit HTrapAllocationMemento(HValue* obj) {
7555 SetOperandAt(0, obj);
7560 class HToFastProperties FINAL : public HUnaryOperation {
7562 DECLARE_INSTRUCTION_FACTORY_P1(HToFastProperties, HValue*);
7564 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
7565 return Representation::Tagged();
7568 DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
7571 explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
7572 set_representation(Representation::Tagged());
7573 SetChangesFlag(kNewSpacePromotion);
7575 // This instruction is not marked as kChangesMaps, but does
7576 // change the map of the input operand. Use it only when creating
7577 // object literals via a runtime call.
7578 DCHECK(value->IsCallRuntime());
7580 const Runtime::Function* function = HCallRuntime::cast(value)->function();
7581 DCHECK(function->function_id == Runtime::kCreateObjectLiteral);
7585 virtual bool IsDeletable() const OVERRIDE { return true; }
7589 class HDateField FINAL : public HUnaryOperation {
7591 DECLARE_INSTRUCTION_FACTORY_P2(HDateField, HValue*, Smi*);
7593 Smi* index() const { return index_; }
7595 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
7596 return Representation::Tagged();
7599 DECLARE_CONCRETE_INSTRUCTION(DateField)
7602 HDateField(HValue* date, Smi* index)
7603 : HUnaryOperation(date), index_(index) {
7604 set_representation(Representation::Tagged());
7611 class HSeqStringGetChar FINAL : public HTemplateInstruction<2> {
7613 static HInstruction* New(Zone* zone,
7615 String::Encoding encoding,
7619 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
7620 return (index == 0) ? Representation::Tagged()
7621 : Representation::Integer32();
7624 String::Encoding encoding() const { return encoding_; }
7625 HValue* string() const { return OperandAt(0); }
7626 HValue* index() const { return OperandAt(1); }
7628 DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)
7631 virtual bool DataEquals(HValue* other) OVERRIDE {
7632 return encoding() == HSeqStringGetChar::cast(other)->encoding();
7635 virtual Range* InferRange(Zone* zone) OVERRIDE {
7636 if (encoding() == String::ONE_BYTE_ENCODING) {
7637 return new(zone) Range(0, String::kMaxOneByteCharCode);
7639 DCHECK_EQ(String::TWO_BYTE_ENCODING, encoding());
7640 return new(zone) Range(0, String::kMaxUtf16CodeUnit);
7645 HSeqStringGetChar(String::Encoding encoding,
7647 HValue* index) : encoding_(encoding) {
7648 SetOperandAt(0, string);
7649 SetOperandAt(1, index);
7650 set_representation(Representation::Integer32());
7652 SetDependsOnFlag(kStringChars);
7655 virtual bool IsDeletable() const OVERRIDE { return true; }
7657 String::Encoding encoding_;
7661 class HSeqStringSetChar FINAL : public HTemplateInstruction<4> {
7663 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(
7664 HSeqStringSetChar, String::Encoding,
7665 HValue*, HValue*, HValue*);
7667 String::Encoding encoding() { return encoding_; }
7668 HValue* context() { return OperandAt(0); }
7669 HValue* string() { return OperandAt(1); }
7670 HValue* index() { return OperandAt(2); }
7671 HValue* value() { return OperandAt(3); }
7673 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
7674 return (index <= 1) ? Representation::Tagged()
7675 : Representation::Integer32();
7678 DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
7681 HSeqStringSetChar(HValue* context,
7682 String::Encoding encoding,
7685 HValue* value) : encoding_(encoding) {
7686 SetOperandAt(0, context);
7687 SetOperandAt(1, string);
7688 SetOperandAt(2, index);
7689 SetOperandAt(3, value);
7690 set_representation(Representation::Tagged());
7691 SetChangesFlag(kStringChars);
7694 String::Encoding encoding_;
7698 class HCheckMapValue FINAL : public HTemplateInstruction<2> {
7700 DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);
7702 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
7703 return Representation::Tagged();
7706 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7708 virtual HType CalculateInferredType() OVERRIDE {
7709 if (value()->type().IsHeapObject()) return value()->type();
7710 return HType::HeapObject();
7713 HValue* value() const { return OperandAt(0); }
7714 HValue* map() const { return OperandAt(1); }
7716 virtual HValue* Canonicalize() OVERRIDE;
7718 DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
7721 virtual int RedefinedOperandIndex() { return 0; }
7723 virtual bool DataEquals(HValue* other) OVERRIDE {
7728 HCheckMapValue(HValue* value, HValue* map)
7729 : HTemplateInstruction<2>(HType::HeapObject()) {
7730 SetOperandAt(0, value);
7731 SetOperandAt(1, map);
7732 set_representation(Representation::Tagged());
7734 SetDependsOnFlag(kMaps);
7735 SetDependsOnFlag(kElementsKind);
7740 class HForInPrepareMap FINAL : public HTemplateInstruction<2> {
7742 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HForInPrepareMap, HValue*);
7744 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
7745 return Representation::Tagged();
7748 HValue* context() const { return OperandAt(0); }
7749 HValue* enumerable() const { return OperandAt(1); }
7751 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7753 virtual HType CalculateInferredType() OVERRIDE {
7754 return HType::Tagged();
7757 DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
7760 HForInPrepareMap(HValue* context,
7762 SetOperandAt(0, context);
7763 SetOperandAt(1, object);
7764 set_representation(Representation::Tagged());
7765 SetAllSideEffects();
7770 class HForInCacheArray FINAL : public HTemplateInstruction<2> {
7772 DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
7774 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
7775 return Representation::Tagged();
7778 HValue* enumerable() const { return OperandAt(0); }
7779 HValue* map() const { return OperandAt(1); }
7780 int idx() const { return idx_; }
7782 HForInCacheArray* index_cache() {
7783 return index_cache_;
7786 void set_index_cache(HForInCacheArray* index_cache) {
7787 index_cache_ = index_cache;
7790 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7792 virtual HType CalculateInferredType() OVERRIDE {
7793 return HType::Tagged();
7796 DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
7799 HForInCacheArray(HValue* enumerable,
7801 int idx) : idx_(idx) {
7802 SetOperandAt(0, enumerable);
7803 SetOperandAt(1, keys);
7804 set_representation(Representation::Tagged());
7808 HForInCacheArray* index_cache_;
7812 class HLoadFieldByIndex FINAL : public HTemplateInstruction<2> {
7814 DECLARE_INSTRUCTION_FACTORY_P2(HLoadFieldByIndex, HValue*, HValue*);
7816 HLoadFieldByIndex(HValue* object,
7818 SetOperandAt(0, object);
7819 SetOperandAt(1, index);
7820 SetChangesFlag(kNewSpacePromotion);
7821 set_representation(Representation::Tagged());
7824 virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
7826 return Representation::Smi();
7828 return Representation::Tagged();
7832 HValue* object() const { return OperandAt(0); }
7833 HValue* index() const { return OperandAt(1); }
7835 virtual OStream& PrintDataTo(OStream& os) const OVERRIDE; // NOLINT
7837 virtual HType CalculateInferredType() OVERRIDE {
7838 return HType::Tagged();
7841 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
7844 virtual bool IsDeletable() const OVERRIDE { return true; }
7848 class HStoreFrameContext: public HUnaryOperation {
7850 DECLARE_INSTRUCTION_FACTORY_P1(HStoreFrameContext, HValue*);
7852 HValue* context() { return OperandAt(0); }
7854 virtual Representation RequiredInputRepresentation(int index) {
7855 return Representation::Tagged();
7858 DECLARE_CONCRETE_INSTRUCTION(StoreFrameContext)
7860 explicit HStoreFrameContext(HValue* context)
7861 : HUnaryOperation(context) {
7862 set_representation(Representation::Tagged());
7863 SetChangesFlag(kContextSlots);
7868 class HAllocateBlockContext: public HTemplateInstruction<2> {
7870 DECLARE_INSTRUCTION_FACTORY_P3(HAllocateBlockContext, HValue*,
7871 HValue*, Handle<ScopeInfo>);
7872 HValue* context() const { return OperandAt(0); }
7873 HValue* function() const { return OperandAt(1); }
7874 Handle<ScopeInfo> scope_info() const { return scope_info_; }
7876 virtual Representation RequiredInputRepresentation(int index) {
7877 return Representation::Tagged();
7880 virtual OStream& PrintDataTo(OStream& os) const; // NOLINT
7882 DECLARE_CONCRETE_INSTRUCTION(AllocateBlockContext)
7885 HAllocateBlockContext(HValue* context,
7887 Handle<ScopeInfo> scope_info)
7888 : scope_info_(scope_info) {
7889 SetOperandAt(0, context);
7890 SetOperandAt(1, function);
7891 set_representation(Representation::Tagged());
7894 Handle<ScopeInfo> scope_info_;
7899 #undef DECLARE_INSTRUCTION
7900 #undef DECLARE_CONCRETE_INSTRUCTION
7902 } } // namespace v8::internal
7904 #endif // V8_HYDROGEN_INSTRUCTIONS_H_