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) \
160 V(StoreContextSlot) \
162 V(StoreGlobalGeneric) \
163 V(StoreKeyedFastDoubleElement) \
164 V(StoreKeyedFastElement) \
165 V(StoreKeyedGeneric) \
166 V(StoreKeyedSpecializedArrayElement) \
168 V(StoreNamedGeneric) \
170 V(StringCharCodeAt) \
171 V(StringCharFromCode) \
176 V(ToFastProperties) \
177 V(TransitionElementsKind) \
179 V(TypeofIsAndBranch) \
180 V(UnaryMathOperation) \
187 V(LoadFieldByIndex) \
191 #define GVN_FLAG_LIST(V) \
194 V(BackingStoreFields) \
198 V(DoubleArrayElements) \
199 V(SpecializedArrayElements) \
206 #define DECLARE_ABSTRACT_INSTRUCTION(type) \
207 virtual bool Is##type() const { return true; } \
208 static H##type* cast(HValue* value) { \
209 ASSERT(value->Is##type()); \
210 return reinterpret_cast<H##type*>(value); \
214 #define DECLARE_CONCRETE_INSTRUCTION(type) \
215 virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
216 static H##type* cast(HValue* value) { \
217 ASSERT(value->Is##type()); \
218 return reinterpret_cast<H##type*>(value); \
220 virtual Opcode opcode() const { return HValue::k##type; }
223 class Range: public ZoneObject {
229 can_be_minus_zero_(false) { }
231 Range(int32_t lower, int32_t upper)
235 can_be_minus_zero_(false) { }
237 int32_t upper() const { return upper_; }
238 int32_t lower() const { return lower_; }
239 Range* next() const { return next_; }
240 Range* CopyClearLower(Zone* zone) const {
241 return new(zone) Range(kMinInt, upper_);
243 Range* CopyClearUpper(Zone* zone) const {
244 return new(zone) Range(lower_, kMaxInt);
246 Range* Copy(Zone* zone) const {
247 Range* result = new(zone) Range(lower_, upper_);
248 result->set_can_be_minus_zero(CanBeMinusZero());
251 int32_t Mask() const;
252 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
253 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
254 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
255 bool CanBeNegative() const { return lower_ < 0; }
256 bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
257 bool IsMostGeneric() const {
258 return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
260 bool IsInSmiRange() const {
261 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
268 void StackUpon(Range* other) {
273 void Intersect(Range* other);
274 void Union(Range* other);
276 void AddConstant(int32_t value);
277 void Sar(int32_t value);
278 void Shl(int32_t value);
279 bool AddAndCheckOverflow(Range* other);
280 bool SubAndCheckOverflow(Range* other);
281 bool MulAndCheckOverflow(Range* other);
287 bool can_be_minus_zero_;
291 class Representation {
302 Representation() : kind_(kNone) { }
304 static Representation None() { return Representation(kNone); }
305 static Representation Tagged() { return Representation(kTagged); }
306 static Representation Integer32() { return Representation(kInteger32); }
307 static Representation Double() { return Representation(kDouble); }
308 static Representation External() { return Representation(kExternal); }
310 bool Equals(const Representation& other) {
311 return kind_ == other.kind_;
314 Kind kind() const { return static_cast<Kind>(kind_); }
315 bool IsNone() const { return kind_ == kNone; }
316 bool IsTagged() const { return kind_ == kTagged; }
317 bool IsInteger32() const { return kind_ == kInteger32; }
318 bool IsDouble() const { return kind_ == kDouble; }
319 bool IsExternal() const { return kind_ == kExternal; }
320 bool IsSpecialization() const {
321 return kind_ == kInteger32 || kind_ == kDouble;
323 const char* Mnemonic() const;
326 explicit Representation(Kind k) : kind_(k) { }
328 // Make sure kind fits in int8.
329 STATIC_ASSERT(kNumRepresentations <= (1 << kBitsPerByte));
337 HType() : type_(kUninitialized) { }
339 static HType Tagged() { return HType(kTagged); }
340 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
341 static HType TaggedNumber() { return HType(kTaggedNumber); }
342 static HType Smi() { return HType(kSmi); }
343 static HType HeapNumber() { return HType(kHeapNumber); }
344 static HType String() { return HType(kString); }
345 static HType Boolean() { return HType(kBoolean); }
346 static HType NonPrimitive() { return HType(kNonPrimitive); }
347 static HType JSArray() { return HType(kJSArray); }
348 static HType JSObject() { return HType(kJSObject); }
349 static HType Uninitialized() { return HType(kUninitialized); }
351 // Return the weakest (least precise) common type.
352 HType Combine(HType other) {
353 return HType(static_cast<Type>(type_ & other.type_));
356 bool Equals(const HType& other) {
357 return type_ == other.type_;
360 bool IsSubtypeOf(const HType& other) {
361 return Combine(other).Equals(other);
365 ASSERT(type_ != kUninitialized);
366 return ((type_ & kTagged) == kTagged);
369 bool IsTaggedPrimitive() {
370 ASSERT(type_ != kUninitialized);
371 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
374 bool IsTaggedNumber() {
375 ASSERT(type_ != kUninitialized);
376 return ((type_ & kTaggedNumber) == kTaggedNumber);
380 ASSERT(type_ != kUninitialized);
381 return ((type_ & kSmi) == kSmi);
384 bool IsHeapNumber() {
385 ASSERT(type_ != kUninitialized);
386 return ((type_ & kHeapNumber) == kHeapNumber);
390 ASSERT(type_ != kUninitialized);
391 return ((type_ & kString) == kString);
395 ASSERT(type_ != kUninitialized);
396 return ((type_ & kBoolean) == kBoolean);
399 bool IsNonPrimitive() {
400 ASSERT(type_ != kUninitialized);
401 return ((type_ & kNonPrimitive) == kNonPrimitive);
405 ASSERT(type_ != kUninitialized);
406 return ((type_ & kJSArray) == kJSArray);
410 ASSERT(type_ != kUninitialized);
411 return ((type_ & kJSObject) == kJSObject);
414 bool IsUninitialized() {
415 return type_ == kUninitialized;
418 bool IsHeapObject() {
419 ASSERT(type_ != kUninitialized);
420 return IsHeapNumber() || IsString() || IsNonPrimitive();
423 static HType TypeFromValue(Handle<Object> value);
425 const char* ToString();
429 kTagged = 0x1, // 0000 0000 0000 0001
430 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
431 kTaggedNumber = 0xd, // 0000 0000 0000 1101
432 kSmi = 0x1d, // 0000 0000 0001 1101
433 kHeapNumber = 0x2d, // 0000 0000 0010 1101
434 kString = 0x45, // 0000 0000 0100 0101
435 kBoolean = 0x85, // 0000 0000 1000 0101
436 kNonPrimitive = 0x101, // 0000 0001 0000 0001
437 kJSObject = 0x301, // 0000 0011 0000 0001
438 kJSArray = 0x701, // 0000 0111 0000 0001
439 kUninitialized = 0x1fff // 0001 1111 1111 1111
442 // Make sure type fits in int16.
443 STATIC_ASSERT(kUninitialized < (1 << (2 * kBitsPerByte)));
445 explicit HType(Type t) : type_(t) { }
451 class HUseListNode: public ZoneObject {
453 HUseListNode(HValue* value, int index, HUseListNode* tail)
454 : tail_(tail), value_(value), index_(index) {
457 HUseListNode* tail();
458 HValue* value() const { return value_; }
459 int index() const { return index_; }
461 void set_tail(HUseListNode* list) { tail_ = list; }
465 tail_ = reinterpret_cast<HUseListNode*>(1);
478 // We reuse use list nodes behind the scenes as uses are added and deleted.
479 // This class is the safe way to iterate uses while deleting them.
480 class HUseIterator BASE_EMBEDDED {
482 bool Done() { return current_ == NULL; }
496 explicit HUseIterator(HUseListNode* head);
498 HUseListNode* current_;
507 // There must be one corresponding kDepends flag for every kChanges flag and
508 // the order of the kChanges flags must be exactly the same as of the kDepends
511 // Declare global value numbering flags.
512 #define DECLARE_FLAG(type) kChanges##type, kDependsOn##type,
513 GVN_FLAG_LIST(DECLARE_FLAG)
516 kLastFlag = kAfterLastFlag - 1
519 typedef EnumSet<GVNFlag> GVNFlagSet;
522 class HValue: public ZoneObject {
524 static const int kNoNumber = -1;
527 kFlexibleRepresentation,
528 // Participate in Global Value Numbering, i.e. elimination of
529 // unnecessary recomputations. If an instruction sets this flag, it must
530 // implement DataEquals(), which will be used to determine if other
531 // occurrences of the instruction are indeed the same.
536 kDeoptimizeOnUndefined,
543 STATIC_ASSERT(kLastFlag < kBitsPerInt);
545 static const int kChangesToDependsFlagsLeftShift = 1;
547 static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags) {
548 return GVNFlagSet(flags.ToIntegral() << kChangesToDependsFlagsLeftShift);
551 static HValue* cast(HValue* value) { return value; }
554 // Declare a unique enum value for each hydrogen instruction.
555 #define DECLARE_OPCODE(type) k##type,
556 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
558 #undef DECLARE_OPCODE
560 virtual Opcode opcode() const = 0;
562 // Declare a non-virtual predicates for each concrete HInstruction or HValue.
563 #define DECLARE_PREDICATE(type) \
564 bool Is##type() const { return opcode() == k##type; }
565 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
566 #undef DECLARE_PREDICATE
567 bool IsPhi() const { return opcode() == kPhi; }
569 // Declare virtual predicates for abstract HInstruction or HValue
570 #define DECLARE_PREDICATE(type) \
571 virtual bool Is##type() const { return false; }
572 HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
573 #undef DECLARE_PREDICATE
575 HValue() : block_(NULL),
577 type_(HType::Tagged()),
583 HBasicBlock* block() const { return block_; }
584 void SetBlock(HBasicBlock* block);
585 int LoopWeight() const;
587 int id() const { return id_; }
588 void set_id(int id) { id_ = id; }
590 HUseIterator uses() const { return HUseIterator(use_list_); }
592 virtual bool EmitAtUses() { return false; }
593 Representation representation() const { return representation_; }
594 void ChangeRepresentation(Representation r) {
595 // Representation was already set and is allowed to be changed.
597 ASSERT(CheckFlag(kFlexibleRepresentation));
598 RepresentationChanged(r);
601 void AssumeRepresentation(Representation r);
603 virtual bool IsConvertibleToInteger() const { return true; }
605 HType type() const { return type_; }
606 void set_type(HType new_type) {
607 ASSERT(new_type.IsSubtypeOf(type_));
611 // An operation needs to override this function iff:
612 // 1) it can produce an int32 output.
613 // 2) the true value of its output can potentially be minus zero.
614 // The implementation must set a flag so that it bails out in the case where
615 // it would otherwise output what should be a minus zero as an int32 zero.
616 // If the operation also exists in a form that takes int32 and outputs int32
617 // then the operation should return its input value so that we can propagate
618 // back. There are three operations that need to propagate back to more than
619 // one input. They are phi and binary div and mul. They always return NULL
620 // and expect the caller to take care of things.
621 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
626 bool IsDefinedAfter(HBasicBlock* other) const;
629 virtual int OperandCount() = 0;
630 virtual HValue* OperandAt(int index) = 0;
631 void SetOperandAt(int index, HValue* value);
633 void DeleteAndReplaceWith(HValue* other);
634 void ReplaceAllUsesWith(HValue* other);
635 bool HasNoUses() const { return use_list_ == NULL; }
636 bool HasMultipleUses() const {
637 return use_list_ != NULL && use_list_->tail() != NULL;
639 int UseCount() const;
641 // Mark this HValue as dead and to be removed from other HValues' use lists.
644 int flags() const { return flags_; }
645 void SetFlag(Flag f) { flags_ |= (1 << f); }
646 void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
647 bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
649 // Returns true if the flag specified is set for all uses, false otherwise.
650 bool CheckUsesForFlag(Flag f);
652 GVNFlagSet gvn_flags() const { return gvn_flags_; }
653 void SetGVNFlag(GVNFlag f) { gvn_flags_.Add(f); }
654 void ClearGVNFlag(GVNFlag f) { gvn_flags_.Remove(f); }
655 bool CheckGVNFlag(GVNFlag f) const { return gvn_flags_.Contains(f); }
656 void SetAllSideEffects() { gvn_flags_.Add(AllSideEffectsFlagSet()); }
657 void ClearAllSideEffects() {
658 gvn_flags_.Remove(AllSideEffectsFlagSet());
660 bool HasSideEffects() const {
661 return gvn_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
663 bool HasObservableSideEffects() const {
664 return gvn_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
667 GVNFlagSet DependsOnFlags() const {
668 GVNFlagSet result = gvn_flags_;
669 result.Intersect(AllDependsOnFlagSet());
673 GVNFlagSet SideEffectFlags() const {
674 GVNFlagSet result = gvn_flags_;
675 result.Intersect(AllSideEffectsFlagSet());
679 GVNFlagSet ChangesFlags() const {
680 GVNFlagSet result = gvn_flags_;
681 result.Intersect(AllChangesFlagSet());
685 GVNFlagSet ObservableChangesFlags() const {
686 GVNFlagSet result = gvn_flags_;
687 result.Intersect(AllChangesFlagSet());
688 result.Intersect(AllObservableSideEffectsFlagSet());
692 Range* range() const { return range_; }
693 bool HasRange() const { return range_ != NULL; }
694 void AddNewRange(Range* r, Zone* zone);
695 void RemoveLastAddedRange();
696 void ComputeInitialRange(Zone* zone);
698 // Representation helpers.
699 virtual Representation RequiredInputRepresentation(int index) = 0;
701 virtual Representation InferredRepresentation() {
702 return representation();
705 // This gives the instruction an opportunity to replace itself with an
706 // instruction that does the same in some better way. To replace an
707 // instruction with a new one, first add the new instruction to the graph,
708 // then return it. Return NULL to have the instruction deleted.
709 virtual HValue* Canonicalize() { return this; }
711 bool Equals(HValue* other);
712 virtual intptr_t Hashcode();
715 virtual void PrintTo(StringStream* stream) = 0;
716 void PrintNameTo(StringStream* stream);
717 void PrintTypeTo(StringStream* stream);
718 void PrintRangeTo(StringStream* stream);
719 void PrintChangesTo(StringStream* stream);
721 const char* Mnemonic() const;
723 // Updated the inferred type of this instruction and returns true if
725 bool UpdateInferredType();
727 virtual HType CalculateInferredType();
730 virtual void Verify() = 0;
734 // This function must be overridden for instructions with flag kUseGVN, to
735 // compare the non-Operand parts of the instruction.
736 virtual bool DataEquals(HValue* other) {
740 virtual void RepresentationChanged(Representation to) { }
741 virtual Range* InferRange(Zone* zone);
742 virtual void DeleteFromGraph() = 0;
743 virtual void InternalSetOperandAt(int index, HValue* value) = 0;
745 ASSERT(block_ != NULL);
749 void set_representation(Representation r) {
750 // Representation is set-once.
751 ASSERT(representation_.IsNone() && !r.IsNone());
755 static GVNFlagSet AllDependsOnFlagSet() {
757 // Create changes mask.
758 #define ADD_FLAG(type) result.Add(kDependsOn##type);
759 GVN_FLAG_LIST(ADD_FLAG)
764 static GVNFlagSet AllChangesFlagSet() {
766 // Create changes mask.
767 #define ADD_FLAG(type) result.Add(kChanges##type);
768 GVN_FLAG_LIST(ADD_FLAG)
773 // A flag mask to mark an instruction as having arbitrary side effects.
774 static GVNFlagSet AllSideEffectsFlagSet() {
775 GVNFlagSet result = AllChangesFlagSet();
776 result.Remove(kChangesOsrEntries);
780 // A flag mask of all side effects that can make observable changes in
781 // an executing program (i.e. are not safe to repeat, move or remove);
782 static GVNFlagSet AllObservableSideEffectsFlagSet() {
783 GVNFlagSet result = AllChangesFlagSet();
784 result.Remove(kChangesElementsKind);
785 result.Remove(kChangesElementsPointer);
786 result.Remove(kChangesMaps);
790 // Remove the matching use from the use list if present. Returns the
791 // removed list node or NULL.
792 HUseListNode* RemoveUse(HValue* value, int index);
794 void RegisterUse(int index, HValue* new_value);
798 // The id of this instruction in the hydrogen graph, assigned when first
799 // added to the graph. Reflects creation order.
802 Representation representation_;
804 HUseListNode* use_list_;
807 GVNFlagSet gvn_flags_;
810 DISALLOW_COPY_AND_ASSIGN(HValue);
814 class HInstruction: public HValue {
816 HInstruction* next() const { return next_; }
817 HInstruction* previous() const { return previous_; }
819 virtual void PrintTo(StringStream* stream);
820 virtual void PrintDataTo(StringStream* stream) { }
822 bool IsLinked() const { return block() != NULL; }
824 void InsertBefore(HInstruction* next);
825 void InsertAfter(HInstruction* previous);
827 int position() const { return position_; }
828 bool has_position() const { return position_ != RelocInfo::kNoPosition; }
829 void set_position(int position) { position_ = position; }
831 bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
833 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
836 virtual void Verify();
839 virtual bool IsCall() { return false; }
841 DECLARE_ABSTRACT_INSTRUCTION(Instruction)
847 position_(RelocInfo::kNoPosition) {
848 SetGVNFlag(kDependsOnOsrEntries);
851 virtual void DeleteFromGraph() { Unlink(); }
854 void InitializeAsFirst(HBasicBlock* block) {
859 void PrintMnemonicTo(StringStream* stream);
862 HInstruction* previous_;
865 friend class HBasicBlock;
870 class HTemplateInstruction : public HInstruction {
872 int OperandCount() { return V; }
873 HValue* OperandAt(int i) { return inputs_[i]; }
876 void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
879 EmbeddedContainer<HValue*, V> inputs_;
883 class HControlInstruction: public HInstruction {
885 virtual HBasicBlock* SuccessorAt(int i) = 0;
886 virtual int SuccessorCount() = 0;
887 virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
889 virtual void PrintDataTo(StringStream* stream);
891 HBasicBlock* FirstSuccessor() {
892 return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
894 HBasicBlock* SecondSuccessor() {
895 return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
898 DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
902 class HSuccessorIterator BASE_EMBEDDED {
904 explicit HSuccessorIterator(HControlInstruction* instr)
905 : instr_(instr), current_(0) { }
907 bool Done() { return current_ >= instr_->SuccessorCount(); }
908 HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
909 void Advance() { current_++; }
912 HControlInstruction* instr_;
917 template<int S, int V>
918 class HTemplateControlInstruction: public HControlInstruction {
920 int SuccessorCount() { return S; }
921 HBasicBlock* SuccessorAt(int i) { return successors_[i]; }
922 void SetSuccessorAt(int i, HBasicBlock* block) { successors_[i] = block; }
924 int OperandCount() { return V; }
925 HValue* OperandAt(int i) { return inputs_[i]; }
929 void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
932 EmbeddedContainer<HBasicBlock*, S> successors_;
933 EmbeddedContainer<HValue*, V> inputs_;
937 class HBlockEntry: public HTemplateInstruction<0> {
939 virtual Representation RequiredInputRepresentation(int index) {
940 return Representation::None();
943 DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
947 // We insert soft-deoptimize when we hit code with unknown typefeedback,
948 // so that we get a chance of re-optimizing with useful typefeedback.
949 // HSoftDeoptimize does not end a basic block as opposed to HDeoptimize.
950 class HSoftDeoptimize: public HTemplateInstruction<0> {
952 virtual Representation RequiredInputRepresentation(int index) {
953 return Representation::None();
956 DECLARE_CONCRETE_INSTRUCTION(SoftDeoptimize)
960 class HDeoptimize: public HControlInstruction {
962 explicit HDeoptimize(int environment_length) : values_(environment_length) { }
964 virtual Representation RequiredInputRepresentation(int index) {
965 return Representation::None();
968 virtual int OperandCount() { return values_.length(); }
969 virtual HValue* OperandAt(int index) { return values_[index]; }
970 virtual void PrintDataTo(StringStream* stream);
972 virtual int SuccessorCount() { return 0; }
973 virtual HBasicBlock* SuccessorAt(int i) {
977 virtual void SetSuccessorAt(int i, HBasicBlock* block) {
981 void AddEnvironmentValue(HValue* value) {
983 SetOperandAt(values_.length() - 1, value);
986 DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
988 enum UseEnvironment {
994 virtual void InternalSetOperandAt(int index, HValue* value) {
995 values_[index] = value;
999 ZoneList<HValue*> values_;
1003 class HGoto: public HTemplateControlInstruction<1, 0> {
1005 explicit HGoto(HBasicBlock* target) {
1006 SetSuccessorAt(0, target);
1009 virtual Representation RequiredInputRepresentation(int index) {
1010 return Representation::None();
1013 virtual void PrintDataTo(StringStream* stream);
1015 DECLARE_CONCRETE_INSTRUCTION(Goto)
1019 class HUnaryControlInstruction: public HTemplateControlInstruction<2, 1> {
1021 HUnaryControlInstruction(HValue* value,
1022 HBasicBlock* true_target,
1023 HBasicBlock* false_target) {
1024 SetOperandAt(0, value);
1025 SetSuccessorAt(0, true_target);
1026 SetSuccessorAt(1, false_target);
1029 virtual void PrintDataTo(StringStream* stream);
1031 HValue* value() { return OperandAt(0); }
1035 class HBranch: public HUnaryControlInstruction {
1037 HBranch(HValue* value,
1038 HBasicBlock* true_target,
1039 HBasicBlock* false_target,
1040 ToBooleanStub::Types expected_input_types = ToBooleanStub::no_types())
1041 : HUnaryControlInstruction(value, true_target, false_target),
1042 expected_input_types_(expected_input_types) {
1043 ASSERT(true_target != NULL && false_target != NULL);
1045 explicit HBranch(HValue* value)
1046 : HUnaryControlInstruction(value, NULL, NULL) { }
1049 virtual Representation RequiredInputRepresentation(int index) {
1050 return Representation::None();
1053 ToBooleanStub::Types expected_input_types() const {
1054 return expected_input_types_;
1057 DECLARE_CONCRETE_INSTRUCTION(Branch)
1060 ToBooleanStub::Types expected_input_types_;
1064 class HCompareMap: public HUnaryControlInstruction {
1066 HCompareMap(HValue* value,
1068 HBasicBlock* true_target,
1069 HBasicBlock* false_target)
1070 : HUnaryControlInstruction(value, true_target, false_target),
1072 ASSERT(true_target != NULL);
1073 ASSERT(false_target != NULL);
1074 ASSERT(!map.is_null());
1077 virtual void PrintDataTo(StringStream* stream);
1079 Handle<Map> map() const { return map_; }
1081 virtual Representation RequiredInputRepresentation(int index) {
1082 return Representation::Tagged();
1085 DECLARE_CONCRETE_INSTRUCTION(CompareMap)
1092 class HReturn: public HTemplateControlInstruction<0, 1> {
1094 explicit HReturn(HValue* value) {
1095 SetOperandAt(0, value);
1098 virtual Representation RequiredInputRepresentation(int index) {
1099 return Representation::Tagged();
1102 virtual void PrintDataTo(StringStream* stream);
1104 HValue* value() { return OperandAt(0); }
1106 DECLARE_CONCRETE_INSTRUCTION(Return)
1110 class HAbnormalExit: public HTemplateControlInstruction<0, 0> {
1112 virtual Representation RequiredInputRepresentation(int index) {
1113 return Representation::None();
1116 DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
1120 class HUnaryOperation: public HTemplateInstruction<1> {
1122 explicit HUnaryOperation(HValue* value) {
1123 SetOperandAt(0, value);
1126 static HUnaryOperation* cast(HValue* value) {
1127 return reinterpret_cast<HUnaryOperation*>(value);
1130 HValue* value() { return OperandAt(0); }
1131 virtual void PrintDataTo(StringStream* stream);
1135 class HThrow: public HTemplateInstruction<2> {
1137 HThrow(HValue* context, HValue* value) {
1138 SetOperandAt(0, context);
1139 SetOperandAt(1, value);
1140 SetAllSideEffects();
1143 virtual Representation RequiredInputRepresentation(int index) {
1144 return Representation::Tagged();
1147 HValue* context() { return OperandAt(0); }
1148 HValue* value() { return OperandAt(1); }
1150 DECLARE_CONCRETE_INSTRUCTION(Throw)
1154 class HUseConst: public HUnaryOperation {
1156 explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
1158 virtual Representation RequiredInputRepresentation(int index) {
1159 return Representation::None();
1162 DECLARE_CONCRETE_INSTRUCTION(UseConst)
1166 class HForceRepresentation: public HTemplateInstruction<1> {
1168 HForceRepresentation(HValue* value, Representation required_representation) {
1169 SetOperandAt(0, value);
1170 set_representation(required_representation);
1173 HValue* value() { return OperandAt(0); }
1175 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1177 virtual Representation RequiredInputRepresentation(int index) {
1178 return representation(); // Same as the output representation.
1181 DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
1185 class HChange: public HUnaryOperation {
1187 HChange(HValue* value,
1190 bool deoptimize_on_undefined)
1191 : HUnaryOperation(value) {
1192 ASSERT(!value->representation().IsNone() && !to.IsNone());
1193 ASSERT(!value->representation().Equals(to));
1194 set_representation(to);
1195 set_type(HType::TaggedNumber());
1197 if (deoptimize_on_undefined) SetFlag(kDeoptimizeOnUndefined);
1198 if (is_truncating) SetFlag(kTruncatingToInt32);
1201 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1202 virtual HType CalculateInferredType();
1203 virtual HValue* Canonicalize();
1205 Representation from() { return value()->representation(); }
1206 Representation to() { return representation(); }
1207 bool deoptimize_on_undefined() const {
1208 return CheckFlag(kDeoptimizeOnUndefined);
1210 bool deoptimize_on_minus_zero() const {
1211 return CheckFlag(kBailoutOnMinusZero);
1213 virtual Representation RequiredInputRepresentation(int index) {
1217 virtual Range* InferRange(Zone* zone);
1219 virtual void PrintDataTo(StringStream* stream);
1221 DECLARE_CONCRETE_INSTRUCTION(Change)
1224 virtual bool DataEquals(HValue* other) { return true; }
1228 class HClampToUint8: public HUnaryOperation {
1230 explicit HClampToUint8(HValue* value)
1231 : HUnaryOperation(value) {
1232 set_representation(Representation::Integer32());
1236 virtual Representation RequiredInputRepresentation(int index) {
1237 return Representation::None();
1240 DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
1243 virtual bool DataEquals(HValue* other) { return true; }
1247 class HSimulate: public HInstruction {
1249 HSimulate(int ast_id, int pop_count)
1251 pop_count_(pop_count),
1253 assigned_indexes_(2) {}
1254 virtual ~HSimulate() {}
1256 virtual void PrintDataTo(StringStream* stream);
1258 bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; }
1259 int ast_id() const { return ast_id_; }
1260 void set_ast_id(int id) {
1261 ASSERT(!HasAstId());
1265 int pop_count() const { return pop_count_; }
1266 const ZoneList<HValue*>* values() const { return &values_; }
1267 int GetAssignedIndexAt(int index) const {
1268 ASSERT(HasAssignedIndexAt(index));
1269 return assigned_indexes_[index];
1271 bool HasAssignedIndexAt(int index) const {
1272 return assigned_indexes_[index] != kNoIndex;
1274 void AddAssignedValue(int index, HValue* value) {
1275 AddValue(index, value);
1277 void AddPushedValue(HValue* value) {
1278 AddValue(kNoIndex, value);
1280 virtual int OperandCount() { return values_.length(); }
1281 virtual HValue* OperandAt(int index) { return values_[index]; }
1283 virtual Representation RequiredInputRepresentation(int index) {
1284 return Representation::None();
1287 DECLARE_CONCRETE_INSTRUCTION(Simulate)
1290 virtual void Verify();
1294 virtual void InternalSetOperandAt(int index, HValue* value) {
1295 values_[index] = value;
1299 static const int kNoIndex = -1;
1300 void AddValue(int index, HValue* value) {
1301 assigned_indexes_.Add(index);
1302 // Resize the list of pushed values.
1304 // Set the operand through the base method in HValue to make sure that the
1305 // use lists are correctly updated.
1306 SetOperandAt(values_.length() - 1, value);
1310 ZoneList<HValue*> values_;
1311 ZoneList<int> assigned_indexes_;
1315 class HStackCheck: public HTemplateInstruction<1> {
1322 HStackCheck(HValue* context, Type type) : type_(type) {
1323 SetOperandAt(0, context);
1326 HValue* context() { return OperandAt(0); }
1328 virtual Representation RequiredInputRepresentation(int index) {
1329 return Representation::Tagged();
1333 // The stack check eliminator might try to eliminate the same stack
1334 // check instruction multiple times.
1340 bool is_function_entry() { return type_ == kFunctionEntry; }
1341 bool is_backwards_branch() { return type_ == kBackwardsBranch; }
1343 DECLARE_CONCRETE_INSTRUCTION(StackCheck)
1350 class HEnterInlined: public HTemplateInstruction<0> {
1352 HEnterInlined(Handle<JSFunction> closure,
1353 int arguments_count,
1354 FunctionLiteral* function,
1357 Variable* arguments)
1358 : closure_(closure),
1359 arguments_count_(arguments_count),
1360 function_(function),
1361 call_kind_(call_kind),
1362 is_construct_(is_construct),
1363 arguments_(arguments) {
1366 virtual void PrintDataTo(StringStream* stream);
1368 Handle<JSFunction> closure() const { return closure_; }
1369 int arguments_count() const { return arguments_count_; }
1370 FunctionLiteral* function() const { return function_; }
1371 CallKind call_kind() const { return call_kind_; }
1372 bool is_construct() const { return is_construct_; }
1374 virtual Representation RequiredInputRepresentation(int index) {
1375 return Representation::None();
1378 Variable* arguments() { return arguments_; }
1380 DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
1383 Handle<JSFunction> closure_;
1384 int arguments_count_;
1385 FunctionLiteral* function_;
1386 CallKind call_kind_;
1388 Variable* arguments_;
1392 class HLeaveInlined: public HTemplateInstruction<0> {
1396 virtual Representation RequiredInputRepresentation(int index) {
1397 return Representation::None();
1400 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
1404 class HPushArgument: public HUnaryOperation {
1406 explicit HPushArgument(HValue* value) : HUnaryOperation(value) {
1407 set_representation(Representation::Tagged());
1410 virtual Representation RequiredInputRepresentation(int index) {
1411 return Representation::Tagged();
1414 HValue* argument() { return OperandAt(0); }
1416 DECLARE_CONCRETE_INSTRUCTION(PushArgument)
1420 class HThisFunction: public HTemplateInstruction<0> {
1422 explicit HThisFunction(Handle<JSFunction> closure) : closure_(closure) {
1423 set_representation(Representation::Tagged());
1427 virtual Representation RequiredInputRepresentation(int index) {
1428 return Representation::None();
1431 Handle<JSFunction> closure() const { return closure_; }
1433 DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
1436 virtual bool DataEquals(HValue* other) {
1437 HThisFunction* b = HThisFunction::cast(other);
1438 return *closure() == *b->closure();
1442 Handle<JSFunction> closure_;
1446 class HContext: public HTemplateInstruction<0> {
1449 set_representation(Representation::Tagged());
1453 virtual Representation RequiredInputRepresentation(int index) {
1454 return Representation::None();
1457 DECLARE_CONCRETE_INSTRUCTION(Context)
1460 virtual bool DataEquals(HValue* other) { return true; }
1464 class HOuterContext: public HUnaryOperation {
1466 explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
1467 set_representation(Representation::Tagged());
1471 DECLARE_CONCRETE_INSTRUCTION(OuterContext);
1473 virtual Representation RequiredInputRepresentation(int index) {
1474 return Representation::Tagged();
1478 virtual bool DataEquals(HValue* other) { return true; }
1482 class HDeclareGlobals: public HUnaryOperation {
1484 HDeclareGlobals(HValue* context,
1485 Handle<FixedArray> pairs,
1487 : HUnaryOperation(context),
1490 set_representation(Representation::Tagged());
1491 SetAllSideEffects();
1494 HValue* context() { return OperandAt(0); }
1495 Handle<FixedArray> pairs() const { return pairs_; }
1496 int flags() const { return flags_; }
1498 DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
1500 virtual Representation RequiredInputRepresentation(int index) {
1501 return Representation::Tagged();
1504 Handle<FixedArray> pairs_;
1509 class HGlobalObject: public HUnaryOperation {
1511 explicit HGlobalObject(HValue* context) : HUnaryOperation(context), qml_global_(false) {
1512 set_representation(Representation::Tagged());
1516 virtual void PrintDataTo(StringStream* stream);
1518 DECLARE_CONCRETE_INSTRUCTION(GlobalObject)
1520 virtual Representation RequiredInputRepresentation(int index) {
1521 return Representation::Tagged();
1524 bool qml_global() { return qml_global_; }
1525 void set_qml_global(bool v) { qml_global_ = v; }
1528 virtual bool DataEquals(HValue* other) {
1529 HGlobalObject* o = HGlobalObject::cast(other);
1530 return o->qml_global_ == qml_global_;
1538 class HGlobalReceiver: public HUnaryOperation {
1540 explicit HGlobalReceiver(HValue* global_object)
1541 : HUnaryOperation(global_object) {
1542 set_representation(Representation::Tagged());
1546 DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver)
1548 virtual Representation RequiredInputRepresentation(int index) {
1549 return Representation::Tagged();
1553 virtual bool DataEquals(HValue* other) { return true; }
1558 class HCall: public HTemplateInstruction<V> {
1560 // The argument count includes the receiver.
1561 explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
1562 this->set_representation(Representation::Tagged());
1563 this->SetAllSideEffects();
1566 virtual HType CalculateInferredType() { return HType::Tagged(); }
1568 virtual int argument_count() const { return argument_count_; }
1570 virtual bool IsCall() { return true; }
1573 int argument_count_;
1577 class HUnaryCall: public HCall<1> {
1579 HUnaryCall(HValue* value, int argument_count)
1580 : HCall<1>(argument_count) {
1581 SetOperandAt(0, value);
1584 virtual Representation RequiredInputRepresentation(int index) {
1585 return Representation::Tagged();
1588 virtual void PrintDataTo(StringStream* stream);
1590 HValue* value() { return OperandAt(0); }
1594 class HBinaryCall: public HCall<2> {
1596 HBinaryCall(HValue* first, HValue* second, int argument_count)
1597 : HCall<2>(argument_count) {
1598 SetOperandAt(0, first);
1599 SetOperandAt(1, second);
1602 virtual void PrintDataTo(StringStream* stream);
1604 virtual Representation RequiredInputRepresentation(int index) {
1605 return Representation::Tagged();
1608 HValue* first() { return OperandAt(0); }
1609 HValue* second() { return OperandAt(1); }
1613 class HInvokeFunction: public HBinaryCall {
1615 HInvokeFunction(HValue* context, HValue* function, int argument_count)
1616 : HBinaryCall(context, function, argument_count) {
1619 virtual Representation RequiredInputRepresentation(int index) {
1620 return Representation::Tagged();
1623 HValue* context() { return first(); }
1624 HValue* function() { return second(); }
1626 DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
1630 class HCallConstantFunction: public HCall<0> {
1632 HCallConstantFunction(Handle<JSFunction> function, int argument_count)
1633 : HCall<0>(argument_count), function_(function) { }
1635 Handle<JSFunction> function() const { return function_; }
1637 bool IsApplyFunction() const {
1638 return function_->code() ==
1639 Isolate::Current()->builtins()->builtin(Builtins::kFunctionApply);
1642 virtual void PrintDataTo(StringStream* stream);
1644 virtual Representation RequiredInputRepresentation(int index) {
1645 return Representation::None();
1648 DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction)
1651 Handle<JSFunction> function_;
1655 class HCallKeyed: public HBinaryCall {
1657 HCallKeyed(HValue* context, HValue* key, int argument_count)
1658 : HBinaryCall(context, key, argument_count) {
1661 virtual Representation RequiredInputRepresentation(int index) {
1662 return Representation::Tagged();
1665 HValue* context() { return first(); }
1666 HValue* key() { return second(); }
1668 DECLARE_CONCRETE_INSTRUCTION(CallKeyed)
1672 class HCallNamed: public HUnaryCall {
1674 HCallNamed(HValue* context, Handle<String> name, int argument_count)
1675 : HUnaryCall(context, argument_count), name_(name) {
1678 virtual void PrintDataTo(StringStream* stream);
1680 HValue* context() { return value(); }
1681 Handle<String> name() const { return name_; }
1683 DECLARE_CONCRETE_INSTRUCTION(CallNamed)
1685 virtual Representation RequiredInputRepresentation(int index) {
1686 return Representation::Tagged();
1690 Handle<String> name_;
1694 class HCallFunction: public HBinaryCall {
1696 HCallFunction(HValue* context, HValue* function, int argument_count)
1697 : HBinaryCall(context, function, argument_count) {
1700 HValue* context() { return first(); }
1701 HValue* function() { return second(); }
1703 virtual Representation RequiredInputRepresentation(int index) {
1704 return Representation::Tagged();
1707 DECLARE_CONCRETE_INSTRUCTION(CallFunction)
1711 class HCallGlobal: public HUnaryCall {
1713 HCallGlobal(HValue* context, Handle<String> name, int argument_count)
1714 : HUnaryCall(context, argument_count), name_(name), qml_global_(false) {
1717 virtual void PrintDataTo(StringStream* stream);
1719 HValue* context() { return value(); }
1720 Handle<String> name() const { return name_; }
1722 virtual Representation RequiredInputRepresentation(int index) {
1723 return Representation::Tagged();
1726 bool qml_global() { return qml_global_; }
1727 void set_qml_global(bool v) { qml_global_ = v; }
1729 DECLARE_CONCRETE_INSTRUCTION(CallGlobal)
1732 Handle<String> name_;
1737 class HCallKnownGlobal: public HCall<0> {
1739 HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
1740 : HCall<0>(argument_count), target_(target) { }
1742 virtual void PrintDataTo(StringStream* stream);
1744 Handle<JSFunction> target() const { return target_; }
1746 virtual Representation RequiredInputRepresentation(int index) {
1747 return Representation::None();
1750 DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal)
1753 Handle<JSFunction> target_;
1757 class HCallNew: public HBinaryCall {
1759 HCallNew(HValue* context, HValue* constructor, int argument_count)
1760 : HBinaryCall(context, constructor, argument_count) {
1763 virtual Representation RequiredInputRepresentation(int index) {
1764 return Representation::Tagged();
1767 HValue* context() { return first(); }
1768 HValue* constructor() { return second(); }
1770 DECLARE_CONCRETE_INSTRUCTION(CallNew)
1774 class HCallRuntime: public HCall<1> {
1776 HCallRuntime(HValue* context,
1777 Handle<String> name,
1778 const Runtime::Function* c_function,
1780 : HCall<1>(argument_count), c_function_(c_function), name_(name) {
1781 SetOperandAt(0, context);
1784 virtual void PrintDataTo(StringStream* stream);
1786 HValue* context() { return OperandAt(0); }
1787 const Runtime::Function* function() const { return c_function_; }
1788 Handle<String> name() const { return name_; }
1790 virtual Representation RequiredInputRepresentation(int index) {
1791 return Representation::Tagged();
1794 DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
1797 const Runtime::Function* c_function_;
1798 Handle<String> name_;
1802 class HJSArrayLength: public HTemplateInstruction<2> {
1804 HJSArrayLength(HValue* value, HValue* typecheck) {
1805 // The length of an array is stored as a tagged value in the array
1806 // object. It is guaranteed to be 32 bit integer, but it can be
1807 // represented as either a smi or heap number.
1808 SetOperandAt(0, value);
1809 SetOperandAt(1, typecheck);
1810 set_representation(Representation::Tagged());
1812 SetGVNFlag(kDependsOnArrayLengths);
1813 SetGVNFlag(kDependsOnMaps);
1816 virtual Representation RequiredInputRepresentation(int index) {
1817 return Representation::Tagged();
1820 virtual void PrintDataTo(StringStream* stream);
1822 HValue* value() { return OperandAt(0); }
1823 HValue* typecheck() { return OperandAt(1); }
1825 DECLARE_CONCRETE_INSTRUCTION(JSArrayLength)
1828 virtual bool DataEquals(HValue* other) { return true; }
1832 class HFixedArrayBaseLength: public HUnaryOperation {
1834 explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) {
1835 set_representation(Representation::Tagged());
1837 SetGVNFlag(kDependsOnArrayLengths);
1840 virtual Representation RequiredInputRepresentation(int index) {
1841 return Representation::Tagged();
1844 DECLARE_CONCRETE_INSTRUCTION(FixedArrayBaseLength)
1847 virtual bool DataEquals(HValue* other) { return true; }
1851 class HElementsKind: public HUnaryOperation {
1853 explicit HElementsKind(HValue* value) : HUnaryOperation(value) {
1854 set_representation(Representation::Integer32());
1856 SetGVNFlag(kDependsOnElementsKind);
1859 virtual Representation RequiredInputRepresentation(int index) {
1860 return Representation::Tagged();
1863 DECLARE_CONCRETE_INSTRUCTION(ElementsKind)
1866 virtual bool DataEquals(HValue* other) { return true; }
1870 class HBitNot: public HUnaryOperation {
1872 explicit HBitNot(HValue* value) : HUnaryOperation(value) {
1873 set_representation(Representation::Integer32());
1875 SetFlag(kTruncatingToInt32);
1878 virtual Representation RequiredInputRepresentation(int index) {
1879 return Representation::Integer32();
1881 virtual HType CalculateInferredType();
1883 DECLARE_CONCRETE_INSTRUCTION(BitNot)
1886 virtual bool DataEquals(HValue* other) { return true; }
1890 class HUnaryMathOperation: public HTemplateInstruction<2> {
1892 HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
1894 SetOperandAt(0, context);
1895 SetOperandAt(1, value);
1900 set_representation(Representation::Integer32());
1903 set_representation(Representation::Tagged());
1904 SetFlag(kFlexibleRepresentation);
1912 set_representation(Representation::Double());
1920 HValue* context() { return OperandAt(0); }
1921 HValue* value() { return OperandAt(1); }
1923 virtual void PrintDataTo(StringStream* stream);
1925 virtual HType CalculateInferredType();
1927 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
1929 virtual Representation RequiredInputRepresentation(int index) {
1931 return Representation::Tagged();
1943 return Representation::Double();
1945 return representation();
1948 return Representation::None();
1953 virtual HValue* Canonicalize() {
1954 // If the input is integer32 then we replace the floor instruction
1955 // with its inputs. This happens before the representation changes are
1957 if (op() == kMathFloor) {
1958 if (value()->representation().IsInteger32()) return value();
1963 BuiltinFunctionId op() const { return op_; }
1964 const char* OpName() const;
1966 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
1969 virtual bool DataEquals(HValue* other) {
1970 HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
1971 return op_ == b->op();
1975 BuiltinFunctionId op_;
1979 class HLoadElements: public HUnaryOperation {
1981 explicit HLoadElements(HValue* value) : HUnaryOperation(value) {
1982 set_representation(Representation::Tagged());
1984 SetGVNFlag(kDependsOnElementsPointer);
1987 virtual Representation RequiredInputRepresentation(int index) {
1988 return Representation::Tagged();
1991 DECLARE_CONCRETE_INSTRUCTION(LoadElements)
1994 virtual bool DataEquals(HValue* other) { return true; }
1998 class HLoadExternalArrayPointer: public HUnaryOperation {
2000 explicit HLoadExternalArrayPointer(HValue* value)
2001 : HUnaryOperation(value) {
2002 set_representation(Representation::External());
2003 // The result of this instruction is idempotent as long as its inputs don't
2004 // change. The external array of a specialized array elements object cannot
2005 // change once set, so it's no necessary to introduce any additional
2006 // dependencies on top of the inputs.
2010 virtual Representation RequiredInputRepresentation(int index) {
2011 return Representation::Tagged();
2014 DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer)
2017 virtual bool DataEquals(HValue* other) { return true; }
2021 class HCheckMaps: public HTemplateInstruction<2> {
2023 HCheckMaps(HValue* value, Handle<Map> map, HValue* typecheck = NULL) {
2024 SetOperandAt(0, value);
2025 // If callers don't depend on a typecheck, they can pass in NULL. In that
2026 // case we use a copy of the |value| argument as a dummy value.
2027 SetOperandAt(1, typecheck != NULL ? typecheck : value);
2028 set_representation(Representation::Tagged());
2030 SetGVNFlag(kDependsOnMaps);
2031 SetGVNFlag(kDependsOnElementsKind);
2032 map_set()->Add(map);
2034 HCheckMaps(HValue* value, SmallMapList* maps) {
2035 SetOperandAt(0, value);
2036 SetOperandAt(1, value);
2037 set_representation(Representation::Tagged());
2039 SetGVNFlag(kDependsOnMaps);
2040 SetGVNFlag(kDependsOnElementsKind);
2041 for (int i = 0; i < maps->length(); i++) {
2042 map_set()->Add(maps->at(i));
2047 static HCheckMaps* NewWithTransitions(HValue* object, Handle<Map> map) {
2048 HCheckMaps* check_map = new HCheckMaps(object, map);
2049 SmallMapList* map_set = check_map->map_set();
2051 // If the map to check has the untransitioned elements, it can be hoisted
2052 // above TransitionElements instructions.
2053 if (map->has_fast_smi_only_elements()) {
2054 check_map->ClearGVNFlag(kDependsOnElementsKind);
2057 Map* transitioned_fast_element_map =
2058 map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL);
2059 ASSERT(transitioned_fast_element_map == NULL ||
2060 map->elements_kind() != FAST_ELEMENTS);
2061 if (transitioned_fast_element_map != NULL) {
2062 map_set->Add(Handle<Map>(transitioned_fast_element_map));
2064 Map* transitioned_double_map =
2065 map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL);
2066 ASSERT(transitioned_double_map == NULL ||
2067 map->elements_kind() == FAST_SMI_ONLY_ELEMENTS);
2068 if (transitioned_double_map != NULL) {
2069 map_set->Add(Handle<Map>(transitioned_double_map));
2076 virtual Representation RequiredInputRepresentation(int index) {
2077 return Representation::Tagged();
2079 virtual void PrintDataTo(StringStream* stream);
2080 virtual HType CalculateInferredType();
2082 HValue* value() { return OperandAt(0); }
2083 SmallMapList* map_set() { return &map_set_; }
2085 DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
2088 virtual bool DataEquals(HValue* other) {
2089 HCheckMaps* b = HCheckMaps::cast(other);
2090 // Relies on the fact that map_set has been sorted before.
2091 if (map_set()->length() != b->map_set()->length()) return false;
2092 for (int i = 0; i < map_set()->length(); i++) {
2093 if (!map_set()->at(i).is_identical_to(b->map_set()->at(i))) return false;
2099 SmallMapList map_set_;
2103 class HCheckFunction: public HUnaryOperation {
2105 HCheckFunction(HValue* value, Handle<JSFunction> function)
2106 : HUnaryOperation(value), target_(function) {
2107 set_representation(Representation::Tagged());
2111 virtual Representation RequiredInputRepresentation(int index) {
2112 return Representation::Tagged();
2114 virtual void PrintDataTo(StringStream* stream);
2115 virtual HType CalculateInferredType();
2118 virtual void Verify();
2121 Handle<JSFunction> target() const { return target_; }
2123 DECLARE_CONCRETE_INSTRUCTION(CheckFunction)
2126 virtual bool DataEquals(HValue* other) {
2127 HCheckFunction* b = HCheckFunction::cast(other);
2128 return target_.is_identical_to(b->target());
2132 Handle<JSFunction> target_;
2136 class HCheckInstanceType: public HUnaryOperation {
2138 static HCheckInstanceType* NewIsSpecObject(HValue* value) {
2139 return new HCheckInstanceType(value, IS_SPEC_OBJECT);
2141 static HCheckInstanceType* NewIsJSArray(HValue* value) {
2142 return new HCheckInstanceType(value, IS_JS_ARRAY);
2144 static HCheckInstanceType* NewIsString(HValue* value) {
2145 return new HCheckInstanceType(value, IS_STRING);
2147 static HCheckInstanceType* NewIsSymbol(HValue* value) {
2148 return new HCheckInstanceType(value, IS_SYMBOL);
2151 virtual void PrintDataTo(StringStream* stream);
2153 virtual Representation RequiredInputRepresentation(int index) {
2154 return Representation::Tagged();
2157 virtual HValue* Canonicalize();
2159 bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
2160 void GetCheckInterval(InstanceType* first, InstanceType* last);
2161 void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
2163 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
2166 // TODO(ager): It could be nice to allow the ommision of instance
2167 // type checks if we have already performed an instance type check
2168 // with a larger range.
2169 virtual bool DataEquals(HValue* other) {
2170 HCheckInstanceType* b = HCheckInstanceType::cast(other);
2171 return check_ == b->check_;
2180 LAST_INTERVAL_CHECK = IS_JS_ARRAY
2183 const char* GetCheckName();
2185 HCheckInstanceType(HValue* value, Check check)
2186 : HUnaryOperation(value), check_(check) {
2187 set_representation(Representation::Tagged());
2195 class HCheckNonSmi: public HUnaryOperation {
2197 explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
2198 set_representation(Representation::Tagged());
2202 virtual Representation RequiredInputRepresentation(int index) {
2203 return Representation::Tagged();
2206 virtual HType CalculateInferredType();
2209 virtual void Verify();
2212 virtual HValue* Canonicalize() {
2213 HType value_type = value()->type();
2214 if (!value_type.IsUninitialized() &&
2215 (value_type.IsHeapNumber() ||
2216 value_type.IsString() ||
2217 value_type.IsBoolean() ||
2218 value_type.IsNonPrimitive())) {
2224 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi)
2227 virtual bool DataEquals(HValue* other) { return true; }
2231 class HCheckPrototypeMaps: public HTemplateInstruction<0> {
2233 HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder)
2234 : prototype_(prototype), holder_(holder) {
2236 SetGVNFlag(kDependsOnMaps);
2240 virtual void Verify();
2243 Handle<JSObject> prototype() const { return prototype_; }
2244 Handle<JSObject> holder() const { return holder_; }
2246 DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps)
2248 virtual Representation RequiredInputRepresentation(int index) {
2249 return Representation::None();
2252 virtual intptr_t Hashcode() {
2253 ASSERT(!HEAP->IsAllocationAllowed());
2254 intptr_t hash = reinterpret_cast<intptr_t>(*prototype());
2255 hash = 17 * hash + reinterpret_cast<intptr_t>(*holder());
2260 virtual bool DataEquals(HValue* other) {
2261 HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
2262 return prototype_.is_identical_to(b->prototype()) &&
2263 holder_.is_identical_to(b->holder());
2267 Handle<JSObject> prototype_;
2268 Handle<JSObject> holder_;
2272 class HCheckSmi: public HUnaryOperation {
2274 explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
2275 set_representation(Representation::Tagged());
2279 virtual Representation RequiredInputRepresentation(int index) {
2280 return Representation::Tagged();
2282 virtual HType CalculateInferredType();
2285 virtual void Verify();
2288 DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
2291 virtual bool DataEquals(HValue* other) { return true; }
2295 class HPhi: public HValue {
2297 explicit HPhi(int merged_index)
2299 merged_index_(merged_index),
2302 is_convertible_to_integer_(true) {
2303 for (int i = 0; i < Representation::kNumRepresentations; i++) {
2304 non_phi_uses_[i] = 0;
2305 indirect_uses_[i] = 0;
2307 ASSERT(merged_index >= 0);
2308 set_representation(Representation::Tagged());
2309 SetFlag(kFlexibleRepresentation);
2312 virtual Representation InferredRepresentation();
2314 virtual Range* InferRange(Zone* zone);
2315 virtual Representation RequiredInputRepresentation(int index) {
2316 return representation();
2318 virtual HType CalculateInferredType();
2319 virtual int OperandCount() { return inputs_.length(); }
2320 virtual HValue* OperandAt(int index) { return inputs_[index]; }
2321 HValue* GetRedundantReplacement();
2322 void AddInput(HValue* value);
2325 bool IsReceiver() { return merged_index_ == 0; }
2327 int merged_index() const { return merged_index_; }
2329 virtual void PrintTo(StringStream* stream);
2332 virtual void Verify();
2335 void InitRealUses(int id);
2336 void AddNonPhiUsesFrom(HPhi* other);
2337 void AddIndirectUsesTo(int* use_count);
2339 int tagged_non_phi_uses() const {
2340 return non_phi_uses_[Representation::kTagged];
2342 int int32_non_phi_uses() const {
2343 return non_phi_uses_[Representation::kInteger32];
2345 int double_non_phi_uses() const {
2346 return non_phi_uses_[Representation::kDouble];
2348 int tagged_indirect_uses() const {
2349 return indirect_uses_[Representation::kTagged];
2351 int int32_indirect_uses() const {
2352 return indirect_uses_[Representation::kInteger32];
2354 int double_indirect_uses() const {
2355 return indirect_uses_[Representation::kDouble];
2357 int phi_id() { return phi_id_; }
2358 bool is_live() { return is_live_; }
2359 void set_is_live(bool b) { is_live_ = b; }
2361 static HPhi* cast(HValue* value) {
2362 ASSERT(value->IsPhi());
2363 return reinterpret_cast<HPhi*>(value);
2365 virtual Opcode opcode() const { return HValue::kPhi; }
2367 virtual bool IsConvertibleToInteger() const {
2368 return is_convertible_to_integer_;
2371 void set_is_convertible_to_integer(bool b) {
2372 is_convertible_to_integer_ = b;
2375 bool AllOperandsConvertibleToInteger() {
2376 for (int i = 0; i < OperandCount(); ++i) {
2377 if (!OperandAt(i)->IsConvertibleToInteger()) return false;
2383 virtual void DeleteFromGraph();
2384 virtual void InternalSetOperandAt(int index, HValue* value) {
2385 inputs_[index] = value;
2389 ZoneList<HValue*> inputs_;
2392 int non_phi_uses_[Representation::kNumRepresentations];
2393 int indirect_uses_[Representation::kNumRepresentations];
2396 bool is_convertible_to_integer_;
2400 class HArgumentsObject: public HTemplateInstruction<0> {
2402 HArgumentsObject() {
2403 set_representation(Representation::Tagged());
2404 SetFlag(kIsArguments);
2407 virtual Representation RequiredInputRepresentation(int index) {
2408 return Representation::None();
2411 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
2415 class HConstant: public HTemplateInstruction<0> {
2417 HConstant(Handle<Object> handle, Representation r);
2419 Handle<Object> handle() const { return handle_; }
2421 bool InOldSpace() const { return !HEAP->InNewSpace(*handle_); }
2423 bool ImmortalImmovable() const {
2425 if (*handle_ == heap->undefined_value()) return true;
2426 if (*handle_ == heap->null_value()) return true;
2427 if (*handle_ == heap->true_value()) return true;
2428 if (*handle_ == heap->false_value()) return true;
2429 if (*handle_ == heap->the_hole_value()) return true;
2430 if (*handle_ == heap->minus_zero_value()) return true;
2431 if (*handle_ == heap->nan_value()) return true;
2432 if (*handle_ == heap->empty_string()) return true;
2436 virtual Representation RequiredInputRepresentation(int index) {
2437 return Representation::None();
2440 virtual bool IsConvertibleToInteger() const {
2441 if (handle_->IsSmi()) return true;
2442 if (handle_->IsHeapNumber() &&
2443 (HeapNumber::cast(*handle_)->value() ==
2444 static_cast<double>(NumberToInt32(*handle_)))) return true;
2448 virtual bool EmitAtUses() { return !representation().IsDouble(); }
2449 virtual HValue* Canonicalize();
2450 virtual void PrintDataTo(StringStream* stream);
2451 virtual HType CalculateInferredType();
2452 bool IsInteger() const { return handle_->IsSmi(); }
2453 HConstant* CopyToRepresentation(Representation r) const;
2454 HConstant* CopyToTruncatedInt32() const;
2455 bool HasInteger32Value() const { return has_int32_value_; }
2456 int32_t Integer32Value() const {
2457 ASSERT(HasInteger32Value());
2458 return int32_value_;
2460 bool HasDoubleValue() const { return has_double_value_; }
2461 double DoubleValue() const {
2462 ASSERT(HasDoubleValue());
2463 return double_value_;
2465 bool HasNumberValue() const { return has_int32_value_ || has_double_value_; }
2466 int32_t NumberValueAsInteger32() const {
2467 ASSERT(HasNumberValue());
2468 if (has_int32_value_) return int32_value_;
2469 return DoubleToInt32(double_value_);
2471 bool HasStringValue() const { return handle_->IsString(); }
2473 bool ToBoolean() const;
2475 virtual intptr_t Hashcode() {
2476 ASSERT(!HEAP->allow_allocation(false));
2477 intptr_t hash = reinterpret_cast<intptr_t>(*handle());
2478 // Prevent smis from having fewer hash values when truncated to
2479 // the least significant bits.
2480 const int kShiftSize = kSmiShiftSize + kSmiTagSize;
2481 STATIC_ASSERT(kShiftSize != 0);
2482 return hash ^ (hash >> kShiftSize);
2486 virtual void Verify() { }
2489 DECLARE_CONCRETE_INSTRUCTION(Constant)
2492 virtual Range* InferRange(Zone* zone);
2494 virtual bool DataEquals(HValue* other) {
2495 HConstant* other_constant = HConstant::cast(other);
2496 return handle().is_identical_to(other_constant->handle());
2500 Handle<Object> handle_;
2502 // The following two values represent the int32 and the double value of the
2503 // given constant if there is a lossless conversion between the constant
2504 // and the specific representation.
2505 bool has_int32_value_ : 1;
2506 bool has_double_value_ : 1;
2507 int32_t int32_value_;
2508 double double_value_;
2512 class HBinaryOperation: public HTemplateInstruction<3> {
2514 HBinaryOperation(HValue* context, HValue* left, HValue* right) {
2515 ASSERT(left != NULL && right != NULL);
2516 SetOperandAt(0, context);
2517 SetOperandAt(1, left);
2518 SetOperandAt(2, right);
2521 HValue* context() { return OperandAt(0); }
2522 HValue* left() { return OperandAt(1); }
2523 HValue* right() { return OperandAt(2); }
2525 // TODO(kasperl): Move these helpers to the IA-32 Lithium
2526 // instruction sequence builder.
2527 HValue* LeastConstantOperand() {
2528 if (IsCommutative() && left()->IsConstant()) return right();
2531 HValue* MostConstantOperand() {
2532 if (IsCommutative() && left()->IsConstant()) return left();
2536 virtual bool IsCommutative() const { return false; }
2538 virtual void PrintDataTo(StringStream* stream);
2542 class HWrapReceiver: public HTemplateInstruction<2> {
2544 HWrapReceiver(HValue* receiver, HValue* function) {
2545 set_representation(Representation::Tagged());
2546 SetOperandAt(0, receiver);
2547 SetOperandAt(1, function);
2550 virtual Representation RequiredInputRepresentation(int index) {
2551 return Representation::Tagged();
2554 HValue* receiver() { return OperandAt(0); }
2555 HValue* function() { return OperandAt(1); }
2557 virtual HValue* Canonicalize();
2559 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
2563 class HApplyArguments: public HTemplateInstruction<4> {
2565 HApplyArguments(HValue* function,
2569 set_representation(Representation::Tagged());
2570 SetOperandAt(0, function);
2571 SetOperandAt(1, receiver);
2572 SetOperandAt(2, length);
2573 SetOperandAt(3, elements);
2574 SetAllSideEffects();
2577 virtual Representation RequiredInputRepresentation(int index) {
2578 // The length is untagged, all other inputs are tagged.
2580 ? Representation::Integer32()
2581 : Representation::Tagged();
2584 HValue* function() { return OperandAt(0); }
2585 HValue* receiver() { return OperandAt(1); }
2586 HValue* length() { return OperandAt(2); }
2587 HValue* elements() { return OperandAt(3); }
2589 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
2593 class HArgumentsElements: public HTemplateInstruction<0> {
2595 HArgumentsElements() {
2596 // The value produced by this instruction is a pointer into the stack
2597 // that looks as if it was a smi because of alignment.
2598 set_representation(Representation::Tagged());
2602 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
2604 virtual Representation RequiredInputRepresentation(int index) {
2605 return Representation::None();
2609 virtual bool DataEquals(HValue* other) { return true; }
2613 class HArgumentsLength: public HUnaryOperation {
2615 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
2616 set_representation(Representation::Integer32());
2620 virtual Representation RequiredInputRepresentation(int index) {
2621 return Representation::Tagged();
2624 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
2627 virtual bool DataEquals(HValue* other) { return true; }
2631 class HAccessArgumentsAt: public HTemplateInstruction<3> {
2633 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
2634 set_representation(Representation::Tagged());
2636 SetOperandAt(0, arguments);
2637 SetOperandAt(1, length);
2638 SetOperandAt(2, index);
2641 virtual void PrintDataTo(StringStream* stream);
2643 virtual Representation RequiredInputRepresentation(int index) {
2644 // The arguments elements is considered tagged.
2646 ? Representation::Tagged()
2647 : Representation::Integer32();
2650 HValue* arguments() { return OperandAt(0); }
2651 HValue* length() { return OperandAt(1); }
2652 HValue* index() { return OperandAt(2); }
2654 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
2656 virtual bool DataEquals(HValue* other) { return true; }
2660 class HBoundsCheck: public HTemplateInstruction<2> {
2662 HBoundsCheck(HValue* index, HValue* length) {
2663 SetOperandAt(0, index);
2664 SetOperandAt(1, length);
2665 set_representation(Representation::Integer32());
2669 virtual Representation RequiredInputRepresentation(int index) {
2670 return Representation::Integer32();
2673 virtual void PrintDataTo(StringStream* stream);
2675 HValue* index() { return OperandAt(0); }
2676 HValue* length() { return OperandAt(1); }
2678 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
2681 virtual bool DataEquals(HValue* other) { return true; }
2685 class HBitwiseBinaryOperation: public HBinaryOperation {
2687 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right)
2688 : HBinaryOperation(context, left, right) {
2689 set_representation(Representation::Tagged());
2690 SetFlag(kFlexibleRepresentation);
2691 SetAllSideEffects();
2694 virtual Representation RequiredInputRepresentation(int index) {
2696 ? Representation::Tagged()
2700 virtual void RepresentationChanged(Representation to) {
2701 if (!to.IsTagged()) {
2702 ASSERT(to.IsInteger32());
2703 ClearAllSideEffects();
2704 SetFlag(kTruncatingToInt32);
2709 virtual HType CalculateInferredType();
2711 DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
2715 class HArithmeticBinaryOperation: public HBinaryOperation {
2717 HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right)
2718 : HBinaryOperation(context, left, right) {
2719 set_representation(Representation::Tagged());
2720 SetFlag(kFlexibleRepresentation);
2721 SetAllSideEffects();
2724 virtual void RepresentationChanged(Representation to) {
2725 if (!to.IsTagged()) {
2726 ClearAllSideEffects();
2731 virtual HType CalculateInferredType();
2732 virtual Representation RequiredInputRepresentation(int index) {
2734 ? Representation::Tagged()
2738 virtual Representation InferredRepresentation() {
2739 if (left()->representation().Equals(right()->representation())) {
2740 return left()->representation();
2742 return HValue::InferredRepresentation();
2747 class HCompareGeneric: public HBinaryOperation {
2749 HCompareGeneric(HValue* context,
2753 : HBinaryOperation(context, left, right), token_(token) {
2754 ASSERT(Token::IsCompareOp(token));
2755 set_representation(Representation::Tagged());
2756 SetAllSideEffects();
2759 virtual Representation RequiredInputRepresentation(int index) {
2760 return Representation::Tagged();
2763 Representation GetInputRepresentation() const {
2764 return Representation::Tagged();
2767 Token::Value token() const { return token_; }
2768 virtual void PrintDataTo(StringStream* stream);
2770 virtual HType CalculateInferredType();
2772 DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
2775 Token::Value token_;
2779 class HCompareIDAndBranch: public HTemplateControlInstruction<2, 2> {
2781 HCompareIDAndBranch(HValue* left, HValue* right, Token::Value token)
2783 ASSERT(Token::IsCompareOp(token));
2784 SetOperandAt(0, left);
2785 SetOperandAt(1, right);
2788 HValue* left() { return OperandAt(0); }
2789 HValue* right() { return OperandAt(1); }
2790 Token::Value token() const { return token_; }
2792 void SetInputRepresentation(Representation r);
2793 Representation GetInputRepresentation() const {
2794 return input_representation_;
2797 virtual Representation RequiredInputRepresentation(int index) {
2798 return input_representation_;
2800 virtual void PrintDataTo(StringStream* stream);
2802 DECLARE_CONCRETE_INSTRUCTION(CompareIDAndBranch)
2805 Representation input_representation_;
2806 Token::Value token_;
2810 class HCompareObjectEqAndBranch: public HTemplateControlInstruction<2, 2> {
2812 HCompareObjectEqAndBranch(HValue* left, HValue* right) {
2813 SetOperandAt(0, left);
2814 SetOperandAt(1, right);
2817 HValue* left() { return OperandAt(0); }
2818 HValue* right() { return OperandAt(1); }
2820 virtual void PrintDataTo(StringStream* stream);
2822 virtual Representation RequiredInputRepresentation(int index) {
2823 return Representation::Tagged();
2826 DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
2830 class HCompareConstantEqAndBranch: public HUnaryControlInstruction {
2832 HCompareConstantEqAndBranch(HValue* left, int right, Token::Value op)
2833 : HUnaryControlInstruction(left, NULL, NULL), op_(op), right_(right) {
2834 ASSERT(op == Token::EQ_STRICT);
2837 Token::Value op() const { return op_; }
2838 HValue* left() { return value(); }
2839 int right() const { return right_; }
2841 virtual Representation RequiredInputRepresentation(int index) {
2842 return Representation::Integer32();
2845 DECLARE_CONCRETE_INSTRUCTION(CompareConstantEqAndBranch);
2848 const Token::Value op_;
2853 class HIsNilAndBranch: public HUnaryControlInstruction {
2855 HIsNilAndBranch(HValue* value, EqualityKind kind, NilValue nil)
2856 : HUnaryControlInstruction(value, NULL, NULL), kind_(kind), nil_(nil) { }
2858 EqualityKind kind() const { return kind_; }
2859 NilValue nil() const { return nil_; }
2861 virtual void PrintDataTo(StringStream* stream);
2863 virtual Representation RequiredInputRepresentation(int index) {
2864 return Representation::Tagged();
2867 DECLARE_CONCRETE_INSTRUCTION(IsNilAndBranch)
2875 class HIsObjectAndBranch: public HUnaryControlInstruction {
2877 explicit HIsObjectAndBranch(HValue* value)
2878 : HUnaryControlInstruction(value, NULL, NULL) { }
2880 virtual Representation RequiredInputRepresentation(int index) {
2881 return Representation::Tagged();
2884 DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch)
2887 class HIsStringAndBranch: public HUnaryControlInstruction {
2889 explicit HIsStringAndBranch(HValue* value)
2890 : HUnaryControlInstruction(value, NULL, NULL) { }
2892 virtual Representation RequiredInputRepresentation(int index) {
2893 return Representation::Tagged();
2896 DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
2900 class HIsSmiAndBranch: public HUnaryControlInstruction {
2902 explicit HIsSmiAndBranch(HValue* value)
2903 : HUnaryControlInstruction(value, NULL, NULL) { }
2905 DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
2907 virtual Representation RequiredInputRepresentation(int index) {
2908 return Representation::Tagged();
2912 virtual bool DataEquals(HValue* other) { return true; }
2916 class HIsUndetectableAndBranch: public HUnaryControlInstruction {
2918 explicit HIsUndetectableAndBranch(HValue* value)
2919 : HUnaryControlInstruction(value, NULL, NULL) { }
2921 virtual Representation RequiredInputRepresentation(int index) {
2922 return Representation::Tagged();
2925 DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
2929 class HStringCompareAndBranch: public HTemplateControlInstruction<2, 3> {
2931 HStringCompareAndBranch(HValue* context,
2936 ASSERT(Token::IsCompareOp(token));
2937 SetOperandAt(0, context);
2938 SetOperandAt(1, left);
2939 SetOperandAt(2, right);
2940 set_representation(Representation::Tagged());
2943 HValue* context() { return OperandAt(0); }
2944 HValue* left() { return OperandAt(1); }
2945 HValue* right() { return OperandAt(2); }
2946 Token::Value token() const { return token_; }
2948 virtual void PrintDataTo(StringStream* stream);
2950 virtual Representation RequiredInputRepresentation(int index) {
2951 return Representation::Tagged();
2954 Representation GetInputRepresentation() const {
2955 return Representation::Tagged();
2958 DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
2961 Token::Value token_;
2965 class HIsConstructCallAndBranch: public HTemplateControlInstruction<2, 0> {
2967 virtual Representation RequiredInputRepresentation(int index) {
2968 return Representation::None();
2971 DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch)
2975 class HHasInstanceTypeAndBranch: public HUnaryControlInstruction {
2977 HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
2978 : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
2979 HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
2980 : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
2981 ASSERT(to == LAST_TYPE); // Others not implemented yet in backend.
2984 InstanceType from() { return from_; }
2985 InstanceType to() { return to_; }
2987 virtual void PrintDataTo(StringStream* stream);
2989 virtual Representation RequiredInputRepresentation(int index) {
2990 return Representation::Tagged();
2993 DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
2997 InstanceType to_; // Inclusive range, not all combinations work.
3001 class HHasCachedArrayIndexAndBranch: public HUnaryControlInstruction {
3003 explicit HHasCachedArrayIndexAndBranch(HValue* value)
3004 : HUnaryControlInstruction(value, NULL, NULL) { }
3006 virtual Representation RequiredInputRepresentation(int index) {
3007 return Representation::Tagged();
3010 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
3014 class HGetCachedArrayIndex: public HUnaryOperation {
3016 explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
3017 set_representation(Representation::Tagged());
3021 virtual Representation RequiredInputRepresentation(int index) {
3022 return Representation::Tagged();
3025 DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
3028 virtual bool DataEquals(HValue* other) { return true; }
3032 class HClassOfTestAndBranch: public HUnaryControlInstruction {
3034 HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
3035 : HUnaryControlInstruction(value, NULL, NULL),
3036 class_name_(class_name) { }
3038 DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
3040 virtual Representation RequiredInputRepresentation(int index) {
3041 return Representation::Tagged();
3044 virtual void PrintDataTo(StringStream* stream);
3046 Handle<String> class_name() const { return class_name_; }
3049 Handle<String> class_name_;
3053 class HTypeofIsAndBranch: public HUnaryControlInstruction {
3055 HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
3056 : HUnaryControlInstruction(value, NULL, NULL),
3057 type_literal_(type_literal) { }
3059 Handle<String> type_literal() { return type_literal_; }
3060 virtual void PrintDataTo(StringStream* stream);
3062 DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
3064 virtual Representation RequiredInputRepresentation(int index) {
3065 return Representation::Tagged();
3069 Handle<String> type_literal_;
3073 class HInstanceOf: public HBinaryOperation {
3075 HInstanceOf(HValue* context, HValue* left, HValue* right)
3076 : HBinaryOperation(context, left, right) {
3077 set_representation(Representation::Tagged());
3078 SetAllSideEffects();
3081 virtual Representation RequiredInputRepresentation(int index) {
3082 return Representation::Tagged();
3085 virtual HType CalculateInferredType();
3087 virtual void PrintDataTo(StringStream* stream);
3089 DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
3093 class HInstanceOfKnownGlobal: public HTemplateInstruction<2> {
3095 HInstanceOfKnownGlobal(HValue* context,
3097 Handle<JSFunction> right)
3098 : function_(right) {
3099 SetOperandAt(0, context);
3100 SetOperandAt(1, left);
3101 set_representation(Representation::Tagged());
3102 SetAllSideEffects();
3105 HValue* context() { return OperandAt(0); }
3106 HValue* left() { return OperandAt(1); }
3107 Handle<JSFunction> function() { return function_; }
3109 virtual Representation RequiredInputRepresentation(int index) {
3110 return Representation::Tagged();
3113 virtual HType CalculateInferredType();
3115 DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal)
3118 Handle<JSFunction> function_;
3122 class HPower: public HTemplateInstruction<2> {
3124 HPower(HValue* left, HValue* right) {
3125 SetOperandAt(0, left);
3126 SetOperandAt(1, right);
3127 set_representation(Representation::Double());
3131 HValue* left() { return OperandAt(0); }
3132 HValue* right() { return OperandAt(1); }
3134 virtual Representation RequiredInputRepresentation(int index) {
3136 ? Representation::Double()
3137 : Representation::None();
3140 DECLARE_CONCRETE_INSTRUCTION(Power)
3143 virtual bool DataEquals(HValue* other) { return true; }
3147 class HRandom: public HTemplateInstruction<1> {
3149 explicit HRandom(HValue* global_object) {
3150 SetOperandAt(0, global_object);
3151 set_representation(Representation::Double());
3154 HValue* global_object() { return OperandAt(0); }
3156 virtual Representation RequiredInputRepresentation(int index) {
3157 return Representation::Tagged();
3160 DECLARE_CONCRETE_INSTRUCTION(Random)
3164 class HAdd: public HArithmeticBinaryOperation {
3166 HAdd(HValue* context, HValue* left, HValue* right)
3167 : HArithmeticBinaryOperation(context, left, right) {
3168 SetFlag(kCanOverflow);
3171 // Add is only commutative if two integer values are added and not if two
3172 // tagged values are added (because it might be a String concatenation).
3173 virtual bool IsCommutative() const {
3174 return !representation().IsTagged();
3177 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3179 static HInstruction* NewHAdd(Zone* zone,
3184 virtual HType CalculateInferredType();
3186 virtual HValue* Canonicalize();
3188 DECLARE_CONCRETE_INSTRUCTION(Add)
3191 virtual bool DataEquals(HValue* other) { return true; }
3193 virtual Range* InferRange(Zone* zone);
3197 class HSub: public HArithmeticBinaryOperation {
3199 HSub(HValue* context, HValue* left, HValue* right)
3200 : HArithmeticBinaryOperation(context, left, right) {
3201 SetFlag(kCanOverflow);
3204 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3206 virtual HValue* Canonicalize();
3208 static HInstruction* NewHSub(Zone* zone,
3213 DECLARE_CONCRETE_INSTRUCTION(Sub)
3216 virtual bool DataEquals(HValue* other) { return true; }
3218 virtual Range* InferRange(Zone* zone);
3222 class HMul: public HArithmeticBinaryOperation {
3224 HMul(HValue* context, HValue* left, HValue* right)
3225 : HArithmeticBinaryOperation(context, left, right) {
3226 SetFlag(kCanOverflow);
3229 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3231 // Only commutative if it is certain that not two objects are multiplicated.
3232 virtual bool IsCommutative() const {
3233 return !representation().IsTagged();
3236 static HInstruction* NewHMul(Zone* zone,
3241 DECLARE_CONCRETE_INSTRUCTION(Mul)
3244 virtual bool DataEquals(HValue* other) { return true; }
3246 virtual Range* InferRange(Zone* zone);
3250 class HMod: public HArithmeticBinaryOperation {
3252 HMod(HValue* context, HValue* left, HValue* right)
3253 : HArithmeticBinaryOperation(context, left, right) {
3254 SetFlag(kCanBeDivByZero);
3257 bool HasPowerOf2Divisor() {
3258 if (right()->IsConstant() &&
3259 HConstant::cast(right())->HasInteger32Value()) {
3260 int32_t value = HConstant::cast(right())->Integer32Value();
3261 return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
3267 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3269 static HInstruction* NewHMod(Zone* zone,
3274 DECLARE_CONCRETE_INSTRUCTION(Mod)
3277 virtual bool DataEquals(HValue* other) { return true; }
3279 virtual Range* InferRange(Zone* zone);
3283 class HDiv: public HArithmeticBinaryOperation {
3285 HDiv(HValue* context, HValue* left, HValue* right)
3286 : HArithmeticBinaryOperation(context, left, right) {
3287 SetFlag(kCanBeDivByZero);
3288 SetFlag(kCanOverflow);
3291 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
3293 static HInstruction* NewHDiv(Zone* zone,
3298 DECLARE_CONCRETE_INSTRUCTION(Div)
3301 virtual bool DataEquals(HValue* other) { return true; }
3303 virtual Range* InferRange(Zone* zone);
3307 class HBitwise: public HBitwiseBinaryOperation {
3309 HBitwise(Token::Value op, HValue* context, HValue* left, HValue* right)
3310 : HBitwiseBinaryOperation(context, left, right), op_(op) {
3311 ASSERT(op == Token::BIT_AND ||
3312 op == Token::BIT_OR ||
3313 op == Token::BIT_XOR);
3316 Token::Value op() const { return op_; }
3318 virtual bool IsCommutative() const { return true; }
3320 virtual HValue* Canonicalize();
3322 static HInstruction* NewHBitwise(Zone* zone,
3328 DECLARE_CONCRETE_INSTRUCTION(Bitwise)
3331 virtual bool DataEquals(HValue* other) {
3332 return op() == HBitwise::cast(other)->op();
3335 virtual Range* InferRange(Zone* zone);
3342 class HShl: public HBitwiseBinaryOperation {
3344 HShl(HValue* context, HValue* left, HValue* right)
3345 : HBitwiseBinaryOperation(context, left, right) { }
3347 virtual Range* InferRange(Zone* zone);
3349 static HInstruction* NewHShl(Zone* zone,
3354 DECLARE_CONCRETE_INSTRUCTION(Shl)
3357 virtual bool DataEquals(HValue* other) { return true; }
3361 class HShr: public HBitwiseBinaryOperation {
3363 HShr(HValue* context, HValue* left, HValue* right)
3364 : HBitwiseBinaryOperation(context, left, right) { }
3366 virtual Range* InferRange(Zone* zone);
3368 static HInstruction* NewHShr(Zone* zone,
3373 DECLARE_CONCRETE_INSTRUCTION(Shr)
3376 virtual bool DataEquals(HValue* other) { return true; }
3380 class HSar: public HBitwiseBinaryOperation {
3382 HSar(HValue* context, HValue* left, HValue* right)
3383 : HBitwiseBinaryOperation(context, left, right) { }
3385 virtual Range* InferRange(Zone* zone);
3387 static HInstruction* NewHSar(Zone* zone,
3392 DECLARE_CONCRETE_INSTRUCTION(Sar)
3395 virtual bool DataEquals(HValue* other) { return true; }
3399 class HOsrEntry: public HTemplateInstruction<0> {
3401 explicit HOsrEntry(int ast_id) : ast_id_(ast_id) {
3402 SetGVNFlag(kChangesOsrEntries);
3405 int ast_id() const { return ast_id_; }
3407 virtual Representation RequiredInputRepresentation(int index) {
3408 return Representation::None();
3411 DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
3418 class HParameter: public HTemplateInstruction<0> {
3420 explicit HParameter(unsigned index) : index_(index) {
3421 set_representation(Representation::Tagged());
3424 unsigned index() const { return index_; }
3426 virtual void PrintDataTo(StringStream* stream);
3428 virtual Representation RequiredInputRepresentation(int index) {
3429 return Representation::None();
3432 DECLARE_CONCRETE_INSTRUCTION(Parameter)
3439 class HCallStub: public HUnaryCall {
3441 HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
3442 : HUnaryCall(context, argument_count),
3443 major_key_(major_key),
3444 transcendental_type_(TranscendentalCache::kNumberOfCaches) {
3447 CodeStub::Major major_key() { return major_key_; }
3449 HValue* context() { return value(); }
3451 void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
3452 transcendental_type_ = transcendental_type;
3454 TranscendentalCache::Type transcendental_type() {
3455 return transcendental_type_;
3458 virtual void PrintDataTo(StringStream* stream);
3460 virtual Representation RequiredInputRepresentation(int index) {
3461 return Representation::Tagged();
3464 DECLARE_CONCRETE_INSTRUCTION(CallStub)
3467 CodeStub::Major major_key_;
3468 TranscendentalCache::Type transcendental_type_;
3472 class HUnknownOSRValue: public HTemplateInstruction<0> {
3475 : incoming_value_(NULL) {
3476 set_representation(Representation::Tagged());
3479 virtual Representation RequiredInputRepresentation(int index) {
3480 return Representation::None();
3483 void set_incoming_value(HPhi* value) {
3484 incoming_value_ = value;
3487 HPhi* incoming_value() {
3488 return incoming_value_;
3491 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
3494 HPhi* incoming_value_;
3498 class HLoadGlobalCell: public HTemplateInstruction<0> {
3500 HLoadGlobalCell(Handle<JSGlobalPropertyCell> cell, PropertyDetails details)
3501 : cell_(cell), details_(details) {
3502 set_representation(Representation::Tagged());
3504 SetGVNFlag(kDependsOnGlobalVars);
3507 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
3508 bool RequiresHoleCheck();
3510 virtual void PrintDataTo(StringStream* stream);
3512 virtual intptr_t Hashcode() {
3513 ASSERT(!HEAP->allow_allocation(false));
3514 return reinterpret_cast<intptr_t>(*cell_);
3517 virtual Representation RequiredInputRepresentation(int index) {
3518 return Representation::None();
3521 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell)
3524 virtual bool DataEquals(HValue* other) {
3525 HLoadGlobalCell* b = HLoadGlobalCell::cast(other);
3526 return cell_.is_identical_to(b->cell());
3530 Handle<JSGlobalPropertyCell> cell_;
3531 PropertyDetails details_;
3535 class HLoadGlobalGeneric: public HTemplateInstruction<2> {
3537 HLoadGlobalGeneric(HValue* context,
3538 HValue* global_object,
3539 Handle<Object> name,
3542 for_typeof_(for_typeof) {
3543 SetOperandAt(0, context);
3544 SetOperandAt(1, global_object);
3545 set_representation(Representation::Tagged());
3546 SetAllSideEffects();
3549 HValue* context() { return OperandAt(0); }
3550 HValue* global_object() { return OperandAt(1); }
3551 Handle<Object> name() const { return name_; }
3552 bool for_typeof() const { return for_typeof_; }
3554 virtual void PrintDataTo(StringStream* stream);
3556 virtual Representation RequiredInputRepresentation(int index) {
3557 return Representation::Tagged();
3560 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
3563 Handle<Object> name_;
3568 inline bool StoringValueNeedsWriteBarrier(HValue* value) {
3569 return !value->type().IsBoolean()
3570 && !value->type().IsSmi()
3571 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
3575 class HStoreGlobalCell: public HUnaryOperation {
3577 HStoreGlobalCell(HValue* value,
3578 Handle<JSGlobalPropertyCell> cell,
3579 PropertyDetails details)
3580 : HUnaryOperation(value),
3583 SetGVNFlag(kChangesGlobalVars);
3586 Handle<JSGlobalPropertyCell> cell() const { return cell_; }
3587 bool RequiresHoleCheck() {
3588 return !details_.IsDontDelete() || details_.IsReadOnly();
3590 bool NeedsWriteBarrier() {
3591 return StoringValueNeedsWriteBarrier(value());
3594 virtual Representation RequiredInputRepresentation(int index) {
3595 return Representation::Tagged();
3597 virtual void PrintDataTo(StringStream* stream);
3599 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell)
3602 Handle<JSGlobalPropertyCell> cell_;
3603 PropertyDetails details_;
3607 class HStoreGlobalGeneric: public HTemplateInstruction<3> {
3609 HStoreGlobalGeneric(HValue* context,
3610 HValue* global_object,
3611 Handle<Object> name,
3613 StrictModeFlag strict_mode_flag)
3615 strict_mode_flag_(strict_mode_flag) {
3616 SetOperandAt(0, context);
3617 SetOperandAt(1, global_object);
3618 SetOperandAt(2, value);
3619 set_representation(Representation::Tagged());
3620 SetAllSideEffects();
3623 HValue* context() { return OperandAt(0); }
3624 HValue* global_object() { return OperandAt(1); }
3625 Handle<Object> name() const { return name_; }
3626 HValue* value() { return OperandAt(2); }
3627 StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
3629 virtual void PrintDataTo(StringStream* stream);
3631 virtual Representation RequiredInputRepresentation(int index) {
3632 return Representation::Tagged();
3635 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric)
3638 Handle<Object> name_;
3639 StrictModeFlag strict_mode_flag_;
3643 class HLoadContextSlot: public HUnaryOperation {
3646 // Perform a normal load of the context slot without checking its value.
3648 // Load and check the value of the context slot. Deoptimize if it's the
3649 // hole value. This is used for checking for loading of uninitialized
3650 // harmony bindings where we deoptimize into full-codegen generated code
3651 // which will subsequently throw a reference error.
3653 // Load and check the value of the context slot. Return undefined if it's
3654 // the hole value. This is used for non-harmony const assignments
3655 kCheckReturnUndefined
3658 HLoadContextSlot(HValue* context, Variable* var)
3659 : HUnaryOperation(context), slot_index_(var->index()) {
3660 ASSERT(var->IsContextSlot());
3661 switch (var->mode()) {
3664 mode_ = kCheckDeoptimize;
3667 mode_ = kCheckReturnUndefined;
3672 set_representation(Representation::Tagged());
3674 SetGVNFlag(kDependsOnContextSlots);
3677 int slot_index() const { return slot_index_; }
3678 Mode mode() const { return mode_; }
3680 bool DeoptimizesOnHole() {
3681 return mode_ == kCheckDeoptimize;
3684 bool RequiresHoleCheck() {
3685 return mode_ != kNoCheck;
3688 virtual Representation RequiredInputRepresentation(int index) {
3689 return Representation::Tagged();
3692 virtual void PrintDataTo(StringStream* stream);
3694 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
3697 virtual bool DataEquals(HValue* other) {
3698 HLoadContextSlot* b = HLoadContextSlot::cast(other);
3699 return (slot_index() == b->slot_index());
3708 class HStoreContextSlot: public HTemplateInstruction<2> {
3711 // Perform a normal store to the context slot without checking its previous
3714 // Check the previous value of the context slot and deoptimize if it's the
3715 // hole value. This is used for checking for assignments to uninitialized
3716 // harmony bindings where we deoptimize into full-codegen generated code
3717 // which will subsequently throw a reference error.
3719 // Check the previous value and ignore assignment if it isn't a hole value
3720 kCheckIgnoreAssignment
3723 HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
3724 : slot_index_(slot_index), mode_(mode) {
3725 SetOperandAt(0, context);
3726 SetOperandAt(1, value);
3727 SetGVNFlag(kChangesContextSlots);
3730 HValue* context() { return OperandAt(0); }
3731 HValue* value() { return OperandAt(1); }
3732 int slot_index() const { return slot_index_; }
3733 Mode mode() const { return mode_; }
3735 bool NeedsWriteBarrier() {
3736 return StoringValueNeedsWriteBarrier(value());
3739 bool DeoptimizesOnHole() {
3740 return mode_ == kCheckDeoptimize;
3743 bool RequiresHoleCheck() {
3744 return mode_ != kNoCheck;
3747 virtual Representation RequiredInputRepresentation(int index) {
3748 return Representation::Tagged();
3751 virtual void PrintDataTo(StringStream* stream);
3753 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
3761 class HLoadNamedField: public HUnaryOperation {
3763 HLoadNamedField(HValue* object, bool is_in_object, int offset)
3764 : HUnaryOperation(object),
3765 is_in_object_(is_in_object),
3767 set_representation(Representation::Tagged());
3769 SetGVNFlag(kDependsOnMaps);
3771 SetGVNFlag(kDependsOnInobjectFields);
3773 SetGVNFlag(kDependsOnBackingStoreFields);
3777 HValue* object() { return OperandAt(0); }
3778 bool is_in_object() const { return is_in_object_; }
3779 int offset() const { return offset_; }
3781 virtual Representation RequiredInputRepresentation(int index) {
3782 return Representation::Tagged();
3784 virtual void PrintDataTo(StringStream* stream);
3786 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
3789 virtual bool DataEquals(HValue* other) {
3790 HLoadNamedField* b = HLoadNamedField::cast(other);
3791 return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
3800 class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
3802 HLoadNamedFieldPolymorphic(HValue* context,
3804 SmallMapList* types,
3805 Handle<String> name);
3807 HValue* context() { return OperandAt(0); }
3808 HValue* object() { return OperandAt(1); }
3809 SmallMapList* types() { return &types_; }
3810 Handle<String> name() { return name_; }
3811 bool need_generic() { return need_generic_; }
3813 virtual Representation RequiredInputRepresentation(int index) {
3814 return Representation::Tagged();
3817 virtual void PrintDataTo(StringStream* stream);
3819 DECLARE_CONCRETE_INSTRUCTION(LoadNamedFieldPolymorphic)
3821 static const int kMaxLoadPolymorphism = 4;
3824 virtual bool DataEquals(HValue* value);
3827 SmallMapList types_;
3828 Handle<String> name_;
3834 class HLoadNamedGeneric: public HTemplateInstruction<2> {
3836 HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
3838 SetOperandAt(0, context);
3839 SetOperandAt(1, object);
3840 set_representation(Representation::Tagged());
3841 SetAllSideEffects();
3844 HValue* context() { return OperandAt(0); }
3845 HValue* object() { return OperandAt(1); }
3846 Handle<Object> name() const { return name_; }
3848 virtual Representation RequiredInputRepresentation(int index) {
3849 return Representation::Tagged();
3852 virtual void PrintDataTo(StringStream* stream);
3854 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
3857 Handle<Object> name_;
3861 class HLoadFunctionPrototype: public HUnaryOperation {
3863 explicit HLoadFunctionPrototype(HValue* function)
3864 : HUnaryOperation(function) {
3865 set_representation(Representation::Tagged());
3867 SetGVNFlag(kDependsOnCalls);
3870 HValue* function() { return OperandAt(0); }
3872 virtual Representation RequiredInputRepresentation(int index) {
3873 return Representation::Tagged();
3876 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
3879 virtual bool DataEquals(HValue* other) { return true; }
3883 class HLoadKeyedFastElement: public HTemplateInstruction<2> {
3885 enum HoleCheckMode { PERFORM_HOLE_CHECK, OMIT_HOLE_CHECK };
3887 HLoadKeyedFastElement(HValue* obj,
3889 HoleCheckMode hole_check_mode = PERFORM_HOLE_CHECK)
3890 : hole_check_mode_(hole_check_mode) {
3891 SetOperandAt(0, obj);
3892 SetOperandAt(1, key);
3893 set_representation(Representation::Tagged());
3894 SetGVNFlag(kDependsOnArrayElements);
3898 HValue* object() { return OperandAt(0); }
3899 HValue* key() { return OperandAt(1); }
3901 virtual Representation RequiredInputRepresentation(int index) {
3902 // The key is supposed to be Integer32.
3904 ? Representation::Tagged()
3905 : Representation::Integer32();
3908 virtual void PrintDataTo(StringStream* stream);
3910 bool RequiresHoleCheck();
3912 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement)
3915 virtual bool DataEquals(HValue* other) {
3916 if (!other->IsLoadKeyedFastElement()) return false;
3917 HLoadKeyedFastElement* other_load = HLoadKeyedFastElement::cast(other);
3918 return hole_check_mode_ == other_load->hole_check_mode_;
3922 HoleCheckMode hole_check_mode_;
3926 class HLoadKeyedFastDoubleElement: public HTemplateInstruction<2> {
3928 HLoadKeyedFastDoubleElement(HValue* elements, HValue* key) {
3929 SetOperandAt(0, elements);
3930 SetOperandAt(1, key);
3931 set_representation(Representation::Double());
3932 SetGVNFlag(kDependsOnDoubleArrayElements);
3936 HValue* elements() { return OperandAt(0); }
3937 HValue* key() { return OperandAt(1); }
3939 virtual Representation RequiredInputRepresentation(int index) {
3940 // The key is supposed to be Integer32.
3942 ? Representation::Tagged()
3943 : Representation::Integer32();
3946 virtual void PrintDataTo(StringStream* stream);
3948 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement)
3951 virtual bool DataEquals(HValue* other) { return true; }
3955 class HLoadKeyedSpecializedArrayElement: public HTemplateInstruction<2> {
3957 HLoadKeyedSpecializedArrayElement(HValue* external_elements,
3959 ElementsKind elements_kind)
3960 : elements_kind_(elements_kind) {
3961 SetOperandAt(0, external_elements);
3962 SetOperandAt(1, key);
3963 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
3964 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3965 set_representation(Representation::Double());
3967 set_representation(Representation::Integer32());
3969 SetGVNFlag(kDependsOnSpecializedArrayElements);
3970 // Native code could change the specialized array.
3971 SetGVNFlag(kDependsOnCalls);
3975 virtual void PrintDataTo(StringStream* stream);
3977 virtual Representation RequiredInputRepresentation(int index) {
3978 // The key is supposed to be Integer32, but the base pointer
3979 // for the element load is a naked pointer.
3981 ? Representation::External()
3982 : Representation::Integer32();
3985 HValue* external_pointer() { return OperandAt(0); }
3986 HValue* key() { return OperandAt(1); }
3987 ElementsKind elements_kind() const { return elements_kind_; }
3989 virtual Range* InferRange(Zone* zone);
3991 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement)
3994 virtual bool DataEquals(HValue* other) {
3995 if (!other->IsLoadKeyedSpecializedArrayElement()) return false;
3996 HLoadKeyedSpecializedArrayElement* cast_other =
3997 HLoadKeyedSpecializedArrayElement::cast(other);
3998 return elements_kind_ == cast_other->elements_kind();
4002 ElementsKind elements_kind_;
4006 class HLoadKeyedGeneric: public HTemplateInstruction<3> {
4008 HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key) {
4009 set_representation(Representation::Tagged());
4010 SetOperandAt(0, obj);
4011 SetOperandAt(1, key);
4012 SetOperandAt(2, context);
4013 SetAllSideEffects();
4016 HValue* object() { return OperandAt(0); }
4017 HValue* key() { return OperandAt(1); }
4018 HValue* context() { return OperandAt(2); }
4020 virtual void PrintDataTo(StringStream* stream);
4022 virtual Representation RequiredInputRepresentation(int index) {
4023 return Representation::Tagged();
4026 virtual HValue* Canonicalize();
4028 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
4032 class HStoreNamedField: public HTemplateInstruction<2> {
4034 HStoreNamedField(HValue* obj,
4035 Handle<String> name,
4040 is_in_object_(in_object),
4042 SetOperandAt(0, obj);
4043 SetOperandAt(1, val);
4044 if (is_in_object_) {
4045 SetGVNFlag(kChangesInobjectFields);
4047 SetGVNFlag(kChangesBackingStoreFields);
4051 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
4053 virtual Representation RequiredInputRepresentation(int index) {
4054 return Representation::Tagged();
4056 virtual void PrintDataTo(StringStream* stream);
4058 HValue* object() { return OperandAt(0); }
4059 HValue* value() { return OperandAt(1); }
4061 Handle<String> name() const { return name_; }
4062 bool is_in_object() const { return is_in_object_; }
4063 int offset() const { return offset_; }
4064 Handle<Map> transition() const { return transition_; }
4065 void set_transition(Handle<Map> map) { transition_ = map; }
4067 bool NeedsWriteBarrier() {
4068 return StoringValueNeedsWriteBarrier(value());
4072 Handle<String> name_;
4075 Handle<Map> transition_;
4079 class HStoreNamedGeneric: public HTemplateInstruction<3> {
4081 HStoreNamedGeneric(HValue* context,
4083 Handle<String> name,
4085 StrictModeFlag strict_mode_flag)
4087 strict_mode_flag_(strict_mode_flag) {
4088 SetOperandAt(0, object);
4089 SetOperandAt(1, value);
4090 SetOperandAt(2, context);
4091 SetAllSideEffects();
4094 HValue* object() { return OperandAt(0); }
4095 HValue* value() { return OperandAt(1); }
4096 HValue* context() { return OperandAt(2); }
4097 Handle<String> name() { return name_; }
4098 StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
4100 virtual void PrintDataTo(StringStream* stream);
4102 virtual Representation RequiredInputRepresentation(int index) {
4103 return Representation::Tagged();
4106 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
4109 Handle<String> name_;
4110 StrictModeFlag strict_mode_flag_;
4114 class HStoreKeyedFastElement: public HTemplateInstruction<3> {
4116 HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val,
4117 ElementsKind elements_kind = FAST_ELEMENTS)
4118 : elements_kind_(elements_kind) {
4119 SetOperandAt(0, obj);
4120 SetOperandAt(1, key);
4121 SetOperandAt(2, val);
4122 SetGVNFlag(kChangesArrayElements);
4125 virtual Representation RequiredInputRepresentation(int index) {
4126 // The key is supposed to be Integer32.
4128 ? Representation::Integer32()
4129 : Representation::Tagged();
4132 HValue* object() { return OperandAt(0); }
4133 HValue* key() { return OperandAt(1); }
4134 HValue* value() { return OperandAt(2); }
4135 bool value_is_smi() {
4136 return elements_kind_ == FAST_SMI_ONLY_ELEMENTS;
4139 bool NeedsWriteBarrier() {
4140 if (value_is_smi()) {
4143 return StoringValueNeedsWriteBarrier(value());
4147 virtual void PrintDataTo(StringStream* stream);
4149 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement)
4152 ElementsKind elements_kind_;
4156 class HStoreKeyedFastDoubleElement: public HTemplateInstruction<3> {
4158 HStoreKeyedFastDoubleElement(HValue* elements,
4161 SetOperandAt(0, elements);
4162 SetOperandAt(1, key);
4163 SetOperandAt(2, val);
4164 SetGVNFlag(kChangesDoubleArrayElements);
4167 virtual Representation RequiredInputRepresentation(int index) {
4169 return Representation::Integer32();
4170 } else if (index == 2) {
4171 return Representation::Double();
4173 return Representation::Tagged();
4177 HValue* elements() { return OperandAt(0); }
4178 HValue* key() { return OperandAt(1); }
4179 HValue* value() { return OperandAt(2); }
4181 bool NeedsWriteBarrier() {
4182 return StoringValueNeedsWriteBarrier(value());
4185 virtual void PrintDataTo(StringStream* stream);
4187 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement)
4191 class HStoreKeyedSpecializedArrayElement: public HTemplateInstruction<3> {
4193 HStoreKeyedSpecializedArrayElement(HValue* external_elements,
4196 ElementsKind elements_kind)
4197 : elements_kind_(elements_kind) {
4198 SetGVNFlag(kChangesSpecializedArrayElements);
4199 SetOperandAt(0, external_elements);
4200 SetOperandAt(1, key);
4201 SetOperandAt(2, val);
4204 virtual void PrintDataTo(StringStream* stream);
4206 virtual Representation RequiredInputRepresentation(int index) {
4208 return Representation::External();
4210 bool float_or_double_elements =
4211 elements_kind() == EXTERNAL_FLOAT_ELEMENTS ||
4212 elements_kind() == EXTERNAL_DOUBLE_ELEMENTS;
4213 if (index == 2 && float_or_double_elements) {
4214 return Representation::Double();
4216 return Representation::Integer32();
4221 HValue* external_pointer() { return OperandAt(0); }
4222 HValue* key() { return OperandAt(1); }
4223 HValue* value() { return OperandAt(2); }
4224 ElementsKind elements_kind() const { return elements_kind_; }
4226 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement)
4229 ElementsKind elements_kind_;
4233 class HStoreKeyedGeneric: public HTemplateInstruction<4> {
4235 HStoreKeyedGeneric(HValue* context,
4239 StrictModeFlag strict_mode_flag)
4240 : strict_mode_flag_(strict_mode_flag) {
4241 SetOperandAt(0, object);
4242 SetOperandAt(1, key);
4243 SetOperandAt(2, value);
4244 SetOperandAt(3, context);
4245 SetAllSideEffects();
4248 HValue* object() { return OperandAt(0); }
4249 HValue* key() { return OperandAt(1); }
4250 HValue* value() { return OperandAt(2); }
4251 HValue* context() { return OperandAt(3); }
4252 StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
4254 virtual Representation RequiredInputRepresentation(int index) {
4255 return Representation::Tagged();
4258 virtual void PrintDataTo(StringStream* stream);
4260 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
4263 StrictModeFlag strict_mode_flag_;
4267 class HTransitionElementsKind: public HTemplateInstruction<1> {
4269 HTransitionElementsKind(HValue* object,
4270 Handle<Map> original_map,
4271 Handle<Map> transitioned_map)
4272 : original_map_(original_map),
4273 transitioned_map_(transitioned_map) {
4274 SetOperandAt(0, object);
4276 SetGVNFlag(kChangesElementsKind);
4277 SetGVNFlag(kChangesElementsPointer);
4278 set_representation(Representation::Tagged());
4281 virtual Representation RequiredInputRepresentation(int index) {
4282 return Representation::Tagged();
4285 HValue* object() { return OperandAt(0); }
4286 Handle<Map> original_map() { return original_map_; }
4287 Handle<Map> transitioned_map() { return transitioned_map_; }
4289 virtual void PrintDataTo(StringStream* stream);
4291 DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
4294 virtual bool DataEquals(HValue* other) {
4295 HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
4296 return original_map_.is_identical_to(instr->original_map()) &&
4297 transitioned_map_.is_identical_to(instr->transitioned_map());
4301 Handle<Map> original_map_;
4302 Handle<Map> transitioned_map_;
4306 class HStringAdd: public HBinaryOperation {
4308 HStringAdd(HValue* context, HValue* left, HValue* right)
4309 : HBinaryOperation(context, left, right) {
4310 set_representation(Representation::Tagged());
4312 SetGVNFlag(kDependsOnMaps);
4315 virtual Representation RequiredInputRepresentation(int index) {
4316 return Representation::Tagged();
4319 virtual HType CalculateInferredType() {
4320 return HType::String();
4323 DECLARE_CONCRETE_INSTRUCTION(StringAdd)
4326 virtual bool DataEquals(HValue* other) { return true; }
4330 class HStringCharCodeAt: public HTemplateInstruction<3> {
4332 HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
4333 SetOperandAt(0, context);
4334 SetOperandAt(1, string);
4335 SetOperandAt(2, index);
4336 set_representation(Representation::Integer32());
4338 SetGVNFlag(kDependsOnMaps);
4341 virtual Representation RequiredInputRepresentation(int index) {
4342 // The index is supposed to be Integer32.
4344 ? Representation::Integer32()
4345 : Representation::Tagged();
4348 HValue* context() { return OperandAt(0); }
4349 HValue* string() { return OperandAt(1); }
4350 HValue* index() { return OperandAt(2); }
4352 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
4355 virtual bool DataEquals(HValue* other) { return true; }
4357 virtual Range* InferRange(Zone* zone) {
4358 return new(zone) Range(0, String::kMaxUtf16CodeUnit);
4363 class HStringCharFromCode: public HTemplateInstruction<2> {
4365 HStringCharFromCode(HValue* context, HValue* char_code) {
4366 SetOperandAt(0, context);
4367 SetOperandAt(1, char_code);
4368 set_representation(Representation::Tagged());
4372 virtual Representation RequiredInputRepresentation(int index) {
4374 ? Representation::Tagged()
4375 : Representation::Integer32();
4377 virtual HType CalculateInferredType();
4379 HValue* context() { return OperandAt(0); }
4380 HValue* value() { return OperandAt(1); }
4382 virtual bool DataEquals(HValue* other) { return true; }
4384 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
4388 class HStringLength: public HUnaryOperation {
4390 explicit HStringLength(HValue* string) : HUnaryOperation(string) {
4391 set_representation(Representation::Tagged());
4393 SetGVNFlag(kDependsOnMaps);
4396 virtual Representation RequiredInputRepresentation(int index) {
4397 return Representation::Tagged();
4400 virtual HType CalculateInferredType() {
4401 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
4402 return HType::Smi();
4405 DECLARE_CONCRETE_INSTRUCTION(StringLength)
4408 virtual bool DataEquals(HValue* other) { return true; }
4410 virtual Range* InferRange(Zone* zone) {
4411 return new(zone) Range(0, String::kMaxLength);
4416 class HAllocateObject: public HTemplateInstruction<1> {
4418 HAllocateObject(HValue* context, Handle<JSFunction> constructor)
4419 : constructor_(constructor) {
4420 SetOperandAt(0, context);
4421 set_representation(Representation::Tagged());
4424 // Maximum instance size for which allocations will be inlined.
4425 static const int kMaxSize = 64 * kPointerSize;
4427 HValue* context() { return OperandAt(0); }
4428 Handle<JSFunction> constructor() { return constructor_; }
4430 virtual Representation RequiredInputRepresentation(int index) {
4431 return Representation::Tagged();
4433 virtual HType CalculateInferredType();
4435 DECLARE_CONCRETE_INSTRUCTION(AllocateObject)
4438 Handle<JSFunction> constructor_;
4443 class HMaterializedLiteral: public HTemplateInstruction<V> {
4445 HMaterializedLiteral<V>(int index, int depth)
4446 : literal_index_(index), depth_(depth) {
4447 this->set_representation(Representation::Tagged());
4450 int literal_index() const { return literal_index_; }
4451 int depth() const { return depth_; }
4459 class HFastLiteral: public HMaterializedLiteral<1> {
4461 HFastLiteral(HValue* context,
4462 Handle<JSObject> boilerplate,
4466 : HMaterializedLiteral<1>(literal_index, depth),
4467 boilerplate_(boilerplate),
4468 total_size_(total_size) {
4469 SetOperandAt(0, context);
4472 // Maximum depth and total number of elements and properties for literal
4473 // graphs to be considered for fast deep-copying.
4474 static const int kMaxLiteralDepth = 3;
4475 static const int kMaxLiteralProperties = 8;
4477 HValue* context() { return OperandAt(0); }
4478 Handle<JSObject> boilerplate() const { return boilerplate_; }
4479 int total_size() const { return total_size_; }
4481 virtual Representation RequiredInputRepresentation(int index) {
4482 return Representation::Tagged();
4484 virtual HType CalculateInferredType();
4486 DECLARE_CONCRETE_INSTRUCTION(FastLiteral)
4489 Handle<JSObject> boilerplate_;
4494 class HArrayLiteral: public HMaterializedLiteral<1> {
4496 HArrayLiteral(HValue* context,
4497 Handle<HeapObject> boilerplate_object,
4501 : HMaterializedLiteral<1>(literal_index, depth),
4503 boilerplate_object_(boilerplate_object) {
4504 SetOperandAt(0, context);
4507 HValue* context() { return OperandAt(0); }
4508 ElementsKind boilerplate_elements_kind() const {
4509 if (!boilerplate_object_->IsJSObject()) {
4510 return FAST_ELEMENTS;
4512 return Handle<JSObject>::cast(boilerplate_object_)->GetElementsKind();
4514 Handle<HeapObject> boilerplate_object() const { return boilerplate_object_; }
4515 int length() const { return length_; }
4517 bool IsCopyOnWrite() const;
4519 virtual Representation RequiredInputRepresentation(int index) {
4520 return Representation::Tagged();
4522 virtual HType CalculateInferredType();
4524 DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral)
4528 Handle<HeapObject> boilerplate_object_;
4532 class HObjectLiteral: public HMaterializedLiteral<1> {
4534 HObjectLiteral(HValue* context,
4535 Handle<FixedArray> constant_properties,
4540 : HMaterializedLiteral<1>(literal_index, depth),
4541 constant_properties_(constant_properties),
4542 fast_elements_(fast_elements),
4543 has_function_(has_function) {
4544 SetOperandAt(0, context);
4547 HValue* context() { return OperandAt(0); }
4548 Handle<FixedArray> constant_properties() const {
4549 return constant_properties_;
4551 bool fast_elements() const { return fast_elements_; }
4552 bool has_function() const { return has_function_; }
4554 virtual Representation RequiredInputRepresentation(int index) {
4555 return Representation::Tagged();
4557 virtual HType CalculateInferredType();
4559 DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral)
4562 Handle<FixedArray> constant_properties_;
4563 bool fast_elements_;
4568 class HRegExpLiteral: public HMaterializedLiteral<1> {
4570 HRegExpLiteral(HValue* context,
4571 Handle<String> pattern,
4572 Handle<String> flags,
4574 : HMaterializedLiteral<1>(literal_index, 0),
4577 SetOperandAt(0, context);
4578 SetAllSideEffects();
4581 HValue* context() { return OperandAt(0); }
4582 Handle<String> pattern() { return pattern_; }
4583 Handle<String> flags() { return flags_; }
4585 virtual Representation RequiredInputRepresentation(int index) {
4586 return Representation::Tagged();
4588 virtual HType CalculateInferredType();
4590 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
4593 Handle<String> pattern_;
4594 Handle<String> flags_;
4598 class HFunctionLiteral: public HTemplateInstruction<1> {
4600 HFunctionLiteral(HValue* context,
4601 Handle<SharedFunctionInfo> shared,
4603 : shared_info_(shared), pretenure_(pretenure) {
4604 SetOperandAt(0, context);
4605 set_representation(Representation::Tagged());
4608 HValue* context() { return OperandAt(0); }
4610 virtual Representation RequiredInputRepresentation(int index) {
4611 return Representation::Tagged();
4613 virtual HType CalculateInferredType();
4615 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral)
4617 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
4618 bool pretenure() const { return pretenure_; }
4621 Handle<SharedFunctionInfo> shared_info_;
4626 class HTypeof: public HTemplateInstruction<2> {
4628 explicit HTypeof(HValue* context, HValue* value) {
4629 SetOperandAt(0, context);
4630 SetOperandAt(1, value);
4631 set_representation(Representation::Tagged());
4634 HValue* context() { return OperandAt(0); }
4635 HValue* value() { return OperandAt(1); }
4637 virtual HValue* Canonicalize();
4638 virtual void PrintDataTo(StringStream* stream);
4640 virtual Representation RequiredInputRepresentation(int index) {
4641 return Representation::Tagged();
4644 DECLARE_CONCRETE_INSTRUCTION(Typeof)
4648 class HToFastProperties: public HUnaryOperation {
4650 explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
4651 // This instruction is not marked as having side effects, but
4652 // changes the map of the input operand. Use it only when creating
4654 ASSERT(value->IsObjectLiteral() || value->IsFastLiteral());
4655 set_representation(Representation::Tagged());
4658 virtual Representation RequiredInputRepresentation(int index) {
4659 return Representation::Tagged();
4662 DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
4666 class HValueOf: public HUnaryOperation {
4668 explicit HValueOf(HValue* value) : HUnaryOperation(value) {
4669 set_representation(Representation::Tagged());
4672 virtual Representation RequiredInputRepresentation(int index) {
4673 return Representation::Tagged();
4676 DECLARE_CONCRETE_INSTRUCTION(ValueOf)
4680 class HDateField: public HUnaryOperation {
4682 HDateField(HValue* date, Smi* index)
4683 : HUnaryOperation(date), index_(index) {
4684 set_representation(Representation::Tagged());
4687 Smi* index() const { return index_; }
4689 virtual Representation RequiredInputRepresentation(int index) {
4690 return Representation::Tagged();
4693 DECLARE_CONCRETE_INSTRUCTION(DateField)
4700 class HDeleteProperty: public HBinaryOperation {
4702 HDeleteProperty(HValue* context, HValue* obj, HValue* key)
4703 : HBinaryOperation(context, obj, key) {
4704 set_representation(Representation::Tagged());
4705 SetAllSideEffects();
4708 virtual Representation RequiredInputRepresentation(int index) {
4709 return Representation::Tagged();
4712 virtual HType CalculateInferredType();
4714 DECLARE_CONCRETE_INSTRUCTION(DeleteProperty)
4716 HValue* object() { return left(); }
4717 HValue* key() { return right(); }
4721 class HIn: public HTemplateInstruction<3> {
4723 HIn(HValue* context, HValue* key, HValue* object) {
4724 SetOperandAt(0, context);
4725 SetOperandAt(1, key);
4726 SetOperandAt(2, object);
4727 set_representation(Representation::Tagged());
4728 SetAllSideEffects();
4731 HValue* context() { return OperandAt(0); }
4732 HValue* key() { return OperandAt(1); }
4733 HValue* object() { return OperandAt(2); }
4735 virtual Representation RequiredInputRepresentation(int index) {
4736 return Representation::Tagged();
4739 virtual HType CalculateInferredType() {
4740 return HType::Boolean();
4743 virtual void PrintDataTo(StringStream* stream);
4745 DECLARE_CONCRETE_INSTRUCTION(In)
4749 class HCheckMapValue: public HTemplateInstruction<2> {
4751 HCheckMapValue(HValue* value,
4753 SetOperandAt(0, value);
4754 SetOperandAt(1, map);
4755 set_representation(Representation::Tagged());
4757 SetGVNFlag(kDependsOnMaps);
4758 SetGVNFlag(kDependsOnElementsKind);
4761 virtual Representation RequiredInputRepresentation(int index) {
4762 return Representation::Tagged();
4765 virtual void PrintDataTo(StringStream* stream);
4767 virtual HType CalculateInferredType() {
4768 return HType::Tagged();
4771 HValue* value() { return OperandAt(0); }
4772 HValue* map() { return OperandAt(1); }
4774 DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
4777 virtual bool DataEquals(HValue* other) {
4783 class HForInPrepareMap : public HTemplateInstruction<2> {
4785 HForInPrepareMap(HValue* context,
4787 SetOperandAt(0, context);
4788 SetOperandAt(1, object);
4789 set_representation(Representation::Tagged());
4790 SetAllSideEffects();
4793 virtual Representation RequiredInputRepresentation(int index) {
4794 return Representation::Tagged();
4797 HValue* context() { return OperandAt(0); }
4798 HValue* enumerable() { return OperandAt(1); }
4800 virtual void PrintDataTo(StringStream* stream);
4802 virtual HType CalculateInferredType() {
4803 return HType::Tagged();
4806 DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
4810 class HForInCacheArray : public HTemplateInstruction<2> {
4812 HForInCacheArray(HValue* enumerable,
4814 int idx) : idx_(idx) {
4815 SetOperandAt(0, enumerable);
4816 SetOperandAt(1, keys);
4817 set_representation(Representation::Tagged());
4820 virtual Representation RequiredInputRepresentation(int index) {
4821 return Representation::Tagged();
4824 HValue* enumerable() { return OperandAt(0); }
4825 HValue* map() { return OperandAt(1); }
4826 int idx() { return idx_; }
4828 HForInCacheArray* index_cache() {
4829 return index_cache_;
4832 void set_index_cache(HForInCacheArray* index_cache) {
4833 index_cache_ = index_cache;
4836 virtual void PrintDataTo(StringStream* stream);
4838 virtual HType CalculateInferredType() {
4839 return HType::Tagged();
4842 DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
4846 HForInCacheArray* index_cache_;
4850 class HLoadFieldByIndex : public HTemplateInstruction<2> {
4852 HLoadFieldByIndex(HValue* object,
4854 SetOperandAt(0, object);
4855 SetOperandAt(1, index);
4856 set_representation(Representation::Tagged());
4859 virtual Representation RequiredInputRepresentation(int index) {
4860 return Representation::Tagged();
4863 HValue* object() { return OperandAt(0); }
4864 HValue* index() { return OperandAt(1); }
4866 virtual void PrintDataTo(StringStream* stream);
4868 virtual HType CalculateInferredType() {
4869 return HType::Tagged();
4872 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
4876 #undef DECLARE_INSTRUCTION
4877 #undef DECLARE_CONCRETE_INSTRUCTION
4879 } } // namespace v8::internal
4881 #endif // V8_HYDROGEN_INSTRUCTIONS_H_