| 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/cha.h" | 7 #include "vm/cha.h" |
| 8 #include "vm/flow_graph_builder.h" | 8 #include "vm/flow_graph_builder.h" |
| 9 #include "vm/hash_map.h" | 9 #include "vm/hash_map.h" |
| 10 #include "vm/il_printer.h" | 10 #include "vm/il_printer.h" |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 if (ic_data.NumberOfChecks() != 1) return kIllegalCid; | 187 if (ic_data.NumberOfChecks() != 1) return kIllegalCid; |
| 188 ASSERT(HasOneTarget(ic_data)); | 188 ASSERT(HasOneTarget(ic_data)); |
| 189 | 189 |
| 190 Function& target = Function::Handle(); | 190 Function& target = Function::Handle(); |
| 191 intptr_t class_id; | 191 intptr_t class_id; |
| 192 ic_data.GetOneClassCheckAt(0, &class_id, &target); | 192 ic_data.GetOneClassCheckAt(0, &class_id, &target); |
| 193 return class_id; | 193 return class_id; |
| 194 } | 194 } |
| 195 | 195 |
| 196 | 196 |
| 197 static void AddCheckClass(BindInstr* instr, |
| 198 InstanceCallComp* comp, |
| 199 Value* value) { |
| 200 // Type propagation has not run yet, we cannot eliminate the check. |
| 201 CheckClassComp* check = new CheckClassComp(value, comp); |
| 202 const ICData& unary_checks = |
| 203 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); |
| 204 check->set_ic_data(&unary_checks); |
| 205 BindInstr* check_instr = new BindInstr(BindInstr::kUnused, check); |
| 206 ASSERT(instr->env() != NULL); // Always the case with SSA. |
| 207 // Attach the original environment to the check instruction. |
| 208 check_instr->set_env(instr->env()); |
| 209 check_instr->InsertBefore(instr); |
| 210 } |
| 211 |
| 212 |
| 197 bool FlowGraphOptimizer::TryReplaceWithArrayOp(BindInstr* instr, | 213 bool FlowGraphOptimizer::TryReplaceWithArrayOp(BindInstr* instr, |
| 198 InstanceCallComp* comp, | 214 InstanceCallComp* comp, |
| 199 Token::Kind op_kind) { | 215 Token::Kind op_kind) { |
| 200 // TODO(fschneider): Optimize []= operator in checked mode as well. | 216 // TODO(fschneider): Optimize []= operator in checked mode as well. |
| 201 if (op_kind == Token::kASSIGN_INDEX && FLAG_enable_type_checks) return false; | 217 if (op_kind == Token::kASSIGN_INDEX && FLAG_enable_type_checks) return false; |
| 202 | 218 |
| 203 const intptr_t class_id = ReceiverClassId(comp); | 219 const intptr_t class_id = ReceiverClassId(comp); |
| 204 switch (class_id) { | 220 switch (class_id) { |
| 205 case kImmutableArrayCid: | 221 case kImmutableArrayCid: |
| 206 // Stores are only specialized for Array and GrowableObjectArray, | 222 // Stores are only specialized for Array and GrowableObjectArray, |
| 207 // not for ImmutableArray. | 223 // not for ImmutableArray. |
| 208 if (op_kind == Token::kASSIGN_INDEX) return false; | 224 if (op_kind == Token::kASSIGN_INDEX) return false; |
| 209 // Fall through. | 225 // Fall through. |
| 210 case kArrayCid: | 226 case kArrayCid: |
| 211 case kGrowableObjectArrayCid: { | 227 case kGrowableObjectArrayCid: { |
| 212 Computation* array_op = NULL; | 228 Computation* array_op = NULL; |
| 213 if (op_kind == Token::kINDEX) { | 229 if (op_kind == Token::kINDEX) { |
| 214 array_op = new LoadIndexedComp(comp->ArgumentAt(0)->value(), | 230 array_op = new LoadIndexedComp(comp->ArgumentAt(0)->value(), |
| 215 comp->ArgumentAt(1)->value(), | 231 comp->ArgumentAt(1)->value(), |
| 216 class_id, | 232 class_id, |
| 217 comp); | 233 comp); |
| 218 } else { | 234 } else { |
| 219 array_op = new StoreIndexedComp(comp->ArgumentAt(0)->value(), | 235 array_op = new StoreIndexedComp(comp->ArgumentAt(0)->value(), |
| 220 comp->ArgumentAt(1)->value(), | 236 comp->ArgumentAt(1)->value(), |
| 221 comp->ArgumentAt(2)->value(), | 237 comp->ArgumentAt(2)->value(), |
| 222 class_id, | 238 class_id, |
| 223 comp); | 239 comp); |
| 224 } | 240 } |
| 225 array_op->set_ic_data(comp->ic_data()); | 241 array_op->set_ic_data(comp->ic_data()); |
| 226 instr->set_computation(array_op); | 242 instr->set_computation(array_op); |
| 227 RemovePushArguments(comp); | 243 RemovePushArguments(comp); |
| 228 return true; | 244 return true; |
| 229 } | 245 } |
| 230 default: | 246 default: |
| 231 return false; | 247 return false; |
| 232 } | 248 } |
| 233 } | 249 } |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 if (target.kind() == RawFunction::kImplicitGetter) { | 375 if (target.kind() == RawFunction::kImplicitGetter) { |
| 360 if (!HasOneTarget(ic_data)) { | 376 if (!HasOneTarget(ic_data)) { |
| 361 // TODO(srdjan): Implement for mutiple targets. | 377 // TODO(srdjan): Implement for mutiple targets. |
| 362 return false; | 378 return false; |
| 363 } | 379 } |
| 364 // Inline implicit instance getter. | 380 // Inline implicit instance getter. |
| 365 const String& field_name = | 381 const String& field_name = |
| 366 String::Handle(Field::NameFromGetter(comp->function_name())); | 382 String::Handle(Field::NameFromGetter(comp->function_name())); |
| 367 const Field& field = Field::Handle(GetField(class_ids[0], field_name)); | 383 const Field& field = Field::Handle(GetField(class_ids[0], field_name)); |
| 368 ASSERT(!field.IsNull()); | 384 ASSERT(!field.IsNull()); |
| 369 | 385 AddCheckClass(instr, comp, comp->ArgumentAt(0)->value()); |
| 370 // Type propagation has not run yet, we cannot eliminate the check. | |
| 371 CheckClassComp* check = | |
| 372 new CheckClassComp(comp->ArgumentAt(0)->value(), comp); | |
| 373 const ICData& unary_checks = | |
| 374 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); | |
| 375 check->set_ic_data(&unary_checks); | |
| 376 BindInstr* check_instr = new BindInstr(BindInstr::kUnused, check); | |
| 377 ASSERT(instr->env() != NULL); // Always the case with SSA. | |
| 378 // Attach the original environment to the check instruction. | |
| 379 check_instr->set_env(instr->env()); | |
| 380 instr->set_env(NULL); | 386 instr->set_env(NULL); |
| 381 check_instr->InsertBefore(instr); | |
| 382 LoadInstanceFieldComp* load = | 387 LoadInstanceFieldComp* load = |
| 383 new LoadInstanceFieldComp(field, | 388 new LoadInstanceFieldComp(field, |
| 384 comp->ArgumentAt(0)->value(), | 389 comp->ArgumentAt(0)->value(), |
| 385 NULL); // Can not deoptimize. | 390 NULL); // Can not deoptimize. |
| 386 instr->set_computation(load); | 391 instr->set_computation(load); |
| 387 RemovePushArguments(comp); | 392 RemovePushArguments(comp); |
| 388 return true; | 393 return true; |
| 389 } | 394 } |
| 390 | 395 |
| 391 // Not an implicit getter. | 396 // Not an implicit getter. |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 // Not an implicit setter. | 556 // Not an implicit setter. |
| 552 // TODO(srdjan): Inline special setters. | 557 // TODO(srdjan): Inline special setters. |
| 553 return false; | 558 return false; |
| 554 } | 559 } |
| 555 // Inline implicit instance setter. | 560 // Inline implicit instance setter. |
| 556 const String& field_name = | 561 const String& field_name = |
| 557 String::Handle(Field::NameFromSetter(comp->function_name())); | 562 String::Handle(Field::NameFromSetter(comp->function_name())); |
| 558 const Field& field = Field::Handle(GetField(class_id, field_name)); | 563 const Field& field = Field::Handle(GetField(class_id, field_name)); |
| 559 ASSERT(!field.IsNull()); | 564 ASSERT(!field.IsNull()); |
| 560 | 565 |
| 561 // Type propagation has not run yet, we cannot eliminate the check. | 566 AddCheckClass(instr, comp, comp->ArgumentAt(0)->value()); |
| 562 CheckClassComp* check = | |
| 563 new CheckClassComp(comp->ArgumentAt(0)->value(), comp); | |
| 564 const ICData& unary_checks = | |
| 565 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); | |
| 566 check->set_ic_data(&unary_checks); | |
| 567 BindInstr* check_instr = new BindInstr(BindInstr::kUnused, check); | |
| 568 ASSERT(instr->env() != NULL); // Always the case with SSA. | |
| 569 // Attach the original environment to the check instruction. | |
| 570 check_instr->set_env(instr->env()); | |
| 571 instr->set_env(NULL); | 567 instr->set_env(NULL); |
| 572 check_instr->InsertBefore(instr); | |
| 573 StoreInstanceFieldComp* store = new StoreInstanceFieldComp( | 568 StoreInstanceFieldComp* store = new StoreInstanceFieldComp( |
| 574 field, | 569 field, |
| 575 comp->ArgumentAt(0)->value(), | 570 comp->ArgumentAt(0)->value(), |
| 576 comp->ArgumentAt(1)->value(), | 571 comp->ArgumentAt(1)->value(), |
| 577 NULL); // Can not deoptimize. | 572 NULL); // Can not deoptimize. |
| 578 instr->set_computation(store); | 573 instr->set_computation(store); |
| 579 RemovePushArguments(comp); | 574 RemovePushArguments(comp); |
| 580 return true; | 575 return true; |
| 581 } | 576 } |
| 582 | 577 |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 949 OS::Print("Replacing v%d with v%d\n", | 944 OS::Print("Replacing v%d with v%d\n", |
| 950 instr->ssa_temp_index(), | 945 instr->ssa_temp_index(), |
| 951 result->ssa_temp_index()); | 946 result->ssa_temp_index()); |
| 952 } | 947 } |
| 953 } | 948 } |
| 954 } | 949 } |
| 955 } | 950 } |
| 956 | 951 |
| 957 | 952 |
| 958 } // namespace dart | 953 } // namespace dart |
| OLD | NEW |