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 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
341 bool IsNone() const { return kind_ == kNone; } | 341 bool IsNone() const { return kind_ == kNone; } |
342 bool IsTagged() const { return kind_ == kTagged; } | 342 bool IsTagged() const { return kind_ == kTagged; } |
343 bool IsInteger32() const { return kind_ == kInteger32; } | 343 bool IsInteger32() const { return kind_ == kInteger32; } |
344 bool IsDouble() const { return kind_ == kDouble; } | 344 bool IsDouble() const { return kind_ == kDouble; } |
345 bool IsExternal() const { return kind_ == kExternal; } | 345 bool IsExternal() const { return kind_ == kExternal; } |
346 bool IsSpecialization() const { | 346 bool IsSpecialization() const { |
347 return kind_ == kInteger32 || kind_ == kDouble; | 347 return kind_ == kInteger32 || kind_ == kDouble; |
348 } | 348 } |
349 const char* Mnemonic() const; | 349 const char* Mnemonic() const; |
350 | 350 |
351 Representation KeyedAccessIndexRequirement() { | |
Jakob Kummerow
2013/01/10 16:06:47
nit: I'm a bit unhappy about adding instruction-sp
| |
352 return IsInteger32() ? Integer32() : Tagged(); | |
353 } | |
354 | |
351 private: | 355 private: |
352 explicit Representation(Kind k) : kind_(k) { } | 356 explicit Representation(Kind k) : kind_(k) { } |
353 | 357 |
354 // Make sure kind fits in int8. | 358 // Make sure kind fits in int8. |
355 STATIC_ASSERT(kNumRepresentations <= (1 << kBitsPerByte)); | 359 STATIC_ASSERT(kNumRepresentations <= (1 << kBitsPerByte)); |
356 | 360 |
357 int8_t kind_; | 361 int8_t kind_; |
358 }; | 362 }; |
359 | 363 |
360 | 364 |
(...skipping 304 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 | 669 // 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 | 670 // 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 | 671 // 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 | 672 // one input. They are phi and binary div and mul. They always return NULL |
669 // and expect the caller to take care of things. | 673 // and expect the caller to take care of things. |
670 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) { | 674 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) { |
671 visited->Add(id()); | 675 visited->Add(id()); |
672 return NULL; | 676 return NULL; |
673 } | 677 } |
674 | 678 |
679 // There are HInstructions that do not really change a value, they | |
680 // only add pieces of information to it (like bounds checks, map checks | |
681 // or SSI definitions after conditional branches). | |
682 // This method must always return the original HValue SSA definition (the | |
683 // register allocator relies on this to avoid allocating multiple registers | |
684 // for the same value). | |
685 virtual HValue* ActualValue() { return this; } | |
686 | |
675 bool IsDefinedAfter(HBasicBlock* other) const; | 687 bool IsDefinedAfter(HBasicBlock* other) const; |
676 | 688 |
677 // Operands. | 689 // Operands. |
678 virtual int OperandCount() = 0; | 690 virtual int OperandCount() = 0; |
679 virtual HValue* OperandAt(int index) const = 0; | 691 virtual HValue* OperandAt(int index) const = 0; |
680 void SetOperandAt(int index, HValue* value); | 692 void SetOperandAt(int index, HValue* value); |
681 | 693 |
682 void DeleteAndReplaceWith(HValue* other); | 694 void DeleteAndReplaceWith(HValue* other); |
683 void ReplaceAllUsesWith(HValue* other); | 695 void ReplaceAllUsesWith(HValue* other); |
684 bool HasNoUses() const { return use_list_ == NULL; } | 696 bool HasNoUses() const { return use_list_ == NULL; } |
(...skipping 2263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2948 | 2960 |
2949 enum BoundsCheckKeyMode { | 2961 enum BoundsCheckKeyMode { |
2950 DONT_ALLOW_SMI_KEY, | 2962 DONT_ALLOW_SMI_KEY, |
2951 ALLOW_SMI_KEY | 2963 ALLOW_SMI_KEY |
2952 }; | 2964 }; |
2953 | 2965 |
2954 | 2966 |
2955 class HBoundsCheck: public HTemplateInstruction<2> { | 2967 class HBoundsCheck: public HTemplateInstruction<2> { |
2956 public: | 2968 public: |
2957 HBoundsCheck(HValue* index, HValue* length, | 2969 HBoundsCheck(HValue* index, HValue* length, |
2958 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY) | 2970 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY, |
2971 Representation r = Representation::None()) | |
2959 : key_mode_(key_mode) { | 2972 : key_mode_(key_mode) { |
2960 SetOperandAt(0, index); | 2973 SetOperandAt(0, index); |
2961 SetOperandAt(1, length); | 2974 SetOperandAt(1, length); |
2962 set_representation(Representation::Integer32()); | 2975 if (r.IsNone()) { |
2976 // In the normal compilation pipeline the representation is flexible | |
2977 // (see comment to RequiredInputRepresentation). | |
2978 SetFlag(kFlexibleRepresentation); | |
2979 } else { | |
2980 // When compiling stubs we want to set the representation explicitly | |
2981 // so the compilation pipeline can skip the HInferRepresentation phase. | |
2982 set_representation(r); | |
2983 } | |
2963 SetFlag(kUseGVN); | 2984 SetFlag(kUseGVN); |
2964 } | 2985 } |
2965 | 2986 |
2966 virtual Representation RequiredInputRepresentation(int arg_index) { | 2987 virtual Representation RequiredInputRepresentation(int arg_index) { |
2967 if (key_mode_ == DONT_ALLOW_SMI_KEY || | 2988 return representation(); |
2968 !length()->representation().IsTagged()) { | |
2969 return Representation::Integer32(); | |
2970 } | |
2971 // If the index is tagged and isn't constant, then allow the length | |
2972 // to be tagged, since it is usually already tagged from loading it out of | |
2973 // the length field of a JSArray. This allows for direct comparison without | |
2974 // untagging. | |
2975 if (index()->representation().IsTagged() && !index()->IsConstant()) { | |
2976 return Representation::Tagged(); | |
2977 } | |
2978 // Also allow the length to be tagged if the index is constant, because | |
2979 // it can be tagged to allow direct comparison. | |
2980 if (index()->IsConstant() && | |
2981 index()->representation().IsInteger32() && | |
2982 arg_index == 1) { | |
2983 return Representation::Tagged(); | |
2984 } | |
2985 return Representation::Integer32(); | |
2986 } | 2989 } |
2987 virtual Representation observed_input_representation(int index) { | 2990 virtual Representation observed_input_representation(int index) { |
2988 return Representation::Integer32(); | 2991 return Representation::Integer32(); |
2989 } | 2992 } |
2990 | 2993 |
2991 virtual void PrintDataTo(StringStream* stream); | 2994 virtual void PrintDataTo(StringStream* stream); |
2995 virtual void InferRepresentation(HInferRepresentation* h_infer); | |
2992 | 2996 |
2993 HValue* index() { return OperandAt(0); } | 2997 HValue* index() { return OperandAt(0); } |
2994 HValue* length() { return OperandAt(1); } | 2998 HValue* length() { return OperandAt(1); } |
2995 | 2999 |
3000 virtual HValue* ActualValue() { | |
3001 return index(); | |
3002 } | |
3003 | |
2996 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) | 3004 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) |
2997 | 3005 |
2998 protected: | 3006 protected: |
2999 virtual bool DataEquals(HValue* other) { return true; } | 3007 virtual bool DataEquals(HValue* other) { return true; } |
3000 BoundsCheckKeyMode key_mode_; | 3008 BoundsCheckKeyMode key_mode_; |
3001 }; | 3009 }; |
3002 | 3010 |
3003 | 3011 |
3004 class HBitwiseBinaryOperation: public HBinaryOperation { | 3012 class HBitwiseBinaryOperation: public HBinaryOperation { |
3005 public: | 3013 public: |
(...skipping 1433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4439 } | 4447 } |
4440 | 4448 |
4441 virtual Representation RequiredInputRepresentation(int index) { | 4449 virtual Representation RequiredInputRepresentation(int index) { |
4442 // kind_fast: tagged[int32] (none) | 4450 // kind_fast: tagged[int32] (none) |
4443 // kind_double: tagged[int32] (none) | 4451 // kind_double: tagged[int32] (none) |
4444 // kind_external: external[int32] (none) | 4452 // kind_external: external[int32] (none) |
4445 if (index == 0) { | 4453 if (index == 0) { |
4446 return is_external() ? Representation::External() | 4454 return is_external() ? Representation::External() |
4447 : Representation::Tagged(); | 4455 : Representation::Tagged(); |
4448 } | 4456 } |
4449 if (index == 1) return Representation::Integer32(); | 4457 if (index == 1) { |
4458 return OperandAt(1)->representation().KeyedAccessIndexRequirement(); | |
4459 } | |
4450 return Representation::None(); | 4460 return Representation::None(); |
4451 } | 4461 } |
4452 | 4462 |
4453 virtual Representation observed_input_representation(int index) { | 4463 virtual Representation observed_input_representation(int index) { |
4454 return RequiredInputRepresentation(index); | 4464 return RequiredInputRepresentation(index); |
4455 } | 4465 } |
4456 | 4466 |
4457 virtual void PrintDataTo(StringStream* stream); | 4467 virtual void PrintDataTo(StringStream* stream); |
4458 | 4468 |
4459 bool RequiresHoleCheck() const; | 4469 bool RequiresHoleCheck() const; |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4654 } | 4664 } |
4655 | 4665 |
4656 virtual Representation RequiredInputRepresentation(int index) { | 4666 virtual Representation RequiredInputRepresentation(int index) { |
4657 // kind_fast: tagged[int32] = tagged | 4667 // kind_fast: tagged[int32] = tagged |
4658 // kind_double: tagged[int32] = double | 4668 // kind_double: tagged[int32] = double |
4659 // kind_external: external[int32] = (double | int32) | 4669 // kind_external: external[int32] = (double | int32) |
4660 if (index == 0) { | 4670 if (index == 0) { |
4661 return is_external() ? Representation::External() | 4671 return is_external() ? Representation::External() |
4662 : Representation::Tagged(); | 4672 : Representation::Tagged(); |
4663 } else if (index == 1) { | 4673 } else if (index == 1) { |
4664 return Representation::Integer32(); | 4674 return OperandAt(1)->representation().KeyedAccessIndexRequirement(); |
4665 } | 4675 } |
4666 | 4676 |
4667 ASSERT_EQ(index, 2); | 4677 ASSERT_EQ(index, 2); |
4668 if (IsDoubleOrFloatElementsKind(elements_kind())) { | 4678 if (IsDoubleOrFloatElementsKind(elements_kind())) { |
4669 return Representation::Double(); | 4679 return Representation::Double(); |
4670 } | 4680 } |
4671 | 4681 |
4672 return is_external() ? Representation::Integer32() | 4682 return is_external() ? Representation::Integer32() |
4673 : Representation::Tagged(); | 4683 : Representation::Tagged(); |
4674 } | 4684 } |
(...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5446 virtual bool IsDeletable() const { return true; } | 5456 virtual bool IsDeletable() const { return true; } |
5447 }; | 5457 }; |
5448 | 5458 |
5449 | 5459 |
5450 #undef DECLARE_INSTRUCTION | 5460 #undef DECLARE_INSTRUCTION |
5451 #undef DECLARE_CONCRETE_INSTRUCTION | 5461 #undef DECLARE_CONCRETE_INSTRUCTION |
5452 | 5462 |
5453 } } // namespace v8::internal | 5463 } } // namespace v8::internal |
5454 | 5464 |
5455 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 5465 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |