| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ | 5 #ifndef V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ |
| 6 #define V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ | 6 #define V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ |
| 7 | 7 |
| 8 #include <cstring> | 8 #include <cstring> |
| 9 #include <iosfwd> | 9 #include <iosfwd> |
| 10 | 10 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 V(AccessArgumentsAt) \ | 49 V(AccessArgumentsAt) \ |
| 50 V(Add) \ | 50 V(Add) \ |
| 51 V(Allocate) \ | 51 V(Allocate) \ |
| 52 V(ApplyArguments) \ | 52 V(ApplyArguments) \ |
| 53 V(ArgumentsElements) \ | 53 V(ArgumentsElements) \ |
| 54 V(ArgumentsLength) \ | 54 V(ArgumentsLength) \ |
| 55 V(ArgumentsObject) \ | 55 V(ArgumentsObject) \ |
| 56 V(Bitwise) \ | 56 V(Bitwise) \ |
| 57 V(BlockEntry) \ | 57 V(BlockEntry) \ |
| 58 V(BoundsCheck) \ | 58 V(BoundsCheck) \ |
| 59 V(BoundsCheckBaseIndexInformation) \ | |
| 60 V(Branch) \ | 59 V(Branch) \ |
| 61 V(CallWithDescriptor) \ | 60 V(CallWithDescriptor) \ |
| 62 V(CallNewArray) \ | 61 V(CallNewArray) \ |
| 63 V(CallRuntime) \ | 62 V(CallRuntime) \ |
| 64 V(CapturedObject) \ | 63 V(CapturedObject) \ |
| 65 V(Change) \ | 64 V(Change) \ |
| 66 V(CheckArrayBufferNotNeutered) \ | 65 V(CheckArrayBufferNotNeutered) \ |
| 67 V(CheckHeapObject) \ | 66 V(CheckHeapObject) \ |
| 68 V(CheckInstanceType) \ | 67 V(CheckInstanceType) \ |
| 69 V(CheckMaps) \ | 68 V(CheckMaps) \ |
| (...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 | 724 |
| 726 // Check if this instruction has some reason that prevents elimination. | 725 // Check if this instruction has some reason that prevents elimination. |
| 727 bool CannotBeEliminated() const { | 726 bool CannotBeEliminated() const { |
| 728 return HasObservableSideEffects() || !IsDeletable(); | 727 return HasObservableSideEffects() || !IsDeletable(); |
| 729 } | 728 } |
| 730 | 729 |
| 731 #ifdef DEBUG | 730 #ifdef DEBUG |
| 732 virtual void Verify() = 0; | 731 virtual void Verify() = 0; |
| 733 #endif | 732 #endif |
| 734 | 733 |
| 735 virtual bool TryDecompose(DecompositionResult* decomposition) { | |
| 736 if (RedefinedOperand() != NULL) { | |
| 737 return RedefinedOperand()->TryDecompose(decomposition); | |
| 738 } else { | |
| 739 return false; | |
| 740 } | |
| 741 } | |
| 742 | |
| 743 // Returns true conservatively if the program might be able to observe a | 734 // Returns true conservatively if the program might be able to observe a |
| 744 // ToString() operation on this value. | 735 // ToString() operation on this value. |
| 745 bool ToStringCanBeObserved() const { | 736 bool ToStringCanBeObserved() const { |
| 746 return ToStringOrToNumberCanBeObserved(); | 737 return ToStringOrToNumberCanBeObserved(); |
| 747 } | 738 } |
| 748 | 739 |
| 749 // Returns true conservatively if the program might be able to observe a | 740 // Returns true conservatively if the program might be able to observe a |
| 750 // ToNumber() operation on this value. | 741 // ToNumber() operation on this value. |
| 751 bool ToNumberCanBeObserved() const { | 742 bool ToNumberCanBeObserved() const { |
| 752 return ToStringOrToNumberCanBeObserved(); | 743 return ToStringOrToNumberCanBeObserved(); |
| (...skipping 2188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2941 bool DataEquals(HValue* other) override { return true; } | 2932 bool DataEquals(HValue* other) override { return true; } |
| 2942 | 2933 |
| 2943 private: | 2934 private: |
| 2944 explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) { | 2935 explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) { |
| 2945 set_representation(Representation::Tagged()); | 2936 set_representation(Representation::Tagged()); |
| 2946 SetFlag(kUseGVN); | 2937 SetFlag(kUseGVN); |
| 2947 } | 2938 } |
| 2948 }; | 2939 }; |
| 2949 | 2940 |
| 2950 | 2941 |
| 2951 class InductionVariableData; | |
| 2952 | |
| 2953 | |
| 2954 struct InductionVariableLimitUpdate { | |
| 2955 InductionVariableData* updated_variable; | |
| 2956 HValue* limit; | |
| 2957 bool limit_is_upper; | |
| 2958 bool limit_is_included; | |
| 2959 | |
| 2960 InductionVariableLimitUpdate() | |
| 2961 : updated_variable(NULL), limit(NULL), | |
| 2962 limit_is_upper(false), limit_is_included(false) {} | |
| 2963 }; | |
| 2964 | |
| 2965 | |
| 2966 class HBoundsCheck; | |
| 2967 class HPhi; | |
| 2968 class HBitwise; | |
| 2969 | |
| 2970 | |
| 2971 class InductionVariableData final : public ZoneObject { | |
| 2972 public: | |
| 2973 class InductionVariableCheck : public ZoneObject { | |
| 2974 public: | |
| 2975 HBoundsCheck* check() { return check_; } | |
| 2976 InductionVariableCheck* next() { return next_; } | |
| 2977 bool HasUpperLimit() { return upper_limit_ >= 0; } | |
| 2978 int32_t upper_limit() { | |
| 2979 DCHECK(HasUpperLimit()); | |
| 2980 return upper_limit_; | |
| 2981 } | |
| 2982 void set_upper_limit(int32_t upper_limit) { | |
| 2983 upper_limit_ = upper_limit; | |
| 2984 } | |
| 2985 | |
| 2986 bool processed() { return processed_; } | |
| 2987 void set_processed() { processed_ = true; } | |
| 2988 | |
| 2989 InductionVariableCheck(HBoundsCheck* check, | |
| 2990 InductionVariableCheck* next, | |
| 2991 int32_t upper_limit = kNoLimit) | |
| 2992 : check_(check), next_(next), upper_limit_(upper_limit), | |
| 2993 processed_(false) {} | |
| 2994 | |
| 2995 private: | |
| 2996 HBoundsCheck* check_; | |
| 2997 InductionVariableCheck* next_; | |
| 2998 int32_t upper_limit_; | |
| 2999 bool processed_; | |
| 3000 }; | |
| 3001 | |
| 3002 class ChecksRelatedToLength : public ZoneObject { | |
| 3003 public: | |
| 3004 HValue* length() { return length_; } | |
| 3005 ChecksRelatedToLength* next() { return next_; } | |
| 3006 InductionVariableCheck* checks() { return checks_; } | |
| 3007 | |
| 3008 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit); | |
| 3009 void CloseCurrentBlock(); | |
| 3010 | |
| 3011 ChecksRelatedToLength(HValue* length, ChecksRelatedToLength* next) | |
| 3012 : length_(length), next_(next), checks_(NULL), | |
| 3013 first_check_in_block_(NULL), | |
| 3014 added_index_(NULL), | |
| 3015 added_constant_(NULL), | |
| 3016 current_and_mask_in_block_(0), | |
| 3017 current_or_mask_in_block_(0) {} | |
| 3018 | |
| 3019 private: | |
| 3020 void UseNewIndexInCurrentBlock(Token::Value token, | |
| 3021 int32_t mask, | |
| 3022 HValue* index_base, | |
| 3023 HValue* context); | |
| 3024 | |
| 3025 HBoundsCheck* first_check_in_block() { return first_check_in_block_; } | |
| 3026 HBitwise* added_index() { return added_index_; } | |
| 3027 void set_added_index(HBitwise* index) { added_index_ = index; } | |
| 3028 HConstant* added_constant() { return added_constant_; } | |
| 3029 void set_added_constant(HConstant* constant) { added_constant_ = constant; } | |
| 3030 int32_t current_and_mask_in_block() { return current_and_mask_in_block_; } | |
| 3031 int32_t current_or_mask_in_block() { return current_or_mask_in_block_; } | |
| 3032 int32_t current_upper_limit() { return current_upper_limit_; } | |
| 3033 | |
| 3034 HValue* length_; | |
| 3035 ChecksRelatedToLength* next_; | |
| 3036 InductionVariableCheck* checks_; | |
| 3037 | |
| 3038 HBoundsCheck* first_check_in_block_; | |
| 3039 HBitwise* added_index_; | |
| 3040 HConstant* added_constant_; | |
| 3041 int32_t current_and_mask_in_block_; | |
| 3042 int32_t current_or_mask_in_block_; | |
| 3043 int32_t current_upper_limit_; | |
| 3044 }; | |
| 3045 | |
| 3046 struct LimitFromPredecessorBlock { | |
| 3047 InductionVariableData* variable; | |
| 3048 Token::Value token; | |
| 3049 HValue* limit; | |
| 3050 HBasicBlock* other_target; | |
| 3051 | |
| 3052 bool LimitIsValid() { return token != Token::ILLEGAL; } | |
| 3053 | |
| 3054 bool LimitIsIncluded() { | |
| 3055 return Token::IsEqualityOp(token) || | |
| 3056 token == Token::GTE || token == Token::LTE; | |
| 3057 } | |
| 3058 bool LimitIsUpper() { | |
| 3059 return token == Token::LTE || token == Token::LT || token == Token::NE; | |
| 3060 } | |
| 3061 | |
| 3062 LimitFromPredecessorBlock() | |
| 3063 : variable(NULL), | |
| 3064 token(Token::ILLEGAL), | |
| 3065 limit(NULL), | |
| 3066 other_target(NULL) {} | |
| 3067 }; | |
| 3068 | |
| 3069 static const int32_t kNoLimit = -1; | |
| 3070 | |
| 3071 static InductionVariableData* ExaminePhi(HPhi* phi); | |
| 3072 static void ComputeLimitFromPredecessorBlock( | |
| 3073 HBasicBlock* block, | |
| 3074 LimitFromPredecessorBlock* result); | |
| 3075 static bool ComputeInductionVariableLimit( | |
| 3076 HBasicBlock* block, | |
| 3077 InductionVariableLimitUpdate* additional_limit); | |
| 3078 | |
| 3079 struct BitwiseDecompositionResult { | |
| 3080 HValue* base; | |
| 3081 int32_t and_mask; | |
| 3082 int32_t or_mask; | |
| 3083 HValue* context; | |
| 3084 | |
| 3085 BitwiseDecompositionResult() | |
| 3086 : base(NULL), and_mask(0), or_mask(0), context(NULL) {} | |
| 3087 }; | |
| 3088 static void DecomposeBitwise(HValue* value, | |
| 3089 BitwiseDecompositionResult* result); | |
| 3090 | |
| 3091 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit); | |
| 3092 | |
| 3093 bool CheckIfBranchIsLoopGuard(Token::Value token, | |
| 3094 HBasicBlock* current_branch, | |
| 3095 HBasicBlock* other_branch); | |
| 3096 | |
| 3097 void UpdateAdditionalLimit(InductionVariableLimitUpdate* update); | |
| 3098 | |
| 3099 HPhi* phi() { return phi_; } | |
| 3100 HValue* base() { return base_; } | |
| 3101 int32_t increment() { return increment_; } | |
| 3102 HValue* limit() { return limit_; } | |
| 3103 bool limit_included() { return limit_included_; } | |
| 3104 HBasicBlock* limit_validity() { return limit_validity_; } | |
| 3105 HBasicBlock* induction_exit_block() { return induction_exit_block_; } | |
| 3106 HBasicBlock* induction_exit_target() { return induction_exit_target_; } | |
| 3107 ChecksRelatedToLength* checks() { return checks_; } | |
| 3108 HValue* additional_upper_limit() { return additional_upper_limit_; } | |
| 3109 bool additional_upper_limit_is_included() { | |
| 3110 return additional_upper_limit_is_included_; | |
| 3111 } | |
| 3112 HValue* additional_lower_limit() { return additional_lower_limit_; } | |
| 3113 bool additional_lower_limit_is_included() { | |
| 3114 return additional_lower_limit_is_included_; | |
| 3115 } | |
| 3116 | |
| 3117 bool LowerLimitIsNonNegativeConstant() { | |
| 3118 if (base()->IsInteger32Constant() && base()->GetInteger32Constant() >= 0) { | |
| 3119 return true; | |
| 3120 } | |
| 3121 if (additional_lower_limit() != NULL && | |
| 3122 additional_lower_limit()->IsInteger32Constant() && | |
| 3123 additional_lower_limit()->GetInteger32Constant() >= 0) { | |
| 3124 // Ignoring the corner case of !additional_lower_limit_is_included() | |
| 3125 // is safe, handling it adds unneeded complexity. | |
| 3126 return true; | |
| 3127 } | |
| 3128 return false; | |
| 3129 } | |
| 3130 | |
| 3131 int32_t ComputeUpperLimit(int32_t and_mask, int32_t or_mask); | |
| 3132 | |
| 3133 private: | |
| 3134 template <class T> void swap(T* a, T* b) { | |
| 3135 T c(*a); | |
| 3136 *a = *b; | |
| 3137 *b = c; | |
| 3138 } | |
| 3139 | |
| 3140 InductionVariableData(HPhi* phi, HValue* base, int32_t increment) | |
| 3141 : phi_(phi), base_(IgnoreOsrValue(base)), increment_(increment), | |
| 3142 limit_(NULL), limit_included_(false), limit_validity_(NULL), | |
| 3143 induction_exit_block_(NULL), induction_exit_target_(NULL), | |
| 3144 checks_(NULL), | |
| 3145 additional_upper_limit_(NULL), | |
| 3146 additional_upper_limit_is_included_(false), | |
| 3147 additional_lower_limit_(NULL), | |
| 3148 additional_lower_limit_is_included_(false) {} | |
| 3149 | |
| 3150 static int32_t ComputeIncrement(HPhi* phi, HValue* phi_operand); | |
| 3151 | |
| 3152 static HValue* IgnoreOsrValue(HValue* v); | |
| 3153 static InductionVariableData* GetInductionVariableData(HValue* v); | |
| 3154 | |
| 3155 HPhi* phi_; | |
| 3156 HValue* base_; | |
| 3157 int32_t increment_; | |
| 3158 HValue* limit_; | |
| 3159 bool limit_included_; | |
| 3160 HBasicBlock* limit_validity_; | |
| 3161 HBasicBlock* induction_exit_block_; | |
| 3162 HBasicBlock* induction_exit_target_; | |
| 3163 ChecksRelatedToLength* checks_; | |
| 3164 HValue* additional_upper_limit_; | |
| 3165 bool additional_upper_limit_is_included_; | |
| 3166 HValue* additional_lower_limit_; | |
| 3167 bool additional_lower_limit_is_included_; | |
| 3168 }; | |
| 3169 | |
| 3170 | |
| 3171 class HPhi final : public HValue { | 2942 class HPhi final : public HValue { |
| 3172 public: | 2943 public: |
| 3173 HPhi(int merged_index, Zone* zone) | 2944 HPhi(int merged_index, Zone* zone) |
| 3174 : inputs_(2, zone), merged_index_(merged_index) { | 2945 : inputs_(2, zone), merged_index_(merged_index) { |
| 3175 DCHECK(merged_index >= 0 || merged_index == kInvalidMergedIndex); | 2946 DCHECK(merged_index >= 0 || merged_index == kInvalidMergedIndex); |
| 3176 SetFlag(kFlexibleRepresentation); | 2947 SetFlag(kFlexibleRepresentation); |
| 3177 SetFlag(kAllowUndefinedAsNaN); | 2948 SetFlag(kAllowUndefinedAsNaN); |
| 3178 } | 2949 } |
| 3179 | 2950 |
| 3180 Representation RepresentationFromInputs() override; | 2951 Representation RepresentationFromInputs() override; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3194 void AddInput(HValue* value); | 2965 void AddInput(HValue* value); |
| 3195 bool HasRealUses(); | 2966 bool HasRealUses(); |
| 3196 | 2967 |
| 3197 bool IsReceiver() const { return merged_index_ == 0; } | 2968 bool IsReceiver() const { return merged_index_ == 0; } |
| 3198 bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; } | 2969 bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; } |
| 3199 | 2970 |
| 3200 SourcePosition position() const override; | 2971 SourcePosition position() const override; |
| 3201 | 2972 |
| 3202 int merged_index() const { return merged_index_; } | 2973 int merged_index() const { return merged_index_; } |
| 3203 | 2974 |
| 3204 InductionVariableData* induction_variable_data() { | |
| 3205 return induction_variable_data_; | |
| 3206 } | |
| 3207 bool IsInductionVariable() { | |
| 3208 return induction_variable_data_ != NULL; | |
| 3209 } | |
| 3210 bool IsLimitedInductionVariable() { | |
| 3211 return IsInductionVariable() && | |
| 3212 induction_variable_data_->limit() != NULL; | |
| 3213 } | |
| 3214 void DetectInductionVariable() { | |
| 3215 DCHECK(induction_variable_data_ == NULL); | |
| 3216 induction_variable_data_ = InductionVariableData::ExaminePhi(this); | |
| 3217 } | |
| 3218 | |
| 3219 std::ostream& PrintTo(std::ostream& os) const override; // NOLINT | 2975 std::ostream& PrintTo(std::ostream& os) const override; // NOLINT |
| 3220 | 2976 |
| 3221 #ifdef DEBUG | 2977 #ifdef DEBUG |
| 3222 void Verify() override; | 2978 void Verify() override; |
| 3223 #endif | 2979 #endif |
| 3224 | 2980 |
| 3225 void InitRealUses(int id); | 2981 void InitRealUses(int id); |
| 3226 void AddNonPhiUsesFrom(HPhi* other); | 2982 void AddNonPhiUsesFrom(HPhi* other); |
| 3227 | 2983 |
| 3228 Representation representation_from_indirect_uses() const { | 2984 Representation representation_from_indirect_uses() const { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 3254 | 3010 |
| 3255 private: | 3011 private: |
| 3256 Representation representation_from_non_phi_uses() const { | 3012 Representation representation_from_non_phi_uses() const { |
| 3257 return representation_from_non_phi_uses_; | 3013 return representation_from_non_phi_uses_; |
| 3258 } | 3014 } |
| 3259 | 3015 |
| 3260 ZoneList<HValue*> inputs_; | 3016 ZoneList<HValue*> inputs_; |
| 3261 int merged_index_ = 0; | 3017 int merged_index_ = 0; |
| 3262 | 3018 |
| 3263 int phi_id_ = -1; | 3019 int phi_id_ = -1; |
| 3264 InductionVariableData* induction_variable_data_ = nullptr; | |
| 3265 | 3020 |
| 3266 Representation representation_from_indirect_uses_ = Representation::None(); | 3021 Representation representation_from_indirect_uses_ = Representation::None(); |
| 3267 Representation representation_from_non_phi_uses_ = Representation::None(); | 3022 Representation representation_from_non_phi_uses_ = Representation::None(); |
| 3268 bool has_type_feedback_from_uses_ = false; | 3023 bool has_type_feedback_from_uses_ = false; |
| 3269 | 3024 |
| 3270 bool IsDeletable() const override { return !IsReceiver(); } | 3025 bool IsDeletable() const override { return !IsReceiver(); } |
| 3271 }; | 3026 }; |
| 3272 | 3027 |
| 3273 | 3028 |
| 3274 // Common base class for HArgumentsObject and HCapturedObject. | 3029 // Common base class for HArgumentsObject and HCapturedObject. |
| (...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3931 SetFlag(kUseGVN); | 3686 SetFlag(kUseGVN); |
| 3932 SetOperandAt(0, arguments); | 3687 SetOperandAt(0, arguments); |
| 3933 SetOperandAt(1, length); | 3688 SetOperandAt(1, length); |
| 3934 SetOperandAt(2, index); | 3689 SetOperandAt(2, index); |
| 3935 } | 3690 } |
| 3936 | 3691 |
| 3937 bool DataEquals(HValue* other) override { return true; } | 3692 bool DataEquals(HValue* other) override { return true; } |
| 3938 }; | 3693 }; |
| 3939 | 3694 |
| 3940 | 3695 |
| 3941 class HBoundsCheckBaseIndexInformation; | |
| 3942 | |
| 3943 | |
| 3944 class HBoundsCheck final : public HTemplateInstruction<2> { | 3696 class HBoundsCheck final : public HTemplateInstruction<2> { |
| 3945 public: | 3697 public: |
| 3946 DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*); | 3698 DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*); |
| 3947 | 3699 |
| 3948 bool skip_check() const { return skip_check_; } | 3700 bool skip_check() const { return skip_check_; } |
| 3949 void set_skip_check() { skip_check_ = true; } | 3701 void set_skip_check() { skip_check_ = true; } |
| 3950 | 3702 |
| 3951 HValue* base() const { return base_; } | 3703 HValue* base() const { return base_; } |
| 3952 int offset() const { return offset_; } | 3704 int offset() const { return offset_; } |
| 3953 int scale() const { return scale_; } | 3705 int scale() const { return scale_; } |
| 3954 | 3706 |
| 3955 void ApplyIndexChange(); | |
| 3956 bool DetectCompoundIndex() { | |
| 3957 DCHECK(base() == NULL); | |
| 3958 | |
| 3959 DecompositionResult decomposition; | |
| 3960 if (index()->TryDecompose(&decomposition)) { | |
| 3961 base_ = decomposition.base(); | |
| 3962 offset_ = decomposition.offset(); | |
| 3963 scale_ = decomposition.scale(); | |
| 3964 return true; | |
| 3965 } else { | |
| 3966 base_ = index(); | |
| 3967 offset_ = 0; | |
| 3968 scale_ = 0; | |
| 3969 return false; | |
| 3970 } | |
| 3971 } | |
| 3972 | |
| 3973 Representation RequiredInputRepresentation(int index) override { | 3707 Representation RequiredInputRepresentation(int index) override { |
| 3974 return representation(); | 3708 return representation(); |
| 3975 } | 3709 } |
| 3976 | 3710 |
| 3977 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT | 3711 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT |
| 3978 void InferRepresentation(HInferRepresentationPhase* h_infer) override; | 3712 void InferRepresentation(HInferRepresentationPhase* h_infer) override; |
| 3979 | 3713 |
| 3980 HValue* index() const { return OperandAt(0); } | 3714 HValue* index() const { return OperandAt(0); } |
| 3981 HValue* length() const { return OperandAt(1); } | 3715 HValue* length() const { return OperandAt(1); } |
| 3982 bool allow_equality() const { return allow_equality_; } | 3716 bool allow_equality() const { return allow_equality_; } |
| 3983 void set_allow_equality(bool v) { allow_equality_ = v; } | 3717 void set_allow_equality(bool v) { allow_equality_ = v; } |
| 3984 | 3718 |
| 3985 int RedefinedOperandIndex() override { return 0; } | 3719 int RedefinedOperandIndex() override { return 0; } |
| 3986 bool IsPurelyInformativeDefinition() override { return skip_check(); } | 3720 bool IsPurelyInformativeDefinition() override { return skip_check(); } |
| 3987 | 3721 |
| 3988 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) | 3722 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) |
| 3989 | 3723 |
| 3990 protected: | 3724 protected: |
| 3991 friend class HBoundsCheckBaseIndexInformation; | |
| 3992 | |
| 3993 Range* InferRange(Zone* zone) override; | 3725 Range* InferRange(Zone* zone) override; |
| 3994 | 3726 |
| 3995 bool DataEquals(HValue* other) override { return true; } | 3727 bool DataEquals(HValue* other) override { return true; } |
| 3996 bool skip_check_; | 3728 bool skip_check_; |
| 3997 HValue* base_; | 3729 HValue* base_; |
| 3998 int offset_; | 3730 int offset_; |
| 3999 int scale_; | 3731 int scale_; |
| 4000 bool allow_equality_; | 3732 bool allow_equality_; |
| 4001 | 3733 |
| 4002 private: | 3734 private: |
| 4003 // Normally HBoundsCheck should be created using the | 3735 // Normally HBoundsCheck should be created using the |
| 4004 // HGraphBuilder::AddBoundsCheck() helper. | 3736 // HGraphBuilder::AddBoundsCheck() helper. |
| 4005 // However when building stubs, where we know that the arguments are Int32, | 3737 // However when building stubs, where we know that the arguments are Int32, |
| 4006 // it makes sense to invoke this constructor directly. | 3738 // it makes sense to invoke this constructor directly. |
| 4007 HBoundsCheck(HValue* index, HValue* length) | 3739 HBoundsCheck(HValue* index, HValue* length) |
| 4008 : skip_check_(false), | 3740 : skip_check_(false), |
| 4009 base_(NULL), offset_(0), scale_(0), | 3741 base_(NULL), offset_(0), scale_(0), |
| 4010 allow_equality_(false) { | 3742 allow_equality_(false) { |
| 4011 SetOperandAt(0, index); | 3743 SetOperandAt(0, index); |
| 4012 SetOperandAt(1, length); | 3744 SetOperandAt(1, length); |
| 4013 SetFlag(kFlexibleRepresentation); | 3745 SetFlag(kFlexibleRepresentation); |
| 4014 SetFlag(kUseGVN); | 3746 SetFlag(kUseGVN); |
| 4015 } | 3747 } |
| 4016 | 3748 |
| 4017 bool IsDeletable() const override { return skip_check() && !FLAG_debug_code; } | 3749 bool IsDeletable() const override { return skip_check() && !FLAG_debug_code; } |
| 4018 }; | 3750 }; |
| 4019 | 3751 |
| 4020 | 3752 |
| 4021 class HBoundsCheckBaseIndexInformation final : public HTemplateInstruction<2> { | |
| 4022 public: | |
| 4023 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) { | |
| 4024 DecompositionResult decomposition; | |
| 4025 if (check->index()->TryDecompose(&decomposition)) { | |
| 4026 SetOperandAt(0, decomposition.base()); | |
| 4027 SetOperandAt(1, check); | |
| 4028 } else { | |
| 4029 UNREACHABLE(); | |
| 4030 } | |
| 4031 } | |
| 4032 | |
| 4033 HValue* base_index() const { return OperandAt(0); } | |
| 4034 HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); } | |
| 4035 | |
| 4036 DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation) | |
| 4037 | |
| 4038 Representation RequiredInputRepresentation(int index) override { | |
| 4039 return representation(); | |
| 4040 } | |
| 4041 | |
| 4042 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT | |
| 4043 | |
| 4044 int RedefinedOperandIndex() override { return 0; } | |
| 4045 bool IsPurelyInformativeDefinition() override { return true; } | |
| 4046 }; | |
| 4047 | |
| 4048 | |
| 4049 class HBitwiseBinaryOperation : public HBinaryOperation { | 3753 class HBitwiseBinaryOperation : public HBinaryOperation { |
| 4050 public: | 3754 public: |
| 4051 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right, | 3755 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right, |
| 4052 HType type = HType::TaggedNumber()) | 3756 HType type = HType::TaggedNumber()) |
| 4053 : HBinaryOperation(context, left, right, type) { | 3757 : HBinaryOperation(context, left, right, type) { |
| 4054 SetFlag(kFlexibleRepresentation); | 3758 SetFlag(kFlexibleRepresentation); |
| 4055 SetFlag(kTruncatingToInt32); | 3759 SetFlag(kTruncatingToInt32); |
| 4056 SetAllSideEffects(); | 3760 SetAllSideEffects(); |
| 4057 } | 3761 } |
| 4058 | 3762 |
| (...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4661 | 4365 |
| 4662 // Add is only commutative if two integer values are added and not if two | 4366 // Add is only commutative if two integer values are added and not if two |
| 4663 // tagged values are added (because it might be a String concatenation). | 4367 // tagged values are added (because it might be a String concatenation). |
| 4664 // We also do not commute (pointer + offset). | 4368 // We also do not commute (pointer + offset). |
| 4665 bool IsCommutative() const override { | 4369 bool IsCommutative() const override { |
| 4666 return !representation().IsTagged() && !representation().IsExternal(); | 4370 return !representation().IsTagged() && !representation().IsExternal(); |
| 4667 } | 4371 } |
| 4668 | 4372 |
| 4669 HValue* Canonicalize() override; | 4373 HValue* Canonicalize() override; |
| 4670 | 4374 |
| 4671 bool TryDecompose(DecompositionResult* decomposition) override { | |
| 4672 if (left()->IsInteger32Constant()) { | |
| 4673 decomposition->Apply(right(), left()->GetInteger32Constant()); | |
| 4674 return true; | |
| 4675 } else if (right()->IsInteger32Constant()) { | |
| 4676 decomposition->Apply(left(), right()->GetInteger32Constant()); | |
| 4677 return true; | |
| 4678 } else { | |
| 4679 return false; | |
| 4680 } | |
| 4681 } | |
| 4682 | |
| 4683 void RepresentationChanged(Representation to) override { | 4375 void RepresentationChanged(Representation to) override { |
| 4684 if (to.IsTagged() && | 4376 if (to.IsTagged() && |
| 4685 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() || | 4377 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() || |
| 4686 left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) { | 4378 left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) { |
| 4687 SetAllSideEffects(); | 4379 SetAllSideEffects(); |
| 4688 ClearFlag(kUseGVN); | 4380 ClearFlag(kUseGVN); |
| 4689 } else { | 4381 } else { |
| 4690 ClearAllSideEffects(); | 4382 ClearAllSideEffects(); |
| 4691 SetFlag(kUseGVN); | 4383 SetFlag(kUseGVN); |
| 4692 } | 4384 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4752 }; | 4444 }; |
| 4753 | 4445 |
| 4754 | 4446 |
| 4755 class HSub final : public HArithmeticBinaryOperation { | 4447 class HSub final : public HArithmeticBinaryOperation { |
| 4756 public: | 4448 public: |
| 4757 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context, | 4449 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context, |
| 4758 HValue* left, HValue* right); | 4450 HValue* left, HValue* right); |
| 4759 | 4451 |
| 4760 HValue* Canonicalize() override; | 4452 HValue* Canonicalize() override; |
| 4761 | 4453 |
| 4762 bool TryDecompose(DecompositionResult* decomposition) override { | |
| 4763 if (right()->IsInteger32Constant()) { | |
| 4764 decomposition->Apply(left(), -right()->GetInteger32Constant()); | |
| 4765 return true; | |
| 4766 } else { | |
| 4767 return false; | |
| 4768 } | |
| 4769 } | |
| 4770 | |
| 4771 DECLARE_CONCRETE_INSTRUCTION(Sub) | 4454 DECLARE_CONCRETE_INSTRUCTION(Sub) |
| 4772 | 4455 |
| 4773 protected: | 4456 protected: |
| 4774 bool DataEquals(HValue* other) override { return true; } | 4457 bool DataEquals(HValue* other) override { return true; } |
| 4775 | 4458 |
| 4776 Range* InferRange(Zone* zone) override; | 4459 Range* InferRange(Zone* zone) override; |
| 4777 | 4460 |
| 4778 private: | 4461 private: |
| 4779 HSub(HValue* context, HValue* left, HValue* right) | 4462 HSub(HValue* context, HValue* left, HValue* right) |
| 4780 : HArithmeticBinaryOperation(context, left, right) { | 4463 : HArithmeticBinaryOperation(context, left, right) { |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5015 HShl(HValue* context, HValue* left, HValue* right) | 4698 HShl(HValue* context, HValue* left, HValue* right) |
| 5016 : HBitwiseBinaryOperation(context, left, right) {} | 4699 : HBitwiseBinaryOperation(context, left, right) {} |
| 5017 }; | 4700 }; |
| 5018 | 4701 |
| 5019 | 4702 |
| 5020 class HShr final : public HBitwiseBinaryOperation { | 4703 class HShr final : public HBitwiseBinaryOperation { |
| 5021 public: | 4704 public: |
| 5022 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context, | 4705 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context, |
| 5023 HValue* left, HValue* right); | 4706 HValue* left, HValue* right); |
| 5024 | 4707 |
| 5025 bool TryDecompose(DecompositionResult* decomposition) override { | |
| 5026 if (right()->IsInteger32Constant()) { | |
| 5027 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) { | |
| 5028 // This is intended to look for HAdd and HSub, to handle compounds | |
| 5029 // like ((base + offset) >> scale) with one single decomposition. | |
| 5030 left()->TryDecompose(decomposition); | |
| 5031 return true; | |
| 5032 } | |
| 5033 } | |
| 5034 return false; | |
| 5035 } | |
| 5036 | |
| 5037 Range* InferRange(Zone* zone) override; | 4708 Range* InferRange(Zone* zone) override; |
| 5038 | 4709 |
| 5039 void UpdateRepresentation(Representation new_rep, | 4710 void UpdateRepresentation(Representation new_rep, |
| 5040 HInferRepresentationPhase* h_infer, | 4711 HInferRepresentationPhase* h_infer, |
| 5041 const char* reason) override { | 4712 const char* reason) override { |
| 5042 if (new_rep.IsSmi()) new_rep = Representation::Integer32(); | 4713 if (new_rep.IsSmi()) new_rep = Representation::Integer32(); |
| 5043 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); | 4714 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); |
| 5044 } | 4715 } |
| 5045 | 4716 |
| 5046 DECLARE_CONCRETE_INSTRUCTION(Shr) | 4717 DECLARE_CONCRETE_INSTRUCTION(Shr) |
| 5047 | 4718 |
| 5048 protected: | 4719 protected: |
| 5049 bool DataEquals(HValue* other) override { return true; } | 4720 bool DataEquals(HValue* other) override { return true; } |
| 5050 | 4721 |
| 5051 private: | 4722 private: |
| 5052 HShr(HValue* context, HValue* left, HValue* right) | 4723 HShr(HValue* context, HValue* left, HValue* right) |
| 5053 : HBitwiseBinaryOperation(context, left, right) {} | 4724 : HBitwiseBinaryOperation(context, left, right) {} |
| 5054 }; | 4725 }; |
| 5055 | 4726 |
| 5056 | 4727 |
| 5057 class HSar final : public HBitwiseBinaryOperation { | 4728 class HSar final : public HBitwiseBinaryOperation { |
| 5058 public: | 4729 public: |
| 5059 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context, | 4730 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context, |
| 5060 HValue* left, HValue* right); | 4731 HValue* left, HValue* right); |
| 5061 | 4732 |
| 5062 bool TryDecompose(DecompositionResult* decomposition) override { | |
| 5063 if (right()->IsInteger32Constant()) { | |
| 5064 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) { | |
| 5065 // This is intended to look for HAdd and HSub, to handle compounds | |
| 5066 // like ((base + offset) >> scale) with one single decomposition. | |
| 5067 left()->TryDecompose(decomposition); | |
| 5068 return true; | |
| 5069 } | |
| 5070 } | |
| 5071 return false; | |
| 5072 } | |
| 5073 | |
| 5074 Range* InferRange(Zone* zone) override; | 4733 Range* InferRange(Zone* zone) override; |
| 5075 | 4734 |
| 5076 void UpdateRepresentation(Representation new_rep, | 4735 void UpdateRepresentation(Representation new_rep, |
| 5077 HInferRepresentationPhase* h_infer, | 4736 HInferRepresentationPhase* h_infer, |
| 5078 const char* reason) override { | 4737 const char* reason) override { |
| 5079 if (new_rep.IsSmi()) new_rep = Representation::Integer32(); | 4738 if (new_rep.IsSmi()) new_rep = Representation::Integer32(); |
| 5080 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); | 4739 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); |
| 5081 } | 4740 } |
| 5082 | 4741 |
| 5083 DECLARE_CONCRETE_INSTRUCTION(Sar) | 4742 DECLARE_CONCRETE_INSTRUCTION(Sar) |
| (...skipping 2507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7591 | 7250 |
| 7592 | 7251 |
| 7593 | 7252 |
| 7594 #undef DECLARE_INSTRUCTION | 7253 #undef DECLARE_INSTRUCTION |
| 7595 #undef DECLARE_CONCRETE_INSTRUCTION | 7254 #undef DECLARE_CONCRETE_INSTRUCTION |
| 7596 | 7255 |
| 7597 } // namespace internal | 7256 } // namespace internal |
| 7598 } // namespace v8 | 7257 } // namespace v8 |
| 7599 | 7258 |
| 7600 #endif // V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ | 7259 #endif // V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ |
| OLD | NEW |