| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/flow_graph_compiler.h" | 10 #include "vm/flow_graph_compiler.h" |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 const GrowableArray<intptr_t>& class_ids) { | 223 const GrowableArray<intptr_t>& class_ids) { |
| 224 for (intptr_t i = 0; i < class_ids.length(); i++) { | 224 for (intptr_t i = 0; i < class_ids.length(); i++) { |
| 225 if (class_ids[i] == class_id) { | 225 if (class_ids[i] == class_id) { |
| 226 return true; | 226 return true; |
| 227 } | 227 } |
| 228 } | 228 } |
| 229 return false; | 229 return false; |
| 230 } | 230 } |
| 231 | 231 |
| 232 | 232 |
| 233 // Returns true if ICData tests two arguments and all ICData cids are in the |
| 234 // required sets 'receiver_class_ids' or 'argument_class_ids', respectively. |
| 233 static bool ICDataHasOnlyReceiverArgumentClassIds( | 235 static bool ICDataHasOnlyReceiverArgumentClassIds( |
| 234 const ICData& ic_data, | 236 const ICData& ic_data, |
| 235 const GrowableArray<intptr_t>& receiver_class_ids, | 237 const GrowableArray<intptr_t>& receiver_class_ids, |
| 236 const GrowableArray<intptr_t>& argument_class_ids) { | 238 const GrowableArray<intptr_t>& argument_class_ids) { |
| 237 if (ic_data.num_args_tested() != 2) return false; | 239 if (ic_data.num_args_tested() != 2) return false; |
| 238 | |
| 239 Function& target = Function::Handle(); | 240 Function& target = Function::Handle(); |
| 240 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 241 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 241 GrowableArray<intptr_t> class_ids; | 242 GrowableArray<intptr_t> class_ids; |
| 242 ic_data.GetCheckAt(i, &class_ids, &target); | 243 ic_data.GetCheckAt(i, &class_ids, &target); |
| 243 ASSERT(class_ids.length() == 2); | 244 ASSERT(class_ids.length() == 2); |
| 244 if (!ClassIdIsOneOf(class_ids[0], receiver_class_ids) || | 245 if (!ClassIdIsOneOf(class_ids[0], receiver_class_ids) || |
| 245 !ClassIdIsOneOf(class_ids[1], argument_class_ids)) { | 246 !ClassIdIsOneOf(class_ids[1], argument_class_ids)) { |
| 246 return false; | 247 return false; |
| 247 } | 248 } |
| 248 } | 249 } |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 ic_data.GetOneClassCheckAt(0, &class_id, &target); | 339 ic_data.GetOneClassCheckAt(0, &class_id, &target); |
| 339 return class_id; | 340 return class_id; |
| 340 } | 341 } |
| 341 | 342 |
| 342 | 343 |
| 343 void FlowGraphOptimizer::AddCheckClass(InstanceCallInstr* call, | 344 void FlowGraphOptimizer::AddCheckClass(InstanceCallInstr* call, |
| 344 Value* value) { | 345 Value* value) { |
| 345 // Type propagation has not run yet, we cannot eliminate the check. | 346 // Type propagation has not run yet, we cannot eliminate the check. |
| 346 const ICData& unary_checks = | 347 const ICData& unary_checks = |
| 347 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()); | 348 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()); |
| 348 CheckClassInstr* check = new CheckClassInstr(value, call, unary_checks); | 349 CheckClassInstr* check = |
| 350 new CheckClassInstr(value, call->deopt_id(), unary_checks); |
| 349 InsertBefore(call, check, call->env(), Definition::kEffect); | 351 InsertBefore(call, check, call->env(), Definition::kEffect); |
| 350 } | 352 } |
| 351 | 353 |
| 352 | 354 |
| 353 static bool ArgIsAlwaysSmi(const ICData& ic_data, intptr_t arg_n) { | 355 static bool ArgIsAlwaysSmi(const ICData& ic_data, intptr_t arg_n) { |
| 354 ASSERT(ic_data.num_args_tested() > arg_n); | 356 ASSERT(ic_data.num_args_tested() > arg_n); |
| 355 if (ic_data.NumberOfChecks() == 0) return false; | 357 if (ic_data.NumberOfChecks() == 0) return false; |
| 356 GrowableArray<intptr_t> class_ids; | 358 GrowableArray<intptr_t> class_ids; |
| 357 Function& target = Function::Handle(); | 359 Function& target = Function::Handle(); |
| 358 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 360 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| (...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1077 // If one of the inputs is null, no ICdata will be collected. | 1079 // If one of the inputs is null, no ICdata will be collected. |
| 1078 if (comp->left()->BindsToConstantNull() || | 1080 if (comp->left()->BindsToConstantNull() || |
| 1079 comp->right()->BindsToConstantNull()) { | 1081 comp->right()->BindsToConstantNull()) { |
| 1080 Token::Kind strict_kind = (comp->kind() == Token::kEQ) ? | 1082 Token::Kind strict_kind = (comp->kind() == Token::kEQ) ? |
| 1081 Token::kEQ_STRICT : Token::kNE_STRICT; | 1083 Token::kEQ_STRICT : Token::kNE_STRICT; |
| 1082 StrictCompareInstr* strict_comp = | 1084 StrictCompareInstr* strict_comp = |
| 1083 new StrictCompareInstr(strict_kind, comp->left(), comp->right()); | 1085 new StrictCompareInstr(strict_kind, comp->left(), comp->right()); |
| 1084 instr->ReplaceWith(strict_comp, iterator); | 1086 instr->ReplaceWith(strict_comp, iterator); |
| 1085 return; | 1087 return; |
| 1086 } | 1088 } |
| 1087 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) return; | 1089 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) { |
| 1090 return; |
| 1091 } |
| 1092 ASSERT(comp->ic_data()->num_args_tested() == 2); |
| 1088 if (comp->ic_data()->NumberOfChecks() == 1) { | 1093 if (comp->ic_data()->NumberOfChecks() == 1) { |
| 1089 ASSERT(comp->ic_data()->num_args_tested() == 2); | |
| 1090 GrowableArray<intptr_t> class_ids; | 1094 GrowableArray<intptr_t> class_ids; |
| 1091 Function& target = Function::Handle(); | 1095 Function& target = Function::Handle(); |
| 1092 comp->ic_data()->GetCheckAt(0, &class_ids, &target); | 1096 comp->ic_data()->GetCheckAt(0, &class_ids, &target); |
| 1093 // TODO(srdjan): allow for mixed mode int/double comparison. | 1097 // TODO(srdjan): allow for mixed mode int/double comparison. |
| 1094 | 1098 |
| 1095 if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { | 1099 if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { |
| 1096 optimizer->InsertBefore( | 1100 optimizer->InsertBefore( |
| 1097 instr, | 1101 instr, |
| 1098 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()), | 1102 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()), |
| 1099 instr->env(), | 1103 instr->env(), |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1111 comp->set_receiver_class_id(kMintCid); | 1115 comp->set_receiver_class_id(kMintCid); |
| 1112 } else { | 1116 } else { |
| 1113 ASSERT(comp->receiver_class_id() == kIllegalCid); | 1117 ASSERT(comp->receiver_class_id() == kIllegalCid); |
| 1114 } | 1118 } |
| 1115 } else if (HasTwoMintOrSmi(*comp->ic_data()) && | 1119 } else if (HasTwoMintOrSmi(*comp->ic_data()) && |
| 1116 FlowGraphCompiler::SupportsUnboxedMints()) { | 1120 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 1117 comp->set_receiver_class_id(kMintCid); | 1121 comp->set_receiver_class_id(kMintCid); |
| 1118 } else if (comp->ic_data()->AllReceiversAreNumbers()) { | 1122 } else if (comp->ic_data()->AllReceiversAreNumbers()) { |
| 1119 comp->set_receiver_class_id(kNumberCid); | 1123 comp->set_receiver_class_id(kNumberCid); |
| 1120 } | 1124 } |
| 1125 |
| 1126 if (comp->receiver_class_id() != kIllegalCid) { |
| 1127 // Done. |
| 1128 return; |
| 1129 } |
| 1130 |
| 1131 // Check if ICDData contains checks with Smi/Null combinations. In that case |
| 1132 // we can still emit the optimized Smi equality operation but need to add |
| 1133 // checks for null or Smi. |
| 1134 // TODO(srdjan): Add it for Double and Mint. |
| 1135 GrowableArray<intptr_t> smi_or_null(2); |
| 1136 smi_or_null.Add(kSmiCid); |
| 1137 smi_or_null.Add(kNullCid); |
| 1138 if (ICDataHasOnlyReceiverArgumentClassIds( |
| 1139 *comp->ic_data(), smi_or_null, smi_or_null)) { |
| 1140 ICData& unary_checks = |
| 1141 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); |
| 1142 const intptr_t deopt_id = comp->deopt_id(); |
| 1143 if ((unary_checks.NumberOfChecks() == 1) && |
| 1144 (unary_checks.GetReceiverClassIdAt(0) == kSmiCid)) { |
| 1145 // Smi only. |
| 1146 optimizer->InsertBefore( |
| 1147 instr, |
| 1148 new CheckSmiInstr(comp->left()->Copy(), deopt_id), |
| 1149 instr->env(), |
| 1150 Definition::kEffect); |
| 1151 } else { |
| 1152 // Smi or NULL. |
| 1153 optimizer->InsertBefore( |
| 1154 instr, |
| 1155 new CheckClassInstr(comp->left()->Copy(), deopt_id, unary_checks), |
| 1156 instr->env(), |
| 1157 Definition::kEffect); |
| 1158 } |
| 1159 |
| 1160 unary_checks = comp->ic_data()->AsUnaryClassChecksForArgNr(1); |
| 1161 if ((unary_checks.NumberOfChecks() == 1) && |
| 1162 (unary_checks.GetReceiverClassIdAt(0) == kSmiCid)) { |
| 1163 // Smi only. |
| 1164 optimizer->InsertBefore( |
| 1165 instr, |
| 1166 new CheckSmiInstr(comp->right()->Copy(), deopt_id), |
| 1167 instr->env(), |
| 1168 Definition::kEffect); |
| 1169 } else { |
| 1170 // Smi or NULL. |
| 1171 optimizer->InsertBefore( |
| 1172 instr, |
| 1173 new CheckClassInstr(comp->right()->Copy(), deopt_id, unary_checks), |
| 1174 instr->env(), |
| 1175 Definition::kEffect); |
| 1176 } |
| 1177 comp->set_receiver_class_id(kSmiCid); |
| 1178 } |
| 1121 } | 1179 } |
| 1122 | 1180 |
| 1123 | 1181 |
| 1124 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareInstr* instr) { | 1182 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareInstr* instr) { |
| 1125 HandleEqualityCompare(this, instr, instr, current_iterator()); | 1183 HandleEqualityCompare(this, instr, instr, current_iterator()); |
| 1126 } | 1184 } |
| 1127 | 1185 |
| 1128 | 1186 |
| 1129 void FlowGraphOptimizer::VisitBranch(BranchInstr* instr) { | 1187 void FlowGraphOptimizer::VisitBranch(BranchInstr* instr) { |
| 1130 ComparisonInstr* comparison = instr->comparison(); | 1188 ComparisonInstr* comparison = instr->comparison(); |
| (...skipping 2040 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3171 | 3229 |
| 3172 if (FLAG_trace_constant_propagation) { | 3230 if (FLAG_trace_constant_propagation) { |
| 3173 OS::Print("\n==== After constant propagation ====\n"); | 3231 OS::Print("\n==== After constant propagation ====\n"); |
| 3174 FlowGraphPrinter printer(*graph_); | 3232 FlowGraphPrinter printer(*graph_); |
| 3175 printer.PrintBlocks(); | 3233 printer.PrintBlocks(); |
| 3176 } | 3234 } |
| 3177 } | 3235 } |
| 3178 | 3236 |
| 3179 | 3237 |
| 3180 } // namespace dart | 3238 } // namespace dart |
| OLD | NEW |