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 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 |