Chromium Code Reviews| 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 |