| 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 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 void HValue::AddDependantsToWorklist(HInferRepresentationPhase* h_infer) { | 142 void HValue::AddDependantsToWorklist(HInferRepresentationPhase* h_infer) { |
| 143 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { | 143 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { |
| 144 h_infer->AddToWorklist(it.value()); | 144 h_infer->AddToWorklist(it.value()); |
| 145 } | 145 } |
| 146 for (int i = 0; i < OperandCount(); ++i) { | 146 for (int i = 0; i < OperandCount(); ++i) { |
| 147 h_infer->AddToWorklist(OperandAt(i)); | 147 h_infer->AddToWorklist(OperandAt(i)); |
| 148 } | 148 } |
| 149 } | 149 } |
| 150 | 150 |
| 151 | 151 |
| 152 // This method is recursive but it is guaranteed to terminate because | |
| 153 // RedefinedOperand() always dominates "this". | |
| 154 bool HValue::IsRelationTrue(NumericRelation relation, | |
| 155 HValue* other, | |
| 156 int offset, | |
| 157 int scale) { | |
| 158 if (this == other) { | |
| 159 return scale == 0 && relation.IsExtendable(offset); | |
| 160 } | |
| 161 | |
| 162 // Test the direct relation. | |
| 163 if (IsRelationTrueInternal(relation, other, offset, scale)) return true; | |
| 164 | |
| 165 // If scale is 0 try the reversed relation. | |
| 166 if (scale == 0 && | |
| 167 // TODO(mmassi): do we need the full, recursive IsRelationTrue? | |
| 168 other->IsRelationTrueInternal(relation.Reversed(), this, -offset)) { | |
| 169 return true; | |
| 170 } | |
| 171 | |
| 172 // Try decomposition (but do not accept scaled compounds). | |
| 173 DecompositionResult decomposition; | |
| 174 if (TryDecompose(&decomposition) && | |
| 175 decomposition.scale() == 0 && | |
| 176 decomposition.base()->IsRelationTrue(relation, other, | |
| 177 offset + decomposition.offset(), | |
| 178 scale)) { | |
| 179 return true; | |
| 180 } | |
| 181 | |
| 182 // Pass the request to the redefined value. | |
| 183 HValue* redefined = RedefinedOperand(); | |
| 184 return redefined != NULL && redefined->IsRelationTrue(relation, other, | |
| 185 offset, scale); | |
| 186 } | |
| 187 | |
| 188 | |
| 189 bool HValue::TryGuaranteeRange(HValue* upper_bound) { | |
| 190 RangeEvaluationContext context = RangeEvaluationContext(this, upper_bound); | |
| 191 TryGuaranteeRangeRecursive(&context); | |
| 192 bool result = context.is_range_satisfied(); | |
| 193 if (result) { | |
| 194 context.lower_bound_guarantee()->SetResponsibilityForRange(DIRECTION_LOWER); | |
| 195 context.upper_bound_guarantee()->SetResponsibilityForRange(DIRECTION_UPPER); | |
| 196 } | |
| 197 return result; | |
| 198 } | |
| 199 | |
| 200 | |
| 201 void HValue::TryGuaranteeRangeRecursive(RangeEvaluationContext* context) { | |
| 202 // Check if we already know that this value satisfies the lower bound. | |
| 203 if (context->lower_bound_guarantee() == NULL) { | |
| 204 if (IsRelationTrueInternal(NumericRelation::Ge(), context->lower_bound(), | |
| 205 context->offset(), context->scale())) { | |
| 206 context->set_lower_bound_guarantee(this); | |
| 207 } | |
| 208 } | |
| 209 | |
| 210 // Check if we already know that this value satisfies the upper bound. | |
| 211 if (context->upper_bound_guarantee() == NULL) { | |
| 212 if (IsRelationTrueInternal(NumericRelation::Lt(), context->upper_bound(), | |
| 213 context->offset(), context->scale()) || | |
| 214 (context->scale() == 0 && | |
| 215 context->upper_bound()->IsRelationTrue(NumericRelation::Gt(), | |
| 216 this, -context->offset()))) { | |
| 217 context->set_upper_bound_guarantee(this); | |
| 218 } | |
| 219 } | |
| 220 | |
| 221 if (context->is_range_satisfied()) return; | |
| 222 | |
| 223 // See if our RedefinedOperand() satisfies the constraints. | |
| 224 if (RedefinedOperand() != NULL) { | |
| 225 RedefinedOperand()->TryGuaranteeRangeRecursive(context); | |
| 226 } | |
| 227 if (context->is_range_satisfied()) return; | |
| 228 | |
| 229 // See if the constraints can be satisfied by decomposition. | |
| 230 DecompositionResult decomposition; | |
| 231 if (TryDecompose(&decomposition)) { | |
| 232 context->swap_candidate(&decomposition); | |
| 233 context->candidate()->TryGuaranteeRangeRecursive(context); | |
| 234 context->swap_candidate(&decomposition); | |
| 235 } | |
| 236 if (context->is_range_satisfied()) return; | |
| 237 | |
| 238 // Try to modify this to satisfy the constraint. | |
| 239 | |
| 240 TryGuaranteeRangeChanging(context); | |
| 241 } | |
| 242 | |
| 243 | |
| 244 RangeEvaluationContext::RangeEvaluationContext(HValue* value, HValue* upper) | |
| 245 : lower_bound_(upper->block()->graph()->GetConstant0()), | |
| 246 lower_bound_guarantee_(NULL), | |
| 247 candidate_(value), | |
| 248 upper_bound_(upper), | |
| 249 upper_bound_guarantee_(NULL), | |
| 250 offset_(0), | |
| 251 scale_(0) { | |
| 252 } | |
| 253 | |
| 254 | |
| 255 HValue* RangeEvaluationContext::ConvertGuarantee(HValue* guarantee) { | |
| 256 return guarantee->IsBoundsCheckBaseIndexInformation() | |
| 257 ? HBoundsCheckBaseIndexInformation::cast(guarantee)->bounds_check() | |
| 258 : guarantee; | |
| 259 } | |
| 260 | |
| 261 | |
| 262 static int32_t ConvertAndSetOverflow(Representation r, | 152 static int32_t ConvertAndSetOverflow(Representation r, |
| 263 int64_t result, | 153 int64_t result, |
| 264 bool* overflow) { | 154 bool* overflow) { |
| 265 if (r.IsSmi()) { | 155 if (r.IsSmi()) { |
| 266 if (result > Smi::kMaxValue) { | 156 if (result > Smi::kMaxValue) { |
| 267 *overflow = true; | 157 *overflow = true; |
| 268 return Smi::kMaxValue; | 158 return Smi::kMaxValue; |
| 269 } | 159 } |
| 270 if (result < Smi::kMinValue) { | 160 if (result < Smi::kMinValue) { |
| 271 *overflow = true; | 161 *overflow = true; |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 result = HType::Boolean(); | 367 result = HType::Boolean(); |
| 478 } else if (value->IsJSObject()) { | 368 } else if (value->IsJSObject()) { |
| 479 result = HType::JSObject(); | 369 result = HType::JSObject(); |
| 480 } else if (value->IsJSArray()) { | 370 } else if (value->IsJSArray()) { |
| 481 result = HType::JSArray(); | 371 result = HType::JSArray(); |
| 482 } | 372 } |
| 483 return result; | 373 return result; |
| 484 } | 374 } |
| 485 | 375 |
| 486 | 376 |
| 487 bool HValue::Dominates(HValue* dominator, HValue* dominated) { | |
| 488 if (dominator->block() != dominated->block()) { | |
| 489 // If they are in different blocks we can use the dominance relation | |
| 490 // between the blocks. | |
| 491 return dominator->block()->Dominates(dominated->block()); | |
| 492 } else { | |
| 493 // Otherwise we must see which instruction comes first, considering | |
| 494 // that phis always precede regular instructions. | |
| 495 if (dominator->IsInstruction()) { | |
| 496 if (dominated->IsInstruction()) { | |
| 497 for (HInstruction* next = HInstruction::cast(dominator)->next(); | |
| 498 next != NULL; | |
| 499 next = next->next()) { | |
| 500 if (next == dominated) return true; | |
| 501 } | |
| 502 return false; | |
| 503 } else if (dominated->IsPhi()) { | |
| 504 return false; | |
| 505 } else { | |
| 506 UNREACHABLE(); | |
| 507 } | |
| 508 } else if (dominator->IsPhi()) { | |
| 509 if (dominated->IsInstruction()) { | |
| 510 return true; | |
| 511 } else { | |
| 512 // We cannot compare which phi comes first. | |
| 513 UNREACHABLE(); | |
| 514 } | |
| 515 } else { | |
| 516 UNREACHABLE(); | |
| 517 } | |
| 518 return false; | |
| 519 } | |
| 520 } | |
| 521 | |
| 522 | |
| 523 bool HValue::TestDominanceUsingProcessedFlag(HValue* dominator, | |
| 524 HValue* dominated) { | |
| 525 if (dominator->block() != dominated->block()) { | |
| 526 return dominator->block()->Dominates(dominated->block()); | |
| 527 } else { | |
| 528 // If both arguments are in the same block we check if dominator is a phi | |
| 529 // or if dominated has not already been processed: in either case we know | |
| 530 // that dominator precedes dominated. | |
| 531 return dominator->IsPhi() || !dominated->CheckFlag(kIDefsProcessingDone); | |
| 532 } | |
| 533 } | |
| 534 | |
| 535 | |
| 536 bool HValue::IsDefinedAfter(HBasicBlock* other) const { | 377 bool HValue::IsDefinedAfter(HBasicBlock* other) const { |
| 537 return block()->block_id() > other->block_id(); | 378 return block()->block_id() > other->block_id(); |
| 538 } | 379 } |
| 539 | 380 |
| 540 | 381 |
| 541 HUseListNode* HUseListNode::tail() { | 382 HUseListNode* HUseListNode::tail() { |
| 542 // Skip and remove dead items in the use list. | 383 // Skip and remove dead items in the use list. |
| 543 while (tail_ != NULL && tail_->value()->CheckFlag(HValue::kIsDead)) { | 384 while (tail_ != NULL && tail_->value()->CheckFlag(HValue::kIsDead)) { |
| 544 tail_ = tail_->tail_; | 385 tail_ = tail_->tail_; |
| 545 } | 386 } |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 953 // Verify that all uses are in the graph. | 794 // Verify that all uses are in the graph. |
| 954 for (HUseIterator use = uses(); !use.Done(); use.Advance()) { | 795 for (HUseIterator use = uses(); !use.Done(); use.Advance()) { |
| 955 if (use.value()->IsInstruction()) { | 796 if (use.value()->IsInstruction()) { |
| 956 ASSERT(HInstruction::cast(use.value())->IsLinked()); | 797 ASSERT(HInstruction::cast(use.value())->IsLinked()); |
| 957 } | 798 } |
| 958 } | 799 } |
| 959 } | 800 } |
| 960 #endif | 801 #endif |
| 961 | 802 |
| 962 | 803 |
| 963 HNumericConstraint* HNumericConstraint::AddToGraph( | |
| 964 HValue* constrained_value, | |
| 965 NumericRelation relation, | |
| 966 HValue* related_value, | |
| 967 HInstruction* insertion_point) { | |
| 968 if (insertion_point == NULL) { | |
| 969 if (constrained_value->IsInstruction()) { | |
| 970 insertion_point = HInstruction::cast(constrained_value); | |
| 971 } else if (constrained_value->IsPhi()) { | |
| 972 insertion_point = constrained_value->block()->first(); | |
| 973 } else { | |
| 974 UNREACHABLE(); | |
| 975 } | |
| 976 } | |
| 977 HNumericConstraint* result = | |
| 978 new(insertion_point->block()->zone()) HNumericConstraint( | |
| 979 constrained_value, relation, related_value); | |
| 980 result->InsertAfter(insertion_point); | |
| 981 return result; | |
| 982 } | |
| 983 | |
| 984 | |
| 985 void HNumericConstraint::PrintDataTo(StringStream* stream) { | |
| 986 stream->Add("("); | |
| 987 constrained_value()->PrintNameTo(stream); | |
| 988 stream->Add(" %s ", relation().Mnemonic()); | |
| 989 related_value()->PrintNameTo(stream); | |
| 990 stream->Add(")"); | |
| 991 } | |
| 992 | |
| 993 | |
| 994 HInductionVariableAnnotation* HInductionVariableAnnotation::AddToGraph( | |
| 995 HPhi* phi, | |
| 996 NumericRelation relation, | |
| 997 int operand_index) { | |
| 998 HInductionVariableAnnotation* result = | |
| 999 new(phi->block()->zone()) HInductionVariableAnnotation(phi, relation, | |
| 1000 operand_index); | |
| 1001 result->InsertAfter(phi->block()->first()); | |
| 1002 return result; | |
| 1003 } | |
| 1004 | |
| 1005 | |
| 1006 void HInductionVariableAnnotation::PrintDataTo(StringStream* stream) { | |
| 1007 stream->Add("("); | |
| 1008 RedefinedOperand()->PrintNameTo(stream); | |
| 1009 stream->Add(" %s ", relation().Mnemonic()); | |
| 1010 induction_base()->PrintNameTo(stream); | |
| 1011 stream->Add(")"); | |
| 1012 } | |
| 1013 | |
| 1014 | |
| 1015 void HDummyUse::PrintDataTo(StringStream* stream) { | 804 void HDummyUse::PrintDataTo(StringStream* stream) { |
| 1016 value()->PrintNameTo(stream); | 805 value()->PrintNameTo(stream); |
| 1017 } | 806 } |
| 1018 | 807 |
| 1019 | 808 |
| 1020 void HEnvironmentMarker::PrintDataTo(StringStream* stream) { | 809 void HEnvironmentMarker::PrintDataTo(StringStream* stream) { |
| 1021 stream->Add("%s var[%d]", kind() == BIND ? "bind" : "lookup", index()); | 810 stream->Add("%s var[%d]", kind() == BIND ? "bind" : "lookup", index()); |
| 1022 } | 811 } |
| 1023 | 812 |
| 1024 | 813 |
| 1025 void HUnaryCall::PrintDataTo(StringStream* stream) { | 814 void HUnaryCall::PrintDataTo(StringStream* stream) { |
| 1026 value()->PrintNameTo(stream); | 815 value()->PrintNameTo(stream); |
| 1027 stream->Add(" "); | 816 stream->Add(" "); |
| 1028 stream->Add("#%d", argument_count()); | 817 stream->Add("#%d", argument_count()); |
| 1029 } | 818 } |
| 1030 | 819 |
| 1031 | 820 |
| 1032 void HBinaryCall::PrintDataTo(StringStream* stream) { | 821 void HBinaryCall::PrintDataTo(StringStream* stream) { |
| 1033 first()->PrintNameTo(stream); | 822 first()->PrintNameTo(stream); |
| 1034 stream->Add(" "); | 823 stream->Add(" "); |
| 1035 second()->PrintNameTo(stream); | 824 second()->PrintNameTo(stream); |
| 1036 stream->Add(" "); | 825 stream->Add(" "); |
| 1037 stream->Add("#%d", argument_count()); | 826 stream->Add("#%d", argument_count()); |
| 1038 } | 827 } |
| 1039 | 828 |
| 1040 | 829 |
| 1041 void HBoundsCheck::TryGuaranteeRangeChanging(RangeEvaluationContext* context) { | |
| 1042 if (context->candidate()->ActualValue() != base()->ActualValue() || | |
| 1043 context->scale() < scale()) { | |
| 1044 return; | |
| 1045 } | |
| 1046 | |
| 1047 // TODO(mmassi) | |
| 1048 // Instead of checking for "same basic block" we should check for | |
| 1049 // "dominates and postdominates". | |
| 1050 if (context->upper_bound() == length() && | |
| 1051 context->lower_bound_guarantee() != NULL && | |
| 1052 context->lower_bound_guarantee() != this && | |
| 1053 context->lower_bound_guarantee()->block() != block() && | |
| 1054 offset() < context->offset() && | |
| 1055 index_can_increase() && | |
| 1056 context->upper_bound_guarantee() == NULL) { | |
| 1057 offset_ = context->offset(); | |
| 1058 SetResponsibilityForRange(DIRECTION_UPPER); | |
| 1059 context->set_upper_bound_guarantee(this); | |
| 1060 isolate()->counters()->bounds_checks_eliminated()->Increment(); | |
| 1061 } else if (context->upper_bound_guarantee() != NULL && | |
| 1062 context->upper_bound_guarantee() != this && | |
| 1063 context->upper_bound_guarantee()->block() != block() && | |
| 1064 offset() > context->offset() && | |
| 1065 index_can_decrease() && | |
| 1066 context->lower_bound_guarantee() == NULL) { | |
| 1067 offset_ = context->offset(); | |
| 1068 SetResponsibilityForRange(DIRECTION_LOWER); | |
| 1069 context->set_lower_bound_guarantee(this); | |
| 1070 isolate()->counters()->bounds_checks_eliminated()->Increment(); | |
| 1071 } | |
| 1072 } | |
| 1073 | |
| 1074 | |
| 1075 void HBoundsCheck::ApplyIndexChange() { | 830 void HBoundsCheck::ApplyIndexChange() { |
| 1076 if (skip_check()) return; | 831 if (skip_check()) return; |
| 1077 | 832 |
| 1078 DecompositionResult decomposition; | 833 DecompositionResult decomposition; |
| 1079 bool index_is_decomposable = index()->TryDecompose(&decomposition); | 834 bool index_is_decomposable = index()->TryDecompose(&decomposition); |
| 1080 if (index_is_decomposable) { | 835 if (index_is_decomposable) { |
| 1081 ASSERT(decomposition.base() == base()); | 836 ASSERT(decomposition.base() == base()); |
| 1082 if (decomposition.offset() == offset() && | 837 if (decomposition.offset() == offset() && |
| 1083 decomposition.scale() == scale()) return; | 838 decomposition.scale() == scale()) return; |
| 1084 } else { | 839 } else { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1112 sar->InsertBefore(this); | 867 sar->InsertBefore(this); |
| 1113 sar->AssumeRepresentation(index()->representation()); | 868 sar->AssumeRepresentation(index()->representation()); |
| 1114 current_index = sar; | 869 current_index = sar; |
| 1115 } | 870 } |
| 1116 | 871 |
| 1117 SetOperandAt(0, current_index); | 872 SetOperandAt(0, current_index); |
| 1118 | 873 |
| 1119 base_ = NULL; | 874 base_ = NULL; |
| 1120 offset_ = 0; | 875 offset_ = 0; |
| 1121 scale_ = 0; | 876 scale_ = 0; |
| 1122 responsibility_direction_ = DIRECTION_NONE; | |
| 1123 } | 877 } |
| 1124 | 878 |
| 1125 | 879 |
| 1126 void HBoundsCheck::AddInformativeDefinitions() { | |
| 1127 // TODO(mmassi): Executing this code during AddInformativeDefinitions | |
| 1128 // is a hack. Move it to some other HPhase. | |
| 1129 if (FLAG_array_bounds_checks_elimination) { | |
| 1130 if (index()->TryGuaranteeRange(length())) { | |
| 1131 set_skip_check(); | |
| 1132 } | |
| 1133 if (DetectCompoundIndex()) { | |
| 1134 HBoundsCheckBaseIndexInformation* base_index_info = | |
| 1135 new(block()->graph()->zone()) | |
| 1136 HBoundsCheckBaseIndexInformation(this); | |
| 1137 base_index_info->InsertAfter(this); | |
| 1138 } | |
| 1139 } | |
| 1140 } | |
| 1141 | |
| 1142 | |
| 1143 bool HBoundsCheck::IsRelationTrueInternal(NumericRelation relation, | |
| 1144 HValue* related_value, | |
| 1145 int offset, | |
| 1146 int scale) { | |
| 1147 if (related_value == length()) { | |
| 1148 // A HBoundsCheck is smaller than the length it compared against. | |
| 1149 return NumericRelation::Lt().CompoundImplies(relation, 0, 0, offset, scale); | |
| 1150 } else if (related_value == block()->graph()->GetConstant0()) { | |
| 1151 // A HBoundsCheck is greater than or equal to zero. | |
| 1152 return NumericRelation::Ge().CompoundImplies(relation, 0, 0, offset, scale); | |
| 1153 } else { | |
| 1154 return false; | |
| 1155 } | |
| 1156 } | |
| 1157 | |
| 1158 | |
| 1159 void HBoundsCheck::PrintDataTo(StringStream* stream) { | 880 void HBoundsCheck::PrintDataTo(StringStream* stream) { |
| 1160 index()->PrintNameTo(stream); | 881 index()->PrintNameTo(stream); |
| 1161 stream->Add(" "); | 882 stream->Add(" "); |
| 1162 length()->PrintNameTo(stream); | 883 length()->PrintNameTo(stream); |
| 1163 if (base() != NULL && (offset() != 0 || scale() != 0)) { | 884 if (base() != NULL && (offset() != 0 || scale() != 0)) { |
| 1164 stream->Add(" base: (("); | 885 stream->Add(" base: (("); |
| 1165 if (base() != index()) { | 886 if (base() != index()) { |
| 1166 index()->PrintNameTo(stream); | 887 index()->PrintNameTo(stream); |
| 1167 } else { | 888 } else { |
| 1168 stream->Add("index"); | 889 stream->Add("index"); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1188 length_rep = Representation::Smi(); | 909 length_rep = Representation::Smi(); |
| 1189 } | 910 } |
| 1190 Representation r = index_rep.generalize(length_rep); | 911 Representation r = index_rep.generalize(length_rep); |
| 1191 if (r.is_more_general_than(Representation::Integer32())) { | 912 if (r.is_more_general_than(Representation::Integer32())) { |
| 1192 r = Representation::Integer32(); | 913 r = Representation::Integer32(); |
| 1193 } | 914 } |
| 1194 UpdateRepresentation(r, h_infer, "boundscheck"); | 915 UpdateRepresentation(r, h_infer, "boundscheck"); |
| 1195 } | 916 } |
| 1196 | 917 |
| 1197 | 918 |
| 1198 bool HBoundsCheckBaseIndexInformation::IsRelationTrueInternal( | |
| 1199 NumericRelation relation, | |
| 1200 HValue* related_value, | |
| 1201 int offset, | |
| 1202 int scale) { | |
| 1203 if (related_value == bounds_check()->length()) { | |
| 1204 return NumericRelation::Lt().CompoundImplies( | |
| 1205 relation, | |
| 1206 bounds_check()->offset(), bounds_check()->scale(), offset, scale); | |
| 1207 } else if (related_value == block()->graph()->GetConstant0()) { | |
| 1208 return NumericRelation::Ge().CompoundImplies( | |
| 1209 relation, | |
| 1210 bounds_check()->offset(), bounds_check()->scale(), offset, scale); | |
| 1211 } else { | |
| 1212 return false; | |
| 1213 } | |
| 1214 } | |
| 1215 | |
| 1216 | |
| 1217 void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) { | 919 void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) { |
| 1218 stream->Add("base: "); | 920 stream->Add("base: "); |
| 1219 base_index()->PrintNameTo(stream); | 921 base_index()->PrintNameTo(stream); |
| 1220 stream->Add(", check: "); | 922 stream->Add(", check: "); |
| 1221 base_index()->PrintNameTo(stream); | 923 base_index()->PrintNameTo(stream); |
| 1222 } | 924 } |
| 1223 | 925 |
| 1224 | 926 |
| 1225 void HCallConstantFunction::PrintDataTo(StringStream* stream) { | 927 void HCallConstantFunction::PrintDataTo(StringStream* stream) { |
| 1226 if (IsApplyFunction()) { | 928 if (IsApplyFunction()) { |
| (...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1943 if (!b->CanBeZero()) { | 1645 if (!b->CanBeZero()) { |
| 1944 ClearFlag(HValue::kCanBeDivByZero); | 1646 ClearFlag(HValue::kCanBeDivByZero); |
| 1945 } | 1647 } |
| 1946 return result; | 1648 return result; |
| 1947 } else { | 1649 } else { |
| 1948 return HValue::InferRange(zone); | 1650 return HValue::InferRange(zone); |
| 1949 } | 1651 } |
| 1950 } | 1652 } |
| 1951 | 1653 |
| 1952 | 1654 |
| 1953 void HPhi::AddInformativeDefinitions() { | |
| 1954 if (OperandCount() == 2) { | |
| 1955 // If one of the operands is an OSR block give up (this cannot be an | |
| 1956 // induction variable). | |
| 1957 if (OperandAt(0)->block()->is_osr_entry() || | |
| 1958 OperandAt(1)->block()->is_osr_entry()) return; | |
| 1959 | |
| 1960 for (int operand_index = 0; operand_index < 2; operand_index++) { | |
| 1961 int other_operand_index = (operand_index + 1) % 2; | |
| 1962 | |
| 1963 static NumericRelation relations[] = { | |
| 1964 NumericRelation::Ge(), | |
| 1965 NumericRelation::Le() | |
| 1966 }; | |
| 1967 | |
| 1968 // Check if this phi is an induction variable. If, e.g., we know that | |
| 1969 // its first input is greater than the phi itself, then that must be | |
| 1970 // the back edge, and the phi is always greater than its second input. | |
| 1971 for (int relation_index = 0; relation_index < 2; relation_index++) { | |
| 1972 if (OperandAt(operand_index)->IsRelationTrue(relations[relation_index], | |
| 1973 this)) { | |
| 1974 HInductionVariableAnnotation::AddToGraph(this, | |
| 1975 relations[relation_index], | |
| 1976 other_operand_index); | |
| 1977 } | |
| 1978 } | |
| 1979 } | |
| 1980 } | |
| 1981 } | |
| 1982 | |
| 1983 | |
| 1984 bool HPhi::IsRelationTrueInternal(NumericRelation relation, | |
| 1985 HValue* other, | |
| 1986 int offset, | |
| 1987 int scale) { | |
| 1988 if (CheckFlag(kNumericConstraintEvaluationInProgress)) return false; | |
| 1989 | |
| 1990 SetFlag(kNumericConstraintEvaluationInProgress); | |
| 1991 bool result = true; | |
| 1992 for (int i = 0; i < OperandCount(); i++) { | |
| 1993 // Skip OSR entry blocks | |
| 1994 if (OperandAt(i)->block()->is_osr_entry()) continue; | |
| 1995 | |
| 1996 if (!OperandAt(i)->IsRelationTrue(relation, other, offset, scale)) { | |
| 1997 result = false; | |
| 1998 break; | |
| 1999 } | |
| 2000 } | |
| 2001 ClearFlag(kNumericConstraintEvaluationInProgress); | |
| 2002 | |
| 2003 return result; | |
| 2004 } | |
| 2005 | |
| 2006 | |
| 2007 InductionVariableData* InductionVariableData::ExaminePhi(HPhi* phi) { | 1655 InductionVariableData* InductionVariableData::ExaminePhi(HPhi* phi) { |
| 2008 if (phi->block()->loop_information() == NULL) return NULL; | 1656 if (phi->block()->loop_information() == NULL) return NULL; |
| 2009 if (phi->OperandCount() != 2) return NULL; | 1657 if (phi->OperandCount() != 2) return NULL; |
| 2010 int32_t candidate_increment; | 1658 int32_t candidate_increment; |
| 2011 | 1659 |
| 2012 candidate_increment = ComputeIncrement(phi, phi->OperandAt(0)); | 1660 candidate_increment = ComputeIncrement(phi, phi->OperandAt(0)); |
| 2013 if (candidate_increment != 0) { | 1661 if (candidate_increment != 0) { |
| 2014 return new(phi->block()->graph()->zone()) | 1662 return new(phi->block()->graph()->zone()) |
| 2015 InductionVariableData(phi, phi->OperandAt(1), candidate_increment); | 1663 InductionVariableData(phi, phi->OperandAt(1), candidate_increment); |
| 2016 } | 1664 } |
| (...skipping 1066 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3083 } | 2731 } |
| 3084 | 2732 |
| 3085 | 2733 |
| 3086 void HStringCompareAndBranch::PrintDataTo(StringStream* stream) { | 2734 void HStringCompareAndBranch::PrintDataTo(StringStream* stream) { |
| 3087 stream->Add(Token::Name(token())); | 2735 stream->Add(Token::Name(token())); |
| 3088 stream->Add(" "); | 2736 stream->Add(" "); |
| 3089 HControlInstruction::PrintDataTo(stream); | 2737 HControlInstruction::PrintDataTo(stream); |
| 3090 } | 2738 } |
| 3091 | 2739 |
| 3092 | 2740 |
| 3093 void HCompareNumericAndBranch::AddInformativeDefinitions() { | |
| 3094 NumericRelation r = NumericRelation::FromToken(token()); | |
| 3095 if (r.IsNone()) return; | |
| 3096 | |
| 3097 HNumericConstraint::AddToGraph(left(), r, right(), SuccessorAt(0)->first()); | |
| 3098 HNumericConstraint::AddToGraph( | |
| 3099 left(), r.Negated(), right(), SuccessorAt(1)->first()); | |
| 3100 } | |
| 3101 | |
| 3102 | |
| 3103 void HCompareNumericAndBranch::PrintDataTo(StringStream* stream) { | 2741 void HCompareNumericAndBranch::PrintDataTo(StringStream* stream) { |
| 3104 stream->Add(Token::Name(token())); | 2742 stream->Add(Token::Name(token())); |
| 3105 stream->Add(" "); | 2743 stream->Add(" "); |
| 3106 left()->PrintNameTo(stream); | 2744 left()->PrintNameTo(stream); |
| 3107 stream->Add(" "); | 2745 stream->Add(" "); |
| 3108 right()->PrintNameTo(stream); | 2746 right()->PrintNameTo(stream); |
| 3109 HControlInstruction::PrintDataTo(stream); | 2747 HControlInstruction::PrintDataTo(stream); |
| 3110 } | 2748 } |
| 3111 | 2749 |
| 3112 | 2750 |
| (...skipping 1366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4479 break; | 4117 break; |
| 4480 case kExternalMemory: | 4118 case kExternalMemory: |
| 4481 stream->Add("[external-memory]"); | 4119 stream->Add("[external-memory]"); |
| 4482 break; | 4120 break; |
| 4483 } | 4121 } |
| 4484 | 4122 |
| 4485 stream->Add("@%d", offset()); | 4123 stream->Add("@%d", offset()); |
| 4486 } | 4124 } |
| 4487 | 4125 |
| 4488 } } // namespace v8::internal | 4126 } } // namespace v8::internal |
| OLD | NEW |