OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
665 // If the operation also exists in a form that takes int32 and outputs int32 | 665 // If the operation also exists in a form that takes int32 and outputs int32 |
666 // then the operation should return its input value so that we can propagate | 666 // then the operation should return its input value so that we can propagate |
667 // back. There are three operations that need to propagate back to more than | 667 // back. There are three operations that need to propagate back to more than |
668 // one input. They are phi and binary div and mul. They always return NULL | 668 // one input. They are phi and binary div and mul. They always return NULL |
669 // and expect the caller to take care of things. | 669 // and expect the caller to take care of things. |
670 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) { | 670 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) { |
671 visited->Add(id()); | 671 visited->Add(id()); |
672 return NULL; | 672 return NULL; |
673 } | 673 } |
674 | 674 |
675 // There are HInstructions that do not really change a value, they | |
676 // only add pieces of information to it (like bounds checks, map checks | |
677 // or SSI definitions after conditional branches). | |
678 // This method must always return the original HValue SSA definition (the | |
679 // register allocator relies on this to avoid allocating multiple registers | |
680 // for the same value). | |
681 virtual HValue* ActualValue() { return this; } | |
682 | |
683 bool IsDefinedAfter(HBasicBlock* other) const; | 675 bool IsDefinedAfter(HBasicBlock* other) const; |
684 | 676 |
685 // Operands. | 677 // Operands. |
686 virtual int OperandCount() = 0; | 678 virtual int OperandCount() = 0; |
687 virtual HValue* OperandAt(int index) const = 0; | 679 virtual HValue* OperandAt(int index) const = 0; |
688 void SetOperandAt(int index, HValue* value); | 680 void SetOperandAt(int index, HValue* value); |
689 | 681 |
690 void DeleteAndReplaceWith(HValue* other); | 682 void DeleteAndReplaceWith(HValue* other); |
691 void ReplaceAllUsesWith(HValue* other); | 683 void ReplaceAllUsesWith(HValue* other); |
692 bool HasNoUses() const { return use_list_ == NULL; } | 684 bool HasNoUses() const { return use_list_ == NULL; } |
(...skipping 2265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2958 | 2950 |
2959 enum BoundsCheckKeyMode { | 2951 enum BoundsCheckKeyMode { |
2960 DONT_ALLOW_SMI_KEY, | 2952 DONT_ALLOW_SMI_KEY, |
2961 ALLOW_SMI_KEY | 2953 ALLOW_SMI_KEY |
2962 }; | 2954 }; |
2963 | 2955 |
2964 | 2956 |
2965 class HBoundsCheck: public HTemplateInstruction<2> { | 2957 class HBoundsCheck: public HTemplateInstruction<2> { |
2966 public: | 2958 public: |
2967 HBoundsCheck(HValue* index, HValue* length, | 2959 HBoundsCheck(HValue* index, HValue* length, |
2968 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY, | 2960 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY) |
2969 Representation r = Representation::None()) | |
2970 : key_mode_(key_mode) { | 2961 : key_mode_(key_mode) { |
2971 SetOperandAt(0, index); | 2962 SetOperandAt(0, index); |
2972 SetOperandAt(1, length); | 2963 SetOperandAt(1, length); |
2973 if (r.IsNone()) { | 2964 set_representation(Representation::Integer32()); |
2974 // In the normal compilation pipeline the representation is flexible | |
2975 // (see comment to RequiredInputRepresentation). | |
2976 SetFlag(kFlexibleRepresentation); | |
2977 } else { | |
2978 // When compiling stubs we want to set the representation explicitly | |
2979 // so the compilation pipeline can skip the HInferRepresentation phase. | |
2980 set_representation(r); | |
2981 } | |
2982 SetFlag(kUseGVN); | 2965 SetFlag(kUseGVN); |
2983 } | 2966 } |
2984 | 2967 |
2985 virtual Representation RequiredInputRepresentation(int arg_index) { | 2968 virtual Representation RequiredInputRepresentation(int arg_index) { |
2986 return representation(); | 2969 if (key_mode_ == DONT_ALLOW_SMI_KEY || |
| 2970 !length()->representation().IsTagged()) { |
| 2971 return Representation::Integer32(); |
| 2972 } |
| 2973 // If the index is tagged and isn't constant, then allow the length |
| 2974 // to be tagged, since it is usually already tagged from loading it out of |
| 2975 // the length field of a JSArray. This allows for direct comparison without |
| 2976 // untagging. |
| 2977 if (index()->representation().IsTagged() && !index()->IsConstant()) { |
| 2978 return Representation::Tagged(); |
| 2979 } |
| 2980 // Also allow the length to be tagged if the index is constant, because |
| 2981 // it can be tagged to allow direct comparison. |
| 2982 if (index()->IsConstant() && |
| 2983 index()->representation().IsInteger32() && |
| 2984 arg_index == 1) { |
| 2985 return Representation::Tagged(); |
| 2986 } |
| 2987 return Representation::Integer32(); |
2987 } | 2988 } |
2988 virtual Representation observed_input_representation(int index) { | 2989 virtual Representation observed_input_representation(int index) { |
2989 return Representation::Integer32(); | 2990 return Representation::Integer32(); |
2990 } | 2991 } |
2991 | 2992 |
2992 virtual void PrintDataTo(StringStream* stream); | 2993 virtual void PrintDataTo(StringStream* stream); |
2993 virtual void InferRepresentation(HInferRepresentation* h_infer); | |
2994 | 2994 |
2995 HValue* index() { return OperandAt(0); } | 2995 HValue* index() { return OperandAt(0); } |
2996 HValue* length() { return OperandAt(1); } | 2996 HValue* length() { return OperandAt(1); } |
2997 | 2997 |
2998 virtual HValue* ActualValue() { | |
2999 return index(); | |
3000 } | |
3001 | |
3002 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) | 2998 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) |
3003 | 2999 |
3004 protected: | 3000 protected: |
3005 virtual bool DataEquals(HValue* other) { return true; } | 3001 virtual bool DataEquals(HValue* other) { return true; } |
3006 BoundsCheckKeyMode key_mode_; | 3002 BoundsCheckKeyMode key_mode_; |
3007 }; | 3003 }; |
3008 | 3004 |
3009 | 3005 |
3010 class HBitwiseBinaryOperation: public HBinaryOperation { | 3006 class HBitwiseBinaryOperation: public HBinaryOperation { |
3011 public: | 3007 public: |
(...skipping 1350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4362 }; | 4358 }; |
4363 | 4359 |
4364 class ArrayInstructionInterface { | 4360 class ArrayInstructionInterface { |
4365 public: | 4361 public: |
4366 virtual HValue* GetKey() = 0; | 4362 virtual HValue* GetKey() = 0; |
4367 virtual void SetKey(HValue* key) = 0; | 4363 virtual void SetKey(HValue* key) = 0; |
4368 virtual void SetIndexOffset(uint32_t index_offset) = 0; | 4364 virtual void SetIndexOffset(uint32_t index_offset) = 0; |
4369 virtual bool IsDehoisted() = 0; | 4365 virtual bool IsDehoisted() = 0; |
4370 virtual void SetDehoisted(bool is_dehoisted) = 0; | 4366 virtual void SetDehoisted(bool is_dehoisted) = 0; |
4371 virtual ~ArrayInstructionInterface() { }; | 4367 virtual ~ArrayInstructionInterface() { }; |
4372 | |
4373 static Representation KeyedAccessIndexRequirement(Representation r) { | |
4374 return r.IsInteger32() | |
4375 ? Representation::Integer32() : Representation::Tagged(); | |
4376 } | |
4377 }; | 4368 }; |
4378 | 4369 |
4379 | 4370 |
4380 class HLoadKeyed | 4371 class HLoadKeyed |
4381 : public HTemplateInstruction<3>, public ArrayInstructionInterface { | 4372 : public HTemplateInstruction<3>, public ArrayInstructionInterface { |
4382 public: | 4373 public: |
4383 HLoadKeyed(HValue* obj, | 4374 HLoadKeyed(HValue* obj, |
4384 HValue* key, | 4375 HValue* key, |
4385 HValue* dependency, | 4376 HValue* dependency, |
4386 ElementsKind elements_kind) | 4377 ElementsKind elements_kind) |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4450 } | 4441 } |
4451 | 4442 |
4452 virtual Representation RequiredInputRepresentation(int index) { | 4443 virtual Representation RequiredInputRepresentation(int index) { |
4453 // kind_fast: tagged[int32] (none) | 4444 // kind_fast: tagged[int32] (none) |
4454 // kind_double: tagged[int32] (none) | 4445 // kind_double: tagged[int32] (none) |
4455 // kind_external: external[int32] (none) | 4446 // kind_external: external[int32] (none) |
4456 if (index == 0) { | 4447 if (index == 0) { |
4457 return is_external() ? Representation::External() | 4448 return is_external() ? Representation::External() |
4458 : Representation::Tagged(); | 4449 : Representation::Tagged(); |
4459 } | 4450 } |
4460 if (index == 1) { | 4451 if (index == 1) return Representation::Integer32(); |
4461 return ArrayInstructionInterface::KeyedAccessIndexRequirement( | |
4462 OperandAt(1)->representation()); | |
4463 } | |
4464 return Representation::None(); | 4452 return Representation::None(); |
4465 } | 4453 } |
4466 | 4454 |
4467 virtual Representation observed_input_representation(int index) { | 4455 virtual Representation observed_input_representation(int index) { |
4468 return RequiredInputRepresentation(index); | 4456 return RequiredInputRepresentation(index); |
4469 } | 4457 } |
4470 | 4458 |
4471 virtual void PrintDataTo(StringStream* stream); | 4459 virtual void PrintDataTo(StringStream* stream); |
4472 | 4460 |
4473 bool RequiresHoleCheck() const; | 4461 bool RequiresHoleCheck() const; |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4668 } | 4656 } |
4669 | 4657 |
4670 virtual Representation RequiredInputRepresentation(int index) { | 4658 virtual Representation RequiredInputRepresentation(int index) { |
4671 // kind_fast: tagged[int32] = tagged | 4659 // kind_fast: tagged[int32] = tagged |
4672 // kind_double: tagged[int32] = double | 4660 // kind_double: tagged[int32] = double |
4673 // kind_external: external[int32] = (double | int32) | 4661 // kind_external: external[int32] = (double | int32) |
4674 if (index == 0) { | 4662 if (index == 0) { |
4675 return is_external() ? Representation::External() | 4663 return is_external() ? Representation::External() |
4676 : Representation::Tagged(); | 4664 : Representation::Tagged(); |
4677 } else if (index == 1) { | 4665 } else if (index == 1) { |
4678 return ArrayInstructionInterface::KeyedAccessIndexRequirement( | 4666 return Representation::Integer32(); |
4679 OperandAt(1)->representation()); | |
4680 } | 4667 } |
4681 | 4668 |
4682 ASSERT_EQ(index, 2); | 4669 ASSERT_EQ(index, 2); |
4683 if (IsDoubleOrFloatElementsKind(elements_kind())) { | 4670 if (IsDoubleOrFloatElementsKind(elements_kind())) { |
4684 return Representation::Double(); | 4671 return Representation::Double(); |
4685 } | 4672 } |
4686 | 4673 |
4687 return is_external() ? Representation::Integer32() | 4674 return is_external() ? Representation::Integer32() |
4688 : Representation::Tagged(); | 4675 : Representation::Tagged(); |
4689 } | 4676 } |
(...skipping 781 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5471 virtual bool IsDeletable() const { return true; } | 5458 virtual bool IsDeletable() const { return true; } |
5472 }; | 5459 }; |
5473 | 5460 |
5474 | 5461 |
5475 #undef DECLARE_INSTRUCTION | 5462 #undef DECLARE_INSTRUCTION |
5476 #undef DECLARE_CONCRETE_INSTRUCTION | 5463 #undef DECLARE_CONCRETE_INSTRUCTION |
5477 | 5464 |
5478 } } // namespace v8::internal | 5465 } } // namespace v8::internal |
5479 | 5466 |
5480 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 5467 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |