1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #ifndef V8_HYDROGEN_INSTRUCTIONS_H_
29 #define V8_HYDROGEN_INSTRUCTIONS_H_
33 #include "allocation.h"
34 #include "code-stubs.h"
35 #include "data-flow.h"
36 #include "small-pointer-list.h"
37 #include "string-stream.h"
38 #include "v8conversions.h"
45 // Forward declarations.
49 class HLoopInformation;
55 #define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V) \
56 V(BitwiseBinaryOperation) \
57 V(ControlInstruction) \
61 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
63 V(AccessArgumentsAt) \
67 V(ArgumentsElements) \
76 V(CallConstantFunction) \
87 V(CheckInstanceType) \
90 V(CheckPrototypeMaps) \
93 V(ClassOfTestAndBranch) \
94 V(CompareIDAndBranch) \
96 V(CompareObjectEqAndBranch) \
98 V(CompareConstantEqAndBranch) \
108 V(FixedArrayBaseLength) \
109 V(ForceRepresentation) \
111 V(GetCachedArrayIndex) \
115 V(HasCachedArrayIndexAndBranch) \
116 V(HasInstanceTypeAndBranch) \
119 V(InstanceOfKnownGlobal) \
121 V(IsConstructCallAndBranch) \
123 V(IsObjectAndBranch) \
124 V(IsStringAndBranch) \
126 V(IsUndetectableAndBranch) \
127 V(StringCompareAndBranch) \
132 V(LoadExternalArrayPointer) \
133 V(LoadFunctionPrototype) \
135 V(LoadGlobalGeneric) \
136 V(LoadKeyedFastDoubleElement) \
137 V(LoadKeyedFastElement) \
138 V(LoadKeyedGeneric) \
139 V(LoadKeyedSpecializedArrayElement) \
141 V(LoadNamedFieldPolymorphic) \
142 V(LoadNamedGeneric) \
161 V(StoreContextSlot) \
163 V(StoreGlobalGeneric) \
164 V(StoreKeyedFastDoubleElement) \
165 V(StoreKeyedFastElement) \
166 V(StoreKeyedGeneric) \
167 V(StoreKeyedSpecializedArrayElement) \
169 V(StoreNamedGeneric) \
171 V(StringCharCodeAt) \
172 V(StringCharFromCode) \
177 V(ToFastProperties) \
178 V(TransitionElementsKind) \
180 V(TypeofIsAndBranch) \
181 V(UnaryMathOperation) \
188 V(LoadFieldByIndex) \
192 #define GVN_TRACKED_FLAG_LIST(V) \
195 #define GVN_UNTRACKED_FLAG_LIST(V) \
198 V(BackingStoreFields) \
202 V(DoubleArrayElements) \
203 V(SpecializedArrayElements) \
210 #define DECLARE_ABSTRACT_INSTRUCTION(type) \
211 virtual bool Is##type() const { return true; } \
212 static H##type* cast(HValue* value) { \
213 ASSERT(value->Is##type()); \
214 return reinterpret_cast<H##type*>(value); \
218 #define DECLARE_CONCRETE_INSTRUCTION(type) \
219 virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
220 static H##type* cast(HValue* value) { \
221 ASSERT(value->Is##type()); \
222 return reinterpret_cast<H##type*>(value); \
224 virtual Opcode opcode() const { return HValue::k##type; }
227 class Range: public ZoneObject {
233 can_be_minus_zero_(false) { }
235 Range(int32_t lower, int32_t upper)
239 can_be_minus_zero_(false) { }
241 int32_t upper() const { return upper_; }
242 int32_t lower() const { return lower_; }
243 Range* next() const { return next_; }
244 Range* CopyClearLower(Zone* zone) const {
245 return new(zone) Range(kMinInt, upper_);
247 Range* CopyClearUpper(Zone* zone) const {
248 return new(zone) Range(lower_, kMaxInt);
250 Range* Copy(Zone* zone) const {
251 Range* result = new(zone) Range(lower_, upper_);
252 result->set_can_be_minus_zero(CanBeMinusZero());
255 int32_t Mask() const;
256 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
257 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
258 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
259 bool CanBeNegative() const { return lower_ < 0; }
260 bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
261 bool IsMostGeneric() const {
262 return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
264 bool IsInSmiRange() const {
265 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
272 void StackUpon(Range* other) {
277 void Intersect(Range* other);
278 void Union(Range* other);
280 void AddConstant(int32_t value);
281 void Sar(int32_t value);
282 void Shl(int32_t value);
283 bool AddAndCheckOverflow(Range* other);
284 bool SubAndCheckOverflow(Range* other);
285 bool MulAndCheckOverflow(Range* other);
291 bool can_be_minus_zero_;
295 class Representation {
306 Representation() : kind_(kNone) { }
308 static Representation None() { return Representation(kNone); }
309 static Representation Tagged() { return Representation(kTagged); }
310 static Representation Integer32() { return Representation(kInteger32); }
311 static Representation Double() { return Representation(kDouble); }
312 static Representation External() { return Representation(kExternal); }
314 bool Equals(const Representation& other) {
315 return kind_ == other.kind_;
318 Kind kind() const { return static_cast<Kind>(kind_); }
319 bool IsNone() const { return kind_ == kNone; }
320 bool IsTagged() const { return kind_ == kTagged; }
321 bool IsInteger32() const { return kind_ == kInteger32; }
322 bool IsDouble() const { return kind_ == kDouble; }
323 bool IsExternal() const { return kind_ == kExternal; }
324 bool IsSpecialization() const {
325 return kind_ == kInteger32 || kind_ == kDouble;
327 const char* Mnemonic() const;
330 explicit Representation(Kind k) : kind_(k) { }
332 // Make sure kind fits in int8.
333 STATIC_ASSERT(kNumRepresentations <= (1 << kBitsPerByte));
341 HType() : type_(kUninitialized) { }
343 static HType Tagged() { return HType(kTagged); }
344 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
345 static HType TaggedNumber() { return HType(kTaggedNumber); }
346 static HType Smi() { return HType(kSmi); }
347 static HType HeapNumber() { return HType(kHeapNumber); }
348 static HType String() { return HType(kString); }
349 static HType Boolean() { return HType(kBoolean); }
350 static HType NonPrimitive() { return HType(kNonPrimitive); }
351 static HType JSArray() { return HType(kJSArray); }
352 static HType JSObject() { return HType(kJSObject); }
353 static HType Uninitialized() { return HType(kUninitialized); }
355 // Return the weakest (least precise) common type.
356 HType Combine(HType other) {
357 return HType(static_cast<Type>(type_ & other.type_));
360 bool Equals(const HType& other) {
361 return type_ == other.type_;
364 bool IsSubtypeOf(const HType& other) {
365 return Combine(other).Equals(other);
369 ASSERT(type_ != kUninitialized);
370 return ((type_ & kTagged) == kTagged);
373 bool IsTaggedPrimitive() {
374 ASSERT(type_ != kUninitialized);
375 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
378 bool IsTaggedNumber() {
379 ASSERT(type_ != kUninitialized);
380 return ((type_ & kTaggedNumber) == kTaggedNumber);
384 ASSERT(type_ != kUninitialized);
385 return ((type_ & kSmi) == kSmi);
388 bool IsHeapNumber() {
389 ASSERT(type_ != kUninitialized);
390 return ((type_ & kHeapNumber) == kHeapNumber);
394 ASSERT(type_ != kUninitialized);
395 return ((type_ & kString) == kString);
399 ASSERT(type_ != kUninitialized);
400 return ((type_ & kBoolean) == kBoolean);
403 bool IsNonPrimitive() {
404 ASSERT(type_ != kUninitialized);
405 return ((type_ & kNonPrimitive) == kNonPrimitive);
409 ASSERT(type_ != kUninitialized);
410 return ((type_ & kJSArray) == kJSArray);
414 ASSERT(type_ != kUninitialized);
415 return ((type_ & kJSObject) == kJSObject);
418 bool IsUninitialized() {
419 return type_ == kUninitialized;
422 bool IsHeapObject() {
423 ASSERT(type_ != kUninitialized);
424 return IsHeapNumber() || IsString() || IsNonPrimitive();
427 static HType TypeFromValue(Handle<Object> value);
429 const char* ToString();
433 kTagged = 0x1, // 0000 0000 0000 0001
434 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
435 kTaggedNumber = 0xd, // 0000 0000 0000 1101
436 kSmi = 0x1d, // 0000 0000 0001 1101
437 kHeapNumber = 0x2d, // 0000 0000 0010 1101
438 kString = 0x45, // 0000 0000 0100 0101
439 kBoolean = 0x85, // 0000 0000 1000 0101
440 kNonPrimitive = 0x101, // 0000 0001 0000 0001
441 kJSObject = 0x301, // 0000 0011 0000 0001
442 kJSArray = 0x701, // 0000 0111 0000 0001
443 kUninitialized = 0x1fff // 0001 1111 1111 1111
446 // Make sure type fits in int16.
447 STATIC_ASSERT(kUninitialized < (1 << (2 * kBitsPerByte)));
449 explicit HType(Type t) : type_(t) { }
455 class HUseListNode: public ZoneObject {
457 HUseListNode(HValue* value, int index, HUseListNode* tail)
458 : tail_(tail), value_(value), index_(index) {
461 HUseListNode* tail();
462 HValue* value() const { return value_; }
463 int index() const { return index_; }
465 void set_tail(HUseListNode* list) { tail_ = list; }
469 tail_ = reinterpret_cast<HUseListNode*>(1);
482 // We reuse use list nodes behind the scenes as uses are added and deleted.
483 // This class is the safe way to iterate uses while deleting them.
484 class HUseIterator BASE_EMBEDDED {
486 bool Done() { return current_ == NULL; }
500 explicit HUseIterator(HUseListNode* head);
502 HUseListNode* current_;
511 // There must be one corresponding kDepends flag for every kChanges flag and
512 // the order of the kChanges flags must be exactly the same as of the kDepends
513 // flags. All tracked flags should appear before untracked ones.
515 // Declare global value numbering flags.
516 #define DECLARE_FLAG(type) kChanges##type, kDependsOn##type,
517 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
518 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
521 kLastFlag = kAfterLastFlag - 1,
522 #define COUNT_FLAG(type) + 1
523 kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG)
527 typedef EnumSet<GVNFlag> GVNFlagSet;
530 class HValue: public ZoneObject {
532 static const int kNoNumber = -1;
535 kFlexibleRepresentation,
536 // Participate in Global Value Numbering, i.e. elimination of
537 // unnecessary recomputations. If an instruction sets this flag, it must
538 // implement DataEquals(), which will be used to determine if other
539 // occurrences of the instruction are indeed the same.
541 // Track instructions that are dominating side effects. If an instruction
542 // sets this flag, it must implement SetSideEffectDominator() and should
543 // indicate which side effects to track by setting GVN flags.
544 kTrackSideEffectDominators,
548 kDeoptimizeOnUndefined,
555 STATIC_ASSERT(kLastFlag < kBitsPerInt);
557 static const int kChangesToDependsFlagsLeftShift = 1;
559 static GVNFlag ChangesFlagFromInt(int x) {
560 return static_cast<GVNFlag>(x * 2);
562 static GVNFlag DependsOnFlagFromInt(int x) {
563 return static_cast<GVNFlag>(x * 2 + 1);
565 static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags) {
566 return GVNFlagSet(flags.ToIntegral() << kChangesToDependsFlagsLeftShift);
569 static HValue* cast(HValue* value) { return value; }
572 // Declare a unique enum value for each hydrogen instruction.
573 #define DECLARE_OPCODE(type) k##type,
574 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
576 #undef DECLARE_OPCODE
578 virtual Opcode opcode() const = 0;
580 // Declare a non-virtual predicates for each concrete HInstruction or HValue.
581 #define DECLARE_PREDICATE(type) \
582 bool Is##type() const { return opcode() == k##type; }
583 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
584 #undef DECLARE_PREDICATE
585 bool IsPhi() const { return opcode() == kPhi; }
587 // Declare virtual predicates for abstract HInstruction or HValue
588 #define DECLARE_PREDICATE(type) \
589 virtual bool Is##type() const { return false; }
590 HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
591 #undef DECLARE_PREDICATE
593 HValue() : block_(NULL),
595 type_(HType::Tagged()),
601 HBasicBlock* block() const { return block_; }
602 void SetBlock(HBasicBlock* block);
603 int LoopWeight() const;
605 int id() const { return id_; }
606 void set_id(int id) { id_ = id; }
608 HUseIterator uses() const { return HUseIterator(use_list_); }
610 virtual bool EmitAtUses() { return false; }
611 Representation representation() const { return representation_; }
612 void ChangeRepresentation(Representation r) {
613 // Representation was already set and is allowed to be changed.
615 ASSERT(CheckFlag(kFlexibleRepresentation));
616 RepresentationChanged(r);
619 void AssumeRepresentation(Representation r);
621 virtual bool IsConvertibleToInteger() const { return true; }
623 HType type() const { return type_; }
624 void set_type(HType new_type) {
625 ASSERT(new_type.IsSubtypeOf(type_));
629 // An operation needs to override this function iff:
630 // 1) it can produce an int32 output.
631 // 2) the true value of its output can potentially be minus zero.
632 // The implementation must set a flag so that it bails out in the case where
633 // it would otherwise output what should be a minus zero as an int32 zero.
634 // If the operation also exists in a form that takes int32 and outputs int32
635 // then the operation should return its input value so that we can propagate
636 // back. There are three operations that need to propagate back to more than
637 // one input. They are phi and binary div and mul. They always return NULL
638 // and expect the caller to take care of things.
639 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
644 bool IsDefinedAfter(HBasicBlock* other) const;
647 virtual int OperandCount() = 0;
648 virtual HValue* OperandAt(int index) = 0;
649 void SetOperandAt(int index, HValue* value);
651 void DeleteAndReplaceWith(HValue* other);
652 void ReplaceAllUsesWith(HValue* other);
653 bool HasNoUses() const { return use_list_ == NULL; }
654 bool HasMultipleUses() const {
655 return use_list_ != NULL && use_list_->tail() != NULL;
657 int UseCount() const;
659 // Mark this HValue as dead and to be removed from other HValues' use lists.
662 int flags() const { return flags_; }
663 void SetFlag(Flag f) { flags_ |= (1 << f); }
664 void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
665 bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
667 // Returns true if the flag specified is set for all uses, false otherwise.
668 bool CheckUsesForFlag(Flag f);
670 GVNFlagSet gvn_flags() const { return gvn_flags_; }
671 void SetGVNFlag(GVNFlag f) { gvn_flags_.Add(f); }
672 void ClearGVNFlag(GVNFlag f) { gvn_flags_.Remove(f); }
673 bool CheckGVNFlag(GVNFlag f) const { return gvn_flags_.Contains(f); }
674 void SetAllSideEffects() { gvn_flags_.Add(AllSideEffectsFlagSet()); }
675 void ClearAllSideEffects() {
676 gvn_flags_.Remove(AllSideEffectsFlagSet());
678 bool HasSideEffects() const {
679 return gvn_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
681 bool HasObservableSideEffects() const {
682 return gvn_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
685 GVNFlagSet DependsOnFlags() const {
686 GVNFlagSet result = gvn_flags_;
687 result.Intersect(AllDependsOnFlagSet());
691 GVNFlagSet SideEffectFlags() const {
692 GVNFlagSet result = gvn_flags_;
693 result.Intersect(AllSideEffectsFlagSet());
697 GVNFlagSet ChangesFlags() const {
698 GVNFlagSet result = gvn_flags_;
699 result.Intersect(AllChangesFlagSet());
703 GVNFlagSet ObservableChangesFlags() const {
704 GVNFlagSet result = gvn_flags_;
705 result.Intersect(AllChangesFlagSet());
706 result.Intersect(AllObservableSideEffectsFlagSet());
710 Range* range() const { return range_; }
711 bool HasRange() const { return range_ != NULL; }
712 void AddNewRange(Range* r, Zone* zone);
713 void RemoveLastAddedRange();
714 void ComputeInitialRange(Zone* zone);
716 // Representation helpers.
717 virtual Representation RequiredInputRepresentation(int index) = 0;
719 virtual Representation InferredRepresentation() {
720 return representation();
723 // This gives the instruction an opportunity to replace itself with an
724 // instruction that does the same in some better way. To replace an
725 // instruction with a new one, first add the new instruction to the graph,
726 // then return it. Return NULL to have the instruction deleted.
727 virtual HValue* Canonicalize() { return this; }
729 bool Equals(HValue* other);
730 virtual intptr_t Hashcode();
733 virtual void PrintTo(StringStream* stream) = 0;
734 void PrintNameTo(StringStream* stream);
735 void PrintTypeTo(StringStream* stream);
736 void PrintRangeTo(StringStream* stream);
737 void PrintChangesTo(StringStream* stream);
739 const char* Mnemonic() const;
741 // Updated the inferred type of this instruction and returns true if
743 bool UpdateInferredType();
745 virtual HType CalculateInferredType();
747 // This function must be overridden for instructions which have the
748 // kTrackSideEffectDominators flag set, to track instructions that are
749 // dominating side effects.
750 virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) {
755 virtual void Verify() = 0;
759 // This function must be overridden for instructions with flag kUseGVN, to
760 // compare the non-Operand parts of the instruction.
761 virtual bool DataEquals(HValue* other) {
765 virtual void RepresentationChanged(Representation to) { }
766 virtual Range* InferRange(Zone* zone);
767 virtual void DeleteFromGraph() = 0;
768 virtual void InternalSetOperandAt(int index, HValue* value) = 0;
770 ASSERT(block_ != NULL);
774 void set_representation(Representation r) {
775 // Representation is set-once.
776 ASSERT(representation_.IsNone() && !r.IsNone());
780 static GVNFlagSet AllDependsOnFlagSet() {
782 // Create changes mask.
783 #define ADD_FLAG(type) result.Add(kDependsOn##type);
784 GVN_TRACKED_FLAG_LIST(ADD_FLAG)
785 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
790 static GVNFlagSet AllChangesFlagSet() {
792 // Create changes mask.
793 #define ADD_FLAG(type) result.Add(kChanges##type);
794 GVN_TRACKED_FLAG_LIST(ADD_FLAG)
795 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
800 // A flag mask to mark an instruction as having arbitrary side effects.
801 static GVNFlagSet AllSideEffectsFlagSet() {
802 GVNFlagSet result = AllChangesFlagSet();
803 result.Remove(kChangesOsrEntries);
807 // A flag mask of all side effects that can make observable changes in
808 // an executing program (i.e. are not safe to repeat, move or remove);
809 static GVNFlagSet AllObservableSideEffectsFlagSet() {
810 GVNFlagSet result = AllChangesFlagSet();
811 result.Remove(kChangesNewSpacePromotion);
812 result.Remove(kChangesElementsKind);
813 result.Remove(kChangesElementsPointer);
814 result.Remove(kChangesMaps);
818 // Remove the matching use from the use list if present. Returns the
819 // removed list node or NULL.
820 HUseListNode* RemoveUse(HValue* value, int index);
822 void RegisterUse(int index, HValue* new_value);
826 // The id of this instruction in the hydrogen graph, assigned when first
827 // added to the graph. Reflects creation order.
830 Representation representation_;
832 HUseListNode* use_list_;
835 GVNFlagSet gvn_flags_;
838 DISALLOW_COPY_AND_ASSIGN(HValue);
842 class HInstruction: public HValue {
844 HInstruction* next() const { return next_; }
845 HInstruction* previous() const { return previous_; }
847 virtual void PrintTo(StringStream* stream);
848 virtual void PrintDataTo(StringStream* stream) { }
850 bool IsLinked() const { return block() != NULL; }
852 void InsertBefore(HInstruction* next);
853 void InsertAfter(HInstruction* previous);
855 int position() const { return position_; }
856 bool has_position() const { return position_ != RelocInfo::kNoPosition; }
857 void set_position(int position) { position_ = position; }
859 bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
861 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
864 virtual void Verify();
867 virtual bool IsCall() { return false; }
869 DECLARE_ABSTRACT_INSTRUCTION(Instruction)
875 position_(RelocInfo::kNoPosition) {
876 SetGVNFlag(kDependsOnOsrEntries);
879 virtual void DeleteFromGraph() { Unlink(); }
882 void InitializeAsFirst(HBasicBlock* block) {
887 void PrintMnemonicTo(StringStream* stream);
890 HInstruction* previous_;
893 friend class HBasicBlock;
898 class HTemplateInstruction : public HInstruction {
900 int OperandCount() { return V; }
901 HValue* OperandAt(int i) { return inputs_[i]; }
904 void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
907 EmbeddedContainer<HValue*, V> inputs_;
911 class HControlInstruction: public HInstruction {
913 virtual HBasicBlock* SuccessorAt(int i) = 0;
914 virtual int SuccessorCount() = 0;
915 virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
917 virtual void PrintDataTo(StringStream* stream);
919 HBasicBlock* FirstSuccessor() {
920 return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
922 HBasicBlock* SecondSuccessor() {
923 return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
926 DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
930 class HSuccessorIterator BASE_EMBEDDED {
932 explicit HSuccessorIterator(HControlInstruction* instr)
933 : instr_(instr), current_(0) { }
935 bool Done() { return current_ >= instr_->SuccessorCount(); }
936 HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
937 void Advance() { current_++; }
940 HControlInstruction* instr_;
945 template<int S, int V>
946 class HTemplateControlInstruction: public HControlInstruction {
948 int SuccessorCount() { return S; }
949 HBasicBlock* SuccessorAt(int i) { return successors_[i]; }
950 void SetSuccessorAt(int i, HBasicBlock* block) { successors_[i] = block; }
952 int OperandCount() { return V; }
953 HValue* OperandAt(int i) { return inputs_[i]; }
957 void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
960 EmbeddedContainer<HBasicBlock*, S> successors_;
961 EmbeddedContainer<HValue*, V> inputs_;
965 class HBlockEntry: public HTemplateInstruction<0> {
967 virtual Representation RequiredInputRepresentation(int index) {
968 return Representation::None();
971 DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
975 // We insert soft-deoptimize when we hit code with unknown typefeedback,
976 // so that we get a chance of re-optimizing with useful typefeedback.
977 // HSoftDeoptimize does not end a basic block as opposed to HDeoptimize.
978 class HSoftDeoptimize: public HTemplateInstruction<0> {
980 virtual Representation RequiredInputRepresentation(int index) {
981 return Representation::None();
984 DECLARE_CONCRETE_INSTRUCTION(SoftDeoptimize)
988 class HDeoptimize: public HControlInstruction {
990 explicit HDeoptimize(int environment_length) : values_(environment_length) { }
992 virtual Representation RequiredInputRepresentation(int index) {
993 return Representation::None();
996 virtual int OperandCount() { return values_.length(); }
997 virtual HValue* OperandAt(int index) { return values_[index]; }
998 virtual void PrintDataTo(StringStream* stream);
1000 virtual int SuccessorCount() { return 0; }
1001 virtual HBasicBlock* SuccessorAt(int i) {
1005 virtual void SetSuccessorAt(int i, HBasicBlock* block) {
1009 void AddEnvironmentValue(HValue* value) {
1011 SetOperandAt(values_.length() - 1, value);
1014 DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
1016 enum UseEnvironment {
1022 virtual void InternalSetOperandAt(int index, HValue* value) {
1023 values_[index] = value;
1027 ZoneList<HValue*> values_;
1031 class HGoto: public HTemplateControlInstruction<1, 0> {
1033 explicit HGoto(HBasicBlock* target) {
1034 SetSuccessorAt(0, target);
1037 virtual Representation RequiredInputRepresentation(int index) {
1038 return Representation::None();
1041 virtual void PrintDataTo(StringStream* stream);
1043 DECLARE_CONCRETE_INSTRUCTION(Goto)
1047 class HUnaryControlInstruction: public HTemplateControlInstruction<2, 1> {
1049 HUnaryControlInstruction(HValue* value,
1050 HBasicBlock* true_target,
1051 HBasicBlock* false_target) {
1052 SetOperandAt(0, value);
1053 SetSuccessorAt(0, true_target);
1054 SetSuccessorAt(1, false_target);
1057 virtual void PrintDataTo(StringStream* stream);
1059 HValue* value() { return OperandAt(0); }
1063 class HBranch: public HUnaryControlInstruction {
1065 HBranch(HValue* value,
1066 HBasicBlock* true_target,
1067 HBasicBlock* false_target,
1068 ToBooleanStub::Types expected_input_types = ToBooleanStub::no_types())
1069 : HUnaryControlInstruction(value, true_target, false_target),
1070 expected_input_types_(expected_input_types) {
1071 ASSERT(true_target != NULL && false_target != NULL);
1073 explicit HBranch(HValue* value)
1074 : HUnaryControlInstruction(value, NULL, NULL) { }
1077 virtual Representation RequiredInputRepresentation(int index) {
1078 return Representation::None();
1081 ToBooleanStub::Types expected_input_types() const {
1082 return expected_input_types_;
1085 DECLARE_CONCRETE_INSTRUCTION(Branch)
1088 ToBooleanStub::Types expected_input_types_;
1092 class HCompareMap: public HUnaryControlInstruction {
1094 HCompareMap(HValue* value,
1096 HBasicBlock* true_target,
1097 HBasicBlock* false_target)
1098 : HUnaryControlInstruction(value, true_target, false_target),
1100 ASSERT(true_target != NULL);
1101 ASSERT(false_target != NULL);
1102 ASSERT(!map.is_null());
1105 virtual void PrintDataTo(StringStream* stream);
1107 Handle<Map> map() const { return map_; }
1109 virtual Representation RequiredInputRepresentation(int index) {
1110 return Representation::Tagged();
1113 DECLARE_CONCRETE_INSTRUCTION(CompareMap)
1120 class HReturn: public HTemplateControlInstruction<0, 1> {
1122 explicit HReturn(HValue* value) {
1123 SetOperandAt(0, value);
1126 virtual Representation RequiredInputRepresentation(int index) {
1127 return Representation::Tagged();
1130 virtual void PrintDataTo(StringStream* stream);
1132 HValue* value() { return OperandAt(0); }
1134 DECLARE_CONCRETE_INSTRUCTION(Return)
1138 class HAbnormalExit: public HTemplateControlInstruction<0, 0> {
1140 virtual Representation RequiredInputRepresentation(int index) {
1141 return Representation::None();
1144 DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
1148 class HUnaryOperation: public HTemplateInstruction<1> {
1150 explicit HUnaryOperation(HValue* value) {
1151 SetOperandAt(0, value);
1154 static HUnaryOperation* cast(HValue* value) {
1155 return reinterpret_cast<HUnaryOperation*>(value);
1158 HValue* value() { return OperandAt(0); }
1159 virtual void PrintDataTo(StringStream* stream);
1163 class HThrow: public HTemplateInstruction<2> {
1165 HThrow(HValue* context, HValue* value) {
1166 SetOperandAt(0, context);
1167 SetOperandAt(1, value);
1168 SetAllSideEffects();
1171 virtual Representation RequiredInputRepresentation(int index) {
1172 return Representation::Tagged();
1175 HValue* context() { return OperandAt(0); }
1176 HValue* value() { return OperandAt(1); }
1178 DECLARE_CONCRETE_INSTRUCTION(Throw)
1182 class HUseConst: public HUnaryOperation {
1184 explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
1186 virtual Representation RequiredInputRepresentation(int index) {
1187 return Representation::None();
1190 DECLARE_CONCRETE_INSTRUCTION(UseConst)
1194 class HForceRepresentation: public HTemplateInstruction<1> {
1196 HForceRepresentation(HValue* value, Representation required_representation) {
1197 SetOperandAt(0, value);
1198 set_representation(required_representation);
1201 HValue* value() { return OperandAt(0); }
1203 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1205 virtual Representation RequiredInputRepresentation(int index) {
1206 return representation(); // Same as the output representation.
1209 DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
1213 class HChange: public HUnaryOperation {
1215 HChange(HValue* value,
1218 bool deoptimize_on_undefined)
1219 : HUnaryOperation(value) {
1220 ASSERT(!value->representation().IsNone() && !to.IsNone());
1221 ASSERT(!value->representation().Equals(to));
1222 set_representation(to);
1223 set_type(HType::TaggedNumber());
1225 if (deoptimize_on_undefined) SetFlag(kDeoptimizeOnUndefined);
1226 if (is_truncating) SetFlag(kTruncatingToInt32);
1227 if (to.IsTagged()) SetGVNFlag(kChangesNewSpacePromotion);
1230 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1231 virtual HType CalculateInferredType();
1232 virtual HValue* Canonicalize();
1234 Representation from() { return value()->representation(); }
1235 Representation to() { return representation(); }
1236 bool deoptimize_on_undefined() const {
1237 return CheckFlag(kDeoptimizeOnUndefined);
1239 bool deoptimize_on_minus_zero() const {
1240 return CheckFlag(kBailoutOnMinusZero);
1242 virtual Representation RequiredInputRepresentation(int index) {
1246 virtual Range* InferRange(Zone* zone);
1248 virtual void PrintDataTo(StringStream* stream);
1250 DECLARE_CONCRETE_INSTRUCTION(Change)
1253 virtual bool DataEquals(HValue* other) { return true; }
1257 class HClampToUint8: public HUnaryOperation {
1259 explicit HClampToUint8(HValue* value)
1260 : HUnaryOperation(value) {
1261 set_representation(Representation::Integer32());
1265 virtual Representation RequiredInputRepresentation(int index) {
1266 return Representation::None();
1269 DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
1272 virtual bool DataEquals(HValue* other) { return true; }
1276 class HSimulate: public HInstruction {
1278 HSimulate(int ast_id, int pop_count)
1280 pop_count_(pop_count),
1282 assigned_indexes_(2) {}
1283 virtual ~HSimulate() {}
1285 virtual void PrintDataTo(StringStream* stream);
1287 bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; }
1288 int ast_id() const { return ast_id_; }
1289 void set_ast_id(int id) {
1290 ASSERT(!HasAstId());
1294 int pop_count() const { return pop_count_; }
1295 const ZoneList<HValue*>* values() const { return &values_; }
1296 int GetAssignedIndexAt(int index) const {
1297 ASSERT(HasAssignedIndexAt(index));
1298 return assigned_indexes_[index];
1300 bool HasAssignedIndexAt(int index) const {
1301 return assigned_indexes_[index] != kNoIndex;
1303 void AddAssignedValue(int index, HValue* value) {
1304 AddValue(index, value);
1306 void AddPushedValue(HValue* value) {
1307 AddValue(kNoIndex, value);
1309 virtual int OperandCount() { return values_.length(); }
1310 virtual HValue* OperandAt(int index) { return values_[index]; }
1312 virtual Representation RequiredInputRepresentation(int index) {
1313 return Representation::None();
1316 DECLARE_CONCRETE_INSTRUCTION(Simulate)
1319 virtual void Verify();
1323 virtual void InternalSetOperandAt(int index, HValue* value) {
1324 values_[index] = value;
1328 static const int kNoIndex = -1;
1329 void AddValue(int index, HValue* value) {
1330 assigned_indexes_.Add(index);
1331 // Resize the list of pushed values.
1333 // Set the operand through the base method in HValue to make sure that the
1334 // use lists are correctly updated.
1335 SetOperandAt(values_.length() - 1, value);
1339 ZoneList<HValue*> values_;
1340 ZoneList<int> assigned_indexes_;
1344 class HStackCheck: public HTemplateInstruction<1> {
1351 HStackCheck(HValue* context, Type type) : type_(type) {
1352 SetOperandAt(0, context);
1353 SetGVNFlag(kChangesNewSpacePromotion);
1356 HValue* context() { return OperandAt(0); }
1358 virtual Representation RequiredInputRepresentation(int index) {
1359 return Representation::Tagged();
1363 // The stack check eliminator might try to eliminate the same stack
1364 // check instruction multiple times.
1370 bool is_function_entry() { return type_ == kFunctionEntry; }
1371 bool is_backwards_branch() { return type_ == kBackwardsBranch; }
1373 DECLARE_CONCRETE_INSTRUCTION(StackCheck)
1380 class HEnterInlined: public HTemplateInstruction<0> {
1382 HEnterInlined(Handle<JSFunction> closure,
1383 int arguments_count,
1384 FunctionLiteral* function,
1387 Variable* arguments_var,
1388 ZoneList<HValue*>* arguments_values)
1389 : closure_(closure),
1390 arguments_count_(arguments_count),
1391 function_(function),
1392 call_kind_(call_kind),
1393 is_construct_(is_construct),
1394 arguments_var_(arguments_var),
1395 arguments_values_(arguments_values) {
1398 virtual void PrintDataTo(StringStream* stream);
1400 Handle<JSFunction> closure() const { return closure_; }
1401 int arguments_count() const { return arguments_count_; }
1402 FunctionLiteral* function() const { return function_; }
1403 CallKind call_kind() const { return call_kind_; }
1404 bool is_construct() const { return is_construct_; }
1406 virtual Representation RequiredInputRepresentation(int index) {
1407 return Representation::None();
1410 Variable* arguments_var() { return arguments_var_; }
1411 ZoneList<HValue*>* arguments_values() { return arguments_values_; }
1413 DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
1416 Handle<JSFunction> closure_;
1417 int arguments_count_;
1418 FunctionLiteral* function_;
1419 CallKind call_kind_;
1421 Variable* arguments_var_;
1422 ZoneList<HValue*>* arguments_values_;
1426 class HLeaveInlined: public HTemplateInstruction<0> {
1428 explicit HLeaveInlined(bool arguments_pushed)
1429 : arguments_pushed_(arguments_pushed) { }
1431 virtual Representation RequiredInputRepresentation(int index) {
1432 return Representation::None();
1435 bool arguments_pushed() {
1436 return arguments_pushed_;
1439 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
1442 bool arguments_pushed_;
1446 class HPushArgument: public HUnaryOperation {
1448 explicit HPushArgument(HValue* value) : HUnaryOperation(value) {
1449 set_representation(Representation::Tagged());
1452 virtual Representation RequiredInputRepresentation(int index) {
1453 return Representation::Tagged();
1456 HValue* argument() { return OperandAt(0); }
1458 DECLARE_CONCRETE_INSTRUCTION(PushArgument)
1462 class HThisFunction: public HTemplateInstruction<0> {
1464 explicit HThisFunction(Handle<JSFunction> closure) : closure_(closure) {
1465 set_representation(Representation::Tagged());
1469 virtual Representation RequiredInputRepresentation(int index) {
1470 return Representation::None();
1473 Handle<JSFunction> closure() const { return closure_; }
1475 DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
1478 virtual bool DataEquals(HValue* other) {
1479 HThisFunction* b = HThisFunction::cast(other);
1480 return *closure() == *b->closure();
1484 Handle<JSFunction> closure_;
1488 class HContext: public HTemplateInstruction<0> {
1491 set_representation(Representation::Tagged());
1495 virtual Representation RequiredInputRepresentation(int index) {
1496 return Representation::None();
1499 DECLARE_CONCRETE_INSTRUCTION(Context)
1502 virtual bool DataEquals(HValue* other) { return true; }
1506 class HOuterContext: public HUnaryOperation {
1508 explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
1509 set_representation(Representation::Tagged());
1513 DECLARE_CONCRETE_INSTRUCTION(OuterContext);
1515 virtual Representation RequiredInputRepresentation(int index) {
1516 return Representation::Tagged();
1520 virtual bool DataEquals(HValue* other) { return true; }
1524 class HDeclareGlobals: public HUnaryOperation {
1526 HDeclareGlobals(HValue* context,
1527 Handle<FixedArray> pairs,
1529 : HUnaryOperation(context),
1532 set_representation(Representation::Tagged());
1533 SetAllSideEffects();
1536 HValue* context() { return OperandAt(0); }
1537 Handle<FixedArray> pairs() const { return pairs_; }
1538 int flags() const { return flags_; }
1540 DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
1542 virtual Representation RequiredInputRepresentation(int index) {
1543 return Representation::Tagged();
1546 Handle<FixedArray> pairs_;
1551 class HGlobalObject: public HUnaryOperation {
1553 explicit HGlobalObject(HValue* context) : HUnaryOperation(context), qml_global_(false) {
1554 set_representation(Representation::Tagged());
1558 virtual void PrintDataTo(StringStream* stream);
1560 DECLARE_CONCRETE_INSTRUCTION(GlobalObject)
1562 virtual Representation RequiredInputRepresentation(int index) {
1563 return Representation::Tagged();
1566 bool qml_global() { return qml_global_; }
1567 void set_qml_global(bool v) { qml_global_ = v; }
1570 virtual bool DataEquals(HValue* other) {
1571 HGlobalObject* o = HGlobalObject::cast(other);
1572 return o->qml_global_ == qml_global_;
1580 class HGlobalReceiver: public HUnaryOperation {
1582 explicit HGlobalReceiver(HValue* global_object)
1583 : HUnaryOperation(global_object) {
1584 set_representation(Representation::Tagged());
1588 DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver)
1590 virtual Representation RequiredInputRepresentation(int index) {
1591 return Representation::Tagged();
1595 virtual bool DataEquals(HValue* other) { return true; }
1600 class HCall: public HTemplateInstruction<V> {
1602 // The argument count includes the receiver.
1603 explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
1604 this->set_representation(Representation::Tagged());
1605 this->SetAllSideEffects();
1608 virtual HType CalculateInferredType() { return HType::Tagged(); }
1610 virtual int argument_count() const { return argument_count_; }
1612 virtual bool IsCall() { return true; }
1615 int argument_count_;
1619 class HUnaryCall: public HCall<1> {
1621 HUnaryCall(HValue* value, int argument_count)
1622 : HCall<1>(argument_count) {
1623 SetOperandAt(0, value);
1626 virtual Representation RequiredInputRepresentation(int index) {
1627 return Representation::Tagged();
1630 virtual void PrintDataTo(StringStream* stream);
1632 HValue* value() { return OperandAt(0); }
1636 class HBinaryCall: public HCall<2> {
1638 HBinaryCall(HValue* first, HValue* second, int argument_count)
1639 : HCall<2>(argument_count) {
1640 SetOperandAt(0, first);
1641 SetOperandAt(1, second);
1644 virtual void PrintDataTo(StringStream* stream);
1646 virtual Representation RequiredInputRepresentation(int index) {
1647 return Representation::Tagged();
1650 HValue* first() { return OperandAt(0); }
1651 HValue* second() { return OperandAt(1); }
1655 class HInvokeFunction: public HBinaryCall {
1657 HInvokeFunction(HValue* context, HValue* function, int argument_count)
1658 : HBinaryCall(context, function, argument_count) {
1661 HInvokeFunction(HValue* context,
1663 Handle<JSFunction> known_function,
1665 : HBinaryCall(context, function, argument_count),
1666 known_function_(known_function) {
1669 virtual Representation RequiredInputRepresentation(int index) {
1670 return Representation::Tagged();
1673 HValue* context() { return first(); }
1674 HValue* function() { return second(); }
1675 Handle<JSFunction> known_function() { return known_function_; }
1677 DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
1680 Handle<JSFunction> known_function_;
1684 class HCallConstantFunction: public HCall<0> {
1686 HCallConstantFunction(Handle<JSFunction> function, int argument_count)
1687 : HCall<0>(argument_count), function_(function) { }
1689 Handle<JSFunction> function() const { return function_; }
1691 bool IsApplyFunction() const {
1692 return function_->code() ==
1693 Isolate::Current()->builtins()->builtin(Builtins::kFunctionApply);
1696 virtual void PrintDataTo(StringStream* stream);
1698 virtual Representation RequiredInputRepresentation(int index) {
1699 return Representation::None();
1702 DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction)
1705 Handle<JSFunction> function_;
1709 class HCallKeyed: public HBinaryCall {
1711 HCallKeyed(HValue* context, HValue* key, int argument_count)
1712 : HBinaryCall(context, key, argument_count) {
1715 virtual Representation RequiredInputRepresentation(int index) {
1716 return Representation::Tagged();
1719 HValue* context() { return first(); }
1720 HValue* key() { return second(); }
1722 DECLARE_CONCRETE_INSTRUCTION(CallKeyed)
1726 class HCallNamed: public HUnaryCall {
1728 HCallNamed(HValue* context, Handle<String> name, int argument_count)
1729 : HUnaryCall(context, argument_count), name_(name) {
1732 virtual void PrintDataTo(StringStream* stream);
1734 HValue* context() { return value(); }
1735 Handle<String> name() const { return name_; }
1737 DECLARE_CONCRETE_INSTRUCTION(CallNamed)
1739 virtual Representation RequiredInputRepresentation(int index) {
1740 return Representation::Tagged();
1744 Handle<String> name_;
1748 class HCallFunction: public HBinaryCall {
1750 HCallFunction(HValue* context, HValue* function, int argument_count)
1751 : HBinaryCall(context, function, argument_count) {
1754 HValue* context() { return first(); }
1755 HValue* function() { return second(); }
1757 virtual Representation RequiredInputRepresentation(int index) {
1758 return Representation::Tagged();
1761 DECLARE_CONCRETE_INSTRUCTION(CallFunction)
1765 class HCallGlobal: public HUnaryCall {
1767 HCallGlobal(HValue* context, Handle<String> name, int argument_count)
1768 : HUnaryCall(context, argument_count), name_(name), qml_global_(false) {
1771 virtual void PrintDataTo(StringStream* stream);
1773 HValue* context() { return value(); }
1774 Handle<String> name() const { return name_; }
1776 virtual Representation RequiredInputRepresentation(int index) {
1777 return Representation::Tagged();
1780 bool qml_global() { return qml_global_; }
1781 void set_qml_global(bool v) { qml_global_ = v; }
1783 DECLARE_CONCRETE_INSTRUCTION(CallGlobal)
1786 Handle<String> name_;
1791 class HCallKnownGlobal: public HCall<0> {
1793 HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
1794 : HCall<0>(argument_count), target_(target) { }
1796 virtual void PrintDataTo(StringStream* stream);
1798 Handle<JSFunction> target() const { return target_; }
1800 virtual Representation RequiredInputRepresentation(int index) {
1801 return Representation::None();
1804 DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal)
1807 Handle<JSFunction> target_;
1811 class HCallNew: public HBinaryCall {
1813 HCallNew(HValue* context, HValue* constructor, int argument_count)
1814 : HBinaryCall(context, constructor, argument_count) {
1817 virtual Representation RequiredInputRepresentation(int index) {
1818 return Representation::Tagged();
1821 HValue* context() { return first(); }
1822 HValue* constructor() { return second(); }
1824 DECLARE_CONCRETE_INSTRUCTION(CallNew)
1828 class HCallRuntime: public HCall<1> {
1830 HCallRuntime(HValue* context,
1831 Handle<String> name,
1832 const Runtime::Function* c_function,
1834 : HCall<1>(argument_count), c_function_(c_function), name_(name) {
1835 SetOperandAt(0, context);
1838 virtual void PrintDataTo(StringStream* stream);
1840 HValue* context() { return OperandAt(0); }
1841 const Runtime::Function* function() const { return c_function_; }
1842 Handle<String> name() const { return name_; }
1844 virtual Representation RequiredInputRepresentation(int index) {
1845 return Representation::Tagged();
1848 DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
1851 const Runtime::Function* c_function_;
1852 Handle<String> name_;
1856 class HJSArrayLength: public HTemplateInstruction<2> {
1858 HJSArrayLength(HValue* value, HValue* typecheck) {
1859 // The length of an array is stored as a tagged value in the array
1860 // object. It is guaranteed to be 32 bit integer, but it can be
1861 // represented as either a smi or heap number.
1862 SetOperandAt(0, value);
1863 SetOperandAt(1, typecheck);
1864 set_representation(Representation::Tagged());
1866 SetGVNFlag(kDependsOnArrayLengths);
1867 SetGVNFlag(kDependsOnMaps);
1870 virtual Representation RequiredInputRepresentation(int index) {
1871 return Representation::Tagged();
1874 virtual void PrintDataTo(StringStream* stream);
1876 HValue* value() { return OperandAt(0); }
1877 HValue* typecheck() { return OperandAt(1); }
1879 DECLARE_CONCRETE_INSTRUCTION(JSArrayLength)
1882 virtual bool DataEquals(HValue* other) { return true; }
1886 class HFixedArrayBaseLength: public HUnaryOperation {
1888 explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) {
1889 set_representation(Representation::Tagged());
1891 SetGVNFlag(kDependsOnArrayLengths);
1894 virtual Representation RequiredInputRepresentation(int index) {
1895 return Representation::Tagged();
1898 DECLARE_CONCRETE_INSTRUCTION(FixedArrayBaseLength)
1901 virtual bool DataEquals(HValue* other) { return true; }
1905 class HElementsKind: public HUnaryOperation {
1907 explicit HElementsKind(HValue* value) : HUnaryOperation(value) {
1908 set_representation(Representation::Integer32());
1910 SetGVNFlag(kDependsOnElementsKind);
1913 virtual Representation RequiredInputRepresentation(int index) {
1914 return Representation::Tagged();
1917 DECLARE_CONCRETE_INSTRUCTION(ElementsKind)
1920 virtual bool DataEquals(HValue* other) { return true; }
1924 class HBitNot: public HUnaryOperation {
1926 explicit HBitNot(HValue* value) : HUnaryOperation(value) {
1927 set_representation(Representation::Integer32());
1929 SetFlag(kTruncatingToInt32);
1932 virtual Representation RequiredInputRepresentation(int index) {
1933 return Representation::Integer32();
1935 virtual HType CalculateInferredType();
1937 virtual HValue* Canonicalize();
1939 DECLARE_CONCRETE_INSTRUCTION(BitNot)
1942 virtual bool DataEquals(HValue* other) { return true; }
1946 class HUnaryMathOperation: public HTemplateInstruction<2> {
1948 HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
1950 SetOperandAt(0, context);
1951 SetOperandAt(1, value);
1956 set_representation(Representation::Integer32());
1959 set_representation(Representation::Tagged());
1960 SetFlag(kFlexibleRepresentation);
1961 SetGVNFlag(kChangesNewSpacePromotion);
1969 set_representation(Representation::Double());
1970 SetGVNFlag(kChangesNewSpacePromotion);
1978 HValue* context() { return OperandAt(0); }
1979 HValue* value() { return OperandAt(1); }
1981 virtual void PrintDataTo(StringStream* stream);
1983 virtual HType CalculateInferredType();
1985 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1987 virtual Representation RequiredInputRepresentation(int index) {
1989 return Representation::Tagged();
2001 return Representation::Double();
2003 return representation();
2006 return Representation::None();
2011 virtual HValue* Canonicalize();
2013 BuiltinFunctionId op() const { return op_; }
2014 const char* OpName() const;
2016 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
2019 virtual bool DataEquals(HValue* other) {
2020 HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
2021 return op_ == b->op();
2025 BuiltinFunctionId op_;
2029 class HLoadElements: public HUnaryOperation {
2031 explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
2032 set_representation(Representation::Tagged());
2034 SetGVNFlag(kDependsOnElementsPointer);
2037 virtual Representation RequiredInputRepresentation(int index) {
2038 return Representation::Tagged();
2041 DECLARE_CONCRETE_INSTRUCTION(LoadElements)
2044 virtual bool DataEquals(HValue* other) { return true; }
2048 class HLoadExternalArrayPointer: public HUnaryOperation {
2050 explicit HLoadExternalArrayPointer(HValue* value)
2051 : HUnaryOperation(value) {
2052 set_representation(Representation::External());
2053 // The result of this instruction is idempotent as long as its inputs don't
2054 // change. The external array of a specialized array elements object cannot
2055 // change once set, so it's no necessary to introduce any additional
2056 // dependencies on top of the inputs.
2060 virtual Representation RequiredInputRepresentation(int index) {
2061 return Representation::Tagged();
2064 DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer)
2067 virtual bool DataEquals(HValue* other) { return true; }
2071 class HCheckMaps: public HTemplateInstruction<2> {
2073 HCheckMaps(HValue* value, Handle<Map> map, HValue* typecheck = NULL) {
2074 SetOperandAt(0, value);
2075 // If callers don't depend on a typecheck, they can pass in NULL. In that
2076 // case we use a copy of the |value| argument as a dummy value.
2077 SetOperandAt(1, typecheck != NULL ? typecheck : value);
2078 set_representation(Representation::Tagged());
2080 SetGVNFlag(kDependsOnMaps);
2081 SetGVNFlag(kDependsOnElementsKind);
2082 map_set()->Add(map);
2084 HCheckMaps(HValue* value, SmallMapList* maps) {
2085 SetOperandAt(0, value);
2086 SetOperandAt(1, value);
2087 set_representation(Representation::Tagged());
2089 SetGVNFlag(kDependsOnMaps);
2090 SetGVNFlag(kDependsOnElementsKind);
2091 for (int i = 0; i < maps->length(); i++) {
2092 map_set()->Add(maps->at(i));
2097 static HCheckMaps* NewWithTransitions(HValue* object, Handle<Map> map) {
2098 HCheckMaps* check_map = new HCheckMaps(object, map);
2099 SmallMapList* map_set = check_map->map_set();
2101 // If the map to check has the untransitioned elements, it can be hoisted
2102 // above TransitionElements instructions.
2103 if (map->has_fast_smi_only_elements()) {
2104 check_map->ClearGVNFlag(kDependsOnElementsKind);
2107 Map* transitioned_fast_element_map =
2108 map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL);
2109 ASSERT(transitioned_fast_element_map == NULL ||
2110 map->elements_kind() != FAST_ELEMENTS);
2111 if (transitioned_fast_element_map != NULL) {
2112 map_set->Add(Handle<Map>(transitioned_fast_element_map));
2114 Map* transitioned_double_map =
2115 map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL);
2116 ASSERT(transitioned_double_map == NULL ||
2117 map->elements_kind() == FAST_SMI_ONLY_ELEMENTS);
2118 if (transitioned_double_map != NULL) {
2119 map_set->Add(Handle<Map>(transitioned_double_map));
2126 virtual Representation RequiredInputRepresentation(int index) {
2127 return Representation::Tagged();
2129 virtual void PrintDataTo(StringStream* stream);
2130 virtual HType CalculateInferredType();
2132 HValue* value() { return OperandAt(0); }
2133 SmallMapList* map_set() { return &map_set_; }
2135 DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
2138 virtual bool DataEquals(HValue* other) {
2139 HCheckMaps* b = HCheckMaps::cast(other);
2140 // Relies on the fact that map_set has been sorted before.
2141 if (map_set()->length() != b->map_set()->length()) return false;
2142 for (int i = 0; i < map_set()->length(); i++) {
2143 if (!map_set()->at(i).is_identical_to(b->map_set()->at(i))) return false;
2149 SmallMapList map_set_;
2153 class HCheckFunction: public HUnaryOperation {
2155 HCheckFunction(HValue* value, Handle<JSFunction> function)
2156 : HUnaryOperation(value), target_(function) {
2157 set_representation(Representation::Tagged());
2161 virtual Representation RequiredInputRepresentation(int index) {
2162 return Representation::Tagged();
2164 virtual void PrintDataTo(StringStream* stream);
2165 virtual HType CalculateInferredType();
2168 virtual void Verify();
2171 Handle<JSFunction> target() const { return target_; }
2173 DECLARE_CONCRETE_INSTRUCTION(CheckFunction)
2176 virtual bool DataEquals(HValue* other) {
2177 HCheckFunction* b = HCheckFunction::cast(other);
2178 return target_.is_identical_to(b->target());
2182 Handle<JSFunction> target_;
2186 class HCheckInstanceType: public HUnaryOperation {
2188 static HCheckInstanceType* NewIsSpecObject(HValue* value) {
2189 return new HCheckInstanceType(value, IS_SPEC_OBJECT);
2191 static HCheckInstanceType* NewIsJSArray(HValue* value) {
2192 return new HCheckInstanceType(value, IS_JS_ARRAY);
2194 static HCheckInstanceType* NewIsString(HValue* value) {
2195 return new HCheckInstanceType(value, IS_STRING);
2197 static HCheckInstanceType* NewIsSymbol(HValue* value) {
2198 return new HCheckInstanceType(value, IS_SYMBOL);
2201 virtual void PrintDataTo(StringStream* stream);
2203 virtual Representation RequiredInputRepresentation(int index) {
2204 return Representation::Tagged();
2207 virtual HValue* Canonicalize();
2209 bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
2210 void GetCheckInterval(InstanceType* first, InstanceType* last);
2211 void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
2213 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
2216 // TODO(ager): It could be nice to allow the ommision of instance
2217 // type checks if we have already performed an instance type check
2218 // with a larger range.
2219 virtual bool DataEquals(HValue* other) {
2220 HCheckInstanceType* b = HCheckInstanceType::cast(other);
2221 return check_ == b->check_;
2230 LAST_INTERVAL_CHECK = IS_JS_ARRAY
2233 const char* GetCheckName();
2235 HCheckInstanceType(HValue* value, Check check)
2236 : HUnaryOperation(value), check_(check) {
2237 set_representation(Representation::Tagged());
2245 class HCheckNonSmi: public HUnaryOperation {
2247 explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
2248 set_representation(Representation::Tagged());
2252 virtual Representation RequiredInputRepresentation(int index) {
2253 return Representation::Tagged();
2256 virtual HType CalculateInferredType();
2259 virtual void Verify();
2262 virtual HValue* Canonicalize() {
2263 HType value_type = value()->type();
2264 if (!value_type.IsUninitialized() &&
2265 (value_type.IsHeapNumber() ||
2266 value_type.IsString() ||
2267 value_type.IsBoolean() ||
2268 value_type.IsNonPrimitive())) {
2274 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi)
2277 virtual bool DataEquals(HValue* other) { return true; }
2281 class HCheckPrototypeMaps: public HTemplateInstruction<0> {
2283 HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
2284 : prototype_(prototype), holder_(holder) {
2286 SetGVNFlag(kDependsOnMaps);
2290 virtual void Verify();
2293 Handle<JSObject> prototype() const { return prototype_; }
2294 Handle<JSObject> holder() const { return holder_; }
2296 DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps)
2298 virtual Representation RequiredInputRepresentation(int index) {
2299 return Representation::None();
2302 virtual intptr_t Hashcode() {
2303 ASSERT(!HEAP->IsAllocationAllowed());
2304 intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
2305 hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
2310 virtual bool DataEquals(HValue* other) {
2311 HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
2312 return prototype_.is_identical_to(b->prototype()) &&
2313 holder_.is_identical_to(b->holder());
2317 Handle<JSObject> prototype_;
2318 Handle<JSObject> holder_;
2322 class HCheckSmi: public HUnaryOperation {
2324 explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
2325 set_representation(Representation::Tagged());
2329 virtual Representation RequiredInputRepresentation(int index) {
2330 return Representation::Tagged();
2332 virtual HType CalculateInferredType();
2335 virtual void Verify();
2338 DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
2341 virtual bool DataEquals(HValue* other) { return true; }
2345 class HPhi: public HValue {
2347 explicit HPhi(int merged_index)
2349 merged_index_(merged_index),
2352 is_convertible_to_integer_(true) {
2353 for (int i = 0; i < Representation::kNumRepresentations; i++) {
2354 non_phi_uses_[i] = 0;
2355 indirect_uses_[i] = 0;
2357 ASSERT(merged_index >= 0);
2358 set_representation(Representation::Tagged());
2359 SetFlag(kFlexibleRepresentation);
2362 virtual Representation InferredRepresentation();
2364 virtual Range* InferRange(Zone* zone);
2365 virtual Representation RequiredInputRepresentation(int index) {
2366 return representation();
2368 virtual HType CalculateInferredType();
2369 virtual int OperandCount() { return inputs_.length(); }
2370 virtual HValue* OperandAt(int index) { return inputs_[index]; }
2371 HValue* GetRedundantReplacement();
2372 void AddInput(HValue* value);
2375 bool IsReceiver() { return merged_index_ == 0; }
2377 int merged_index() const { return merged_index_; }
2379 virtual void PrintTo(StringStream* stream);
2382 virtual void Verify();
2385 void InitRealUses(int id);
2386 void AddNonPhiUsesFrom(HPhi* other);
2387 void AddIndirectUsesTo(int* use_count);
2389 int tagged_non_phi_uses() const {
2390 return non_phi_uses_[Representation::kTagged];
2392 int int32_non_phi_uses() const {
2393 return non_phi_uses_[Representation::kInteger32];
2395 int double_non_phi_uses() const {
2396 return non_phi_uses_[Representation::kDouble];
2398 int tagged_indirect_uses() const {
2399 return indirect_uses_[Representation::kTagged];
2401 int int32_indirect_uses() const {
2402 return indirect_uses_[Representation::kInteger32];
2404 int double_indirect_uses() const {
2405 return indirect_uses_[Representation::kDouble];
2407 int phi_id() { return phi_id_; }
2408 bool is_live() { return is_live_; }
2409 void set_is_live(bool b) { is_live_ = b; }
2411 static HPhi* cast(HValue* value) {
2412 ASSERT(value->IsPhi());
2413 return reinterpret_cast<HPhi*>(value);
2415 virtual Opcode opcode() const { return HValue::kPhi; }
2417 virtual bool IsConvertibleToInteger() const {
2418 return is_convertible_to_integer_;
2421 void set_is_convertible_to_integer(bool b) {
2422 is_convertible_to_integer_ = b;
2425 bool AllOperandsConvertibleToInteger() {
2426 for (int i = 0; i < OperandCount(); ++i) {
2427 if (!OperandAt(i)->IsConvertibleToInteger()) return false;
2433 virtual void DeleteFromGraph();
2434 virtual void InternalSetOperandAt(int index, HValue* value) {
2435 inputs_[index] = value;
2439 ZoneList<HValue*> inputs_;
2442 int non_phi_uses_[Representation::kNumRepresentations];
2443 int indirect_uses_[Representation::kNumRepresentations];
2446 bool is_convertible_to_integer_;
2450 class HArgumentsObject: public HTemplateInstruction<0> {
2452 HArgumentsObject() {
2453 set_representation(Representation::Tagged());
2454 SetFlag(kIsArguments);
2457 virtual Representation RequiredInputRepresentation(int index) {
2458 return Representation::None();
2461 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
2465 class HConstant: public HTemplateInstruction<0> {
2467 HConstant(Handle<Object> handle, Representation r);
2469 Handle<Object> handle() const { return handle_; }
2471 bool InOldSpace() const { return !HEAP->InNewSpace(*handle_); }
2473 bool ImmortalImmovable() const {
2475 if (*handle_ == heap->undefined_value()) return true;
2476 if (*handle_ == heap->null_value()) return true;
2477 if (*handle_ == heap->true_value()) return true;
2478 if (*handle_ == heap->false_value()) return true;
2479 if (*handle_ == heap->the_hole_value()) return true;
2480 if (*handle_ == heap->minus_zero_value()) return true;
2481 if (*handle_ == heap->nan_value()) return true;
2482 if (*handle_ == heap->empty_string()) return true;
2486 virtual Representation RequiredInputRepresentation(int index) {
2487 return Representation::None();
2490 virtual bool IsConvertibleToInteger() const {
2491 if (handle_->IsSmi()) return true;
2492 if (handle_->IsHeapNumber() &&
2493 (HeapNumber::cast(*handle_)->value() ==
2494 static_cast<double>(NumberToInt32(*handle_)))) return true;
2498 virtual bool EmitAtUses() { return !representation().IsDouble(); }
2499 virtual HValue* Canonicalize();
2500 virtual void PrintDataTo(StringStream* stream);
2501 virtual HType CalculateInferredType();
2502 bool IsInteger() const { return handle_->IsSmi(); }
2503 HConstant* CopyToRepresentation(Representation r) const;
2504 HConstant* CopyToTruncatedInt32() const;
2505 bool HasInteger32Value() const { return has_int32_value_; }
2506 int32_t Integer32Value() const {
2507 ASSERT(HasInteger32Value());
2508 return int32_value_;
2510 bool HasDoubleValue() const { return has_double_value_; }
2511 double DoubleValue() const {
2512 ASSERT(HasDoubleValue());
2513 return double_value_;
2515 bool HasNumberValue() const { return has_int32_value_ || has_double_value_; }
2516 int32_t NumberValueAsInteger32() const {
2517 ASSERT(HasNumberValue());
2518 if (has_int32_value_) return int32_value_;
2519 return DoubleToInt32(double_value_);
2521 bool HasStringValue() const { return handle_->IsString(); }
2523 bool ToBoolean() const;
2525 virtual intptr_t Hashcode() {
2526 ASSERT(!HEAP->allow_allocation(false));
2527 intptr_t hash = reinterpret_cast<intptr_t>(*handle());
2528 // Prevent smis from having fewer hash values when truncated to
2529 // the least significant bits.
2530 const int kShiftSize = kSmiShiftSize + kSmiTagSize;
2531 STATIC_ASSERT(kShiftSize != 0);
2532 return hash ^ (hash >> kShiftSize);
2536 virtual void Verify() { }
2539 DECLARE_CONCRETE_INSTRUCTION(Constant)
2542 virtual Range* InferRange(Zone* zone);
2544 virtual bool DataEquals(HValue* other) {
2545 HConstant* other_constant = HConstant::cast(other);
2546 return handle().is_identical_to(other_constant->handle());
2550 Handle<Object> handle_;
2552 // The following two values represent the int32 and the double value of the
2553 // given constant if there is a lossless conversion between the constant
2554 // and the specific representation.
2555 bool has_int32_value_ : 1;
2556 bool has_double_value_ : 1;
2557 int32_t int32_value_;
2558 double double_value_;
2562 class HBinaryOperation: public HTemplateInstruction<3> {
2564 HBinaryOperation(HValue* context, HValue* left, HValue* right) {
2565 ASSERT(left != NULL && right != NULL);
2566 SetOperandAt(0, context);
2567 SetOperandAt(1, left);
2568 SetOperandAt(2, right);
2571 HValue* context() { return OperandAt(0); }
2572 HValue* left() { return OperandAt(1); }
2573 HValue* right() { return OperandAt(2); }
2575 // TODO(kasperl): Move these helpers to the IA-32 Lithium
2576 // instruction sequence builder.
2577 HValue* LeastConstantOperand() {
2578 if (IsCommutative() && left()->IsConstant()) return right();
2581 HValue* MostConstantOperand() {
2582 if (IsCommutative() && left()->IsConstant()) return left();
2586 virtual bool IsCommutative() const { return false; }
2588 virtual void PrintDataTo(StringStream* stream);
2592 class HWrapReceiver: public HTemplateInstruction<2> {
2594 HWrapReceiver(HValue* receiver, HValue* function) {
2595 set_representation(Representation::Tagged());
2596 SetOperandAt(0, receiver);
2597 SetOperandAt(1, function);
2600 virtual Representation RequiredInputRepresentation(int index) {
2601 return Representation::Tagged();
2604 HValue* receiver() { return OperandAt(0); }
2605 HValue* function() { return OperandAt(1); }
2607 virtual HValue* Canonicalize();
2609 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
2613 class HApplyArguments: public HTemplateInstruction<4> {
2615 HApplyArguments(HValue* function,
2619 set_representation(Representation::Tagged());
2620 SetOperandAt(0, function);
2621 SetOperandAt(1, receiver);
2622 SetOperandAt(2, length);
2623 SetOperandAt(3, elements);
2624 SetAllSideEffects();
2627 virtual Representation RequiredInputRepresentation(int index) {
2628 // The length is untagged, all other inputs are tagged.
2630 ? Representation::Integer32()
2631 : Representation::Tagged();
2634 HValue* function() { return OperandAt(0); }
2635 HValue* receiver() { return OperandAt(1); }
2636 HValue* length() { return OperandAt(2); }
2637 HValue* elements() { return OperandAt(3); }
2639 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
2643 class HArgumentsElements: public HTemplateInstruction<0> {
2645 explicit HArgumentsElements(bool from_inlined) : from_inlined_(from_inlined) {
2646 // The value produced by this instruction is a pointer into the stack
2647 // that looks as if it was a smi because of alignment.
2648 set_representation(Representation::Tagged());
2652 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
2654 virtual Representation RequiredInputRepresentation(int index) {
2655 return Representation::None();
2658 bool from_inlined() const { return from_inlined_; }
2661 virtual bool DataEquals(HValue* other) { return true; }
2667 class HArgumentsLength: public HUnaryOperation {
2669 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
2670 set_representation(Representation::Integer32());
2674 virtual Representation RequiredInputRepresentation(int index) {
2675 return Representation::Tagged();
2678 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
2681 virtual bool DataEquals(HValue* other) { return true; }
2685 class HAccessArgumentsAt: public HTemplateInstruction<3> {
2687 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
2688 set_representation(Representation::Tagged());
2690 SetOperandAt(0, arguments);
2691 SetOperandAt(1, length);
2692 SetOperandAt(2, index);
2695 virtual void PrintDataTo(StringStream* stream);
2697 virtual Representation RequiredInputRepresentation(int index) {
2698 // The arguments elements is considered tagged.
2700 ? Representation::Tagged()
2701 : Representation::Integer32();
2704 HValue* arguments() { return OperandAt(0); }
2705 HValue* length() { return OperandAt(1); }
2706 HValue* index() { return OperandAt(2); }
2708 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
2710 virtual bool DataEquals(HValue* other) { return true; }
2714 class HBoundsCheck: public HTemplateInstruction<2> {
2716 HBoundsCheck(HValue* index, HValue* length) {
2717 SetOperandAt(0, index);
2718 SetOperandAt(1, length);
2719 set_representation(Representation::Integer32());
2723 virtual Representation RequiredInputRepresentation(int index) {
2724 return Representation::Integer32();
2727 virtual void PrintDataTo(StringStream* stream);
2729 HValue* index() { return OperandAt(0); }
2730 HValue* length() { return OperandAt(1); }
2732 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
2735 virtual bool DataEquals(HValue* other) { return true; }
2739 class HBitwiseBinaryOperation: public HBinaryOperation {
2741 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right)
2742 : HBinaryOperation(context, left, right) {
2743 set_representation(Representation::Tagged());
2744 SetFlag(kFlexibleRepresentation);
2745 SetAllSideEffects();
2748 virtual Representation RequiredInputRepresentation(int index) {
2750 ? Representation::Tagged()
2754 virtual void RepresentationChanged(Representation to) {
2755 if (!to.IsTagged()) {
2756 ASSERT(to.IsInteger32());
2757 ClearAllSideEffects();
2758 SetFlag(kTruncatingToInt32);
2763 virtual HType CalculateInferredType();
2765 DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
2769 class HMathFloorOfDiv: public HBinaryOperation {
2771 HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
2772 : HBinaryOperation(context, left, right) {
2773 set_representation(Representation::Integer32());
2777 virtual Representation RequiredInputRepresentation(int index) {
2778 return Representation::Integer32();
2781 DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
2784 virtual bool DataEquals(HValue* other) { return true; }
2788 class HArithmeticBinaryOperation: public HBinaryOperation {
2790 HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right)
2791 : HBinaryOperation(context, left, right) {
2792 set_representation(Representation::Tagged());
2793 SetFlag(kFlexibleRepresentation);
2794 SetAllSideEffects();
2797 virtual void RepresentationChanged(Representation to) {
2798 if (!to.IsTagged()) {
2799 ClearAllSideEffects();
2804 virtual HType CalculateInferredType();
2805 virtual Representation RequiredInputRepresentation(int index) {
2807 ? Representation::Tagged()
2811 virtual Representation InferredRepresentation() {
2812 if (left()->representation().Equals(right()->representation())) {
2813 return left()->representation();
2815 return HValue::InferredRepresentation();
2820 class HCompareGeneric: public HBinaryOperation {
2822 HCompareGeneric(HValue* context,
2826 : HBinaryOperation(context, left, right), token_(token) {
2827 ASSERT(Token::IsCompareOp(token));
2828 set_representation(Representation::Tagged());
2829 SetAllSideEffects();
2832 virtual Representation RequiredInputRepresentation(int index) {
2833 return Representation::Tagged();
2836 Representation GetInputRepresentation() const {
2837 return Representation::Tagged();
2840 Token::Value token() const { return token_; }
2841 virtual void PrintDataTo(StringStream* stream);
2843 virtual HType CalculateInferredType();
2845 DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
2848 Token::Value token_;
2852 class HCompareIDAndBranch: public HTemplateControlInstruction<2, 2> {
2854 HCompareIDAndBranch(HValue* left, HValue* right, Token::Value token)
2856 ASSERT(Token::IsCompareOp(token));
2857 SetOperandAt(0, left);
2858 SetOperandAt(1, right);
2861 HValue* left() { return OperandAt(0); }
2862 HValue* right() { return OperandAt(1); }
2863 Token::Value token() const { return token_; }
2865 void SetInputRepresentation(Representation r);
2866 Representation GetInputRepresentation() const {
2867 return input_representation_;
2870 virtual Representation RequiredInputRepresentation(int index) {
2871 return input_representation_;
2873 virtual void PrintDataTo(StringStream* stream);
2875 DECLARE_CONCRETE_INSTRUCTION(CompareIDAndBranch)
2878 Representation input_representation_;
2879 Token::Value token_;
2883 class HCompareObjectEqAndBranch: public HTemplateControlInstruction<2, 2> {
2885 HCompareObjectEqAndBranch(HValue* left, HValue* right) {
2886 SetOperandAt(0, left);
2887 SetOperandAt(1, right);
2890 HValue* left() { return OperandAt(0); }
2891 HValue* right() { return OperandAt(1); }
2893 virtual void PrintDataTo(StringStream* stream);
2895 virtual Representation RequiredInputRepresentation(int index) {
2896 return Representation::Tagged();
2899 DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
2903 class HCompareConstantEqAndBranch: public HUnaryControlInstruction {
2905 HCompareConstantEqAndBranch(HValue* left, int right, Token::Value op)
2906 : HUnaryControlInstruction(left, NULL, NULL), op_(op), right_(right) {
2907 ASSERT(op == Token::EQ_STRICT);
2910 Token::Value op() const { return op_; }
2911 HValue* left() { return value(); }
2912 int right() const { return right_; }
2914 virtual Representation RequiredInputRepresentation(int index) {
2915 return Representation::Integer32();
2918 DECLARE_CONCRETE_INSTRUCTION(CompareConstantEqAndBranch);
2921 const Token::Value op_;
2926 class HIsNilAndBranch: public HUnaryControlInstruction {
2928 HIsNilAndBranch(HValue* value, EqualityKind kind, NilValue nil)
2929 : HUnaryControlInstruction(value, NULL, NULL), kind_(kind), nil_(nil) { }
2931 EqualityKind kind() const { return kind_; }
2932 NilValue nil() const { return nil_; }
2934 virtual void PrintDataTo(StringStream* stream);
2936 virtual Representation RequiredInputRepresentation(int index) {
2937 return Representation::Tagged();
2940 DECLARE_CONCRETE_INSTRUCTION(IsNilAndBranch)
2948 class HIsObjectAndBranch: public HUnaryControlInstruction {
2950 explicit HIsObjectAndBranch(HValue* value)
2951 : HUnaryControlInstruction(value, NULL, NULL) { }
2953 virtual Representation RequiredInputRepresentation(int index) {
2954 return Representation::Tagged();
2957 DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch)
2960 class HIsStringAndBranch: public HUnaryControlInstruction {
2962 explicit HIsStringAndBranch(HValue* value)
2963 : HUnaryControlInstruction(value, NULL, NULL) { }
2965 virtual Representation RequiredInputRepresentation(int index) {
2966 return Representation::Tagged();
2969 DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
2973 class HIsSmiAndBranch: public HUnaryControlInstruction {
2975 explicit HIsSmiAndBranch(HValue* value)
2976 : HUnaryControlInstruction(value, NULL, NULL) { }
2978 DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
2980 virtual Representation RequiredInputRepresentation(int index) {
2981 return Representation::Tagged();
2985 virtual bool DataEquals(HValue* other) { return true; }
2989 class HIsUndetectableAndBranch: public HUnaryControlInstruction {
2991 explicit HIsUndetectableAndBranch(HValue* value)
2992 : HUnaryControlInstruction(value, NULL, NULL) { }
2994 virtual Representation RequiredInputRepresentation(int index) {
2995 return Representation::Tagged();
2998 DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
3002 class HStringCompareAndBranch: public HTemplateControlInstruction<2, 3> {
3004 HStringCompareAndBranch(HValue* context,
3009 ASSERT(Token::IsCompareOp(token));
3010 SetOperandAt(0, context);
3011 SetOperandAt(1, left);
3012 SetOperandAt(2, right);
3013 set_representation(Representation::Tagged());
3016 HValue* context() { return OperandAt(0); }
3017 HValue* left() { return OperandAt(1); }
3018 HValue* right() { return OperandAt(2); }
3019 Token::Value token() const { return token_; }
3021 virtual void PrintDataTo(StringStream* stream);
3023 virtual Representation RequiredInputRepresentation(int index) {
3024 return Representation::Tagged();
3027 Representation GetInputRepresentation() const {
3028 return Representation::Tagged();
3031 DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
3034 Token::Value token_;
3038 class HIsConstructCallAndBranch: public HTemplateControlInstruction<2, 0> {
3040 virtual Representation RequiredInputRepresentation(int index) {
3041 return Representation::None();
3044 DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch)
3048 class HHasInstanceTypeAndBranch: public HUnaryControlInstruction {
3050 HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
3051 : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
3052 HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
3053 : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
3054 ASSERT(to == LAST_TYPE); // Others not implemented yet in backend.
3057 InstanceType from() { return from_; }
3058 InstanceType to() { return to_; }
3060 virtual void PrintDataTo(StringStream* stream);
3062 virtual Representation RequiredInputRepresentation(int index) {
3063 return Representation::Tagged();
3066 DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
3070 InstanceType to_; // Inclusive range, not all combinations work.
3074 class HHasCachedArrayIndexAndBranch: public HUnaryControlInstruction {
3076 explicit HHasCachedArrayIndexAndBranch(HValue* value)
3077 : HUnaryControlInstruction(value, NULL, NULL) { }
3079 virtual Representation RequiredInputRepresentation(int index) {
3080 return Representation::Tagged();
3083 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
3087 class HGetCachedArrayIndex: public HUnaryOperation {
3089 explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
3090 set_representation(Representation::Tagged());
3094 virtual Representation RequiredInputRepresentation(int index) {
3095 return Representation::Tagged();
3098 DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
3101 virtual bool DataEquals(HValue* other) { return true; }
3105 class HClassOfTestAndBranch: public HUnaryControlInstruction {
3107 HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
3108 : HUnaryControlInstruction(value, NULL, NULL),
3109 class_name_(class_name) { }
3111 DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
3113 virtual Representation RequiredInputRepresentation(int index) {
3114 return Representation::Tagged();
3117 virtual void PrintDataTo(StringStream* stream);
3119 Handle<String> class_name() const { return class_name_; }
3122 Handle<String> class_name_;
3126 class HTypeofIsAndBranch: public HUnaryControlInstruction {
3128 HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
3129 : HUnaryControlInstruction(value, NULL, NULL),
3130 type_literal_(type_literal) { }
3132 Handle<String> type_literal() { return type_literal_; }
3133 virtual void PrintDataTo(StringStream* stream);
3135 DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
3137 virtual Representation RequiredInputRepresentation(int index) {
3138 return Representation::Tagged();
3142 Handle<String> type_literal_;
3146 class HInstanceOf: public HBinaryOperation {
3148 HInstanceOf(HValue* context, HValue* left, HValue* right)
3149 : HBinaryOperation(context, left, right) {
3150 set_representation(Representation::Tagged());
3151 SetAllSideEffects();
3154 virtual Representation RequiredInputRepresentation(int index) {
3155 return Representation::Tagged();
3158 virtual HType CalculateInferredType();
3160 virtual void PrintDataTo(StringStream* stream);
3162 DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
3166 class HInstanceOfKnownGlobal: public HTemplateInstruction<2> {
3168 HInstanceOfKnownGlobal(HValue* context,
3170 Handle<JSFunction> right)
3171 : function_(right) {
3172 SetOperandAt(0, context);
3173 SetOperandAt(1, left);
3174 set_representation(Representation::Tagged());
3175 SetAllSideEffects();
3178 HValue* context() { return OperandAt(0); }
3179 HValue* left() { return OperandAt(1); }
3180 Handle<JSFunction> function() { return function_; }
3182 virtual Representation RequiredInputRepresentation(int index) {
3183 return Representation::Tagged();
3186 virtual HType CalculateInferredType();
3188 DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal)
3191 Handle<JSFunction> function_;
3195 class HPower: public HTemplateInstruction<2> {
3197 HPower(HValue* left, HValue* right) {
3198 SetOperandAt(0, left);
3199 SetOperandAt(1, right);
3200 set_representation(Representation::Double());
3202 SetGVNFlag(kChangesNewSpacePromotion);
3205 HValue* left() { return OperandAt(0); }
3206 HValue* right() { return OperandAt(1); }
3208 virtual Representation RequiredInputRepresentation(int index) {
3210 ? Representation::Double()
3211 : Representation::None();
3214 DECLARE_CONCRETE_INSTRUCTION(Power)
3217 virtual bool DataEquals(HValue* other) { return true; }
3221 class HRandom: public HTemplateInstruction<1> {
3223 explicit HRandom(HValue* global_object) {
3224 SetOperandAt(0, global_object);
3225 set_representation(Representation::Double());
3228 HValue* global_object() { return OperandAt(0); }
3230 virtual Representation RequiredInputRepresentation(int index) {
3231 return Representation::Tagged();
3234 DECLARE_CONCRETE_INSTRUCTION(Random)
3238 class HAdd: public HArithmeticBinaryOperation {
3240 HAdd(HValue* context, HValue* left, HValue* right)
3241 : HArithmeticBinaryOperation(context, left, right) {
3242 SetFlag(kCanOverflow);
3245 // Add is only commutative if two integer values are added and not if two
3246 // tagged values are added (because it might be a String concatenation).
3247 virtual bool IsCommutative() const {
3248 return !representation().IsTagged();
3251 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3253 static HInstruction* NewHAdd(Zone* zone,
3258 virtual HType CalculateInferredType();
3260 virtual HValue* Canonicalize();
3262 DECLARE_CONCRETE_INSTRUCTION(Add)
3265 virtual bool DataEquals(HValue* other) { return true; }
3267 virtual Range* InferRange(Zone* zone);
3271 class HSub: public HArithmeticBinaryOperation {
3273 HSub(HValue* context, HValue* left, HValue* right)
3274 : HArithmeticBinaryOperation(context, left, right) {
3275 SetFlag(kCanOverflow);
3278 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3280 virtual HValue* Canonicalize();
3282 static HInstruction* NewHSub(Zone* zone,
3287 DECLARE_CONCRETE_INSTRUCTION(Sub)
3290 virtual bool DataEquals(HValue* other) { return true; }
3292 virtual Range* InferRange(Zone* zone);
3296 class HMul: public HArithmeticBinaryOperation {
3298 HMul(HValue* context, HValue* left, HValue* right)
3299 : HArithmeticBinaryOperation(context, left, right) {
3300 SetFlag(kCanOverflow);
3303 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3305 // Only commutative if it is certain that not two objects are multiplicated.
3306 virtual bool IsCommutative() const {
3307 return !representation().IsTagged();
3310 static HInstruction* NewHMul(Zone* zone,
3315 DECLARE_CONCRETE_INSTRUCTION(Mul)
3318 virtual bool DataEquals(HValue* other) { return true; }
3320 virtual Range* InferRange(Zone* zone);
3324 class HMod: public HArithmeticBinaryOperation {
3326 HMod(HValue* context, HValue* left, HValue* right)
3327 : HArithmeticBinaryOperation(context, left, right) {
3328 SetFlag(kCanBeDivByZero);
3331 bool HasPowerOf2Divisor() {
3332 if (right()->IsConstant() &&
3333 HConstant::cast(right())->HasInteger32Value()) {
3334 int32_t value = HConstant::cast(right())->Integer32Value();
3335 return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
3341 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3343 static HInstruction* NewHMod(Zone* zone,
3348 DECLARE_CONCRETE_INSTRUCTION(Mod)
3351 virtual bool DataEquals(HValue* other) { return true; }
3353 virtual Range* InferRange(Zone* zone);
3357 class HDiv: public HArithmeticBinaryOperation {
3359 HDiv(HValue* context, HValue* left, HValue* right)
3360 : HArithmeticBinaryOperation(context, left, right) {
3361 SetFlag(kCanBeDivByZero);
3362 SetFlag(kCanOverflow);
3365 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3367 static HInstruction* NewHDiv(Zone* zone,
3372 DECLARE_CONCRETE_INSTRUCTION(Div)
3375 virtual bool DataEquals(HValue* other) { return true; }
3377 virtual Range* InferRange(Zone* zone);
3381 class HBitwise: public HBitwiseBinaryOperation {
3383 HBitwise(Token::Value op, HValue* context, HValue* left, HValue* right)
3384 : HBitwiseBinaryOperation(context, left, right), op_(op) {
3385 ASSERT(op == Token::BIT_AND ||
3386 op == Token::BIT_OR ||
3387 op == Token::BIT_XOR);
3390 Token::Value op() const { return op_; }
3392 virtual bool IsCommutative() const { return true; }
3394 virtual HValue* Canonicalize();
3396 static HInstruction* NewHBitwise(Zone* zone,
3402 virtual void PrintDataTo(StringStream* stream);
3404 DECLARE_CONCRETE_INSTRUCTION(Bitwise)
3407 virtual bool DataEquals(HValue* other) {
3408 return op() == HBitwise::cast(other)->op();
3411 virtual Range* InferRange(Zone* zone);
3418 class HShl: public HBitwiseBinaryOperation {
3420 HShl(HValue* context, HValue* left, HValue* right)
3421 : HBitwiseBinaryOperation(context, left, right) { }
3423 virtual Range* InferRange(Zone* zone);
3425 static HInstruction* NewHShl(Zone* zone,
3430 DECLARE_CONCRETE_INSTRUCTION(Shl)
3433 virtual bool DataEquals(HValue* other) { return true; }
3437 class HShr: public HBitwiseBinaryOperation {
3439 HShr(HValue* context, HValue* left, HValue* right)
3440 : HBitwiseBinaryOperation(context, left, right) { }
3442 virtual Range* InferRange(Zone* zone);
3444 static HInstruction* NewHShr(Zone* zone,
3449 DECLARE_CONCRETE_INSTRUCTION(Shr)
3452 virtual bool DataEquals(HValue* other) { return true; }
3456 class HSar: public HBitwiseBinaryOperation {
3458 HSar(HValue* context, HValue* left, HValue* right)
3459 : HBitwiseBinaryOperation(context, left, right) { }
3461 virtual Range* InferRange(Zone* zone);
3463 static HInstruction* NewHSar(Zone* zone,
3468 DECLARE_CONCRETE_INSTRUCTION(Sar)
3471 virtual bool DataEquals(HValue* other) { return true; }
3475 class HOsrEntry: public HTemplateInstruction<0> {
3477 explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
3478 SetGVNFlag(kChangesOsrEntries);
3481 int ast_id() const { return ast_id_; }
3483 virtual Representation RequiredInputRepresentation(int index) {
3484 return Representation::None();
3487 DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
3494 class HParameter: public HTemplateInstruction<0> {
3496 explicit HParameter(unsigned index) : index_(index) {
3497 set_representation(Representation::Tagged());
3500 unsigned index() const { return index_; }
3502 virtual void PrintDataTo(StringStream* stream);
3504 virtual Representation RequiredInputRepresentation(int index) {
3505 return Representation::None();
3508 DECLARE_CONCRETE_INSTRUCTION(Parameter)
3515 class HCallStub: public HUnaryCall {
3517 HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
3518 : HUnaryCall(context, argument_count),
3519 major_key_(major_key),
3520 transcendental_type_(TranscendentalCache::kNumberOfCaches) {
3523 CodeStub::Major major_key() { return major_key_; }
3525 HValue* context() { return value(); }
3527 void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
3528 transcendental_type_ = transcendental_type;
3530 TranscendentalCache::Type transcendental_type() {
3531 return transcendental_type_;
3534 virtual void PrintDataTo(StringStream* stream);
3536 virtual Representation RequiredInputRepresentation(int index) {
3537 return Representation::Tagged();
3540 DECLARE_CONCRETE_INSTRUCTION(CallStub)
3543 CodeStub::Major major_key_;
3544 TranscendentalCache::Type transcendental_type_;
3548 class HUnknownOSRValue: public HTemplateInstruction<0> {
3551 : incoming_value_(NULL) {
3552 set_representation(Representation::Tagged());
3555 virtual Representation RequiredInputRepresentation(int index) {
3556 return Representation::None();
3559 void set_incoming_value(HPhi* value) {
3560 incoming_value_ = value;
3563 HPhi* incoming_value() {
3564 return incoming_value_;
3567 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
3570 HPhi* incoming_value_;
3574 class HLoadGlobalCell: public HTemplateInstruction<0> {
3576 HLoadGlobalCell(Handle<JSGlobalPropertyCell> cell, PropertyDetails details)
3577 : cell_(cell), details_(details) {
3578 set_representation(Representation::Tagged());
3580 SetGVNFlag(kDependsOnGlobalVars);
3583 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
3584 bool RequiresHoleCheck();
3586 virtual void PrintDataTo(StringStream* stream);
3588 virtual intptr_t Hashcode() {
3589 ASSERT(!HEAP->allow_allocation(false));
3590 return reinterpret_cast<intptr_t>(*cell_);
3593 virtual Representation RequiredInputRepresentation(int index) {
3594 return Representation::None();
3597 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell)
3600 virtual bool DataEquals(HValue* other) {
3601 HLoadGlobalCell* b = HLoadGlobalCell::cast(other);
3602 return cell_.is_identical_to(b->cell());
3606 Handle<JSGlobalPropertyCell> cell_;
3607 PropertyDetails details_;
3611 class HLoadGlobalGeneric: public HTemplateInstruction<2> {
3613 HLoadGlobalGeneric(HValue* context,
3614 HValue* global_object,
3615 Handle<Object> name,
3618 for_typeof_(for_typeof) {
3619 SetOperandAt(0, context);
3620 SetOperandAt(1, global_object);
3621 set_representation(Representation::Tagged());
3622 SetAllSideEffects();
3625 HValue* context() { return OperandAt(0); }
3626 HValue* global_object() { return OperandAt(1); }
3627 Handle<Object> name() const { return name_; }
3628 bool for_typeof() const { return for_typeof_; }
3630 virtual void PrintDataTo(StringStream* stream);
3632 virtual Representation RequiredInputRepresentation(int index) {
3633 return Representation::Tagged();
3636 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
3639 Handle<Object> name_;
3644 inline bool StoringValueNeedsWriteBarrier(HValue* value) {
3645 return !value->type().IsBoolean()
3646 && !value->type().IsSmi()
3647 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
3651 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
3652 HValue* new_space_dominator) {
3653 return !object->IsAllocateObject() || (object != new_space_dominator);
3657 class HStoreGlobalCell: public HUnaryOperation {
3659 HStoreGlobalCell(HValue* value,
3660 Handle<JSGlobalPropertyCell> cell,
3661 PropertyDetails details)
3662 : HUnaryOperation(value),
3665 SetGVNFlag(kChangesGlobalVars);
3668 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
3669 bool RequiresHoleCheck() {
3670 return !details_.IsDontDelete() || details_.IsReadOnly();
3672 bool NeedsWriteBarrier() {
3673 return StoringValueNeedsWriteBarrier(value());
3676 virtual Representation RequiredInputRepresentation(int index) {
3677 return Representation::Tagged();
3679 virtual void PrintDataTo(StringStream* stream);
3681 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell)
3684 Handle<JSGlobalPropertyCell> cell_;
3685 PropertyDetails details_;
3689 class HStoreGlobalGeneric: public HTemplateInstruction<3> {
3691 HStoreGlobalGeneric(HValue* context,
3692 HValue* global_object,
3693 Handle<Object> name,
3695 StrictModeFlag strict_mode_flag)
3697 strict_mode_flag_(strict_mode_flag) {
3698 SetOperandAt(0, context);
3699 SetOperandAt(1, global_object);
3700 SetOperandAt(2, value);
3701 set_representation(Representation::Tagged());
3702 SetAllSideEffects();
3705 HValue* context() { return OperandAt(0); }
3706 HValue* global_object() { return OperandAt(1); }
3707 Handle<Object> name() const { return name_; }
3708 HValue* value() { return OperandAt(2); }
3709 StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
3711 virtual void PrintDataTo(StringStream* stream);
3713 virtual Representation RequiredInputRepresentation(int index) {
3714 return Representation::Tagged();
3717 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric)
3720 Handle<Object> name_;
3721 StrictModeFlag strict_mode_flag_;
3725 class HLoadContextSlot: public HUnaryOperation {
3728 // Perform a normal load of the context slot without checking its value.
3730 // Load and check the value of the context slot. Deoptimize if it's the
3731 // hole value. This is used for checking for loading of uninitialized
3732 // harmony bindings where we deoptimize into full-codegen generated code
3733 // which will subsequently throw a reference error.
3735 // Load and check the value of the context slot. Return undefined if it's
3736 // the hole value. This is used for non-harmony const assignments
3737 kCheckReturnUndefined
3740 HLoadContextSlot(HValue* context, Variable* var)
3741 : HUnaryOperation(context), slot_index_(var->index()) {
3742 ASSERT(var->IsContextSlot());
3743 switch (var->mode()) {
3746 mode_ = kCheckDeoptimize;
3749 mode_ = kCheckReturnUndefined;
3754 set_representation(Representation::Tagged());
3756 SetGVNFlag(kDependsOnContextSlots);
3759 int slot_index() const { return slot_index_; }
3760 Mode mode() const { return mode_; }
3762 bool DeoptimizesOnHole() {
3763 return mode_ == kCheckDeoptimize;
3766 bool RequiresHoleCheck() {
3767 return mode_ != kNoCheck;
3770 virtual Representation RequiredInputRepresentation(int index) {
3771 return Representation::Tagged();
3774 virtual void PrintDataTo(StringStream* stream);
3776 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
3779 virtual bool DataEquals(HValue* other) {
3780 HLoadContextSlot* b = HLoadContextSlot::cast(other);
3781 return (slot_index() == b->slot_index());
3790 class HStoreContextSlot: public HTemplateInstruction<2> {
3793 // Perform a normal store to the context slot without checking its previous
3796 // Check the previous value of the context slot and deoptimize if it's the
3797 // hole value. This is used for checking for assignments to uninitialized
3798 // harmony bindings where we deoptimize into full-codegen generated code
3799 // which will subsequently throw a reference error.
3801 // Check the previous value and ignore assignment if it isn't a hole value
3802 kCheckIgnoreAssignment
3805 HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
3806 : slot_index_(slot_index), mode_(mode) {
3807 SetOperandAt(0, context);
3808 SetOperandAt(1, value);
3809 SetGVNFlag(kChangesContextSlots);
3812 HValue* context() { return OperandAt(0); }
3813 HValue* value() { return OperandAt(1); }
3814 int slot_index() const { return slot_index_; }
3815 Mode mode() const { return mode_; }
3817 bool NeedsWriteBarrier() {
3818 return StoringValueNeedsWriteBarrier(value());
3821 bool DeoptimizesOnHole() {
3822 return mode_ == kCheckDeoptimize;
3825 bool RequiresHoleCheck() {
3826 return mode_ != kNoCheck;
3829 virtual Representation RequiredInputRepresentation(int index) {
3830 return Representation::Tagged();
3833 virtual void PrintDataTo(StringStream* stream);
3835 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
3843 class HLoadNamedField: public HUnaryOperation {
3845 HLoadNamedField(HValue* object, bool is_in_object, int offset)
3846 : HUnaryOperation(object),
3847 is_in_object_(is_in_object),
3849 set_representation(Representation::Tagged());
3851 SetGVNFlag(kDependsOnMaps);
3853 SetGVNFlag(kDependsOnInobjectFields);
3855 SetGVNFlag(kDependsOnBackingStoreFields);
3859 HValue* object() { return OperandAt(0); }
3860 bool is_in_object() const { return is_in_object_; }
3861 int offset() const { return offset_; }
3863 virtual Representation RequiredInputRepresentation(int index) {
3864 return Representation::Tagged();
3866 virtual void PrintDataTo(StringStream* stream);
3868 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
3871 virtual bool DataEquals(HValue* other) {
3872 HLoadNamedField* b = HLoadNamedField::cast(other);
3873 return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
3882 class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
3884 HLoadNamedFieldPolymorphic(HValue* context,
3886 SmallMapList* types,
3887 Handle<String> name);
3889 HValue* context() { return OperandAt(0); }
3890 HValue* object() { return OperandAt(1); }
3891 SmallMapList* types() { return &types_; }
3892 Handle<String> name() { return name_; }
3893 bool need_generic() { return need_generic_; }
3895 virtual Representation RequiredInputRepresentation(int index) {
3896 return Representation::Tagged();
3899 virtual void PrintDataTo(StringStream* stream);
3901 DECLARE_CONCRETE_INSTRUCTION(LoadNamedFieldPolymorphic)
3903 static const int kMaxLoadPolymorphism = 4;
3906 virtual bool DataEquals(HValue* value);
3909 SmallMapList types_;
3910 Handle<String> name_;
3916 class HLoadNamedGeneric: public HTemplateInstruction<2> {
3918 HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
3920 SetOperandAt(0, context);
3921 SetOperandAt(1, object);
3922 set_representation(Representation::Tagged());
3923 SetAllSideEffects();
3926 HValue* context() { return OperandAt(0); }
3927 HValue* object() { return OperandAt(1); }
3928 Handle<Object> name() const { return name_; }
3930 virtual Representation RequiredInputRepresentation(int index) {
3931 return Representation::Tagged();
3934 virtual void PrintDataTo(StringStream* stream);
3936 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
3939 Handle<Object> name_;
3943 class HLoadFunctionPrototype: public HUnaryOperation {
3945 explicit HLoadFunctionPrototype(HValue* function)
3946 : HUnaryOperation(function) {
3947 set_representation(Representation::Tagged());
3949 SetGVNFlag(kDependsOnCalls);
3952 HValue* function() { return OperandAt(0); }
3954 virtual Representation RequiredInputRepresentation(int index) {
3955 return Representation::Tagged();
3958 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
3961 virtual bool DataEquals(HValue* other) { return true; }
3964 class ArrayInstructionInterface {
3966 virtual HValue* GetKey() = 0;
3967 virtual void SetKey(HValue* key) = 0;
3968 virtual void SetIndexOffset(uint32_t index_offset) = 0;
3969 virtual bool IsDehoisted() = 0;
3970 virtual void SetDehoisted(bool is_dehoisted) = 0;
3971 virtual ~ArrayInstructionInterface() { };
3974 class HLoadKeyedFastElement
3975 : public HTemplateInstruction<2>, public ArrayInstructionInterface {
3977 enum HoleCheckMode { PERFORM_HOLE_CHECK, OMIT_HOLE_CHECK };
3979 HLoadKeyedFastElement(HValue* obj,
3981 HoleCheckMode hole_check_mode = PERFORM_HOLE_CHECK)
3982 : hole_check_mode_(hole_check_mode),
3984 is_dehoisted_(false) {
3985 SetOperandAt(0, obj);
3986 SetOperandAt(1, key);
3987 set_representation(Representation::Tagged());
3988 SetGVNFlag(kDependsOnArrayElements);
3992 HValue* object() { return OperandAt(0); }
3993 HValue* key() { return OperandAt(1); }
3994 uint32_t index_offset() { return index_offset_; }
3995 void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
3996 HValue* GetKey() { return key(); }
3997 void SetKey(HValue* key) { SetOperandAt(1, key); }
3998 bool IsDehoisted() { return is_dehoisted_; }
3999 void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
4001 virtual Representation RequiredInputRepresentation(int index) {
4002 // The key is supposed to be Integer32.
4004 ? Representation::Tagged()
4005 : Representation::Integer32();
4008 virtual void PrintDataTo(StringStream* stream);
4010 bool RequiresHoleCheck();
4012 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement)
4015 virtual bool DataEquals(HValue* other) {
4016 if (!other->IsLoadKeyedFastElement()) return false;
4017 HLoadKeyedFastElement* other_load = HLoadKeyedFastElement::cast(other);
4018 if (is_dehoisted_ && index_offset_ != other_load->index_offset_)
4020 return hole_check_mode_ == other_load->hole_check_mode_;
4024 HoleCheckMode hole_check_mode_;
4025 uint32_t index_offset_;
4030 class HLoadKeyedFastDoubleElement
4031 : public HTemplateInstruction<2>, public ArrayInstructionInterface {
4033 HLoadKeyedFastDoubleElement(HValue* elements, HValue* key)
4034 : index_offset_(0), is_dehoisted_(false) {
4035 SetOperandAt(0, elements);
4036 SetOperandAt(1, key);
4037 set_representation(Representation::Double());
4038 SetGVNFlag(kDependsOnDoubleArrayElements);
4042 HValue* elements() { return OperandAt(0); }
4043 HValue* key() { return OperandAt(1); }
4044 uint32_t index_offset() { return index_offset_; }
4045 void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
4046 HValue* GetKey() { return key(); }
4047 void SetKey(HValue* key) { SetOperandAt(1, key); }
4048 bool IsDehoisted() { return is_dehoisted_; }
4049 void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
4051 virtual Representation RequiredInputRepresentation(int index) {
4052 // The key is supposed to be Integer32.
4054 ? Representation::Tagged()
4055 : Representation::Integer32();
4058 virtual void PrintDataTo(StringStream* stream);
4060 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement)
4063 virtual bool DataEquals(HValue* other) { return true; }
4066 uint32_t index_offset_;
4071 class HLoadKeyedSpecializedArrayElement
4072 : public HTemplateInstruction<2>, public ArrayInstructionInterface {
4074 HLoadKeyedSpecializedArrayElement(HValue* external_elements,
4076 ElementsKind elements_kind)
4077 : elements_kind_(elements_kind),
4079 is_dehoisted_(false) {
4080 SetOperandAt(0, external_elements);
4081 SetOperandAt(1, key);
4082 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
4083 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
4084 set_representation(Representation::Double());
4086 set_representation(Representation::Integer32());
4088 SetGVNFlag(kDependsOnSpecializedArrayElements);
4089 // Native code could change the specialized array.
4090 SetGVNFlag(kDependsOnCalls);
4094 virtual void PrintDataTo(StringStream* stream);
4096 virtual Representation RequiredInputRepresentation(int index) {
4097 // The key is supposed to be Integer32, but the base pointer
4098 // for the element load is a naked pointer.
4100 ? Representation::External()
4101 : Representation::Integer32();
4104 HValue* external_pointer() { return OperandAt(0); }
4105 HValue* key() { return OperandAt(1); }
4106 ElementsKind elements_kind() const { return elements_kind_; }
4107 uint32_t index_offset() { return index_offset_; }
4108 void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
4109 HValue* GetKey() { return key(); }
4110 void SetKey(HValue* key) { SetOperandAt(1, key); }
4111 bool IsDehoisted() { return is_dehoisted_; }
4112 void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
4114 virtual Range* InferRange(Zone* zone);
4116 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement)
4119 virtual bool DataEquals(HValue* other) {
4120 if (!other->IsLoadKeyedSpecializedArrayElement()) return false;
4121 HLoadKeyedSpecializedArrayElement* cast_other =
4122 HLoadKeyedSpecializedArrayElement::cast(other);
4123 return elements_kind_ == cast_other->elements_kind();
4127 ElementsKind elements_kind_;
4128 uint32_t index_offset_;
4133 class HLoadKeyedGeneric: public HTemplateInstruction<3> {
4135 HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key) {
4136 set_representation(Representation::Tagged());
4137 SetOperandAt(0, obj);
4138 SetOperandAt(1, key);
4139 SetOperandAt(2, context);
4140 SetAllSideEffects();
4143 HValue* object() { return OperandAt(0); }
4144 HValue* key() { return OperandAt(1); }
4145 HValue* context() { return OperandAt(2); }
4147 virtual void PrintDataTo(StringStream* stream);
4149 virtual Representation RequiredInputRepresentation(int index) {
4150 return Representation::Tagged();
4153 virtual HValue* Canonicalize();
4155 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
4159 class HStoreNamedField: public HTemplateInstruction<2> {
4161 HStoreNamedField(HValue* obj,
4162 Handle<String> name,
4167 is_in_object_(in_object),
4169 new_space_dominator_(NULL) {
4170 SetOperandAt(0, obj);
4171 SetOperandAt(1, val);
4172 SetFlag(kTrackSideEffectDominators);
4173 SetGVNFlag(kDependsOnNewSpacePromotion);
4174 if (is_in_object_) {
4175 SetGVNFlag(kChangesInobjectFields);
4177 SetGVNFlag(kChangesBackingStoreFields);
4181 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
4183 virtual Representation RequiredInputRepresentation(int index) {
4184 return Representation::Tagged();
4186 virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) {
4187 ASSERT(side_effect == kChangesNewSpacePromotion);
4188 new_space_dominator_ = dominator;
4190 virtual void PrintDataTo(StringStream* stream);
4192 HValue* object() { return OperandAt(0); }
4193 HValue* value() { return OperandAt(1); }
4195 Handle<String> name() const { return name_; }
4196 bool is_in_object() const { return is_in_object_; }
4197 int offset() const { return offset_; }
4198 Handle<Map> transition() const { return transition_; }
4199 void set_transition(Handle<Map> map) { transition_ = map; }
4200 HValue* new_space_dominator() const { return new_space_dominator_; }
4202 bool NeedsWriteBarrier() {
4203 return StoringValueNeedsWriteBarrier(value()) &&
4204 ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
4208 Handle<String> name_;
4211 Handle<Map> transition_;
4212 HValue* new_space_dominator_;
4216 class HStoreNamedGeneric: public HTemplateInstruction<3> {
4218 HStoreNamedGeneric(HValue* context,
4220 Handle<String> name,
4222 StrictModeFlag strict_mode_flag)
4224 strict_mode_flag_(strict_mode_flag) {
4225 SetOperandAt(0, object);
4226 SetOperandAt(1, value);
4227 SetOperandAt(2, context);
4228 SetAllSideEffects();
4231 HValue* object() { return OperandAt(0); }
4232 HValue* value() { return OperandAt(1); }
4233 HValue* context() { return OperandAt(2); }
4234 Handle<String> name() { return name_; }
4235 StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
4237 virtual void PrintDataTo(StringStream* stream);
4239 virtual Representation RequiredInputRepresentation(int index) {
4240 return Representation::Tagged();
4243 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
4246 Handle<String> name_;
4247 StrictModeFlag strict_mode_flag_;
4251 class HStoreKeyedFastElement
4252 : public HTemplateInstruction<3>, public ArrayInstructionInterface {
4254 HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val,
4255 ElementsKind elements_kind = FAST_ELEMENTS)
4256 : elements_kind_(elements_kind), index_offset_(0), is_dehoisted_(false) {
4257 SetOperandAt(0, obj);
4258 SetOperandAt(1, key);
4259 SetOperandAt(2, val);
4260 SetGVNFlag(kChangesArrayElements);
4263 virtual Representation RequiredInputRepresentation(int index) {
4264 // The key is supposed to be Integer32.
4266 ? Representation::Integer32()
4267 : Representation::Tagged();
4270 HValue* object() { return OperandAt(0); }
4271 HValue* key() { return OperandAt(1); }
4272 HValue* value() { return OperandAt(2); }
4273 bool value_is_smi() {
4274 return elements_kind_ == FAST_SMI_ONLY_ELEMENTS;
4276 uint32_t index_offset() { return index_offset_; }
4277 void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
4278 HValue* GetKey() { return key(); }
4279 void SetKey(HValue* key) { SetOperandAt(1, key); }
4280 bool IsDehoisted() { return is_dehoisted_; }
4281 void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
4283 bool NeedsWriteBarrier() {
4284 if (value_is_smi()) {
4287 return StoringValueNeedsWriteBarrier(value());
4291 virtual void PrintDataTo(StringStream* stream);
4293 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement)
4296 ElementsKind elements_kind_;
4297 uint32_t index_offset_;
4302 class HStoreKeyedFastDoubleElement
4303 : public HTemplateInstruction<3>, public ArrayInstructionInterface {
4305 HStoreKeyedFastDoubleElement(HValue* elements,
4308 : index_offset_(0), is_dehoisted_(false) {
4309 SetOperandAt(0, elements);
4310 SetOperandAt(1, key);
4311 SetOperandAt(2, val);
4312 SetGVNFlag(kChangesDoubleArrayElements);
4315 virtual Representation RequiredInputRepresentation(int index) {
4317 return Representation::Integer32();
4318 } else if (index == 2) {
4319 return Representation::Double();
4321 return Representation::Tagged();
4325 HValue* elements() { return OperandAt(0); }
4326 HValue* key() { return OperandAt(1); }
4327 HValue* value() { return OperandAt(2); }
4328 uint32_t index_offset() { return index_offset_; }
4329 void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
4330 HValue* GetKey() { return key(); }
4331 void SetKey(HValue* key) { SetOperandAt(1, key); }
4332 bool IsDehoisted() { return is_dehoisted_; }
4333 void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
4335 bool NeedsWriteBarrier() {
4336 return StoringValueNeedsWriteBarrier(value());
4339 bool NeedsCanonicalization();
4341 virtual void PrintDataTo(StringStream* stream);
4343 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement)
4346 uint32_t index_offset_;
4351 class HStoreKeyedSpecializedArrayElement
4352 : public HTemplateInstruction<3>, public ArrayInstructionInterface {
4354 HStoreKeyedSpecializedArrayElement(HValue* external_elements,
4357 ElementsKind elements_kind)
4358 : elements_kind_(elements_kind), index_offset_(0), is_dehoisted_(false) {
4359 SetGVNFlag(kChangesSpecializedArrayElements);
4360 SetOperandAt(0, external_elements);
4361 SetOperandAt(1, key);
4362 SetOperandAt(2, val);
4365 virtual void PrintDataTo(StringStream* stream);
4367 virtual Representation RequiredInputRepresentation(int index) {
4369 return Representation::External();
4371 bool float_or_double_elements =
4372 elements_kind() == EXTERNAL_FLOAT_ELEMENTS ||
4373 elements_kind() == EXTERNAL_DOUBLE_ELEMENTS;
4374 if (index == 2 && float_or_double_elements) {
4375 return Representation::Double();
4377 return Representation::Integer32();
4382 HValue* external_pointer() { return OperandAt(0); }
4383 HValue* key() { return OperandAt(1); }
4384 HValue* value() { return OperandAt(2); }
4385 ElementsKind elements_kind() const { return elements_kind_; }
4386 uint32_t index_offset() { return index_offset_; }
4387 void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
4388 HValue* GetKey() { return key(); }
4389 void SetKey(HValue* key) { SetOperandAt(1, key); }
4390 bool IsDehoisted() { return is_dehoisted_; }
4391 void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
4393 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement)
4396 ElementsKind elements_kind_;
4397 uint32_t index_offset_;
4402 class HStoreKeyedGeneric: public HTemplateInstruction<4> {
4404 HStoreKeyedGeneric(HValue* context,
4408 StrictModeFlag strict_mode_flag)
4409 : strict_mode_flag_(strict_mode_flag) {
4410 SetOperandAt(0, object);
4411 SetOperandAt(1, key);
4412 SetOperandAt(2, value);
4413 SetOperandAt(3, context);
4414 SetAllSideEffects();
4417 HValue* object() { return OperandAt(0); }
4418 HValue* key() { return OperandAt(1); }
4419 HValue* value() { return OperandAt(2); }
4420 HValue* context() { return OperandAt(3); }
4421 StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
4423 virtual Representation RequiredInputRepresentation(int index) {
4424 return Representation::Tagged();
4427 virtual void PrintDataTo(StringStream* stream);
4429 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
4432 StrictModeFlag strict_mode_flag_;
4436 class HTransitionElementsKind: public HTemplateInstruction<1> {
4438 HTransitionElementsKind(HValue* object,
4439 Handle<Map> original_map,
4440 Handle<Map> transitioned_map)
4441 : original_map_(original_map),
4442 transitioned_map_(transitioned_map) {
4443 SetOperandAt(0, object);
4445 SetGVNFlag(kChangesElementsKind);
4446 SetGVNFlag(kChangesElementsPointer);
4447 SetGVNFlag(kChangesNewSpacePromotion);
4448 set_representation(Representation::Tagged());
4451 virtual Representation RequiredInputRepresentation(int index) {
4452 return Representation::Tagged();
4455 HValue* object() { return OperandAt(0); }
4456 Handle<Map> original_map() { return original_map_; }
4457 Handle<Map> transitioned_map() { return transitioned_map_; }
4459 virtual void PrintDataTo(StringStream* stream);
4461 DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
4464 virtual bool DataEquals(HValue* other) {
4465 HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
4466 return original_map_.is_identical_to(instr->original_map()) &&
4467 transitioned_map_.is_identical_to(instr->transitioned_map());
4471 Handle<Map> original_map_;
4472 Handle<Map> transitioned_map_;
4476 class HStringAdd: public HBinaryOperation {
4478 HStringAdd(HValue* context, HValue* left, HValue* right)
4479 : HBinaryOperation(context, left, right) {
4480 set_representation(Representation::Tagged());
4482 SetGVNFlag(kDependsOnMaps);
4485 virtual Representation RequiredInputRepresentation(int index) {
4486 return Representation::Tagged();
4489 virtual HType CalculateInferredType() {
4490 return HType::String();
4493 DECLARE_CONCRETE_INSTRUCTION(StringAdd)
4496 virtual bool DataEquals(HValue* other) { return true; }
4500 class HStringCharCodeAt: public HTemplateInstruction<3> {
4502 HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
4503 SetOperandAt(0, context);
4504 SetOperandAt(1, string);
4505 SetOperandAt(2, index);
4506 set_representation(Representation::Integer32());
4508 SetGVNFlag(kDependsOnMaps);
4509 SetGVNFlag(kChangesNewSpacePromotion);
4512 virtual Representation RequiredInputRepresentation(int index) {
4513 // The index is supposed to be Integer32.
4515 ? Representation::Integer32()
4516 : Representation::Tagged();
4519 HValue* context() { return OperandAt(0); }
4520 HValue* string() { return OperandAt(1); }
4521 HValue* index() { return OperandAt(2); }
4523 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
4526 virtual bool DataEquals(HValue* other) { return true; }
4528 virtual Range* InferRange(Zone* zone) {
4529 return new(zone) Range(0, String::kMaxUtf16CodeUnit);
4534 class HStringCharFromCode: public HTemplateInstruction<2> {
4536 HStringCharFromCode(HValue* context, HValue* char_code) {
4537 SetOperandAt(0, context);
4538 SetOperandAt(1, char_code);
4539 set_representation(Representation::Tagged());
4541 SetGVNFlag(kChangesNewSpacePromotion);
4544 virtual Representation RequiredInputRepresentation(int index) {
4546 ? Representation::Tagged()
4547 : Representation::Integer32();
4549 virtual HType CalculateInferredType();
4551 HValue* context() { return OperandAt(0); }
4552 HValue* value() { return OperandAt(1); }
4554 virtual bool DataEquals(HValue* other) { return true; }
4556 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
4560 class HStringLength: public HUnaryOperation {
4562 explicit HStringLength(HValue* string) : HUnaryOperation(string) {
4563 set_representation(Representation::Tagged());
4565 SetGVNFlag(kDependsOnMaps);
4568 virtual Representation RequiredInputRepresentation(int index) {
4569 return Representation::Tagged();
4572 virtual HType CalculateInferredType() {
4573 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
4574 return HType::Smi();
4577 DECLARE_CONCRETE_INSTRUCTION(StringLength)
4580 virtual bool DataEquals(HValue* other) { return true; }
4582 virtual Range* InferRange(Zone* zone) {
4583 return new(zone) Range(0, String::kMaxLength);
4588 class HAllocateObject: public HTemplateInstruction<1> {
4590 HAllocateObject(HValue* context, Handle<JSFunction> constructor)
4591 : constructor_(constructor) {
4592 SetOperandAt(0, context);
4593 set_representation(Representation::Tagged());
4594 SetGVNFlag(kChangesNewSpacePromotion);
4597 // Maximum instance size for which allocations will be inlined.
4598 static const int kMaxSize = 64 * kPointerSize;
4600 HValue* context() { return OperandAt(0); }
4601 Handle<JSFunction> constructor() { return constructor_; }
4603 virtual Representation RequiredInputRepresentation(int index) {
4604 return Representation::Tagged();
4606 virtual HType CalculateInferredType();
4608 DECLARE_CONCRETE_INSTRUCTION(AllocateObject)
4611 Handle<JSFunction> constructor_;
4616 class HMaterializedLiteral: public HTemplateInstruction<V> {
4618 HMaterializedLiteral<V>(int index, int depth)
4619 : literal_index_(index), depth_(depth) {
4620 this->set_representation(Representation::Tagged());
4623 int literal_index() const { return literal_index_; }
4624 int depth() const { return depth_; }
4632 class HFastLiteral: public HMaterializedLiteral<1> {
4634 HFastLiteral(HValue* context,
4635 Handle<JSObject> boilerplate,
4639 : HMaterializedLiteral<1>(literal_index, depth),
4640 boilerplate_(boilerplate),
4641 total_size_(total_size) {
4642 SetOperandAt(0, context);
4643 SetGVNFlag(kChangesNewSpacePromotion);
4646 // Maximum depth and total number of elements and properties for literal
4647 // graphs to be considered for fast deep-copying.
4648 static const int kMaxLiteralDepth = 3;
4649 static const int kMaxLiteralProperties = 8;
4651 HValue* context() { return OperandAt(0); }
4652 Handle<JSObject> boilerplate() const { return boilerplate_; }
4653 int total_size() const { return total_size_; }
4655 virtual Representation RequiredInputRepresentation(int index) {
4656 return Representation::Tagged();
4658 virtual HType CalculateInferredType();
4660 DECLARE_CONCRETE_INSTRUCTION(FastLiteral)
4663 Handle<JSObject> boilerplate_;
4668 class HArrayLiteral: public HMaterializedLiteral<1> {
4670 HArrayLiteral(HValue* context,
4671 Handle<HeapObject> boilerplate_object,
4675 : HMaterializedLiteral<1>(literal_index, depth),
4677 boilerplate_object_(boilerplate_object) {
4678 SetOperandAt(0, context);
4679 SetGVNFlag(kChangesNewSpacePromotion);
4682 HValue* context() { return OperandAt(0); }
4683 ElementsKind boilerplate_elements_kind() const {
4684 if (!boilerplate_object_->IsJSObject()) {
4685 return FAST_ELEMENTS;
4687 return Handle<JSObject>::cast(boilerplate_object_)->GetElementsKind();
4689 Handle<HeapObject> boilerplate_object() const { return boilerplate_object_; }
4690 int length() const { return length_; }
4692 bool IsCopyOnWrite() const;
4694 virtual Representation RequiredInputRepresentation(int index) {
4695 return Representation::Tagged();
4697 virtual HType CalculateInferredType();
4699 DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral)
4703 Handle<HeapObject> boilerplate_object_;
4707 class HObjectLiteral: public HMaterializedLiteral<1> {
4709 HObjectLiteral(HValue* context,
4710 Handle<FixedArray> constant_properties,
4715 : HMaterializedLiteral<1>(literal_index, depth),
4716 constant_properties_(constant_properties),
4717 fast_elements_(fast_elements),
4718 has_function_(has_function) {
4719 SetOperandAt(0, context);
4720 SetGVNFlag(kChangesNewSpacePromotion);
4723 HValue* context() { return OperandAt(0); }
4724 Handle<FixedArray> constant_properties() const {
4725 return constant_properties_;
4727 bool fast_elements() const { return fast_elements_; }
4728 bool has_function() const { return has_function_; }
4730 virtual Representation RequiredInputRepresentation(int index) {
4731 return Representation::Tagged();
4733 virtual HType CalculateInferredType();
4735 DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral)
4738 Handle<FixedArray> constant_properties_;
4739 bool fast_elements_;
4744 class HRegExpLiteral: public HMaterializedLiteral<1> {
4746 HRegExpLiteral(HValue* context,
4747 Handle<String> pattern,
4748 Handle<String> flags,
4750 : HMaterializedLiteral<1>(literal_index, 0),
4753 SetOperandAt(0, context);
4754 SetAllSideEffects();
4757 HValue* context() { return OperandAt(0); }
4758 Handle<String> pattern() { return pattern_; }
4759 Handle<String> flags() { return flags_; }
4761 virtual Representation RequiredInputRepresentation(int index) {
4762 return Representation::Tagged();
4764 virtual HType CalculateInferredType();
4766 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
4769 Handle<String> pattern_;
4770 Handle<String> flags_;
4774 class HFunctionLiteral: public HTemplateInstruction<1> {
4776 HFunctionLiteral(HValue* context,
4777 Handle<SharedFunctionInfo> shared,
4779 : shared_info_(shared), pretenure_(pretenure) {
4780 SetOperandAt(0, context);
4781 set_representation(Representation::Tagged());
4782 SetGVNFlag(kChangesNewSpacePromotion);
4785 HValue* context() { return OperandAt(0); }
4787 virtual Representation RequiredInputRepresentation(int index) {
4788 return Representation::Tagged();
4790 virtual HType CalculateInferredType();
4792 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral)
4794 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
4795 bool pretenure() const { return pretenure_; }
4798 Handle<SharedFunctionInfo> shared_info_;
4803 class HTypeof: public HTemplateInstruction<2> {
4805 explicit HTypeof(HValue* context, HValue* value) {
4806 SetOperandAt(0, context);
4807 SetOperandAt(1, value);
4808 set_representation(Representation::Tagged());
4811 HValue* context() { return OperandAt(0); }
4812 HValue* value() { return OperandAt(1); }
4814 virtual HValue* Canonicalize();
4815 virtual void PrintDataTo(StringStream* stream);
4817 virtual Representation RequiredInputRepresentation(int index) {
4818 return Representation::Tagged();
4821 DECLARE_CONCRETE_INSTRUCTION(Typeof)
4825 class HToFastProperties: public HUnaryOperation {
4827 explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
4828 // This instruction is not marked as having side effects, but
4829 // changes the map of the input operand. Use it only when creating
4831 ASSERT(value->IsObjectLiteral() || value->IsFastLiteral());
4832 set_representation(Representation::Tagged());
4835 virtual Representation RequiredInputRepresentation(int index) {
4836 return Representation::Tagged();
4839 DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
4843 class HValueOf: public HUnaryOperation {
4845 explicit HValueOf(HValue* value) : HUnaryOperation(value) {
4846 set_representation(Representation::Tagged());
4849 virtual Representation RequiredInputRepresentation(int index) {
4850 return Representation::Tagged();
4853 DECLARE_CONCRETE_INSTRUCTION(ValueOf)
4857 class HDateField: public HUnaryOperation {
4859 HDateField(HValue* date, Smi* index)
4860 : HUnaryOperation(date), index_(index) {
4861 set_representation(Representation::Tagged());
4864 Smi* index() const { return index_; }
4866 virtual Representation RequiredInputRepresentation(int index) {
4867 return Representation::Tagged();
4870 DECLARE_CONCRETE_INSTRUCTION(DateField)
4877 class HDeleteProperty: public HBinaryOperation {
4879 HDeleteProperty(HValue* context, HValue* obj, HValue* key)
4880 : HBinaryOperation(context, obj, key) {
4881 set_representation(Representation::Tagged());
4882 SetAllSideEffects();
4885 virtual Representation RequiredInputRepresentation(int index) {
4886 return Representation::Tagged();
4889 virtual HType CalculateInferredType();
4891 DECLARE_CONCRETE_INSTRUCTION(DeleteProperty)
4893 HValue* object() { return left(); }
4894 HValue* key() { return right(); }
4898 class HIn: public HTemplateInstruction<3> {
4900 HIn(HValue* context, HValue* key, HValue* object) {
4901 SetOperandAt(0, context);
4902 SetOperandAt(1, key);
4903 SetOperandAt(2, object);
4904 set_representation(Representation::Tagged());
4905 SetAllSideEffects();
4908 HValue* context() { return OperandAt(0); }
4909 HValue* key() { return OperandAt(1); }
4910 HValue* object() { return OperandAt(2); }
4912 virtual Representation RequiredInputRepresentation(int index) {
4913 return Representation::Tagged();
4916 virtual HType CalculateInferredType() {
4917 return HType::Boolean();
4920 virtual void PrintDataTo(StringStream* stream);
4922 DECLARE_CONCRETE_INSTRUCTION(In)
4926 class HCheckMapValue: public HTemplateInstruction<2> {
4928 HCheckMapValue(HValue* value,
4930 SetOperandAt(0, value);
4931 SetOperandAt(1, map);
4932 set_representation(Representation::Tagged());
4934 SetGVNFlag(kDependsOnMaps);
4935 SetGVNFlag(kDependsOnElementsKind);
4938 virtual Representation RequiredInputRepresentation(int index) {
4939 return Representation::Tagged();
4942 virtual void PrintDataTo(StringStream* stream);
4944 virtual HType CalculateInferredType() {
4945 return HType::Tagged();
4948 HValue* value() { return OperandAt(0); }
4949 HValue* map() { return OperandAt(1); }
4951 DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
4954 virtual bool DataEquals(HValue* other) {
4960 class HForInPrepareMap : public HTemplateInstruction<2> {
4962 HForInPrepareMap(HValue* context,
4964 SetOperandAt(0, context);
4965 SetOperandAt(1, object);
4966 set_representation(Representation::Tagged());
4967 SetAllSideEffects();
4970 virtual Representation RequiredInputRepresentation(int index) {
4971 return Representation::Tagged();
4974 HValue* context() { return OperandAt(0); }
4975 HValue* enumerable() { return OperandAt(1); }
4977 virtual void PrintDataTo(StringStream* stream);
4979 virtual HType CalculateInferredType() {
4980 return HType::Tagged();
4983 DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
4987 class HForInCacheArray : public HTemplateInstruction<2> {
4989 HForInCacheArray(HValue* enumerable,
4991 int idx) : idx_(idx) {
4992 SetOperandAt(0, enumerable);
4993 SetOperandAt(1, keys);
4994 set_representation(Representation::Tagged());
4997 virtual Representation RequiredInputRepresentation(int index) {
4998 return Representation::Tagged();
5001 HValue* enumerable() { return OperandAt(0); }
5002 HValue* map() { return OperandAt(1); }
5003 int idx() { return idx_; }
5005 HForInCacheArray* index_cache() {
5006 return index_cache_;
5009 void set_index_cache(HForInCacheArray* index_cache) {
5010 index_cache_ = index_cache;
5013 virtual void PrintDataTo(StringStream* stream);
5015 virtual HType CalculateInferredType() {
5016 return HType::Tagged();
5019 DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
5023 HForInCacheArray* index_cache_;
5027 class HLoadFieldByIndex : public HTemplateInstruction<2> {
5029 HLoadFieldByIndex(HValue* object,
5031 SetOperandAt(0, object);
5032 SetOperandAt(1, index);
5033 set_representation(Representation::Tagged());
5036 virtual Representation RequiredInputRepresentation(int index) {
5037 return Representation::Tagged();
5040 HValue* object() { return OperandAt(0); }
5041 HValue* index() { return OperandAt(1); }
5043 virtual void PrintDataTo(StringStream* stream);
5045 virtual HType CalculateInferredType() {
5046 return HType::Tagged();
5049 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
5053 #undef DECLARE_INSTRUCTION
5054 #undef DECLARE_CONCRETE_INSTRUCTION
5056 } } // namespace v8::internal
5058 #endif // V8_HYDROGEN_INSTRUCTIONS_H_