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 |
152 static int32_t ConvertAndSetOverflow(Representation r, | 262 static int32_t ConvertAndSetOverflow(Representation r, |
153 int64_t result, | 263 int64_t result, |
154 bool* overflow) { | 264 bool* overflow) { |
155 if (r.IsSmi()) { | 265 if (r.IsSmi()) { |
156 if (result > Smi::kMaxValue) { | 266 if (result > Smi::kMaxValue) { |
157 *overflow = true; | 267 *overflow = true; |
158 return Smi::kMaxValue; | 268 return Smi::kMaxValue; |
159 } | 269 } |
160 if (result < Smi::kMinValue) { | 270 if (result < Smi::kMinValue) { |
161 *overflow = true; | 271 *overflow = true; |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 result = HType::Boolean(); | 477 result = HType::Boolean(); |
368 } else if (value->IsJSObject()) { | 478 } else if (value->IsJSObject()) { |
369 result = HType::JSObject(); | 479 result = HType::JSObject(); |
370 } else if (value->IsJSArray()) { | 480 } else if (value->IsJSArray()) { |
371 result = HType::JSArray(); | 481 result = HType::JSArray(); |
372 } | 482 } |
373 return result; | 483 return result; |
374 } | 484 } |
375 | 485 |
376 | 486 |
| 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 |
377 bool HValue::IsDefinedAfter(HBasicBlock* other) const { | 536 bool HValue::IsDefinedAfter(HBasicBlock* other) const { |
378 return block()->block_id() > other->block_id(); | 537 return block()->block_id() > other->block_id(); |
379 } | 538 } |
380 | 539 |
381 | 540 |
382 HUseListNode* HUseListNode::tail() { | 541 HUseListNode* HUseListNode::tail() { |
383 // Skip and remove dead items in the use list. | 542 // Skip and remove dead items in the use list. |
384 while (tail_ != NULL && tail_->value()->CheckFlag(HValue::kIsDead)) { | 543 while (tail_ != NULL && tail_->value()->CheckFlag(HValue::kIsDead)) { |
385 tail_ = tail_->tail_; | 544 tail_ = tail_->tail_; |
386 } | 545 } |
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 // Verify that all uses are in the graph. | 953 // Verify that all uses are in the graph. |
795 for (HUseIterator use = uses(); !use.Done(); use.Advance()) { | 954 for (HUseIterator use = uses(); !use.Done(); use.Advance()) { |
796 if (use.value()->IsInstruction()) { | 955 if (use.value()->IsInstruction()) { |
797 ASSERT(HInstruction::cast(use.value())->IsLinked()); | 956 ASSERT(HInstruction::cast(use.value())->IsLinked()); |
798 } | 957 } |
799 } | 958 } |
800 } | 959 } |
801 #endif | 960 #endif |
802 | 961 |
803 | 962 |
| 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 |
804 void HDummyUse::PrintDataTo(StringStream* stream) { | 1015 void HDummyUse::PrintDataTo(StringStream* stream) { |
805 value()->PrintNameTo(stream); | 1016 value()->PrintNameTo(stream); |
806 } | 1017 } |
807 | 1018 |
808 | 1019 |
809 void HEnvironmentMarker::PrintDataTo(StringStream* stream) { | 1020 void HEnvironmentMarker::PrintDataTo(StringStream* stream) { |
810 stream->Add("%s var[%d]", kind() == BIND ? "bind" : "lookup", index()); | 1021 stream->Add("%s var[%d]", kind() == BIND ? "bind" : "lookup", index()); |
811 } | 1022 } |
812 | 1023 |
813 | 1024 |
814 void HUnaryCall::PrintDataTo(StringStream* stream) { | 1025 void HUnaryCall::PrintDataTo(StringStream* stream) { |
815 value()->PrintNameTo(stream); | 1026 value()->PrintNameTo(stream); |
816 stream->Add(" "); | 1027 stream->Add(" "); |
817 stream->Add("#%d", argument_count()); | 1028 stream->Add("#%d", argument_count()); |
818 } | 1029 } |
819 | 1030 |
820 | 1031 |
821 void HBinaryCall::PrintDataTo(StringStream* stream) { | 1032 void HBinaryCall::PrintDataTo(StringStream* stream) { |
822 first()->PrintNameTo(stream); | 1033 first()->PrintNameTo(stream); |
823 stream->Add(" "); | 1034 stream->Add(" "); |
824 second()->PrintNameTo(stream); | 1035 second()->PrintNameTo(stream); |
825 stream->Add(" "); | 1036 stream->Add(" "); |
826 stream->Add("#%d", argument_count()); | 1037 stream->Add("#%d", argument_count()); |
827 } | 1038 } |
828 | 1039 |
829 | 1040 |
| 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 |
830 void HBoundsCheck::ApplyIndexChange() { | 1075 void HBoundsCheck::ApplyIndexChange() { |
831 if (skip_check()) return; | 1076 if (skip_check()) return; |
832 | 1077 |
833 DecompositionResult decomposition; | 1078 DecompositionResult decomposition; |
834 bool index_is_decomposable = index()->TryDecompose(&decomposition); | 1079 bool index_is_decomposable = index()->TryDecompose(&decomposition); |
835 if (index_is_decomposable) { | 1080 if (index_is_decomposable) { |
836 ASSERT(decomposition.base() == base()); | 1081 ASSERT(decomposition.base() == base()); |
837 if (decomposition.offset() == offset() && | 1082 if (decomposition.offset() == offset() && |
838 decomposition.scale() == scale()) return; | 1083 decomposition.scale() == scale()) return; |
839 } else { | 1084 } else { |
(...skipping 27 matching lines...) Expand all Loading... |
867 sar->InsertBefore(this); | 1112 sar->InsertBefore(this); |
868 sar->AssumeRepresentation(index()->representation()); | 1113 sar->AssumeRepresentation(index()->representation()); |
869 current_index = sar; | 1114 current_index = sar; |
870 } | 1115 } |
871 | 1116 |
872 SetOperandAt(0, current_index); | 1117 SetOperandAt(0, current_index); |
873 | 1118 |
874 base_ = NULL; | 1119 base_ = NULL; |
875 offset_ = 0; | 1120 offset_ = 0; |
876 scale_ = 0; | 1121 scale_ = 0; |
| 1122 responsibility_direction_ = DIRECTION_NONE; |
877 } | 1123 } |
878 | 1124 |
879 | 1125 |
| 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 |
880 void HBoundsCheck::PrintDataTo(StringStream* stream) { | 1159 void HBoundsCheck::PrintDataTo(StringStream* stream) { |
881 index()->PrintNameTo(stream); | 1160 index()->PrintNameTo(stream); |
882 stream->Add(" "); | 1161 stream->Add(" "); |
883 length()->PrintNameTo(stream); | 1162 length()->PrintNameTo(stream); |
884 if (base() != NULL && (offset() != 0 || scale() != 0)) { | 1163 if (base() != NULL && (offset() != 0 || scale() != 0)) { |
885 stream->Add(" base: (("); | 1164 stream->Add(" base: (("); |
886 if (base() != index()) { | 1165 if (base() != index()) { |
887 index()->PrintNameTo(stream); | 1166 index()->PrintNameTo(stream); |
888 } else { | 1167 } else { |
889 stream->Add("index"); | 1168 stream->Add("index"); |
(...skipping 19 matching lines...) Expand all Loading... |
909 length_rep = Representation::Smi(); | 1188 length_rep = Representation::Smi(); |
910 } | 1189 } |
911 Representation r = index_rep.generalize(length_rep); | 1190 Representation r = index_rep.generalize(length_rep); |
912 if (r.is_more_general_than(Representation::Integer32())) { | 1191 if (r.is_more_general_than(Representation::Integer32())) { |
913 r = Representation::Integer32(); | 1192 r = Representation::Integer32(); |
914 } | 1193 } |
915 UpdateRepresentation(r, h_infer, "boundscheck"); | 1194 UpdateRepresentation(r, h_infer, "boundscheck"); |
916 } | 1195 } |
917 | 1196 |
918 | 1197 |
| 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 |
919 void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) { | 1217 void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) { |
920 stream->Add("base: "); | 1218 stream->Add("base: "); |
921 base_index()->PrintNameTo(stream); | 1219 base_index()->PrintNameTo(stream); |
922 stream->Add(", check: "); | 1220 stream->Add(", check: "); |
923 base_index()->PrintNameTo(stream); | 1221 base_index()->PrintNameTo(stream); |
924 } | 1222 } |
925 | 1223 |
926 | 1224 |
927 void HCallConstantFunction::PrintDataTo(StringStream* stream) { | 1225 void HCallConstantFunction::PrintDataTo(StringStream* stream) { |
928 if (IsApplyFunction()) { | 1226 if (IsApplyFunction()) { |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1148 } | 1446 } |
1149 | 1447 |
1150 | 1448 |
1151 void HLoadFieldByIndex::PrintDataTo(StringStream* stream) { | 1449 void HLoadFieldByIndex::PrintDataTo(StringStream* stream) { |
1152 object()->PrintNameTo(stream); | 1450 object()->PrintNameTo(stream); |
1153 stream->Add(" "); | 1451 stream->Add(" "); |
1154 index()->PrintNameTo(stream); | 1452 index()->PrintNameTo(stream); |
1155 } | 1453 } |
1156 | 1454 |
1157 | 1455 |
1158 static bool MatchLeftIsOnes(HValue* l, HValue* r, HValue** negated) { | |
1159 if (!l->EqualsInteger32Constant(~0)) return false; | |
1160 *negated = r; | |
1161 return true; | |
1162 } | |
1163 | |
1164 | |
1165 static bool MatchNegationViaXor(HValue* instr, HValue** negated) { | |
1166 if (!instr->IsBitwise()) return false; | |
1167 HBitwise* b = HBitwise::cast(instr); | |
1168 return (b->op() == Token::BIT_XOR) && | |
1169 (MatchLeftIsOnes(b->left(), b->right(), negated) || | |
1170 MatchLeftIsOnes(b->right(), b->left(), negated)); | |
1171 } | |
1172 | |
1173 | |
1174 static bool MatchDoubleNegation(HValue* instr, HValue** arg) { | |
1175 HValue* negated; | |
1176 return MatchNegationViaXor(instr, &negated) && | |
1177 MatchNegationViaXor(negated, arg); | |
1178 } | |
1179 | |
1180 | |
1181 HValue* HBitwise::Canonicalize() { | 1456 HValue* HBitwise::Canonicalize() { |
1182 if (!representation().IsSmiOrInteger32()) return this; | 1457 if (!representation().IsSmiOrInteger32()) return this; |
1183 // If x is an int32, then x & -1 == x, x | 0 == x and x ^ 0 == x. | 1458 // If x is an int32, then x & -1 == x, x | 0 == x and x ^ 0 == x. |
1184 int32_t nop_constant = (op() == Token::BIT_AND) ? -1 : 0; | 1459 int32_t nop_constant = (op() == Token::BIT_AND) ? -1 : 0; |
1185 if (left()->EqualsInteger32Constant(nop_constant) && | 1460 if (left()->EqualsInteger32Constant(nop_constant) && |
1186 !right()->CheckFlag(kUint32)) { | 1461 !right()->CheckFlag(kUint32)) { |
1187 return right(); | 1462 return right(); |
1188 } | 1463 } |
1189 if (right()->EqualsInteger32Constant(nop_constant) && | 1464 if (right()->EqualsInteger32Constant(nop_constant) && |
1190 !left()->CheckFlag(kUint32)) { | 1465 !left()->CheckFlag(kUint32)) { |
1191 return left(); | 1466 return left(); |
1192 } | 1467 } |
1193 // Optimize double negation, a common pattern used for ToInt32(x). | 1468 return this; |
1194 HValue* arg; | 1469 } |
1195 if (MatchDoubleNegation(this, &arg) && !arg->CheckFlag(kUint32)) { | 1470 |
1196 return arg; | 1471 |
| 1472 HValue* HBitNot::Canonicalize() { |
| 1473 // Optimize ~~x, a common pattern used for ToInt32(x). |
| 1474 if (value()->IsBitNot()) { |
| 1475 HValue* result = HBitNot::cast(value())->value(); |
| 1476 ASSERT(result->representation().IsInteger32()); |
| 1477 if (!result->CheckFlag(kUint32)) { |
| 1478 return result; |
| 1479 } |
1197 } | 1480 } |
1198 return this; | 1481 return this; |
1199 } | 1482 } |
1200 | 1483 |
1201 | 1484 |
1202 static bool IsIdentityOperation(HValue* arg1, HValue* arg2, int32_t identity) { | 1485 static bool IsIdentityOperation(HValue* arg1, HValue* arg2, int32_t identity) { |
1203 return arg1->representation().IsSpecialization() && | 1486 return arg1->representation().IsSpecialization() && |
1204 arg2->EqualsInteger32Constant(identity); | 1487 arg2->EqualsInteger32Constant(identity); |
1205 } | 1488 } |
1206 | 1489 |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1397 | 1680 |
1398 | 1681 |
1399 void HCheckMaps::HandleSideEffectDominator(GVNFlag side_effect, | 1682 void HCheckMaps::HandleSideEffectDominator(GVNFlag side_effect, |
1400 HValue* dominator) { | 1683 HValue* dominator) { |
1401 ASSERT(side_effect == kChangesMaps); | 1684 ASSERT(side_effect == kChangesMaps); |
1402 // TODO(mstarzinger): For now we specialize on HStoreNamedField, but once | 1685 // TODO(mstarzinger): For now we specialize on HStoreNamedField, but once |
1403 // type information is rich enough we should generalize this to any HType | 1686 // type information is rich enough we should generalize this to any HType |
1404 // for which the map is known. | 1687 // for which the map is known. |
1405 if (HasNoUses() && dominator->IsStoreNamedField()) { | 1688 if (HasNoUses() && dominator->IsStoreNamedField()) { |
1406 HStoreNamedField* store = HStoreNamedField::cast(dominator); | 1689 HStoreNamedField* store = HStoreNamedField::cast(dominator); |
1407 if (!store->has_transition() || store->object() != value()) return; | 1690 UniqueValueId map_unique_id = store->transition_unique_id(); |
1408 HConstant* transition = HConstant::cast(store->transition()); | 1691 if (!map_unique_id.IsInitialized() || store->object() != value()) return; |
1409 for (int i = 0; i < map_set()->length(); i++) { | 1692 for (int i = 0; i < map_set()->length(); i++) { |
1410 if (transition->UniqueValueIdsMatch(map_unique_ids_.at(i))) { | 1693 if (map_unique_id == map_unique_ids_.at(i)) { |
1411 DeleteAndReplaceWith(NULL); | 1694 DeleteAndReplaceWith(NULL); |
1412 return; | 1695 return; |
1413 } | 1696 } |
1414 } | 1697 } |
1415 } | 1698 } |
1416 } | 1699 } |
1417 | 1700 |
1418 | 1701 |
1419 void HCheckMaps::PrintDataTo(StringStream* stream) { | 1702 void HCheckMaps::PrintDataTo(StringStream* stream) { |
1420 value()->PrintNameTo(stream); | 1703 value()->PrintNameTo(stream); |
(...skipping 30 matching lines...) Expand all Loading... |
1451 return ""; | 1734 return ""; |
1452 } | 1735 } |
1453 | 1736 |
1454 | 1737 |
1455 void HCheckInstanceType::PrintDataTo(StringStream* stream) { | 1738 void HCheckInstanceType::PrintDataTo(StringStream* stream) { |
1456 stream->Add("%s ", GetCheckName()); | 1739 stream->Add("%s ", GetCheckName()); |
1457 HUnaryOperation::PrintDataTo(stream); | 1740 HUnaryOperation::PrintDataTo(stream); |
1458 } | 1741 } |
1459 | 1742 |
1460 | 1743 |
| 1744 void HCheckPrototypeMaps::PrintDataTo(StringStream* stream) { |
| 1745 stream->Add("[receiver_prototype=%p,holder=%p]%s", |
| 1746 *prototypes_.first(), *prototypes_.last(), |
| 1747 CanOmitPrototypeChecks() ? " (omitted)" : ""); |
| 1748 } |
| 1749 |
| 1750 |
1461 void HCallStub::PrintDataTo(StringStream* stream) { | 1751 void HCallStub::PrintDataTo(StringStream* stream) { |
1462 stream->Add("%s ", | 1752 stream->Add("%s ", |
1463 CodeStub::MajorName(major_key_, false)); | 1753 CodeStub::MajorName(major_key_, false)); |
1464 HUnaryCall::PrintDataTo(stream); | 1754 HUnaryCall::PrintDataTo(stream); |
1465 } | 1755 } |
1466 | 1756 |
1467 | 1757 |
1468 void HInstanceOf::PrintDataTo(StringStream* stream) { | 1758 void HInstanceOf::PrintDataTo(StringStream* stream) { |
1469 left()->PrintNameTo(stream); | 1759 left()->PrintNameTo(stream); |
1470 stream->Add(" "); | 1760 stream->Add(" "); |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1653 if (!b->CanBeZero()) { | 1943 if (!b->CanBeZero()) { |
1654 ClearFlag(HValue::kCanBeDivByZero); | 1944 ClearFlag(HValue::kCanBeDivByZero); |
1655 } | 1945 } |
1656 return result; | 1946 return result; |
1657 } else { | 1947 } else { |
1658 return HValue::InferRange(zone); | 1948 return HValue::InferRange(zone); |
1659 } | 1949 } |
1660 } | 1950 } |
1661 | 1951 |
1662 | 1952 |
| 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 |
1663 InductionVariableData* InductionVariableData::ExaminePhi(HPhi* phi) { | 2007 InductionVariableData* InductionVariableData::ExaminePhi(HPhi* phi) { |
1664 if (phi->block()->loop_information() == NULL) return NULL; | 2008 if (phi->block()->loop_information() == NULL) return NULL; |
1665 if (phi->OperandCount() != 2) return NULL; | 2009 if (phi->OperandCount() != 2) return NULL; |
1666 int32_t candidate_increment; | 2010 int32_t candidate_increment; |
1667 | 2011 |
1668 candidate_increment = ComputeIncrement(phi, phi->OperandAt(0)); | 2012 candidate_increment = ComputeIncrement(phi, phi->OperandAt(0)); |
1669 if (candidate_increment != 0) { | 2013 if (candidate_increment != 0) { |
1670 return new(phi->block()->graph()->zone()) | 2014 return new(phi->block()->graph()->zone()) |
1671 InductionVariableData(phi, phi->OperandAt(1), candidate_increment); | 2015 InductionVariableData(phi, phi->OperandAt(1), candidate_increment); |
1672 } | 2016 } |
(...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2404 has_external_reference_value_(true), | 2748 has_external_reference_value_(true), |
2405 is_internalized_string_(false), | 2749 is_internalized_string_(false), |
2406 is_not_in_new_space_(true), | 2750 is_not_in_new_space_(true), |
2407 is_cell_(false), | 2751 is_cell_(false), |
2408 boolean_value_(true), | 2752 boolean_value_(true), |
2409 external_reference_value_(reference) { | 2753 external_reference_value_(reference) { |
2410 Initialize(Representation::External()); | 2754 Initialize(Representation::External()); |
2411 } | 2755 } |
2412 | 2756 |
2413 | 2757 |
2414 static void PrepareConstant(Handle<Object> object) { | |
2415 if (!object->IsJSObject()) return; | |
2416 Handle<JSObject> js_object = Handle<JSObject>::cast(object); | |
2417 if (!js_object->map()->is_deprecated()) return; | |
2418 JSObject::TryMigrateInstance(js_object); | |
2419 } | |
2420 | |
2421 | |
2422 void HConstant::Initialize(Representation r) { | 2758 void HConstant::Initialize(Representation r) { |
2423 if (r.IsNone()) { | 2759 if (r.IsNone()) { |
2424 if (has_smi_value_ && kSmiValueSize == 31) { | 2760 if (has_smi_value_ && kSmiValueSize == 31) { |
2425 r = Representation::Smi(); | 2761 r = Representation::Smi(); |
2426 } else if (has_int32_value_) { | 2762 } else if (has_int32_value_) { |
2427 r = Representation::Integer32(); | 2763 r = Representation::Integer32(); |
2428 } else if (has_double_value_) { | 2764 } else if (has_double_value_) { |
2429 r = Representation::Double(); | 2765 r = Representation::Double(); |
2430 } else if (has_external_reference_value_) { | 2766 } else if (has_external_reference_value_) { |
2431 r = Representation::External(); | 2767 r = Representation::External(); |
2432 } else { | 2768 } else { |
2433 PrepareConstant(handle_); | |
2434 r = Representation::Tagged(); | 2769 r = Representation::Tagged(); |
2435 } | 2770 } |
2436 } | 2771 } |
2437 set_representation(r); | 2772 set_representation(r); |
2438 SetFlag(kUseGVN); | 2773 SetFlag(kUseGVN); |
2439 } | 2774 } |
2440 | 2775 |
2441 | 2776 |
2442 bool HConstant::EmitAtUses() { | 2777 bool HConstant::EmitAtUses() { |
2443 ASSERT(IsLinked()); | 2778 ASSERT(IsLinked()); |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2748 } | 3083 } |
2749 | 3084 |
2750 | 3085 |
2751 void HStringCompareAndBranch::PrintDataTo(StringStream* stream) { | 3086 void HStringCompareAndBranch::PrintDataTo(StringStream* stream) { |
2752 stream->Add(Token::Name(token())); | 3087 stream->Add(Token::Name(token())); |
2753 stream->Add(" "); | 3088 stream->Add(" "); |
2754 HControlInstruction::PrintDataTo(stream); | 3089 HControlInstruction::PrintDataTo(stream); |
2755 } | 3090 } |
2756 | 3091 |
2757 | 3092 |
| 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 |
2758 void HCompareNumericAndBranch::PrintDataTo(StringStream* stream) { | 3103 void HCompareNumericAndBranch::PrintDataTo(StringStream* stream) { |
2759 stream->Add(Token::Name(token())); | 3104 stream->Add(Token::Name(token())); |
2760 stream->Add(" "); | 3105 stream->Add(" "); |
2761 left()->PrintNameTo(stream); | 3106 left()->PrintNameTo(stream); |
2762 stream->Add(" "); | 3107 stream->Add(" "); |
2763 right()->PrintNameTo(stream); | 3108 right()->PrintNameTo(stream); |
2764 HControlInstruction::PrintDataTo(stream); | 3109 HControlInstruction::PrintDataTo(stream); |
2765 } | 3110 } |
2766 | 3111 |
2767 | 3112 |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2946 | 3291 |
2947 | 3292 |
2948 HCheckMaps* HCheckMaps::New(Zone* zone, | 3293 HCheckMaps* HCheckMaps::New(Zone* zone, |
2949 HValue* context, | 3294 HValue* context, |
2950 HValue* value, | 3295 HValue* value, |
2951 Handle<Map> map, | 3296 Handle<Map> map, |
2952 CompilationInfo* info, | 3297 CompilationInfo* info, |
2953 HValue* typecheck) { | 3298 HValue* typecheck) { |
2954 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck); | 3299 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck); |
2955 check_map->map_set_.Add(map, zone); | 3300 check_map->map_set_.Add(map, zone); |
2956 check_map->has_migration_target_ = map->is_migration_target(); | |
2957 if (map->CanOmitMapChecks() && | 3301 if (map->CanOmitMapChecks() && |
2958 value->IsConstant() && | 3302 value->IsConstant() && |
2959 HConstant::cast(value)->InstanceOf(map)) { | 3303 HConstant::cast(value)->InstanceOf(map)) { |
2960 check_map->omit(info); | 3304 check_map->omit(info); |
2961 } | 3305 } |
2962 return check_map; | 3306 return check_map; |
2963 } | 3307 } |
2964 | 3308 |
2965 | 3309 |
2966 void HCheckMaps::FinalizeUniqueValueId() { | 3310 void HCheckMaps::FinalizeUniqueValueId() { |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3171 | 3515 |
3172 | 3516 |
3173 void HStoreNamedField::PrintDataTo(StringStream* stream) { | 3517 void HStoreNamedField::PrintDataTo(StringStream* stream) { |
3174 object()->PrintNameTo(stream); | 3518 object()->PrintNameTo(stream); |
3175 access_.PrintTo(stream); | 3519 access_.PrintTo(stream); |
3176 stream->Add(" = "); | 3520 stream->Add(" = "); |
3177 value()->PrintNameTo(stream); | 3521 value()->PrintNameTo(stream); |
3178 if (NeedsWriteBarrier()) { | 3522 if (NeedsWriteBarrier()) { |
3179 stream->Add(" (write-barrier)"); | 3523 stream->Add(" (write-barrier)"); |
3180 } | 3524 } |
3181 if (has_transition()) { | 3525 if (!transition().is_null()) { |
3182 stream->Add(" (transition map %p)", *transition_map()); | 3526 stream->Add(" (transition map %p)", *transition()); |
3183 } | 3527 } |
3184 } | 3528 } |
3185 | 3529 |
3186 | 3530 |
3187 void HStoreKeyed::PrintDataTo(StringStream* stream) { | 3531 void HStoreKeyed::PrintDataTo(StringStream* stream) { |
3188 if (!is_external()) { | 3532 if (!is_external()) { |
3189 elements()->PrintNameTo(stream); | 3533 elements()->PrintNameTo(stream); |
3190 } else { | 3534 } else { |
3191 elements()->PrintNameTo(stream); | 3535 elements()->PrintNameTo(stream); |
3192 stream->Add("."); | 3536 stream->Add("."); |
(...skipping 942 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4135 break; | 4479 break; |
4136 case kExternalMemory: | 4480 case kExternalMemory: |
4137 stream->Add("[external-memory]"); | 4481 stream->Add("[external-memory]"); |
4138 break; | 4482 break; |
4139 } | 4483 } |
4140 | 4484 |
4141 stream->Add("@%d", offset()); | 4485 stream->Add("@%d", offset()); |
4142 } | 4486 } |
4143 | 4487 |
4144 } } // namespace v8::internal | 4488 } } // namespace v8::internal |
OLD | NEW |