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 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
153 void HValue::AddDependantsToWorklist(HInferRepresentation* h_infer) { | 153 void HValue::AddDependantsToWorklist(HInferRepresentation* h_infer) { |
154 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { | 154 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { |
155 h_infer->AddToWorklist(it.value()); | 155 h_infer->AddToWorklist(it.value()); |
156 } | 156 } |
157 for (int i = 0; i < OperandCount(); ++i) { | 157 for (int i = 0; i < OperandCount(); ++i) { |
158 h_infer->AddToWorklist(OperandAt(i)); | 158 h_infer->AddToWorklist(OperandAt(i)); |
159 } | 159 } |
160 } | 160 } |
161 | 161 |
162 | 162 |
163 // This method is recursive but it is guaranteed to terminate because | |
164 // RedefinedOperand() always dominates "this". | |
165 bool HValue::IsRelationTrue(NumericRelation relation, | |
166 HValue* other, | |
167 int offset, | |
168 int scale) { | |
169 if (this == other) { | |
170 return NumericRelation::Eq().Implies(relation); | |
171 } | |
172 | |
173 // Test the direct relation. | |
174 if (IsRelationTrueInternal(relation, other, offset, scale)) return true; | |
175 | |
176 // If scale is 0 try the reversed relation.. | |
Jakob Kummerow
2013/03/14 12:50:09
nit: s/.././
Massi
2013/03/14 15:07:18
Done.
| |
177 if (scale == 0 && | |
178 // TODO(mmassi): do we need the full, recursive IsRelationTrue? | |
179 other->IsRelationTrueInternal(relation.Reversed(), this, -offset)) { | |
180 return true; | |
181 } | |
182 | |
183 // Try decomposition. | |
184 HValue* my_base = NULL; | |
185 int my_offset = 0; | |
186 int my_scale = 0; | |
187 if (TryDecompose(&my_base, &my_offset, &my_scale) && my_scale == 0 && | |
188 my_base->IsRelationTrue(relation, other, offset + my_offset, scale)) { | |
189 return true; | |
190 } | |
191 | |
192 // Pass the request to the redefined value. | |
193 HValue* redefined = RedefinedOperand(); | |
194 return redefined != NULL && redefined->IsRelationTrue(relation, other, | |
195 offset, scale); | |
196 } | |
197 | |
198 | |
199 bool HValue::TryGuaranteeRange(HValue* upper_bound) { | |
200 RangeEvaluationContext context = RangeEvaluationContext(this, upper_bound); | |
201 TryGuaranteeRangeRecursive(&context); | |
202 bool result = context.is_range_satisfied(); | |
203 if (result) { | |
204 context.lower_check_guarantee()->SetResponsibilityForRange(DIRECTION_LOWER); | |
205 context.upper_check_guarantee()->SetResponsibilityForRange(DIRECTION_UPPER); | |
206 } | |
207 return result; | |
208 } | |
209 | |
210 | |
211 void HValue::TryGuaranteeRangeRecursive(RangeEvaluationContext* context) { | |
212 // Check if we already know that this value satisfies the lower bound. | |
213 if (!context->is_lower_bound_satisfied()) { | |
214 if (IsRelationTrueInternal(NumericRelation::Ge(), context->lower_bound(), | |
215 context->offset(), context->scale())) { | |
216 context->set_lower_check_guarantee(this); | |
217 } | |
218 } | |
219 | |
220 // Check if we already know that this value satisfies the upper bound. | |
221 if (!context->is_upper_bound_satisfied()) { | |
222 if (IsRelationTrueInternal(NumericRelation::Lt(), context->upper_bound(), | |
223 context->offset(), context->scale()) || | |
224 (context->scale() == 0 && | |
225 context->upper_bound()->IsRelationTrue(NumericRelation::Gt(), | |
226 this, -context->offset()))) { | |
227 context->set_upper_check_guarantee(this); | |
228 } | |
229 } | |
230 | |
231 if (context->is_range_satisfied()) return; | |
232 | |
233 // See if our RedefinedOperand() satisfies the constraints. | |
234 if (RedefinedOperand() != NULL) { | |
235 RedefinedOperand()->TryGuaranteeRangeRecursive(context); | |
236 } | |
237 if (context->is_range_satisfied()) return; | |
238 | |
239 // See if the constraints can be satisfied by decomposition. | |
240 HValue* base = NULL; | |
241 int offset = context->offset(); | |
242 int scale = context->scale(); | |
243 if (TryDecompose(&base, &offset, &scale)) { | |
244 context->swap_candidate(&base, &offset, &scale); | |
245 context->candidate()->TryGuaranteeRangeRecursive(context); | |
246 context->swap_candidate(&base, &offset, &scale); | |
247 } | |
248 if (context->is_range_satisfied()) return; | |
249 | |
250 // Try to modify this to satisfy the constraint. | |
251 | |
252 TryGuaranteeRangeChanging(context); | |
253 } | |
254 | |
255 | |
256 RangeEvaluationContext::RangeEvaluationContext(HValue* value, HValue* upper) | |
257 : lower_bound_(upper->block()->graph()->GetConstant0()), | |
258 lower_check_guarantee_(NULL), | |
259 candidate_(value), | |
260 upper_bound_(upper), | |
261 upper_check_guarantee_(NULL), | |
262 offset_(0), | |
263 scale_(0) { | |
264 } | |
265 | |
266 | |
267 HValue* RangeEvaluationContext::ConvertGuarantee(HValue* guarantee) { | |
268 return guarantee->IsBoundsCheckBaseIndexInformation() | |
269 ? HBoundsCheckBaseIndexInformation::cast(guarantee)->bounds_check() | |
270 : guarantee; | |
271 } | |
272 | |
273 | |
163 static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) { | 274 static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) { |
164 if (result > kMaxInt) { | 275 if (result > kMaxInt) { |
165 *overflow = true; | 276 *overflow = true; |
166 return kMaxInt; | 277 return kMaxInt; |
167 } | 278 } |
168 if (result < kMinInt) { | 279 if (result < kMinInt) { |
169 *overflow = true; | 280 *overflow = true; |
170 return kMinInt; | 281 return kMinInt; |
171 } | 282 } |
172 return static_cast<int32_t>(result); | 283 return static_cast<int32_t>(result); |
(...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
878 | 989 |
879 void HBinaryCall::PrintDataTo(StringStream* stream) { | 990 void HBinaryCall::PrintDataTo(StringStream* stream) { |
880 first()->PrintNameTo(stream); | 991 first()->PrintNameTo(stream); |
881 stream->Add(" "); | 992 stream->Add(" "); |
882 second()->PrintNameTo(stream); | 993 second()->PrintNameTo(stream); |
883 stream->Add(" "); | 994 stream->Add(" "); |
884 stream->Add("#%d", argument_count()); | 995 stream->Add("#%d", argument_count()); |
885 } | 996 } |
886 | 997 |
887 | 998 |
999 void HBoundsCheck::TryGuaranteeRangeChanging(RangeEvaluationContext* context) { | |
1000 if (context->candidate()->ActualValue() != base()->ActualValue() || | |
1001 context->scale() < scale()) { | |
1002 return; | |
1003 } | |
1004 | |
1005 // TODO(mmassi) | |
1006 // Instead of checking for "same basic block" we should check for | |
1007 // "dominates and postdominates". | |
1008 if (context->upper_bound() == length() && | |
1009 context->is_lower_bound_satisfied() && | |
1010 context->lower_check_guarantee() != this && | |
1011 context->lower_check_guarantee()->block() != block() && | |
1012 offset() < context->offset() && | |
1013 index_can_increase() && | |
1014 !context->is_upper_bound_satisfied()) { | |
1015 offset_ = context->offset(); | |
1016 SetResponsibilityForRange(DIRECTION_UPPER); | |
1017 context->set_upper_check_guarantee(this); | |
1018 } else if (context->is_upper_bound_satisfied() && | |
1019 context->upper_check_guarantee() != this && | |
1020 context->upper_check_guarantee()->block() != block() && | |
1021 offset() > context->offset() && | |
1022 index_can_decrease() && | |
1023 !context->is_lower_bound_satisfied()) { | |
1024 offset_ = context->offset(); | |
1025 SetResponsibilityForRange(DIRECTION_LOWER); | |
1026 context->set_lower_check_guarantee(this); | |
1027 } | |
1028 } | |
1029 | |
1030 | |
1031 void HBoundsCheck::ApplyIndexChange() { | |
1032 if (skip_check()) return; | |
1033 | |
1034 HValue* index_base = NULL; | |
1035 int index_offset = 0; | |
1036 int index_scale = 0; | |
1037 bool index_is_decomposable = index()->TryDecompose( | |
1038 &index_base, &index_offset, &index_scale); | |
1039 if (index_is_decomposable) { | |
1040 ASSERT(index_base == base()); | |
1041 if (index_offset == offset() && index_scale == scale()) return; | |
1042 } else { | |
1043 return; | |
1044 } | |
1045 | |
1046 ReplaceAllUsesWith(index()); | |
1047 | |
1048 HValue* current_index = index_base; | |
1049 int actual_offset = index_offset + offset(); | |
1050 int actual_scale = index_scale + scale(); | |
1051 | |
1052 if (actual_offset != 0) { | |
1053 HConstant* add_offset = new(block()->graph()->zone()) HConstant( | |
1054 actual_offset, index()->representation()); | |
1055 add_offset->InsertBefore(this); | |
1056 HAdd* add = new(block()->graph()->zone()) HAdd( | |
1057 block()->graph()->GetInvalidContext(), current_index, add_offset); | |
1058 add->InsertBefore(this); | |
1059 add->AssumeRepresentation(index()->representation()); | |
1060 current_index = add; | |
1061 } | |
1062 | |
1063 if (actual_scale != 0) { | |
1064 HConstant* sar_scale = new(block()->graph()->zone()) HConstant( | |
1065 actual_scale, index()->representation()); | |
1066 sar_scale->InsertBefore(this); | |
1067 HSar* sar = new(block()->graph()->zone()) HSar( | |
1068 block()->graph()->GetInvalidContext(), current_index, sar_scale); | |
1069 sar->InsertBefore(this); | |
1070 sar->AssumeRepresentation(index()->representation()); | |
1071 current_index = sar; | |
1072 } | |
1073 | |
1074 SetOperandAt(0, current_index); | |
1075 | |
1076 base_ = NULL; | |
1077 offset_ = 0; | |
1078 scale_ = 0; | |
1079 responsibility_direction_ = DIRECTION_NONE; | |
1080 } | |
1081 | |
1082 | |
888 void HBoundsCheck::AddInformativeDefinitions() { | 1083 void HBoundsCheck::AddInformativeDefinitions() { |
889 // TODO(mmassi): Executing this code during AddInformativeDefinitions | 1084 // TODO(mmassi): Executing this code during AddInformativeDefinitions |
890 // is a hack. Move it to some other HPhase. | 1085 // is a hack. Move it to some other HPhase. |
891 if (index()->IsRelationTrue(NumericRelation::Ge(), | 1086 if (FLAG_new_abcd) { |
892 block()->graph()->GetConstant0()) && | 1087 if (index()->TryGuaranteeRange(length())) { |
893 index()->IsRelationTrue(NumericRelation::Lt(), length())) { | 1088 set_skip_check(true); |
894 set_skip_check(true); | 1089 } |
1090 if (DetectCompoundIndex()) { | |
1091 HBoundsCheckBaseIndexInformation* base_index_info = | |
1092 new(block()->graph()->zone()) | |
1093 HBoundsCheckBaseIndexInformation(this); | |
1094 base_index_info->InsertAfter(this); | |
1095 } | |
1096 } else { | |
1097 if (index()->IsRelationTrue(NumericRelation::Ge(), | |
1098 block()->graph()->GetConstant0()) && | |
1099 index()->IsRelationTrue(NumericRelation::Lt(), length())) { | |
1100 set_skip_check(true); | |
1101 } | |
895 } | 1102 } |
896 } | 1103 } |
897 | 1104 |
898 | 1105 |
899 bool HBoundsCheck::IsRelationTrueInternal(NumericRelation relation, | 1106 bool HBoundsCheck::IsRelationTrueInternal(NumericRelation relation, |
900 HValue* related_value) { | 1107 HValue* related_value, |
1108 int offset, | |
1109 int scale) { | |
901 if (related_value == length()) { | 1110 if (related_value == length()) { |
902 // A HBoundsCheck is smaller than the length it compared against. | 1111 // A HBoundsCheck is smaller than the length it compared against. |
903 return NumericRelation::Lt().Implies(relation); | 1112 return NumericRelation::Lt().CompoundImplies(relation, 0, 0, offset, scale); |
904 } else if (related_value == block()->graph()->GetConstant0()) { | 1113 } else if (related_value == block()->graph()->GetConstant0()) { |
905 // A HBoundsCheck is greater than or equal to zero. | 1114 // A HBoundsCheck is greater than or equal to zero. |
906 return NumericRelation::Ge().Implies(relation); | 1115 return NumericRelation::Ge().CompoundImplies(relation, 0, 0, offset, scale); |
907 } else { | 1116 } else { |
908 return false; | 1117 return false; |
909 } | 1118 } |
910 } | 1119 } |
911 | 1120 |
912 | 1121 |
913 void HBoundsCheck::PrintDataTo(StringStream* stream) { | 1122 void HBoundsCheck::PrintDataTo(StringStream* stream) { |
914 index()->PrintNameTo(stream); | 1123 index()->PrintNameTo(stream); |
915 stream->Add(" "); | 1124 stream->Add(" "); |
916 length()->PrintNameTo(stream); | 1125 length()->PrintNameTo(stream); |
1126 if (base() != NULL && (offset() != 0 || scale() != 0)) { | |
1127 stream->Add(" base: (("); | |
1128 if (base() != index()) { | |
1129 index()->PrintNameTo(stream); | |
1130 } else { | |
1131 stream->Add("index"); | |
1132 } | |
1133 stream->Add(" + %d) >> %d)", offset(), scale()); | |
1134 } | |
917 if (skip_check()) { | 1135 if (skip_check()) { |
918 stream->Add(" [DISABLED]"); | 1136 stream->Add(" [DISABLED]"); |
919 } | 1137 } |
920 } | 1138 } |
921 | 1139 |
922 | 1140 |
923 void HBoundsCheck::InferRepresentation(HInferRepresentation* h_infer) { | 1141 void HBoundsCheck::InferRepresentation(HInferRepresentation* h_infer) { |
924 ASSERT(CheckFlag(kFlexibleRepresentation)); | 1142 ASSERT(CheckFlag(kFlexibleRepresentation)); |
925 Representation r; | 1143 Representation r; |
926 if (key_mode_ == DONT_ALLOW_SMI_KEY || | 1144 if (key_mode_ == DONT_ALLOW_SMI_KEY || |
927 !length()->representation().IsTagged()) { | 1145 !length()->representation().IsTagged()) { |
928 r = Representation::Integer32(); | 1146 r = Representation::Integer32(); |
929 } else if (index()->representation().IsTagged() || | 1147 } else if (index()->representation().IsTagged() || |
930 (index()->ActualValue()->IsConstant() && | 1148 (index()->ActualValue()->IsConstant() && |
931 HConstant::cast(index()->ActualValue())->HasSmiValue())) { | 1149 HConstant::cast(index()->ActualValue())->HasSmiValue())) { |
932 // If the index is tagged, or a constant that holds a Smi, allow the length | 1150 // If the index is tagged, or a constant that holds a Smi, allow the length |
933 // to be tagged, since it is usually already tagged from loading it out of | 1151 // to be tagged, since it is usually already tagged from loading it out of |
934 // the length field of a JSArray. This allows for direct comparison without | 1152 // the length field of a JSArray. This allows for direct comparison without |
935 // untagging. | 1153 // untagging. |
936 r = Representation::Tagged(); | 1154 r = Representation::Tagged(); |
937 } else { | 1155 } else { |
938 r = Representation::Integer32(); | 1156 r = Representation::Integer32(); |
939 } | 1157 } |
940 UpdateRepresentation(r, h_infer, "boundscheck"); | 1158 UpdateRepresentation(r, h_infer, "boundscheck"); |
941 } | 1159 } |
942 | 1160 |
943 | 1161 |
1162 bool HBoundsCheckBaseIndexInformation::IsRelationTrueInternal( | |
1163 NumericRelation relation, | |
1164 HValue* related_value, | |
1165 int offset, | |
1166 int scale) { | |
1167 if (related_value == bounds_check()->length()) { | |
1168 return NumericRelation::Lt().CompoundImplies( | |
1169 relation, | |
1170 bounds_check()->offset(), bounds_check()->scale(), offset, scale); | |
1171 } else if (related_value == block()->graph()->GetConstant0()) { | |
1172 return NumericRelation::Ge().CompoundImplies( | |
1173 relation, | |
1174 bounds_check()->offset(), bounds_check()->scale(), offset, scale); | |
1175 } else { | |
1176 return false; | |
1177 } | |
1178 } | |
1179 | |
1180 | |
1181 void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) { | |
1182 stream->Add("base: "); | |
1183 base_index()->PrintNameTo(stream); | |
1184 stream->Add(", check: "); | |
1185 base_index()->PrintNameTo(stream); | |
1186 } | |
1187 | |
1188 | |
944 void HCallConstantFunction::PrintDataTo(StringStream* stream) { | 1189 void HCallConstantFunction::PrintDataTo(StringStream* stream) { |
945 if (IsApplyFunction()) { | 1190 if (IsApplyFunction()) { |
946 stream->Add("optimized apply "); | 1191 stream->Add("optimized apply "); |
947 } else { | 1192 } else { |
948 stream->Add("%o ", function()->shared()->DebugName()); | 1193 stream->Add("%o ", function()->shared()->DebugName()); |
949 } | 1194 } |
950 stream->Add("#%d", argument_count()); | 1195 stream->Add("#%d", argument_count()); |
951 } | 1196 } |
952 | 1197 |
953 | 1198 |
(...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1597 HInductionVariableAnnotation::AddToGraph(this, | 1842 HInductionVariableAnnotation::AddToGraph(this, |
1598 relations[relation_index], | 1843 relations[relation_index], |
1599 other_operand_index); | 1844 other_operand_index); |
1600 } | 1845 } |
1601 } | 1846 } |
1602 } | 1847 } |
1603 } | 1848 } |
1604 } | 1849 } |
1605 | 1850 |
1606 | 1851 |
1607 bool HPhi::IsRelationTrueInternal(NumericRelation relation, HValue* other) { | 1852 bool HPhi::IsRelationTrueInternal(NumericRelation relation, |
1853 HValue* other, | |
1854 int offset, | |
1855 int scale) { | |
1608 if (CheckFlag(kNumericConstraintEvaluationInProgress)) return false; | 1856 if (CheckFlag(kNumericConstraintEvaluationInProgress)) return false; |
1609 | 1857 |
1610 SetFlag(kNumericConstraintEvaluationInProgress); | 1858 SetFlag(kNumericConstraintEvaluationInProgress); |
1611 bool result = true; | 1859 bool result = true; |
1612 for (int i = 0; i < OperandCount(); i++) { | 1860 for (int i = 0; i < OperandCount(); i++) { |
1613 // Skip OSR entry blocks | 1861 // Skip OSR entry blocks |
1614 if (OperandAt(i)->block()->is_osr_entry()) continue; | 1862 if (OperandAt(i)->block()->is_osr_entry()) continue; |
1615 | 1863 |
1616 if (!OperandAt(i)->IsRelationTrue(relation, other)) { | 1864 if (!OperandAt(i)->IsRelationTrue(relation, other, offset, scale)) { |
1617 result = false; | 1865 result = false; |
1618 break; | 1866 break; |
1619 } | 1867 } |
1620 } | 1868 } |
1621 ClearFlag(kNumericConstraintEvaluationInProgress); | 1869 ClearFlag(kNumericConstraintEvaluationInProgress); |
1622 | 1870 |
1623 return result; | 1871 return result; |
1624 } | 1872 } |
1625 | 1873 |
1626 | 1874 |
(...skipping 1473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3100 | 3348 |
3101 | 3349 |
3102 void HCheckFunction::Verify() { | 3350 void HCheckFunction::Verify() { |
3103 HInstruction::Verify(); | 3351 HInstruction::Verify(); |
3104 ASSERT(HasNoUses()); | 3352 ASSERT(HasNoUses()); |
3105 } | 3353 } |
3106 | 3354 |
3107 #endif | 3355 #endif |
3108 | 3356 |
3109 } } // namespace v8::internal | 3357 } } // namespace v8::internal |
OLD | NEW |