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 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
666 // If the operation also exists in a form that takes int32 and outputs int32 | 666 // If the operation also exists in a form that takes int32 and outputs int32 |
667 // then the operation should return its input value so that we can propagate | 667 // then the operation should return its input value so that we can propagate |
668 // back. There are three operations that need to propagate back to more than | 668 // back. There are three operations that need to propagate back to more than |
669 // one input. They are phi and binary div and mul. They always return NULL | 669 // one input. They are phi and binary div and mul. They always return NULL |
670 // and expect the caller to take care of things. | 670 // and expect the caller to take care of things. |
671 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) { | 671 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) { |
672 visited->Add(id()); | 672 visited->Add(id()); |
673 return NULL; | 673 return NULL; |
674 } | 674 } |
675 | 675 |
676 // There are HInstructions that do not really change a value, they | |
677 // only add pieces of information to it (like bounds checks, map checks, | |
678 // smi checks...). | |
679 // We call these instructions "informative definitions", or "iDef". | |
680 // One of the iDef operands is special because it is the value that is | |
681 // "transferred" to the output, we call it the "redefined operand". | |
682 // If an HValue is an iDef it must override RedefinedOperandIndex() so that | |
683 // it does not return kNoRedefinedOperand; | |
684 static const int kNoRedefinedOperand = -1; | |
685 virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; } | |
686 bool IsInformativelDefinition() { | |
Jakob Kummerow
2013/01/29 10:33:01
nit: s/IsInformativelDefinition/IsInformativeDefin
Massi
2013/01/29 15:39:00
Done.
| |
687 return RedefinedOperandIndex() != kNoRedefinedOperand; | |
688 } | |
689 HValue* RedefinedOperand() { | |
690 ASSERT(IsInformativelDefinition()); | |
691 return OperandAt(RedefinedOperandIndex()); | |
692 } | |
693 | |
694 // This method must always return the original HValue SSA definition | |
695 // (regardless of any iDef of this value). | |
696 HValue* ActualValue() { | |
697 return IsInformativelDefinition() | |
698 ? RedefinedOperand()->ActualValue() : this; | |
Jakob Kummerow
2013/01/29 10:33:01
nit: preferred formatting:
return IsInformati
Massi
2013/01/29 15:39:00
Done.
| |
699 } | |
700 | |
676 bool IsDefinedAfter(HBasicBlock* other) const; | 701 bool IsDefinedAfter(HBasicBlock* other) const; |
677 | 702 |
678 // Operands. | 703 // Operands. |
679 virtual int OperandCount() = 0; | 704 virtual int OperandCount() = 0; |
680 virtual HValue* OperandAt(int index) const = 0; | 705 virtual HValue* OperandAt(int index) const = 0; |
681 void SetOperandAt(int index, HValue* value); | 706 void SetOperandAt(int index, HValue* value); |
682 | 707 |
683 void DeleteAndReplaceWith(HValue* other); | 708 void DeleteAndReplaceWith(HValue* other); |
684 void ReplaceAllUsesWith(HValue* other); | 709 void ReplaceAllUsesWith(HValue* other); |
685 bool HasNoUses() const { return use_list_ == NULL; } | 710 bool HasNoUses() const { return use_list_ == NULL; } |
(...skipping 2327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3013 | 3038 |
3014 enum BoundsCheckKeyMode { | 3039 enum BoundsCheckKeyMode { |
3015 DONT_ALLOW_SMI_KEY, | 3040 DONT_ALLOW_SMI_KEY, |
3016 ALLOW_SMI_KEY | 3041 ALLOW_SMI_KEY |
3017 }; | 3042 }; |
3018 | 3043 |
3019 | 3044 |
3020 class HBoundsCheck: public HTemplateInstruction<2> { | 3045 class HBoundsCheck: public HTemplateInstruction<2> { |
3021 public: | 3046 public: |
3022 HBoundsCheck(HValue* index, HValue* length, | 3047 HBoundsCheck(HValue* index, HValue* length, |
3023 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY) | 3048 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY, |
3049 Representation r = Representation::None()) | |
3024 : key_mode_(key_mode) { | 3050 : key_mode_(key_mode) { |
3025 SetOperandAt(0, index); | 3051 SetOperandAt(0, index); |
3026 SetOperandAt(1, length); | 3052 SetOperandAt(1, length); |
3027 set_representation(Representation::Integer32()); | 3053 if (r.IsNone()) { |
3054 // In the normal compilation pipeline the representation is flexible | |
3055 // (see comment to RequiredInputRepresentation). | |
3056 SetFlag(kFlexibleRepresentation); | |
3057 } else { | |
3058 // When compiling stubs we want to set the representation explicitly | |
3059 // so the compilation pipeline can skip the HInferRepresentation phase. | |
3060 set_representation(r); | |
3061 } | |
3028 SetFlag(kUseGVN); | 3062 SetFlag(kUseGVN); |
3029 } | 3063 } |
3030 | 3064 |
3031 virtual Representation RequiredInputRepresentation(int arg_index) { | 3065 virtual Representation RequiredInputRepresentation(int arg_index) { |
3032 if (key_mode_ == DONT_ALLOW_SMI_KEY || | 3066 return representation(); |
3033 !length()->representation().IsTagged()) { | |
3034 return Representation::Integer32(); | |
3035 } | |
3036 // If the index is tagged and isn't constant, then allow the length | |
3037 // to be tagged, since it is usually already tagged from loading it out of | |
3038 // the length field of a JSArray. This allows for direct comparison without | |
3039 // untagging. | |
3040 if (index()->representation().IsTagged() && !index()->IsConstant()) { | |
3041 return Representation::Tagged(); | |
3042 } | |
3043 // Also allow the length to be tagged if the index is constant, because | |
3044 // it can be tagged to allow direct comparison. | |
3045 if (index()->IsConstant() && | |
3046 index()->representation().IsInteger32() && | |
3047 arg_index == 1) { | |
3048 return Representation::Tagged(); | |
3049 } | |
3050 return Representation::Integer32(); | |
3051 } | 3067 } |
3052 virtual Representation observed_input_representation(int index) { | 3068 virtual Representation observed_input_representation(int index) { |
3053 return Representation::Integer32(); | 3069 return Representation::Integer32(); |
3054 } | 3070 } |
3055 | 3071 |
3056 virtual void PrintDataTo(StringStream* stream); | 3072 virtual void PrintDataTo(StringStream* stream); |
3073 virtual void InferRepresentation(HInferRepresentation* h_infer); | |
3057 | 3074 |
3058 HValue* index() { return OperandAt(0); } | 3075 HValue* index() { return OperandAt(0); } |
3059 HValue* length() { return OperandAt(1); } | 3076 HValue* length() { return OperandAt(1); } |
3060 | 3077 |
3078 virtual int RedefinedOperandIndex() { return 0; } | |
3079 | |
3061 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) | 3080 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) |
3062 | 3081 |
3063 protected: | 3082 protected: |
3064 virtual bool DataEquals(HValue* other) { return true; } | 3083 virtual bool DataEquals(HValue* other) { return true; } |
3065 BoundsCheckKeyMode key_mode_; | 3084 BoundsCheckKeyMode key_mode_; |
3066 }; | 3085 }; |
3067 | 3086 |
3068 | 3087 |
3069 class HBitwiseBinaryOperation: public HBinaryOperation { | 3088 class HBitwiseBinaryOperation: public HBinaryOperation { |
3070 public: | 3089 public: |
(...skipping 1355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4426 }; | 4445 }; |
4427 | 4446 |
4428 class ArrayInstructionInterface { | 4447 class ArrayInstructionInterface { |
4429 public: | 4448 public: |
4430 virtual HValue* GetKey() = 0; | 4449 virtual HValue* GetKey() = 0; |
4431 virtual void SetKey(HValue* key) = 0; | 4450 virtual void SetKey(HValue* key) = 0; |
4432 virtual void SetIndexOffset(uint32_t index_offset) = 0; | 4451 virtual void SetIndexOffset(uint32_t index_offset) = 0; |
4433 virtual bool IsDehoisted() = 0; | 4452 virtual bool IsDehoisted() = 0; |
4434 virtual void SetDehoisted(bool is_dehoisted) = 0; | 4453 virtual void SetDehoisted(bool is_dehoisted) = 0; |
4435 virtual ~ArrayInstructionInterface() { }; | 4454 virtual ~ArrayInstructionInterface() { }; |
4455 | |
4456 static Representation KeyedAccessIndexRequirement(Representation r) { | |
4457 return r.IsInteger32() | |
4458 ? Representation::Integer32() : Representation::Tagged(); | |
Jakob Kummerow
2013/01/29 10:33:01
nit: preferred formatting:
return r.IsInteger3
Massi
2013/01/29 15:39:00
Done.
| |
4459 } | |
4436 }; | 4460 }; |
4437 | 4461 |
4438 | 4462 |
4439 class HLoadKeyed | 4463 class HLoadKeyed |
4440 : public HTemplateInstruction<3>, public ArrayInstructionInterface { | 4464 : public HTemplateInstruction<3>, public ArrayInstructionInterface { |
4441 public: | 4465 public: |
4442 HLoadKeyed(HValue* obj, | 4466 HLoadKeyed(HValue* obj, |
4443 HValue* key, | 4467 HValue* key, |
4444 HValue* dependency, | 4468 HValue* dependency, |
4445 ElementsKind elements_kind) | 4469 ElementsKind elements_kind) |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4509 } | 4533 } |
4510 | 4534 |
4511 virtual Representation RequiredInputRepresentation(int index) { | 4535 virtual Representation RequiredInputRepresentation(int index) { |
4512 // kind_fast: tagged[int32] (none) | 4536 // kind_fast: tagged[int32] (none) |
4513 // kind_double: tagged[int32] (none) | 4537 // kind_double: tagged[int32] (none) |
4514 // kind_external: external[int32] (none) | 4538 // kind_external: external[int32] (none) |
4515 if (index == 0) { | 4539 if (index == 0) { |
4516 return is_external() ? Representation::External() | 4540 return is_external() ? Representation::External() |
4517 : Representation::Tagged(); | 4541 : Representation::Tagged(); |
4518 } | 4542 } |
4519 if (index == 1) return Representation::Integer32(); | 4543 if (index == 1) { |
4544 return ArrayInstructionInterface::KeyedAccessIndexRequirement( | |
4545 OperandAt(1)->representation()); | |
4546 } | |
4520 return Representation::None(); | 4547 return Representation::None(); |
4521 } | 4548 } |
4522 | 4549 |
4523 virtual Representation observed_input_representation(int index) { | 4550 virtual Representation observed_input_representation(int index) { |
4524 return RequiredInputRepresentation(index); | 4551 return RequiredInputRepresentation(index); |
4525 } | 4552 } |
4526 | 4553 |
4527 virtual void PrintDataTo(StringStream* stream); | 4554 virtual void PrintDataTo(StringStream* stream); |
4528 | 4555 |
4529 bool RequiresHoleCheck() const; | 4556 bool RequiresHoleCheck() const; |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4724 } | 4751 } |
4725 | 4752 |
4726 virtual Representation RequiredInputRepresentation(int index) { | 4753 virtual Representation RequiredInputRepresentation(int index) { |
4727 // kind_fast: tagged[int32] = tagged | 4754 // kind_fast: tagged[int32] = tagged |
4728 // kind_double: tagged[int32] = double | 4755 // kind_double: tagged[int32] = double |
4729 // kind_external: external[int32] = (double | int32) | 4756 // kind_external: external[int32] = (double | int32) |
4730 if (index == 0) { | 4757 if (index == 0) { |
4731 return is_external() ? Representation::External() | 4758 return is_external() ? Representation::External() |
4732 : Representation::Tagged(); | 4759 : Representation::Tagged(); |
4733 } else if (index == 1) { | 4760 } else if (index == 1) { |
4734 return Representation::Integer32(); | 4761 return ArrayInstructionInterface::KeyedAccessIndexRequirement( |
4762 OperandAt(1)->representation()); | |
4735 } | 4763 } |
4736 | 4764 |
4737 ASSERT_EQ(index, 2); | 4765 ASSERT_EQ(index, 2); |
4738 if (IsDoubleOrFloatElementsKind(elements_kind())) { | 4766 if (IsDoubleOrFloatElementsKind(elements_kind())) { |
4739 return Representation::Double(); | 4767 return Representation::Double(); |
4740 } | 4768 } |
4741 | 4769 |
4742 return is_external() ? Representation::Integer32() | 4770 return is_external() ? Representation::Integer32() |
4743 : Representation::Tagged(); | 4771 : Representation::Tagged(); |
4744 } | 4772 } |
(...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5539 virtual bool IsDeletable() const { return true; } | 5567 virtual bool IsDeletable() const { return true; } |
5540 }; | 5568 }; |
5541 | 5569 |
5542 | 5570 |
5543 #undef DECLARE_INSTRUCTION | 5571 #undef DECLARE_INSTRUCTION |
5544 #undef DECLARE_CONCRETE_INSTRUCTION | 5572 #undef DECLARE_CONCRETE_INSTRUCTION |
5545 | 5573 |
5546 } } // namespace v8::internal | 5574 } } // namespace v8::internal |
5547 | 5575 |
5548 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 5576 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |